@@ -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