diff --git a/importlib_resources/future/adapters.py b/importlib_resources/future/adapters.py index 56dea7c..9aa5b5e 100644 --- a/importlib_resources/future/adapters.py +++ b/importlib_resources/future/adapters.py @@ -1,3 +1,4 @@ +import functools import pathlib from contextlib import suppress from types import SimpleNamespace @@ -5,6 +6,39 @@ from .. import readers, _adapters +def _block_standard(reader_getter): + """ + Wrap _adapters.TraversableResourcesLoader.get_resource_reader + and intercept any standard library readers. + """ + + @functools.wraps(reader_getter) + def wrapper(*args, **kwargs): + """ + If the reader is from the standard library, return None to allow + allow likely newer implementations in this library to take precedence. + """ + try: + reader = reader_getter(*args, **kwargs) + except NotADirectoryError: + # MultiplexedPath may fail on zip subdirectory + return + # Python 3.10+ + if reader.__class__.__module__.startswith('importlib.resources.'): + return + # Python 3.8, 3.9 + if isinstance(reader, _adapters.CompatibilityFiles) and ( + reader.spec.loader.__class__.__module__.startswith('zipimport') + or reader.spec.loader.__class__.__module__.startswith( + '_frozen_importlib_external' + ) + ): + return + return reader + + return wrapper + + class TraversableResourcesLoader(_adapters.TraversableResourcesLoader): """ Adapt loaders to provide TraversableResources and other @@ -15,7 +49,10 @@ class TraversableResourcesLoader(_adapters.TraversableResourcesLoader): """ def get_resource_reader(self, name): - return self._standard_reader() or super().get_resource_reader(name) + return ( + _block_standard(super().get_resource_reader)(name) + or self._standard_reader() + ) def _standard_reader(self): return self._zip_reader() or self._namespace_reader() or self._file_reader() diff --git a/newsfragments/295.feature.rst b/newsfragments/295.feature.rst new file mode 100644 index 0000000..3d74253 --- /dev/null +++ b/newsfragments/295.feature.rst @@ -0,0 +1 @@ +Future compatibility adapters now ensure that standard library readers are replaced without overriding non-standard readers.