Nav2 Navigation Stack - kilted  kilted
ROS 2 Navigation Stack
replace_string.py
1 # Copyright (c) 2019 Intel Corporation
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 import tempfile
16 from typing import Optional
17 
18 import launch
19 
20 
21 class ReplaceString(launch.Substitution): # type: ignore[misc]
22  """
23  Substitution that replaces strings on a given file.
24 
25  Used in launch system
26  """
27 
28  def __init__(
29  self,
30  source_file: launch.SomeSubstitutionsType,
31  replacements: dict[str, launch.SomeSubstitutionsType],
32  condition: Optional[launch.Condition] = None,
33  ) -> None:
34  super().__init__()
35 
36  from launch.utilities import normalize_to_list_of_substitutions
37 
38  # import here to avoid loop
39 
40  self.__source_file: list[launch.Substitution] = \
41  normalize_to_list_of_substitutions(source_file)
42  self.__replacements__replacements = {}
43  for key in replacements:
44  self.__replacements__replacements[key] = normalize_to_list_of_substitutions(
45  replacements[key]
46  )
47  self.__condition__condition = condition
48 
49  @property
50  def name(self) -> list[launch.Substitution]:
51  """Getter for name."""
52  return self.__source_file
53 
54  @property
55  def condition(self) -> Optional[launch.Condition]:
56  """Getter for condition."""
57  return self.__condition__condition
58 
59  def describe(self) -> str:
60  """Return a description of this substitution as a string."""
61  return ''
62 
63  def perform(self, context: launch.LaunchContext) -> str:
64  yaml_filename: str = launch.utilities.perform_substitutions(
65  context, self.namename
66  )
67  if self.__condition__condition is None or self.__condition__condition.evaluate(context):
68  output_file = tempfile.NamedTemporaryFile(mode='w', delete=False)
69  replacements = self.resolve_replacementsresolve_replacements(context)
70  try:
71  input_file = open(yaml_filename)
72  self.replacereplace(input_file, output_file, replacements)
73  except Exception as err: # noqa: B902
74  print('ReplaceString substitution error: ', err)
75  finally:
76  input_file.close()
77  output_file.close()
78  return output_file.name
79  else:
80  return yaml_filename
81 
82  def resolve_replacements(self, context: launch.LaunchContext) -> dict[str, str]:
83  resolved_replacements = {}
84  for key in self.__replacements__replacements:
85  resolved_replacements[key] = launch.utilities.perform_substitutions(
86  context, self.__replacements__replacements[key]
87  )
88  return resolved_replacements
89 
90  def replace(self, input_file: launch.SomeSubstitutionsType,
91  output_file: launch.SomeSubstitutionsType, replacements: dict[str, str]) -> None:
92  for line in input_file:
93  for key, value in replacements.items():
94  if isinstance(key, str) and isinstance(value, str):
95  if key in line:
96  line = line.replace(key, value)
97  else:
98  raise TypeError(
99  'A provided replacement pair is not a string. Both key and value should be'
100  'strings.'
101  )
102  output_file.write(line)
Optional[launch.Condition] condition(self)
dict[str, str] resolve_replacements(self, launch.LaunchContext context)
list[launch.Substitution] name(self)
None replace(self, launch.SomeSubstitutionsType input_file, launch.SomeSubstitutionsType output_file, dict[str, str] replacements)