mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-04 23:50:31 +00:00
[ruff
] Extend FA102 with listed PEP 585-compatible APIs (#20659)
Resolves https://github.com/astral-sh/ruff/issues/20512 This PR expands FA102’s preview coverage to flag every PEP 585-compatible API that breaks without from `from __future__ import annotations`, including `collections.abc`. The rule now treats asyncio futures, pathlib-style queues, weakref containers, shelve proxies, and the full `collections.abc` family as generics once preview mode is enabled. Stable behavior is unchanged; the broader matching runs behind `is_future_required_preview_generics_enabled`, letting us vet the new diagnostics before marking them as stable. I've also added a snapshot test that covers all of the newly supported types. Check out https://docs.python.org/3/library/stdtypes.html#standard-generic-classes for a list of commonly used PEP 585-compatible APIs.
This commit is contained in:
parent
7d7237c660
commit
ebfb33c30b
8 changed files with 1049 additions and 27 deletions
|
@ -0,0 +1,91 @@
|
|||
import asyncio
|
||||
import collections
|
||||
import contextlib
|
||||
import dataclasses
|
||||
import functools
|
||||
import os
|
||||
import queue
|
||||
import re
|
||||
import shelve
|
||||
import types
|
||||
import weakref
|
||||
from collections.abc import (
|
||||
AsyncGenerator,
|
||||
AsyncIterable,
|
||||
AsyncIterator,
|
||||
Awaitable,
|
||||
ByteString,
|
||||
Callable,
|
||||
Collection,
|
||||
Container,
|
||||
Coroutine,
|
||||
Generator,
|
||||
Iterable,
|
||||
Iterator,
|
||||
ItemsView,
|
||||
KeysView,
|
||||
Mapping,
|
||||
MappingView,
|
||||
MutableMapping,
|
||||
MutableSequence,
|
||||
MutableSet,
|
||||
Reversible,
|
||||
Sequence,
|
||||
Set,
|
||||
ValuesView,
|
||||
)
|
||||
|
||||
|
||||
def takes_preview_generics(
|
||||
future: asyncio.Future[int],
|
||||
task: asyncio.Task[str],
|
||||
deque_object: collections.deque[int],
|
||||
defaultdict_object: collections.defaultdict[str, int],
|
||||
ordered_dict: collections.OrderedDict[str, int],
|
||||
counter_obj: collections.Counter[str],
|
||||
chain_map: collections.ChainMap[str, int],
|
||||
context_manager: contextlib.AbstractContextManager[str],
|
||||
async_context_manager: contextlib.AbstractAsyncContextManager[int],
|
||||
dataclass_field: dataclasses.Field[int],
|
||||
cached_prop: functools.cached_property[int],
|
||||
partial_method: functools.partialmethod[int],
|
||||
path_like: os.PathLike[str],
|
||||
lifo_queue: queue.LifoQueue[int],
|
||||
regular_queue: queue.Queue[int],
|
||||
priority_queue: queue.PriorityQueue[int],
|
||||
simple_queue: queue.SimpleQueue[int],
|
||||
regex_pattern: re.Pattern[str],
|
||||
regex_match: re.Match[str],
|
||||
bsd_db_shelf: shelve.BsdDbShelf[str, int],
|
||||
db_filename_shelf: shelve.DbfilenameShelf[str, int],
|
||||
shelf_obj: shelve.Shelf[str, int],
|
||||
mapping_proxy: types.MappingProxyType[str, int],
|
||||
weak_key_dict: weakref.WeakKeyDictionary[object, int],
|
||||
weak_method: weakref.WeakMethod[int],
|
||||
weak_set: weakref.WeakSet[int],
|
||||
weak_value_dict: weakref.WeakValueDictionary[object, int],
|
||||
awaitable: Awaitable[int],
|
||||
coroutine: Coroutine[int, None, str],
|
||||
async_iterable: AsyncIterable[int],
|
||||
async_iterator: AsyncIterator[int],
|
||||
async_generator: AsyncGenerator[int, None],
|
||||
iterable: Iterable[int],
|
||||
iterator: Iterator[int],
|
||||
generator: Generator[int, None, None],
|
||||
reversible: Reversible[int],
|
||||
container: Container[int],
|
||||
collection: Collection[int],
|
||||
callable_obj: Callable[[int], str],
|
||||
set_obj: Set[int],
|
||||
mutable_set: MutableSet[int],
|
||||
mapping: Mapping[str, int],
|
||||
mutable_mapping: MutableMapping[str, int],
|
||||
sequence: Sequence[int],
|
||||
mutable_sequence: MutableSequence[int],
|
||||
byte_string: ByteString[int],
|
||||
mapping_view: MappingView[str, int],
|
||||
keys_view: KeysView[str],
|
||||
items_view: ItemsView[str, int],
|
||||
values_view: ValuesView[int],
|
||||
) -> None:
|
||||
...
|
|
@ -8,7 +8,8 @@ use ruff_text_size::Ranged;
|
|||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::preview::{
|
||||
is_optional_as_none_in_union_enabled, is_unnecessary_default_type_args_stubs_enabled,
|
||||
is_future_required_preview_generics_enabled, is_optional_as_none_in_union_enabled,
|
||||
is_unnecessary_default_type_args_stubs_enabled,
|
||||
};
|
||||
use crate::registry::Rule;
|
||||
use crate::rules::{
|
||||
|
@ -69,7 +70,11 @@ pub(crate) fn expression(expr: &Expr, checker: &Checker) {
|
|||
&& checker.semantic.in_annotation()
|
||||
&& checker.semantic.in_runtime_evaluated_annotation()
|
||||
&& !checker.semantic.in_string_type_definition()
|
||||
&& typing::is_pep585_generic(value, &checker.semantic)
|
||||
&& typing::is_pep585_generic(
|
||||
value,
|
||||
&checker.semantic,
|
||||
is_future_required_preview_generics_enabled(checker.settings()),
|
||||
)
|
||||
{
|
||||
flake8_future_annotations::rules::future_required_type_annotation(
|
||||
checker,
|
||||
|
|
|
@ -200,6 +200,11 @@ pub(crate) const fn is_optional_as_none_in_union_enabled(settings: &LinterSettin
|
|||
settings.preview.is_enabled()
|
||||
}
|
||||
|
||||
// https://github.com/astral-sh/ruff/pull/20659
|
||||
pub(crate) const fn is_future_required_preview_generics_enabled(settings: &LinterSettings) -> bool {
|
||||
settings.preview.is_enabled()
|
||||
}
|
||||
|
||||
// https://github.com/astral-sh/ruff/pull/18683
|
||||
pub(crate) const fn is_safe_super_call_with_parameters_fix_enabled(
|
||||
settings: &LinterSettings,
|
||||
|
|
|
@ -9,6 +9,7 @@ mod tests {
|
|||
use test_case::test_case;
|
||||
|
||||
use crate::registry::Rule;
|
||||
use crate::settings::types::PreviewMode;
|
||||
use crate::test::test_path;
|
||||
use crate::{assert_diagnostics, settings};
|
||||
use ruff_python_ast::PythonVersion;
|
||||
|
@ -39,6 +40,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test_case(Path::new("no_future_import_uses_lowercase.py"))]
|
||||
#[test_case(Path::new("no_future_import_uses_preview_generics.py"))]
|
||||
#[test_case(Path::new("no_future_import_uses_union.py"))]
|
||||
#[test_case(Path::new("no_future_import_uses_union_inner.py"))]
|
||||
#[test_case(Path::new("ok_no_types.py"))]
|
||||
|
@ -56,4 +58,19 @@ mod tests {
|
|||
assert_diagnostics!(snapshot, diagnostics);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case(Path::new("no_future_import_uses_preview_generics.py"))]
|
||||
fn fa102_preview(path: &Path) -> Result<()> {
|
||||
let snapshot = format!("fa102_preview_{}", path.to_string_lossy());
|
||||
let diagnostics = test_path(
|
||||
Path::new("flake8_future_annotations").join(path).as_path(),
|
||||
&settings::LinterSettings {
|
||||
unresolved_target_version: PythonVersion::PY37.into(),
|
||||
preview: PreviewMode::Enabled,
|
||||
..settings::LinterSettings::for_rule(Rule::FutureRequiredTypeAnnotation)
|
||||
},
|
||||
)?;
|
||||
assert_diagnostics!(snapshot, diagnostics);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_future_annotations/mod.rs
|
||||
---
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:42:19
|
||||
|
|
||||
40 | future: asyncio.Future[int],
|
||||
41 | task: asyncio.Task[str],
|
||||
42 | deque_object: collections.deque[int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
43 | defaultdict_object: collections.defaultdict[str, int],
|
||||
44 | ordered_dict: collections.OrderedDict[str, int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:43:25
|
||||
|
|
||||
41 | task: asyncio.Task[str],
|
||||
42 | deque_object: collections.deque[int],
|
||||
43 | defaultdict_object: collections.defaultdict[str, int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
44 | ordered_dict: collections.OrderedDict[str, int],
|
||||
45 | counter_obj: collections.Counter[str],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
|
@ -0,0 +1,851 @@
|
|||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_future_annotations/mod.rs
|
||||
---
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:40:13
|
||||
|
|
||||
39 | def takes_preview_generics(
|
||||
40 | future: asyncio.Future[int],
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
41 | task: asyncio.Task[str],
|
||||
42 | deque_object: collections.deque[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:41:11
|
||||
|
|
||||
39 | def takes_preview_generics(
|
||||
40 | future: asyncio.Future[int],
|
||||
41 | task: asyncio.Task[str],
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
42 | deque_object: collections.deque[int],
|
||||
43 | defaultdict_object: collections.defaultdict[str, int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:42:19
|
||||
|
|
||||
40 | future: asyncio.Future[int],
|
||||
41 | task: asyncio.Task[str],
|
||||
42 | deque_object: collections.deque[int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
43 | defaultdict_object: collections.defaultdict[str, int],
|
||||
44 | ordered_dict: collections.OrderedDict[str, int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:43:25
|
||||
|
|
||||
41 | task: asyncio.Task[str],
|
||||
42 | deque_object: collections.deque[int],
|
||||
43 | defaultdict_object: collections.defaultdict[str, int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
44 | ordered_dict: collections.OrderedDict[str, int],
|
||||
45 | counter_obj: collections.Counter[str],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:44:19
|
||||
|
|
||||
42 | deque_object: collections.deque[int],
|
||||
43 | defaultdict_object: collections.defaultdict[str, int],
|
||||
44 | ordered_dict: collections.OrderedDict[str, int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
45 | counter_obj: collections.Counter[str],
|
||||
46 | chain_map: collections.ChainMap[str, int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:45:18
|
||||
|
|
||||
43 | defaultdict_object: collections.defaultdict[str, int],
|
||||
44 | ordered_dict: collections.OrderedDict[str, int],
|
||||
45 | counter_obj: collections.Counter[str],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
46 | chain_map: collections.ChainMap[str, int],
|
||||
47 | context_manager: contextlib.AbstractContextManager[str],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:46:16
|
||||
|
|
||||
44 | ordered_dict: collections.OrderedDict[str, int],
|
||||
45 | counter_obj: collections.Counter[str],
|
||||
46 | chain_map: collections.ChainMap[str, int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
47 | context_manager: contextlib.AbstractContextManager[str],
|
||||
48 | async_context_manager: contextlib.AbstractAsyncContextManager[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:47:22
|
||||
|
|
||||
45 | counter_obj: collections.Counter[str],
|
||||
46 | chain_map: collections.ChainMap[str, int],
|
||||
47 | context_manager: contextlib.AbstractContextManager[str],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
48 | async_context_manager: contextlib.AbstractAsyncContextManager[int],
|
||||
49 | dataclass_field: dataclasses.Field[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:48:28
|
||||
|
|
||||
46 | chain_map: collections.ChainMap[str, int],
|
||||
47 | context_manager: contextlib.AbstractContextManager[str],
|
||||
48 | async_context_manager: contextlib.AbstractAsyncContextManager[int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
49 | dataclass_field: dataclasses.Field[int],
|
||||
50 | cached_prop: functools.cached_property[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:49:22
|
||||
|
|
||||
47 | context_manager: contextlib.AbstractContextManager[str],
|
||||
48 | async_context_manager: contextlib.AbstractAsyncContextManager[int],
|
||||
49 | dataclass_field: dataclasses.Field[int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
50 | cached_prop: functools.cached_property[int],
|
||||
51 | partial_method: functools.partialmethod[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:50:18
|
||||
|
|
||||
48 | async_context_manager: contextlib.AbstractAsyncContextManager[int],
|
||||
49 | dataclass_field: dataclasses.Field[int],
|
||||
50 | cached_prop: functools.cached_property[int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
51 | partial_method: functools.partialmethod[int],
|
||||
52 | path_like: os.PathLike[str],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:51:21
|
||||
|
|
||||
49 | dataclass_field: dataclasses.Field[int],
|
||||
50 | cached_prop: functools.cached_property[int],
|
||||
51 | partial_method: functools.partialmethod[int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
52 | path_like: os.PathLike[str],
|
||||
53 | lifo_queue: queue.LifoQueue[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:52:16
|
||||
|
|
||||
50 | cached_prop: functools.cached_property[int],
|
||||
51 | partial_method: functools.partialmethod[int],
|
||||
52 | path_like: os.PathLike[str],
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
53 | lifo_queue: queue.LifoQueue[int],
|
||||
54 | regular_queue: queue.Queue[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:53:17
|
||||
|
|
||||
51 | partial_method: functools.partialmethod[int],
|
||||
52 | path_like: os.PathLike[str],
|
||||
53 | lifo_queue: queue.LifoQueue[int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
54 | regular_queue: queue.Queue[int],
|
||||
55 | priority_queue: queue.PriorityQueue[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:54:20
|
||||
|
|
||||
52 | path_like: os.PathLike[str],
|
||||
53 | lifo_queue: queue.LifoQueue[int],
|
||||
54 | regular_queue: queue.Queue[int],
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
55 | priority_queue: queue.PriorityQueue[int],
|
||||
56 | simple_queue: queue.SimpleQueue[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:55:21
|
||||
|
|
||||
53 | lifo_queue: queue.LifoQueue[int],
|
||||
54 | regular_queue: queue.Queue[int],
|
||||
55 | priority_queue: queue.PriorityQueue[int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
56 | simple_queue: queue.SimpleQueue[int],
|
||||
57 | regex_pattern: re.Pattern[str],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:56:19
|
||||
|
|
||||
54 | regular_queue: queue.Queue[int],
|
||||
55 | priority_queue: queue.PriorityQueue[int],
|
||||
56 | simple_queue: queue.SimpleQueue[int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
57 | regex_pattern: re.Pattern[str],
|
||||
58 | regex_match: re.Match[str],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:57:20
|
||||
|
|
||||
55 | priority_queue: queue.PriorityQueue[int],
|
||||
56 | simple_queue: queue.SimpleQueue[int],
|
||||
57 | regex_pattern: re.Pattern[str],
|
||||
| ^^^^^^^^^^^^^^^
|
||||
58 | regex_match: re.Match[str],
|
||||
59 | bsd_db_shelf: shelve.BsdDbShelf[str, int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:58:18
|
||||
|
|
||||
56 | simple_queue: queue.SimpleQueue[int],
|
||||
57 | regex_pattern: re.Pattern[str],
|
||||
58 | regex_match: re.Match[str],
|
||||
| ^^^^^^^^^^^^^
|
||||
59 | bsd_db_shelf: shelve.BsdDbShelf[str, int],
|
||||
60 | db_filename_shelf: shelve.DbfilenameShelf[str, int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:59:19
|
||||
|
|
||||
57 | regex_pattern: re.Pattern[str],
|
||||
58 | regex_match: re.Match[str],
|
||||
59 | bsd_db_shelf: shelve.BsdDbShelf[str, int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
60 | db_filename_shelf: shelve.DbfilenameShelf[str, int],
|
||||
61 | shelf_obj: shelve.Shelf[str, int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:60:24
|
||||
|
|
||||
58 | regex_match: re.Match[str],
|
||||
59 | bsd_db_shelf: shelve.BsdDbShelf[str, int],
|
||||
60 | db_filename_shelf: shelve.DbfilenameShelf[str, int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
61 | shelf_obj: shelve.Shelf[str, int],
|
||||
62 | mapping_proxy: types.MappingProxyType[str, int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:61:16
|
||||
|
|
||||
59 | bsd_db_shelf: shelve.BsdDbShelf[str, int],
|
||||
60 | db_filename_shelf: shelve.DbfilenameShelf[str, int],
|
||||
61 | shelf_obj: shelve.Shelf[str, int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
62 | mapping_proxy: types.MappingProxyType[str, int],
|
||||
63 | weak_key_dict: weakref.WeakKeyDictionary[object, int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:62:20
|
||||
|
|
||||
60 | db_filename_shelf: shelve.DbfilenameShelf[str, int],
|
||||
61 | shelf_obj: shelve.Shelf[str, int],
|
||||
62 | mapping_proxy: types.MappingProxyType[str, int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
63 | weak_key_dict: weakref.WeakKeyDictionary[object, int],
|
||||
64 | weak_method: weakref.WeakMethod[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:63:20
|
||||
|
|
||||
61 | shelf_obj: shelve.Shelf[str, int],
|
||||
62 | mapping_proxy: types.MappingProxyType[str, int],
|
||||
63 | weak_key_dict: weakref.WeakKeyDictionary[object, int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
64 | weak_method: weakref.WeakMethod[int],
|
||||
65 | weak_set: weakref.WeakSet[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:64:18
|
||||
|
|
||||
62 | mapping_proxy: types.MappingProxyType[str, int],
|
||||
63 | weak_key_dict: weakref.WeakKeyDictionary[object, int],
|
||||
64 | weak_method: weakref.WeakMethod[int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
65 | weak_set: weakref.WeakSet[int],
|
||||
66 | weak_value_dict: weakref.WeakValueDictionary[object, int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:65:15
|
||||
|
|
||||
63 | weak_key_dict: weakref.WeakKeyDictionary[object, int],
|
||||
64 | weak_method: weakref.WeakMethod[int],
|
||||
65 | weak_set: weakref.WeakSet[int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
66 | weak_value_dict: weakref.WeakValueDictionary[object, int],
|
||||
67 | awaitable: Awaitable[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:66:22
|
||||
|
|
||||
64 | weak_method: weakref.WeakMethod[int],
|
||||
65 | weak_set: weakref.WeakSet[int],
|
||||
66 | weak_value_dict: weakref.WeakValueDictionary[object, int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
67 | awaitable: Awaitable[int],
|
||||
68 | coroutine: Coroutine[int, None, str],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:67:16
|
||||
|
|
||||
65 | weak_set: weakref.WeakSet[int],
|
||||
66 | weak_value_dict: weakref.WeakValueDictionary[object, int],
|
||||
67 | awaitable: Awaitable[int],
|
||||
| ^^^^^^^^^^^^^^
|
||||
68 | coroutine: Coroutine[int, None, str],
|
||||
69 | async_iterable: AsyncIterable[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:68:16
|
||||
|
|
||||
66 | weak_value_dict: weakref.WeakValueDictionary[object, int],
|
||||
67 | awaitable: Awaitable[int],
|
||||
68 | coroutine: Coroutine[int, None, str],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
69 | async_iterable: AsyncIterable[int],
|
||||
70 | async_iterator: AsyncIterator[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:69:21
|
||||
|
|
||||
67 | awaitable: Awaitable[int],
|
||||
68 | coroutine: Coroutine[int, None, str],
|
||||
69 | async_iterable: AsyncIterable[int],
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
70 | async_iterator: AsyncIterator[int],
|
||||
71 | async_generator: AsyncGenerator[int, None],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:70:21
|
||||
|
|
||||
68 | coroutine: Coroutine[int, None, str],
|
||||
69 | async_iterable: AsyncIterable[int],
|
||||
70 | async_iterator: AsyncIterator[int],
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
71 | async_generator: AsyncGenerator[int, None],
|
||||
72 | iterable: Iterable[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:71:22
|
||||
|
|
||||
69 | async_iterable: AsyncIterable[int],
|
||||
70 | async_iterator: AsyncIterator[int],
|
||||
71 | async_generator: AsyncGenerator[int, None],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
72 | iterable: Iterable[int],
|
||||
73 | iterator: Iterator[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:72:15
|
||||
|
|
||||
70 | async_iterator: AsyncIterator[int],
|
||||
71 | async_generator: AsyncGenerator[int, None],
|
||||
72 | iterable: Iterable[int],
|
||||
| ^^^^^^^^^^^^^
|
||||
73 | iterator: Iterator[int],
|
||||
74 | generator: Generator[int, None, None],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:73:15
|
||||
|
|
||||
71 | async_generator: AsyncGenerator[int, None],
|
||||
72 | iterable: Iterable[int],
|
||||
73 | iterator: Iterator[int],
|
||||
| ^^^^^^^^^^^^^
|
||||
74 | generator: Generator[int, None, None],
|
||||
75 | reversible: Reversible[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:74:16
|
||||
|
|
||||
72 | iterable: Iterable[int],
|
||||
73 | iterator: Iterator[int],
|
||||
74 | generator: Generator[int, None, None],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
75 | reversible: Reversible[int],
|
||||
76 | container: Container[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:75:17
|
||||
|
|
||||
73 | iterator: Iterator[int],
|
||||
74 | generator: Generator[int, None, None],
|
||||
75 | reversible: Reversible[int],
|
||||
| ^^^^^^^^^^^^^^^
|
||||
76 | container: Container[int],
|
||||
77 | collection: Collection[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:76:16
|
||||
|
|
||||
74 | generator: Generator[int, None, None],
|
||||
75 | reversible: Reversible[int],
|
||||
76 | container: Container[int],
|
||||
| ^^^^^^^^^^^^^^
|
||||
77 | collection: Collection[int],
|
||||
78 | callable_obj: Callable[[int], str],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:77:17
|
||||
|
|
||||
75 | reversible: Reversible[int],
|
||||
76 | container: Container[int],
|
||||
77 | collection: Collection[int],
|
||||
| ^^^^^^^^^^^^^^^
|
||||
78 | callable_obj: Callable[[int], str],
|
||||
79 | set_obj: Set[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:78:19
|
||||
|
|
||||
76 | container: Container[int],
|
||||
77 | collection: Collection[int],
|
||||
78 | callable_obj: Callable[[int], str],
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
79 | set_obj: Set[int],
|
||||
80 | mutable_set: MutableSet[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:79:14
|
||||
|
|
||||
77 | collection: Collection[int],
|
||||
78 | callable_obj: Callable[[int], str],
|
||||
79 | set_obj: Set[int],
|
||||
| ^^^^^^^^
|
||||
80 | mutable_set: MutableSet[int],
|
||||
81 | mapping: Mapping[str, int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:80:18
|
||||
|
|
||||
78 | callable_obj: Callable[[int], str],
|
||||
79 | set_obj: Set[int],
|
||||
80 | mutable_set: MutableSet[int],
|
||||
| ^^^^^^^^^^^^^^^
|
||||
81 | mapping: Mapping[str, int],
|
||||
82 | mutable_mapping: MutableMapping[str, int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:81:14
|
||||
|
|
||||
79 | set_obj: Set[int],
|
||||
80 | mutable_set: MutableSet[int],
|
||||
81 | mapping: Mapping[str, int],
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
82 | mutable_mapping: MutableMapping[str, int],
|
||||
83 | sequence: Sequence[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:82:22
|
||||
|
|
||||
80 | mutable_set: MutableSet[int],
|
||||
81 | mapping: Mapping[str, int],
|
||||
82 | mutable_mapping: MutableMapping[str, int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
83 | sequence: Sequence[int],
|
||||
84 | mutable_sequence: MutableSequence[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:83:15
|
||||
|
|
||||
81 | mapping: Mapping[str, int],
|
||||
82 | mutable_mapping: MutableMapping[str, int],
|
||||
83 | sequence: Sequence[int],
|
||||
| ^^^^^^^^^^^^^
|
||||
84 | mutable_sequence: MutableSequence[int],
|
||||
85 | byte_string: ByteString[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:84:23
|
||||
|
|
||||
82 | mutable_mapping: MutableMapping[str, int],
|
||||
83 | sequence: Sequence[int],
|
||||
84 | mutable_sequence: MutableSequence[int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
85 | byte_string: ByteString[int],
|
||||
86 | mapping_view: MappingView[str, int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:85:18
|
||||
|
|
||||
83 | sequence: Sequence[int],
|
||||
84 | mutable_sequence: MutableSequence[int],
|
||||
85 | byte_string: ByteString[int],
|
||||
| ^^^^^^^^^^^^^^^
|
||||
86 | mapping_view: MappingView[str, int],
|
||||
87 | keys_view: KeysView[str],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:86:19
|
||||
|
|
||||
84 | mutable_sequence: MutableSequence[int],
|
||||
85 | byte_string: ByteString[int],
|
||||
86 | mapping_view: MappingView[str, int],
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
87 | keys_view: KeysView[str],
|
||||
88 | items_view: ItemsView[str, int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:87:16
|
||||
|
|
||||
85 | byte_string: ByteString[int],
|
||||
86 | mapping_view: MappingView[str, int],
|
||||
87 | keys_view: KeysView[str],
|
||||
| ^^^^^^^^^^^^^
|
||||
88 | items_view: ItemsView[str, int],
|
||||
89 | values_view: ValuesView[int],
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:88:17
|
||||
|
|
||||
86 | mapping_view: MappingView[str, int],
|
||||
87 | keys_view: KeysView[str],
|
||||
88 | items_view: ItemsView[str, int],
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
89 | values_view: ValuesView[int],
|
||||
90 | ) -> None:
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
||||
|
||||
FA102 [*] Missing `from __future__ import annotations`, but uses PEP 585 collection
|
||||
--> no_future_import_uses_preview_generics.py:89:18
|
||||
|
|
||||
87 | keys_view: KeysView[str],
|
||||
88 | items_view: ItemsView[str, int],
|
||||
89 | values_view: ValuesView[int],
|
||||
| ^^^^^^^^^^^^^^^
|
||||
90 | ) -> None:
|
||||
91 | ...
|
||||
|
|
||||
help: Add `from __future__ import annotations`
|
||||
1 + from __future__ import annotations
|
||||
2 | import asyncio
|
||||
3 | import collections
|
||||
4 | import contextlib
|
||||
note: This is an unsafe fix and may change runtime behavior
|
|
@ -8,11 +8,10 @@ use ruff_python_ast::{
|
|||
StmtAssign,
|
||||
};
|
||||
use ruff_python_stdlib::typing::{
|
||||
as_pep_585_generic, has_pep_585_generic, is_immutable_generic_type,
|
||||
is_immutable_non_generic_type, is_immutable_return_type, is_literal_member,
|
||||
is_mutable_return_type, is_pep_593_generic_member, is_pep_593_generic_type,
|
||||
is_standard_library_generic, is_standard_library_generic_member, is_standard_library_literal,
|
||||
is_typed_dict, is_typed_dict_member,
|
||||
as_pep_585_generic, is_immutable_generic_type, is_immutable_non_generic_type,
|
||||
is_immutable_return_type, is_literal_member, is_mutable_return_type, is_pep_593_generic_member,
|
||||
is_pep_593_generic_type, is_standard_library_generic, is_standard_library_generic_member,
|
||||
is_standard_library_literal, is_typed_dict, is_typed_dict_member,
|
||||
};
|
||||
use ruff_text_size::Ranged;
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
|
@ -148,14 +147,46 @@ pub fn to_pep585_generic(expr: &Expr, semantic: &SemanticModel) -> Option<Module
|
|||
}
|
||||
|
||||
/// Return whether a given expression uses a PEP 585 standard library generic.
|
||||
pub fn is_pep585_generic(expr: &Expr, semantic: &SemanticModel) -> bool {
|
||||
pub fn is_pep585_generic(
|
||||
expr: &Expr,
|
||||
semantic: &SemanticModel,
|
||||
include_preview_generics: bool,
|
||||
) -> bool {
|
||||
semantic
|
||||
.resolve_qualified_name(expr)
|
||||
.is_some_and(|qualified_name| {
|
||||
let [module, name] = qualified_name.segments() else {
|
||||
return false;
|
||||
};
|
||||
has_pep_585_generic(module, name)
|
||||
.is_some_and(|qualified_name| match qualified_name.segments() {
|
||||
["", "dict" | "frozenset" | "list" | "set" | "tuple" | "type"]
|
||||
| ["collections", "deque" | "defaultdict"] => true,
|
||||
["asyncio", "Future" | "Task"]
|
||||
| ["collections", "ChainMap" | "Counter" | "OrderedDict"]
|
||||
| [
|
||||
"contextlib",
|
||||
"AbstractAsyncContextManager" | "AbstractContextManager",
|
||||
]
|
||||
| ["dataclasses", "Field"]
|
||||
| ["functools", "cached_property" | "partialmethod"]
|
||||
| ["os", "PathLike"]
|
||||
| [
|
||||
"queue",
|
||||
"LifoQueue" | "PriorityQueue" | "Queue" | "SimpleQueue",
|
||||
]
|
||||
| ["re", "Match" | "Pattern"]
|
||||
| ["shelve", "BsdDbShelf" | "DbfilenameShelf" | "Shelf"]
|
||||
| ["types", "MappingProxyType"]
|
||||
| [
|
||||
"weakref",
|
||||
"WeakKeyDictionary" | "WeakMethod" | "WeakSet" | "WeakValueDictionary",
|
||||
]
|
||||
| [
|
||||
"collections",
|
||||
"abc",
|
||||
"AsyncGenerator" | "AsyncIterable" | "AsyncIterator" | "Awaitable" | "ByteString"
|
||||
| "Callable" | "Collection" | "Container" | "Coroutine" | "Generator" | "ItemsView"
|
||||
| "Iterable" | "Iterator" | "KeysView" | "Mapping" | "MappingView"
|
||||
| "MutableMapping" | "MutableSequence" | "MutableSet" | "Reversible" | "Sequence"
|
||||
| "Set" | "ValuesView",
|
||||
] => include_preview_generics,
|
||||
_ => false,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -354,20 +354,6 @@ pub fn as_pep_585_generic(module: &str, member: &str) -> Option<ModuleMember> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Given a typing member, returns `true` if a generic equivalent exists in the Python standard
|
||||
/// library (e.g., `list` for `typing.List`), as introduced by [PEP 585].
|
||||
///
|
||||
/// [PEP 585]: https://peps.python.org/pep-0585/
|
||||
pub fn has_pep_585_generic(module: &str, member: &str) -> bool {
|
||||
// Constructed by taking every pattern from `as_pep_585_generic`, removing all but
|
||||
// the last element in each pattern, and de-duplicating the values.
|
||||
matches!(
|
||||
(module, member),
|
||||
("", "dict" | "frozenset" | "list" | "set" | "tuple" | "type")
|
||||
| ("collections", "deque" | "defaultdict")
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the expected return type for a magic method.
|
||||
///
|
||||
/// See: <https://github.com/JelleZijlstra/autotyping/blob/0adba5ba0eee33c1de4ad9d0c79acfd737321dd9/autotyping/autotyping.py#L69-L91>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue