33 from __future__
import print_function, division
41 import xml.dom.minidom
43 from copy
import deepcopy
44 from .cli
import process_args
45 from .color
import error, message, warning
46 from .xmlutils
import opt_attrs, reqd_attrs, first_child_element, \
47 next_sibling_element, replace_node
52 encoding = {
'encoding':
'utf-8'}
59 substitution_args_context = {}
76 Prepend the dirname of the currently processed file 77 if filename_spec is not yet absolute 79 if not os.path.isabs(filename_spec):
80 parent_filename = filestack[-1]
81 basedir = os.path.dirname(parent_filename)
if parent_filename
else '.' 82 return os.path.join(basedir, filename_spec)
87 """Wrapper class for yaml lists to allow recursive inheritance of wrapper property""" 90 """This static method, used by both YamlListWrapper and YamlDictWrapper, 91 dispatches to the correct wrapper class depending on the type of yaml item""" 92 if isinstance(item, dict):
94 elif isinstance(item, list):
100 return YamlListWrapper.wrap(super(YamlListWrapper, self).
__getitem__(idx))
103 for item
in super(YamlListWrapper, self).
__iter__():
104 yield YamlListWrapper.wrap(item)
108 """Wrapper class providing dotted access to dict items""" 111 return YamlListWrapper.wrap(super(YamlDictWrapper, self).
__getitem__(item))
113 raise AttributeError(
"The yaml dictionary has no key '{}'".format(item))
115 __getitem__ = __getattr__
119 """utility function to construct radian values from yaml""" 120 value = loader.construct_scalar(node)
122 return float(
safe_eval(value, _global_symbols))
128 """utility function for converting degrees into radians from yaml""" 135 yaml.SafeLoader.add_constructor(
u'!radians', construct_angle_radians)
136 yaml.SafeLoader.add_constructor(
u'!degrees', construct_angle_degrees)
138 raise XacroException(
"yaml support not available; install python-yaml")
142 filestack.append(filename)
144 return YamlListWrapper.wrap(yaml.safe_load(f))
149 all_includes.append(filename)
153 results = re.split(
'[{}]'.format(sep), s)
155 return [item
for item
in results
if item]
167 def deprecate(f, msg):
168 def wrapper(*args, **kwargs):
170 return f(*args, **kwargs)
172 return wrapper
if msg
else f
174 def expose(*args, **kwargs):
176 source, ns, deprecate_msg = (kwargs.pop(key,
None)
for key
in [
'source',
'ns',
'deprecate_msg'])
179 if source
is not None:
180 addons.update([(key, source[key])
for key
in args])
183 addons.update(**kwargs)
190 result.update([(ns, target)])
191 target.update(addons)
193 if deprecate_msg
is not None:
194 result.update([(key, deprecate(f, deprecate_msg.format(name=key, ns=ns)))
for key, f
in addons.items()])
196 result.update(addons)
198 deprecate_msg =
'Using {name}() directly is deprecated. Use {ns}.{name}() instead.' 200 expose(
'list',
'dict',
'map',
'len',
'str',
'float',
'int',
'True',
'False',
'min',
'max',
'round',
203 expose(
'sorted',
'range', source=__builtins__, ns=
'python', deprecate_msg=deprecate_msg)
205 expose(
'list',
'dict',
'map',
'len',
'str',
'float',
'int',
'True',
'False',
'min',
'max',
'round',
206 'all',
'any',
'complex',
'divmod',
'enumerate',
'filter',
'frozenset',
'hash',
'isinstance',
'issubclass',
207 'ord',
'repr',
'reversed',
'slice',
'set',
'sum',
'tuple',
'type',
'zip', source=__builtins__, ns=
'python')
210 expose([(k, v)
for k, v
in math.__dict__.items()
if not k.startswith(
'_')], ns=
'math', deprecate_msg=
'')
213 expose(load_yaml=load_yaml, abs_filename=abs_filename_spec, dotify=YamlDictWrapper,
214 ns=
'xacro', deprecate_msg=deprecate_msg)
215 expose(arg=
lambda name: substitution_args_context[
'arg'][name], ns=
'xacro')
217 def message_adapter(f):
218 def wrapper(*args, **kwargs):
219 location = kwargs.pop(
'print_location', f.__name__
in [
'warning',
'error'])
220 kwargs.pop(
'file',
None)
231 expose([(f.__name__, message_adapter(f))
for f
in [message, warning, error, print_location]], ns=
'xacro')
232 expose(fatal=fatal, tokenize=tokenize, ns=
'xacro')
238 code = compile(expr.strip(),
"<expression>",
"eval")
239 invalid_names = [n
for n
in code.co_names
if n.startswith(
"__")]
241 raise XacroException(
"Use of invalid name(s): ",
', '.join(invalid_names))
242 globals.update(__builtins__= {})
243 return eval(code, globals, locals)
248 XacroException allows to wrap another exception (exc) and to augment 249 its error message: prefixing with msg and suffixing with suffix. 250 str(e) finally prints: msg str(exc) suffix 253 def __init__(self, msg=None, suffix=None, exc=None, macro=None):
254 super(XacroException, self).
__init__(msg)
257 self.
macros = []
if macro
is None else [macro]
261 return ' '.join([s
for s
in [
unicode(e)
for e
in items]
if s
not in [
'',
'None']])
269 Helper routine to fetch required and optional attributes 270 and complain about any additional attributes. 271 :param tag (xml.dom.Element): DOM element node 272 :param required [str]: list of required attributes 273 :param optional [str]: list of optional attributes 277 allowed = required + optional
278 extra = [a
for a
in tag.attributes.keys()
if a
not in allowed
and not a.startswith(
"xmlns:")]
280 warning(
"%s: unknown attribute(s): %s" % (tag.nodeName,
', '.join(extra)))
292 warning(
"Deprecated: xacro tag '{}' w/o 'xacro:' xml namespace prefix (will be forbidden in Noetic)".format(tag_name))
295 message(
"""Use the following command to fix incorrect tag usage: 296 find . -iname "*.xacro" | xargs sed -i 's#<\([/]\\?\)\(if\|unless\|include\|arg\|property\|macro\|insert_block\)#<\\1xacro:\\2#g'""")
297 print(file=sys.stderr)
301 allow_non_prefixed_tags =
True 306 Check whether tagName starts with xacro prefix. If not, issue a warning. 308 :return: True if tagName is accepted as xacro tag 309 False if tagName doesn't start with xacro prefix, but the prefix is required 311 if tag_name.startswith(
'xacro:'):
314 if allow_non_prefixed_tags:
316 return allow_non_prefixed_tags
331 from roslaunch.substitution_args
import resolve_args, ArgException
332 from rospkg.common
import ResourceNotFound
333 return resolve_args(s, context=substitution_args_context, resolve_anon=
False)
334 except ImportError
as e:
336 except ArgException
as e:
338 except ResourceNotFound
as e:
342 do_check_order =
False 360 if isinstance(value, _basestr):
362 if len(value) >= 2
and value[0] ==
"'" and value[-1] ==
"'":
366 for f
in [int, float,
lambda x: get_boolean_value(x,
None)]:
378 'Consider disabling lazy evaluation via lazy_eval="false"' 379 .format(
" -> ".join(self.
recursive + [key])))
386 value = self.
table[key]
387 if (verbosity > 2
and self.
parent is None)
or verbosity > 3:
388 print(
"{indent}use {key}: {value} ({loc})".format(
389 indent=self.
depth*
' ', key=key, value=value, loc=filestack[-1]), file=sys.stderr)
395 if key
in self.
table:
403 if do_check_order
and key
in self.
used and key
not in self.
redefined:
406 if key
in _global_symbols:
407 warning(
"redefining global symbol: %s" % key)
411 self.
table[key] = value
412 if unevaluated
and isinstance(value, _basestr):
418 if (verbosity > 2
and self.
parent is None)
or verbosity > 3:
419 print(
"{indent}set {key}: {value} ({loc})".format(
420 indent=self.
depth*
' ', key=key, value=value, loc=filestack[-1]), file=sys.stderr)
423 self.
_setitem(key, value, unevaluated=
True)
429 p.table.pop(key,
None)
434 key
in self.
table or \
439 if isinstance(self.
parent, Table):
455 return self.__getitem__(item)
457 raise NameError(
"name '{}' is not defined".format(item))
462 super(PropertyNameSpace, self).
__init__(parent)
467 super(MacroNameSpace, self).
__init__(*args, **kwargs)
475 self.__dict__.update(other.__dict__)
478 for k, v
in kwargs.items():
479 self.__setattr__(k, len(self.
res))
480 self.
res.append(re.compile(v))
497 for i
in range(len(self.
res)):
498 m = self.
res[i].match(self.
str)
500 self.
top = (i, m.group(0))
501 self.
str = self.
str[m.end():]
507 include_no_matches_msg =
"""Include tag's filename spec \"{}\" matched no files.""" 513 if elt.tagName
not in [
'xacro:include',
'include']:
517 if elt.tagName ==
'include':
522 if elt.childNodes
and not (len(elt.childNodes) == 1
and 523 elt.childNodes[0].nodeType == elt.TEXT_NODE):
535 except XacroException
as e:
536 if e.exc
and isinstance(e.exc, NameError)
and symbols
is None:
537 raise XacroException(
'variable filename is supported with in-order option only')
541 if re.search(
'[*[?]+', filename_spec):
543 filenames = sorted(glob.glob(filename_spec))
544 if len(filenames) == 0:
545 warning(include_no_matches_msg.format(filename_spec))
548 filenames = [filename_spec]
550 for filename
in filenames:
552 all_includes.append(filename)
557 """import all namespace declarations into parent""" 558 for name, value
in attributes.items():
559 if name.startswith(
'xmlns:'):
560 oldAttr = parent.getAttributeNode(name)
561 if oldAttr
and oldAttr.value != value:
562 warning(
"inconsistent namespace redefinitions for {name}:" 563 "\n old: {old}\n new: {new} ({new_file})".format(
564 name=name, old=oldAttr.value, new=value,
565 new_file=filestack[-1]))
567 parent.setAttribute(name, value)
572 filename_spec, namespace_spec =
check_attrs(elt, [
'filename'], [
'ns'])
575 namespace_spec = eval_text(namespace_spec, symbols)
579 raise XacroException(
'namespaces are supported with in-order option only')
585 warning(
"Child elements of a <xacro:include> tag are ignored")
591 filestack.append(filename)
592 include = parse(
None, filename).documentElement
595 func(include, ns_macros, ns_symbols)
596 included.append(include)
602 remove_previous_comments(elt)
622 Checks whether name is a valid property or macro identifier. 623 With python-based evaluation, we need to avoid name clashes with python keywords. 627 root = ast.parse(name)
629 if isinstance(root, ast.Module)
and \
630 len(root.body) == 1
and isinstance(root.body[0], ast.Expr)
and \
631 isinstance(root.body[0].value, ast.Name)
and root.body[0].value.id == name:
639 default_value =
'''\$\{.*?\}|\$\(.*?\)|(?:'.*?'|\".*?\"|[^\s'\"]+)+|''' 640 re_macro_arg = re.compile(
r'^\s*([^\s:=]+?)\s*:?=\s*(\^\|?)?(' + default_value +
')(?:\s+|$)(.*)')
646 parse the first param spec from a macro parameter string s 647 accepting the following syntax: <param>[:=|=][^|]<default> 648 :param s: param spec string 649 :return: param, (forward, default), rest-of-string 650 forward will be either param or None (depending on whether ^ was specified) 651 default will be the default string or None 652 If there is no default spec at all, the middle pair will be replaced by None 654 m = re_macro_arg.match(s)
657 param, forward, default, rest = m.groups()
660 return param, (param
if forward
else None, default), rest
663 result = s.lstrip().split(
None, 1)
664 return result[0],
None, result[1]
if len(result) > 1
else '' 668 assert(elt.tagName
in [
'macro',
'xacro:macro'])
669 remove_previous_comments(elt)
671 name, params =
check_attrs(elt, [
'name'], [
'params'])
673 warning(
"deprecated use of 'call' as macro name: xacro:call became a keyword")
674 if name.find(
'.') != -1:
675 raise XacroException(
"macro names must not contain '.' (reserved for namespaces): %s" % name)
676 if name.startswith(
'xacro:'):
677 warning(
"macro names must not contain prefix 'xacro:': %s" % name)
681 macro = macros.get(name,
Macro())
683 macro.history.append(deepcopy(filestack))
688 macro.defaultmap = {}
691 macro.params.append(param)
692 if value
is not None:
693 macro.defaultmap[param] = value
704 if elt.tagName
in [
'macro',
'xacro:macro'] \
714 assert(elt.tagName
in [
'property',
'xacro:property'])
715 remove_previous_comments(elt)
717 name, value, default, remove, scope, lazy_eval = \
718 check_attrs(elt, [
'name'], [
'value',
'default',
'remove',
'scope',
'lazy_eval'])
719 name = eval_text(name, table)
721 raise XacroException(
'Property names must be valid python identifiers: ' + name)
722 if name.startswith(
'__'):
723 raise XacroException(
'Property names must not start with double underscore:' + name)
724 remove = get_boolean_value(eval_text(remove
or 'false', table), remove)
725 if sum([value
is not None, default
is not None, remove]) > 1:
726 raise XacroException(
'Property attributes default, value, and remove are mutually exclusive: ' + name)
728 if remove
and name
in table:
733 if default
is not None:
734 if scope
is not None:
735 warning(
"%s: default property value can only be defined on local scope" % name)
736 if name
not in table:
749 lazy_eval = get_boolean_value(eval_text(lazy_eval
or 'true', table), lazy_eval)
751 if scope
and scope ==
'global':
752 target_table = table.root()
754 elif scope
and scope ==
'parent':
755 if table.parent
is not None:
756 target_table = table.parent
758 if not isinstance(table, PropertyNameSpace):
760 while isinstance(target_table, PropertyNameSpace):
761 target_table = target_table.parent
763 warning(
"%s: no parent scope at global scope " % name)
768 if not lazy_eval
and isinstance(value, _basestr):
769 value = eval_text(value, table)
771 target_table._setitem(name, value, unevaluated=lazy_eval)
779 if elt.tagName
in [
'property',
'xacro:property'] \
781 for name
in [
'default',
'remove']:
782 if name
in elt.attributes.keys():
783 raise XacroException(
'Property attribute {} supported with in-order option only'.format(name))
791 LEXER =
QuickLexer(DOLLAR_DOLLAR_BRACE=
r"^\$\$+(\{|\()",
792 EXPR=
r"^\$\{[^\}]*\}",
793 EXTENSION=
r"^\$\([^\)]*\)",
794 TEXT=
r"[^$]+|\$[^{($]+|\$$")
798 def eval_text(text, symbols):
801 return safe_eval(eval_text(s, symbols), _global_symbols, symbols)
802 except Exception
as e:
805 suffix=os.linesep +
"when evaluating expression '%s'" % s)
807 def handle_extension(s):
816 results.append(handle_expr(lex.next()[1][2:-1]))
817 elif id == lex.EXTENSION:
818 results.append(handle_extension(lex.next()[1][2:-1]))
820 results.append(lex.next()[1])
821 elif id == lex.DOLLAR_DOLLAR_BRACE:
822 results.append(lex.next()[1][1:])
824 if len(results) == 1:
828 return ''.join(map(unicode, results))
831 def eval_default_arg(forward_variable, default, symbols, macro):
832 if forward_variable
is None:
833 return eval_text(default, symbols)
835 return symbols[forward_variable]
837 if default
is not None:
838 return eval_text(default, symbols)
840 raise XacroException(
"Undefined property to forward: " + forward_variable, macro=macro)
843 def handle_dynamic_macro_call(node, macros, symbols):
846 raise XacroException(
"xacro:call is missing the 'macro' attribute")
847 name =
unicode(eval_text(name, symbols))
850 node.removeAttribute(
'macro')
851 node.tagName =
'xacro:' + name
854 return handle_macro_call(node, macros, symbols)
856 raise XacroException(
"unknown macro name '%s' in xacro:call" % name)
859 def resolve_macro(fullname, macros, symbols):
861 namespaces = fullname.split(
'.')
862 name = namespaces.pop(-1)
864 def _resolve(namespaces, name, macros, symbols):
866 for ns
in namespaces:
868 symbols = symbols[ns]
869 return macros, symbols, macros[name]
873 return _resolve([], fullname, macros, symbols)
876 return _resolve(namespaces, name, macros, symbols)
881 def handle_macro_call(node, macros, symbols):
882 if node.tagName.startswith(
'xacro:'):
883 name = node.tagName[6:]
884 elif allow_non_prefixed_tags:
890 macros, symbols, m = resolve_macro(name, macros, symbols)
891 if name
is node.tagName:
893 body = m.body.cloneNode(deep=
True)
897 if node.tagName ==
'xacro:call':
898 return handle_dynamic_macro_call(node, macros, symbols)
904 scoped_symbols =
Table(symbols)
906 for name, value
in node.attributes.items():
907 if name
not in params:
910 scoped_symbols._setitem(name, eval_text(value, symbols), unevaluated=
False)
911 node.setAttribute(name,
"")
914 eval_all(node, macros, symbols)
918 for param
in params[:]:
923 scoped_symbols[param] = block
926 if block
is not None:
927 raise XacroException(
"Unused block \"%s\"" % block.tagName, macro=m)
930 for param
in params[:]:
936 name, default = m.defaultmap.get(param, (
None,
None))
937 if name
is not None or default
is not None:
938 scoped_symbols._setitem(param, eval_default_arg(name, default, symbols, m), unevaluated=
False)
942 raise XacroException(
"Undefined parameters [%s]" %
",".join(params), macro=m)
944 eval_all(body, macros, scoped_symbols)
947 remove_previous_comments(node)
957 def get_boolean_value(value, condition):
959 Return a boolean value that corresponds to the given Xacro condition value. 960 Values "true", "1" and "1.0" are supposed to be True. 961 Values "false", "0" and "0.0" are supposed to be False. 962 All other values raise an exception. 964 :param value: The value to be evaluated. The value has to already be evaluated by Xacro. 965 :param condition: The original condition text in the XML. 966 :return: The corresponding boolean value, or a Python expression that, converted to boolean, corresponds to it. 967 :raises ValueError: If the condition value is incorrect. 970 if isinstance(value, _basestr):
971 if value ==
'true' or value ==
'True':
973 elif value ==
'false' or value ==
'False':
976 return bool(int(value))
980 raise XacroException(
"Xacro conditional \"%s\" evaluated to \"%s\", " 981 "which is not a boolean expression." % (condition, value))
984 _empty_text_node = xml.dom.minidom.getDOMImplementation().createDocument(
None,
"dummy",
None).createTextNode(
'\n\n')
987 def remove_previous_comments(node):
988 """remove consecutive comments in front of the xacro-specific node""" 989 next = node.nextSibling
990 previous = node.previousSibling
992 if previous.nodeType == xml.dom.Node.TEXT_NODE
and \
993 previous.data.isspace()
and previous.data.count(
'\n') <= 1:
994 previous = previous.previousSibling
996 if previous
and previous.nodeType == xml.dom.Node.COMMENT_NODE:
998 previous = previous.previousSibling
999 node.parentNode.removeChild(comment)
1003 if next
and _empty_text_node != next:
1004 node.parentNode.insertBefore(_empty_text_node, next)
1008 def eval_all(node, macros, symbols):
1009 """Recursively evaluate node, expanding macros, replacing properties, and evaluating expressions""" 1011 for name, value
in node.attributes.items():
1012 if name.startswith(
'xacro:'):
1013 node.removeAttribute(name)
1015 result =
unicode(eval_text(value, symbols))
1016 node.setAttribute(name, result)
1020 node.removeAttribute(
'xmlns:xacro')
1021 except xml.dom.NotFoundErr:
1024 node = node.firstChild
1025 eval_comments =
False 1027 next = node.nextSibling
1028 if node.nodeType == xml.dom.Node.ELEMENT_NODE:
1029 eval_comments =
False 1030 if node.tagName
in [
'insert_block',
'xacro:insert_block'] \
1034 if (
"**" + name)
in symbols:
1036 block = symbols[
'**' + name]
1038 elif (
"*" + name)
in symbols:
1040 block = symbols[
'*' + name]
1041 content_only =
False 1046 block = block.cloneNode(deep=
True)
1048 eval_all(block, macros, symbols)
1049 replace_node(node, by=block, content_only=content_only)
1054 elif node.tagName
in [
'property',
'xacro:property'] \
1058 elif node.tagName
in [
'macro',
'xacro:macro'] \
1062 elif node.tagName
in [
'arg',
'xacro:arg'] \
1064 name, default =
check_attrs(node, [
'name',
'default'], [])
1065 if name
not in substitution_args_context[
'arg']:
1066 substitution_args_context[
'arg'][name] =
unicode(eval_text(default, symbols))
1068 remove_previous_comments(node)
1071 elif node.tagName ==
'xacro:element':
1072 name = eval_text(*
reqd_attrs(node, [
'xacro:name']), symbols=symbols)
1076 node.removeAttribute(
'xacro:name')
1077 node.nodeName = node.tagName = name
1080 elif node.tagName ==
'xacro:attribute':
1081 name, value = [eval_text(a, symbols)
for a
in reqd_attrs(node, [
'name',
'value'])]
1085 node.parentNode.setAttribute(name, value)
1088 elif node.tagName
in [
'if',
'xacro:if',
'unless',
'xacro:unless'] \
1090 remove_previous_comments(node)
1092 keep = get_boolean_value(eval_text(cond, symbols), cond)
1093 if node.tagName
in [
'unless',
'xacro:unless']:
1097 eval_all(node, macros, symbols)
1102 elif handle_macro_call(node, macros, symbols):
1107 if node.tagName.startswith(
"xacro:"):
1108 raise XacroException(
"unknown macro name: %s" % node.tagName[6:])
1110 eval_all(node, macros, symbols)
1112 elif node.nodeType == xml.dom.Node.TEXT_NODE:
1113 node.data =
unicode(eval_text(node.data, symbols))
1114 if node.data.strip():
1115 eval_comments =
False 1117 elif node.nodeType == xml.dom.Node.COMMENT_NODE:
1118 if "xacro:eval-comments" in node.data:
1119 eval_comments =
"xacro:eval-comments:off" not in node.data
1122 node.data =
unicode(eval_text(node.data, symbols))
1129 def parse(inp, filename=None):
1131 Parse input or filename into a DOM tree. 1132 If inp is None, open filename and load from there. 1133 Otherwise, parse inp, either as string or file object. 1134 If inp is already a DOM tree, this function is a noop. 1135 :return:xml.dom.minidom.Document 1136 :raise: xml.parsers.expat.ExpatError 1141 inp = f = open(filename)
1142 except IOError
as e:
1148 if isinstance(inp, _basestr):
1149 return xml.dom.minidom.parseString(inp)
1150 elif hasattr(inp,
'read'):
1151 return xml.dom.minidom.parse(inp)
1159 def process_doc(doc,
1160 in_order=True, just_deps=False, just_includes=False,
1161 mappings=None, xacro_ns=True, **kwargs):
1162 global verbosity, do_check_order
1163 verbosity = kwargs.get(
'verbosity', verbosity)
1164 do_check_order = kwargs.get(
'do_check_order', do_check_order)
1167 if mappings
is None:
1169 substitution_args_context[
'arg'] = mappings
1171 global allow_non_prefixed_tags
1172 allow_non_prefixed_tags = xacro_ns
1180 if (just_deps
or just_includes)
and not in_order:
1193 targetNS = doc.documentElement.getAttribute(
'xacro:targetNamespace')
1195 doc.documentElement.removeAttribute(
'xacro:targetNamespace')
1196 doc.documentElement.setAttribute(
'xmlns', targetNS)
1198 eval_all(doc.documentElement, macros, symbols)
1201 substitution_args_context[
'arg'] = {}
1203 if do_check_order
and symbols.redefined:
1204 warning(
"Document is incompatible to in-order processing.")
1205 warning(
"The following properties were redefined after usage:")
1206 for k, v
in symbols.redefined.items():
1207 message(k,
"redefined in", v, color=
'yellow')
1210 def open_output(output_filename):
1211 if output_filename
is None:
1214 dir_name = os.path.dirname(output_filename)
1217 os.makedirs(dir_name)
1224 return open(output_filename,
'w')
1225 except IOError
as e:
1229 def print_location():
1230 msg =
'when instantiating macro:' 1231 for m
in reversed(macrostack
or []):
1232 name = m.body.getAttribute(
'name')
1233 location =
'({file})'.format(file = m.history[-1][-1]
or '???')
1234 print(msg, name, location, file=sys.stderr)
1235 msg =
'instantiated from:' 1237 msg =
'in file:' if macrostack
else 'when processing file:' 1238 for f
in reversed(filestack
or []):
1241 print(msg, f, file=sys.stderr)
1242 msg =
'included from:' 1245 def process_file(input_file_name, **kwargs):
1246 """main processing pipeline""" 1250 doc = parse(
None, input_file_name)
1252 process_doc(doc, **kwargs)
1255 banner = [xml.dom.minidom.Comment(c)
for c
in 1256 [
" %s " % (
'=' * 83),
1257 " | This document was autogenerated by xacro from %-30s | " % input_file_name,
1258 " | EDITING THIS FILE BY HAND IS NOT RECOMMENDED %-30s | " %
"",
1259 " %s " % (
'=' * 83)]]
1260 first = doc.firstChild
1261 for comment
in banner:
1262 doc.insertBefore(comment, first)
1274 doc = process_file(input_file_name, **vars(opts))
1276 out = open_output(opts.output)
1279 except xml.parsers.expat.ExpatError
as e:
1280 error(
"XML parsing error: %s" %
unicode(e), alt_text=
None)
1283 print(file=sys.stderr)
1284 print(
"Check that:", file=sys.stderr)
1285 print(
" - Your XML is well-formed", file=sys.stderr)
1286 print(
" - You have the xacro xmlns declaration:",
1287 "xmlns:xacro=\"http://www.ros.org/wiki/xacro\"", file=sys.stderr)
1290 except Exception
as e:
1298 print(file=sys.stderr)
1305 out.write(
" ".join(set(all_includes)))
1310 out.write(doc.toprettyxml(indent=
' ', **encoding))
def __init__(self, args, kwargs)
def _setitem(self, key, value, unevaluated)
def check_deprecated_tag(tag_name)
def process_includes(elt, macros=None, symbols=None)
def grab_properties(elt, table)
def __init__(self, msg=None, suffix=None, exc=None, macro=None)
def __setitem__(self, key, value)
def construct_angle_radians(loader, node)
def next_sibling_element(node)
def abs_filename_spec(filename_spec)
def __getattr__(self, item)
def process_include(elt, macros, symbols, func)
def grab_property(elt, table)
def __init__(self, args, kwargs)
def construct_angle_degrees(loader, node)
def first_child_element(elt)
def tokenize(s, sep=', skip_empty=True)
def create_global_symbols()
def import_xml_namespaces(parent, attributes)
def grab_macro(elt, macros)
def safe_eval(expr, globals, locals=None)
def reqd_attrs(tag, attrs)
def __delitem__(self, key)
def message(msg, args, kwargs)
def __getattr__(self, item)
def replace_node(node, by, content_only=False)
def __contains__(self, key)
def warning(args, kwargs)
def process_args(argv, require_input=True)
def __init__(self, parent=None)
def __getitem__(self, idx)
def grab_macros(elt, macros)
def deprecated_tag(tag_name=None, _issued=[False])
def check_attrs(tag, required, optional)
def __getitem__(self, key)
def __init__(self, parent=None)
def get_include_files(filename_spec, symbols)
def opt_attrs(tag, attrs)