From 28970d1c0ac1efaa26b7c7bd51ab9ed3558aba25 Mon Sep 17 00:00:00 2001 From: Scott K Logan Date: Mon, 14 Oct 2024 21:17:14 -0500 Subject: [PATCH 1/2] Support generic invocation of package_discovery functions Other function groups like augmentation, identification, and discovery, can be invoked with an explicit list of extensions instances. This supports scenarios where we want to use extensions other than the ones registered for colcon_core. --- colcon_core/package_selection/__init__.py | 66 ++++++++++++++++------- 1 file changed, 46 insertions(+), 20 deletions(-) diff --git a/colcon_core/package_selection/__init__.py b/colcon_core/package_selection/__init__.py index e76a474b..1cfb1d5d 100644 --- a/colcon_core/package_selection/__init__.py +++ b/colcon_core/package_selection/__init__.py @@ -71,7 +71,9 @@ def select_packages(self, *, args, decorators): raise NotImplementedError() -def add_arguments(parser): +def add_arguments( + parser, *, discovery_extensions=None, selection_extensions=None, +): """ Add the command line arguments for the package selection extensions. @@ -80,9 +82,9 @@ def add_arguments(parser): :param parser: The argument parser """ - add_package_discovery_arguments(parser) + add_package_discovery_arguments(parser, extensions=discovery_extensions) - _add_package_selection_arguments(parser) + _add_package_selection_arguments(parser, extensions=selection_extensions) def get_package_selection_extensions(*, group_name=None): @@ -101,15 +103,16 @@ def get_package_selection_extensions(*, group_name=None): return order_extensions_by_priority(extensions) -def _add_package_selection_arguments(parser): +def _add_package_selection_arguments(parser, *, extensions=None): """ Add the command line arguments for the package selection extensions. :param parser: The argument parser """ - package_selection_extensions = get_package_selection_extensions() + if extensions is None: + extensions = get_package_selection_extensions() group = parser.add_argument_group(title='Package selection arguments') - for extension in package_selection_extensions.values(): + for extension in extensions.values(): try: retval = extension.add_arguments(parser=group) assert retval is None, 'add_arguments() should return None' @@ -125,7 +128,9 @@ def _add_package_selection_arguments(parser): def get_packages( args, *, additional_argument_names=None, - direct_categories=None, recursive_categories=None + direct_categories=None, recursive_categories=None, + discovery_extensions=None, identification_extensions=None, + augmentation_extensions=None, selection_extensions=None, ): """ Get the selected package decorators in topological order. @@ -146,12 +151,18 @@ def get_packages( package names """ descriptors = get_package_descriptors( - args, additional_argument_names=additional_argument_names) + args, additional_argument_names=additional_argument_names, + discovery_extensions=discovery_extensions, + identification_extensions=identification_extensions, + augmentation_extensions=augmentation_extensions, + selection_extensions=selection_extensions) decorators = topological_order_packages( descriptors, direct_categories=direct_categories, recursive_categories=recursive_categories) - select_package_decorators(args, decorators) + select_package_decorators( + args, decorators, + selection_extensions=selection_extensions) # check for duplicate package names pkgs = [m.descriptor for m in decorators if m.selected] @@ -169,7 +180,11 @@ def get_packages( return decorators -def get_package_descriptors(args, *, additional_argument_names=None): +def get_package_descriptors( + args, *, additional_argument_names=None, discovery_extensions=None, + identification_extensions=None, augmentation_extensions=None, + selection_extensions=None, +): """ Get the package descriptors. @@ -185,20 +200,28 @@ def get_package_descriptors(args, *, additional_argument_names=None): :py:class:`colcon_core.package_descriptor.PackageDescriptor` :rtype: set """ - extensions = get_package_identification_extensions() - descriptors = discover_packages(args, extensions) + if identification_extensions is None: + identification_extensions = get_package_identification_extensions() + descriptors = discover_packages( + args, identification_extensions, + discovery_extensions=discovery_extensions) pkg_names = {d.name for d in descriptors} - _check_package_selection_parameters(args, pkg_names) + _check_package_selection_parameters( + args, pkg_names, selection_extensions=selection_extensions) augment_packages( - descriptors, additional_argument_names=additional_argument_names) + descriptors, additional_argument_names=additional_argument_names, + augmentation_extensions=augmentation_extensions) return descriptors -def _check_package_selection_parameters(args, pkg_names): - package_selection_extensions = get_package_selection_extensions() - for extension in package_selection_extensions.values(): +def _check_package_selection_parameters( + args, pkg_names, *, selection_extensions=None, +): + if selection_extensions is None: + selection_extensions = get_package_selection_extensions() + for extension in selection_extensions.values(): try: retval = extension.check_parameters(args=args, pkg_names=pkg_names) assert retval is None, 'check_parameters() should return None' @@ -211,7 +234,9 @@ def _check_package_selection_parameters(args, pkg_names): # skip failing extension, continue with next one -def select_package_decorators(args, decorators): +def select_package_decorators( + args, decorators, *, selection_extensions=None, +): """ Select the package decorators based on the command line arguments. @@ -222,8 +247,9 @@ def select_package_decorators(args, decorators): """ # filtering must happen after the topological ordering since otherwise # packages in the middle of the dependency graph might be missing - package_selection_extensions = get_package_selection_extensions() - for extension in package_selection_extensions.values(): + if selection_extensions is None: + selection_extensions = get_package_selection_extensions() + for extension in selection_extensions.values(): try: retval = extension.select_packages( args=args, decorators=decorators) From a89d8922e22e3d4aa26f4a946daf1bcf5e292d40 Mon Sep 17 00:00:00 2001 From: Scott K Logan Date: Wed, 16 Oct 2024 10:27:22 -0500 Subject: [PATCH 2/2] Add parameter documentation --- colcon_core/package_selection/__init__.py | 33 +++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/colcon_core/package_selection/__init__.py b/colcon_core/package_selection/__init__.py index 1cfb1d5d..37c5df88 100644 --- a/colcon_core/package_selection/__init__.py +++ b/colcon_core/package_selection/__init__.py @@ -81,6 +81,12 @@ def add_arguments( the package discovery arguments. :param parser: The argument parser + :param discovery_extensions: The package discovery extensions to use, if + `None` is passed use the extensions provided by + :function:`get_package_discovery_extensions` + :param selection_extensions: The package selection extensions to use, if + `None` is passed use the extensions provided by + :function:`get_package_selection_extensions` """ add_package_discovery_arguments(parser, extensions=discovery_extensions) @@ -146,6 +152,18 @@ def get_packages( :param Iterable[str]|Mapping[str, Iterable[str]] recursive_categories: The names of the recursive categories, optionally mapped from the immediate upstream category which included the dependency + :param discovery_extensions: The package discovery extensions to use, if + `None` is passed use the extensions provided by + :function:`get_package_discovery_extensions` + :param identification_extensions: The package identification extensions to + use, if `None` is passed use the extensions provided by + :function:`get_package_identification_extensions` + :param augmentation_extensions: The package augmentation extensions, if + `None` is passed use the extensions provided by + :function:`get_package_augmentation_extensions` + :param selection_extensions: The package selection extensions to use, if + `None` is passed use the extensions provided by + :function:`get_package_selection_extensions` :rtype: list :raises RuntimeError: if the returned set of packages contains duplicates package names @@ -196,6 +214,18 @@ def get_package_descriptors( :param additional_argument_names: A list of additional arguments to consider + :param discovery_extensions: The package discovery extensions to use, if + `None` is passed use the extensions provided by + :function:`get_package_discovery_extensions` + :param identification_extensions: The package identification extensions to + use, if `None` is passed use the extensions provided by + :function:`get_package_identification_extensions` + :param augmentation_extensions: The package augmentation extensions, if + `None` is passed use the extensions provided by + :function:`get_package_augmentation_extensions` + :param selection_extensions: The package selection extensions to use, if + `None` is passed use the extensions provided by + :function:`get_package_selection_extensions` :returns: set of :py:class:`colcon_core.package_descriptor.PackageDescriptor` :rtype: set @@ -244,6 +274,9 @@ def select_package_decorators( :param args: The parsed command line arguments :param list decorators: The package decorators in topological order + :param selection_extensions: The package selection extensions to use, if + `None` is passed use the extensions provided by + :function:`get_package_selection_extensions` """ # filtering must happen after the topological ordering since otherwise # packages in the middle of the dependency graph might be missing