Repository: colcon/colcon-core

Issue:
Several lines from _local_setup_util_sh.py contain this: E501 line too long
Transfered from: https://github.com/ament/ament_package/issues/146 (@ionutnechita-intel FYI)

---

OS:
ROS2 rolling - 02 April 2024
Ubuntu 24.04 Alpha LTS

This line have issue with flake8 and pycodestyle:

```
cat  _local_setup_util_sh.py
...
FORMAT_STR_INVOKE_SCRIPT = 'COLCON_CURRENT_PREFIX="{prefix}" _colcon_prefix_sh_source_script "{script_path}"'  # noqa: E501
FORMAT_STR_REMOVE_LEADING_SEPARATOR = 'if [ "$(echo -n ${name} | head -c 1)" = ":" ]; then export {name}=${{{name}#?}} ; fi'  # noqa: E501
FORMAT_STR_REMOVE_TRAILING_SEPARATOR = 'if [ "$(echo -n ${name} | tail -c 1)" = ":" ]; then export {name}=${{{name}%?}} ; fi'  # noqa: E501

```

I append  noqa: E501 to bypass this errors.

Hints from issue comments:

Solution patch:
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index a704527..64661c6 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -8,7 +8,7 @@ on:
 jobs:
   pytest:
     uses: colcon/ci/.github/workflows/pytest.yaml@main
-    with:
-      codecov: true
+    secrets:
+      CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
   bootstrap:
     uses: ./.github/workflows/bootstrap.yaml
diff --git a/colcon_core/argument_parser/__init__.py b/colcon_core/argument_parser/__init__.py
index 44f7431..21f0694 100644
--- a/colcon_core/argument_parser/__init__.py
+++ b/colcon_core/argument_parser/__init__.py
@@ -42,7 +42,7 @@ class ArgumentParserDecoratorExtensionPoint:
         raise NotImplementedError()
 
 
-def get_argument_parser_extensions():
+def get_argument_parser_extensions(*, group_name=None):
     """
     Get the available argument parser extensions.
 
@@ -50,7 +50,9 @@ def get_argument_parser_extensions():
 
     :rtype: OrderedDict
     """
-    extensions = instantiate_extensions(__name__)
+    if group_name is None:
+        group_name = __name__
+    extensions = instantiate_extensions(group_name)
     for name, extension in extensions.items():
         extension.ARGUMENT_PARSER_DECORATOR_NAME = name
     return order_extensions_by_priority(extensions)
diff --git a/colcon_core/command.py b/colcon_core/command.py
index 228d3b3..bad98e2 100644
--- a/colcon_core/command.py
+++ b/colcon_core/command.py
@@ -86,7 +86,6 @@ def register_command_exit_handler(handler):
 
     :param handler: The callable
     """
-    global _command_exit_handlers
     if handler not in _command_exit_handlers:
         _command_exit_handlers.append(handler)
 
@@ -113,7 +112,6 @@ def main(*, command_name='colcon', argv=None):
     :param list argv: The list of arguments
     :returns: The return code
     """
-    global _command_exit_handlers
     try:
         return _main(command_name=command_name, argv=argv)
     except KeyboardInterrupt:
@@ -126,7 +124,6 @@ def main(*, command_name='colcon', argv=None):
 
 
 def _main(*, command_name, argv):
-    global colcon_logger
     # default log level, for searchability: COLCON_LOG_LEVEL
     colcon_logger.setLevel(logging.WARNING)
     set_logger_level_from_env(
@@ -387,8 +384,6 @@ def create_subparser(parser, cmd_name, verb_extensions, *, attribute):
       selected verb
     :returns: The special action object
     """
-    global colcon_logger
-
     # list of available verbs with their descriptions
     verbs = []
     for name, extension in verb_extensions.items():
diff --git a/colcon_core/environment/__init__.py b/colcon_core/environment/__init__.py
index d57adbf..a7324d0 100644
--- a/colcon_core/environment/__init__.py
+++ b/colcon_core/environment/__init__.py
@@ -47,7 +47,7 @@ class EnvironmentExtensionPoint:
         raise NotImplementedError()
 
 
-def get_environment_extensions():
+def get_environment_extensions(*, group_name=None):
     """
     Get the available environment extensions.
 
@@ -55,7 +55,9 @@ def get_environment_extensions():
 
     :rtype: OrderedDict
     """
-    extensions = instantiate_extensions(__name__)
+    if group_name is None:
+        group_name = __name__
+    extensions = instantiate_extensions(group_name)
     for name in list(extensions.keys()):
         extension = extensions[name]
         extension.ENVIRONMENT_NAME = name
diff --git a/colcon_core/event_handler/__init__.py b/colcon_core/event_handler/__init__.py
index a51756c..4378946 100644
--- a/colcon_core/event_handler/__init__.py
+++ b/colcon_core/event_handler/__init__.py
@@ -44,7 +44,7 @@ class EventHandlerExtensionPoint:
         raise NotImplementedError()
 
 
-def get_event_handler_extensions(*, context):
+def get_event_handler_extensions(*, context, group_name=None):
     """
     Get the available event handler extensions.
 
@@ -52,7 +52,9 @@ def get_event_handler_extensions(*, context):
 
     :rtype: OrderedDict
     """
-    extensions = instantiate_extensions(__name__)
+    if group_name is None:
+        group_name = __name__
+    extensions = instantiate_extensions(group_name)
     for name, extension in extensions.items():
         extension.EVENT_HANDLER_NAME = name
         extension.context = context
diff --git a/colcon_core/executor/__init__.py b/colcon_core/executor/__init__.py
index aca0357..c0bdacc 100644
--- a/colcon_core/executor/__init__.py
+++ b/colcon_core/executor/__init__.py
@@ -197,7 +197,7 @@ class ExecutorExtensionPoint:
         self._event_controller.flush()
 
 
-def get_executor_extensions():
+def get_executor_extensions(*, group_name=None):
     """
     Get the available executor extensions.
 
@@ -206,7 +206,9 @@ def get_executor_extensions():
 
     :rtype: OrderedDict
     """
-    extensions = instantiate_extensions(__name__)
+    if group_name is None:
+        group_name = __name__
+    extensions = instantiate_extensions(group_name)
     for name, extension in extensions.items():
         extension.EXECUTOR_NAME = name
     return order_extensions_grouped_by_priority(extensions)
diff --git a/colcon_core/logging.py b/colcon_core/logging.py
index 0a555b6..67db572 100644
--- a/colcon_core/logging.py
+++ b/colcon_core/logging.py
@@ -95,15 +95,15 @@ def add_file_handler(logger, path):
         if isinstance(handler, logging.StreamHandler):
             formatter = handler.formatter
             # filter colcon specific log messages from default stream handler
-            handler.addFilter(Filter(colcon_logger.name))
+            handler.addFilter(Filter(logger.name))
 
     # add a stream handler replacing the one filtered on the root logger
     handler = logging.StreamHandler()
     if formatter:
         # use same formatter as for stream handler
         handler.setFormatter(formatter)
-    handler.setLevel(colcon_logger.getEffectiveLevel())
-    colcon_logger.addHandler(handler)
+    handler.setLevel(logger.getEffectiveLevel())
+    logger.addHandler(handler)
 
     # add a file handler writing all log levels
     handler = logging.FileHandler(str(path))
@@ -121,9 +121,9 @@ def add_file_handler(logger, path):
         # use same formatter as for stream handler
         handler.setFormatter(formatter)
     handler.setLevel(1)
-    colcon_logger.addHandler(handler)
+    logger.addHandler(handler)
 
     # change the logger to handle all levels
-    colcon_logger.setLevel(1)
+    logger.setLevel(1)
 
     return handler
diff --git a/colcon_core/package_augmentation/__init__.py b/colcon_core/package_augmentation/__init__.py
index 3b57929..e741292 100644
--- a/colcon_core/package_augmentation/__init__.py
+++ b/colcon_core/package_augmentation/__init__.py
@@ -65,7 +65,7 @@ class PackageAugmentationExtensionPoint:
         raise NotImplementedError()
 
 
-def get_package_augmentation_extensions():
+def get_package_augmentation_extensions(*, group_name=None):
     """
     Get the available package augmentation extensions.
 
@@ -73,7 +73,9 @@ def get_package_augmentation_extensions():
 
     :rtype: OrderedDict
     """
-    extensions = instantiate_extensions(__name__)
+    if group_name is None:
+        group_name = __name__
+    extensions = instantiate_extensions(group_name)
     for name, extension in extensions.items():
         extension.PACKAGE_AUGMENTATION_NAME = name
     return order_extensions_by_priority(extensions)
diff --git a/colcon_core/package_discovery/__init__.py b/colcon_core/package_discovery/__init__.py
index fc60f14..c16f3b1 100644
--- a/colcon_core/package_discovery/__init__.py
+++ b/colcon_core/package_discovery/__init__.py
@@ -84,7 +84,7 @@ class PackageDiscoveryExtensionPoint:
         raise NotImplementedError()
 
 
-def get_package_discovery_extensions():
+def get_package_discovery_extensions(*, group_name=None):
     """
     Get the available package discovery extensions.
 
@@ -92,7 +92,9 @@ def get_package_discovery_extensions():
 
     :rtype: OrderedDict
     """
-    extensions = instantiate_extensions(__name__)
+    if group_name is None:
+        group_name = __name__
+    extensions = instantiate_extensions(group_name)
     for name, extension in extensions.items():
         extension.PACKAGE_DISCOVERY_NAME = name
     return order_extensions_by_priority(extensions)
diff --git a/colcon_core/package_identification/__init__.py b/colcon_core/package_identification/__init__.py
index 11e17d7..01dd8a2 100644
--- a/colcon_core/package_identification/__init__.py
+++ b/colcon_core/package_identification/__init__.py
@@ -64,7 +64,7 @@ class PackageIdentificationExtensionPoint:
         raise NotImplementedError()
 
 
-def get_package_identification_extensions():
+def get_package_identification_extensions(*, group_name=None):
     """
     Get the available package identification extensions.
 
@@ -73,7 +73,9 @@ def get_package_identification_extensions():
 
     :rtype: OrderedDict
     """
-    extensions = instantiate_extensions(__name__)
+    if group_name is None:
+        group_name = __name__
+    extensions = instantiate_extensions(group_name)
     for name, extension in extensions.items():
         extension.PACKAGE_IDENTIFICATION_NAME = name
     return order_extensions_grouped_by_priority(extensions)
diff --git a/colcon_core/package_selection/__init__.py b/colcon_core/package_selection/__init__.py
index 6b1bdc9..bdbacd8 100644
--- a/colcon_core/package_selection/__init__.py
+++ b/colcon_core/package_selection/__init__.py
@@ -85,7 +85,7 @@ def add_arguments(parser):
     _add_package_selection_arguments(parser)
 
 
-def get_package_selection_extensions():
+def get_package_selection_extensions(*, group_name=None):
     """
     Get the available package selection extensions.
 
@@ -93,7 +93,9 @@ def get_package_selection_extensions():
 
     :rtype: OrderedDict
     """
-    extensions = instantiate_extensions(__name__)
+    if group_name is None:
+        group_name = __name__
+    extensions = instantiate_extensions(group_name)
     for name, extension in extensions.items():
         extension.PACKAGE_SELECTION_NAME = name
     return order_extensions_by_priority(extensions)
diff --git a/colcon_core/prefix_path/__init__.py b/colcon_core/prefix_path/__init__.py
index 15aae0b..4fa34eb 100644
--- a/colcon_core/prefix_path/__init__.py
+++ b/colcon_core/prefix_path/__init__.py
@@ -40,7 +40,7 @@ class PrefixPathExtensionPoint:
         raise NotImplementedError()
 
 
-def get_prefix_path_extensions():
+def get_prefix_path_extensions(*, group_name=None):
     """
     Get the available prefix path extensions.
 
@@ -49,7 +49,9 @@ def get_prefix_path_extensions():
 
     :rtype: OrderedDict
     """
-    extensions = instantiate_extensions(__name__)
+    if group_name is None:
+        group_name = __name__
+    extensions = instantiate_extensions(group_name)
     for name, extension in extensions.items():
         extension.PREFIX_PATH_NAME = name
     return order_extensions_grouped_by_priority(extensions)
diff --git a/colcon_core/shell/__init__.py b/colcon_core/shell/__init__.py
index faa103f..7924b79 100644
--- a/colcon_core/shell/__init__.py
+++ b/colcon_core/shell/__init__.py
@@ -273,7 +273,7 @@ class ShellExtensionPoint:
         raise NotImplementedError()
 
 
-def get_shell_extensions():
+def get_shell_extensions(*, group_name=None):
     """
     Get the available shell extensions.
 
@@ -282,7 +282,9 @@ def get_shell_extensions():
 
     :rtype: OrderedDict
     """
-    extensions = instantiate_extensions(__name__)
+    if group_name is None:
+        group_name = __name__
+    extensions = instantiate_extensions(group_name)
     for name, extension in extensions.items():
         extension.SHELL_NAME = name
     return order_extensions_grouped_by_priority(extensions)
@@ -593,7 +595,7 @@ class FindInstalledPackagesExtensionPoint:
         raise NotImplementedError()
 
 
-def get_find_installed_packages_extensions():
+def get_find_installed_packages_extensions(*, group_name=None):
     """
     Get the available package identification extensions.
 
@@ -602,7 +604,10 @@ def get_find_installed_packages_extensions():
 
     :rtype: OrderedDict
     """
-    extensions = instantiate_extensions(__name__ + '.find_installed_packages')
+    if group_name is None:
+        group_name = __name__
+    extensions = instantiate_extensions(
+        group_name + '.find_installed_packages')
     for name, extension in extensions.items():
         extension.PACKAGE_IDENTIFICATION_NAME = name
     return order_extensions_grouped_by_priority(extensions)
diff --git a/colcon_core/verb/__init__.py b/colcon_core/verb/__init__.py
index 640dc21..49913ba 100644
--- a/colcon_core/verb/__init__.py
+++ b/colcon_core/verb/__init__.py
@@ -48,7 +48,7 @@ class VerbExtensionPoint:
         raise NotImplementedError()
 
 
-def get_verb_extensions():
+def get_verb_extensions(*, group_name=None):
     """
     Get the available verb extensions.
 
@@ -56,7 +56,9 @@ def get_verb_extensions():
 
     :rtype: OrderedDict
     """
-    extensions = instantiate_extensions(__name__)
+    if group_name is None:
+        group_name = __name__
+    extensions = instantiate_extensions(group_name)
     for name, extension in extensions.items():
         extension.VERB_NAME = name
     return order_extensions_by_name(extensions)


Test patch:
diff --git a/colcon_core/task/python/test/__init__.py b/colcon_core/task/python/test/__init__.py
index 74a5ed2..a01ec47 100644
--- a/colcon_core/task/python/test/__init__.py
+++ b/colcon_core/task/python/test/__init__.py
@@ -137,7 +137,7 @@ class PythonTestingStepExtensionPoint:
         raise NotImplementedError()
 
 
-def get_python_testing_step_extensions():
+def get_python_testing_step_extensions(*, group_name=None):
     """
     Get the available Python testing step extensions.
 
@@ -145,8 +145,9 @@ def get_python_testing_step_extensions():
 
     :rtype: OrderedDict
     """
-    extensions = instantiate_extensions(
-        'colcon_core.python_testing', unique_instance=False)
+    if group_name is None:
+        group_name = 'colcon_core.python_testing'
+    extensions = instantiate_extensions(group_name, unique_instance=False)
     for name in list(extensions.keys()):
         extension = extensions[name]
         extension.STEP_TYPE = name
diff --git a/test/test_logging.py b/test/test_logging.py
index c676738..3de09b9 100644
--- a/test/test_logging.py
+++ b/test/test_logging.py
@@ -2,8 +2,10 @@
 # Licensed under the Apache License, Version 2.0
 
 import logging
+from pathlib import Path
 from unittest.mock import Mock
 
+from colcon_core.logging import add_file_handler
 from colcon_core.logging import get_numeric_log_level
 from colcon_core.logging import set_logger_level_from_env
 import pytest
@@ -56,3 +58,21 @@ def test_get_numeric_log_level():
     with pytest.raises(ValueError) as e:
         get_numeric_log_level('-1')
     assert str(e.value).endswith('numeric log levels must be positive')
+
+
+def test_add_file_handler(tmpdir):
+    log_path = Path(tmpdir) / 'test_add_file_handler.log'
+    log_path.touch()
+    logger = logging.getLogger('test_add_file_handler')
+    try:
+        logger.setLevel(logging.WARN)
+        add_file_handler(logger, log_path)
+        assert logger.getEffectiveLevel() != logging.WARN
+        logger.info('test_add_file_handler')
+    finally:
+        for handler in logger.handlers:
+            logger.removeHandler(handler)
+            handler.close()
+
+    # check only that we logged SOMETHING to the file
+    assert log_path.stat().st_size > 10