mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-05 16:10:36 +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::checkers::ast::Checker;
|
||||||
use crate::preview::{
|
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::registry::Rule;
|
||||||
use crate::rules::{
|
use crate::rules::{
|
||||||
|
@ -69,7 +70,11 @@ pub(crate) fn expression(expr: &Expr, checker: &Checker) {
|
||||||
&& checker.semantic.in_annotation()
|
&& checker.semantic.in_annotation()
|
||||||
&& checker.semantic.in_runtime_evaluated_annotation()
|
&& checker.semantic.in_runtime_evaluated_annotation()
|
||||||
&& !checker.semantic.in_string_type_definition()
|
&& !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(
|
flake8_future_annotations::rules::future_required_type_annotation(
|
||||||
checker,
|
checker,
|
||||||
|
|
|
@ -200,6 +200,11 @@ pub(crate) const fn is_optional_as_none_in_union_enabled(settings: &LinterSettin
|
||||||
settings.preview.is_enabled()
|
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
|
// https://github.com/astral-sh/ruff/pull/18683
|
||||||
pub(crate) const fn is_safe_super_call_with_parameters_fix_enabled(
|
pub(crate) const fn is_safe_super_call_with_parameters_fix_enabled(
|
||||||
settings: &LinterSettings,
|
settings: &LinterSettings,
|
||||||
|
|
|
@ -9,6 +9,7 @@ mod tests {
|
||||||
use test_case::test_case;
|
use test_case::test_case;
|
||||||
|
|
||||||
use crate::registry::Rule;
|
use crate::registry::Rule;
|
||||||
|
use crate::settings::types::PreviewMode;
|
||||||
use crate::test::test_path;
|
use crate::test::test_path;
|
||||||
use crate::{assert_diagnostics, settings};
|
use crate::{assert_diagnostics, settings};
|
||||||
use ruff_python_ast::PythonVersion;
|
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_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.py"))]
|
||||||
#[test_case(Path::new("no_future_import_uses_union_inner.py"))]
|
#[test_case(Path::new("no_future_import_uses_union_inner.py"))]
|
||||||
#[test_case(Path::new("ok_no_types.py"))]
|
#[test_case(Path::new("ok_no_types.py"))]
|
||||||
|
@ -56,4 +58,19 @@ mod tests {
|
||||||
assert_diagnostics!(snapshot, diagnostics);
|
assert_diagnostics!(snapshot, diagnostics);
|
||||||
Ok(())
|
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,
|
StmtAssign,
|
||||||
};
|
};
|
||||||
use ruff_python_stdlib::typing::{
|
use ruff_python_stdlib::typing::{
|
||||||
as_pep_585_generic, has_pep_585_generic, is_immutable_generic_type,
|
as_pep_585_generic, is_immutable_generic_type, is_immutable_non_generic_type,
|
||||||
is_immutable_non_generic_type, is_immutable_return_type, is_literal_member,
|
is_immutable_return_type, is_literal_member, is_mutable_return_type, is_pep_593_generic_member,
|
||||||
is_mutable_return_type, is_pep_593_generic_member, is_pep_593_generic_type,
|
is_pep_593_generic_type, is_standard_library_generic, is_standard_library_generic_member,
|
||||||
is_standard_library_generic, is_standard_library_generic_member, is_standard_library_literal,
|
is_standard_library_literal, is_typed_dict, is_typed_dict_member,
|
||||||
is_typed_dict, is_typed_dict_member,
|
|
||||||
};
|
};
|
||||||
use ruff_text_size::Ranged;
|
use ruff_text_size::Ranged;
|
||||||
use smallvec::{SmallVec, smallvec};
|
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.
|
/// 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
|
semantic
|
||||||
.resolve_qualified_name(expr)
|
.resolve_qualified_name(expr)
|
||||||
.is_some_and(|qualified_name| {
|
.is_some_and(|qualified_name| match qualified_name.segments() {
|
||||||
let [module, name] = qualified_name.segments() else {
|
["", "dict" | "frozenset" | "list" | "set" | "tuple" | "type"]
|
||||||
return false;
|
| ["collections", "deque" | "defaultdict"] => true,
|
||||||
};
|
["asyncio", "Future" | "Task"]
|
||||||
has_pep_585_generic(module, name)
|
| ["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.
|
/// Returns the expected return type for a magic method.
|
||||||
///
|
///
|
||||||
/// See: <https://github.com/JelleZijlstra/autotyping/blob/0adba5ba0eee33c1de4ad9d0c79acfd737321dd9/autotyping/autotyping.py#L69-L91>
|
/// See: <https://github.com/JelleZijlstra/autotyping/blob/0adba5ba0eee33c1de4ad9d0c79acfd737321dd9/autotyping/autotyping.py#L69-L91>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue