Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

importlib.abc.Traversable.read_text() incompatible withimportlib.resources._functional.read_text() usage (Python 3.13) #127012

Open
python/importlib_resources
#321
Assignees
kurtmckeejaraco
Labels
stdlibPython modules in the Lib dirtopic-importlibtype-bugAn unexpected behavior, bug, or error
@kurtmckee

Description

@kurtmckee

Bug report

Bug description:

I'm writing a custom importer and discovered that the function signature forimportlib.abc.Traversable.read_text() is incompatible with the usage inimportlib.resources._functional.read_text(), specifically on Python 3.13.

  1. importlib.abc.Traversable.read_text() is a concrete method; its implementation calls the.open() method, which is an abstract method that must be implemented. The expectation is therefore that implementing.open() in a Traversable subclass is sufficient for.read_text() to work.

    Note below that the.read_text() method is not marked as abstract, and includes only one parameter:encoding:

    defread_text(self,encoding:Optional[str]=None)->str:
    """
    Read contents of self as text
    """
    withself.open(encoding=encoding)asstrm:
    returnstrm.read()

  2. Application code that attempts to read a package resource, likeimportlib.resources.read_text(module, "resource.txt") ultimately leads to a call toimportlib.resources._functional.read_text(), which attempts to call the.read_text() method of a Traversable subclass, but includes anerrors parameter that doesn't exist in Traversable's default concrete method:

    defread_text(anchor,*path_names,encoding=_MISSING,errors='strict'):
    """Read and return contents of *resource* within *package* as str."""
    encoding=_get_encoding_arg(path_names,encoding)
    resource=_get_resource(anchor,path_names)
    returnresource.read_text(encoding=encoding,errors=errors)

  3. Consequently, it appears to be necessary for all Traversable subclasses to not only re-implement its concrete.read_text() method, but also to override its signature.

I think that the Traversable.read_text() method signature, and the call site inimportlib.resources._functional.read_text(), need to align with each other.

I'd like to submit a PR for this! However, I would like confirmation that anerrors parameter should be added to theTraversable.read_text() method.

Note that adding anerrors parameter was previously discussed in#88368.

Demonstration of TypeError bug

importioimportsysimporttypingimportpathlibimporttypesimportimportlib.abcimportimportlib.machineryimportimportlib.metadataimportimportlib.resources.abcclassExampleFinder(importlib.abc.MetaPathFinder):deffind_spec(self,fullname:str,path:typing.Sequence[str]|None,target:types.ModuleType|None=None,    )->importlib.machinery.ModuleSpec|None:iffullname!="demonstrate_error":returnNoneprint(f"ExampleFinder.find_spec('{fullname}')")spec=importlib.machinery.ModuleSpec(name=fullname,loader=ExampleLoader(),is_package=True,        )returnspecsys.meta_path.append(ExampleFinder())classExampleLoader(importlib.abc.Loader):defexec_module(self,module:types.ModuleType)->None:print(f"ExampleLoader.exec_module({module})")exec("",module.__dict__)defget_resource_reader(self,fullname:str)->"ExampleTraversableResources":print(f"ExampleLoader.get_resource_reader('{fullname}')")returnExampleTraversableResources(fullname)classExampleTraversableResources(importlib.resources.abc.TraversableResources):def__init__(self,fullname:str)->None:self.fullname=fullnamedeffiles(self)->"ExampleTraversable":print("ExampleTraversableResources.files()")returnExampleTraversable(self.fullname)# ----------------------------------------------------------------------------# ExampleTraversable implements all five of the Traversable abstract methods.# Specifically, it is expected that implementing `.open()` will be sufficient,# but this will not be the case.#classExampleTraversable(importlib.resources.abc.Traversable):def__init__(self,path:str):self._path=pathdefiterdir(self)->typing.Iterator["ExampleTraversable"]:yieldExampleTraversable("resource.txt")defis_dir(self)->bool:returnFalsedefis_file(self)->bool:returnTruedefopen(self,mode='r',*args,**kwargs)->typing.IO[typing.AnyStr]:returnio.StringIO("Nice! The call to .read_text() succeeded!")# Uncomment this `.read_text()` method to make `.read_text()` calls work.# It overrides the `Traversable.read_text()` signature.## def read_text(self, encoding: str | None, errors: str | None) -> str:#     print(f"ExampleTraversable.read_text('{encoding}', '{errors}')")#     return str(super().read_text(encoding))@propertydefname(self)->str:returnpathlib.PurePosixPath(self._path).name# -------------------------------------------------------------------------------# Everything above allows us to import this hard-coded module# and demonstrate a TypeError lurking in the Traversable.read_text() signature.#importdemonstrate_error# The next line will raise a TypeError.# `importlib/resources/_functional.py:read_text()` calls `Traversable.read_text()`# with an `errors` argument that is not supported by the default concrete method.print(importlib.resources.read_text(demonstrate_error,"resource.txt"))

CPython versions tested on:

3.13

Operating systems tested on:

Linux

Metadata

Metadata

Labels

stdlibPython modules in the Lib dirtopic-importlibtype-bugAn unexpected behavior, bug, or error

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions


    [8]ページ先頭

    ©2009-2025 Movatter.jp