python / python/cpython

importlib.resources regression for custom ResourceReader

Đang mở
#127,337 3 bình luận 0 reaction 1 người được giao Xem trên GitHub

@FFY00 đang làm issue này rồi.

Từ ngày 1/12/2024.

3.13 3.14 stdlib topic-importlib
Ngôn ngữ chính
Python
Star
77.2k
Fork
35.9k
Chỉ số merge pull request
Chỉ số pull request đang chờ

Mô tả

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

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.