Description
Hello friends,
I'm looking at how to reimplement resource overrides in Pyramid. It's a unique feature that in the past involved patching a custom package.__loader__
which could intercept and do its own file lookups for various requests. This worked with all pkg_resources apis, like pkg_resources.resource_filename
, etc to return a different path than the one physically on disk when a path is overridden.
To implement this, I've been going through the PEPs and trying to understand the protocol that importlib.resources
uses to support overriding how resources are loaded from a package. I've narrowed this down to spec.loader.get_resource_reader()
being able to be defined. My plan will be to define a ProxyLoader
which defines its own get_resource_reader
but proxies the rest of the loader functionality back to the original loader. So, I'm looking at how to define a custom abc.TraversableResources
class that does what I need, and then hook package.__spec__.loader
to return it from get_resource_reader()
.
From what I can tell, the logic here is inconsistent between importlib_resources and the stdlib impl in CPython. I'm looking here:
compared to
importlib_resources/importlib_resources/_compat.py
Lines 75 to 90 in 7d8b020
In both cases, TraversableResourceLoader is attempting to determine which reader to return. In the stdlib, preference is given to the native spec.loader.get_resource_reader()
if the reader returned has a files()
method. However, importlib_resources inverts the lookup such that zip/namespace/file take priority over the "native" reader. So for example, if self.path
exists, then whatever I set as spec.loader.get_resource_reader()
will never be invoked and hence I can't override the lookups.
Currently, to get this to work with importlib_resources, it appears that I would need the spec.path
to be a non-existent path, which would trigger the logic to fallback to the native reader that I patch, but this is by far not ideal.
The TLDR is that I would propose importlib_resources moves the _native_reader(self.spec)
invocation to the TOP of the list, which would be more in line with the stdlib.
I would really appreciate any guidance here. Maybe I'm completely off base and missing something critical in the importlib machinery, and happy to talk more about this use-case in Pyramid that has been supported for many years via a PEP320 loader used by pkg_resources. Thank you!