From 7c3eac6e8c1403232d022177209d1a5ba7d34043 Mon Sep 17 00:00:00 2001 From: William Wedler Date: Tue, 3 Jan 2023 23:10:36 -0500 Subject: [PATCH] include names of all parents for modules Signed-off-by: William Wedler --- .../launch/substitutions/python_expression.py | 7 +++++- .../substitutions/test_python_expression.py | 24 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/launch/launch/substitutions/python_expression.py b/launch/launch/substitutions/python_expression.py index f891e2118..e5cba7c27 100644 --- a/launch/launch/substitutions/python_expression.py +++ b/launch/launch/substitutions/python_expression.py @@ -105,7 +105,12 @@ def perform(self, context: LaunchContext) -> Text: """Perform the substitution by evaluating the expression.""" from ..utilities import perform_substitutions module_names = [context.perform_substitution(sub) for sub in self.python_modules] - module_objects = [importlib.import_module(name) for name in module_names] + # Get names of package and all parents for modules in the list of python_modules + # For example, python module "a.b.c" has parents "a.b" and "a" + inherited_names = [".".join(p[0:n]) for n in range(1, len(p)) for p in + [name.split('.') for name in module_names]] + all_module_names = list(set(module_names + inherited_names)) + module_objects = [importlib.import_module(name) for name in all_module_names] expression_locals = {} for module in module_objects: # For backwards compatility, we allow math definitions to be implicitly diff --git a/launch/test/launch/substitutions/test_python_expression.py b/launch/test/launch/substitutions/test_python_expression.py index a52b52e2d..e92c5bc47 100644 --- a/launch/test/launch/substitutions/test_python_expression.py +++ b/launch/test/launch/substitutions/test_python_expression.py @@ -114,3 +114,27 @@ def test_python_substitution_two_modules(): # Test the describe() method assert subst.describe() ==\ "PythonExpr('math.isfinite(sys.getrefcount(str(\"hello world!\")))', ['sys', 'math'])" + + +def test_python_substitution_submodule(): + """Evaluation while passing modules within a package.""" + python_modules = [ + 'launch.substitutions.PythonExpression', + 'launch.substitutions.SubstitutionFailure', + 'launch.utilities.is_a_subclass' + ] + lc = LaunchContext() + expr = ( + f'not launch.utilities.is_a_subclass(' + f' launch.substitutions.PythonExpression,' + f' launch.substitutions.SubstitutionFailure' + f')' + ) + subst = PythonExpression([expr], python_modules) + try: + result = subst.perform(lc) + except SubstitutionFailure: + pytest.fail('Failed to evaluate PythonExpression containing sys module.') + + # The expression should evaluate to True + assert result