substitution_args.py
Go to the documentation of this file.
1 # Software License Agreement (BSD License)
2 #
3 # Copyright (c) 2008, Willow Garage, Inc.
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 #
10 # * Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # * Redistributions in binary form must reproduce the above
13 # copyright notice, this list of conditions and the following
14 # disclaimer in the documentation and/or other materials provided
15 # with the distribution.
16 # * Neither the name of Willow Garage, Inc. nor the names of its
17 # contributors may be used to endorse or promote products derived
18 # from this software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 # POSSIBILITY OF SUCH DAMAGE.
32 #
33 # Revision $Id: substitution_args.py 15178 2011-10-10 21:22:53Z kwc $
34 
35 """
36 Library for processing XML substitution args.
37 """
38 
39 import os
40 
41 try:
42  from cStringIO import StringIO # Python 2.x
43 except ImportError:
44  from io import StringIO # Python 3.x
45 
46 
47 class SubstitutionException(Exception):
48  """
49  Base class for exceptions in substitution_args routines
50  """
51  pass
53  """
54  Exception for missing $(arg) values
55  """
56  pass
57 
58 def _split_command(resolved, command_with_args):
59  cmd = '$(%s)' % command_with_args
60  idx1 = resolved.find(cmd)
61  idx2 = idx1 + len(cmd)
62  return resolved[0:idx1], resolved[idx2:]
63 
64 
66  idx = value.find(' ')
67  if idx < 0:
68  path, rest = value, ''
69  else:
70  path, rest = value[0:idx], value[idx:]
71  return path, rest
72 
73 
74 def _sanitize_path(path):
75  path = path.replace('/', os.sep)
76  path = path.replace('\\', os.sep)
77  return path
78 
79 
80 def _arg(resolved, a, args, context):
81  """
82  process $(arg) arg
83 
84  :returns: updated resolved argument, ``str``
85  :raises: :exc:`ArgException` If arg invalidly specified
86  """
87  if len(args) == 0:
88  raise SubstitutionException("$(arg var) must specify an environment variable [%s]"%(a))
89  elif len(args) > 1:
90  raise SubstitutionException("$(arg var) may only specify one arg [%s]"%(a))
91 
92  if 'arg' not in context:
93  context['arg'] = {}
94  arg_context = context['arg']
95 
96  arg_name = args[0]
97  if arg_name in arg_context:
98  arg_value = arg_context[arg_name]
99  return resolved.replace("$(%s)"%a, arg_value)
100  else:
101  raise ArgException(arg_name)
102 
103 
104 def resolve_args(arg_str, context=None, resolve_anon=True):
105  """
106  Resolves substitution args (see wiki spec U{http://ros.org/wiki/roslaunch}).
107 
108  @param arg_str: string to resolve zero or more substitution args
109  in. arg_str may be None, in which case resolve_args will
110  return None
111  @type arg_str: str
112  @param context dict: (optional) dictionary for storing results of
113  the 'anon' and 'arg' substitution args. multiple calls to
114  resolve_args should use the same context so that 'anon'
115  substitions resolve consistently. If no context is provided, a
116  new one will be created for each call. Values for the 'arg'
117  context should be stored as a dictionary in the 'arg' key.
118  @type context: dict
119  @param resolve_anon bool: If True (default), will resolve $(anon
120  foo). If false, will leave these args as-is.
121  @type resolve_anon: bool
122 
123  @return str: arg_str with substitution args resolved
124  @rtype: str
125  @raise SubstitutionException: if there is an error resolving substitution args
126  """
127  if context is None:
128  context = {}
129  #parse found substitution args
130  if not arg_str:
131  return arg_str
132  # first resolve variables like 'env' and 'arg'
133  commands = {
134  'arg': _arg,
135  }
136  resolved = _resolve_args(arg_str, context, resolve_anon, commands)
137  # than resolve 'find' as it requires the subsequent path to be expanded already
138 
139  resolved = _resolve_args(resolved, context, resolve_anon, commands)
140  return resolved
141 
142 def _resolve_args(arg_str, context, resolve_anon, commands):
143  valid = ['arg']
144  resolved = arg_str
145  for a in _collect_args(arg_str):
146  splits = [s for s in a.split(' ') if s]
147  if not splits[0] in valid:
148  raise SubstitutionException("Unknown substitution command [%s]. Valid commands are %s"%(a, valid))
149  command = splits[0]
150  args = splits[1:]
151  if command in commands:
152  resolved = commands[command](resolved, a, args, context)
153  return resolved
154 
155 _OUT = 0
156 _DOLLAR = 1
157 _LP = 2
158 _IN = 3
159 def _collect_args(arg_str):
160  """
161  State-machine parser for resolve_args. Substitution args are of the form:
162  $(find package_name)/scripts/foo.py $(export some/attribute blar) non-relevant stuff
163 
164  @param arg_str: argument string to parse args from
165  @type arg_str: str
166  @raise SubstitutionException: if args are invalidly specified
167  @return: list of arguments
168  @rtype: [str]
169  """
170  buff = StringIO()
171  args = []
172  state = _OUT
173  for c in arg_str:
174  # No escapes supported
175  if c == '$':
176  if state == _OUT:
177  state = _DOLLAR
178  elif state == _DOLLAR:
179  pass
180  else:
181  raise SubstitutionException("Dollar signs '$' cannot be inside of substitution args [%s]"%arg_str)
182  elif c == '(':
183  if state == _DOLLAR:
184  state = _LP
185  elif state != _OUT:
186  raise SubstitutionException("Invalid left parenthesis '(' in substitution args [%s]"%arg_str)
187  elif c == ')':
188  if state == _IN:
189  #save contents of collected buffer
190  args.append(buff.getvalue())
191  buff.truncate(0)
192  buff.seek(0)
193  state = _OUT
194  else:
195  state = _OUT
196  elif state == _DOLLAR:
197  # left paren must immediately follow dollar sign to enter _IN state
198  state = _OUT
199  elif state == _LP:
200  state = _IN
201 
202  if state == _IN:
203  buff.write(c)
204  return args
205 
206 
def _separate_first_path(value)
def _resolve_args(arg_str, context, resolve_anon, commands)
def _split_command(resolved, command_with_args)
ssize_t len
def _collect_args(arg_str)
def resolve_args(arg_str, context=None, resolve_anon=True)
def _arg(resolved, a, args, context)


rotors_gazebo
Author(s): Fadri Furrer, Michael Burri, Mina Kamel, Janosch Nikolic, Markus Achtelik
autogenerated on Mon Feb 28 2022 23:39:12