Skip to content

fix: parse hyphenated strings correctly inside container literals#678

Open
Yadidiah-k wants to merge 1 commit into
google:masterfrom
Yadidiah-k:fix/hyphenated-strings-in-containers
Open

fix: parse hyphenated strings correctly inside container literals#678
Yadidiah-k wants to merge 1 commit into
google:masterfrom
Yadidiah-k:fix/hyphenated-strings-in-containers

Conversation

@Yadidiah-k

Copy link
Copy Markdown

Fixes #561

What was wrong

When a hyphenated string like foo-bar appears inside a container literal — tuple, list, set, or dict — Python's ast.parse turns the hyphen into a BinOp(Sub) node (foo - bar). The AST walker in _LiteralEval only replaced bare Name nodes with strings; it left BinOp nodes untouched. When ast.literal_eval then encountered the unresolved BinOp, it raised ValueError, and the entire container fell back to a plain string.

# Before
>>> fire.Fire(lambda obj: type(obj).__name__, '(foo-bar,baz)')
str        # should be tuple

# After  
>>> fire.Fire(lambda obj: type(obj).__name__, '(foo-bar,baz)')
tuple

Fix

Added _BinOpSubToStr, a helper that recursively converts a Name-Sub-Name chain back to a hyphenated string (handles multi-segment names like a-b-c too). The walker now calls it alongside _Replacement for both list children and single-value fields. Works for tuples, lists, and dicts.

Numeric subtraction like 123-456 is unaffected — Constant nodes are not Name nodes and _BinOpSubToStr returns None for them, so no replacement happens.

Tests added

  • testDefaultParseValueHyphenatedStringsInTuple
  • testDefaultParseValueHyphenatedStringsInList
  • testDefaultParseValueHyphenatedStringsInDict

All 23 parser tests pass.

When a hyphenated string like 'foo-bar' appears inside a tuple, list,
set, or dict (e.g. '(foo-bar,baz)'), ast.parse turns the hyphen into a
BinOp(Sub) node. The AST walker only replaced bare Name nodes, leaving
the BinOp unresolved. ast.literal_eval then failed on the BinOp and the
entire container fell back to a plain string instead of a tuple/list/dict.

Add _BinOpSubToStr to recursively convert a Name-Sub-Name chain back to
a hyphenated string, and call it in the walker alongside _Replacement.
This handles multi-segment names like 'a-b-c' too.

Fixes google#561
@google-cla

google-cla Bot commented Jul 5, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tuple of strings parsed as string if one of the strings contains a hyphen

1 participant