4 from __future__
import print_function
9 from xml.dom.minidom
import parseString
18 from cStringIO
import StringIO
20 from io
import StringIO
21 from contextlib
import contextmanager
25 whitespace = re.compile(
r'\s+')
29 if whitespace.sub(
' ', a).strip() == whitespace.sub(
' ', b).strip():
33 a_dict = ast.literal_eval(a)
34 b_dict = ast.literal_eval(b)
35 if (isinstance(a_dict, dict)
and isinstance(b_dict, dict)
and a_dict == b_dict):
41 def match_splits(a_, b_):
42 if len(a_) != len(b_):
return False 43 for a, b
in zip(a_, b_):
46 if abs(float(a) - float(b)) > 1.0e-9:
52 return match_splits(a.split(), b.split())
56 if len(a.attributes) != len(b.attributes):
57 print(
"Different number of attributes")
59 a_atts = a.attributes.items()
60 b_atts = b.attributes.items()
64 for a, b
in zip(a_atts, b_atts):
66 print(
"Different attribute names: %s and %s" % (a[0], b[0]))
69 print(
"Different attribute values: %s and %s" % (a[1], b[1]))
76 print(
"Different text values: '%s' and '%s'" % (a, b))
86 if a.nodeType != b.nodeType:
87 print(
"Different node types: %s and %s" % (a, b))
91 if a.nodeType
in [xml.dom.Node.TEXT_NODE,
92 xml.dom.Node.CDATA_SECTION_NODE,
93 xml.dom.Node.COMMENT_NODE]:
97 if a.nodeType != xml.dom.Node.ELEMENT_NODE:
101 if a.nodeName != b.nodeName:
102 print(
"Different element names: %s and %s" % (a.nodeName, b.nodeName))
114 ((a.nodeType
in ignore_nodes)
or 115 (a.nodeType == xml.dom.Node.TEXT_NODE
and whitespace.sub(
'', a.data) ==
""))):
118 ((b.nodeType
in ignore_nodes)
or 119 (b.nodeType == xml.dom.Node.TEXT_NODE
and whitespace.sub(
'', b.data) ==
""))):
125 if a: a = a.nextSibling
126 if b: b = b.nextSibling
132 if isinstance(a, str):
133 return xml_matches(parseString(a).documentElement, b, ignore_nodes)
134 if isinstance(b, str):
135 return xml_matches(a, parseString(b).documentElement, ignore_nodes)
136 if a.nodeType == xml.dom.Node.DOCUMENT_NODE:
137 return xml_matches(a.documentElement, b, ignore_nodes)
138 if b.nodeType == xml.dom.Node.DOCUMENT_NODE:
139 return xml_matches(a, b.documentElement, ignore_nodes)
142 print(
"Match failed:")
143 a.writexml(sys.stdout)
146 b.writexml(sys.stdout)
155 old, sys.stderr = sys.stderr, StringIO()
156 result = function(*args, **kwargs)
158 yield (result, sys.stderr.read())
166 self.assertTrue(
text_matches(
" foo bar ",
"foo \t\n\r bar"))
169 self.assertTrue(
text_matches(
"0.123456789",
"0.123456788"))
171 self.assertFalse(
text_matches(
"0.123456789",
"0.1234567879"))
174 self.assertTrue(
text_matches(
"{'a': 1, 'b': 2, 'c': 3}",
"{'c': 3, 'b': 2, 'a': 1}"))
176 self.assertFalse(
text_matches(
"{'a': 1, 'b': 2, 'c': 3}",
"{'c': 3, 'b': 2, 'a': 0}"))
179 self.assertTrue(
xml_matches(
'''<foo/>''',
'''<foo> \t\n\r </foo>'''))
181 self.assertTrue(
xml_matches(
'''<foo> \t\n\r </foo>''',
'''<foo/>'''))
183 self.assertTrue(
xml_matches(
'''<a><b/></a>''',
'''<a>\n<b> </b> </a>'''))
186 self.assertTrue(
xml_matches(
'''<a><b/><!-- foo --> <!-- bar --></a>''',
187 '''<a><b/></a>''', [xml.dom.Node.COMMENT_NODE]))
206 content = {
'xacro:simple':
'simple'}
207 ns2 = dict({k: v+
'2' for k,v
in content.items()})
208 ns1 = dict({k: v+
'1' for k,v
in content.items()})
210 macros = dict(content)
211 macros.update(ns1=ns1)
213 self.assertEqual(xacro.resolve_macro(
'simple', macros),
'simple')
214 self.assertEqual(xacro.resolve_macro(
'ns1.simple', macros),
'simple1')
215 self.assertEqual(xacro.resolve_macro(
'ns1.ns2.simple', macros),
'simple2')
217 self.assertEqual(xacro.resolve_macro(
'xacro:simple', macros),
'simple')
218 self.assertEqual(xacro.resolve_macro(
'xacro:ns1.simple', macros),
'simple1')
219 self.assertEqual(xacro.resolve_macro(
'xacro:ns1.ns2.simple', macros),
'simple2')
223 self.assertEqual(p, param, msg=
"'{0}' != '{1}' parsing {2}".format(p, param, s))
224 if forward
or default:
225 self.assertTrue(v
is not None)
226 self.assertEqual(v[0], forward, msg=
"'{0}' != '{1}' parsing {2}".format(v[0], forward, s))
227 self.assertEqual(v[1], default, msg=
"'{0}' != '{1}' parsing {2}".format(v[1], default, s))
229 self.assertTrue(v
is None)
230 self.assertEqual(r, rest, msg=
"'{0}' != '{1}' parsing {2}".format(r, rest, s))
233 for forward
in [
'',
'^',
'^|']:
234 defaults = [
'',
"f('some string','some other')",
"f('a b')"]
235 if forward ==
'^': defaults = [
'']
236 for default
in defaults:
237 seps = [
'=',
':=']
if forward
or default
else [
'']
239 for rest
in [
'',
' ',
' bar',
' bar=42']:
240 s =
'foo{0}{1}{2}{3}'.format(sep, forward, default, rest)
242 default
if default
else None,
245 for ws
in [
' ',
' \t ',
' \n ']:
246 self.
check_macro_arg(ws +
'foo' + ws +
'bar=42' + ws,
'foo',
None,
None,
'bar=42' + ws)
251 super(TestXacroBase, self).
__init__(*args, **kwargs)
262 args.update(vars(opts))
263 args.update(dict(in_order = self.
in_order))
266 doc = xacro.parse(xml)
267 xacro.process_doc(doc, **args)
273 args.append(
'--inorder')
274 test_dir = os.path.abspath(os.path.dirname(__file__))
275 xacro_path = os.path.join(test_dir,
'..',
'scripts',
'xacro')
276 subprocess.call([xacro_path, input_path] + args)
282 super(TestXacroCommentsIgnored, self).
__init__(*args, **kwargs)
287 test_dir= os.path.abspath(os.path.dirname(__file__))
288 pr2_xacro_path = os.path.join(test_dir,
'robots',
'pr2',
'pr2.urdf.xacro')
289 pr2_golden_parse_path = os.path.join(test_dir,
'robots',
'pr2',
'pr2_1.11.4.xml')
291 xml.dom.minidom.parse(pr2_golden_parse_path),
298 super(TestXacroCommentsIgnored, self).
__init__(*args, **kwargs)
302 src =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 303 <xacro:property name="invalid.name"/></a>''' 307 src =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 308 <xacro:macro name="foo"><a>foo</a></xacro:macro> 309 <xacro:macro name="bar"><b>bar</b></xacro:macro> 310 <xacro:property name="var" value="%s"/> 311 <xacro:call macro="${var}"/></a>''' 312 res =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro">%s</a>''' 317 src =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 318 <xacro:macro name="foo"><a name="foo"/></xacro:macro> 319 <xacro:macro name="call"><a name="bar"/></xacro:macro> 323 res =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"><a name="bar"/></a>''' 328 self.assertTrue(
"deprecated use of macro name 'call'" in output)
333 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 334 <xacro:call macro="foo"/></a>''')
339 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 340 <xacro:undefined><foo/><bar/></xacro:undefined></a>''')
343 src =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 344 <xacro:macro name="foo" params="name"><xacro:element xacro:name="${name}"/></xacro:macro> 345 <xacro:foo name="A"/> 346 <xacro:foo name="B"/> 348 res =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"><A/><B/></a>''' 352 src =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 353 <xacro:macro name="foo" params="name value"> 354 <tag><xacro:attribute name="${name}" value="${value}"/></tag> 356 <xacro:foo name="A" value="foo"/> 357 <xacro:foo name="B" value="bar"/> 359 res =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"><tag A="foo"/><tag B="bar"/></a>''' 363 src =
'''<xml xmlns:xacro="http://www.ros.org/wiki/xacro"> 364 <xacro:property name="foo" value="1.0"/> 365 <xacro:macro name="m" params="foo"><a foo="${foo}"/></xacro:macro> 366 <xacro:m foo="1 ${foo}"/> 367 <!-- now redefining the property and macro --> 368 <xacro:property name="foo" value="2.0"/> 369 <xacro:macro name="m" params="foo"><b bar="${foo}"/></xacro:macro> 370 <xacro:m foo="2 ${foo}"/> 373 <xml xmlns:xacro="http://www.ros.org/wiki/xacro"> 379 <xml xmlns:xacro="http://www.ros.org/wiki/xacro"> 388 self.
quick_xacro(
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 389 <xacro:macro name="inner" params="*the_block"> 390 <in_the_inner><xacro:insert_block name="the_block" /></in_the_inner> 392 <xacro:macro name="outer" params="*the_block"> 393 <in_the_outer><xacro:inner><xacro:insert_block name="the_block" /></xacro:inner></in_the_outer> 395 <xacro:outer><woot /></xacro:outer></a>'''),
396 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 397 <in_the_outer><in_the_inner><woot /></in_the_inner></in_the_outer></a>''')
401 <xacro:macro name="foo" params="lst">${lst[-1]}</xacro:macro> 402 <foo lst="${[1,2,3]}"/></a>'''),
403 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro">3</a>''')
407 <xacro:macro name="foo" params="a='1 -2' c=3"><bar a="${a}" c="${c}"/></xacro:macro> 408 <xacro:foo/></a>'''),
409 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"><bar a="1 -2" c="3"/></a>''')
413 self.
quick_xacro(
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 414 <xacro:property name="foo" value="42" /> 415 <the_foo result="${foo}" /> 417 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 418 <the_foo result="42" /> 423 <xacro:macro name="foo" params="factor"> 424 <xacro:property name="foo" value="${21*factor}" scope="parent"/> 426 <xacro:foo factor="2"/><a foo="${foo}"/></a>'''),
427 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"><a foo="42"/></a>''')
431 <xacro:macro name="foo" params="factor"> 432 <xacro:macro name="bar"> 433 <xacro:property name="foo" value="${21*factor}" scope="global"/> 437 <xacro:foo factor="2"/><a foo="${foo}"/></a>'''),
438 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"><a foo="42"/></a>''')
442 self.
quick_xacro(
'''<a><f v="${0.9 / 2 - 0.2}" /></a>'''),
443 '''<a><f v="0.25" /></a>''')
447 self.
quick_xacro(
'''<a><f v="$(find xacro)/test/test_xacro.py" /></a>'''),
448 '''<a><f v="''' + os.path.abspath((__file__).replace(
".pyc",
".py") +
'''" /></a>'''))
452 self.
quick_xacro(
'''<a><f v="$(arg sub_arg)" /></a>''', cli=[
'sub_arg:=my_arg']),
453 '''<a><f v="my_arg" /></a>''')
457 self.
quick_xacro(
'''<a b="$${foo}" c="$$${foo}" d="text $${foo}" e="text $$${foo}" f="$$(pwd)" />'''),
458 '''<a b="${foo}" c="$${foo}" d="text ${foo}" e="text $${foo}" f="$(pwd)" />''')
462 self.
quick_xacro(
'''<a b="$" c="text $" d="text $ text"/>'''),
463 '''<a b="$" c="text $" d="text $ text"/>''')
467 self.
quick_xacro(
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 468 <xacro:macro name="foo" params="*block"> 469 <xacro:insert_block name="block" /> 470 <xacro:insert_block name="block" /> 476 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 482 src =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 483 <xacro:macro name="foo" params="*block{A} *block{B}"> 484 <xacro:insert_block name="block1" /> 485 <xacro:insert_block name="block2" /> 492 res =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 497 for d
in [dict(A=
'1', B=
'2'), dict(A=
'2', B=
'1')]:
502 self.
quick_xacro(
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 503 <xacro:macro name="m" params="num"> 504 <test number="${num}" /> 506 <xacro:m num="100" /> 508 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 509 <test number="100" /> 514 self.
quick_xacro(
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 515 <xacro:macro name="bar">bar</xacro:macro> 516 <xacro:property name="val" value="2" /> 517 <xacro:property name="some_block"> 518 <some_block attr="${val}"><xacro:bar/></some_block> 521 <xacro:insert_block name="some_block" /> 524 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 525 <foo><some_block attr="2">bar</some_block></foo> 530 <a xmlns:xacro="http://www.ros.org/xacro"> 531 <xacro:include filename="include1.xml" /></a>'''),
532 '''<a xmlns:xacro="http://www.ros.org/xacro"><inc1/></a>''')
535 input =
'''<a xmlns:xacro="http://www.ros.org/xacro"> 536 <xacro:include filename="include{glob}.xml"/></a>''' 537 result =
'<a xmlns:xacro="http://www.ros.org/xacro"><inc1/><inc2/></a>' 538 for pattern
in [
'*',
'?',
'[1-2]']:
543 self.
quick_xacro,
'''<a xmlns:xacro="http://www.ros.org/xacro"> 544 <xacro:include filename="include-nada.xml" /></a>''')
548 src =
'''<a><include filename="nada"><tag/></include></a>''' 551 self.assertEqual(output,
'')
554 doc =
'''<a xmlns:xacro="http://www.ros.org/xacro"> 555 <xacro:property name="file" value="include1.xml"/> 556 <xacro:include filename="${file}" /></a>''' 559 '''<a xmlns:xacro="http://www.ros.org/xacro"><inc1/></a>''')
565 <a xmlns:xacro="http://www.ros.org/xacro"> 566 <xacro:include filename="include1.xml"/> 567 <xacro:include filename="./include1.xml"/> 568 <xacro:include filename="subdir/include-recursive.xacro"/> 570 '''<a xmlns:xacro="http://www.ros.org/xacro"> 572 <subdir_inc1/><subdir_inc1/><inc1/></a>''')
576 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 577 <xacro:property name="var" value="main"/> 578 <xacro:include filename="include1.xacro" ns="A"/> 579 <xacro:include filename="include2.xacro" ns="B"/> 581 <main var="${var}" A="${2*A.var}" B="${B.var+1}"/> 584 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 585 <inc1/><inc2/><main var="main" A="2" B="3"/> 596 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 597 <xacro:if value="false"> 600 <xacro:if value="true"> 605 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 612 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 613 <xacro:if value="nonsense"><foo/></xacro:if></a>''')
618 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 619 <xacro:if value="${0*42}"> 625 <xacro:if value="${0}"> 628 <xacro:if value="${1*2+3}"> 633 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 640 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 641 <xacro:if value="${3*0.0}"> 644 <xacro:if value="${3*0.1}"> 649 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 656 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 657 <xacro:property name="condT" value="${True}"/> 658 <xacro:property name="condF" value="${False}"/> 659 <xacro:if value="${condF}"><a /></xacro:if> 660 <xacro:if value="${condT}"><b /></xacro:if> 661 <xacro:if value="${True}"><c /></xacro:if> 664 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 670 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 671 <xacro:if value="1"><xacro:if value="0"><a>bar</a></xacro:if></xacro:if> 673 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"/>''')
677 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 678 <xacro:property name="var" value="useit"/> 679 <xacro:if value="${var == 'useit'}"><foo>bar</foo></xacro:if> 680 <xacro:if value="${'use' in var}"><bar>foo</bar></xacro:if> 682 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 689 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 690 <xacro:property name="xyz" value="5 -2"/> 693 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 699 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 700 <foo function="${1. + sin(pi)}"/> 702 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 703 <foo function="1.0"/> 708 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 709 <xacro:if value="1"><!-- comment --> text <b>bar</b></xacro:if> 711 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 712 <!-- comment --> text <b>bar</b></a>''')
716 self.
quick_xacro(
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 717 <xacro:macro name="foo" params="*block"> 720 <xacro:insert_block name="block" /> 723 <!-- ignored comment --> 728 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 736 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 739 <!-- ignore multiline comments before any xacro tag --> 741 <xacro:property name="foo" value="1"/> 743 <xacro:if value="1"><!-- B --></xacro:if> 745 <xacro:macro name="foo"><!-- C --></xacro:macro> 749 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 750 <!-- A --><!-- B --><!-- C --></a>''')
755 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 756 <xacro:property name="a" value=" 42 "/> 757 <xacro:property name="a2" value="${ 2 * a }"/> 761 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 768 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 769 <xacro:property name="a2" value="${2*a}"/> 770 <xacro:property name="a" value="42"/> 774 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 781 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 782 <xacro:property name="a" value="${a2}"/> 783 <xacro:property name="a2" value="${2*a}"/> 790 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 791 <xacro:property name="a" value="1"/> 792 <xacro:property name="b" value="2"/> 793 <xacro:property name="c" value="3"/> 794 <xacro:property name="product" value="${a*b*c}"/> 795 <answer product="${product}"/> 798 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 799 <answer product="6"/> 805 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 806 <xacro:property name="a" value="42"/> 807 <xacro:property name="b" value="${a}"/> 808 <xacro:property name="b" value="${-a}"/> 809 <xacro:property name="b" value="${a}"/> 810 <answer b="${b} ${b} ${b}"/> 813 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 814 <answer b="42 42 42"/> 820 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 821 <xacro:property name="a" value="42"/> 822 <xacro:property name="b" value="${a}"/> 823 <xacro:property name="c" value="${b}"/> 824 <xacro:property name="d" value="${c}"/> 828 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 835 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 836 <xacro:property name="a" value="42"/> 837 <xacro:property name="b" value="2.1"/> 838 <xacro:property name="c" value="${a}"/> 839 <xacro:property name="d" value="${b}"/> 840 <xacro:property name="f" value="${c*d}"/> 844 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 851 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 852 <xacro:property name="x" value="42"/> 853 <xacro:property name="wheel_width" value="${x}"/> 854 <link name="my_link"> 855 <origin xyz="0 0 ${wheel_width/2}"/> 859 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 860 <link name="my_link"> 861 <origin xyz="0 0 21.0"/> 868 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 869 <xacro:property name="x" value="0"/> 870 <tag badness="${1/x}"/> 876 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 877 <xacro:macro name="fixed_link" params="parent_link:=base_link child_link *joint_pose"> 878 <link name="${child_link}"/> 879 <joint name="${child_link}_joint" type="fixed"> 880 <xacro:insert_block name="joint_pose" /> 881 <parent link="${parent_link}"/> 882 <child link="${child_link}" /> 885 <xacro:fixed_link child_link="foo"> 886 <origin xyz="0 0 0" rpy="0 0 0" /> 890 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 892 <joint name="foo_joint" type="fixed"> 893 <origin rpy="0 0 0" xyz="0 0 0"/> 894 <parent link="base_link"/> 902 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 903 <xacro:macro name="fixed_link" params="parent_link:=base_link child_link *joint_pose"> 904 <link name="${child_link}"/> 905 <joint name="${child_link}_joint" type="fixed"> 906 <xacro:insert_block name="joint_pose" /> 907 <parent link="${parent_link}"/> 908 <child link="${child_link}" /> 911 <xacro:fixed_link child_link="foo" parent_link="bar"> 912 <origin xyz="0 0 0" rpy="0 0 0" /> 916 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 918 <joint name="foo_joint" type="fixed"> 919 <origin rpy="0 0 0" xyz="0 0 0"/> 928 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 929 <xacro:macro name="fixed_link" params="parent_link child_link *joint_pose"> 930 <link name="${child_link}"/> 931 <joint name="${child_link}_joint" type="fixed"> 932 <xacro:insert_block name="joint_pose" /> 933 <parent link="${parent_link}"/> 934 <child link="${child_link}" /> 937 <xacro:fixed_link child_link="foo"> 938 <origin xyz="0 0 0" rpy="0 0 0" /> 945 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 946 <xacro:arg name="foo" default="2"/> 947 <link name="my_link"> 948 <origin xyz="0 0 $(arg foo)"/> 952 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 953 <link name="my_link"> 954 <origin xyz="0 0 2"/> 961 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 962 <xacro:arg name="foo" default="2"/> 963 <link name="my_link"> 964 <origin xyz="0 0 $(arg foo)"/> 967 ''', [
'foo:=4']),
'''\ 968 <robot xmlns:xacro="http://www.ros.org/wiki/xacro"> 969 <link name="my_link"> 970 <origin xyz="0 0 4"/> 975 self.assertRaises(Exception,
977 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 978 <a arg="$(arg foo)"/> 984 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 985 <xacro:arg name="foo" default=""/>$(arg foo)</a>'''),
986 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"/>''')
991 tmp_dir_name = tempfile.mkdtemp()
992 output_path = os.path.join(tmp_dir_name,
"should_not_exist")
993 self.
run_xacro(
'broken.xacro',
'-o', output_path)
995 output_file_created = os.path.isfile(output_path)
996 shutil.rmtree(tmp_dir_name)
998 self.assertFalse(output_file_created)
1003 tmp_dir_name = tempfile.mkdtemp()
1004 shutil.rmtree(tmp_dir_name)
1005 output_path = os.path.join(tmp_dir_name,
"out")
1006 self.
run_xacro(
'include1.xml',
'-o', output_path)
1008 output_file_created = os.path.isfile(output_path)
1009 shutil.rmtree(tmp_dir_name)
1011 self.assertTrue(output_file_created)
1016 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1017 <xacro:property name="list" value="[0, 1+1, 2]"/> 1018 <xacro:property name="tuple" value="(0,1+1,2)"/> 1019 <xacro:property name="dict" value="{'a':0, 'b':1+1, 'c':2}"/> 1020 <a list="${list}" tuple="${tuple}" dict="${dict}"/> 1022 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1023 <a list="[0, 1+1, 2]" tuple="(0,1+1,2)" dict="{'a':0, 'b':1+1, 'c':2}"/> 1029 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1030 <xacro:property name="list" value="${[0, 1+1, 2]}"/> 1031 <xacro:property name="tuple" value="${(0,1+1,2)}"/> 1032 <xacro:property name="dic" value="${dict(a=0, b=1+1, c=2)}"/> 1033 <a list="${list}" tuple="${tuple}" dict="${dic}"/> 1035 '''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1036 <a list="[0, 2, 2]" tuple="(0, 2, 2)" dict="{'a': 0, 'c': 2, 'b': 2}"/> 1042 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1043 <arg name="foo" value="bar"/> 1044 <include filename="foo"/> 1045 </a>''', xacro_ns=
False),
1047 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1048 <arg name="foo" value="bar"/> 1049 <include filename="foo"/> 1058 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1059 <xacro:arg name="foo" default="0.5"/> 1060 <xacro:property name="prop" value="$(arg foo)" /> 1061 <a prop="${prop-0.3}"/> 1064 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1071 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1072 <xacro:arg name="foo" default="0.5"/> 1073 <xacro:arg name="bar" default="$(arg foo)"/> 1074 <xacro:property name="prop" value="$(arg bar)" /> 1075 <a prop="${prop-0.3}"/> 1078 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1083 src =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1084 <xacro:macro name="xacro:my_macro"><foo/></xacro:macro> 1087 res =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"><foo/></a>''' 1091 src =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1092 <xacro:property name="pi" value="3.14"/></a>''' 1094 self.
assert_matches(result,
'<a xmlns:xacro="http://www.ros.org/wiki/xacro"/>')
1095 self.assertTrue(output)
1099 <a xmlns:xacro="http://www.ros.org/xacro"> 1100 <xacro:macro name="foo" params="a b:=${a} c:=$${a}"> a=${a} b=${b} c=${c} </xacro:macro> 1101 <xacro:property name="a" value="1"/> 1102 <xacro:property name="d" value="$${a}"/> 1103 <d d="${d}"><foo a="2"/></d> 1105 res =
'''<a xmlns:xacro="http://www.ros.org/xacro"><d d="${a}"> a=2 b=1 c=${a} </d></a>''' 1109 src=
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1110 <xacro:property name="arg" value="42"/> 1111 <xacro:macro name="foo" params="arg:=^%s">${arg}</xacro:macro> 1114 res=
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro">%s</a>''' 1120 src=
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro">${2*'$(arg var)'}</a>''' 1121 res=
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro">%s</a>''' 1125 src=
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro">$(arg ${'v'+'ar'})</a>''' 1126 res=
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro">%s</a>''' 1132 super(TestXacroInorder, self).
__init__(*args, **kwargs)
1136 doc = (
'''<a xmlns:xacro="http://www.ros.org/xacro"> 1137 <xacro:if value="false"><xacro:include filename="non-existent"/></xacro:if></a>''')
1139 '''<a xmlns:xacro="http://www.ros.org/xacro"/>''')
1144 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1145 <xacro:arg name="has_stuff" default="false"/> 1146 <xacro:if value="$(arg has_stuff)"> 1147 <xacro:include file="$(find nonexistent_package)/stuff.urdf" /> 1150 '<a xmlns:xacro="http://www.ros.org/wiki/xacro"/>')
1154 <a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1155 <xacro:property name="settings" value="${load_yaml('settings.yaml')}"/> 1156 <xacro:property name="type" value="$(arg type)"/> 1157 <xacro:include filename="${settings['arms'][type]['file']}"/> 1158 <xacro:call macro="${settings['arms'][type]['macro']}"/> 1160 res =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"><{tag}/></a>''' 1161 for i
in [
'inc1',
'inc2']:
1166 src=
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1167 <xacro:macro name="foo" params="arg:=${2*foo}"> 1168 <xacro:property name="foo" value="-"/> 1171 <xacro:property name="foo" value="${3*7}"/> 1173 <xacro:property name="foo" value="*"/> 1176 res=
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1177 <f val="42"/><f val="**"/></a>''' 1181 src =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1182 <xacro:property name="bar" value="unused"/> 1183 <xacro:property name="foo" value="unused"/> 1184 <xacro:macro name="foo" params="arg:=${foo}"> 1188 <xacro:property name="bar" value="dummy"/> 1189 <xacro:property name="foo" value="21"/></a>''' 1191 self.assertTrue(
"Document is incompatible to --inorder processing." in output)
1192 self.assertTrue(
"foo" in output)
1193 self.assertTrue(
"bar" not in output)
1197 <a xmlns:xacro="http://www.ros.org/xacro"> 1198 <xacro:property name="prop" default="false"/> 1199 <xacro:unless value="${prop}"> 1201 <xacro:property name="prop" value="true"/> 1204 <!-- second foo should be ignored --> 1205 <xacro:unless value="${prop}"> 1207 <xacro:property name="prop" value="true"/> 1210 res =
'''<a xmlns:xacro="http://www.ros.org/xacro"><foo/></a>''' 1214 src =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro">🍔 </a>''' 1218 src =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1219 <xacro:property name="burger" value="🍔"/> 1221 res =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro">🍔</a>''' 1225 src =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1226 <xacro:property name="burger" value="🍔"/> 1227 <b c="${burger}"/></a>''' 1228 res =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"><b c="🍔"/></a>''' 1232 src =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1233 <xacro:property name="burger"> 1236 <xacro:insert_block name="burger"/></a>''' 1237 res =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro">🍔</a>''' 1241 src =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1242 <xacro:property name="burger" value="🍔"/> 1243 <xacro:if value="${burger == u'🍔'}"> 1247 res =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro">🍟</a>''' 1251 src =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1252 <xacro:macro name="burger" params="how_many"> 1255 <xacro:burger how_many="4"/> 1257 res =
'''<a xmlns:xacro="http://www.ros.org/wiki/xacro"> 1264 test_dir= os.path.abspath(os.path.dirname(__file__))
1265 input_path = os.path.join(test_dir,
'emoji.xacro')
1266 tmp_dir_name = tempfile.mkdtemp()
1267 output_path = os.path.join(tmp_dir_name,
"out.xml")
1268 self.
run_xacro(input_path,
'-o', output_path)
1269 output_file_created = os.path.isfile(output_path)
1271 '''<robot xmlns:xacro="http://ros.org/wiki/xacro">🍔</robot>''')
1272 shutil.rmtree(tmp_dir_name)
1274 if __name__ ==
'__main__':
def test_from_issue(self)
def test_include_lazy(self)
def test_multiple_blocks(self)
def test_extension_in_expression(self)
def test_normalize_whitespace_nested(self)
def test_default_arg_empty(self)
def test_xacro_attribute(self)
def test_include_from_variable(self)
def test_recursive_bad_math(self)
def test_whitespace_vs_empty_node(self)
def __init__(self, args, kwargs)
def assert_matches(self, a, b)
def test_property_scope_global(self)
def test_include_deprecated(self)
def text_values_match(a, b)
def test_match_similar_numbers(self)
def test_equality_expression_in_if_statement(self)
def test_parse_macro_whitespace(self)
def test_default_param_override(self)
def test_multiple_definition_and_evaluation(self)
def test_evaluate_macro_params_before_body(self)
def test_broken_input_doesnt_create_empty_output_file(self)
def test_math_ignores_spaces(self)
def test_include_recursive(self)
def test_multiple_insert_blocks(self)
def test_math_expressions(self)
def test_boolean_if_statement(self)
def test_param_missing(self)
def test_consider_non_elements_block(self)
def test_recursive_evaluation_wrong_order(self)
def test_integer_if_statement(self)
def __init__(self, args, kwargs)
def test_overwrite_globals(self)
def capture_stderr(function, args, kwargs)
def test_mismatch_different_numbers(self)
def test_default_property(self)
def test_consecutive_if(self)
def test_is_valid_name(self)
def test_issue_63_fixed_with_inorder_processing(self)
def test_recursive_definition(self)
def test_macro_name_with_colon(self)
def test_unicode_property(self)
def test_default_param(self)
def test_yaml_support(self)
def test_property_forwarding(self)
def test_create_subdirs(self)
def test_invalid_property_name(self)
def test_transitive_evaluation(self)
def run_xacro(self, input_path, args)
def test_no_evaluation(self)
def test_parse_macro_arg(self)
def test_multi_tree_evaluation(self)
def test_include_nonexistent(self)
def test_float_if_statement(self)
def xml_matches(a, b, ignore_nodes=[])
def test_substitution_args_arg(self)
def test_default_arg_override(self)
def test_iterable_literals_eval(self)
def test_include_glob(self)
def test_macro_default_param_evaluation_order(self)
def test_consider_non_elements_if(self)
def test_integer_stays_integer(self)
def test_macro_undefined(self)
def test_multiple_recursive_evaluation(self)
def all_attributes_match(a, b)
def test_dynamic_macro_name_clash(self)
def test_substitution_args_find(self)
def test_insert_block_property(self)
def test_macro_params_escaped_string(self)
def test_include_with_namespace(self)
def test_default_arg(self)
def test_match_unordered_dicts(self)
def test_unicode_property_attribute(self)
def test_recursive_evaluation(self)
def test_property_scope_parent(self)
def test_no_double_evaluation(self)
def test_normalize_whitespace_text(self)
def test_expression_in_extension(self)
def test_unicode_property_block(self)
def process_args(argv, require_input=True)
def test_unicode_literal_parsing(self)
def test_transitive_arg_evaluation(self)
def test_xacro_element(self)
def test_mismatch_different_dicts(self)
def test_property_replacement(self)
def test_unicode_file(self)
def test_ignore_comments(self)
def test_enforce_xacro_ns(self)
def test_ignore_xacro_comments(self)
def test_dynamic_macro_names(self)
def test_inorder_processing(self)
def test_issue_68_numeric_arg(self)
def test_invalid_if_statement(self)
def test_just_a_dollar_sign(self)
def test_should_replace_before_macroexpand(self)
def test_normalize_whitespace_trim(self)
def test_unicode_macro(self)
def test_empty_node_vs_whitespace(self)
def test_escaping_dollar_braces(self)
def quick_xacro(self, xml, cli=None, kwargs)
def check_macro_arg(self, s, param, forward, default, rest)
def test_dynamic_macro_undefined(self)
def test_resolve_macro(self)
def __init__(self, args, kwargs)
def test_default_arg_missing(self)
def test_unicode_conditional(self)
def test_iterable_literals_plain(self)
def test_check_order_warning(self)
def nodes_match(a, b, ignore_nodes)