|
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,45 @@ 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 | + context_locals = context.get_locals_as_dict() |
| 196 | + self.__previous_launch_file_path = context_locals.get('current_launch_file_path', None) |
| 197 | + self.__previous_launch_file_dir = context_locals.get('current_launch_file_directory', None) |
| 198 | + context.extend_locals({ |
| 199 | + 'current_launch_file_path': self._get_launch_file(), |
| 200 | + }) |
| 201 | + context.extend_locals({ |
| 202 | + 'current_launch_file_directory': self._get_launch_file_directory(), |
| 203 | + }) |
| 204 | + |
| 205 | + def _restore_launch_file_location_locals(self, context: LaunchContext) -> None: |
| 206 | + # We want to keep the state of the context locals even after the include, since included |
| 207 | + # launch descriptions are meant to act as if they were included literally in the parent |
| 208 | + # launch description. |
| 209 | + # However, we want to restore the launch file path/dir locals to their previous state, and |
| 210 | + # we may have to just delete them if we're now going back to a launch script (i.e., not a |
| 211 | + # launch file). However, there is no easy way to delete context locals, so save current |
| 212 | + # locals, reset to the state before the include previous state and then re-apply locals, |
| 213 | + # potentially minus the launch file path/dir locals. |
| 214 | + context_locals = context.get_locals_as_dict() |
| 215 | + if self.__previous_launch_file_path is None: |
| 216 | + del context_locals['current_launch_file_path'] |
| 217 | + else: |
| 218 | + context_locals['current_launch_file_path'] = self.__previous_launch_file_path |
| 219 | + if self.__previous_launch_file_dir is None: |
| 220 | + del context_locals['current_launch_file_directory'] |
| 221 | + else: |
| 222 | + context_locals['current_launch_file_directory'] = self.__previous_launch_file_dir |
| 223 | + context._pop_locals() |
| 224 | + context.extend_locals(context_locals) |
192 | 225 |
|
193 | 226 | def __repr__(self) -> Text:
|
194 | 227 | """Return a description of this IncludeLaunchDescription as a string."""
|
|
0 commit comments