"""Utility functions for file input/output."""from__future__importannotationsimportloggingimportosimportrefrompathlibimportPath__all__:list[str]=["find_file_upstream"]logger=logging.getLogger(__name__)
[docs]deffind_file_upstream(sub_directory:str|os.PathLike[str],pattern:str|None,regex:str|None=None,top_directory:str|os.PathLike[str]|None=None,)->Path|None:""" Search for first upstream parent of sub_directory that contains pattern. Return first pattern found. Return None if no pattern has been found when parent equals directory. Parameters ---------- sub_directory : Directory or file path to start with. pattern : glob pattern passed to :func:`Path.glob` regex : regex pattern passed to :func:`re.search` and applied in addition to glob pattern top_directory : Directory in which to stop the search. Returns ------- Path | None """sub_directory=Path(sub_directory).resolve(strict=True)ifpatternisNone:pattern="*.*"iftop_directoryisNone:top_directory=sub_directory.anchorifregexisnotNone:regex_=re.compile(regex)else:regex_=Noneforparentinsub_directory.parents:file_list=list(parent.glob(pattern))ifregex_isnotNone:file_list=[file_forfile_infile_listifregex_.search(str(file_))isnotNone]iffile_list:returnfile_list[0]ifparent==top_directory:returnNonereturnNone