def save_files(folder: Filepath, file_data: Dict[Filepath, str]) -> bool: """Save all `file_data` under `folder`. All paths in `file_data` are relative to `folder`. Inputs: folder: Filepath file_data: Dict[Filepath, str] The file name (relative to `folder`) and its content. Returns: None """ # Python's `pathlib.Path` objects are simply nicer to work with... folder = pathlib.Path(folder) # Delete all YAML files under `folder`. This avoids stale manifests. try: for fp in folder.rglob("*.yaml"): logit.info(f"Removing stale <{fp}>") fp.unlink() except (IOError, PermissionError) as err: logit.error(f"{err}") return True # Iterate over the dict and write each file. Abort on error. for fname, yaml_str in file_data.items(): # Skip the file if its content would be empty. if yaml_str == '': continue # Construct absolute file path. fname_abs = folder / fname logit.debug(f"Creating path for <{fname}>") # Create the parent directories and write the file. Abort on error. logit.info(f"Saving YAML file <{fname_abs}>") try: fname_abs.parent.mkdir(parents=True, exist_ok=True) fname_abs.write_text(yaml_str) except (IOError, PermissionError) as err: logit.error(f"{err}") return True # Tell caller that all files were successfully written. return False
def load( folder: Filepath, selectors: Selectors ) -> Tuple[ServerManifests, LocalManifestLists, bool]: """Recursively load all "*.yaml" files under `folder`. Ignores all files not ending in ".yaml". Also removes all manifests that do not match the `selectors`. Returns no data in the case of an error. NOTE: this is merely a wrapper around the various low-level functions to load and parse the YAML files. Input: folder: Filepath Source folder. selectors: Selectors Returns: (local manifest without file info, local manifests with file info) """ # Python's `pathlib.Path` objects are simply nicer to work with... folder = pathlib.Path(folder) # Compile the list of all YAML files in `folder` but only store their path # relative to `folder`. fnames = [(_.relative_to(folder), _.name) for _ in folder.rglob("*.yaml")] fnames = [path for path, name in fnames if not name.startswith(".")] try: # Load the files and abort on error. fdata_raw, err = load_files(folder, fnames) assert not err and fdata_raw is not None # Return the YAML parsed manifests. man_files, err = parse(fdata_raw, selectors) assert not err and man_files is not None # Remove the Filepath dimension. man_meta, err = unpack(man_files) assert not err and man_meta is not None except AssertionError: return ({}, {}, True) # Return the file based manifests and unpacked manifests. return (man_meta, man_files, False)