substitution_args.py
Go to the documentation of this file.
00001 # Software License Agreement (BSD License)
00002 #
00003 # Copyright (c) 2008, Willow Garage, Inc.
00004 # All rights reserved.
00005 #
00006 # Redistribution and use in source and binary forms, with or without
00007 # modification, are permitted provided that the following conditions
00008 # are met:
00009 #
00010 #  * Redistributions of source code must retain the above copyright
00011 #    notice, this list of conditions and the following disclaimer.
00012 #  * Redistributions in binary form must reproduce the above
00013 #    copyright notice, this list of conditions and the following
00014 #    disclaimer in the documentation and/or other materials provided
00015 #    with the distribution.
00016 #  * Neither the name of Willow Garage, Inc. nor the names of its
00017 #    contributors may be used to endorse or promote products derived
00018 #    from this software without specific prior written permission.
00019 #
00020 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 # POSSIBILITY OF SUCH DAMAGE.
00032 #
00033 # Revision $Id: substitution_args.py 15178 2011-10-10 21:22:53Z kwc $
00034 
00035 """
00036 Library for processing XML substitution args.
00037 """
00038 
00039 import os
00040 
00041 try:
00042     from cStringIO import StringIO # Python 2.x
00043 except ImportError:
00044     from io import StringIO # Python 3.x
00045 
00046 
00047 class SubstitutionException(Exception):
00048     """
00049     Base class for exceptions in substitution_args routines
00050     """
00051     pass
00052 class ArgException(SubstitutionException):
00053     """
00054     Exception for missing $(arg) values
00055     """
00056     pass
00057 
00058 def _split_command(resolved, command_with_args):
00059     cmd = '$(%s)' % command_with_args
00060     idx1 = resolved.find(cmd)
00061     idx2 = idx1 + len(cmd)
00062     return resolved[0:idx1], resolved[idx2:]
00063 
00064 
00065 def _separate_first_path(value):
00066     idx = value.find(' ')
00067     if idx < 0:
00068         path, rest = value, ''
00069     else:
00070         path, rest = value[0:idx], value[idx:]
00071     return path, rest
00072 
00073 
00074 def _sanitize_path(path):
00075     path = path.replace('/', os.sep)
00076     path = path.replace('\\', os.sep)
00077     return path
00078 
00079 
00080 def _arg(resolved, a, args, context):
00081     """
00082     process $(arg) arg
00083     
00084     :returns: updated resolved argument, ``str``
00085     :raises: :exc:`ArgException` If arg invalidly specified
00086     """
00087     if len(args) == 0:
00088         raise SubstitutionException("$(arg var) must specify an environment variable [%s]"%(a))
00089     elif len(args) > 1:
00090         raise SubstitutionException("$(arg var) may only specify one arg [%s]"%(a))
00091     
00092     if 'arg' not in context:
00093         context['arg'] = {}
00094     arg_context = context['arg']
00095 
00096     arg_name = args[0]
00097     if arg_name in arg_context:
00098         arg_value = arg_context[arg_name]
00099         return resolved.replace("$(%s)"%a, arg_value)
00100     else:
00101         raise ArgException(arg_name)
00102 
00103 
00104 def resolve_args(arg_str, context=None, resolve_anon=True):
00105     """
00106     Resolves substitution args (see wiki spec U{http://ros.org/wiki/roslaunch}).
00107 
00108     @param arg_str: string to resolve zero or more substitution args
00109         in. arg_str may be None, in which case resolve_args will
00110         return None
00111     @type  arg_str: str
00112     @param context dict: (optional) dictionary for storing results of
00113         the 'anon' and 'arg' substitution args. multiple calls to
00114         resolve_args should use the same context so that 'anon'
00115         substitions resolve consistently. If no context is provided, a
00116         new one will be created for each call. Values for the 'arg'
00117         context should be stored as a dictionary in the 'arg' key.
00118     @type  context: dict
00119     @param resolve_anon bool: If True (default), will resolve $(anon
00120         foo). If false, will leave these args as-is.
00121     @type  resolve_anon: bool
00122 
00123     @return str: arg_str with substitution args resolved
00124     @rtype:  str
00125     @raise SubstitutionException: if there is an error resolving substitution args
00126     """
00127     if context is None:
00128         context = {}
00129     #parse found substitution args
00130     if not arg_str:
00131         return arg_str
00132     # first resolve variables like 'env' and 'arg'
00133     commands = {
00134         'arg': _arg,
00135     }
00136     resolved = _resolve_args(arg_str, context, resolve_anon, commands)
00137     # than resolve 'find' as it requires the subsequent path to be expanded already
00138 
00139     resolved = _resolve_args(resolved, context, resolve_anon, commands)
00140     return resolved
00141 
00142 def _resolve_args(arg_str, context, resolve_anon, commands):
00143     valid = ['arg']
00144     resolved = arg_str
00145     for a in _collect_args(arg_str):
00146         splits = [s for s in a.split(' ') if s]
00147         if not splits[0] in valid:
00148             raise SubstitutionException("Unknown substitution command [%s]. Valid commands are %s"%(a, valid))
00149         command = splits[0]
00150         args = splits[1:]
00151         if command in commands:
00152             resolved = commands[command](resolved, a, args, context)
00153     return resolved
00154 
00155 _OUT  = 0
00156 _DOLLAR = 1
00157 _LP = 2
00158 _IN = 3
00159 def _collect_args(arg_str):
00160     """
00161     State-machine parser for resolve_args. Substitution args are of the form:
00162     $(find package_name)/scripts/foo.py $(export some/attribute blar) non-relevant stuff
00163     
00164     @param arg_str: argument string to parse args from
00165     @type  arg_str: str
00166     @raise SubstitutionException: if args are invalidly specified
00167     @return: list of arguments
00168     @rtype: [str]
00169     """
00170     buff = StringIO()
00171     args = []
00172     state = _OUT
00173     for c in arg_str:
00174         # No escapes supported
00175         if c == '$':
00176             if state == _OUT:
00177                 state = _DOLLAR
00178             elif state == _DOLLAR:
00179                 pass
00180             else:
00181                 raise SubstitutionException("Dollar signs '$' cannot be inside of substitution args [%s]"%arg_str)
00182         elif c == '(':
00183             if state == _DOLLAR:
00184                 state = _LP
00185             elif state != _OUT:
00186                 raise SubstitutionException("Invalid left parenthesis '(' in substitution args [%s]"%arg_str)
00187         elif c == ')':
00188             if state == _IN:
00189                 #save contents of collected buffer
00190                 args.append(buff.getvalue())
00191                 buff.truncate(0)
00192                 buff.seek(0)
00193                 state = _OUT
00194             else:
00195                 state = _OUT
00196         elif state == _DOLLAR:
00197             # left paren must immediately follow dollar sign to enter _IN state
00198             state = _OUT
00199         elif state == _LP:
00200             state = _IN
00201 
00202         if state == _IN:
00203             buff.write(c)
00204     return args
00205 
00206 


rotors_gazebo
Author(s): Fadri Furrer, Michael Burri, Mina Kamel, Janosch Nikolic, Markus Achtelik
autogenerated on Thu Apr 18 2019 02:43:49