Skip to content

Parse bare words with hyphens inside containers as strings#670

Open
LeSingh1 wants to merge 1 commit into
google:masterfrom
LeSingh1:fix-561-hyphen-bareword-tuple
Open

Parse bare words with hyphens inside containers as strings#670
LeSingh1 wants to merge 1 commit into
google:masterfrom
LeSingh1:fix-561-hyphen-bareword-tuple

Conversation

@LeSingh1

@LeSingh1 LeSingh1 commented Jun 1, 2026

Copy link
Copy Markdown

Summary

Fixes #561.

A bare word containing a hyphen, such as foo-bar, parses as an AST BinOp (Name - Name). When such a word appeared inside a container like a tuple or list, _LiteralEval only rewrote bare ast.Name nodes into strings. The BinOp survived, ast.literal_eval failed on it, and the whole input collapsed back to a raw string.

DefaultParseValue('(foo-bar, baz)')  ->  '(foo-bar, baz)'   # whole thing a string

Expected: ('foo-bar', 'baz').

Fix

When walking the AST, also detect a bare-word BinOp (a BinOp whose leaves are all ast.Name) and replace it with its original source text as a string, using ast.get_source_segment. BinOps that contain numbers are deliberately left untouched so existing behavior is preserved.

After the change:

'(foo-bar, baz)'  ->  ('foo-bar', 'baz')
'[a-b-c, d]'      ->  ['a-b-c', 'd']
'{a: foo-bar}'    ->  {'a': 'foo-bar'}
'1+1'             ->  '1+1'        (unchanged)
'[1+1]'           ->  '[1+1]'      (unchanged)
'2017-10-10'      ->  '2017-10-10' (unchanged)

ast.get_source_segment is available on Python 3.8+, consistent with the existing 3.8 version guard in this file.

Tests

Added testDefaultParseValueBareWordsWithHyphens to fire/parser_test.py. It fails before the change and passes after. Full suite:

$ python -m pytest fire/parser_test.py -q
21 passed

core_test.py and fire_test.py also pass.


Developed with AI assistance and verified locally as described above.

A bare word containing a hyphen, such as foo-bar, parses as an AST BinOp
(Name - Name). When such a word appeared inside a container like a tuple
or list, _LiteralEval only rewrote bare ast.Name nodes into strings, so
the BinOp survived, ast.literal_eval failed on it, and the entire input
collapsed back to a raw string.

Detect a bare-word BinOp (a BinOp whose leaves are all ast.Name) and
replace it with its original source text as a string. BinOps that contain
numbers, such as 1+1 or 2017-10-10, are left untouched to preserve their
existing behavior.

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

Labels

None yet

1 participant