Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/python/typeshed into pkg_re…
Browse files Browse the repository at this point in the history
…sources-remove-_Importer
  • Loading branch information
Avasam committed Feb 29, 2024
2 parents ed67106 + e050986 commit 8fb9cd1
Show file tree
Hide file tree
Showing 68 changed files with 810 additions and 362 deletions.
10 changes: 5 additions & 5 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Since typeshed stubs them, they can still be expected to be found in a
# developer's venv for intellisense and reference reasons
# A flake8-builtins
# B flake8-bugbear
# D flake8-docstrings
# N8 pep8-naming
# SIM flake8-simplify
Expand All @@ -17,7 +18,6 @@
# E701 Multiple statements on one line (colon) -- disallows "..." on the same line

# Some rules are considered irrelevant to stub files:
# B All flake8-bugbear rules are .py-specific
# F401 imported but unused -- does not recognize re-exports
# https://github.com/PyCQA/pyflakes/issues/474

Expand All @@ -27,18 +27,18 @@
# F405 defined from star imports

[flake8]
extend-ignore = A, D, N8, SIM, RST, TYP, E301, E302, E305, E501, E701
extend-ignore = A, B, D, N8, SIM, RST, TYP, E301, E302, E305, E501, E701
per-file-ignores =
*.py: E203
*.pyi: B, E741, F401, F403, F405
*.pyi: E741, F401, F403, F405
# Since typing.pyi defines "overload" this is not recognized by Flake8 as typing.overload.
# Unfortunately, Flake8 does not allow to "noqa" just a specific error inside the file itself.
# https://github.com/PyCQA/flake8/issues/1079
# F811 redefinition of unused '...'
stdlib/typing.pyi: B, E741, F401, F403, F405, F811
stdlib/typing.pyi: E741, F401, F403, F405, F811
# Generated protobuf files include docstrings,
# and import some things from typing_extensions that could be imported from typing
*_pb2.pyi: B, E741, F401, F403, F405, Y021, Y023, Y026, Y053, Y054
*_pb2.pyi: E741, F401, F403, F405, Y021, Y023, Y026, Y053, Y054

exclude = .venv*,.git
noqa_require_code = true
6 changes: 3 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -163,22 +163,22 @@ jobs:
version: ${{ steps.pyright_version.outputs.value }}
python-platform: ${{ matrix.python-platform }}
python-version: ${{ matrix.python-version }}
no-comments: ${{ matrix.python-version != '3.11' || matrix.python-platform != 'Linux' }} # Having each job create the same comment is too noisy.
annotate: ${{ matrix.python-version == '3.11' && matrix.python-platform == 'Linux' }} # Having each job create the same comment is too noisy.
- name: Run pyright with stricter settings on some of the stubs
uses: jakebailey/pyright-action@v2
with:
version: ${{ steps.pyright_version.outputs.value }}
python-platform: ${{ matrix.python-platform }}
python-version: ${{ matrix.python-version }}
no-comments: ${{ matrix.python-version != '3.11' || matrix.python-platform != 'Linux' }} # Having each job create the same comment is too noisy.
annotate: ${{ matrix.python-version == '3.11' && matrix.python-platform == 'Linux' }} # Having each job create the same comment is too noisy.
project: ./pyrightconfig.stricter.json
- name: Run pyright on the test cases
uses: jakebailey/pyright-action@v2
with:
version: ${{ steps.pyright_version.outputs.value }}
python-platform: ${{ matrix.python-platform }}
python-version: ${{ matrix.python-version }}
no-comments: ${{ matrix.python-version != '3.11' || matrix.python-platform != 'Linux' }} # Having each job create the same comment is too noisy.
annotate: ${{ matrix.python-version == '3.11' && matrix.python-platform == 'Linux' }} # Having each job create the same comment is too noisy.
project: ./pyrightconfig.testcases.json

stub-uploader:
Expand Down
1 change: 0 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ repos:
hooks:
- id: flake8
additional_dependencies:
- "flake8-bugbear==24.1.17" # must match requirements-tests.txt
- "flake8-noqa==1.4.0" # must match requirements-tests.txt
- "flake8-pyi==24.1.0" # must match requirements-tests.txt
types: [file]
Expand Down
1 change: 0 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ you're free to do so. Either run the following manually...

Our code is also linted using [`Flake8`](https://github.com/pycqa/flake8),
with plugins [`flake8-pyi`](https://github.com/pycqa/flake8-pyi),
[`flake8-bugbear`](https://github.com/PyCQA/flake8-bugbear),
and [`flake8-noqa`](https://github.com/plinss/flake8-noqa).
As with our other checks, running
Flake8 before filing a PR is not required. However, if you wish to run Flake8
Expand Down
32 changes: 23 additions & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ exclude = [

[tool.ruff.lint]
select = [
"B", # flake8-bugbear
"FA", # flake8-future-annotations
"I", # isort
"UP", # pyupgrade
# Only enable rules that have safe autofixes:
"F401", # Remove unused imports
"PYI009", # use `...`, not `pass`, in empty class bodies
Expand All @@ -39,14 +41,26 @@ select = [
"PYI032", # use `object`, not `Any`, as the second parameter to `__eq__`
"PYI055", # multiple `type[T]` usages in a union
"PYI058", # use `Iterator` as the return type for `__iter__` methods
"UP004", # Remove explicit `object` inheritance
"UP006", # PEP-585 autofixes
"UP007", # PEP-604 autofixes
"UP013", # Class-based syntax for TypedDicts
"UP014", # Class-based syntax for NamedTuples
"UP019", # Use str over typing.Text
"UP035", # import from typing, not typing_extensions, wherever possible
"UP039", # don't use parens after a class definition with no bases
]
ignore = [
# Slower and more verbose https://github.com/astral-sh/ruff/issues/7871
"UP038", # Use `X | Y` in `isinstance` call instead of `(X, Y)`
]

[tool.ruff.lint.per-file-ignores]
# Disable "modernization" rules with autofixes from test cases as they often
# deliberately contain code that might not be considered idiomatic or modern
# These can be run manually once in a while
"**/test_cases/**/*.py" = ["UP"]
"*.pyi" = [
# Most flake8-bugbear rules don't apply for third-party stubs like typeshed,
# B033 could be slightly useful but Ruff doesn't have per-file select
"B", # flake8-bugbear
]
# Generated protobuf files:
# TODO: Re-run sync_tensorflow_protobuf_stubs.sh with this rule enabled to remove this entry
"*_pb2.pyi" = [
"UP036", # Version block is outdated for minimum Python version
]

[tool.ruff.lint.isort]
Expand Down Expand Up @@ -100,5 +114,5 @@ extra-standard-library = [
known-first-party = ["parse_metadata", "utils"]

[tool.typeshed]
pyright_version = "1.1.342"
pyright_version = "1.1.350"
oldest_supported_python = "3.8"
1 change: 0 additions & 1 deletion pyrightconfig.stricter.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@
"stubs/tqdm",
"stubs/ttkthemes",
"stubs/vobject",
"stubs/WebOb",
"stubs/workalendar",
],
"typeCheckingMode": "strict",
Expand Down
2 changes: 1 addition & 1 deletion pyrightconfig.testcases.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// See https://github.com/python/typeshed/pull/8083
"enableTypeIgnoreComments": true,
// If a test case uses this anti-pattern, there's likely a reason and annoying to `type: ignore`.
// Let flake8-bugbear flag it (B006)
// Let Ruff flag it (B006)
"reportCallInDefaultInitializer": "none",
// Too strict and not needed for type testing
"reportMissingSuperCall": "none",
Expand Down
1 change: 0 additions & 1 deletion requirements-tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
# "tool.typeshed" section in pyproject.toml for additional type checkers.
black==24.1.1 # must match .pre-commit-config.yaml
flake8==7.0.0 # must match .pre-commit-config.yaml
flake8-bugbear==24.1.17 # must match .pre-commit-config.yaml
flake8-noqa==1.4.0 # must match .pre-commit-config.yaml
flake8-pyi==24.1.0 # must match .pre-commit-config.yaml
mypy==1.8.0
Expand Down
4 changes: 2 additions & 2 deletions scripts/runtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from typing import Any

try:
from termcolor import colored # pyright: ignore[reportGeneralTypeIssues]
from termcolor import colored # pyright: ignore[reportAssignmentType]
except ImportError:

def colored(text: str, color: str | None = None, **kwargs: Any) -> str: # type: ignore[misc]
Expand Down Expand Up @@ -101,7 +101,7 @@ def main() -> None:
strict_params = _get_strict_params(path)
print(f"\nRunning Pyright ({'stricter' if strict_params else 'base' } configs) for Python {python_version}...")
pyright_result = subprocess.run(
[sys.executable, "tests/pyright_test.py", path, "--pythonversion", python_version] + strict_params,
[sys.executable, "tests/pyright_test.py", path, "--pythonversion", python_version, *strict_params],
stderr=subprocess.PIPE,
text=True,
)
Expand Down
4 changes: 2 additions & 2 deletions scripts/stubsabot.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def from_cmd_arg(cls, cmd_arg: str) -> ActionLevel:
try:
return cls[cmd_arg]
except KeyError:
raise argparse.ArgumentTypeError(f'Argument must be one of "{list(cls.__members__)}"')
raise argparse.ArgumentTypeError(f'Argument must be one of "{list(cls.__members__)}"') from None

nothing = 0, "make no changes"
local = 1, "make changes that affect local repo"
Expand Down Expand Up @@ -516,7 +516,7 @@ async def determine_action(stub_path: Path, session: aiohttp.ClientSession) -> U
)


@functools.lru_cache()
@functools.lru_cache
def get_origin_owner() -> str:
output = subprocess.check_output(["git", "remote", "get-url", "origin"], text=True).strip()
match = re.match(r"([email protected]:|https://github.com/)(?P<owner>[^/]+)/(?P<repo>[^/\s]+)", output)
Expand Down
12 changes: 6 additions & 6 deletions stdlib/_operator.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,16 @@ def length_hint(__obj: object, __default: int = 0) -> int: ...
@final
class attrgetter(Generic[_T_co]):
@overload
def __new__(cls, attr: str) -> attrgetter[Any]: ...
def __new__(cls, attr: str, /) -> attrgetter[Any]: ...
@overload
def __new__(cls, attr: str, __attr2: str) -> attrgetter[tuple[Any, Any]]: ...
def __new__(cls, attr: str, attr2: str, /) -> attrgetter[tuple[Any, Any]]: ...
@overload
def __new__(cls, attr: str, __attr2: str, __attr3: str) -> attrgetter[tuple[Any, Any, Any]]: ...
def __new__(cls, attr: str, attr2: str, attr3: str, /) -> attrgetter[tuple[Any, Any, Any]]: ...
@overload
def __new__(cls, attr: str, __attr2: str, __attr3: str, __attr4: str) -> attrgetter[tuple[Any, Any, Any, Any]]: ...
def __new__(cls, attr: str, attr2: str, attr3: str, attr4: str, /) -> attrgetter[tuple[Any, Any, Any, Any]]: ...
@overload
def __new__(cls, attr: str, *attrs: str) -> attrgetter[tuple[Any, ...]]: ...
def __call__(self, obj: Any) -> _T_co: ...
def __new__(cls, attr: str, /, *attrs: str) -> attrgetter[tuple[Any, ...]]: ...
def __call__(self, obj: Any, /) -> _T_co: ...

@final
class itemgetter(Generic[_T_co]):
Expand Down
2 changes: 1 addition & 1 deletion stdlib/asyncio/tasks.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ else:
# While this is true in general, here it's sort-of okay to have a covariant subclass,
# since the only reason why `asyncio.Future` is invariant is the `set_result()` method,
# and `asyncio.Task.set_result()` always raises.
class Task(Future[_T_co]): # type: ignore[type-var] # pyright: ignore[reportGeneralTypeIssues]
class Task(Future[_T_co]): # type: ignore[type-var] # pyright: ignore[reportInvalidTypeArguments]
if sys.version_info >= (3, 12):
def __init__(
self,
Expand Down
4 changes: 2 additions & 2 deletions stdlib/builtins.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ class str(Sequence[str]):
def center(self: LiteralString, __width: SupportsIndex, __fillchar: LiteralString = " ") -> LiteralString: ...
@overload
def center(self, __width: SupportsIndex, __fillchar: str = " ") -> str: ... # type: ignore[misc]
def count(self, x: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ...
def count(self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...) -> int: ...
def encode(self, encoding: str = "utf-8", errors: str = "strict") -> bytes: ...
def endswith(
self, __suffix: str | tuple[str, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
Expand Down Expand Up @@ -1220,7 +1220,7 @@ class property:
class _NotImplementedType(Any):
# A little weird, but typing the __call__ as NotImplemented makes the error message
# for NotImplemented() much better
__call__: NotImplemented # type: ignore[valid-type] # pyright: ignore[reportGeneralTypeIssues]
__call__: NotImplemented # type: ignore[valid-type] # pyright: ignore[reportInvalidTypeForm]

NotImplemented: _NotImplementedType

Expand Down
4 changes: 2 additions & 2 deletions stdlib/os/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -869,8 +869,8 @@ if sys.platform != "win32":
def abort() -> NoReturn: ...

# These are defined as execl(file, *args) but the first *arg is mandatory.
def execl(file: StrOrBytesPath, __arg0: StrOrBytesPath, *args: StrOrBytesPath) -> NoReturn: ...
def execlp(file: StrOrBytesPath, __arg0: StrOrBytesPath, *args: StrOrBytesPath) -> NoReturn: ...
def execl(file: StrOrBytesPath, *args: Unpack[tuple[StrOrBytesPath, Unpack[tuple[StrOrBytesPath, ...]]]]) -> NoReturn: ...
def execlp(file: StrOrBytesPath, *args: Unpack[tuple[StrOrBytesPath, Unpack[tuple[StrOrBytesPath, ...]]]]) -> NoReturn: ...

# These are: execle(file, *args, env) but env is pulled from the last element of the args.
def execle(
Expand Down
8 changes: 8 additions & 0 deletions stdlib/queue.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ _T = TypeVar("_T")
class Empty(Exception): ...
class Full(Exception): ...

if sys.version_info >= (3, 13):
class ShutDown(Exception): ...

class Queue(Generic[_T]):
maxsize: int

Expand All @@ -20,6 +23,8 @@ class Queue(Generic[_T]):
not_full: Condition # undocumented
all_tasks_done: Condition # undocumented
unfinished_tasks: int # undocumented
if sys.version_info >= (3, 13):
is_shutdown: bool # undocumented
# Despite the fact that `queue` has `deque` type,
# we treat it as `Any` to allow different implementations in subtypes.
queue: Any # undocumented
Expand All @@ -29,6 +34,9 @@ class Queue(Generic[_T]):
def full(self) -> bool: ...
def get(self, block: bool = True, timeout: float | None = None) -> _T: ...
def get_nowait(self) -> _T: ...
if sys.version_info >= (3, 13):
def shutdown(self, immediate: bool = False) -> None: ...

def _get(self) -> _T: ...
def put(self, item: _T, block: bool = True, timeout: float | None = None) -> None: ...
def put_nowait(self, item: _T) -> None: ...
Expand Down
2 changes: 1 addition & 1 deletion stdlib/tkinter/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,7 @@ class Wm:
iconmask = wm_iconmask
def wm_iconname(self, newName: Incomplete | None = None) -> str: ...
iconname = wm_iconname
def wm_iconphoto(self, default: bool, __image1: _PhotoImageLike | str, *args: _PhotoImageLike | str) -> None: ...
def wm_iconphoto(self, default: bool, image1: _PhotoImageLike | str, /, *args: _PhotoImageLike | str) -> None: ...
iconphoto = wm_iconphoto
def wm_iconposition(self, x: int | None = None, y: int | None = None) -> tuple[int, int] | None: ...
iconposition = wm_iconposition
Expand Down
16 changes: 8 additions & 8 deletions stubs/WTForms/@tests/test_cases/check_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ def also_not_a_filter() -> None: ...

# but if we pass in some callables with an incompatible param spec
# then we should get type errors
Field(filters=(str.upper, str.lower, int, not_a_filter)) # type:ignore
Field(filters=(Filter1(), Filter2(), also_not_a_filter)) # type:ignore
Field(filters=[str.upper, str.lower, int, also_not_a_filter]) # type:ignore
Field(filters=[Filter1(), Filter2(), not_a_filter]) # type:ignore
field.process(None, extra_filters=(str.upper, str.lower, int, not_a_filter)) # type:ignore
field.process(None, extra_filters=(Filter1(), Filter2(), also_not_a_filter)) # type:ignore
field.process(None, extra_filters=[str.upper, str.lower, int, also_not_a_filter]) # type:ignore
field.process(None, extra_filters=[Filter1(), Filter2(), not_a_filter]) # type:ignore
Field(filters=(str.upper, str.lower, int, not_a_filter)) # type: ignore
Field(filters=(Filter1(), Filter2(), also_not_a_filter)) # type: ignore
Field(filters=[str.upper, str.lower, int, also_not_a_filter]) # type: ignore
Field(filters=[Filter1(), Filter2(), not_a_filter]) # type: ignore
field.process(None, extra_filters=(str.upper, str.lower, int, not_a_filter)) # type: ignore
field.process(None, extra_filters=(Filter1(), Filter2(), also_not_a_filter)) # type: ignore
field.process(None, extra_filters=[str.upper, str.lower, int, also_not_a_filter]) # type: ignore
field.process(None, extra_filters=[Filter1(), Filter2(), not_a_filter]) # type: ignore
8 changes: 4 additions & 4 deletions stubs/WTForms/@tests/test_cases/check_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@
string_field.validate(form, (Optional(), Email()))

# but not on Field
field = Field(validators=(Optional(), Email())) # type:ignore
field.validate(form, (Optional(), Email())) # type:ignore
field = Field(validators=(Optional(), Email())) # type: ignore
field.validate(form, (Optional(), Email())) # type: ignore

# unless we only pass the Field validator
Field(validators=(Optional(),))
field.validate(form, (Optional(),))

# DateField should accept Field validators but not StringField validators
date_field = DateField(validators=(Optional(), Email())) # type:ignore
date_field.validate(form, (Optional(), Email())) # type:ignore
date_field = DateField(validators=(Optional(), Email())) # type: ignore
date_field.validate(form, (Optional(), Email())) # type: ignore
DateField(validators=(Optional(),))

# for lists we can't be as strict so we won't get type errors here
Expand Down
6 changes: 3 additions & 3 deletions stubs/WTForms/@tests/test_cases/check_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

# more specific widgets should only work on more specific fields
Field(widget=Input())
Field(widget=TextArea()) # type:ignore
Field(widget=Select()) # type:ignore
Field(widget=TextArea()) # type: ignore
Field(widget=Select()) # type: ignore

# less specific widgets are fine, even if they're often not what you want
StringField(widget=Input())
Expand All @@ -15,7 +15,7 @@
SelectField(widget=Input(), option_widget=Input())
SelectField(widget=Select(), option_widget=Option())
# a more specific type other than Option widget is not allowed
SelectField(widget=Select(), option_widget=TextArea()) # type:ignore
SelectField(widget=Select(), option_widget=TextArea()) # type: ignore

# we should be able to pass Field() even though it wants an unbound_field
# this gets around __new__ not working in type checking
Expand Down
11 changes: 11 additions & 0 deletions stubs/WebOb/@tests/stubtest_allowlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,17 @@ webob.request.AdhocAttrMixin.__setattr__
# make sense to annotate them and pretend they're part of the API.
webob.request.BaseRequest.__init__

# We needed to add a dummy *_: _P.args in order to support ParamSpec
webob.dec.wsgify.middleware
webob.dec._MiddlewareFactory.__call__

# We renamed some of the arguments in positional only overloads for greater
# clarity about what the arguments mean, stubtest should probably be a bit
# more lenient here, since this is only unsafe if that overload accepts
# arbitrary named arguments, that could overlap with the argument in that
# specific position
webob.dec.wsgify.__call__

# Error: is not present at runtime
# =============================
# This attribute is there to help mypy type narrow NoVars based on its static
Expand Down
Loading

0 comments on commit 8fb9cd1

Please sign in to comment.