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