mirror of
https://github.com/davidhalter/typeshed.git
synced 2025-12-28 06:36:54 +08:00
Add test to ensure certain names are not imported from typing_extensions (#6619)
This commit is contained in:
@@ -244,10 +244,13 @@ instead in typeshed stubs. This currently affects:
|
||||
- `Literal` (new in Python 3.8)
|
||||
- `SupportsIndex` (new in Python 3.8)
|
||||
- `TypedDict` (new in Python 3.8)
|
||||
- `Concatenate` (new in Python 3.10)
|
||||
- `ParamSpec` (new in Python 3.10)
|
||||
- `TypeGuard` (new in Python 3.10)
|
||||
|
||||
An exception is `Protocol`: although it was added in Python 3.8, it
|
||||
can be used in stubs regardless of Python version.
|
||||
Two exceptions are `Protocol` and `runtime_checkable`: although
|
||||
these were added in Python 3.8, they can be used in stubs regardless
|
||||
of Python version.
|
||||
|
||||
### What to include
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ from _typeshed import (
|
||||
from abc import ABCMeta, abstractmethod
|
||||
from importlib.machinery import ModuleSpec
|
||||
from io import BufferedRandom, BufferedReader, BufferedWriter, FileIO, TextIOWrapper
|
||||
from typing import IO, Any, BinaryIO, Iterator, Mapping, NoReturn, Protocol, Sequence, Union, overload
|
||||
from typing_extensions import Literal, runtime_checkable
|
||||
from typing import IO, Any, BinaryIO, Iterator, Mapping, NoReturn, Protocol, Sequence, Union, overload, runtime_checkable
|
||||
from typing_extensions import Literal
|
||||
|
||||
_Path = Union[bytes, str]
|
||||
|
||||
|
||||
@@ -12,6 +12,23 @@ STUBS_SUPPORTING_PYTHON_2 = frozenset(
|
||||
CONTEXT_MANAGER_ALIASES = {"ContextManager": "AbstractContextManager", "AsyncContextManager": "AbstractAsyncContextManager"}
|
||||
CONTEXTLIB_ALIAS_ALLOWLIST = frozenset({Path("stdlib/contextlib.pyi"), Path("stdlib/typing_extensions.pyi")})
|
||||
|
||||
IMPORTED_FROM_TYPING_NOT_TYPING_EXTENSIONS = frozenset(
|
||||
{"ClassVar", "Type", "NewType", "overload", "Text", "Protocol", "runtime_checkable", "NoReturn"}
|
||||
)
|
||||
|
||||
IMPORTED_FROM_COLLECTIONS_ABC_NOT_TYPING_EXTENSIONS = frozenset(
|
||||
{"Awaitable", "Coroutine", "AsyncIterable", "AsyncIterator", "AsyncGenerator"}
|
||||
)
|
||||
|
||||
# The values in the mapping are what these are called in `collections`
|
||||
IMPORTED_FROM_COLLECTIONS_NOT_TYPING_EXTENSIONS = {
|
||||
"Counter": "Counter",
|
||||
"Deque": "deque",
|
||||
"DefaultDict": "defaultdict",
|
||||
"OrderedDict": "OrderedDict",
|
||||
"ChainMap": "ChainMap",
|
||||
}
|
||||
|
||||
|
||||
def check_new_syntax(tree: ast.AST, path: Path) -> list[str]:
|
||||
errors = []
|
||||
@@ -85,6 +102,38 @@ def check_new_syntax(tree: ast.AST, path: Path) -> list[str]:
|
||||
if any(cls.name == "Set" for cls in imported_classes):
|
||||
self.set_from_collections_abc = True
|
||||
|
||||
elif node.module == "typing_extensions":
|
||||
for imported_object in node.names:
|
||||
imported_object_name = imported_object.name
|
||||
if imported_object_name in IMPORTED_FROM_TYPING_NOT_TYPING_EXTENSIONS:
|
||||
errors.append(
|
||||
f"{path}:{node.lineno}: "
|
||||
f"Use `typing.{imported_object_name}` instead of `typing_extensions.{imported_object_name}`"
|
||||
)
|
||||
elif imported_object_name in IMPORTED_FROM_COLLECTIONS_ABC_NOT_TYPING_EXTENSIONS:
|
||||
errors.append(
|
||||
f"{path}:{node.lineno}: "
|
||||
f"Use `collections.abc.{imported_object_name}` or `typing.{imported_object_name}` "
|
||||
f"instead of `typing_extensions.{imported_object_name}`"
|
||||
)
|
||||
elif imported_object_name in IMPORTED_FROM_COLLECTIONS_NOT_TYPING_EXTENSIONS:
|
||||
errors.append(
|
||||
f"{path}:{node.lineno}: "
|
||||
f"Use `collections.{IMPORTED_FROM_COLLECTIONS_NOT_TYPING_EXTENSIONS[imported_object_name]}` "
|
||||
f"or `typing.{imported_object_name}` instead of `typing_extensions.{imported_object_name}`"
|
||||
)
|
||||
elif imported_object_name in CONTEXT_MANAGER_ALIASES:
|
||||
if python_2_support_required:
|
||||
errors.append(
|
||||
f"{path}:{node.lineno}: "
|
||||
f"Use `typing.{imported_object_name}` instead of `typing_extensions.{imported_object_name}`"
|
||||
)
|
||||
else:
|
||||
errors.append(
|
||||
f"{path}:{node.lineno}: Use `contextlib.{CONTEXT_MANAGER_ALIASES[imported_object_name]}` "
|
||||
f"instead of `typing_extensions.{imported_object_name}`"
|
||||
)
|
||||
|
||||
elif not python_2_support_required and path not in CONTEXTLIB_ALIAS_ALLOWLIST and node.module == "typing":
|
||||
for imported_class in node.names:
|
||||
imported_class_name = imported_class.name
|
||||
|
||||
Reference in New Issue
Block a user