python / python/cpython

importlib.resources regression for custom ResourceReader

Aberta
#127,337 3 comentários 0 reações 1 responsável Ver no GitHub

@FFY00 já está trabalhando nisso.

Desde 1/12/2024.

3.13 3.14 stdlib topic-importlib
Linguagem predominante
Python
Estrelas
77.2k
Forks
36k
Métricas de merge de PRs
Métricas de PR pendentes

Descrição

Since Python 3.13 (including 3.14), my custom ResourceReader is now raising errors when used with importlib.resources.contents. This code is otherwise functioning fine from 3.8 onwards.

Traceback (most recent call last):
  File "D:\cpython\t.py", line 41, in <module>
    print(contents(FakeModule))
          ~~~~~~~~^^^^^^^^^^^^
  File "D:\cpython\Lib\importlib\resources\_functional.py", line 60, in contents
    return (resource.name for resource in _get_resource(anchor, path_names).iterdir())
                                          ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
  File "D:\cpython\Lib\importlib\resources\_functional.py", line 81, in _get_resource
    return files(anchor).joinpath(*path_names)
           ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
TypeError: CompatibilityFiles.SpecPath.joinpath() missing 1 required positional argument: 'other'

Self-contained repro below (the real one gets compiled into DLLs, so you don't want to try to debug it ;) ):

from importlib.abc import Loader
from importlib.machinery import ModuleSpec
from importlib.resources.abc import ResourceReader

_DATA = {"FakeModule.NAME": b"hello"}
_DATA_NAMES = set(_DATA)

class MyReader(ResourceReader):
    def __init__(self, prefix):
        self.prefix = prefix

    def open_resource(self, resource):
        import io
        return io.BytesIO(_DATA[self.prefix + resource])

    def resource_path(self, resource):
        raise FileNotFoundError()

    def is_resource(self, resource):
        return self.prefix + resource in _DATA_NAMES

    def contents(self):
        p = self.prefix
        lp = len(p)
        return (n[lp:] for n in _DATA_NAMES if n.startswith(p))

class MyLoader(Loader):
    create_module = ...
    exec_module = ...

    def get_resource_reader(self, fullname):
        return MyReader(fullname + ".")

class FakeModule:
    __loader__ = MyLoader()
    __name__ = "FakeModule"
    __spec__ = ModuleSpec(__name__, __loader__)

from importlib.resources import contents
print(contents(FakeModule))

(ping @jaraco)

Linked PRs
  • gh-154919

Guia de contribuição

Abrir o guia de contribuição

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Avaliação

Esta issue ainda não foi avaliada.

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.