diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a2ca42b1bd7b..306f581fb530 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -26,7 +26,7 @@ jobs: steps: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 - - run: ./tests/check_pep_604.py + - run: ./tests/check_new_syntax.py flake8: name: Lint with flake8 diff --git a/stdlib/multiprocessing/pool.pyi b/stdlib/multiprocessing/pool.pyi index 20cfc59633d5..5eaf0562bfc3 100644 --- a/stdlib/multiprocessing/pool.pyi +++ b/stdlib/multiprocessing/pool.pyi @@ -1,6 +1,6 @@ import sys from _typeshed import Self -from typing import Any, Callable, ContextManager, Dict, Generic, Iterable, Iterator, List, Mapping, TypeVar +from typing import Any, Callable, ContextManager, Generic, Iterable, Iterator, List, Mapping, TypeVar if sys.version_info >= (3, 9): from types import GenericAlias @@ -17,7 +17,7 @@ class ApplyResult(Generic[_T]): else: def __init__( self, - cache: Dict[int, ApplyResult[Any]], + cache: dict[int, ApplyResult[Any]], callback: Callable[[_T], None] | None, error_callback: Callable[[BaseException], None] | None, ) -> None: ... @@ -44,7 +44,7 @@ class MapResult(ApplyResult[List[_T]]): else: def __init__( self, - cache: Dict[int, ApplyResult[Any]], + cache: dict[int, ApplyResult[Any]], chunksize: int, length: int, callback: Callable[[List[_T]], None] | None, @@ -55,7 +55,7 @@ class IMapIterator(Iterator[_T]): if sys.version_info >= (3, 8): def __init__(self, pool: Pool) -> None: ... else: - def __init__(self, cache: Dict[int, IMapIterator[Any]]) -> None: ... + def __init__(self, cache: dict[int, IMapIterator[Any]]) -> None: ... def __iter__(self: _S) -> _S: ... def next(self, timeout: float | None = ...) -> _T: ... def __next__(self, timeout: float | None = ...) -> _T: ... diff --git a/stdlib/plistlib.pyi b/stdlib/plistlib.pyi index 93d4fdc2480a..07b6963746be 100644 --- a/stdlib/plistlib.pyi +++ b/stdlib/plistlib.pyi @@ -1,7 +1,7 @@ import sys from datetime import datetime from enum import Enum -from typing import IO, Any, Dict as _Dict, List, Mapping, MutableMapping, Tuple, Type +from typing import IO, Any, Dict as _Dict, Mapping, MutableMapping, Tuple, Type class PlistFormat(Enum): FMT_XML: int @@ -31,7 +31,7 @@ else: ) -> Any: ... def dump( - value: Mapping[str, Any] | List[Any] | Tuple[Any, ...] | str | bool | float | bytes | datetime, + value: Mapping[str, Any] | list[Any] | Tuple[Any, ...] | str | bool | float | bytes | datetime, fp: IO[bytes], *, fmt: PlistFormat = ..., @@ -39,7 +39,7 @@ def dump( skipkeys: bool = ..., ) -> None: ... def dumps( - value: Mapping[str, Any] | List[Any] | Tuple[Any, ...] | str | bool | float | bytes | datetime, + value: Mapping[str, Any] | list[Any] | Tuple[Any, ...] | str | bool | float | bytes | datetime, *, fmt: PlistFormat = ..., skipkeys: bool = ..., diff --git a/stubs/beautifulsoup4/bs4/element.pyi b/stubs/beautifulsoup4/bs4/element.pyi index 8dada6ceac1a..24c6e7a896ac 100644 --- a/stubs/beautifulsoup4/bs4/element.pyi +++ b/stubs/beautifulsoup4/bs4/element.pyi @@ -235,7 +235,7 @@ class Tag(PageElement): sourcepos: int | None known_xml: bool | None attrs: Mapping[str, str] - contents: List[PageElement] + contents: list[PageElement] hidden: bool can_be_empty_element: bool | None cdata_list_attributes: list[str] | None diff --git a/stubs/dateparser/dateparser/languages/loader.pyi b/stubs/dateparser/dateparser/languages/loader.pyi index 431979be4f02..8eaa38c77b08 100644 --- a/stubs/dateparser/dateparser/languages/loader.pyi +++ b/stubs/dateparser/dateparser/languages/loader.pyi @@ -1,5 +1,5 @@ from collections import OrderedDict -from typing import Any, Iterator, List +from typing import Any, Iterator from .locale import Locale @@ -8,16 +8,16 @@ LOCALE_SPLIT_PATTERN: Any class LocaleDataLoader: def get_locale_map( self, - languages: List[str] | None = ..., - locales: List[str] | None = ..., + languages: list[str] | None = ..., + locales: list[str] | None = ..., region: str | None = ..., use_given_order: bool = ..., allow_conflicting_locales: bool = ..., - ) -> OrderedDict[str, List[Any] | str | int]: ... + ) -> OrderedDict[str, list[Any] | str | int]: ... def get_locales( self, - languages: List[str] | None = ..., - locales: List[str] | None = ..., + languages: list[str] | None = ..., + locales: list[str] | None = ..., region: str | None = ..., use_given_order: bool = ..., allow_conflicting_locales: bool = ..., diff --git a/stubs/dateparser/dateparser/search/__init__.pyi b/stubs/dateparser/dateparser/search/__init__.pyi index e75ed92a6c5f..9a15ace9dce0 100644 --- a/stubs/dateparser/dateparser/search/__init__.pyi +++ b/stubs/dateparser/dateparser/search/__init__.pyi @@ -1,6 +1,6 @@ import sys from datetime import datetime -from typing import Any, List, Mapping, Set, Tuple, overload +from typing import Any, Mapping, Set, Tuple, overload if sys.version_info >= (3, 8): from typing import Literal @@ -10,14 +10,14 @@ else: @overload def search_dates( text: str, - languages: List[str] | Tuple[str] | Set[str] | None, + languages: list[str] | Tuple[str] | Set[str] | None, settings: Mapping[Any, Any] | None, add_detected_language: Literal[True], -) -> List[Tuple[str, datetime, str]]: ... +) -> list[Tuple[str, datetime, str]]: ... @overload def search_dates( text: str, - languages: List[str] | Tuple[str] | Set[str] | None = ..., + languages: list[str] | Tuple[str] | Set[str] | None = ..., settings: Mapping[Any, Any] | None = ..., add_detected_language: Literal[False] = ..., -) -> List[Tuple[str, datetime]]: ... +) -> list[Tuple[str, datetime]]: ... diff --git a/stubs/entrypoints/entrypoints.pyi b/stubs/entrypoints/entrypoints.pyi index 444d6cbc9587..6301b93ed8da 100644 --- a/stubs/entrypoints/entrypoints.pyi +++ b/stubs/entrypoints/entrypoints.pyi @@ -1,6 +1,6 @@ import sys from _typeshed import Self -from typing import Any, Dict, Iterator, List, Sequence, Text, Tuple, Type +from typing import Any, Iterator, Sequence, Text, Tuple, Type if sys.version_info >= (3, 0): from configparser import ConfigParser @@ -53,5 +53,5 @@ def iter_files_distros( path: Sequence[Text] | None = ..., repeated_distro: Text = ... ) -> Iterator[Tuple[ConfigParser, Distribution | None]]: ... def get_single(group: Text, name: Text, path: Sequence[Text] | None = ...) -> EntryPoint: ... -def get_group_named(group: Text, path: Sequence[Text] | None = ...) -> Dict[str, EntryPoint]: ... -def get_group_all(group: Text, path: Sequence[Text] | None = ...) -> List[EntryPoint]: ... +def get_group_named(group: Text, path: Sequence[Text] | None = ...) -> dict[str, EntryPoint]: ... +def get_group_all(group: Text, path: Sequence[Text] | None = ...) -> list[EntryPoint]: ... diff --git a/tests/check_pep_604.py b/tests/check_new_syntax.py similarity index 57% rename from tests/check_pep_604.py rename to tests/check_new_syntax.py index 3cf19f532b9d..278f91cb8929 100755 --- a/tests/check_pep_604.py +++ b/tests/check_new_syntax.py @@ -6,47 +6,44 @@ from pathlib import Path -def check_pep_604(tree: ast.AST, path: Path) -> list[str]: +def check_new_syntax(tree: ast.AST, path: Path) -> list[str]: errors = [] - class UnionFinder(ast.NodeVisitor): + class OldSyntaxFinder(ast.NodeVisitor): def visit_Subscript(self, node: ast.Subscript) -> None: - if ( - isinstance(node.value, ast.Name) - and node.value.id == "Union" - and isinstance(node.slice, ast.Tuple) - ): + if not isinstance(node.value, ast.Name): + return + + if node.value.id == "Union" and isinstance(node.slice, ast.Tuple): new_syntax = " | ".join(ast.unparse(x) for x in node.slice.elts) - errors.append( - (f"{path}:{node.lineno}: Use PEP 604 syntax for Union, e.g. `{new_syntax}`") - ) - if ( - isinstance(node.value, ast.Name) - and node.value.id == "Optional" - ): + errors.append(f"{path}:{node.lineno}: Use PEP 604 syntax for Union, e.g. `{new_syntax}`") + if node.value.id == "Optional": new_syntax = f"{ast.unparse(node.slice)} | None" - errors.append( - (f"{path}:{node.lineno}: Use PEP 604 syntax for Optional, e.g. `{new_syntax}`") - ) + errors.append(f"{path}:{node.lineno}: Use PEP 604 syntax for Optional, e.g. `{new_syntax}`") + if node.value.id in {"List", "Dict"}: + new_syntax = f"{node.value.id.lower()}[{ast.unparse(node.slice)}]" + errors.append(f"{path}:{node.lineno}: Use built-in generics, e.g. `{new_syntax}`") # This doesn't check type aliases (or type var bounds, etc), since those are not # currently supported + # + # TODO: can use built-in generics in type aliases class AnnotationFinder(ast.NodeVisitor): def visit_AnnAssign(self, node: ast.AnnAssign) -> None: - UnionFinder().visit(node.annotation) + OldSyntaxFinder().visit(node.annotation) def visit_arg(self, node: ast.arg) -> None: if node.annotation is not None: - UnionFinder().visit(node.annotation) + OldSyntaxFinder().visit(node.annotation) def visit_FunctionDef(self, node: ast.FunctionDef) -> None: if node.returns is not None: - UnionFinder().visit(node.returns) + OldSyntaxFinder().visit(node.returns) self.generic_visit(node) def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None: if node.returns is not None: - UnionFinder().visit(node.returns) + OldSyntaxFinder().visit(node.returns) self.generic_visit(node) AnnotationFinder().visit(tree) @@ -63,7 +60,7 @@ def main() -> None: with open(path) as f: tree = ast.parse(f.read()) - errors.extend(check_pep_604(tree, path)) + errors.extend(check_new_syntax(tree, path)) if errors: print("\n".join(errors))