Skip to content

Commit 75a8d03

Browse files
committed
Fix infinite expansion check to ignore executables
An executable may be used more than once during a nested expansion.
1 parent 152f946 commit 75a8d03

File tree

1 file changed

+17
-6
lines changed

1 file changed

+17
-6
lines changed

nancy/__init__.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,23 @@ def get_file(leaf: Path) -> Path:
126126
debug(f"Found '{file_or_exec}'")
127127
return file_or_exec
128128

129-
def read_file(file: Path, args: list[str]) -> str:
129+
# Read or run file and return the output, with either the
130+
# file if it was read, so as to exclude it from recursive
131+
# expansion, or `None` if the file was an executable, as
132+
# executables may be used repeatedly in a nested expansion.
133+
def read_file(
134+
file: Path, args: list[str]
135+
) -> tuple[Optional[Path], str]:
130136
if is_executable(file):
131137
debug(f"Running {file} {' '.join(args)}")
132-
output = subprocess.check_output([file.resolve(strict=True)] + args, text=True)
138+
output = subprocess.check_output(
139+
[file.resolve(strict=True)] + args, text=True
140+
)
141+
return (None, output)
133142
else:
134143
with open(file, encoding="utf-8") as fh:
135144
output = fh.read()
136-
return output
145+
return (file, output)
137146

138147
# Set up macros
139148
macros: dict[str, Callable[..., str]] = {}
@@ -145,19 +154,21 @@ def read_file(file: Path, args: list[str]) -> str:
145154

146155
def get_included_file(
147156
command_name: str, args: list[str]
148-
) -> tuple[Path, str]:
157+
) -> tuple[Optional[Path], str]:
149158
debug(f"${command_name}{{{','.join(args)}}}")
150159
if len(args) < 1:
151160
raise ValueError(
152161
f"${command_name} expects at least one argument"
153162
)
154163
file = get_file(Path(args[0]))
155-
return file, read_file(file, args[1:])
164+
return read_file(file, args[1:])
156165

157166
def include(args: list[str]) -> str:
158167
file, contents = get_included_file("include", args)
159168
return strip_final_newline(
160-
inner_expand(contents, expand_stack + [file])
169+
inner_expand(
170+
contents, expand_stack + [file] if file is not None else []
171+
)
161172
)
162173

163174
macros["include"] = include

0 commit comments

Comments
 (0)