[docs]deffiles(package):# type: (Package) -> Traversable""" Get a Traversable resource from a package """returnfrom_package(get_package(package))
defnormalize_path(path):# type: (Any) -> str"""Normalize a path by ensuring it is a string. If the resulting string contains path separators, an exception is raised. """str_path=str(path)parent,file_name=os.path.split(str_path)ifparent:raiseValueError(f'{path!r} must be only a file name')returnfile_namedefget_resource_reader(package):# type: (types.ModuleType) -> Optional[ResourceReader]""" Return the package's loader if it's a ResourceReader. """# We can't use# a issubclass() check here because apparently abc.'s __subclasscheck__()# hook wants to create a weak reference to the object, but# zipimport.zipimporter does not support weak references, resulting in a# TypeError. That seems terrible.spec=package.__spec__reader=getattr(spec.loader,'get_resource_reader',None)# type: ignoreifreaderisNone:returnNonereturnreader(spec.name)# type: ignoredefresolve(cand):# type: (Package) -> types.ModuleTypereturncandifisinstance(cand,types.ModuleType)elseimportlib.import_module(cand)defget_package(package):# type: (Package) -> types.ModuleType"""Take a package name or module object and return the module. Raise an exception if the resolved module is not a package. """resolved=resolve(package)ifwrap_spec(resolved).submodule_search_locationsisNone:raiseTypeError(f'{package!r} is not a package')returnresolveddeffrom_package(package):""" Return a Traversable object for the given package. """spec=wrap_spec(package)reader=spec.loader.get_resource_reader(spec.name)returnreader.files()@contextlib.contextmanagerdef_tempfile(reader,suffix='',# gh-93353: Keep a reference to call os.remove() in late Python# finalization.*,_os_remove=os.remove):# Not using tempfile.NamedTemporaryFile as it leads to deeper 'try'# blocks due to the need to close the temporary file to work on Windows# properly.fd,raw_path=tempfile.mkstemp(suffix=suffix)try:os.write(fd,reader())os.close(fd)delreaderyieldpathlib.Path(raw_path)finally:try:_os_remove(raw_path)exceptFileNotFoundError:pass@functools.singledispatchdefas_file(path):""" Given a Traversable object, return that object as a path on the local file system in a context manager. """return_tempfile(path.read_bytes,suffix=path.name)@as_file.register(pathlib.Path)@contextlib.contextmanagerdef_(path):""" Degenerate behavior for pathlib.Path objects. """yieldpath