Skip to content

Commit 3ee2798

Browse files
apt1002Alistair Turnbull
authored andcommitted
Replace function expand() with class Trees
1 parent 567e91e commit 3ee2798

File tree

1 file changed

+64
-44
lines changed

1 file changed

+64
-44
lines changed

nancy/__init__.py

Lines changed: 64 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -81,31 +81,40 @@ def parse_arguments(
8181
return args, next_index + 1
8282

8383

84-
def expand(
85-
inputs: list[Path], output_path: Path, build_path: Optional[Path] = Path()
86-
) -> None:
87-
"""Expand the input tree.
84+
class Trees:
85+
def __init__(
86+
self,
87+
inputs: list[Path],
88+
output_path: Path,
89+
build_path: Optional[Path]=None,
90+
):
91+
"""The state that is constant for a whole invocation of Nancy.
8892
89-
Args:
90-
inputs (list[Path]): a list of filesystem `Path`s to overlay to make
91-
an abstract input tree
92-
output_path (Path): the filesystem `Path` of the output directory
93-
build_path (Optional[Path]): the subtree of `inputs` to process.
94-
Defaults to the whole tree.
95-
"""
96-
if len(inputs) == 0:
97-
raise ValueError("at least one input must be given")
98-
if build_path is None:
99-
build_path = Path()
100-
if build_path.is_absolute():
101-
raise ValueError("build path must be relative")
102-
for root in inputs:
103-
if not root.exists():
104-
raise ValueError(f"input '{root}' does not exist")
105-
if not root.is_dir():
106-
raise ValueError(f"input '{root}' is not a directory")
107-
108-
def find_object(obj: Path) -> Optional[Union[Path, list[os.DirEntry[str]]]]:
93+
Args:
94+
inputs (list[Path]): a list of filesystem `Path`s to overlay to
95+
make an abstract input tree
96+
output_path (Path): the filesystem `Path` of the output directory
97+
build_path (Optional[Path]): the subtree of `inputs` to process.
98+
Defaults to the whole tree.
99+
"""
100+
if len(inputs) == 0:
101+
raise ValueError("at least one input must be given")
102+
for root in inputs:
103+
if not root.exists():
104+
raise ValueError(f"input '{root}' does not exist")
105+
if not root.is_dir():
106+
raise ValueError(f"input '{root}' is not a directory")
107+
self.inputs = inputs
108+
self.output_path = output_path
109+
if build_path is None:
110+
build_path = Path()
111+
if build_path.is_absolute():
112+
raise ValueError("build path must be relative")
113+
self.build_path = build_path
114+
115+
def find_object(
116+
self, obj: Path,
117+
) -> Optional[Union[Path, list[os.DirEntry[str]]]]:
109118
"""Find an object in the input tree.
110119
111120
Find the first file or directory with relative path `obj` in the
@@ -117,8 +126,8 @@ def find_object(obj: Path) -> Optional[Union[Path, list[os.DirEntry[str]]]]:
117126
If something neither a file nor directory is found, raise an error.
118127
If no result is found, return `None`.
119128
"""
120-
debug(f"find_object {obj} {inputs}")
121-
objects = [root / obj for root in inputs]
129+
debug(f"find_object {obj} {self.inputs}")
130+
objects = [root / obj for root in self.inputs]
122131
dirs = []
123132
debug(f"objects to consider: {objects}")
124133
for o in objects:
@@ -139,6 +148,7 @@ def find_object(obj: Path) -> Optional[Union[Path, list[os.DirEntry[str]]]]:
139148
return sorted(list(dirents.values()), key=lambda x: sorting_name(x.name))
140149

141150
def expand_bytes(
151+
self,
142152
text: bytes,
143153
base_file: Path,
144154
file_path: Path,
@@ -191,7 +201,7 @@ def find_on_path(start_path: Path, file: Path) -> Optional[Path]:
191201
norm_file = Path(os.path.normpath(file))
192202
for parent in (start_path / "_").parents:
193203
this_search = parent / norm_file
194-
obj = find_object(this_search)
204+
obj = self.find_object(this_search)
195205
if (
196206
obj is not None
197207
and not isinstance(obj, list)
@@ -404,7 +414,7 @@ def do_macro(
404414

405415
return inner_expand(text, [file_path])
406416

407-
def expand_file(base_file: Path, file_path: Path, output_file: Path) -> bytes:
417+
def expand_file(self, base_file: Path, file_path: Path, output_file: Path) -> bytes:
408418
"""Expand a file given its filesystem `Path`.
409419
410420
Args:
@@ -413,9 +423,9 @@ def expand_file(base_file: Path, file_path: Path, output_file: Path) -> bytes:
413423
output_file (Path): the filesystem output `Path`
414424
"""
415425
debug(f"expand_file {base_file} on path {file_path} to {output_file}")
416-
return expand_bytes(file_path.read_bytes(), base_file, file_path, output_file)
426+
return self.expand_bytes(file_path.read_bytes(), base_file, file_path, output_file)
417427

418-
def get_output_path(base_file: Path, file_path: Path) -> Path:
428+
def get_output_path(self, base_file: Path, file_path: Path) -> Path:
419429
"""Compute the output path of an input file.
420430
421431
Args:
@@ -425,29 +435,29 @@ def get_output_path(base_file: Path, file_path: Path) -> Path:
425435
Returns:
426436
Path
427437
"""
428-
relpath = base_file.relative_to(build_path)
438+
relpath = base_file.relative_to(self.build_path)
429439
output_file = relpath
430440
if output_file.name != "":
431441
output_file = output_file.with_name(
432442
os.fsdecode(re.sub(TEMPLATE_REGEX, "", relpath.name))
433443
)
434444
output_file = os.fsdecode(
435-
expand_bytes(bytes(output_file), output_file, file_path)
445+
self.expand_bytes(bytes(output_file), output_file, file_path)
436446
)
437-
return output_path / output_file
447+
return self.output_path / output_file
438448

439-
def process_file(base_file: Path, file_path: Path) -> None:
449+
def process_file(self, base_file: Path, file_path: Path) -> None:
440450
"""Expand, copy or ignore a single file.
441451
442452
Args:
443453
base_file (Path): the filesystem `Path`
444454
file_path (Path): the `inputs`-relative `Path`
445455
"""
446-
output_file = get_output_path(base_file, file_path)
456+
output_file = self.get_output_path(base_file, file_path)
447457
debug(f"Processing file '{file_path}'")
448458
if re.search(TEMPLATE_REGEX, file_path.name):
449459
debug(f"Expanding '{base_file}' to '{output_file}'")
450-
output = expand_file(base_file, file_path, output_file)
460+
output = self.expand_file(base_file, file_path, output_file)
451461
if not re.search(NO_COPY_REGEX, str(output_file)):
452462
if output_file == Path("-"):
453463
sys.stdout.buffer.write(output)
@@ -461,13 +471,13 @@ def process_file(base_file: Path, file_path: Path) -> None:
461471
else:
462472
shutil.copyfile(file_path, output_file)
463473

464-
def process_path(obj: Path) -> None:
474+
def process_path(self, obj: Path) -> None:
465475
"""Recursively scan `obj` and pass every file to `process_file`."""
466-
dirent = find_object(obj)
476+
dirent = self.find_object(obj)
467477
if dirent is None:
468478
raise ValueError(f"'{obj}' matches no path in the inputs")
469479
if isinstance(dirent, list):
470-
output_dir = get_output_path(obj, obj)
480+
output_dir = self.get_output_path(obj, obj)
471481
if output_dir == Path("-"):
472482
raise ValueError("cannot output multiple files to stdout ('-')")
473483
debug(f"Entering directory '{obj}'")
@@ -476,13 +486,18 @@ def process_path(obj: Path) -> None:
476486
if child_dirent.name[0] != ".":
477487
child_object = obj / child_dirent.name
478488
if child_dirent.is_file():
479-
process_file(child_object, Path(child_dirent.path))
489+
self.process_file(child_object, Path(child_dirent.path))
480490
else:
481-
process_path(child_object)
491+
self.process_path(child_object)
482492
else:
483-
process_file(obj, dirent)
493+
self.process_file(obj, dirent)
494+
484495

485-
process_path(build_path)
496+
# TODO: Inline into callers, and remove.
497+
def expand(
498+
inputs: list[Path], output_path: Path, build_path: Optional[Path] = Path()
499+
) -> None:
500+
Trees(inputs, output_path, build_path).process_path(build_path)
486501

487502

488503
def main(argv: list[str] = sys.argv[1:]) -> None:
@@ -531,7 +546,12 @@ def main(argv: list[str] = sys.argv[1:]) -> None:
531546
args.path = inputs[0]
532547
inputs[0] = Path.cwd()
533548

534-
expand(inputs, Path(args.output), Path(args.path) if args.path else None)
549+
trees = Trees(
550+
inputs,
551+
Path(args.output),
552+
Path(args.path) if args.path else None,
553+
)
554+
trees.process_path(trees.build_path)
535555
except Exception as err:
536556
if "DEBUG" in os.environ:
537557
logging.error(err, exc_info=True)

0 commit comments

Comments
 (0)