mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-01 14:21:24 +00:00
Avoid triggering N806 on TypeAlias
assignments (#7119)
This commit is contained in:
parent
1067261a55
commit
5ec73a6137
4 changed files with 35 additions and 26 deletions
|
@ -1,8 +1,6 @@
|
||||||
import collections
|
import collections
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from typing import TypeVar
|
from typing import TypeAlias, TypeVar, NewType, NamedTuple, TypedDict
|
||||||
from typing import NewType
|
|
||||||
from typing import NamedTuple, TypedDict
|
|
||||||
|
|
||||||
GLOBAL: str = "foo"
|
GLOBAL: str = "foo"
|
||||||
|
|
||||||
|
@ -21,9 +19,11 @@ def assign():
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
UserId = NewType("UserId", int)
|
UserId = NewType("UserId", int)
|
||||||
|
|
||||||
Employee = NamedTuple('Employee', [('name', str), ('id', int)])
|
Employee = NamedTuple("Employee", [("name", str), ("id", int)])
|
||||||
|
|
||||||
Point2D = TypedDict('Point2D', {'in': int, 'x-y': int})
|
Point2D = TypedDict("Point2D", {"in": int, "x-y": int})
|
||||||
|
|
||||||
|
IntOrStr: TypeAlias = int | str
|
||||||
|
|
||||||
|
|
||||||
def aug_assign(rank, world_size):
|
def aug_assign(rank, world_size):
|
||||||
|
|
|
@ -22,6 +22,7 @@ pub(super) fn is_acronym(name: &str, asname: &str) -> bool {
|
||||||
name.chars().filter(|c| c.is_uppercase()).join("") == asname
|
name.chars().filter(|c| c.is_uppercase()).join("") == asname
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the statement is an assignment to a named tuple.
|
||||||
pub(super) fn is_named_tuple_assignment(stmt: &Stmt, semantic: &SemanticModel) -> bool {
|
pub(super) fn is_named_tuple_assignment(stmt: &Stmt, semantic: &SemanticModel) -> bool {
|
||||||
let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else {
|
let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -30,13 +31,12 @@ pub(super) fn is_named_tuple_assignment(stmt: &Stmt, semantic: &SemanticModel) -
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
semantic.resolve_call_path(func).is_some_and(|call_path| {
|
semantic.resolve_call_path(func).is_some_and(|call_path| {
|
||||||
matches!(
|
matches!(call_path.as_slice(), ["collections", "namedtuple"])
|
||||||
call_path.as_slice(),
|
|| semantic.match_typing_call_path(&call_path, "NamedTuple")
|
||||||
["collections", "namedtuple"] | ["typing", "NamedTuple"]
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the statement is an assignment to a `TypedDict`.
|
||||||
pub(super) fn is_typed_dict_assignment(stmt: &Stmt, semantic: &SemanticModel) -> bool {
|
pub(super) fn is_typed_dict_assignment(stmt: &Stmt, semantic: &SemanticModel) -> bool {
|
||||||
let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else {
|
let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -44,11 +44,10 @@ pub(super) fn is_typed_dict_assignment(stmt: &Stmt, semantic: &SemanticModel) ->
|
||||||
let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() else {
|
let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
semantic
|
semantic.match_typing_expr(func, "TypedDict")
|
||||||
.resolve_call_path(func)
|
|
||||||
.is_some_and(|call_path| matches!(call_path.as_slice(), ["typing", "TypedDict"]))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the statement is an assignment to a `TypeVar` or `NewType`.
|
||||||
pub(super) fn is_type_var_assignment(stmt: &Stmt, semantic: &SemanticModel) -> bool {
|
pub(super) fn is_type_var_assignment(stmt: &Stmt, semantic: &SemanticModel) -> bool {
|
||||||
let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else {
|
let Stmt::Assign(ast::StmtAssign { value, .. }) = stmt else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -56,9 +55,18 @@ pub(super) fn is_type_var_assignment(stmt: &Stmt, semantic: &SemanticModel) -> b
|
||||||
let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() else {
|
let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
semantic
|
semantic.resolve_call_path(func).is_some_and(|call_path| {
|
||||||
.resolve_call_path(func)
|
semantic.match_typing_call_path(&call_path, "TypeVar")
|
||||||
.is_some_and(|call_path| matches!(call_path.as_slice(), ["typing", "TypeVar" | "NewType"]))
|
|| semantic.match_typing_call_path(&call_path, "NewType")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if the statement is an assignment to a `TypeAlias`.
|
||||||
|
pub(super) fn is_type_alias_assignment(stmt: &Stmt, semantic: &SemanticModel) -> bool {
|
||||||
|
let Stmt::AnnAssign(ast::StmtAnnAssign { annotation, .. }) = stmt else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
semantic.match_typing_expr(annotation, "TypeAlias")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn is_typed_dict_class(arguments: Option<&Arguments>, semantic: &SemanticModel) -> bool {
|
pub(super) fn is_typed_dict_class(arguments: Option<&Arguments>, semantic: &SemanticModel) -> bool {
|
||||||
|
|
|
@ -70,6 +70,7 @@ pub(crate) fn non_lowercase_variable_in_function(checker: &mut Checker, expr: &E
|
||||||
if helpers::is_named_tuple_assignment(parent, checker.semantic())
|
if helpers::is_named_tuple_assignment(parent, checker.semantic())
|
||||||
|| helpers::is_typed_dict_assignment(parent, checker.semantic())
|
|| helpers::is_typed_dict_assignment(parent, checker.semantic())
|
||||||
|| helpers::is_type_var_assignment(parent, checker.semantic())
|
|| helpers::is_type_var_assignment(parent, checker.semantic())
|
||||||
|
|| helpers::is_type_alias_assignment(parent, checker.semantic())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
---
|
---
|
||||||
source: crates/ruff/src/rules/pep8_naming/mod.rs
|
source: crates/ruff/src/rules/pep8_naming/mod.rs
|
||||||
---
|
---
|
||||||
N806.py:14:5: N806 Variable `Camel` in function should be lowercase
|
N806.py:12:5: N806 Variable `Camel` in function should be lowercase
|
||||||
|
|
|
|
||||||
12 | GLOBAL = "bar"
|
10 | GLOBAL = "bar"
|
||||||
13 | lower = 0
|
11 | lower = 0
|
||||||
14 | Camel = 0
|
12 | Camel = 0
|
||||||
| ^^^^^ N806
|
| ^^^^^ N806
|
||||||
15 | CONSTANT = 0
|
13 | CONSTANT = 0
|
||||||
16 | _ = 0
|
14 | _ = 0
|
||||||
|
|
|
|
||||||
|
|
||||||
N806.py:15:5: N806 Variable `CONSTANT` in function should be lowercase
|
N806.py:13:5: N806 Variable `CONSTANT` in function should be lowercase
|
||||||
|
|
|
|
||||||
13 | lower = 0
|
11 | lower = 0
|
||||||
14 | Camel = 0
|
12 | Camel = 0
|
||||||
15 | CONSTANT = 0
|
13 | CONSTANT = 0
|
||||||
| ^^^^^^^^ N806
|
| ^^^^^^^^ N806
|
||||||
16 | _ = 0
|
14 | _ = 0
|
||||||
|
|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue