From 9d8fda0e0b62b1e6a5dd66731b3df5aa386a6f21 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Thu, 10 Oct 2024 17:42:03 -0700 Subject: [PATCH] Manual fixes for the rest --- pyanalyze/annotations.py | 14 +++----------- pyanalyze/checker.py | 8 ++++---- pyanalyze/format_strings.py | 10 ++++++++-- pyanalyze/name_check_visitor.py | 18 +++++------------- pyanalyze/node_visitor.py | 3 ++- pyanalyze/stacked_scopes.py | 9 +++++---- .../_pyanalyze_tests-stubs/contextmanager.pyi | 4 ++-- .../stubs/_pyanalyze_tests-stubs/recursion.pyi | 5 +++-- pyanalyze/value.py | 9 +++++---- pyanalyze/yield_checker.py | 9 ++++++--- 10 files changed, 43 insertions(+), 46 deletions(-) diff --git a/pyanalyze/annotations.py b/pyanalyze/annotations.py index 54455fd3..ea8c3101 100644 --- a/pyanalyze/annotations.py +++ b/pyanalyze/annotations.py @@ -29,17 +29,9 @@ import contextlib import typing from collections.abc import Callable, Container, Generator, Hashable, Mapping, Sequence +from contextlib import AbstractContextManager from dataclasses import InitVar, dataclass, field -from typing import ( - TYPE_CHECKING, - Any, - ContextManager, - NewType, - Optional, - TypeVar, - Union, - cast, -) +from typing import TYPE_CHECKING, Any, NewType, Optional, TypeVar, Union, cast import qcore import typing_extensions @@ -139,7 +131,7 @@ class Context: """While this is True, no errors are shown for undefined names.""" _being_evaluated: set[int] = field(default_factory=set, init=False) - def suppress_undefined_names(self) -> ContextManager[None]: + def suppress_undefined_names(self) -> AbstractContextManager[None]: """Temporarily suppress errors about undefined names.""" return qcore.override(self, "should_suppress_undefined_names", True) diff --git a/pyanalyze/checker.py b/pyanalyze/checker.py index 837ae612..d7891be3 100644 --- a/pyanalyze/checker.py +++ b/pyanalyze/checker.py @@ -9,9 +9,9 @@ import sys import types from collections.abc import Iterable, Iterator, Sequence -from contextlib import contextmanager +from contextlib import AbstractContextManager, contextmanager from dataclasses import InitVar, dataclass, field -from typing import Callable, ContextManager, Optional, Union +from typing import Callable, Optional, Union import qcore @@ -263,12 +263,12 @@ def record_any_used(self) -> None: """Record that Any was used to secure a match.""" self._has_used_any_match = True - def reset_any_used(self) -> ContextManager[None]: + def reset_any_used(self) -> AbstractContextManager[None]: """Context that resets the value used by :meth:`has_used_any_match` and :meth:`record_any_match`.""" return qcore.override(self, "_has_used_any_match", False) - def set_exclude_any(self) -> ContextManager[None]: + def set_exclude_any(self) -> AbstractContextManager[None]: """Within this context, `Any` is compatible only with itself.""" return qcore.override(self, "_should_exclude_any", True) diff --git a/pyanalyze/format_strings.py b/pyanalyze/format_strings.py index 4834123b..8f9d5a73 100644 --- a/pyanalyze/format_strings.py +++ b/pyanalyze/format_strings.py @@ -372,9 +372,15 @@ def accept_tuple_args_no_mvv( num_args = len(all_args) num_specifiers = len(specifiers) if num_args < num_specifiers: - yield f"too few arguments to format string: got {num_args} but expected {num_specifiers}" + yield ( + f"too few arguments to format string: " + f"got {num_args} but expected {num_specifiers}" + ) elif num_args > num_specifiers: - yield f"too many arguments to format string: got {num_args} but expected {num_specifiers}" + yield ( + f"too many arguments to format string: " + f"got {num_args} but expected {num_specifiers}" + ) else: for arg, specifier in zip(all_args, specifiers): yield from specifier.accept(arg, ctx) diff --git a/pyanalyze/name_check_visitor.py b/pyanalyze/name_check_visitor.py index 2cf5ec51..448610df 100644 --- a/pyanalyze/name_check_visitor.py +++ b/pyanalyze/name_check_visitor.py @@ -28,19 +28,11 @@ from abc import abstractmethod from argparse import ArgumentParser from collections.abc import Container, Generator, Iterable, Iterator, Mapping, Sequence +from contextlib import AbstractContextManager from dataclasses import dataclass from itertools import chain from pathlib import Path -from typing import ( - Annotated, - Any, - Callable, - ClassVar, - ContextManager, - Optional, - TypeVar, - Union, -) +from typing import Annotated, Any, Callable, ClassVar, Optional, TypeVar, Union from unittest.mock import ANY import asynq @@ -1236,7 +1228,7 @@ def can_assume_compatibility(self, left: TypeObject, right: TypeObject) -> bool: def assume_compatibility( self, left: TypeObject, right: TypeObject - ) -> ContextManager[None]: + ) -> AbstractContextManager[None]: return self.checker.assume_compatibility(left, right) def has_used_any_match(self) -> bool: @@ -1247,12 +1239,12 @@ def record_any_used(self) -> None: """Record that Any was used to secure a match.""" self._has_used_any_match = True - def reset_any_used(self) -> ContextManager[None]: + def reset_any_used(self) -> AbstractContextManager[None]: """Context that resets the value used by :meth:`has_used_any_match` and :meth:`record_any_match`.""" return qcore.override(self, "_has_used_any_match", False) - def set_exclude_any(self) -> ContextManager[None]: + def set_exclude_any(self) -> AbstractContextManager[None]: """Within this context, `Any` is compatible only with itself.""" return qcore.override(self, "_should_exclude_any", True) diff --git a/pyanalyze/node_visitor.py b/pyanalyze/node_visitor.py index ee5a49d7..8b3b1d49 100644 --- a/pyanalyze/node_visitor.py +++ b/pyanalyze/node_visitor.py @@ -821,7 +821,8 @@ def _get_argument_parser(cls) -> argparse.ArgumentParser: for code in cls.error_code_enum: enabled_string = "on" if cls.is_enabled_by_default(code) else "off" code_descriptions.append( - f" - {code.name}: {cls.get_description_for_error_code(code)} (default: {enabled_string})" + f" - {code.name}: {cls.get_description_for_error_code(code)}" + f" (default: {enabled_string})" ) epilog = "Supported checks:\n" + "\n".join(code_descriptions) diff --git a/pyanalyze/stacked_scopes.py b/pyanalyze/stacked_scopes.py index bcdd99eb..a9f7e704 100644 --- a/pyanalyze/stacked_scopes.py +++ b/pyanalyze/stacked_scopes.py @@ -26,10 +26,11 @@ from ast import AST from collections import OrderedDict, defaultdict from collections.abc import Iterable, Iterator, Sequence +from contextlib import AbstractContextManager from dataclasses import dataclass, field, replace from itertools import chain from types import ModuleType -from typing import Any, Callable, ContextManager, NamedTuple, Optional, TypeVar, Union +from typing import Any, Callable, NamedTuple, Optional, TypeVar, Union import qcore @@ -1508,14 +1509,14 @@ def set( """ self.scopes[-1].set(varname, value, node, state) - def suppressing_subscope(self) -> ContextManager[SubScope]: + def suppressing_subscope(self) -> AbstractContextManager[SubScope]: return self.scopes[-1].suppressing_subscope() - def subscope(self) -> ContextManager[SubScope]: + def subscope(self) -> AbstractContextManager[SubScope]: """Creates a new subscope (see the :class:`FunctionScope` docstring).""" return self.scopes[-1].subscope() - def loop_scope(self) -> ContextManager[list[SubScope]]: + def loop_scope(self) -> AbstractContextManager[list[SubScope]]: """Creates a new loop scope (see the :class:`FunctionScope` docstring).""" return self.scopes[-1].loop_scope() diff --git a/pyanalyze/stubs/_pyanalyze_tests-stubs/contextmanager.pyi b/pyanalyze/stubs/_pyanalyze_tests-stubs/contextmanager.pyi index 5550b0b0..269ba9d0 100644 --- a/pyanalyze/stubs/_pyanalyze_tests-stubs/contextmanager.pyi +++ b/pyanalyze/stubs/_pyanalyze_tests-stubs/contextmanager.pyi @@ -1,3 +1,3 @@ -from typing import ContextManager +from contextlib import AbstractContextManager -def cm() -> ContextManager[int]: ... +def cm() -> AbstractContextManager[int]: ... diff --git a/pyanalyze/stubs/_pyanalyze_tests-stubs/recursion.pyi b/pyanalyze/stubs/_pyanalyze_tests-stubs/recursion.pyi index be28b435..38b74fb7 100644 --- a/pyanalyze/stubs/_pyanalyze_tests-stubs/recursion.pyi +++ b/pyanalyze/stubs/_pyanalyze_tests-stubs/recursion.pyi @@ -1,8 +1,9 @@ -from typing import AnyStr, ContextManager +from contextlib import AbstractContextManager +from typing import AnyStr from typing_extensions import TypeAlias -class _ScandirIterator(ContextManager[_ScandirIterator[AnyStr]]): +class _ScandirIterator(AbstractContextManager[_ScandirIterator[AnyStr]]): def close(self) -> None: ... StrJson: TypeAlias = str | dict[str, StrJson] diff --git a/pyanalyze/value.py b/pyanalyze/value.py index 2bc7f56c..58a76902 100644 --- a/pyanalyze/value.py +++ b/pyanalyze/value.py @@ -25,10 +25,11 @@ def function(x: int, y: list[int], z: Any): import textwrap from collections import deque from collections.abc import Iterable, Iterator, Mapping, Sequence +from contextlib import AbstractContextManager from dataclasses import InitVar, dataclass, field from itertools import chain from types import FunctionType, ModuleType -from typing import Any, Callable, ContextManager, Optional, TypeVar, Union +from typing import Any, Callable, Optional, TypeVar, Union import qcore from typing_extensions import ParamSpec, Protocol, assert_never @@ -274,7 +275,7 @@ def assume_compatibility( self, left: "pyanalyze.type_object.TypeObject", right: "pyanalyze.type_object.TypeObject", - ) -> ContextManager[None]: + ) -> AbstractContextManager[None]: return qcore.empty_context def has_used_any_match(self) -> bool: @@ -284,12 +285,12 @@ def has_used_any_match(self) -> bool: def record_any_used(self) -> None: """Record that Any was used to secure a match.""" - def reset_any_used(self) -> ContextManager[None]: + def reset_any_used(self) -> AbstractContextManager[None]: """Context that resets the value used by :meth:`has_used_any_match` and :meth:`record_any_match`.""" return qcore.empty_context - def set_exclude_any(self) -> ContextManager[None]: + def set_exclude_any(self) -> AbstractContextManager[None]: """Within this context, `Any` is compatible only with itself.""" return qcore.empty_context diff --git a/pyanalyze/yield_checker.py b/pyanalyze/yield_checker.py index 66489a40..76ee9b0e 100644 --- a/pyanalyze/yield_checker.py +++ b/pyanalyze/yield_checker.py @@ -14,8 +14,9 @@ import itertools import logging from collections.abc import Iterator, Sequence +from contextlib import AbstractContextManager from dataclasses import dataclass, field -from typing import Any, Callable, ContextManager, Optional +from typing import Any, Callable, Optional import asynq import qcore @@ -168,7 +169,7 @@ class YieldChecker: current_function_node: Optional[FunctionNode] = None alerted_nodes: set[FunctionNode] = field(default_factory=set) - def set_function_node(self, node: FunctionNode) -> ContextManager[None]: + def set_function_node(self, node: FunctionNode) -> AbstractContextManager[None]: return qcore.override(self, "current_function_node", node) @contextlib.contextmanager @@ -197,7 +198,9 @@ def check_yield( # Unnecessary yield checking - def check_yield_result_assignment(self, in_yield: bool) -> ContextManager[None]: + def check_yield_result_assignment( + self, in_yield: bool + ) -> AbstractContextManager[None]: return qcore.override(self, "in_yield_result_assignment", in_yield) def record_assignment(self, name: str) -> None: