-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Add stubs for importlib.(resources.)readers
#10928
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
02d1537
8911bd4
8232196
fb4b603
8678928
05a9272
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,61 @@ | ||||||
# On py311+, things are actually defined in importlib.resources.readers, | ||||||
# and re-exported here, | ||||||
# but doing it this way leads to less code duplication for us | ||||||
|
||||||
import pathlib | ||||||
import sys | ||||||
from _typeshed import Incomplete, StrPath | ||||||
from collections.abc import Iterable, Iterator | ||||||
from io import BufferedReader | ||||||
from typing import NoReturn, TypeVar | ||||||
from typing_extensions import Literal, Never | ||||||
|
||||||
if sys.version_info >= (3, 11): | ||||||
import importlib.resources.abc as abc | ||||||
else: | ||||||
import importlib.abc as abc | ||||||
|
||||||
if sys.version_info >= (3, 10): | ||||||
if sys.version_info >= (3, 11): | ||||||
__all__ = ["FileReader", "ZipReader", "MultiplexedPath", "NamespaceReader"] | ||||||
|
||||||
if sys.version_info < (3, 11): | ||||||
_T = TypeVar("_T") | ||||||
|
||||||
def remove_duplicates(items: Iterable[_T]) -> Iterator[_T]: ... | ||||||
|
||||||
class FileReader(abc.TraversableResources): | ||||||
path: pathlib.Path | ||||||
def __init__(self, loader) -> None: ... | ||||||
def resource_path(self, resource: StrPath) -> str: ... | ||||||
def files(self) -> pathlib.Path: ... | ||||||
|
||||||
class ZipReader(abc.TraversableResources): | ||||||
prefix: str | ||||||
archive: Incomplete | ||||||
def __init__(self, loader, module: str) -> None: ... | ||||||
def open_resource(self, resource: str) -> BufferedReader: ... | ||||||
def is_resource(self, path: StrPath) -> bool: ... | ||||||
def files(self): ... | ||||||
|
||||||
class MultiplexedPath(abc.Traversable): | ||||||
def __init__(self, *paths: abc.Traversable) -> None: ... | ||||||
def iterdir(self) -> Iterator[abc.Traversable]: ... | ||||||
def read_bytes(self) -> NoReturn: ... | ||||||
def read_text(self, *args: Never, **kwargs: Never) -> NoReturn: ... # type: ignore[override] | ||||||
def is_dir(self) -> Literal[True]: ... | ||||||
def is_file(self) -> Literal[False]: ... | ||||||
if sys.version_info >= (3, 12): | ||||||
def joinpath(self, *descendants: str) -> abc.Traversable: ... | ||||||
else: | ||||||
def joinpath(self, child: str) -> abc.Traversable: ... # type: ignore[override] | ||||||
__truediv__ = joinpath | ||||||
def open(self, *args: Never, **kwargs: Never) -> NoReturn: ... # type: ignore[override] | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that was a deliberate choice... I thought maybe it would be useful for type checkers to warn you if you provided arguments to this function. Since it always fails at runtime, it seems like you're probably making a mistake if you're passing arguments to it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But that should already be caught by the trav_open: SignatureOf[Traversible.open] = MultiplexedPath.open I wonder why no type checker complains about using That said, I don't feel strongly about this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If we only have the I'll concede that this is a bit of a hack, and that we're really working around the lack of something like python/typing#1043 -- but I think it's useful for the time being |
||||||
@property | ||||||
def name(self) -> str: ... | ||||||
|
||||||
class NamespaceReader(abc.TraversableResources): | ||||||
path: MultiplexedPath | ||||||
def __init__(self, namespace_path) -> None: ... | ||||||
def resource_path(self, resource: str) -> str: ... | ||||||
def files(self) -> MultiplexedPath: ... |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# On py311+, things are actually defined here | ||
# and re-exported from importlib.readers, | ||
# but doing it this way leads to less code duplication for us | ||
|
||
import sys | ||
from collections.abc import Iterable, Iterator | ||
from typing import TypeVar | ||
|
||
if sys.version_info >= (3, 11): | ||
from importlib.readers import * | ||
|
||
_T = TypeVar("_T") | ||
|
||
def remove_duplicates(items: Iterable[_T]) -> Iterator[_T]: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This obviously returns a
zipfile.Path
at runtime. Unfortunately, if you add that annotation right now, mypy complains:This points to an error either in our zipfile stubs or in our
importlib.(resources.)abc
stubs. Type checkers should probably understandzipfile.Path
as being a subtype ofTraversable
; I believe that's the intention of the authors of these modules.Anyway, that looks non-trivial to fix, so I'd rather defer it to another PR for now.