|
24 | 24 |
|
25 | 25 | import launch.logging |
26 | 26 |
|
| 27 | +from .opaque_function import OpaqueFunction |
27 | 28 | from .set_launch_configuration import SetLaunchConfiguration |
28 | 29 | from ..action import Action |
29 | 30 | from ..frontend import Entity |
@@ -147,13 +148,7 @@ def _try_get_arguments_names_without_context(self): |
147 | 148 | def execute(self, context: LaunchContext) -> List[LaunchDescriptionEntity]: |
148 | 149 | """Execute the action.""" |
149 | 150 | launch_description = self.__launch_description_source.get_launch_description(context) |
150 | | - # If the location does not exist, then it's likely set to '<script>' or something. |
151 | | - context.extend_locals({ |
152 | | - 'current_launch_file_path': self._get_launch_file(), |
153 | | - }) |
154 | | - context.extend_locals({ |
155 | | - 'current_launch_file_directory': self._get_launch_file_directory(), |
156 | | - }) |
| 151 | + self._set_launch_file_location_locals(context) |
157 | 152 |
|
158 | 153 | # Do best effort checking to see if non-optional, non-default declared arguments |
159 | 154 | # are being satisfied. |
@@ -188,7 +183,44 @@ def execute(self, context: LaunchContext) -> List[LaunchDescriptionEntity]: |
188 | 183 | set_launch_configuration_actions.append(SetLaunchConfiguration(name, value)) |
189 | 184 |
|
190 | 185 | # Set launch arguments as launch configurations and then include the launch description. |
191 | | - return [*set_launch_configuration_actions, launch_description] |
| 186 | + return [ |
| 187 | + *set_launch_configuration_actions, |
| 188 | + launch_description, |
| 189 | + OpaqueFunction(function=self._restore_launch_file_location_locals), |
| 190 | + ] |
| 191 | + |
| 192 | + def _set_launch_file_location_locals(self, context: LaunchContext) -> None: |
| 193 | + context._push_locals() |
| 194 | + # Keep the previous launch file path/dir locals so that we can restore them after |
| 195 | + self.__previous_launch_file_path = context.get_locals_as_dict().get('current_launch_file_path' , None) |
| 196 | + self.__previous_launch_file_directory = context.get_locals_as_dict().get('current_launch_file_directory', None) |
| 197 | + context.extend_locals({ |
| 198 | + 'current_launch_file_path': self._get_launch_file(), |
| 199 | + }) |
| 200 | + context.extend_locals({ |
| 201 | + 'current_launch_file_directory': self._get_launch_file_directory(), |
| 202 | + }) |
| 203 | + |
| 204 | + def _restore_launch_file_location_locals(self, context: LaunchContext) -> None: |
| 205 | + # We want to keep the state of the context locals even after the include, since included |
| 206 | + # launch descriptions are meant to act as if they were included literally in the parent |
| 207 | + # launch description. |
| 208 | + # However, we want to restore the launch file path/dir locals to their previous state, and |
| 209 | + # we may have to just delete them if we're now going back to a launch script (i.e., not a |
| 210 | + # launch file). However, there is no easy way to delete context locals, so save current |
| 211 | + # locals, reset to the state before the include previous state and then re-apply locals, |
| 212 | + # potentially minus the launch file path/dir locals. |
| 213 | + locals = context.get_locals_as_dict() |
| 214 | + if self.__previous_launch_file_path is None: |
| 215 | + del locals['current_launch_file_path'] |
| 216 | + else: |
| 217 | + locals['current_launch_file_path'] = self.__previous_launch_file_path |
| 218 | + if self.__previous_launch_file_directory is None: |
| 219 | + del locals['current_launch_file_directory'] |
| 220 | + else: |
| 221 | + locals['current_launch_file_directory'] = self.__previous_launch_file_directory |
| 222 | + context._pop_locals() |
| 223 | + context.extend_locals(locals) |
192 | 224 |
|
193 | 225 | def __repr__(self) -> Text: |
194 | 226 | """Return a description of this IncludeLaunchDescription as a string.""" |
|
0 commit comments