diff --git a/hypothesis-python/RELEASE.rst b/hypothesis-python/RELEASE.rst new file mode 100644 index 0000000000..c6a3d02e05 --- /dev/null +++ b/hypothesis-python/RELEASE.rst @@ -0,0 +1,3 @@ +RELEASE_TYPE: patch + +This patch upgrades remaining type annotations to Python 3.9 syntax. diff --git a/hypothesis-python/setup.py b/hypothesis-python/setup.py index 4fc0d3fe84..14c24b9efb 100644 --- a/hypothesis-python/setup.py +++ b/hypothesis-python/setup.py @@ -60,7 +60,7 @@ def local_file(name): "pytest": ["pytest>=4.6"], "dpcontracts": ["dpcontracts>=0.4"], "redis": ["redis>=3.0.0"], - "crosshair": ["hypothesis-crosshair>=0.0.14", "crosshair-tool>=0.0.73"], + "crosshair": ["hypothesis-crosshair>=0.0.16", "crosshair-tool>=0.0.74"], # zoneinfo is an odd one: every dependency is platform-conditional. "zoneinfo": [ "tzdata>=2024.2 ; sys_platform == 'win32' or sys_platform == 'emscripten'", diff --git a/hypothesis-python/src/_hypothesis_ftz_detector.py b/hypothesis-python/src/_hypothesis_ftz_detector.py index 2c73530c9a..2ee203429b 100644 --- a/hypothesis-python/src/_hypothesis_ftz_detector.py +++ b/hypothesis-python/src/_hypothesis_ftz_detector.py @@ -18,13 +18,13 @@ import importlib import sys -from typing import TYPE_CHECKING, Callable, Optional, Set, Tuple +from typing import TYPE_CHECKING, Callable, Optional if TYPE_CHECKING: from multiprocessing import Queue from typing import TypeAlias -FTZCulprits: "TypeAlias" = Tuple[Optional[bool], Set[str]] +FTZCulprits: "TypeAlias" = tuple[Optional[bool], set[str]] KNOWN_EVER_CULPRITS = ( @@ -104,7 +104,7 @@ def identify_ftz_culprits() -> str: # that importing them in a new process sets the FTZ state. As a heuristic, we'll # start with packages known to have ever enabled FTZ, then top-level packages as # a way to eliminate large fractions of the search space relatively quickly. - def key(name: str) -> Tuple[bool, int, str]: + def key(name: str) -> tuple[bool, int, str]: """Prefer known-FTZ modules, then top-level packages, then alphabetical.""" return (name not in KNOWN_EVER_CULPRITS, name.count("."), name) diff --git a/hypothesis-python/src/hypothesis/_settings.py b/hypothesis-python/src/hypothesis/_settings.py index d337be4f57..2f18ff920f 100644 --- a/hypothesis-python/src/hypothesis/_settings.py +++ b/hypothesis-python/src/hypothesis/_settings.py @@ -19,18 +19,9 @@ import inspect import os import warnings +from collections.abc import Collection from enum import Enum, EnumMeta, IntEnum, unique -from typing import ( - TYPE_CHECKING, - Any, - ClassVar, - Collection, - Dict, - List, - Optional, - TypeVar, - Union, -) +from typing import TYPE_CHECKING, Any, ClassVar, Optional, TypeVar, Union import attr @@ -49,7 +40,7 @@ __all__ = ["settings"] -all_settings: Dict[str, "Setting"] = {} +all_settings: dict[str, "Setting"] = {} T = TypeVar("T") @@ -138,7 +129,7 @@ class settings(metaclass=settingsMeta): """ __definitions_are_locked = False - _profiles: ClassVar[Dict[str, "settings"]] = {} + _profiles: ClassVar[dict[str, "settings"]] = {} __module__ = "hypothesis" def __getattr__(self, name): @@ -479,7 +470,7 @@ def __repr__(self): return f"{self.__class__.__name__}.{self.name}" @classmethod - def all(cls) -> List["HealthCheck"]: + def all(cls) -> list["HealthCheck"]: # Skipping of deprecated attributes is handled in HealthCheckMeta.__iter__ note_deprecation( "`HealthCheck.all()` is deprecated; use `list(HealthCheck)` instead.", diff --git a/hypothesis-python/src/hypothesis/database.py b/hypothesis-python/src/hypothesis/database.py index 72b015ce9e..72b6d8251d 100644 --- a/hypothesis-python/src/hypothesis/database.py +++ b/hypothesis-python/src/hypothesis/database.py @@ -14,12 +14,13 @@ import os import sys import warnings +from collections.abc import Iterable from datetime import datetime, timedelta, timezone from functools import lru_cache from hashlib import sha384 from os import getenv from pathlib import Path, PurePath -from typing import Dict, Iterable, Optional, Set +from typing import Optional from urllib.error import HTTPError, URLError from urllib.request import Request, urlopen from zipfile import BadZipFile, ZipFile @@ -195,7 +196,7 @@ class DirectoryBasedExampleDatabase(ExampleDatabase): def __init__(self, path: os.PathLike) -> None: self.path = Path(path) - self.keypaths: Dict[bytes, Path] = {} + self.keypaths: dict[bytes, Path] = {} def __repr__(self) -> str: return f"DirectoryBasedExampleDatabase({self.path!r})" @@ -444,7 +445,7 @@ def __init__( # .hypothesis/github-artifacts//.zip self._artifact: Optional[Path] = None # This caches the artifact structure - self._access_cache: Optional[Dict[PurePath, Set[PurePath]]] = None + self._access_cache: Optional[dict[PurePath, set[PurePath]]] = None # Message to display if user doesn't wrap around ReadOnlyDatabase self._read_only_message = ( diff --git a/hypothesis-python/src/hypothesis/extra/_array_helpers.py b/hypothesis-python/src/hypothesis/extra/_array_helpers.py index c66853fd1c..681d55e8f2 100644 --- a/hypothesis-python/src/hypothesis/extra/_array_helpers.py +++ b/hypothesis-python/src/hypothesis/extra/_array_helpers.py @@ -9,7 +9,7 @@ # obtain one at https://mozilla.org/MPL/2.0/. import re -from typing import NamedTuple, Optional, Tuple, Union +from typing import NamedTuple, Optional, Union from hypothesis import assume, strategies as st from hypothesis.errors import InvalidArgument @@ -36,13 +36,13 @@ ] -Shape = Tuple[int, ...] +Shape = tuple[int, ...] # We silence flake8 here because it disagrees with mypy about `ellipsis` (`type(...)`) -BasicIndex = Tuple[Union[int, slice, None, "ellipsis"], ...] # noqa: F821 +BasicIndex = tuple[Union[int, slice, None, "ellipsis"], ...] # noqa: F821 class BroadcastableShapes(NamedTuple): - input_shapes: Tuple[Shape, ...] + input_shapes: tuple[Shape, ...] result_shape: Shape @@ -121,7 +121,7 @@ def valid_tuple_axes( *, min_size: int = 0, max_size: Optional[int] = None, -) -> st.SearchStrategy[Tuple[int, ...]]: +) -> st.SearchStrategy[tuple[int, ...]]: """All tuples will have a length >= ``min_size`` and <= ``max_size``. The default value for ``max_size`` is ``ndim``. @@ -282,7 +282,7 @@ def broadcastable_shapes( class _GUfuncSig(NamedTuple): - input_shapes: Tuple[Shape, ...] + input_shapes: tuple[Shape, ...] result_shape: Shape diff --git a/hypothesis-python/src/hypothesis/extra/array_api.py b/hypothesis-python/src/hypothesis/extra/array_api.py index 85e5f3f8f9..f3a7ecc155 100644 --- a/hypothesis-python/src/hypothesis/extra/array_api.py +++ b/hypothesis-python/src/hypothesis/extra/array_api.py @@ -10,21 +10,15 @@ import math import sys +from collections.abc import Iterable, Iterator, Mapping, Sequence from numbers import Real from types import SimpleNamespace from typing import ( TYPE_CHECKING, Any, - Iterable, - Iterator, - List, Literal, - Mapping, NamedTuple, Optional, - Sequence, - Tuple, - Type, TypeVar, Union, get_args, @@ -89,7 +83,7 @@ @check_function -def check_xp_attributes(xp: Any, attributes: List[str]) -> None: +def check_xp_attributes(xp: Any, attributes: list[str]) -> None: missing_attrs = [attr for attr in attributes if not hasattr(xp, attr)] if len(missing_attrs) > 0: f_attrs = ", ".join(missing_attrs) @@ -100,7 +94,7 @@ def check_xp_attributes(xp: Any, attributes: List[str]) -> None: def partition_attributes_and_stubs( xp: Any, attributes: Iterable[str] -) -> Tuple[List[Any], List[str]]: +) -> tuple[list[Any], list[str]]: non_stubs = [] stubs = [] for attr in attributes: @@ -112,7 +106,7 @@ def partition_attributes_and_stubs( return non_stubs, stubs -def warn_on_missing_dtypes(xp: Any, stubs: List[str]) -> None: +def warn_on_missing_dtypes(xp: Any, stubs: list[str]) -> None: f_stubs = ", ".join(stubs) warn( f"Array module {xp.__name__} does not have the following " @@ -124,7 +118,7 @@ def warn_on_missing_dtypes(xp: Any, stubs: List[str]) -> None: def find_castable_builtin_for_dtype( xp: Any, api_version: NominalVersion, dtype: DataType -) -> Type[Union[bool, int, float, complex]]: +) -> type[Union[bool, int, float, complex]]: """Returns builtin type which can have values that are castable to the given dtype, according to :xp-ref:`type promotion rules `. @@ -591,7 +585,7 @@ def _arrays( @check_function -def check_dtypes(xp: Any, dtypes: List[DataType], stubs: List[str]) -> None: +def check_dtypes(xp: Any, dtypes: list[DataType], stubs: list[str]) -> None: if len(dtypes) == 0: assert len(stubs) > 0, "No dtypes passed but stubs is empty" f_stubs = ", ".join(stubs) diff --git a/hypothesis-python/src/hypothesis/extra/codemods.py b/hypothesis-python/src/hypothesis/extra/codemods.py index 85d1d44fd6..00e6ad30b1 100644 --- a/hypothesis-python/src/hypothesis/extra/codemods.py +++ b/hypothesis-python/src/hypothesis/extra/codemods.py @@ -48,7 +48,7 @@ import functools import importlib from inspect import Parameter, signature -from typing import ClassVar, List +from typing import ClassVar import libcst as cst import libcst.matchers as m @@ -65,7 +65,7 @@ def refactor(code: str) -> str: """ context = cst.codemod.CodemodContext() mod = cst.parse_module(code) - transforms: List[VisitorBasedCodemodCommand] = [ + transforms: list[VisitorBasedCodemodCommand] = [ HypothesisFixPositionalKeywonlyArgs(context), HypothesisFixComplexMinMagnitude(context), HypothesisFixHealthCheckAll(context), diff --git a/hypothesis-python/src/hypothesis/extra/django/_fields.py b/hypothesis-python/src/hypothesis/extra/django/_fields.py index d27eafd3d6..36b43dffe6 100644 --- a/hypothesis-python/src/hypothesis/extra/django/_fields.py +++ b/hypothesis-python/src/hypothesis/extra/django/_fields.py @@ -13,7 +13,7 @@ from datetime import datetime, timedelta from decimal import Decimal from functools import lru_cache -from typing import Any, Callable, Dict, Type, TypeVar, Union +from typing import Any, Callable, TypeVar, Union import django from django import forms as df @@ -68,8 +68,8 @@ def timezones(): # Mapping of field types, to strategy objects or functions of (type) -> strategy -_FieldLookUpType = Dict[ - Type[AnyField], +_FieldLookUpType = dict[ + type[AnyField], Union[st.SearchStrategy, Callable[[Any], st.SearchStrategy]], ] _global_field_lookup: _FieldLookUpType = { @@ -319,7 +319,7 @@ def _for_model_multiple_choice(field): def register_field_strategy( - field_type: Type[AnyField], strategy: st.SearchStrategy + field_type: type[AnyField], strategy: st.SearchStrategy ) -> None: """Add an entry to the global field-to-strategy lookup used by :func:`~hypothesis.extra.django.from_field`. diff --git a/hypothesis-python/src/hypothesis/extra/django/_impl.py b/hypothesis-python/src/hypothesis/extra/django/_impl.py index 09a1c2707c..b1aa59744c 100644 --- a/hypothesis-python/src/hypothesis/extra/django/_impl.py +++ b/hypothesis-python/src/hypothesis/extra/django/_impl.py @@ -11,7 +11,7 @@ import sys import unittest from functools import partial -from typing import TYPE_CHECKING, Optional, Type, TypeVar, Union +from typing import TYPE_CHECKING, Optional, TypeVar, Union from django import forms as df, test as dt from django.contrib.staticfiles import testing as dst @@ -66,7 +66,7 @@ class StaticLiveServerTestCase(HypothesisTestCase, dst.StaticLiveServerTestCase) @defines_strategy() def from_model( - model: Type[ModelT], /, **field_strategies: Union[st.SearchStrategy, EllipsisType] + model: type[ModelT], /, **field_strategies: Union[st.SearchStrategy, EllipsisType] ) -> st.SearchStrategy[ModelT]: """Return a strategy for examples of ``model``. @@ -136,7 +136,7 @@ def _models_impl(draw, strat): @defines_strategy() def from_form( - form: Type[df.Form], + form: type[df.Form], form_kwargs: Optional[dict] = None, **field_strategies: Union[st.SearchStrategy, EllipsisType], ) -> st.SearchStrategy[df.Form]: diff --git a/hypothesis-python/src/hypothesis/extra/lark.py b/hypothesis-python/src/hypothesis/extra/lark.py index 37b5f5d401..9b26519a6e 100644 --- a/hypothesis-python/src/hypothesis/extra/lark.py +++ b/hypothesis-python/src/hypothesis/extra/lark.py @@ -25,7 +25,7 @@ """ from inspect import signature -from typing import Dict, Optional +from typing import Optional import lark from lark.grammar import NonTerminal, Terminal @@ -201,7 +201,7 @@ def from_lark( grammar: lark.lark.Lark, *, start: Optional[str] = None, - explicit: Optional[Dict[str, st.SearchStrategy[str]]] = None, + explicit: Optional[dict[str, st.SearchStrategy[str]]] = None, alphabet: st.SearchStrategy[str] = st.characters(codec="utf-8"), ) -> st.SearchStrategy[str]: """A strategy for strings accepted by the given context-free grammar. diff --git a/hypothesis-python/src/hypothesis/extra/numpy.py b/hypothesis-python/src/hypothesis/extra/numpy.py index b6e75d3efa..a94471769b 100644 --- a/hypothesis-python/src/hypothesis/extra/numpy.py +++ b/hypothesis-python/src/hypothesis/extra/numpy.py @@ -11,20 +11,8 @@ import importlib import math import types -from typing import ( - TYPE_CHECKING, - Any, - Literal, - Mapping, - Optional, - Sequence, - Tuple, - Type, - TypeVar, - Union, - cast, - overload, -) +from collections.abc import Mapping, Sequence +from typing import TYPE_CHECKING, Any, Literal, Optional, TypeVar, Union, cast, overload import numpy as np @@ -1190,7 +1178,7 @@ def integer_array_indices( shape: Shape, *, result_shape: st.SearchStrategy[Shape] = array_shapes(), -) -> "st.SearchStrategy[Tuple[NDArray[np.signedinteger[Any]], ...]]": ... +) -> "st.SearchStrategy[tuple[NDArray[np.signedinteger[Any]], ...]]": ... @overload @@ -1200,7 +1188,7 @@ def integer_array_indices( *, result_shape: st.SearchStrategy[Shape] = array_shapes(), dtype: "np.dtype[I]", -) -> "st.SearchStrategy[Tuple[NDArray[I], ...]]": ... +) -> "st.SearchStrategy[tuple[NDArray[I], ...]]": ... @defines_strategy() @@ -1209,7 +1197,7 @@ def integer_array_indices( *, result_shape: st.SearchStrategy[Shape] = array_shapes(), dtype: "np.dtype[I] | np.dtype[np.signedinteger[Any]]" = np.dtype(int), -) -> "st.SearchStrategy[Tuple[NDArray[I], ...]]": +) -> "st.SearchStrategy[tuple[NDArray[I], ...]]": """Return a search strategy for tuples of integer-arrays that, when used to index into an array of shape ``shape``, given an array whose shape was drawn from ``result_shape``. @@ -1314,7 +1302,7 @@ def _dtype_from_args(args): return np.dtype(dtype) -def _from_type(thing: Type[Ex]) -> Optional[st.SearchStrategy[Ex]]: +def _from_type(thing: type[Ex]) -> Optional[st.SearchStrategy[Ex]]: """Called by st.from_type to try to infer a strategy for thing using numpy. If we can infer a numpy-specific strategy for thing, we return that; otherwise, diff --git a/hypothesis-python/src/hypothesis/extra/pandas/impl.py b/hypothesis-python/src/hypothesis/extra/pandas/impl.py index 16ef90fc63..5beeede287 100644 --- a/hypothesis-python/src/hypothesis/extra/pandas/impl.py +++ b/hypothesis-python/src/hypothesis/extra/pandas/impl.py @@ -9,9 +9,10 @@ # obtain one at https://mozilla.org/MPL/2.0/. from collections import OrderedDict, abc +from collections.abc import Sequence from copy import copy from datetime import datetime, timedelta -from typing import Any, Generic, List, Optional, Sequence, Set, Union +from typing import Any, Generic, Optional, Union import attr import numpy as np @@ -389,7 +390,7 @@ def columns( elements: Optional[st.SearchStrategy[Ex]] = None, fill: Optional[st.SearchStrategy[Ex]] = None, unique: bool = False, -) -> List[column[Ex]]: +) -> list[column[Ex]]: """A convenience function for producing a list of :class:`column` objects of the same general shape. @@ -400,7 +401,7 @@ def columns( create the columns. """ if isinstance(names_or_number, (int, float)): - names: List[Union[int, str, None]] = [None] * names_or_number + names: list[Union[int, str, None]] = [None] * names_or_number else: names = list(names_or_number) return [ @@ -554,7 +555,7 @@ def row(): cols = try_convert(tuple, columns, "columns") rewritten_columns = [] - column_names: Set[str] = set() + column_names: set[str] = set() for i, c in enumerate(cols): check_type(column, c, f"columns[{i}]") diff --git a/hypothesis-python/src/hypothesis/extra/redis.py b/hypothesis-python/src/hypothesis/extra/redis.py index e0f1c1b851..516c2d88e4 100644 --- a/hypothesis-python/src/hypothesis/extra/redis.py +++ b/hypothesis-python/src/hypothesis/extra/redis.py @@ -8,9 +8,9 @@ # v. 2.0. If a copy of the MPL was not distributed with this file, You can # obtain one at https://mozilla.org/MPL/2.0/. +from collections.abc import Iterable from contextlib import contextmanager from datetime import timedelta -from typing import Iterable from redis import Redis diff --git a/hypothesis-python/src/hypothesis/internal/charmap.py b/hypothesis-python/src/hypothesis/internal/charmap.py index 468beeb5e8..8a1e98ef18 100644 --- a/hypothesis-python/src/hypothesis/internal/charmap.py +++ b/hypothesis-python/src/hypothesis/internal/charmap.py @@ -16,15 +16,14 @@ import tempfile import unicodedata from functools import lru_cache -from typing import Dict, Tuple from hypothesis.configuration import storage_directory from hypothesis.control import _current_build_context from hypothesis.errors import InvalidArgument from hypothesis.internal.intervalsets import IntervalSet -intervals = Tuple[Tuple[int, int], ...] -cache_type = Dict[Tuple[Tuple[str, ...], int, int, intervals], IntervalSet] +intervals = tuple[tuple[int, int], ...] +cache_type = dict[tuple[tuple[str, ...], int, int, intervals], IntervalSet] def charmap_file(fname="charmap"): diff --git a/hypothesis-python/src/hypothesis/internal/conjecture/choicetree.py b/hypothesis-python/src/hypothesis/internal/conjecture/choicetree.py index d7645e1889..0ba8ab819b 100644 --- a/hypothesis-python/src/hypothesis/internal/conjecture/choicetree.py +++ b/hypothesis-python/src/hypothesis/internal/conjecture/choicetree.py @@ -9,8 +9,9 @@ # obtain one at https://mozilla.org/MPL/2.0/. from collections import defaultdict +from collections.abc import Iterable, Sequence from random import Random -from typing import Callable, Dict, Iterable, List, Optional, Sequence +from typing import Callable, List, Optional from hypothesis.internal.conjecture.junkdrawer import LazySequenceCopy @@ -144,7 +145,7 @@ def step( class TreeNode: def __init__(self) -> None: - self.children: Dict[int, TreeNode] = defaultdict(TreeNode) + self.children: dict[int, TreeNode] = defaultdict(TreeNode) self.live_child_count: "Optional[int]" = None self.n: "Optional[int]" = None diff --git a/hypothesis-python/src/hypothesis/internal/conjecture/data.py b/hypothesis-python/src/hypothesis/internal/conjecture/data.py index 26496e143c..3664d76729 100644 --- a/hypothesis-python/src/hypothesis/internal/conjecture/data.py +++ b/hypothesis-python/src/hypothesis/internal/conjecture/data.py @@ -13,6 +13,7 @@ import math import time from collections import defaultdict +from collections.abc import Iterable, Iterator, Sequence from enum import IntEnum from random import Random from sys import float_info @@ -20,19 +21,9 @@ TYPE_CHECKING, Any, Callable, - DefaultDict, - Dict, - FrozenSet, - Iterable, - Iterator, - List, Literal, NoReturn, Optional, - Sequence, - Set, - Tuple, - Type, TypedDict, TypeVar, Union, @@ -86,10 +77,10 @@ def wrapper(tp): TOP_LABEL = calc_label_from_name("top") -InterestingOrigin = Tuple[ - Type[BaseException], str, int, Tuple[Any, ...], Tuple[Tuple[Any, ...], ...] +InterestingOrigin = tuple[ + type[BaseException], str, int, tuple[Any, ...], tuple[tuple[Any, ...], ...] ] -TargetObservations = Dict[str, Union[int, float]] +TargetObservations = dict[str, Union[int, float]] T = TypeVar("T") @@ -129,7 +120,7 @@ class BooleanKWargs(TypedDict): ] IRTypeName: TypeAlias = Literal["integer", "string", "boolean", "float", "bytes"] # index, ir_type, kwargs, forced -MisalignedAt: TypeAlias = Tuple[int, IRTypeName, IRKWargsType, Optional[IRType]] +MisalignedAt: TypeAlias = tuple[int, IRTypeName, IRKWargsType, Optional[IRType]] class ExtraInformation: @@ -161,7 +152,7 @@ class StructuralCoverageTag: label: int = attr.ib() -STRUCTURAL_COVERAGE_CACHE: Dict[int, StructuralCoverageTag] = {} +STRUCTURAL_COVERAGE_CACHE: dict[int, StructuralCoverageTag] = {} def structural_coverage(label: int) -> StructuralCoverageTag: @@ -330,7 +321,7 @@ def ir_length(self) -> int: return self.ir_end - self.ir_start @property - def children(self) -> "List[Example]": + def children(self) -> "list[Example]": """The list of all examples with this as a parent, in increasing index order.""" return [self.owner[i] for i in self.owner.children[self.index]] @@ -346,7 +337,7 @@ class ExampleProperty: """ def __init__(self, examples: "Examples"): - self.example_stack: "List[int]" = [] + self.example_stack: "list[int]" = [] self.examples = examples self.bytes_read = 0 self.example_count = 0 @@ -415,7 +406,7 @@ def finish(self) -> Any: return self.result -def calculated_example_property(cls: Type[ExampleProperty]) -> Any: +def calculated_example_property(cls: type[ExampleProperty]) -> Any: """Given an ``ExampleProperty`` as above we use this decorator to transform it into a lazy property on the ``Examples`` class, which has as its value the result of calling ``cls.run()``, @@ -458,10 +449,10 @@ class ExampleRecord: """ def __init__(self) -> None: - self.labels: List[int] = [] - self.__index_of_labels: "Optional[Dict[int, int]]" = {} + self.labels: list[int] = [] + self.__index_of_labels: "dict[int, int] | None" = {} self.trail = IntList() - self.ir_nodes: List[IRNode] = [] + self.ir_nodes: list[IRNode] = [] def freeze(self) -> None: self.__index_of_labels = None @@ -522,7 +513,7 @@ def __init__(self, record: ExampleRecord, blocks: "Blocks") -> None: STOP_EXAMPLE_DISCARD_RECORD ) + record.trail.count(STOP_EXAMPLE_NO_DISCARD_RECORD) self.blocks = blocks - self.__children: "Optional[List[Sequence[int]]]" = None + self.__children: "list[Sequence[int]] | None" = None class _starts_and_ends(ExampleProperty): def begin(self) -> None: @@ -535,10 +526,10 @@ def start_example(self, i: int, label_index: int) -> None: def stop_example(self, i: int, *, discarded: bool) -> None: self.ends[i] = self.bytes_read - def finish(self) -> Tuple[IntList, IntList]: + def finish(self) -> tuple[IntList, IntList]: return (self.starts, self.ends) - starts_and_ends: "Tuple[IntList, IntList]" = calculated_example_property( + starts_and_ends: "tuple[IntList, IntList]" = calculated_example_property( _starts_and_ends ) @@ -561,10 +552,10 @@ def start_example(self, i: int, label_index: int) -> None: def stop_example(self, i: int, *, discarded: bool) -> None: self.ends[i] = self.ir_node_count - def finish(self) -> Tuple[IntList, IntList]: + def finish(self) -> tuple[IntList, IntList]: return (self.starts, self.ends) - ir_starts_and_ends: "Tuple[IntList, IntList]" = calculated_example_property( + ir_starts_and_ends: "tuple[IntList, IntList]" = calculated_example_property( _ir_starts_and_ends ) @@ -578,21 +569,21 @@ def ir_ends(self) -> IntList: class _discarded(ExampleProperty): def begin(self) -> None: - self.result: "Set[int]" = set() + self.result: "set[int]" = set() - def finish(self) -> FrozenSet[int]: + def finish(self) -> frozenset[int]: return frozenset(self.result) def stop_example(self, i: int, *, discarded: bool) -> None: if discarded: self.result.add(i) - discarded: FrozenSet[int] = calculated_example_property(_discarded) + discarded: frozenset[int] = calculated_example_property(_discarded) class _trivial(ExampleProperty): def begin(self) -> None: self.nontrivial = IntList.of_length(len(self.examples)) - self.result: "Set[int]" = set() + self.result: "set[int]" = set() def block(self, i: int) -> None: if not self.examples.blocks.trivial(i): @@ -605,10 +596,10 @@ def stop_example(self, i: int, *, discarded: bool) -> None: else: self.result.add(i) - def finish(self) -> FrozenSet[int]: + def finish(self) -> frozenset[int]: return frozenset(self.result) - trivial: FrozenSet[int] = calculated_example_property(_trivial) + trivial: frozenset[int] = calculated_example_property(_trivial) class _parentage(ExampleProperty): def stop_example(self, i: int, *, discarded: bool) -> None: @@ -633,7 +624,7 @@ def begin(self) -> None: def ir_node(self, ir_node: "IRNode") -> None: self.result.append(ir_node) - ir_tree_nodes: "List[IRNode]" = calculated_example_property(_ir_tree_nodes) + ir_tree_nodes: "list[IRNode]" = calculated_example_property(_ir_tree_nodes) class _label_indices(ExampleProperty): def start_example(self, i: int, label_index: int) -> None: @@ -643,7 +634,7 @@ def start_example(self, i: int, label_index: int) -> None: class _mutator_groups(ExampleProperty): def begin(self) -> None: - self.groups: "Dict[int, Set[Tuple[int, int]]]" = defaultdict(set) + self.groups: "dict[int, set[tuple[int, int]]]" = defaultdict(set) def start_example(self, i: int, label_index: int) -> None: # TODO should we discard start == end cases? occurs for eg st.data() @@ -652,17 +643,17 @@ def start_example(self, i: int, label_index: int) -> None: key = (self.examples[i].ir_start, self.examples[i].ir_end) self.groups[label_index].add(key) - def finish(self) -> Iterable[Set[Tuple[int, int]]]: + def finish(self) -> Iterable[set[tuple[int, int]]]: # Discard groups with only one example, since the mutator can't # do anything useful with them. return [g for g in self.groups.values() if len(g) >= 2] - mutator_groups: List[Set[Tuple[int, int]]] = calculated_example_property( + mutator_groups: list[set[tuple[int, int]]] = calculated_example_property( _mutator_groups ) @property - def children(self) -> List[Sequence[int]]: + def children(self) -> list[Sequence[int]]: if self.__children is None: children = [IntList() for _ in range(len(self))] for i, p in enumerate(self.parentage): @@ -722,7 +713,7 @@ class Block: all_zero: bool = attr.ib(repr=False) @property - def bounds(self) -> Tuple[int, int]: + def bounds(self) -> tuple[int, int]: return (self.start, self.end) @property @@ -753,7 +744,7 @@ class Blocks: __slots__ = ("endpoints", "owner", "__blocks", "__count", "__sparse") owner: "Union[ConjectureData, ConjectureResult, None]" - __blocks: Union[Dict[int, Block], List[Optional[Block]]] + __blocks: Union[dict[int, Block], list[Optional[Block]]] def __init__(self, owner: "ConjectureData") -> None: self.owner = owner @@ -788,7 +779,7 @@ def end(self, i: int) -> int: """Equivalent to self[i].end.""" return self.endpoints[i] - def all_bounds(self) -> Iterable[Tuple[int, int]]: + def all_bounds(self) -> Iterable[tuple[int, int]]: """Equivalent to [(b.start, b.end) for b in self].""" prev = 0 for e in self.endpoints: @@ -837,7 +828,7 @@ def __getitem__(self, i: int) -> Block: # stop being sparse and want to use most of the blocks. Switch # over to a list at that point. if self.__sparse and len(self.__blocks) * 2 >= len(self): - new_blocks: "List[Optional[Block]]" = [None] * len(self) + new_blocks: "list[Block | None]" = [None] * len(self) assert isinstance(self.__blocks, dict) for k, v in self.__blocks.items(): new_blocks[k] = v @@ -894,7 +885,7 @@ def __iter__(self) -> Iterator[Block]: yield self[i] def __repr__(self) -> str: - parts: "List[str]" = [] + parts: "list[str]" = [] for i in range(len(self)): b = self.__known_block(i) if b is None: @@ -1172,11 +1163,11 @@ class ConjectureResult: extra_information: Optional[ExtraInformation] = attr.ib() has_discards: bool = attr.ib() target_observations: TargetObservations = attr.ib() - tags: FrozenSet[StructuralCoverageTag] = attr.ib() - forced_indices: FrozenSet[int] = attr.ib(repr=False) + tags: frozenset[StructuralCoverageTag] = attr.ib() + forced_indices: frozenset[int] = attr.ib(repr=False) examples: Examples = attr.ib(repr=False, eq=False) - arg_slices: Set[Tuple[int, int]] = attr.ib(repr=False) - slice_comments: Dict[Tuple[int, int], str] = attr.ib(repr=False) + arg_slices: set[tuple[int, int]] = attr.ib(repr=False) + slice_comments: dict[tuple[int, int], str] = attr.ib(repr=False) misaligned_at: Optional[MisalignedAt] = attr.ib(repr=False) index: int = attr.ib(init=False) @@ -1200,7 +1191,7 @@ def as_result(self) -> "ConjectureResult": class _BackendInfoMsg(TypedDict): type: str title: str - content: Union[str, Dict[str, Any]] + content: Union[str, dict[str, Any]] class PrimitiveProvider(abc.ABC): @@ -1259,7 +1250,7 @@ def realize(self, value: T) -> T: """ return value - def observe_test_case(self) -> Dict[str, Any]: + def observe_test_case(self) -> dict[str, Any]: """Called at the end of the test case when observability mode is active. The return value should be a non-symbolic json-encodable dictionary, @@ -1865,12 +1856,12 @@ def _draw_float_init_logic( max_value: float, allow_nan: bool, smallest_nonzero_magnitude: float, - ) -> Tuple[ + ) -> tuple[ Optional[Sampler], Optional[Literal[0, 1]], Optional[Callable[[float], float]], Optional[Callable[[float], float]], - List[float], + list[float], ]: """ Caches initialization logic for draw_float, as an alternative to @@ -1903,12 +1894,12 @@ def _compute_draw_float_init_logic( max_value: float, allow_nan: bool, smallest_nonzero_magnitude: float, - ) -> Tuple[ + ) -> tuple[ Optional[Sampler], Optional[Literal[0, 1]], Optional[Callable[[float], float]], Optional[Callable[[float], float]], - List[float], + list[float], ]: if smallest_nonzero_magnitude == 0.0: # pragma: no cover raise FloatingPointError( @@ -1974,7 +1965,7 @@ class ConjectureData: @classmethod def for_buffer( cls, - buffer: Union[List[int], bytes], + buffer: Union[list[int], bytes], *, observer: Optional[DataObserver] = None, provider: Union[type, PrimitiveProvider] = HypothesisProvider, @@ -1986,7 +1977,7 @@ def for_buffer( @classmethod def for_ir_tree( cls, - ir_tree_prefix: List[IRNode], + ir_tree_prefix: list[IRNode], *, observer: Optional[DataObserver] = None, provider: Union[type, PrimitiveProvider] = HypothesisProvider, @@ -2006,12 +1997,12 @@ def for_ir_tree( def __init__( self, max_length: int, - prefix: Union[List[int], bytes, bytearray], + prefix: Union[list[int], bytes, bytearray], *, random: Optional[Random], observer: Optional[DataObserver] = None, provider: Union[type, PrimitiveProvider] = HypothesisProvider, - ir_tree_prefix: Optional[List[IRNode]] = None, + ir_tree_prefix: Optional[list[IRNode]] = None, ) -> None: if observer is None: observer = DataObserver() @@ -2038,11 +2029,11 @@ def __init__( global_test_counter += 1 self.start_time = time.perf_counter() self.gc_start_time = gc_cumulative_time() - self.events: Dict[str, Union[str, int, float]] = {} - self.forced_indices: "Set[int]" = set() + self.events: dict[str, Union[str, int, float]] = {} + self.forced_indices: "set[int]" = set() self.interesting_origin: Optional[InterestingOrigin] = None - self.draw_times: "Dict[str, float]" = {} - self._stateful_run_times: "DefaultDict[str, float]" = defaultdict(float) + self.draw_times: "dict[str, float]" = {} + self._stateful_run_times: "defaultdict[str, float]" = defaultdict(float) self.max_depth = 0 self.has_discards = False @@ -2059,8 +2050,8 @@ def __init__( # Tags which indicate something about which part of the search space # this example is in. These are used to guide generation. - self.tags: "Set[StructuralCoverageTag]" = set() - self.labels_for_structure_stack: "List[Set[int]]" = [] + self.tags: "set[StructuralCoverageTag]" = set() + self.labels_for_structure_stack: "list[set[int]]" = [] # Normally unpopulated but we need this in the niche case # that self.as_result() is Overrun but we still want the @@ -2074,9 +2065,9 @@ def __init__( # Slice indices for discrete reportable parts that which-parts-matter can # try varying, to report if the minimal example always fails anyway. - self.arg_slices: Set[Tuple[int, int]] = set() - self.slice_comments: Dict[Tuple[int, int], str] = {} - self._observability_args: Dict[str, Any] = {} + self.arg_slices: set[tuple[int, int]] = set() + self.slice_comments: dict[tuple[int, int], str] = {} + self._observability_args: dict[str, Any] = {} self._observability_predicates: defaultdict = defaultdict( lambda: {"satisfied": 0, "unsatisfied": 0} ) diff --git a/hypothesis-python/src/hypothesis/internal/conjecture/datatree.py b/hypothesis-python/src/hypothesis/internal/conjecture/datatree.py index 87a0c988c8..5ec38c2edf 100644 --- a/hypothesis-python/src/hypothesis/internal/conjecture/datatree.py +++ b/hypothesis-python/src/hypothesis/internal/conjecture/datatree.py @@ -10,7 +10,7 @@ import itertools import math -from typing import List, Optional, Union +from typing import Optional, Union import attr @@ -418,9 +418,9 @@ class TreeNode: # The kwargs, value, and ir_types of the nodes stored here. These always # have the same length. The values at index i belong to node i. - kwargs: List[IRKWargsType] = attr.ib(factory=list) - values: List[IRType] = attr.ib(factory=list) - ir_types: List[IRTypeName] = attr.ib(factory=list) + kwargs: list[IRKWargsType] = attr.ib(factory=list) + values: list[IRType] = attr.ib(factory=list) + ir_types: list[IRTypeName] = attr.ib(factory=list) # The indices of nodes which had forced values. # diff --git a/hypothesis-python/src/hypothesis/internal/conjecture/junkdrawer.py b/hypothesis-python/src/hypothesis/internal/conjecture/junkdrawer.py index 39382637db..2c46a95223 100644 --- a/hypothesis-python/src/hypothesis/internal/conjecture/junkdrawer.py +++ b/hypothesis-python/src/hypothesis/internal/conjecture/junkdrawer.py @@ -17,19 +17,15 @@ import sys import time import warnings +from collections.abc import Iterable, Iterator, Sequence from random import Random from typing import ( Any, Callable, - Dict, Generic, - Iterable, - Iterator, List, Literal, Optional, - Sequence, - Tuple, TypeVar, Union, overload, @@ -54,14 +50,14 @@ def array_or_list( def replace_all( ls: Sequence[T], - replacements: Iterable[Tuple[int, int, Sequence[T]]], -) -> List[T]: + replacements: Iterable[tuple[int, int, Sequence[T]]], +) -> list[T]: """Substitute multiple replacement values into a list. Replacements is a list of (start, end, value) triples. """ - result: List[T] = [] + result: list[T] = [] prev = 0 offset = 0 for u, v, r in replacements: @@ -208,7 +204,7 @@ class LazySequenceCopy: def __init__(self, values: Sequence[int]): self.__values = values self.__len = len(values) - self.__mask: Optional[Dict[int, int]] = None + self.__mask: Optional[dict[int, int]] = None self.__popped_indices: Optional[SortedList] = None def __len__(self) -> int: @@ -434,7 +430,7 @@ def gc_cumulative_time() -> float: if hasattr(gc, "callbacks"): # CPython def gc_callback( - phase: Literal["start", "stop"], info: Dict[str, int] + phase: Literal["start", "stop"], info: dict[str, int] ) -> None: global _gc_start, _gc_cumulative_time try: diff --git a/hypothesis-python/src/hypothesis/internal/conjecture/shrinker.py b/hypothesis-python/src/hypothesis/internal/conjecture/shrinker.py index d1084e4cdd..a1a3424963 100644 --- a/hypothesis-python/src/hypothesis/internal/conjecture/shrinker.py +++ b/hypothesis-python/src/hypothesis/internal/conjecture/shrinker.py @@ -9,7 +9,7 @@ # obtain one at https://mozilla.org/MPL/2.0/. from collections import defaultdict -from typing import TYPE_CHECKING, Callable, Dict, Optional, Tuple, TypeVar, Union +from typing import TYPE_CHECKING, Callable, Optional, TypeVar, Union import attr @@ -45,7 +45,7 @@ SortKeyT = TypeVar("SortKeyT", str, bytes) -def sort_key(buffer: SortKeyT) -> Tuple[int, SortKeyT]: +def sort_key(buffer: SortKeyT) -> tuple[int, SortKeyT]: """Returns a sort key such that "simpler" buffers are smaller than "more complicated" ones. @@ -71,7 +71,7 @@ def sort_key(buffer: SortKeyT) -> Tuple[int, SortKeyT]: return (len(buffer), buffer) -SHRINK_PASS_DEFINITIONS: Dict[str, "ShrinkPassDefinition"] = {} +SHRINK_PASS_DEFINITIONS: dict[str, "ShrinkPassDefinition"] = {} @attr.s() @@ -313,7 +313,7 @@ def __init__( self.initial_misaligned = self.engine.misaligned_count self.calls_at_last_shrink = self.initial_calls - self.passes_by_name: Dict[str, ShrinkPass] = {} + self.passes_by_name: dict[str, ShrinkPass] = {} # Because the shrinker is also used to `pareto_optimise` in the target phase, # we sometimes want to allow extending buffers instead of aborting at the end. diff --git a/hypothesis-python/src/hypothesis/internal/conjecture/utils.py b/hypothesis-python/src/hypothesis/internal/conjecture/utils.py index 3724c82177..c08cb7e094 100644 --- a/hypothesis-python/src/hypothesis/internal/conjecture/utils.py +++ b/hypothesis-python/src/hypothesis/internal/conjecture/utils.py @@ -13,8 +13,9 @@ import heapq import sys from collections import OrderedDict, abc +from collections.abc import Sequence from functools import lru_cache -from typing import TYPE_CHECKING, List, Optional, Sequence, Tuple, Type, TypeVar, Union +from typing import TYPE_CHECKING, List, Optional, TypeVar, Union from hypothesis.errors import InvalidArgument from hypothesis.internal.compat import int_from_bytes @@ -56,7 +57,7 @@ def identity(v: T) -> T: def check_sample( - values: Union[Type[enum.Enum], Sequence[T]], strategy_name: str + values: Union[type[enum.Enum], Sequence[T]], strategy_name: str ) -> Sequence[T]: if "numpy" in sys.modules and isinstance(values, sys.modules["numpy"].ndarray): if values.ndim != 1: @@ -103,7 +104,7 @@ class Sampler: shrinking the chosen element. """ - table: List[Tuple[int, int, float]] # (base_idx, alt_idx, alt_chance) + table: list[tuple[int, int, float]] # (base_idx, alt_idx, alt_chance) def __init__(self, weights: Sequence[float], *, observe: bool = True): self.observe = observe @@ -158,7 +159,7 @@ def __init__(self, weights: Sequence[float], *, observe: bool = True): while small: table[small.pop()][2] = zero - self.table: "List[Tuple[int, int, float]]" = [] + self.table: "list[tuple[int, int, float]]" = [] for base, alternate, alternate_chance in table: # type: ignore assert isinstance(base, int) assert isinstance(alternate, int) or alternate is None diff --git a/hypothesis-python/src/hypothesis/internal/coverage.py b/hypothesis-python/src/hypothesis/internal/coverage.py index 57b9f8ed04..5f219d6407 100644 --- a/hypothesis-python/src/hypothesis/internal/coverage.py +++ b/hypothesis-python/src/hypothesis/internal/coverage.py @@ -12,7 +12,7 @@ import os import sys from contextlib import contextmanager -from typing import Callable, Dict, Set, Tuple, TypeVar +from typing import Callable, TypeVar from hypothesis.internal.reflection import proxies @@ -30,7 +30,7 @@ """ Func = TypeVar("Func", bound=Callable) -pretty_file_name_cache: Dict[str, str] = {} +pretty_file_name_cache: dict[str, str] = {} def pretty_file_name(f): @@ -55,7 +55,7 @@ def pretty_file_name(f): # By this point, "branch-check" should have already been deleted by the # tox config. We can't delete it here because of #1718. - written: Set[Tuple[str, bool]] = set() + written: set[tuple[str, bool]] = set() def record_branch(name, value): key = (name, value) diff --git a/hypothesis-python/src/hypothesis/internal/entropy.py b/hypothesis-python/src/hypothesis/internal/entropy.py index fe7d3f8347..21d17c465d 100644 --- a/hypothesis-python/src/hypothesis/internal/entropy.py +++ b/hypothesis-python/src/hypothesis/internal/entropy.py @@ -13,8 +13,9 @@ import random import sys import warnings +from collections.abc import Hashable from itertools import count -from typing import TYPE_CHECKING, Any, Callable, Hashable, Tuple +from typing import TYPE_CHECKING, Any, Callable from weakref import WeakValueDictionary import hypothesis.core @@ -147,7 +148,7 @@ def my_WORKING_hook(): def get_seeder_and_restorer( seed: Hashable = 0, -) -> Tuple[Callable[[], None], Callable[[], None]]: +) -> tuple[Callable[[], None], Callable[[], None]]: """Return a pair of functions which respectively seed all and restore the state of all registered PRNGs. diff --git a/hypothesis-python/src/hypothesis/internal/escalation.py b/hypothesis-python/src/hypothesis/internal/escalation.py index d18b2546fd..0fa6454167 100644 --- a/hypothesis-python/src/hypothesis/internal/escalation.py +++ b/hypothesis-python/src/hypothesis/internal/escalation.py @@ -16,7 +16,7 @@ from functools import partial from inspect import getframeinfo from pathlib import Path -from typing import Dict, NamedTuple, Optional, Tuple, Type +from typing import NamedTuple, Optional import hypothesis from hypothesis.errors import _Trimmable @@ -49,7 +49,7 @@ def accept(filepath): return accept -FILE_CACHE: Dict[bytes, bool] = {} +FILE_CACHE: dict[bytes, bool] = {} is_hypothesis_file = belongs_to(hypothesis) @@ -91,7 +91,7 @@ class InterestingOrigin(NamedTuple): # location, but have extracted this logic in order to see through `except ...:` # blocks and understand the __cause__ (`raise x from y`) or __context__ that # first raised an exception as well as PEP-654 exception groups. - exc_type: Type[BaseException] + exc_type: type[BaseException] filename: Optional[str] lineno: Optional[int] context: "InterestingOrigin | tuple[()]" @@ -109,7 +109,7 @@ def __str__(self) -> str: @classmethod def from_exception( - cls, exception: BaseException, /, seen: Tuple[BaseException, ...] = () + cls, exception: BaseException, /, seen: tuple[BaseException, ...] = () ) -> "InterestingOrigin": filename, lineno = None, None if tb := get_trimmed_traceback(exception): diff --git a/hypothesis-python/src/hypothesis/internal/filtering.py b/hypothesis-python/src/hypothesis/internal/filtering.py index bfe858ccfe..4d0435c517 100644 --- a/hypothesis-python/src/hypothesis/internal/filtering.py +++ b/hypothesis-python/src/hypothesis/internal/filtering.py @@ -26,10 +26,11 @@ import inspect import math import operator +from collections.abc import Collection from decimal import Decimal from fractions import Fraction from functools import partial -from typing import Any, Callable, Collection, Dict, NamedTuple, Optional, TypeVar +from typing import Any, Callable, NamedTuple, Optional, TypeVar from hypothesis.internal.compat import ceil, floor from hypothesis.internal.floats import next_down, next_up @@ -60,7 +61,7 @@ class ConstructivePredicate(NamedTuple): for each numeric type, for strings, for bytes, for collection sizes, etc. """ - kwargs: Dict[str, Any] + kwargs: dict[str, Any] predicate: Optional[Predicate] @classmethod diff --git a/hypothesis-python/src/hypothesis/internal/floats.py b/hypothesis-python/src/hypothesis/internal/floats.py index 79e6433dca..3ef5d6c030 100644 --- a/hypothesis-python/src/hypothesis/internal/floats.py +++ b/hypothesis-python/src/hypothesis/internal/floats.py @@ -11,16 +11,7 @@ import math import struct from sys import float_info -from typing import ( - TYPE_CHECKING, - Callable, - Dict, - Literal, - Optional, - SupportsFloat, - Tuple, - Union, -) +from typing import TYPE_CHECKING, Callable, Literal, Optional, SupportsFloat, Union if TYPE_CHECKING: from typing import TypeAlias @@ -35,13 +26,13 @@ # Format codes for (int, float) sized types, used for byte-wise casts. # See https://docs.python.org/3/library/struct.html#format-characters -STRUCT_FORMATS: Dict[int, Tuple[UnsignedIntFormat, FloatFormat]] = { +STRUCT_FORMATS: dict[int, tuple[UnsignedIntFormat, FloatFormat]] = { 16: ("!H", "!e"), 32: ("!I", "!f"), 64: ("!Q", "!d"), } -TO_SIGNED_FORMAT: Dict[UnsignedIntFormat, SignedIntFormat] = { +TO_SIGNED_FORMAT: dict[UnsignedIntFormat, SignedIntFormat] = { "!H": "!h", "!I": "!i", "!Q": "!q", @@ -138,7 +129,7 @@ def next_up_normal(value: float, width: int, *, allow_subnormal: bool) -> float: # Smallest positive non-zero numbers that is fully representable by an # IEEE-754 float, calculated with the width's associated minimum exponent. # Values from https://en.wikipedia.org/wiki/IEEE_754#Basic_and_interchange_formats -width_smallest_normals: Dict[int, float] = { +width_smallest_normals: dict[int, float] = { 16: 2 ** -(2 ** (5 - 1) - 2), 32: 2 ** -(2 ** (8 - 1) - 2), 64: 2 ** -(2 ** (11 - 1) - 2), diff --git a/hypothesis-python/src/hypothesis/stateful.py b/hypothesis-python/src/hypothesis/stateful.py index 190d7076fd..7c60d2752f 100644 --- a/hypothesis-python/src/hypothesis/stateful.py +++ b/hypothesis-python/src/hypothesis/stateful.py @@ -17,22 +17,12 @@ """ import collections import inspect +from collections.abc import Iterable, Sequence from copy import copy from functools import lru_cache from io import StringIO from time import perf_counter -from typing import ( - Any, - Callable, - ClassVar, - Dict, - Iterable, - List, - Optional, - Sequence, - Union, - overload, -) +from typing import Any, Callable, ClassVar, Optional, Union, overload from unittest import TestCase import attr @@ -274,17 +264,17 @@ class RuleBasedStateMachine(metaclass=StateMachineMeta): At any given point a random applicable rule will be executed. """ - _rules_per_class: ClassVar[Dict[type, List[classmethod]]] = {} - _invariants_per_class: ClassVar[Dict[type, List[classmethod]]] = {} - _initializers_per_class: ClassVar[Dict[type, List[classmethod]]] = {} + _rules_per_class: ClassVar[dict[type, list[classmethod]]] = {} + _invariants_per_class: ClassVar[dict[type, list[classmethod]]] = {} + _initializers_per_class: ClassVar[dict[type, list[classmethod]]] = {} def __init__(self) -> None: if not self.rules(): raise InvalidDefinition(f"Type {type(self).__name__} defines no rules") - self.bundles: Dict[str, list] = {} + self.bundles: dict[str, list] = {} self.names_counters: collections.Counter = collections.Counter() self.names_list: list[str] = [] - self.names_to_values: Dict[str, Any] = {} + self.names_to_values: dict[str, Any] = {} self.__stream = StringIO() self.__printer = RepresentationPrinter( self.__stream, context=_current_build_context.value @@ -651,15 +641,15 @@ def _convert_targets(targets, target): # a `SearchStrategy`, which the concrete implementation does not accept. # # Omitted `targets` parameters, where the default value is used, are typed with -# a special `_OmittedArgument` type. We cannot type them as `Tuple[()]`, because -# `Tuple[()]` is a subtype of `Sequence[Bundle[Ex]]`, leading to signature +# a special `_OmittedArgument` type. We cannot type them as `tuple[()]`, because +# `tuple[()]` is a subtype of `Sequence[Bundle[Ex]]`, leading to signature # overlaps with incompatible return types. The `_OmittedArgument` type will never be # encountered at runtime, and exists solely to annotate the default of `targets`. # PEP 661 (Sentinel Values) might provide a more elegant alternative in the future. # -# We could've also annotated `targets` as `Tuple[_OmittedArgument]`, but then when +# We could've also annotated `targets` as `tuple[_OmittedArgument]`, but then when # both `target` and `targets` are provided, mypy describes the type error as an -# invalid argument type for `targets` (expected `Tuple[_OmittedArgument]`, got ...). +# invalid argument type for `targets` (expected `tuple[_OmittedArgument]`, got ...). # By annotating it as a bare `_OmittedArgument` type, mypy's error will warn that # there is no overloaded signature matching the call, which is more descriptive. # diff --git a/hypothesis-python/src/hypothesis/statistics.py b/hypothesis-python/src/hypothesis/statistics.py index bd3f4e3e30..cee3c2b9ef 100644 --- a/hypothesis-python/src/hypothesis/statistics.py +++ b/hypothesis-python/src/hypothesis/statistics.py @@ -10,7 +10,8 @@ import math from collections import Counter -from typing import TYPE_CHECKING, Dict, Iterable, List, cast +from collections.abc import Iterable +from typing import TYPE_CHECKING, cast from hypothesis._settings import Phase from hypothesis.utils.dynamicvariables import DynamicVariable @@ -27,7 +28,7 @@ def note_statistics(stats_dict: "StatisticsDict") -> None: callback(stats_dict) -def describe_targets(best_targets: Dict[str, float]) -> List[str]: +def describe_targets(best_targets: dict[str, float]) -> list[str]: """Return a list of lines describing the results of `target`, if any.""" # These lines are included in the general statistics description below, # but also printed immediately below failing examples to alleviate the diff --git a/hypothesis-python/src/hypothesis/strategies/_internal/collections.py b/hypothesis-python/src/hypothesis/strategies/_internal/collections.py index 5d43390630..e647ec07fb 100644 --- a/hypothesis-python/src/hypothesis/strategies/_internal/collections.py +++ b/hypothesis-python/src/hypothesis/strategies/_internal/collections.py @@ -9,7 +9,8 @@ # obtain one at https://mozilla.org/MPL/2.0/. import copy -from typing import Any, Iterable, Tuple, overload +from collections.abc import Iterable +from typing import Any, overload from hypothesis.errors import InvalidArgument from hypothesis.internal.conjecture import utils as cu @@ -64,26 +65,26 @@ def calc_is_empty(self, recur): @overload -def tuples() -> SearchStrategy[Tuple[()]]: # pragma: no cover +def tuples() -> SearchStrategy[tuple[()]]: # pragma: no cover ... @overload -def tuples(__a1: SearchStrategy[Ex]) -> SearchStrategy[Tuple[Ex]]: # pragma: no cover +def tuples(__a1: SearchStrategy[Ex]) -> SearchStrategy[tuple[Ex]]: # pragma: no cover ... @overload def tuples( __a1: SearchStrategy[Ex], __a2: SearchStrategy[T] -) -> SearchStrategy[Tuple[Ex, T]]: # pragma: no cover +) -> SearchStrategy[tuple[Ex, T]]: # pragma: no cover ... @overload def tuples( __a1: SearchStrategy[Ex], __a2: SearchStrategy[T], __a3: SearchStrategy[T3] -) -> SearchStrategy[Tuple[Ex, T, T3]]: # pragma: no cover +) -> SearchStrategy[tuple[Ex, T, T3]]: # pragma: no cover ... @@ -93,7 +94,7 @@ def tuples( __a2: SearchStrategy[T], __a3: SearchStrategy[T3], __a4: SearchStrategy[T4], -) -> SearchStrategy[Tuple[Ex, T, T3, T4]]: # pragma: no cover +) -> SearchStrategy[tuple[Ex, T, T3, T4]]: # pragma: no cover ... @@ -104,20 +105,20 @@ def tuples( __a3: SearchStrategy[T3], __a4: SearchStrategy[T4], __a5: SearchStrategy[T5], -) -> SearchStrategy[Tuple[Ex, T, T3, T4, T5]]: # pragma: no cover +) -> SearchStrategy[tuple[Ex, T, T3, T4, T5]]: # pragma: no cover ... @overload def tuples( *args: SearchStrategy[Any], -) -> SearchStrategy[Tuple[Any, ...]]: # pragma: no cover +) -> SearchStrategy[tuple[Any, ...]]: # pragma: no cover ... @cacheable @defines_strategy() -def tuples(*args: SearchStrategy[Any]) -> SearchStrategy[Tuple[Any, ...]]: +def tuples(*args: SearchStrategy[Any]) -> SearchStrategy[tuple[Any, ...]]: """Return a strategy which generates a tuple of the same length as args by generating the value at index i from args[i]. diff --git a/hypothesis-python/src/hypothesis/strategies/_internal/core.py b/hypothesis-python/src/hypothesis/strategies/_internal/core.py index b26e9f722a..e652116ed5 100644 --- a/hypothesis-python/src/hypothesis/strategies/_internal/core.py +++ b/hypothesis-python/src/hypothesis/strategies/_internal/core.py @@ -27,6 +27,7 @@ from re import Pattern from types import FunctionType, GenericAlias from typing import ( + Annotated, Any, AnyStr, Callable, @@ -1360,7 +1361,7 @@ def _get_typeddict_qualifiers(key, annotation_type): qualifiers = [] while True: annotation_origin = types.extended_get_origin(annotation_type) - if annotation_origin in types.AnnotatedTypes: + if annotation_origin is Annotated: if annotation_args := get_args(annotation_type): annotation_type = annotation_args[0] else: @@ -1793,7 +1794,7 @@ class DrawFn(Protocol): .. code-block:: python @composite - def list_and_index(draw: DrawFn) -> Tuple[int, str]: + def list_and_index(draw: DrawFn) -> tuple[int, str]: i = draw(integers()) # type inferred as 'int' s = draw(text()) # type inferred as 'str' return i, s diff --git a/hypothesis-python/src/hypothesis/strategies/_internal/lazy.py b/hypothesis-python/src/hypothesis/strategies/_internal/lazy.py index 8f887293e6..6cb582c5e0 100644 --- a/hypothesis-python/src/hypothesis/strategies/_internal/lazy.py +++ b/hypothesis-python/src/hypothesis/strategies/_internal/lazy.py @@ -8,8 +8,8 @@ # v. 2.0. If a copy of the MPL was not distributed with this file, You can # obtain one at https://mozilla.org/MPL/2.0/. +from collections.abc import MutableMapping from inspect import signature -from typing import MutableMapping from weakref import WeakKeyDictionary from hypothesis.configuration import check_sideeffect_during_initialization diff --git a/hypothesis-python/src/hypothesis/strategies/_internal/random.py b/hypothesis-python/src/hypothesis/strategies/_internal/random.py index 30de91e234..0e87459443 100644 --- a/hypothesis-python/src/hypothesis/strategies/_internal/random.py +++ b/hypothesis-python/src/hypothesis/strategies/_internal/random.py @@ -11,7 +11,7 @@ import inspect import math from random import Random -from typing import Any, Dict +from typing import Any import attr @@ -110,7 +110,7 @@ def _randbelow(self, n: int) -> int: # type: ignore STUBS = {f.__name__: f for f in [getrandbits, random, _randbelow]} -SIGNATURES: Dict[str, inspect.Signature] = {} +SIGNATURES: dict[str, inspect.Signature] = {} def sig_of(name): diff --git a/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py b/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py index dc7a129d06..c040f748a5 100644 --- a/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py +++ b/hypothesis-python/src/hypothesis/strategies/_internal/strategies.py @@ -11,6 +11,7 @@ import sys import warnings from collections import abc, defaultdict +from collections.abc import Sequence from functools import lru_cache from random import shuffle from typing import ( @@ -18,10 +19,7 @@ Any, Callable, ClassVar, - Dict, Generic, - List, - Sequence, TypeVar, Union, cast, @@ -327,7 +325,7 @@ def example(self) -> Ex: try: return self.__examples.pop() except (AttributeError, IndexError): - self.__examples: List[Ex] = [] + self.__examples: list[Ex] = [] from hypothesis.core import given @@ -395,7 +393,7 @@ def _filter_for_filtered_draw(self, condition): return FilteredStrategy(conditions=(condition,), strategy=self) @property - def branches(self) -> List["SearchStrategy[Ex]"]: + def branches(self) -> list["SearchStrategy[Ex]"]: return [self] def __or__(self, other: "SearchStrategy[T]") -> "SearchStrategy[Union[Ex, T]]": @@ -432,7 +430,7 @@ def validate(self) -> None: self.validate_called = False raise - LABELS: ClassVar[Dict[type, int]] = {} + LABELS: ClassVar[dict[type, int]] = {} @property def class_label(self): @@ -850,7 +848,7 @@ def do_draw(self, data: ConjectureData) -> Any: raise UnsatisfiedAssumption @property - def branches(self) -> List[SearchStrategy[Ex]]: + def branches(self) -> list[SearchStrategy[Ex]]: return [ MappedStrategy(strategy, pack=self.pack) for strategy in self.mapped_strategy.branches @@ -1025,7 +1023,7 @@ def do_filtered_draw(self, data): return filter_not_satisfied @property - def branches(self) -> List[SearchStrategy[Ex]]: + def branches(self) -> list[SearchStrategy[Ex]]: return [ FilteredStrategy(strategy=strategy, conditions=self.flat_conditions) for strategy in self.filtered_strategy.branches diff --git a/hypothesis-python/src/hypothesis/strategies/_internal/types.py b/hypothesis-python/src/hypothesis/strategies/_internal/types.py index 6d14b2e516..6dea780c95 100644 --- a/hypothesis-python/src/hypothesis/strategies/_internal/types.py +++ b/hypothesis-python/src/hypothesis/strategies/_internal/types.py @@ -73,28 +73,6 @@ except ImportError: _AnnotatedAlias = () -TypeAliasTypes: tuple = () -try: - TypeAliasTypes += (typing.TypeAlias,) -except AttributeError: # pragma: no cover - pass # Is missing for `python<3.10` -try: - TypeAliasTypes += (typing_extensions.TypeAlias,) -except AttributeError: # pragma: no cover - pass # Is missing for `typing_extensions<3.10` - -ClassVarTypes: tuple = (typing.ClassVar,) -try: - ClassVarTypes += (typing_extensions.ClassVar,) -except AttributeError: # pragma: no cover - pass # `typing_extensions` might not be installed - -FinalTypes: tuple = (typing.Final,) -try: - FinalTypes += (typing_extensions.Final,) -except AttributeError: # pragma: no cover - pass # `typing_extensions` might not be installed - ConcatenateTypes: tuple = () try: ConcatenateTypes += (typing.Concatenate,) @@ -163,13 +141,6 @@ pass # `typing_extensions` might not be installed -AnnotatedTypes: tuple = (typing.Annotated,) -try: - AnnotatedTypes += (typing_extensions.Annotated,) -except AttributeError: # pragma: no cover - pass # `typing_extensions` might not be installed - - LiteralStringTypes: tuple = () try: LiteralStringTypes += (typing.LiteralString,) # type: ignore @@ -206,21 +177,21 @@ # `Final` is a great example: it just indicates that this value can't be reassigned. NON_RUNTIME_TYPES = ( typing.Any, - *ClassVarTypes, - *TypeAliasTypes, - *FinalTypes, + typing.Annotated, *ConcatenateTypes, *ParamSpecTypes, *TypeGuardTypes, ) for name in ( - "Annotated", + "ClassVar", + "Final", "NoReturn", "Self", "Required", "NotRequired", "ReadOnly", "Never", + "TypeAlias", "TypeVarTuple", "Unpack", ): diff --git a/hypothesis-python/src/hypothesis/strategies/_internal/utils.py b/hypothesis-python/src/hypothesis/strategies/_internal/utils.py index d60eabea9b..8fb6ff7e72 100644 --- a/hypothesis-python/src/hypothesis/strategies/_internal/utils.py +++ b/hypothesis-python/src/hypothesis/strategies/_internal/utils.py @@ -11,7 +11,7 @@ import sys import threading from inspect import signature -from typing import TYPE_CHECKING, Callable, Dict +from typing import TYPE_CHECKING, Callable import attr @@ -25,7 +25,7 @@ if TYPE_CHECKING: from hypothesis.strategies._internal.strategies import SearchStrategy, T -_strategies: Dict[str, Callable[..., "SearchStrategy"]] = {} +_strategies: dict[str, Callable[..., "SearchStrategy"]] = {} class FloatKey: diff --git a/hypothesis-python/src/hypothesis/utils/dynamicvariables.py b/hypothesis-python/src/hypothesis/utils/dynamicvariables.py index cb823628b2..11b5b89958 100644 --- a/hypothesis-python/src/hypothesis/utils/dynamicvariables.py +++ b/hypothesis-python/src/hypothesis/utils/dynamicvariables.py @@ -9,8 +9,9 @@ # obtain one at https://mozilla.org/MPL/2.0/. import threading +from collections.abc import Generator from contextlib import contextmanager -from typing import Generator, Generic, TypeVar +from typing import Generic, TypeVar T = TypeVar("T") diff --git a/hypothesis-python/tests/array_api/conftest.py b/hypothesis-python/tests/array_api/conftest.py index 128f357fb9..f9b29290c8 100644 --- a/hypothesis-python/tests/array_api/conftest.py +++ b/hypothesis-python/tests/array_api/conftest.py @@ -12,7 +12,6 @@ from importlib import import_module from os import getenv from types import ModuleType, SimpleNamespace -from typing import List, Tuple import pytest @@ -47,7 +46,7 @@ class InvalidArgumentWarning(UserWarning): name_to_entry_point = installed_array_modules() -xp_and_xps_pairs: List[Tuple[ModuleType, SimpleNamespace]] = [] +xp_and_xps_pairs: list[tuple[ModuleType, SimpleNamespace]] = [] with warnings.catch_warnings(): # We ignore all warnings here as many array modules warn on import. Ideally # we would just ignore ImportWarning, but no one seems to use it! diff --git a/hypothesis-python/tests/array_api/test_partial_adoptors.py b/hypothesis-python/tests/array_api/test_partial_adoptors.py index 7e6531e46d..186b7a82f1 100644 --- a/hypothesis-python/tests/array_api/test_partial_adoptors.py +++ b/hypothesis-python/tests/array_api/test_partial_adoptors.py @@ -12,7 +12,6 @@ import warnings from copy import copy from types import SimpleNamespace -from typing import Tuple import pytest @@ -45,7 +44,7 @@ def __getattr__(self, name): return object.__getattr__(self, name) -def wrap_array(func: callable, exclude: Tuple[str, ...] = ()) -> callable: +def wrap_array(func: callable, exclude: tuple[str, ...] = ()) -> callable: @functools.wraps(func) def wrapped(*args, **kwargs): result = func(*args, **kwargs) @@ -59,7 +58,7 @@ def wrapped(*args, **kwargs): def make_mock_xp( - *, exclude: Tuple[str, ...] = (), exclude_methods: Tuple[str, ...] = () + *, exclude: tuple[str, ...] = (), exclude_methods: tuple[str, ...] = () ) -> SimpleNamespace: xp = copy(mock_xp) assert isinstance(exclude, tuple) # sanity check diff --git a/hypothesis-python/tests/common/utils.py b/hypothesis-python/tests/common/utils.py index 521ecca41e..6b70b254ff 100644 --- a/hypothesis-python/tests/common/utils.py +++ b/hypothesis-python/tests/common/utils.py @@ -214,8 +214,8 @@ def temp_registered(type_, strat_or_factory): previously-registered strategy which we got wrong in a few places. """ prev = _global_type_lookup.get(type_) + register_type_strategy(type_, strat_or_factory) try: - register_type_strategy(type_, strat_or_factory) yield finally: del _global_type_lookup[type_] diff --git a/hypothesis-python/tests/conjecture/test_alt_backend.py b/hypothesis-python/tests/conjecture/test_alt_backend.py index 805029ad56..dd9edfe809 100644 --- a/hypothesis-python/tests/conjecture/test_alt_backend.py +++ b/hypothesis-python/tests/conjecture/test_alt_backend.py @@ -10,9 +10,10 @@ import math import sys +from collections.abc import Sequence from contextlib import contextmanager from random import Random -from typing import Optional, Sequence +from typing import Optional import pytest diff --git a/hypothesis-python/tests/cover/test_attrs_inference.py b/hypothesis-python/tests/cover/test_attrs_inference.py index 4f5d2524c9..b62b12e00b 100644 --- a/hypothesis-python/tests/cover/test_attrs_inference.py +++ b/hypothesis-python/tests/cover/test_attrs_inference.py @@ -50,9 +50,9 @@ class Inferrables: validator=[attr.validators.in_("abcd"), attr.validators.in_(["ab", "cd"])] ) - typing_list = attr.ib(type=typing.List[int]) - typing_list_of_list = attr.ib(type=typing.List[typing.List[int]]) - typing_dict = attr.ib(type=typing.Dict[str, int]) + typing_list = attr.ib(type=list[int]) + typing_list_of_list = attr.ib(type=list[list[int]]) + typing_dict = attr.ib(type=dict[str, int]) typing_optional = attr.ib(type=typing.Optional[bool]) typing_union = attr.ib(type=typing.Union[str, int]) diff --git a/hypothesis-python/tests/cover/test_database_backend.py b/hypothesis-python/tests/cover/test_database_backend.py index 19d33d2df1..53b56d49e0 100644 --- a/hypothesis-python/tests/cover/test_database_backend.py +++ b/hypothesis-python/tests/cover/test_database_backend.py @@ -12,11 +12,12 @@ import re import tempfile import zipfile +from collections.abc import Iterator from contextlib import contextmanager, nullcontext from datetime import datetime, timedelta, timezone from pathlib import Path from shutil import make_archive, rmtree -from typing import Iterator, Optional, Tuple +from typing import Optional import pytest @@ -188,7 +189,7 @@ def test_ga_require_readonly_wrapping(): @contextmanager def ga_empty_artifact( date: Optional[datetime] = None, path: Optional[Path] = None -) -> Iterator[Tuple[Path, Path]]: +) -> Iterator[tuple[Path, Path]]: """Creates an empty GitHub artifact.""" if date: timestamp = date.isoformat().replace(":", "_") diff --git a/hypothesis-python/tests/cover/test_health_checks.py b/hypothesis-python/tests/cover/test_health_checks.py index 4133b6d1e7..3d0f04e536 100644 --- a/hypothesis-python/tests/cover/test_health_checks.py +++ b/hypothesis-python/tests/cover/test_health_checks.py @@ -64,6 +64,7 @@ def test(x): test() +@pytest.mark.skipif(settings._current_profile == "crosshair", reason="nondeterministic") def test_suppressing_filtering_health_check(): forbidden = set() diff --git a/hypothesis-python/tests/cover/test_lookup.py b/hypothesis-python/tests/cover/test_lookup.py index d1a42d86b3..9994c02ed3 100644 --- a/hypothesis-python/tests/cover/test_lookup.py +++ b/hypothesis-python/tests/cover/test_lookup.py @@ -25,6 +25,14 @@ from dataclasses import dataclass from inspect import signature from numbers import Real +from typing import ( + Dict as _Dict, + FrozenSet as _FrozenSet, + List as _List, + Set as _Set, + Tuple as _Tuple, + Type as _Type, +) import pytest @@ -66,12 +74,6 @@ ), key=str, ) -_Type = getattr(typing, "Type", None) -_List = getattr(typing, "List", None) -_Dict = getattr(typing, "Dict", None) -_Set = getattr(typing, "Set", None) -_FrozenSet = getattr(typing, "FrozenSet", None) -_Tuple = getattr(typing, "Tuple", None) @pytest.mark.parametrize("typ", generics, ids=repr) diff --git a/hypothesis-python/tests/cover/test_lookup_py39.py b/hypothesis-python/tests/cover/test_lookup_py39.py index 35bf803573..3181850c8e 100644 --- a/hypothesis-python/tests/cover/test_lookup_py39.py +++ b/hypothesis-python/tests/cover/test_lookup_py39.py @@ -30,12 +30,10 @@ "annotated_type,expected_strategy_repr", [ (typing.Annotated[int, "foo"], "integers()"), - (typing.Annotated[typing.List[float], "foo"], "lists(floats())"), + (typing.Annotated[list[float], "foo"], "lists(floats())"), (typing.Annotated[typing.Annotated[str, "foo"], "bar"], "text()"), ( - typing.Annotated[ - typing.Annotated[typing.List[typing.Dict[str, bool]], "foo"], "bar" - ], + typing.Annotated[typing.Annotated[list[dict[str, bool]], "foo"], "bar"], "lists(dictionaries(keys=text(), values=booleans()))", ), ], @@ -101,7 +99,7 @@ def test_issue_3080(): @dataclasses.dataclass class TypingTuple: - a: dict[typing.Tuple[int, int], str] + a: dict[tuple[int, int], str] @dataclasses.dataclass diff --git a/hypothesis-python/tests/cover/test_type_lookup.py b/hypothesis-python/tests/cover/test_type_lookup.py index 2b731b1e75..9d239496ef 100644 --- a/hypothesis-python/tests/cover/test_type_lookup.py +++ b/hypothesis-python/tests/cover/test_type_lookup.py @@ -11,8 +11,10 @@ import abc import enum import sys +import typing +from collections.abc import Sequence from inspect import Parameter as P, Signature -from typing import Callable, Dict, Generic, List, Sequence, TypeVar, Union +from typing import Callable, Generic, List as _List, TypeVar, Union import pytest @@ -279,7 +281,7 @@ class Lines(Sequence[str]): """ -class SpecificDict(Dict[int, int]): +class SpecificDict(dict[int, int]): pass @@ -308,10 +310,10 @@ def test_issue_2951_regression(): def test_issue_2951_regression_two_params(): map_strat = st.builds(SpecificDict, st.dictionaries(st.integers(), st.integers())) - expected = repr(st.from_type(Dict[int, int])) + expected = repr(st.from_type(dict[int, int])) with temp_registered(SpecificDict, map_strat): assert st.from_type(SpecificDict) == map_strat - assert expected == repr(st.from_type(Dict[int, int])) + assert expected == repr(st.from_type(dict[int, int])) @pytest.mark.parametrize( @@ -332,15 +334,20 @@ def test_generic_origin_with_type_args(generic, strategy): assert generic not in types._global_type_lookup +skip_39 = pytest.mark.skipif(sys.version_info[:2] == (3, 9), reason="early version") + + @pytest.mark.parametrize( "generic", ( Callable, - List, + list, Sequence, # you can register types with all generic parameters - List[T], - Sequence[T], + _List[T], + getattr(typing, "Sequence", None)[T], # pyupgrade workaround + pytest.param(list[T], marks=skip_39), + pytest.param(Sequence[T], marks=skip_39), # User-defined generics should also work MyGeneric, MyGeneric[T], diff --git a/hypothesis-python/tests/nocover/test_build_signature.py b/hypothesis-python/tests/nocover/test_build_signature.py index ae5f3740fc..348a4daf20 100644 --- a/hypothesis-python/tests/nocover/test_build_signature.py +++ b/hypothesis-python/tests/nocover/test_build_signature.py @@ -9,7 +9,7 @@ # obtain one at https://mozilla.org/MPL/2.0/. from inspect import signature -from typing import List, Optional, get_type_hints +from typing import Optional, get_type_hints from hypothesis import given, strategies as st @@ -63,7 +63,7 @@ def use_annotations( def use_signature( - self, testA: int, testB: Optional[str] = None, *, testX: float, testY: List[str] + self, testA: int, testB: Optional[str] = None, *, testX: float, testY: list[str] ): pass diff --git a/hypothesis-python/tests/nocover/test_drypython_returns.py b/hypothesis-python/tests/nocover/test_drypython_returns.py index 6c1ce3e0a5..3e1d8a703f 100644 --- a/hypothesis-python/tests/nocover/test_drypython_returns.py +++ b/hypothesis-python/tests/nocover/test_drypython_returns.py @@ -178,8 +178,9 @@ def mixed_generic_func2(obj: _SecondBase[float, D]): ], ) def test_several_generic_bases_functions(type_, func): - with temp_registered(_FirstBase, st.builds(type_)), temp_registered( - _SecondBase, st.builds(type_) + with ( + temp_registered(_FirstBase, st.builds(type_)), + temp_registered(_SecondBase, st.builds(type_)), ): find_any(st.builds(func)) diff --git a/hypothesis-python/tests/nocover/test_type_lookup_forward_ref.py b/hypothesis-python/tests/nocover/test_type_lookup_forward_ref.py index ab48ad6a31..2c9638800f 100644 --- a/hypothesis-python/tests/nocover/test_type_lookup_forward_ref.py +++ b/hypothesis-python/tests/nocover/test_type_lookup_forward_ref.py @@ -8,7 +8,7 @@ # v. 2.0. If a copy of the MPL was not distributed with this file, You can # obtain one at https://mozilla.org/MPL/2.0/. -from typing import Dict, ForwardRef, List, Union +from typing import Dict as _Dict, ForwardRef, Union import pytest @@ -24,8 +24,8 @@ @given(st.data()) def test_mutually_recursive_types_with_typevar(data): # The previously-failing example from the issue - A = Dict[bool, "B"] - B = Union[List[bool], A] + A = _Dict[bool, "B"] + B = Union[list[bool], A] with pytest.raises(ResolutionFailed, match=r"Could not resolve ForwardRef\('B'\)"): data.draw(st.from_type(A)) @@ -44,8 +44,8 @@ def test_mutually_recursive_types_with_typevar(data): def test_mutually_recursive_types_with_typevar_alternate(data): # It's not particularly clear why this version passed when the previous # test failed, but different behaviour means we add both to the suite. - C = Union[List[bool], "D"] - D = Dict[bool, C] + C = Union[list[bool], "D"] + D = dict[bool, C] with pytest.raises(ResolutionFailed, match=r"Could not resolve ForwardRef\('D'\)"): data.draw(st.from_type(C)) diff --git a/hypothesis-python/tests/typing_extensions/test_backported_types.py b/hypothesis-python/tests/typing_extensions/test_backported_types.py index ab7c723f81..9e09b29de4 100644 --- a/hypothesis-python/tests/typing_extensions/test_backported_types.py +++ b/hypothesis-python/tests/typing_extensions/test_backported_types.py @@ -9,12 +9,11 @@ # obtain one at https://mozilla.org/MPL/2.0/. import collections -from typing import Callable, DefaultDict, Dict, List, NewType, Type, Union +from typing import Annotated, Callable, DefaultDict, NewType, Union import pytest import typing_extensions from typing_extensions import ( - Annotated, Concatenate, LiteralString, NotRequired, @@ -78,10 +77,10 @@ def test_simple_typeddict(value): def test_typing_extensions_Type_int(): - assert_simple_property(from_type(Type[int]), lambda v: v is int) + assert_simple_property(from_type(type[int]), lambda v: v is int) -@given(from_type(Union[Type[str], Type[list]])) +@given(from_type(Union[type[str], type[list]])) def test_typing_extensions_Type_Union(ex): assert ex in (str, list) @@ -105,56 +104,6 @@ def test_defaultdict(ex): assert all(isinstance(elem, int) for elem in ex.values()) -@pytest.mark.parametrize( - "annotated_type,expected_strategy_repr", - [ - (Annotated[int, "foo"], "integers()"), - (Annotated[List[float], "foo"], "lists(floats())"), - (Annotated[Annotated[str, "foo"], "bar"], "text()"), - ( - Annotated[Annotated[List[Dict[str, bool]], "foo"], "bar"], - "lists(dictionaries(keys=text(), values=booleans()))", - ), - ], -) -def test_typing_extensions_Annotated(annotated_type, expected_strategy_repr): - assert repr(st.from_type(annotated_type)) == expected_strategy_repr - - -PositiveInt = Annotated[int, st.integers(min_value=1)] -MoreThenTenInt = Annotated[PositiveInt, st.integers(min_value=10 + 1)] -WithTwoStrategies = Annotated[int, st.integers(), st.none()] -ExtraAnnotationNoStrategy = Annotated[PositiveInt, "metadata"] - - -def arg_positive(x: PositiveInt): - assert x > 0 - - -def arg_more_than_ten(x: MoreThenTenInt): - assert x > 10 - - -@given(st.data()) -def test_annotated_positive_int(data): - data.draw(st.builds(arg_positive)) - - -@given(st.data()) -def test_annotated_more_than_ten(data): - data.draw(st.builds(arg_more_than_ten)) - - -@given(st.data()) -def test_annotated_with_two_strategies(data): - assert data.draw(st.from_type(WithTwoStrategies)) is None - - -@given(st.data()) -def test_annotated_extra_metadata(data): - assert data.draw(st.from_type(ExtraAnnotationNoStrategy)) > 0 - - @pytest.mark.parametrize("non_runtime_type", NON_RUNTIME_TYPES) def test_non_runtime_type_cannot_be_resolved(non_runtime_type): strategy = st.from_type(non_runtime_type) diff --git a/website/content/2017-07-16-types-and-properties.md b/website/content/2017-07-16-types-and-properties.md index 509db2cbe5..7aa25e1249 100644 --- a/website/content/2017-07-16-types-and-properties.md +++ b/website/content/2017-07-16-types-and-properties.md @@ -58,13 +58,12 @@ Consider writing this code based on types instead: ```python from statistics import mean -from typing import List from hypothesis import given, strategies as st @given(ls=...) -def test_mean_is_in_bounds(ls: List[float]): +def test_mean_is_in_bounds(ls: list[float]): assert min(ls) <= mean(ls) <= max(ls) ``` @@ -79,13 +78,12 @@ we have to add a precondition to make the test valid: ```python import math from statistics import mean -from typing import List from hypothesis import assume, given, strategies as st @given(ls=...) -def test_mean_is_in_bounds(ls: List[float]): +def test_mean_is_in_bounds(ls: list[float]): assume(len(ls) > 1) assume(all(math.isfinite(x) for x in ls)) assert min(ls) <= mean(ls) <= max(ls) diff --git a/whole_repo_tests/revealed_types.py b/whole_repo_tests/revealed_types.py index c78f3da6bc..08fa706afc 100644 --- a/whole_repo_tests/revealed_types.py +++ b/whole_repo_tests/revealed_types.py @@ -20,16 +20,16 @@ ("text()", "str"), ("integers().map(str)", "str"), ("booleans().filter(bool)", "bool"), - ("tuples()", "Tuple[()]"), - ("tuples(integers())", "Tuple[int]"), - ("tuples(integers(), text())", "Tuple[int, str]"), + ("tuples()", "tuple[()]"), + ("tuples(integers())", "tuple[int]"), + ("tuples(integers(), text())", "tuple[int, str]"), ( "tuples(integers(), text(), integers(), text(), integers())", - "Tuple[int, str, int, str, int]", + "tuple[int, str, int, str, int]", ), ( "tuples(text(), text(), text(), text(), text(), text())", - "Tuple[Any, ...]", + "tuple[Any, ...]", ), ] @@ -140,14 +140,14 @@ ), ( "integer_array_indices(shape=(2, 3))", - "Tuple[ndarray[Any, dtype[signedinteger[Any]]], ...]", + "tuple[ndarray[Any, dtype[signedinteger[Any]]], ...]", ), ( 'integer_array_indices(shape=(2, 3), dtype=np.dtype("int32"))', - "Tuple[ndarray[Any, dtype[signedinteger[_32Bit]]], ...]", + "tuple[ndarray[Any, dtype[signedinteger[_32Bit]]], ...]", ), ( 'integer_array_indices(shape=(2, 3), dtype=np.dtype("uint8"))', - "Tuple[ndarray[Any, dtype[unsignedinteger[_8Bit]]], ...]", + "tuple[ndarray[Any, dtype[unsignedinteger[_8Bit]]], ...]", ), ] diff --git a/whole_repo_tests/test_mypy.py b/whole_repo_tests/test_mypy.py index 0616fce557..8022c3f32b 100644 --- a/whole_repo_tests/test_mypy.py +++ b/whole_repo_tests/test_mypy.py @@ -63,7 +63,6 @@ def get_mypy_analysed_type(fname): ) .replace("numpy._typing.", "") .replace("numpy.", "") - .replace("tuple", "Tuple") .replace("List[", "list[") .replace("Dict[", "dict[") )