Skip to content

Argument values containing quotes are unexpectedly parsed as string literals in conditionals #377

@tomqext

Description

@tomqext

This came up when calling xacro from python. Not sure if this is an actual problem or expected behavior. I've lost a couple of days on this so at the very least maybe this can serve as a warning to the next person

Problem (?)

When passing argument values that contain single quote characters to xacro, the single quotes are interpreted as string literal delimiters within conditional expressions rather than as part of the value itself. Double quotes are not. This leads to (in my opinion) surprising and inconsistent behavior.

Steps to reproduce

example_problem.xacro

<?xml version="1.0" ?>
<robot name="example_problem" xmlns:xacro="http://www.ros.org/wiki/xacro">

  <xacro:arg name="example_arg" default="" />
  <xacro:property name="example_arg" value="$(arg example_arg)" />

  <xacro:if value="${example_arg == ''}">
    <link name="example_link"/>
  </xacro:if>

</robot>

Example calls to xacro

# Empty string: if conditional evaluates to true - resulting URDF contains example_link
xacro example_problem.xacro example_arg:=

# Literal single quotes: also matches empty string - resulting URDF contains example_link
xacro example_problem.xacro example_arg:="''"

# Literal double quotes: does not match empty string - resulting URDF does not contain example_link
xacro example_problem.xacro example_arg:='""'

This is particularly confusing when calling xacro from Python, where quote characters naturally end up in argument values:

# User intends to pass an empty string, but actually passes literal ""
subprocess.run(['xacro', 'example_problem.xacro', 'example_arg:=""'])

# User intends to pass an empty string, but '' gets parsed as empty string
# (happens to work, but maybe for the wrong reason)
subprocess.run(["xacro", "example_problem.xacro", "example_arg:=''"])

Is this behavior expected? Personally, I'd expect example_arg:="''" to be evaluated in the same way as example_arg:='""', but it feels like there might be some complexities here that I'm not fully aware of

EDIT: Perhaps a better example

example_problem_2.xacro

What if we're trying to match a single space in the conditional?

<?xml version="1.0" ?>
<robot name="example_problem" xmlns:xacro="http://www.ros.org/wiki/xacro">

  <xacro:arg name="example_arg" default="" />
  <xacro:property name="example_arg" value="$(arg example_arg)" />

  <xacro:if value="${example_arg == ' '}">
    <link name="example_link_space"/>
  </xacro:if>

</robot>
xacro example_problem_2.xacro example_arg:='" "'

Results in:

<?xml version="1.0" ?>
...
<robot name="example_problem">
</robot>

Whereas:

xacro example_problem_2.xacro example_arg:="' '"

Results in:

<?xml version="1.0" ?>
...
<robot name="example_problem">
  <link name="example_link_space"/>
</robot>

Environment

xacro version: 1.14.20
ROS: Noetic
OS: Ubuntu 20.04

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions