Skip to content

Commit

Permalink
Fix a newly-introduced bug in argument parsing
Browse files Browse the repository at this point in the history
The bug-fix in commit 426eff1 (v8.0.4) broke argument parsing in a different
way: commas inside nested arguments were treated as delimiting arguments in
the outermost macro.

Instead, find commas at the same time as counting nested braces.

Add a regression test.
  • Loading branch information
rrthomas committed Jan 25, 2025
1 parent 4d06db0 commit b1ca531
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 12 deletions.
35 changes: 23 additions & 12 deletions nancy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,14 @@ def read_file(file: str, args: list[str]) -> str:
macros["path"] = lambda _args: base_file
macros["realpath"] = lambda _args: file_path

def get_included_file(command_name: str, args: list[str]) -> tuple[str, str]:
def get_included_file(
command_name: str, args: list[str]
) -> tuple[str, str]:
debug(f"${command_name}{{{','.join(args)}}}")
if len(args) < 1:
raise ValueError(f"${command_name} expects at least one argument")
raise ValueError(
f"${command_name} expects at least one argument"
)
file = get_file(args[0])
return file, read_file(file, args[1:])

Expand All @@ -148,8 +152,7 @@ def paste(args: list[str]) -> str:

macros["paste"] = paste

def do_macro(macro: str, arg: Optional[str]) -> str:
args = [] if arg is None else re.split(r"(?<!\\),", arg)
def do_macro(macro: str, args: list[str]) -> str:
debug(f"do_macro {macro} {args}")
expanded_args: list[str] = []
for a in args:
Expand All @@ -172,27 +175,35 @@ def do_macro(macro: str, arg: Optional[str]) -> str:
debug(f"match: {res} {res.end()}")
escaped = res[1]
name = res[2]
args_start = res.end()
startpos = args_start
args = None
if args_start < len(expanded) and expanded[args_start] == "{":
arg_start = res.end()
startpos = arg_start
args = []
# Parse arguments, respecting nested commands
if arg_start < len(expanded) and expanded[arg_start] == "{":
depth = 1
next_index = args_start + 1
next_index = arg_start + 1
while next_index < len(expanded):
if expanded[next_index] == "}":
depth -= 1
if depth == 0:
args.append(expanded[arg_start + 1 : next_index])
break
elif expanded[next_index] == "{":
depth += 1
elif (
depth == 1
and expanded[next_index] == ","
and expanded[next_index - 1] != "\\"
):
args.append(expanded[arg_start + 1 : next_index])
arg_start = next_index
next_index += 1
if next_index == len(expanded):
raise ValueError("missing close brace")
startpos = next_index + 1
args = expanded[args_start + 1 : next_index]
if escaped != "":
# Just remove the leading '\'
output = f"${name}{f'{{{args}}}' if args is not None else ''}"
output = f"${name}{f'{{{".".join(args)}}}' if len(args) > 0 else ''}"
else:
output = do_macro(name, args)
expanded = expanded[: res.start()] + output + expanded[startpos:]
Expand Down Expand Up @@ -265,7 +276,7 @@ def main(argv: list[str] = sys.argv[1:]) -> None:
description="A simple templating system.",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=f"The INPUT-PATH is a '{os.path.pathsep}'-separated list; the inputs are merged\n"
+ "in left-to-right order."
+ "in left-to-right order.",
)
parser.add_argument(
"input",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bar
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bar
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
$include{echo,$include{foo.in.txt}}
8 changes: 8 additions & 0 deletions tests/test_nancy.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,14 @@ def test_expanding_a_file_with_relative_includes() -> None:
)


def test_nested_argument_in_comma_list_works() -> None:
with chdir(tests_dir):
passing_test(
["nested-argument-in-comma-list-src"],
"nested-argument-in-comma-list-expected",
)


def test_empty_input_path_causes_an_error() -> None:
with chdir(tests_dir):
failing_test([], "at least one input must be given")
Expand Down

0 comments on commit b1ca531

Please sign in to comment.