mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-18 01:20:24 +00:00
Rename semantic_model
and model
usages to semantic
(#5097)
## Summary As discussed in Discord, and similar to oxc, we're going to refer to this as `.semantic()` everywhere. While I was auditing usages of `model: &SemanticModel`, I also changed as many function signatures as I could find to consistently take the model as the _last_ argument, rather than the first.
This commit is contained in:
parent
65dbfd2556
commit
bae183b823
209 changed files with 1058 additions and 1167 deletions
File diff suppressed because it is too large
Load diff
|
@ -116,7 +116,7 @@ impl<'a> Importer<'a> {
|
|||
&self,
|
||||
import: &StmtImports,
|
||||
at: TextSize,
|
||||
semantic_model: &SemanticModel,
|
||||
semantic: &SemanticModel,
|
||||
) -> Result<TypingImportEdit> {
|
||||
// Generate the modified import statement.
|
||||
let content = autofix::codemods::retain_imports(
|
||||
|
@ -130,7 +130,7 @@ impl<'a> Importer<'a> {
|
|||
let (type_checking_edit, type_checking) = self.get_or_import_symbol(
|
||||
&ImportRequest::import_from("typing", "TYPE_CHECKING"),
|
||||
at,
|
||||
semantic_model,
|
||||
semantic,
|
||||
)?;
|
||||
|
||||
// Add the import to a `TYPE_CHECKING` block.
|
||||
|
@ -164,11 +164,11 @@ impl<'a> Importer<'a> {
|
|||
&self,
|
||||
symbol: &ImportRequest,
|
||||
at: TextSize,
|
||||
semantic_model: &SemanticModel,
|
||||
semantic: &SemanticModel,
|
||||
) -> Result<(Edit, String), ResolutionError> {
|
||||
match self.get_symbol(symbol, at, semantic_model) {
|
||||
match self.get_symbol(symbol, at, semantic) {
|
||||
Some(result) => result,
|
||||
None => self.import_symbol(symbol, at, semantic_model),
|
||||
None => self.import_symbol(symbol, at, semantic),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,11 +177,10 @@ impl<'a> Importer<'a> {
|
|||
&self,
|
||||
symbol: &ImportRequest,
|
||||
at: TextSize,
|
||||
semantic_model: &SemanticModel,
|
||||
semantic: &SemanticModel,
|
||||
) -> Option<Result<(Edit, String), ResolutionError>> {
|
||||
// If the symbol is already available in the current scope, use it.
|
||||
let imported_name =
|
||||
semantic_model.resolve_qualified_import_name(symbol.module, symbol.member)?;
|
||||
let imported_name = semantic.resolve_qualified_import_name(symbol.module, symbol.member)?;
|
||||
|
||||
// If the symbol source (i.e., the import statement) comes after the current location,
|
||||
// abort. For example, we could be generating an edit within a function, and the import
|
||||
|
@ -196,7 +195,7 @@ impl<'a> Importer<'a> {
|
|||
|
||||
// If the symbol source (i.e., the import statement) is in a typing-only context, but we're
|
||||
// in a runtime context, abort.
|
||||
if imported_name.context().is_typing() && semantic_model.execution_context().is_runtime() {
|
||||
if imported_name.context().is_typing() && semantic.execution_context().is_runtime() {
|
||||
return Some(Err(ResolutionError::IncompatibleContext));
|
||||
}
|
||||
|
||||
|
@ -233,13 +232,13 @@ impl<'a> Importer<'a> {
|
|||
&self,
|
||||
symbol: &ImportRequest,
|
||||
at: TextSize,
|
||||
semantic_model: &SemanticModel,
|
||||
semantic: &SemanticModel,
|
||||
) -> Result<(Edit, String), ResolutionError> {
|
||||
if let Some(stmt) = self.find_import_from(symbol.module, at) {
|
||||
// Case 1: `from functools import lru_cache` is in scope, and we're trying to reference
|
||||
// `functools.cache`; thus, we add `cache` to the import, and return `"cache"` as the
|
||||
// bound name.
|
||||
if semantic_model.is_available(symbol.member) {
|
||||
if semantic.is_available(symbol.member) {
|
||||
let Ok(import_edit) = self.add_member(stmt, symbol.member) else {
|
||||
return Err(ResolutionError::InvalidEdit);
|
||||
};
|
||||
|
@ -252,7 +251,7 @@ impl<'a> Importer<'a> {
|
|||
ImportStyle::Import => {
|
||||
// Case 2a: No `functools` import is in scope; thus, we add `import functools`,
|
||||
// and return `"functools.cache"` as the bound name.
|
||||
if semantic_model.is_available(symbol.module) {
|
||||
if semantic.is_available(symbol.module) {
|
||||
let import_edit =
|
||||
self.add_import(&AnyImport::Import(Import::module(symbol.module)), at);
|
||||
Ok((
|
||||
|
@ -270,7 +269,7 @@ impl<'a> Importer<'a> {
|
|||
ImportStyle::ImportFrom => {
|
||||
// Case 2b: No `functools` import is in scope; thus, we add
|
||||
// `from functools import cache`, and return `"cache"` as the bound name.
|
||||
if semantic_model.is_available(symbol.member) {
|
||||
if semantic.is_available(symbol.member) {
|
||||
let import_edit = self.add_import(
|
||||
&AnyImport::ImportFrom(ImportFrom::member(
|
||||
symbol.module,
|
||||
|
|
|
@ -67,7 +67,7 @@ pub(crate) fn variable_name_task_id(
|
|||
|
||||
// If the function doesn't come from Airflow, we can't do anything.
|
||||
if !checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| matches!(call_path[0], "airflow"))
|
||||
{
|
||||
|
|
|
@ -2,8 +2,8 @@ use rustpython_parser::ast::Expr;
|
|||
|
||||
use ruff_python_semantic::SemanticModel;
|
||||
|
||||
pub(super) fn is_sys(model: &SemanticModel, expr: &Expr, target: &str) -> bool {
|
||||
model
|
||||
pub(super) fn is_sys(expr: &Expr, target: &str, semantic: &SemanticModel) -> bool {
|
||||
semantic
|
||||
.resolve_call_path(expr)
|
||||
.map_or(false, |call_path| call_path.as_slice() == ["sys", target])
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ impl Violation for SysVersionCmpStr10 {
|
|||
pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], comparators: &[Expr]) {
|
||||
match left {
|
||||
Expr::Subscript(ast::ExprSubscript { value, slice, .. })
|
||||
if is_sys(checker.semantic_model(), value, "version_info") =>
|
||||
if is_sys(value, "version_info", checker.semantic()) =>
|
||||
{
|
||||
if let Expr::Constant(ast::ExprConstant {
|
||||
value: Constant::Int(i),
|
||||
|
@ -111,7 +111,7 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], compara
|
|||
}
|
||||
|
||||
Expr::Attribute(ast::ExprAttribute { value, attr, .. })
|
||||
if is_sys(checker.semantic_model(), value, "version_info") && attr == "minor" =>
|
||||
if is_sys(value, "version_info", checker.semantic()) && attr == "minor" =>
|
||||
{
|
||||
if let (
|
||||
[Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE],
|
||||
|
@ -132,7 +132,7 @@ pub(crate) fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], compara
|
|||
_ => {}
|
||||
}
|
||||
|
||||
if is_sys(checker.semantic_model(), left, "version") {
|
||||
if is_sys(left, "version", checker.semantic()) {
|
||||
if let (
|
||||
[Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE],
|
||||
[Expr::Constant(ast::ExprConstant {
|
||||
|
|
|
@ -18,7 +18,7 @@ impl Violation for SixPY3 {
|
|||
/// YTT202
|
||||
pub(crate) fn name_or_attribute(checker: &mut Checker, expr: &Expr) {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(expr)
|
||||
.map_or(false, |call_path| call_path.as_slice() == ["six", "PY3"])
|
||||
{
|
||||
|
|
|
@ -50,7 +50,7 @@ impl Violation for SysVersionSlice1 {
|
|||
|
||||
/// YTT101, YTT102, YTT301, YTT303
|
||||
pub(crate) fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) {
|
||||
if is_sys(checker.semantic_model(), value, "version") {
|
||||
if is_sys(value, "version", checker.semantic()) {
|
||||
match slice {
|
||||
Expr::Slice(ast::ExprSlice {
|
||||
lower: None,
|
||||
|
|
|
@ -35,14 +35,14 @@ pub(super) fn match_function_def(
|
|||
}
|
||||
|
||||
/// Return the name of the function, if it's overloaded.
|
||||
pub(crate) fn overloaded_name(model: &SemanticModel, definition: &Definition) -> Option<String> {
|
||||
pub(crate) fn overloaded_name(definition: &Definition, semantic: &SemanticModel) -> Option<String> {
|
||||
if let Definition::Member(Member {
|
||||
kind: MemberKind::Function | MemberKind::NestedFunction | MemberKind::Method,
|
||||
stmt,
|
||||
..
|
||||
}) = definition
|
||||
{
|
||||
if visibility::is_overload(model, cast::decorator_list(stmt)) {
|
||||
if visibility::is_overload(cast::decorator_list(stmt), semantic) {
|
||||
let (name, ..) = match_function_def(stmt);
|
||||
Some(name.to_string())
|
||||
} else {
|
||||
|
@ -56,9 +56,9 @@ pub(crate) fn overloaded_name(model: &SemanticModel, definition: &Definition) ->
|
|||
/// Return `true` if the definition is the implementation for an overloaded
|
||||
/// function.
|
||||
pub(crate) fn is_overload_impl(
|
||||
model: &SemanticModel,
|
||||
definition: &Definition,
|
||||
overloaded_name: &str,
|
||||
semantic: &SemanticModel,
|
||||
) -> bool {
|
||||
if let Definition::Member(Member {
|
||||
kind: MemberKind::Function | MemberKind::NestedFunction | MemberKind::Method,
|
||||
|
@ -66,7 +66,7 @@ pub(crate) fn is_overload_impl(
|
|||
..
|
||||
}) = definition
|
||||
{
|
||||
if visibility::is_overload(model, cast::decorator_list(stmt)) {
|
||||
if visibility::is_overload(cast::decorator_list(stmt), semantic) {
|
||||
false
|
||||
} else {
|
||||
let (name, ..) = match_function_def(stmt);
|
||||
|
|
|
@ -431,15 +431,15 @@ fn is_none_returning(body: &[Stmt]) -> bool {
|
|||
|
||||
/// ANN401
|
||||
fn check_dynamically_typed<F>(
|
||||
model: &SemanticModel,
|
||||
annotation: &Expr,
|
||||
func: F,
|
||||
diagnostics: &mut Vec<Diagnostic>,
|
||||
is_overridden: bool,
|
||||
semantic: &SemanticModel,
|
||||
) where
|
||||
F: FnOnce() -> String,
|
||||
{
|
||||
if !is_overridden && model.match_typing_expr(annotation, "Any") {
|
||||
if !is_overridden && semantic.match_typing_expr(annotation, "Any") {
|
||||
diagnostics.push(Diagnostic::new(
|
||||
AnyType { name: func() },
|
||||
annotation.range(),
|
||||
|
@ -480,7 +480,7 @@ pub(crate) fn definition(
|
|||
// unless configured to suppress ANN* for declarations that are fully untyped.
|
||||
let mut diagnostics = Vec::new();
|
||||
|
||||
let is_overridden = visibility::is_override(checker.semantic_model(), decorator_list);
|
||||
let is_overridden = visibility::is_override(decorator_list, checker.semantic());
|
||||
|
||||
// ANN001, ANN401
|
||||
for arg in args
|
||||
|
@ -492,10 +492,7 @@ pub(crate) fn definition(
|
|||
// If this is a non-static method, skip `cls` or `self`.
|
||||
usize::from(
|
||||
is_method
|
||||
&& !visibility::is_staticmethod(
|
||||
checker.semantic_model(),
|
||||
cast::decorator_list(stmt),
|
||||
),
|
||||
&& !visibility::is_staticmethod(cast::decorator_list(stmt), checker.semantic()),
|
||||
),
|
||||
)
|
||||
{
|
||||
|
@ -504,11 +501,11 @@ pub(crate) fn definition(
|
|||
has_any_typed_arg = true;
|
||||
if checker.enabled(Rule::AnyType) {
|
||||
check_dynamically_typed(
|
||||
checker.semantic_model(),
|
||||
annotation,
|
||||
|| arg.arg.to_string(),
|
||||
&mut diagnostics,
|
||||
is_overridden,
|
||||
checker.semantic(),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
@ -535,11 +532,11 @@ pub(crate) fn definition(
|
|||
if checker.enabled(Rule::AnyType) {
|
||||
let name = &arg.arg;
|
||||
check_dynamically_typed(
|
||||
checker.semantic_model(),
|
||||
expr,
|
||||
|| format!("*{name}"),
|
||||
&mut diagnostics,
|
||||
is_overridden,
|
||||
checker.semantic(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -567,11 +564,11 @@ pub(crate) fn definition(
|
|||
if checker.enabled(Rule::AnyType) {
|
||||
let name = &arg.arg;
|
||||
check_dynamically_typed(
|
||||
checker.semantic_model(),
|
||||
expr,
|
||||
|| format!("**{name}"),
|
||||
&mut diagnostics,
|
||||
is_overridden,
|
||||
checker.semantic(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -592,13 +589,10 @@ pub(crate) fn definition(
|
|||
}
|
||||
|
||||
// ANN101, ANN102
|
||||
if is_method
|
||||
&& !visibility::is_staticmethod(checker.semantic_model(), cast::decorator_list(stmt))
|
||||
{
|
||||
if is_method && !visibility::is_staticmethod(cast::decorator_list(stmt), checker.semantic()) {
|
||||
if let Some(arg) = args.posonlyargs.first().or_else(|| args.args.first()) {
|
||||
if arg.annotation.is_none() {
|
||||
if visibility::is_classmethod(checker.semantic_model(), cast::decorator_list(stmt))
|
||||
{
|
||||
if visibility::is_classmethod(cast::decorator_list(stmt), checker.semantic()) {
|
||||
if checker.enabled(Rule::MissingTypeCls) {
|
||||
diagnostics.push(Diagnostic::new(
|
||||
MissingTypeCls {
|
||||
|
@ -628,11 +622,11 @@ pub(crate) fn definition(
|
|||
has_typed_return = true;
|
||||
if checker.enabled(Rule::AnyType) {
|
||||
check_dynamically_typed(
|
||||
checker.semantic_model(),
|
||||
expr,
|
||||
|| name.to_string(),
|
||||
&mut diagnostics,
|
||||
is_overridden,
|
||||
checker.semantic(),
|
||||
);
|
||||
}
|
||||
} else if !(
|
||||
|
@ -640,9 +634,7 @@ pub(crate) fn definition(
|
|||
// (explicitly or implicitly).
|
||||
checker.settings.flake8_annotations.suppress_none_returning && is_none_returning(body)
|
||||
) {
|
||||
if is_method
|
||||
&& visibility::is_classmethod(checker.semantic_model(), cast::decorator_list(stmt))
|
||||
{
|
||||
if is_method && visibility::is_classmethod(cast::decorator_list(stmt), checker.semantic()) {
|
||||
if checker.enabled(Rule::MissingReturnTypeClassMethod) {
|
||||
diagnostics.push(Diagnostic::new(
|
||||
MissingReturnTypeClassMethod {
|
||||
|
@ -652,7 +644,7 @@ pub(crate) fn definition(
|
|||
));
|
||||
}
|
||||
} else if is_method
|
||||
&& visibility::is_staticmethod(checker.semantic_model(), cast::decorator_list(stmt))
|
||||
&& visibility::is_staticmethod(cast::decorator_list(stmt), checker.semantic())
|
||||
{
|
||||
if checker.enabled(Rule::MissingReturnTypeStaticMethod) {
|
||||
diagnostics.push(Diagnostic::new(
|
||||
|
|
|
@ -64,9 +64,9 @@ const BLOCKING_HTTP_CALLS: &[&[&str]] = &[
|
|||
|
||||
/// ASYNC100
|
||||
pub(crate) fn blocking_http_call(checker: &mut Checker, expr: &Expr) {
|
||||
if checker.semantic_model().in_async_context() {
|
||||
if checker.semantic().in_async_context() {
|
||||
if let Expr::Call(ast::ExprCall { func, .. }) = expr {
|
||||
let call_path = checker.semantic_model().resolve_call_path(func);
|
||||
let call_path = checker.semantic().resolve_call_path(func);
|
||||
let is_blocking =
|
||||
call_path.map_or(false, |path| BLOCKING_HTTP_CALLS.contains(&path.as_slice()));
|
||||
|
||||
|
|
|
@ -56,10 +56,10 @@ const UNSAFE_OS_METHODS: &[&[&str]] = &[
|
|||
|
||||
/// ASYNC102
|
||||
pub(crate) fn blocking_os_call(checker: &mut Checker, expr: &Expr) {
|
||||
if checker.semantic_model().in_async_context() {
|
||||
if checker.semantic().in_async_context() {
|
||||
if let Expr::Call(ast::ExprCall { func, .. }) = expr {
|
||||
let is_unsafe_os_method = checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |path| UNSAFE_OS_METHODS.contains(&path.as_slice()));
|
||||
|
||||
|
|
|
@ -59,10 +59,10 @@ const OPEN_SLEEP_OR_SUBPROCESS_CALL: &[&[&str]] = &[
|
|||
|
||||
/// ASYNC101
|
||||
pub(crate) fn open_sleep_or_subprocess_call(checker: &mut Checker, expr: &Expr) {
|
||||
if checker.semantic_model().in_async_context() {
|
||||
if checker.semantic().in_async_context() {
|
||||
if let Expr::Call(ast::ExprCall { func, .. }) = expr {
|
||||
let is_open_sleep_or_subprocess_call = checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |path| {
|
||||
OPEN_SLEEP_OR_SUBPROCESS_CALL.contains(&path.as_slice())
|
||||
|
|
|
@ -22,17 +22,21 @@ pub(super) fn matches_password_name(string: &str) -> bool {
|
|||
PASSWORD_CANDIDATE_REGEX.is_match(string)
|
||||
}
|
||||
|
||||
pub(super) fn is_untyped_exception(type_: Option<&Expr>, model: &SemanticModel) -> bool {
|
||||
pub(super) fn is_untyped_exception(type_: Option<&Expr>, semantic: &SemanticModel) -> bool {
|
||||
type_.map_or(true, |type_| {
|
||||
if let Expr::Tuple(ast::ExprTuple { elts, .. }) = &type_ {
|
||||
elts.iter().any(|type_| {
|
||||
model.resolve_call_path(type_).map_or(false, |call_path| {
|
||||
semantic
|
||||
.resolve_call_path(type_)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["", "Exception"]
|
||||
|| call_path.as_slice() == ["", "BaseException"]
|
||||
})
|
||||
})
|
||||
} else {
|
||||
model.resolve_call_path(type_).map_or(false, |call_path| {
|
||||
semantic
|
||||
.resolve_call_path(type_)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["", "Exception"]
|
||||
|| call_path.as_slice() == ["", "BaseException"]
|
||||
})
|
||||
|
|
|
@ -108,7 +108,7 @@ pub(crate) fn bad_file_permissions(
|
|||
keywords: &[Keyword],
|
||||
) {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| call_path.as_slice() == ["os", "chmod"])
|
||||
{
|
||||
|
|
|
@ -60,7 +60,7 @@ fn unparse_string_format_expression(checker: &mut Checker, expr: &Expr) -> Optio
|
|||
op: Operator::Add | Operator::Mod,
|
||||
..
|
||||
}) => {
|
||||
let Some(parent) = checker.semantic_model().expr_parent() else {
|
||||
let Some(parent) = checker.semantic().expr_parent() else {
|
||||
if any_over_expr(expr, &has_string_literal) {
|
||||
return Some(checker.generator().expr(expr));
|
||||
}
|
||||
|
|
|
@ -48,9 +48,8 @@ pub(crate) fn hashlib_insecure_hash_functions(
|
|||
args: &[Expr],
|
||||
keywords: &[Keyword],
|
||||
) {
|
||||
if let Some(hashlib_call) =
|
||||
checker
|
||||
.semantic_model()
|
||||
if let Some(hashlib_call) = checker
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.and_then(|call_path| {
|
||||
if call_path.as_slice() == ["hashlib", "new"] {
|
||||
|
|
|
@ -37,7 +37,7 @@ pub(crate) fn jinja2_autoescape_false(
|
|||
keywords: &[Keyword],
|
||||
) {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["jinja2", "Environment"]
|
||||
|
|
|
@ -24,7 +24,7 @@ pub(crate) fn logging_config_insecure_listen(
|
|||
keywords: &[Keyword],
|
||||
) {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["logging", "config", "listen"]
|
||||
|
|
|
@ -18,7 +18,7 @@ impl Violation for ParamikoCall {
|
|||
/// S601
|
||||
pub(crate) fn paramiko_call(checker: &mut Checker, func: &Expr) {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["paramiko", "exec_command"]
|
||||
|
|
|
@ -44,7 +44,7 @@ pub(crate) fn request_with_no_cert_validation(
|
|||
keywords: &[Keyword],
|
||||
) {
|
||||
if let Some(target) = checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.and_then(|call_path| {
|
||||
if call_path.len() == 2 {
|
||||
|
|
|
@ -34,7 +34,7 @@ pub(crate) fn request_without_timeout(
|
|||
keywords: &[Keyword],
|
||||
) {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
HTTP_VERBS
|
||||
|
|
|
@ -102,8 +102,8 @@ pub(crate) fn shell_injection(
|
|||
args: &[Expr],
|
||||
keywords: &[Keyword],
|
||||
) {
|
||||
let call_kind = get_call_kind(func, checker.semantic_model());
|
||||
let shell_keyword = find_shell_keyword(checker.semantic_model(), keywords);
|
||||
let call_kind = get_call_kind(func, checker.semantic());
|
||||
let shell_keyword = find_shell_keyword(keywords, checker.semantic());
|
||||
|
||||
if matches!(call_kind, Some(CallKind::Subprocess)) {
|
||||
if let Some(arg) = args.first() {
|
||||
|
@ -227,8 +227,8 @@ enum CallKind {
|
|||
}
|
||||
|
||||
/// Return the [`CallKind`] of the given function call.
|
||||
fn get_call_kind(func: &Expr, model: &SemanticModel) -> Option<CallKind> {
|
||||
model
|
||||
fn get_call_kind(func: &Expr, semantic: &SemanticModel) -> Option<CallKind> {
|
||||
semantic
|
||||
.resolve_call_path(func)
|
||||
.and_then(|call_path| match call_path.as_slice() {
|
||||
&[module, submodule] => match module {
|
||||
|
@ -269,14 +269,14 @@ struct ShellKeyword<'a> {
|
|||
|
||||
/// Return the `shell` keyword argument to the given function call, if any.
|
||||
fn find_shell_keyword<'a>(
|
||||
model: &SemanticModel,
|
||||
keywords: &'a [Keyword],
|
||||
semantic: &SemanticModel,
|
||||
) -> Option<ShellKeyword<'a>> {
|
||||
keywords
|
||||
.iter()
|
||||
.find(|keyword| keyword.arg.as_ref().map_or(false, |arg| arg == "shell"))
|
||||
.map(|keyword| ShellKeyword {
|
||||
truthiness: Truthiness::from_expr(&keyword.value, |id| model.is_builtin(id)),
|
||||
truthiness: Truthiness::from_expr(&keyword.value, |id| semantic.is_builtin(id)),
|
||||
keyword,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ pub(crate) fn snmp_insecure_version(
|
|||
keywords: &[Keyword],
|
||||
) {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["pysnmp", "hlapi", "CommunityData"]
|
||||
|
|
|
@ -27,7 +27,7 @@ pub(crate) fn snmp_weak_cryptography(
|
|||
keywords: &[Keyword],
|
||||
) {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["pysnmp", "hlapi", "UsmUserData"]
|
||||
|
|
|
@ -470,7 +470,7 @@ pub(crate) fn suspicious_function_call(checker: &mut Checker, expr: &Expr) {
|
|||
return;
|
||||
};
|
||||
|
||||
let Some(reason) = checker.semantic_model().resolve_call_path(func).and_then(|call_path| {
|
||||
let Some(reason) = checker.semantic().resolve_call_path(func).and_then(|call_path| {
|
||||
for module in SUSPICIOUS_MEMBERS {
|
||||
for member in module.members {
|
||||
if call_path.as_slice() == *member {
|
||||
|
|
|
@ -27,7 +27,7 @@ pub(crate) fn try_except_continue(
|
|||
) {
|
||||
if body.len() == 1
|
||||
&& body[0].is_continue_stmt()
|
||||
&& (check_typed_exception || is_untyped_exception(type_, checker.semantic_model()))
|
||||
&& (check_typed_exception || is_untyped_exception(type_, checker.semantic()))
|
||||
{
|
||||
checker
|
||||
.diagnostics
|
||||
|
|
|
@ -27,7 +27,7 @@ pub(crate) fn try_except_pass(
|
|||
) {
|
||||
if body.len() == 1
|
||||
&& body[0].is_pass_stmt()
|
||||
&& (check_typed_exception || is_untyped_exception(type_, checker.semantic_model()))
|
||||
&& (check_typed_exception || is_untyped_exception(type_, checker.semantic()))
|
||||
{
|
||||
checker
|
||||
.diagnostics
|
||||
|
|
|
@ -38,14 +38,14 @@ pub(crate) fn unsafe_yaml_load(
|
|||
keywords: &[Keyword],
|
||||
) {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| call_path.as_slice() == ["yaml", "load"])
|
||||
{
|
||||
let call_args = SimpleCallArgs::new(args, keywords);
|
||||
if let Some(loader_arg) = call_args.argument("Loader", 1) {
|
||||
if !checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(loader_arg)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["yaml", "SafeLoader"]
|
||||
|
|
|
@ -34,7 +34,7 @@ pub(crate) fn blind_except(
|
|||
return;
|
||||
};
|
||||
for exception in ["BaseException", "Exception"] {
|
||||
if id == exception && checker.semantic_model().is_builtin(exception) {
|
||||
if id == exception && checker.semantic().is_builtin(exception) {
|
||||
// If the exception is re-raised, don't flag an error.
|
||||
if body.iter().any(|stmt| {
|
||||
if let Stmt::Raise(ast::StmtRaise { exc, .. }) = stmt {
|
||||
|
@ -58,7 +58,7 @@ pub(crate) fn blind_except(
|
|||
if body.iter().any(|stmt| {
|
||||
if let Stmt::Expr(ast::StmtExpr { value, range: _ }) = stmt {
|
||||
if let Expr::Call(ast::ExprCall { func, keywords, .. }) = value.as_ref() {
|
||||
if logging::is_logger_candidate(func, checker.semantic_model()) {
|
||||
if logging::is_logger_candidate(func, checker.semantic()) {
|
||||
if let Some(attribute) = func.as_attribute_expr() {
|
||||
let attr = attribute.attr.as_str();
|
||||
if attr == "exception" {
|
||||
|
|
|
@ -36,16 +36,16 @@ impl Violation for EmptyMethodWithoutAbstractDecorator {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_abc_class(model: &SemanticModel, bases: &[Expr], keywords: &[Keyword]) -> bool {
|
||||
fn is_abc_class(bases: &[Expr], keywords: &[Keyword], semantic: &SemanticModel) -> bool {
|
||||
keywords.iter().any(|keyword| {
|
||||
keyword.arg.as_ref().map_or(false, |arg| arg == "metaclass")
|
||||
&& model
|
||||
&& semantic
|
||||
.resolve_call_path(&keyword.value)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["abc", "ABCMeta"]
|
||||
})
|
||||
}) || bases.iter().any(|base| {
|
||||
model
|
||||
semantic
|
||||
.resolve_call_path(base)
|
||||
.map_or(false, |call_path| call_path.as_slice() == ["abc", "ABC"])
|
||||
})
|
||||
|
@ -80,7 +80,7 @@ pub(crate) fn abstract_base_class(
|
|||
if bases.len() + keywords.len() != 1 {
|
||||
return;
|
||||
}
|
||||
if !is_abc_class(checker.semantic_model(), bases, keywords) {
|
||||
if !is_abc_class(bases, keywords, checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ pub(crate) fn abstract_base_class(
|
|||
continue;
|
||||
};
|
||||
|
||||
let has_abstract_decorator = is_abstract(checker.semantic_model(), decorator_list);
|
||||
let has_abstract_decorator = is_abstract(decorator_list, checker.semantic());
|
||||
has_abstract_method |= has_abstract_decorator;
|
||||
|
||||
if !checker.enabled(Rule::EmptyMethodWithoutAbstractDecorator) {
|
||||
|
@ -118,7 +118,7 @@ pub(crate) fn abstract_base_class(
|
|||
|
||||
if !has_abstract_decorator
|
||||
&& is_empty_body(body)
|
||||
&& !is_overload(checker.semantic_model(), decorator_list)
|
||||
&& !is_overload(decorator_list, checker.semantic())
|
||||
{
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
EmptyMethodWithoutAbstractDecorator {
|
||||
|
|
|
@ -66,7 +66,7 @@ pub(crate) fn assert_raises_exception(checker: &mut Checker, stmt: &Stmt, items:
|
|||
}
|
||||
|
||||
if !checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(args.first().unwrap())
|
||||
.map_or(false, |call_path| call_path.as_slice() == ["", "Exception"])
|
||||
{
|
||||
|
@ -78,7 +78,7 @@ pub(crate) fn assert_raises_exception(checker: &mut Checker, stmt: &Stmt, items:
|
|||
{
|
||||
AssertionKind::AssertRaises
|
||||
} else if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["pytest", "raises"]
|
||||
|
|
|
@ -18,8 +18,8 @@ impl Violation for CachedInstanceMethod {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_cache_func(model: &SemanticModel, expr: &Expr) -> bool {
|
||||
model.resolve_call_path(expr).map_or(false, |call_path| {
|
||||
fn is_cache_func(expr: &Expr, semantic: &SemanticModel) -> bool {
|
||||
semantic.resolve_call_path(expr).map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["functools", "lru_cache"]
|
||||
|| call_path.as_slice() == ["functools", "cache"]
|
||||
})
|
||||
|
@ -27,7 +27,7 @@ fn is_cache_func(model: &SemanticModel, expr: &Expr) -> bool {
|
|||
|
||||
/// B019
|
||||
pub(crate) fn cached_instance_method(checker: &mut Checker, decorator_list: &[Decorator]) {
|
||||
if !checker.semantic_model().scope().kind.is_class() {
|
||||
if !checker.semantic().scope().kind.is_class() {
|
||||
return;
|
||||
}
|
||||
for decorator in decorator_list {
|
||||
|
@ -41,11 +41,11 @@ pub(crate) fn cached_instance_method(checker: &mut Checker, decorator_list: &[De
|
|||
}
|
||||
for decorator in decorator_list {
|
||||
if is_cache_func(
|
||||
checker.semantic_model(),
|
||||
match &decorator.expression {
|
||||
Expr::Call(ast::ExprCall { func, .. }) => func,
|
||||
_ => &decorator.expression,
|
||||
},
|
||||
checker.semantic(),
|
||||
) {
|
||||
checker
|
||||
.diagnostics
|
||||
|
|
|
@ -73,7 +73,7 @@ impl Violation for FunctionCallInDefaultArgument {
|
|||
}
|
||||
|
||||
struct ArgumentDefaultVisitor<'a> {
|
||||
model: &'a SemanticModel<'a>,
|
||||
semantic: &'a SemanticModel<'a>,
|
||||
extend_immutable_calls: Vec<CallPath<'a>>,
|
||||
diagnostics: Vec<(DiagnosticKind, TextRange)>,
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ struct ArgumentDefaultVisitor<'a> {
|
|||
impl<'a> ArgumentDefaultVisitor<'a> {
|
||||
fn new(model: &'a SemanticModel<'a>, extend_immutable_calls: Vec<CallPath<'a>>) -> Self {
|
||||
Self {
|
||||
model,
|
||||
semantic: model,
|
||||
extend_immutable_calls,
|
||||
diagnostics: Vec::new(),
|
||||
}
|
||||
|
@ -95,8 +95,8 @@ where
|
|||
fn visit_expr(&mut self, expr: &'b Expr) {
|
||||
match expr {
|
||||
Expr::Call(ast::ExprCall { func, .. }) => {
|
||||
if !is_mutable_func(self.model, func)
|
||||
&& !is_immutable_func(self.model, func, &self.extend_immutable_calls)
|
||||
if !is_mutable_func(func, self.semantic)
|
||||
&& !is_immutable_func(func, self.semantic, &self.extend_immutable_calls)
|
||||
{
|
||||
self.diagnostics.push((
|
||||
FunctionCallInDefaultArgument {
|
||||
|
@ -125,8 +125,7 @@ pub(crate) fn function_call_argument_default(checker: &mut Checker, arguments: &
|
|||
.map(|target| from_qualified_name(target))
|
||||
.collect();
|
||||
let diagnostics = {
|
||||
let mut visitor =
|
||||
ArgumentDefaultVisitor::new(checker.semantic_model(), extend_immutable_calls);
|
||||
let mut visitor = ArgumentDefaultVisitor::new(checker.semantic(), extend_immutable_calls);
|
||||
for expr in arguments
|
||||
.defaults
|
||||
.iter()
|
||||
|
|
|
@ -26,15 +26,15 @@ const MUTABLE_FUNCS: &[&[&str]] = &[
|
|||
&["collections", "deque"],
|
||||
];
|
||||
|
||||
pub(crate) fn is_mutable_func(model: &SemanticModel, func: &Expr) -> bool {
|
||||
model.resolve_call_path(func).map_or(false, |call_path| {
|
||||
pub(crate) fn is_mutable_func(func: &Expr, semantic: &SemanticModel) -> bool {
|
||||
semantic.resolve_call_path(func).map_or(false, |call_path| {
|
||||
MUTABLE_FUNCS
|
||||
.iter()
|
||||
.any(|target| call_path.as_slice() == *target)
|
||||
})
|
||||
}
|
||||
|
||||
fn is_mutable_expr(model: &SemanticModel, expr: &Expr) -> bool {
|
||||
fn is_mutable_expr(expr: &Expr, semantic: &SemanticModel) -> bool {
|
||||
match expr {
|
||||
Expr::List(_)
|
||||
| Expr::Dict(_)
|
||||
|
@ -42,7 +42,7 @@ fn is_mutable_expr(model: &SemanticModel, expr: &Expr) -> bool {
|
|||
| Expr::ListComp(_)
|
||||
| Expr::DictComp(_)
|
||||
| Expr::SetComp(_) => true,
|
||||
Expr::Call(ast::ExprCall { func, .. }) => is_mutable_func(model, func),
|
||||
Expr::Call(ast::ExprCall { func, .. }) => is_mutable_func(func, semantic),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -64,9 +64,9 @@ pub(crate) fn mutable_argument_default(checker: &mut Checker, arguments: &Argume
|
|||
.zip(arguments.defaults.iter().rev()),
|
||||
)
|
||||
{
|
||||
if is_mutable_expr(checker.semantic_model(), default)
|
||||
if is_mutable_expr(default, checker.semantic())
|
||||
&& !arg.annotation.as_ref().map_or(false, |expr| {
|
||||
is_immutable_annotation(checker.semantic_model(), expr)
|
||||
is_immutable_annotation(expr, checker.semantic())
|
||||
})
|
||||
{
|
||||
checker
|
||||
|
|
|
@ -45,7 +45,7 @@ pub(crate) fn no_explicit_stacklevel(
|
|||
keywords: &[Keyword],
|
||||
) {
|
||||
if !checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["warnings", "warn"]
|
||||
|
|
|
@ -342,7 +342,7 @@ pub(crate) fn reuse_of_groupby_generator(
|
|||
};
|
||||
// Check if the function call is `itertools.groupby`
|
||||
if !checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["itertools", "groupby"]
|
||||
|
|
|
@ -75,7 +75,7 @@ pub(crate) fn setattr_with_constant(
|
|||
if let Stmt::Expr(ast::StmtExpr {
|
||||
value: child,
|
||||
range: _,
|
||||
}) = checker.semantic_model().stmt()
|
||||
}) = checker.semantic().stmt()
|
||||
{
|
||||
if expr == child.as_ref() {
|
||||
let mut diagnostic = Diagnostic::new(SetAttrWithConstant, expr.range());
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
use rustc_hash::FxHashMap;
|
||||
use rustpython_parser::ast::{self, Expr, Ranged, Stmt};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
|
@ -30,7 +29,7 @@ use ruff_python_ast::{helpers, visitor};
|
|||
use crate::checkers::ast::Checker;
|
||||
use crate::registry::AsRule;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, result_like::BoolLike)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, result_like::BoolLike)]
|
||||
enum Certainty {
|
||||
Certain,
|
||||
Uncertain,
|
||||
|
@ -129,7 +128,7 @@ pub(crate) fn unused_loop_control_variable(checker: &mut Checker, target: &Expr,
|
|||
|
||||
// Avoid fixing any variables that _may_ be used, but undetectably so.
|
||||
let certainty = Certainty::from(!helpers::uses_magic_variable_access(body, |id| {
|
||||
checker.semantic_model().is_builtin(id)
|
||||
checker.semantic().is_builtin(id)
|
||||
}));
|
||||
|
||||
// Attempt to rename the variable by prepending an underscore, but avoid
|
||||
|
@ -154,10 +153,10 @@ pub(crate) fn unused_loop_control_variable(checker: &mut Checker, target: &Expr,
|
|||
if certainty.into() && checker.patch(diagnostic.kind.rule()) {
|
||||
// Avoid fixing if the variable, or any future bindings to the variable, are
|
||||
// used _after_ the loop.
|
||||
let scope = checker.semantic_model().scope();
|
||||
let scope = checker.semantic().scope();
|
||||
if scope
|
||||
.get_all(name)
|
||||
.map(|binding_id| checker.semantic_model().binding(binding_id))
|
||||
.map(|binding_id| checker.semantic().binding(binding_id))
|
||||
.all(|binding| !binding.is_used())
|
||||
{
|
||||
diagnostic.set_fix(Fix::suggested(Edit::range_replacement(
|
||||
|
|
|
@ -27,7 +27,7 @@ pub(crate) fn useless_contextlib_suppress(
|
|||
) {
|
||||
if args.is_empty()
|
||||
&& checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["contextlib", "suppress"]
|
||||
|
|
|
@ -53,7 +53,7 @@ pub(crate) fn useless_expression(checker: &mut Checker, value: &Expr) {
|
|||
}
|
||||
|
||||
// Ignore statements that have side effects.
|
||||
if contains_effect(value, |id| checker.semantic_model().is_builtin(id)) {
|
||||
if contains_effect(value, |id| checker.semantic().is_builtin(id)) {
|
||||
// Flag attributes as useless expressions, even if they're attached to calls or other
|
||||
// expressions.
|
||||
if matches!(value, Expr::Attribute(_)) {
|
||||
|
|
|
@ -27,13 +27,13 @@ pub(crate) fn zip_without_explicit_strict(
|
|||
) {
|
||||
if let Expr::Name(ast::ExprName { id, .. }) = func {
|
||||
if id == "zip"
|
||||
&& checker.semantic_model().is_builtin("zip")
|
||||
&& checker.semantic().is_builtin("zip")
|
||||
&& !kwargs
|
||||
.iter()
|
||||
.any(|keyword| keyword.arg.as_ref().map_or(false, |name| name == "strict"))
|
||||
&& !args
|
||||
.iter()
|
||||
.any(|arg| is_infinite_iterator(arg, checker.semantic_model()))
|
||||
.any(|arg| is_infinite_iterator(arg, checker.semantic()))
|
||||
{
|
||||
checker
|
||||
.diagnostics
|
||||
|
@ -44,14 +44,13 @@ pub(crate) fn zip_without_explicit_strict(
|
|||
|
||||
/// Return `true` if the [`Expr`] appears to be an infinite iterator (e.g., a call to
|
||||
/// `itertools.cycle` or similar).
|
||||
fn is_infinite_iterator(arg: &Expr, model: &SemanticModel) -> bool {
|
||||
fn is_infinite_iterator(arg: &Expr, semantic: &SemanticModel) -> bool {
|
||||
let Expr::Call(ast::ExprCall { func, args, keywords, .. }) = &arg else {
|
||||
return false;
|
||||
};
|
||||
|
||||
return model
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| match call_path.as_slice() {
|
||||
semantic.resolve_call_path(func).map_or(false, |call_path| {
|
||||
match call_path.as_slice() {
|
||||
["itertools", "cycle" | "count"] => true,
|
||||
["itertools", "repeat"] => {
|
||||
// Ex) `itertools.repeat(1)`
|
||||
|
@ -76,5 +75,6 @@ fn is_infinite_iterator(arg: &Expr, model: &SemanticModel) -> bool {
|
|||
false
|
||||
}
|
||||
_ => false,
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -72,11 +72,11 @@ pub(crate) fn builtin_attribute_shadowing(
|
|||
if shadows_builtin(name, &checker.settings.flake8_builtins.builtins_ignorelist) {
|
||||
// Ignore shadowing within `TypedDict` definitions, since these are only accessible through
|
||||
// subscripting and not through attribute access.
|
||||
if class_def.bases.iter().any(|base| {
|
||||
checker
|
||||
.semantic_model()
|
||||
.match_typing_expr(base, "TypedDict")
|
||||
}) {
|
||||
if class_def
|
||||
.bases
|
||||
.iter()
|
||||
.any(|base| checker.semantic().match_typing_expr(base, "TypedDict"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -502,7 +502,7 @@ pub(crate) fn fix_unnecessary_collection_call(
|
|||
/// this method will pad the start and end of an expression as needed to
|
||||
/// avoid producing invalid syntax.
|
||||
fn pad_expression(content: String, range: TextRange, checker: &Checker) -> String {
|
||||
if !checker.semantic_model().in_f_string() {
|
||||
if !checker.semantic().in_f_string() {
|
||||
return content;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ pub(crate) fn unnecessary_call_around_sorted(
|
|||
if inner != "sorted" {
|
||||
return;
|
||||
}
|
||||
if !checker.semantic_model().is_builtin(inner) || !checker.semantic_model().is_builtin(outer) {
|
||||
if !checker.semantic().is_builtin(inner) || !checker.semantic().is_builtin(outer) {
|
||||
return;
|
||||
}
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
|
|
|
@ -79,7 +79,7 @@ pub(crate) fn unnecessary_collection_call(
|
|||
}
|
||||
_ => return,
|
||||
};
|
||||
if !checker.semantic_model().is_builtin(id) {
|
||||
if !checker.semantic().is_builtin(id) {
|
||||
return;
|
||||
}
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
|
|
|
@ -56,7 +56,7 @@ fn add_diagnostic(checker: &mut Checker, expr: &Expr) {
|
|||
Expr::DictComp(_) => "dict",
|
||||
_ => return,
|
||||
};
|
||||
if !checker.semantic_model().is_builtin(id) {
|
||||
if !checker.semantic().is_builtin(id) {
|
||||
return;
|
||||
}
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
|
|
|
@ -76,7 +76,7 @@ pub(crate) fn unnecessary_comprehension_any_all(
|
|||
if is_async_generator(elt) {
|
||||
return;
|
||||
}
|
||||
if !checker.semantic_model().is_builtin(id) {
|
||||
if !checker.semantic().is_builtin(id) {
|
||||
return;
|
||||
}
|
||||
let mut diagnostic = Diagnostic::new(UnnecessaryComprehensionAnyAll, args[0].range());
|
||||
|
|
|
@ -90,7 +90,7 @@ pub(crate) fn unnecessary_double_cast_or_process(
|
|||
let Some(inner) = helpers::expr_name(func) else {
|
||||
return;
|
||||
};
|
||||
if !checker.semantic_model().is_builtin(inner) || !checker.semantic_model().is_builtin(outer) {
|
||||
if !checker.semantic().is_builtin(inner) || !checker.semantic().is_builtin(outer) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ pub(crate) fn unnecessary_generator_list(
|
|||
let Some(argument) = helpers::exactly_one_argument_with_matching_function("list", func, args, keywords) else {
|
||||
return;
|
||||
};
|
||||
if !checker.semantic_model().is_builtin("list") {
|
||||
if !checker.semantic().is_builtin("list") {
|
||||
return;
|
||||
}
|
||||
if let Expr::GeneratorExp(_) = argument {
|
||||
|
|
|
@ -52,7 +52,7 @@ pub(crate) fn unnecessary_generator_set(
|
|||
let Some(argument) = helpers::exactly_one_argument_with_matching_function("set", func, args, keywords) else {
|
||||
return;
|
||||
};
|
||||
if !checker.semantic_model().is_builtin("set") {
|
||||
if !checker.semantic().is_builtin("set") {
|
||||
return;
|
||||
}
|
||||
if let Expr::GeneratorExp(_) = argument {
|
||||
|
|
|
@ -48,7 +48,7 @@ pub(crate) fn unnecessary_list_call(
|
|||
let Some(argument) = helpers::first_argument_with_matching_function("list", func, args) else {
|
||||
return;
|
||||
};
|
||||
if !checker.semantic_model().is_builtin("list") {
|
||||
if !checker.semantic().is_builtin("list") {
|
||||
return;
|
||||
}
|
||||
if !argument.is_list_comp_expr() {
|
||||
|
|
|
@ -50,7 +50,7 @@ pub(crate) fn unnecessary_list_comprehension_dict(
|
|||
let Some(argument) = helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords) else {
|
||||
return;
|
||||
};
|
||||
if !checker.semantic_model().is_builtin("dict") {
|
||||
if !checker.semantic().is_builtin("dict") {
|
||||
return;
|
||||
}
|
||||
let Expr::ListComp(ast::ExprListComp { elt, .. }) = argument else {
|
||||
|
|
|
@ -50,7 +50,7 @@ pub(crate) fn unnecessary_list_comprehension_set(
|
|||
let Some(argument) = helpers::exactly_one_argument_with_matching_function("set", func, args, keywords) else {
|
||||
return;
|
||||
};
|
||||
if !checker.semantic_model().is_builtin("set") {
|
||||
if !checker.semantic().is_builtin("set") {
|
||||
return;
|
||||
}
|
||||
if argument.is_list_comp_expr() {
|
||||
|
|
|
@ -57,7 +57,7 @@ pub(crate) fn unnecessary_literal_dict(
|
|||
let Some(argument) = helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords) else {
|
||||
return;
|
||||
};
|
||||
if !checker.semantic_model().is_builtin("dict") {
|
||||
if !checker.semantic().is_builtin("dict") {
|
||||
return;
|
||||
}
|
||||
let (kind, elts) = match argument {
|
||||
|
|
|
@ -58,7 +58,7 @@ pub(crate) fn unnecessary_literal_set(
|
|||
let Some(argument) = helpers::exactly_one_argument_with_matching_function("set", func, args, keywords) else {
|
||||
return;
|
||||
};
|
||||
if !checker.semantic_model().is_builtin("set") {
|
||||
if !checker.semantic().is_builtin("set") {
|
||||
return;
|
||||
}
|
||||
let kind = match argument {
|
||||
|
|
|
@ -76,7 +76,7 @@ pub(crate) fn unnecessary_literal_within_dict_call(
|
|||
let Some(argument) = helpers::first_argument_with_matching_function("dict", func, args) else {
|
||||
return;
|
||||
};
|
||||
if !checker.semantic_model().is_builtin("dict") {
|
||||
if !checker.semantic().is_builtin("dict") {
|
||||
return;
|
||||
}
|
||||
let argument_kind = match argument {
|
||||
|
|
|
@ -79,7 +79,7 @@ pub(crate) fn unnecessary_literal_within_list_call(
|
|||
let Some(argument) = helpers::first_argument_with_matching_function("list", func, args) else {
|
||||
return;
|
||||
};
|
||||
if !checker.semantic_model().is_builtin("list") {
|
||||
if !checker.semantic().is_builtin("list") {
|
||||
return;
|
||||
}
|
||||
let argument_kind = match argument {
|
||||
|
|
|
@ -80,7 +80,7 @@ pub(crate) fn unnecessary_literal_within_tuple_call(
|
|||
let Some(argument) = helpers::first_argument_with_matching_function("tuple", func, args) else {
|
||||
return;
|
||||
};
|
||||
if !checker.semantic_model().is_builtin("tuple") {
|
||||
if !checker.semantic().is_builtin("tuple") {
|
||||
return;
|
||||
}
|
||||
let argument_kind = match argument {
|
||||
|
|
|
@ -88,7 +88,7 @@ pub(crate) fn unnecessary_map(
|
|||
};
|
||||
match id {
|
||||
"map" => {
|
||||
if !checker.semantic_model().is_builtin(id) {
|
||||
if !checker.semantic().is_builtin(id) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,7 @@ pub(crate) fn unnecessary_map(
|
|||
}
|
||||
}
|
||||
"list" | "set" => {
|
||||
if !checker.semantic_model().is_builtin(id) {
|
||||
if !checker.semantic().is_builtin(id) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,7 @@ pub(crate) fn unnecessary_map(
|
|||
}
|
||||
}
|
||||
"dict" => {
|
||||
if !checker.semantic_model().is_builtin(id) {
|
||||
if !checker.semantic().is_builtin(id) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ pub(crate) fn unnecessary_subscript_reversal(
|
|||
if !(id == "set" || id == "sorted" || id == "reversed") {
|
||||
return;
|
||||
}
|
||||
if !checker.semantic_model().is_builtin(id) {
|
||||
if !checker.semantic().is_builtin(id) {
|
||||
return;
|
||||
}
|
||||
let Expr::Subscript(ast::ExprSubscript { slice, .. }) = first_arg else {
|
||||
|
|
|
@ -27,7 +27,7 @@ impl Violation for CallDateFromtimestamp {
|
|||
/// Use `datetime.datetime.fromtimestamp(, tz=).date()` instead.
|
||||
pub(crate) fn call_date_fromtimestamp(checker: &mut Checker, func: &Expr, location: TextRange) {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["datetime", "date", "fromtimestamp"]
|
||||
|
|
|
@ -27,7 +27,7 @@ impl Violation for CallDateToday {
|
|||
/// Use `datetime.datetime.now(tz=).date()` instead.
|
||||
pub(crate) fn call_date_today(checker: &mut Checker, func: &Expr, location: TextRange) {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["datetime", "date", "today"]
|
||||
|
|
|
@ -28,7 +28,7 @@ pub(crate) fn call_datetime_fromtimestamp(
|
|||
location: TextRange,
|
||||
) {
|
||||
if !checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["datetime", "datetime", "fromtimestamp"]
|
||||
|
|
|
@ -26,7 +26,7 @@ pub(crate) fn call_datetime_now_without_tzinfo(
|
|||
location: TextRange,
|
||||
) {
|
||||
if !checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["datetime", "datetime", "now"]
|
||||
|
|
|
@ -28,7 +28,7 @@ pub(crate) fn call_datetime_strptime_without_zone(
|
|||
location: TextRange,
|
||||
) {
|
||||
if !checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["datetime", "datetime", "strptime"]
|
||||
|
@ -49,7 +49,7 @@ pub(crate) fn call_datetime_strptime_without_zone(
|
|||
}
|
||||
};
|
||||
|
||||
let (Some(grandparent), Some(parent)) = (checker.semantic_model().expr_grandparent(), checker.semantic_model().expr_parent()) else {
|
||||
let (Some(grandparent), Some(parent)) = (checker.semantic().expr_grandparent(), checker.semantic().expr_parent()) else {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
CallDatetimeStrptimeWithoutZone,
|
||||
location,
|
||||
|
|
|
@ -27,7 +27,7 @@ impl Violation for CallDatetimeToday {
|
|||
/// Use `datetime.datetime.now(tz=)` instead.
|
||||
pub(crate) fn call_datetime_today(checker: &mut Checker, func: &Expr, location: TextRange) {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["datetime", "datetime", "today"]
|
||||
|
|
|
@ -34,7 +34,7 @@ pub(crate) fn call_datetime_utcfromtimestamp(
|
|||
location: TextRange,
|
||||
) {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["datetime", "datetime", "utcfromtimestamp"]
|
||||
|
|
|
@ -29,7 +29,7 @@ impl Violation for CallDatetimeUtcnow {
|
|||
/// current time in UTC is by calling `datetime.now(timezone.utc)`.
|
||||
pub(crate) fn call_datetime_utcnow(checker: &mut Checker, func: &Expr, location: TextRange) {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["datetime", "datetime", "utcnow"]
|
||||
|
|
|
@ -25,7 +25,7 @@ pub(crate) fn call_datetime_without_tzinfo(
|
|||
location: TextRange,
|
||||
) {
|
||||
if !checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["datetime", "datetime"]
|
||||
|
|
|
@ -44,7 +44,7 @@ const DEBUGGERS: &[&[&str]] = &[
|
|||
/// Checks for the presence of a debugger call.
|
||||
pub(crate) fn debugger_call(checker: &mut Checker, expr: &Expr, func: &Expr) {
|
||||
if let Some(target) = checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.and_then(|call_path| {
|
||||
DEBUGGERS
|
||||
|
|
|
@ -54,7 +54,7 @@ pub(crate) fn all_with_model_form(
|
|||
) -> Option<Diagnostic> {
|
||||
if !bases
|
||||
.iter()
|
||||
.any(|base| is_model_form(checker.semantic_model(), base))
|
||||
.any(|base| is_model_form(base, checker.semantic()))
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ pub(crate) fn exclude_with_model_form(
|
|||
) -> Option<Diagnostic> {
|
||||
if !bases
|
||||
.iter()
|
||||
.any(|base| is_model_form(checker.semantic_model(), base))
|
||||
.any(|base| is_model_form(base, checker.semantic()))
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
|
|
@ -3,23 +3,23 @@ use rustpython_parser::ast::Expr;
|
|||
use ruff_python_semantic::SemanticModel;
|
||||
|
||||
/// Return `true` if a Python class appears to be a Django model, based on its base classes.
|
||||
pub(super) fn is_model(model: &SemanticModel, base: &Expr) -> bool {
|
||||
model.resolve_call_path(base).map_or(false, |call_path| {
|
||||
pub(super) fn is_model(base: &Expr, semantic: &SemanticModel) -> bool {
|
||||
semantic.resolve_call_path(base).map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["django", "db", "models", "Model"]
|
||||
})
|
||||
}
|
||||
|
||||
/// Return `true` if a Python class appears to be a Django model form, based on its base classes.
|
||||
pub(super) fn is_model_form(model: &SemanticModel, base: &Expr) -> bool {
|
||||
model.resolve_call_path(base).map_or(false, |call_path| {
|
||||
pub(super) fn is_model_form(base: &Expr, semantic: &SemanticModel) -> bool {
|
||||
semantic.resolve_call_path(base).map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["django", "forms", "ModelForm"]
|
||||
|| call_path.as_slice() == ["django", "forms", "models", "ModelForm"]
|
||||
})
|
||||
}
|
||||
|
||||
/// Return `true` if the expression is constructor for a Django model field.
|
||||
pub(super) fn is_model_field(model: &SemanticModel, expr: &Expr) -> bool {
|
||||
model.resolve_call_path(expr).map_or(false, |call_path| {
|
||||
pub(super) fn is_model_field(expr: &Expr, semantic: &SemanticModel) -> bool {
|
||||
semantic.resolve_call_path(expr).map_or(false, |call_path| {
|
||||
call_path
|
||||
.as_slice()
|
||||
.starts_with(&["django", "db", "models"])
|
||||
|
@ -28,10 +28,10 @@ pub(super) fn is_model_field(model: &SemanticModel, expr: &Expr) -> bool {
|
|||
|
||||
/// Return the name of the field type, if the expression is constructor for a Django model field.
|
||||
pub(super) fn get_model_field_name<'a>(
|
||||
model: &'a SemanticModel,
|
||||
expr: &'a Expr,
|
||||
semantic: &'a SemanticModel,
|
||||
) -> Option<&'a str> {
|
||||
model.resolve_call_path(expr).and_then(|call_path| {
|
||||
semantic.resolve_call_path(expr).and_then(|call_path| {
|
||||
let call_path = call_path.as_slice();
|
||||
if !call_path.starts_with(&["django", "db", "models"]) {
|
||||
return None;
|
||||
|
|
|
@ -51,7 +51,7 @@ pub(crate) fn locals_in_render_function(
|
|||
keywords: &[Keyword],
|
||||
) {
|
||||
if !checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["django", "shortcuts", "render"]
|
||||
|
@ -61,7 +61,7 @@ pub(crate) fn locals_in_render_function(
|
|||
}
|
||||
|
||||
let locals = if args.len() >= 3 {
|
||||
if !is_locals_call(checker.semantic_model(), &args[2]) {
|
||||
if !is_locals_call(&args[2], checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
&args[2]
|
||||
|
@ -69,7 +69,7 @@ pub(crate) fn locals_in_render_function(
|
|||
.iter()
|
||||
.find(|keyword| keyword.arg.as_ref().map_or(false, |arg| arg == "context"))
|
||||
{
|
||||
if !is_locals_call(checker.semantic_model(), &keyword.value) {
|
||||
if !is_locals_call(&keyword.value, checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
&keyword.value
|
||||
|
@ -83,11 +83,11 @@ pub(crate) fn locals_in_render_function(
|
|||
));
|
||||
}
|
||||
|
||||
fn is_locals_call(model: &SemanticModel, expr: &Expr) -> bool {
|
||||
fn is_locals_call(expr: &Expr, semantic: &SemanticModel) -> bool {
|
||||
let Expr::Call(ast::ExprCall { func, .. }) = expr else {
|
||||
return false
|
||||
};
|
||||
model
|
||||
semantic
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| call_path.as_slice() == ["", "locals"])
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ pub(crate) fn model_without_dunder_str(
|
|||
body: &[Stmt],
|
||||
class_location: &Stmt,
|
||||
) -> Option<Diagnostic> {
|
||||
if !checker_applies(checker.semantic_model(), bases, body) {
|
||||
if !is_non_abstract_model(bases, body, checker.semantic()) {
|
||||
return None;
|
||||
}
|
||||
if !has_dunder_method(body) {
|
||||
|
@ -80,12 +80,12 @@ fn has_dunder_method(body: &[Stmt]) -> bool {
|
|||
})
|
||||
}
|
||||
|
||||
fn checker_applies(model: &SemanticModel, bases: &[Expr], body: &[Stmt]) -> bool {
|
||||
fn is_non_abstract_model(bases: &[Expr], body: &[Stmt], semantic: &SemanticModel) -> bool {
|
||||
for base in bases.iter() {
|
||||
if is_model_abstract(body) {
|
||||
continue;
|
||||
}
|
||||
if helpers::is_model(model, base) {
|
||||
if helpers::is_model(base, semantic) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ fn is_nullable_field<'a>(checker: &'a Checker, value: &'a Expr) -> Option<&'a st
|
|||
return None;
|
||||
};
|
||||
|
||||
let Some(valid_field_name) = helpers::get_model_field_name(checker.semantic_model(), func) else {
|
||||
let Some(valid_field_name) = helpers::get_model_field_name(func, checker.semantic()) else {
|
||||
return None;
|
||||
};
|
||||
|
||||
|
|
|
@ -100,11 +100,11 @@ impl fmt::Display for ContentType {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_element_type(model: &SemanticModel, element: &Stmt) -> Option<ContentType> {
|
||||
fn get_element_type(element: &Stmt, semantic: &SemanticModel) -> Option<ContentType> {
|
||||
match element {
|
||||
Stmt::Assign(ast::StmtAssign { targets, value, .. }) => {
|
||||
if let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() {
|
||||
if helpers::is_model_field(model, func) {
|
||||
if helpers::is_model_field(func, semantic) {
|
||||
return Some(ContentType::FieldDeclaration);
|
||||
}
|
||||
}
|
||||
|
@ -145,13 +145,13 @@ pub(crate) fn unordered_body_content_in_model(
|
|||
) {
|
||||
if !bases
|
||||
.iter()
|
||||
.any(|base| helpers::is_model(checker.semantic_model(), base))
|
||||
.any(|base| helpers::is_model(base, checker.semantic()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
let mut elements_type_found = Vec::new();
|
||||
for element in body.iter() {
|
||||
let Some(current_element_type) = get_element_type(checker.semantic_model(), element) else {
|
||||
let Some(current_element_type) = get_element_type(element, checker.semantic()) else {
|
||||
continue;
|
||||
};
|
||||
let Some(&element_type) = elements_type_found
|
||||
|
|
|
@ -190,7 +190,7 @@ pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr
|
|||
if let Some(indentation) =
|
||||
whitespace::indentation(checker.locator, stmt)
|
||||
{
|
||||
if checker.semantic_model().is_available("msg") {
|
||||
if checker.semantic().is_available("msg") {
|
||||
diagnostic.set_fix(generate_fix(
|
||||
stmt,
|
||||
first,
|
||||
|
@ -213,7 +213,7 @@ pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr
|
|||
if let Some(indentation) =
|
||||
whitespace::indentation(checker.locator, stmt)
|
||||
{
|
||||
if checker.semantic_model().is_available("msg") {
|
||||
if checker.semantic().is_available("msg") {
|
||||
diagnostic.set_fix(generate_fix(
|
||||
stmt,
|
||||
first,
|
||||
|
@ -240,7 +240,7 @@ pub(crate) fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr
|
|||
if let Some(indentation) =
|
||||
whitespace::indentation(checker.locator, stmt)
|
||||
{
|
||||
if checker.semantic_model().is_available("msg") {
|
||||
if checker.semantic().is_available("msg") {
|
||||
diagnostic.set_fix(generate_fix(
|
||||
stmt,
|
||||
first,
|
||||
|
|
|
@ -65,7 +65,7 @@ impl Violation for FutureRewritableTypeAnnotation {
|
|||
/// FA100
|
||||
pub(crate) fn future_rewritable_type_annotation(checker: &mut Checker, expr: &Expr) {
|
||||
let name = checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(expr)
|
||||
.map(|binding| format_call_path(&binding));
|
||||
|
||||
|
|
|
@ -106,7 +106,7 @@ fn check_log_record_attr_clash(checker: &mut Checker, extra: &Keyword) {
|
|||
}
|
||||
Expr::Call(ast::ExprCall { func, keywords, .. }) => {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| call_path.as_slice() == ["", "dict"])
|
||||
{
|
||||
|
@ -151,7 +151,7 @@ pub(crate) fn logging_call(
|
|||
args: &[Expr],
|
||||
keywords: &[Keyword],
|
||||
) {
|
||||
if !logging::is_logger_candidate(func, checker.semantic_model()) {
|
||||
if !logging::is_logger_candidate(func, checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -193,10 +193,10 @@ pub(crate) fn logging_call(
|
|||
|
||||
// G201, G202
|
||||
if checker.any_enabled(&[Rule::LoggingExcInfo, Rule::LoggingRedundantExcInfo]) {
|
||||
if !checker.semantic_model().in_exception_handler() {
|
||||
if !checker.semantic().in_exception_handler() {
|
||||
return;
|
||||
}
|
||||
let Some(exc_info) = logging::exc_info(keywords, checker.semantic_model()) else {
|
||||
let Some(exc_info) = logging::exc_info(keywords, checker.semantic()) else {
|
||||
return;
|
||||
};
|
||||
if let LoggingCallType::LevelCall(logging_level) = logging_call_type {
|
||||
|
|
|
@ -66,7 +66,7 @@ pub(crate) fn non_unique_enums<'a, 'b>(
|
|||
|
||||
if !bases.iter().any(|expr| {
|
||||
checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(expr)
|
||||
.map_or(false, |call_path| call_path.as_slice() == ["enum", "Enum"])
|
||||
}) {
|
||||
|
@ -81,7 +81,7 @@ pub(crate) fn non_unique_enums<'a, 'b>(
|
|||
|
||||
if let Expr::Call(ast::ExprCall { func, .. }) = value.as_ref() {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(func)
|
||||
.map_or(false, |call_path| call_path.as_slice() == ["enum", "auto"])
|
||||
{
|
||||
|
|
|
@ -69,7 +69,7 @@ pub(crate) fn reimplemented_list_builtin(checker: &mut Checker, expr: &ExprLambd
|
|||
if elts.is_empty() {
|
||||
let mut diagnostic = Diagnostic::new(ReimplementedListBuiltin, expr.range());
|
||||
if checker.patch(diagnostic.kind.rule()) {
|
||||
if checker.semantic_model().is_builtin("list") {
|
||||
if checker.semantic().is_builtin("list") {
|
||||
diagnostic.set_fix(Fix::automatic(Edit::range_replacement(
|
||||
"list".to_string(),
|
||||
expr.range(),
|
||||
|
|
|
@ -78,7 +78,7 @@ impl Violation for PPrint {
|
|||
/// T201, T203
|
||||
pub(crate) fn print_call(checker: &mut Checker, func: &Expr, keywords: &[Keyword]) {
|
||||
let diagnostic = {
|
||||
let call_path = checker.semantic_model().resolve_call_path(func);
|
||||
let call_path = checker.semantic().resolve_call_path(func);
|
||||
if call_path
|
||||
.as_ref()
|
||||
.map_or(false, |call_path| *call_path.as_slice() == ["", "print"])
|
||||
|
@ -90,14 +90,13 @@ pub(crate) fn print_call(checker: &mut Checker, func: &Expr, keywords: &[Keyword
|
|||
.find(|keyword| keyword.arg.as_ref().map_or(false, |arg| arg == "file"))
|
||||
{
|
||||
if !is_const_none(&keyword.value) {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.resolve_call_path(&keyword.value)
|
||||
.map_or(true, |call_path| {
|
||||
if checker.semantic().resolve_call_path(&keyword.value).map_or(
|
||||
true,
|
||||
|call_path| {
|
||||
call_path.as_slice() != ["sys", "stdout"]
|
||||
&& call_path.as_slice() != ["sys", "stderr"]
|
||||
})
|
||||
{
|
||||
},
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,14 +66,11 @@ pub(crate) fn any_eq_ne_annotation(checker: &mut Checker, name: &str, args: &Arg
|
|||
return;
|
||||
};
|
||||
|
||||
if !checker.semantic_model().scope().kind.is_class() {
|
||||
if !checker.semantic().scope().kind.is_class() {
|
||||
return;
|
||||
}
|
||||
|
||||
if checker
|
||||
.semantic_model()
|
||||
.match_typing_expr(annotation, "Any")
|
||||
{
|
||||
if checker.semantic().match_typing_expr(annotation, "Any") {
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
AnyEqNeAnnotation {
|
||||
method_name: name.to_string(),
|
||||
|
@ -82,7 +79,7 @@ pub(crate) fn any_eq_ne_annotation(checker: &mut Checker, name: &str, args: &Arg
|
|||
);
|
||||
if checker.patch(diagnostic.kind.rule()) {
|
||||
// Ex) `def __eq__(self, obj: Any): ...`
|
||||
if checker.semantic_model().is_builtin("object") {
|
||||
if checker.semantic().is_builtin("object") {
|
||||
diagnostic.set_fix(Fix::automatic(Edit::range_replacement(
|
||||
"object".to_string(),
|
||||
annotation.range(),
|
||||
|
|
|
@ -69,7 +69,7 @@ pub(crate) fn bad_version_info_comparison(
|
|||
};
|
||||
|
||||
if !checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(left)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["sys", "version_info"]
|
||||
|
|
|
@ -51,7 +51,7 @@ impl Violation for CollectionsNamedTuple {
|
|||
/// PYI024
|
||||
pub(crate) fn collections_named_tuple(checker: &mut Checker, expr: &Expr) {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(expr)
|
||||
.map_or(false, |call_path| {
|
||||
matches!(call_path.as_slice(), ["collections", "namedtuple"])
|
||||
|
|
|
@ -101,7 +101,7 @@ pub(crate) fn iter_method_return_iterable(checker: &mut Checker, definition: &De
|
|||
};
|
||||
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(annotation)
|
||||
.map_or(false, |call_path| {
|
||||
if async_ {
|
||||
|
|
|
@ -56,10 +56,7 @@ pub(crate) fn no_return_argument_annotation(checker: &mut Checker, args: &Argume
|
|||
)
|
||||
.filter_map(|arg| arg.annotation.as_ref())
|
||||
{
|
||||
if checker
|
||||
.semantic_model()
|
||||
.match_typing_expr(annotation, "NoReturn")
|
||||
{
|
||||
if checker.semantic().match_typing_expr(annotation, "NoReturn") {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
NoReturnArgumentAnnotationInStub {
|
||||
module: if checker.settings.target_version >= Py311 {
|
||||
|
|
|
@ -118,7 +118,7 @@ pub(crate) fn non_self_return_type(
|
|||
args: &Arguments,
|
||||
async_: bool,
|
||||
) {
|
||||
let ScopeKind::Class(class_def) = checker.semantic_model().scope().kind else {
|
||||
let ScopeKind::Class(class_def) = checker.semantic().scope().kind else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -131,8 +131,8 @@ pub(crate) fn non_self_return_type(
|
|||
};
|
||||
|
||||
// Skip any abstract or overloaded methods.
|
||||
if is_abstract(checker.semantic_model(), decorator_list)
|
||||
|| is_overload(checker.semantic_model(), decorator_list)
|
||||
if is_abstract(decorator_list, checker.semantic())
|
||||
|| is_overload(decorator_list, checker.semantic())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ pub(crate) fn non_self_return_type(
|
|||
if async_ {
|
||||
if name == "__aenter__"
|
||||
&& is_name(returns, &class_def.name)
|
||||
&& !is_final(checker.semantic_model(), &class_def.decorator_list)
|
||||
&& !is_final(&class_def.decorator_list, checker.semantic())
|
||||
{
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
NonSelfReturnType {
|
||||
|
@ -155,7 +155,7 @@ pub(crate) fn non_self_return_type(
|
|||
|
||||
// In-place methods that are expected to return `Self`.
|
||||
if INPLACE_BINOP_METHODS.contains(&name) {
|
||||
if !is_self(returns, checker.semantic_model()) {
|
||||
if !is_self(returns, checker.semantic()) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
NonSelfReturnType {
|
||||
class_name: class_def.name.to_string(),
|
||||
|
@ -169,7 +169,7 @@ pub(crate) fn non_self_return_type(
|
|||
|
||||
if is_name(returns, &class_def.name) {
|
||||
if matches!(name, "__enter__" | "__new__")
|
||||
&& !is_final(checker.semantic_model(), &class_def.decorator_list)
|
||||
&& !is_final(&class_def.decorator_list, checker.semantic())
|
||||
{
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
NonSelfReturnType {
|
||||
|
@ -184,8 +184,8 @@ pub(crate) fn non_self_return_type(
|
|||
|
||||
match name {
|
||||
"__iter__" => {
|
||||
if is_iterable(returns, checker.semantic_model())
|
||||
&& is_iterator(&class_def.bases, checker.semantic_model())
|
||||
if is_iterable(returns, checker.semantic())
|
||||
&& is_iterator(&class_def.bases, checker.semantic())
|
||||
{
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
NonSelfReturnType {
|
||||
|
@ -197,8 +197,8 @@ pub(crate) fn non_self_return_type(
|
|||
}
|
||||
}
|
||||
"__aiter__" => {
|
||||
if is_async_iterable(returns, checker.semantic_model())
|
||||
&& is_async_iterator(&class_def.bases, checker.semantic_model())
|
||||
if is_async_iterable(returns, checker.semantic())
|
||||
&& is_async_iterator(&class_def.bases, checker.semantic())
|
||||
{
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
NonSelfReturnType {
|
||||
|
@ -238,14 +238,14 @@ fn is_name(expr: &Expr, name: &str) -> bool {
|
|||
}
|
||||
|
||||
/// Return `true` if the given expression resolves to `typing.Self`.
|
||||
fn is_self(expr: &Expr, model: &SemanticModel) -> bool {
|
||||
model.match_typing_expr(expr, "Self")
|
||||
fn is_self(expr: &Expr, semantic: &SemanticModel) -> bool {
|
||||
semantic.match_typing_expr(expr, "Self")
|
||||
}
|
||||
|
||||
/// Return `true` if the given class extends `collections.abc.Iterator`.
|
||||
fn is_iterator(bases: &[Expr], model: &SemanticModel) -> bool {
|
||||
fn is_iterator(bases: &[Expr], semantic: &SemanticModel) -> bool {
|
||||
bases.iter().any(|expr| {
|
||||
model
|
||||
semantic
|
||||
.resolve_call_path(map_subscript(expr))
|
||||
.map_or(false, |call_path| {
|
||||
matches!(
|
||||
|
@ -257,8 +257,8 @@ fn is_iterator(bases: &[Expr], model: &SemanticModel) -> bool {
|
|||
}
|
||||
|
||||
/// Return `true` if the given expression resolves to `collections.abc.Iterable`.
|
||||
fn is_iterable(expr: &Expr, model: &SemanticModel) -> bool {
|
||||
model
|
||||
fn is_iterable(expr: &Expr, semantic: &SemanticModel) -> bool {
|
||||
semantic
|
||||
.resolve_call_path(map_subscript(expr))
|
||||
.map_or(false, |call_path| {
|
||||
matches!(
|
||||
|
@ -270,9 +270,9 @@ fn is_iterable(expr: &Expr, model: &SemanticModel) -> bool {
|
|||
}
|
||||
|
||||
/// Return `true` if the given class extends `collections.abc.AsyncIterator`.
|
||||
fn is_async_iterator(bases: &[Expr], model: &SemanticModel) -> bool {
|
||||
fn is_async_iterator(bases: &[Expr], semantic: &SemanticModel) -> bool {
|
||||
bases.iter().any(|expr| {
|
||||
model
|
||||
semantic
|
||||
.resolve_call_path(map_subscript(expr))
|
||||
.map_or(false, |call_path| {
|
||||
matches!(
|
||||
|
@ -284,8 +284,8 @@ fn is_async_iterator(bases: &[Expr], model: &SemanticModel) -> bool {
|
|||
}
|
||||
|
||||
/// Return `true` if the given expression resolves to `collections.abc.AsyncIterable`.
|
||||
fn is_async_iterable(expr: &Expr, model: &SemanticModel) -> bool {
|
||||
model
|
||||
fn is_async_iterable(expr: &Expr, semantic: &SemanticModel) -> bool {
|
||||
semantic
|
||||
.resolve_call_path(map_subscript(expr))
|
||||
.map_or(false, |call_path| {
|
||||
matches!(
|
||||
|
|
|
@ -70,12 +70,12 @@ pub(crate) fn prefix_type_params(checker: &mut Checker, value: &Expr, targets: &
|
|||
};
|
||||
|
||||
if let Expr::Call(ast::ExprCall { func, .. }) = value {
|
||||
let Some(kind) = checker.semantic_model().resolve_call_path(func).and_then(|call_path| {
|
||||
if checker.semantic_model().match_typing_call_path(&call_path, "ParamSpec") {
|
||||
let Some(kind) = checker.semantic().resolve_call_path(func).and_then(|call_path| {
|
||||
if checker.semantic().match_typing_call_path(&call_path, "ParamSpec") {
|
||||
Some(VarKind::ParamSpec)
|
||||
} else if checker.semantic_model().match_typing_call_path(&call_path, "TypeVar") {
|
||||
} else if checker.semantic().match_typing_call_path(&call_path, "TypeVar") {
|
||||
Some(VarKind::TypeVar)
|
||||
} else if checker.semantic_model().match_typing_call_path(&call_path, "TypeVarTuple") {
|
||||
} else if checker.semantic().match_typing_call_path(&call_path, "TypeVarTuple") {
|
||||
Some(VarKind::TypeVarTuple)
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -123,7 +123,7 @@ fn is_valid_default_value_with_annotation(
|
|||
default: &Expr,
|
||||
allow_container: bool,
|
||||
locator: &Locator,
|
||||
model: &SemanticModel,
|
||||
semantic: &SemanticModel,
|
||||
) -> bool {
|
||||
match default {
|
||||
Expr::Constant(_) => {
|
||||
|
@ -136,7 +136,7 @@ fn is_valid_default_value_with_annotation(
|
|||
&& elts.len() <= 10
|
||||
&& elts
|
||||
.iter()
|
||||
.all(|e| is_valid_default_value_with_annotation(e, false, locator, model));
|
||||
.all(|e| is_valid_default_value_with_annotation(e, false, locator, semantic));
|
||||
}
|
||||
Expr::Dict(ast::ExprDict {
|
||||
keys,
|
||||
|
@ -147,8 +147,8 @@ fn is_valid_default_value_with_annotation(
|
|||
&& keys.len() <= 10
|
||||
&& keys.iter().zip(values).all(|(k, v)| {
|
||||
k.as_ref().map_or(false, |k| {
|
||||
is_valid_default_value_with_annotation(k, false, locator, model)
|
||||
}) && is_valid_default_value_with_annotation(v, false, locator, model)
|
||||
is_valid_default_value_with_annotation(k, false, locator, semantic)
|
||||
}) && is_valid_default_value_with_annotation(v, false, locator, semantic)
|
||||
});
|
||||
}
|
||||
Expr::UnaryOp(ast::ExprUnaryOp {
|
||||
|
@ -164,12 +164,15 @@ fn is_valid_default_value_with_annotation(
|
|||
}) => return true,
|
||||
// Ex) `-math.inf`, `-math.pi`, etc.
|
||||
Expr::Attribute(_) => {
|
||||
if model.resolve_call_path(operand).map_or(false, |call_path| {
|
||||
if semantic
|
||||
.resolve_call_path(operand)
|
||||
.map_or(false, |call_path| {
|
||||
ALLOWED_MATH_ATTRIBUTES_IN_DEFAULTS.iter().any(|target| {
|
||||
// reject `-math.nan`
|
||||
call_path.as_slice() == *target && *target != ["math", "nan"]
|
||||
})
|
||||
}) {
|
||||
})
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -214,12 +217,15 @@ fn is_valid_default_value_with_annotation(
|
|||
}
|
||||
// Ex) `math.inf`, `sys.stdin`, etc.
|
||||
Expr::Attribute(_) => {
|
||||
if model.resolve_call_path(default).map_or(false, |call_path| {
|
||||
if semantic
|
||||
.resolve_call_path(default)
|
||||
.map_or(false, |call_path| {
|
||||
ALLOWED_MATH_ATTRIBUTES_IN_DEFAULTS
|
||||
.iter()
|
||||
.chain(ALLOWED_ATTRIBUTES_IN_DEFAULTS.iter())
|
||||
.any(|target| call_path.as_slice() == *target)
|
||||
}) {
|
||||
})
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -265,11 +271,11 @@ fn is_valid_default_value_without_annotation(default: &Expr) -> bool {
|
|||
|
||||
/// Returns `true` if an [`Expr`] appears to be `TypeVar`, `TypeVarTuple`, `NewType`, or `ParamSpec`
|
||||
/// call.
|
||||
fn is_type_var_like_call(model: &SemanticModel, expr: &Expr) -> bool {
|
||||
fn is_type_var_like_call(expr: &Expr, semantic: &SemanticModel) -> bool {
|
||||
let Expr::Call(ast::ExprCall { func, .. } )= expr else {
|
||||
return false;
|
||||
};
|
||||
model.resolve_call_path(func).map_or(false, |call_path| {
|
||||
semantic.resolve_call_path(func).map_or(false, |call_path| {
|
||||
matches!(
|
||||
call_path.as_slice(),
|
||||
[
|
||||
|
@ -282,11 +288,11 @@ fn is_type_var_like_call(model: &SemanticModel, expr: &Expr) -> bool {
|
|||
|
||||
/// Returns `true` if this is a "special" assignment which must have a value (e.g., an assignment to
|
||||
/// `__all__`).
|
||||
fn is_special_assignment(model: &SemanticModel, target: &Expr) -> bool {
|
||||
fn is_special_assignment(target: &Expr, semantic: &SemanticModel) -> bool {
|
||||
if let Expr::Name(ast::ExprName { id, .. }) = target {
|
||||
match id.as_str() {
|
||||
"__all__" => model.scope().kind.is_module(),
|
||||
"__match_args__" | "__slots__" => model.scope().kind.is_class(),
|
||||
"__all__" => semantic.scope().kind.is_module(),
|
||||
"__match_args__" | "__slots__" => semantic.scope().kind.is_class(),
|
||||
_ => false,
|
||||
}
|
||||
} else {
|
||||
|
@ -295,9 +301,9 @@ fn is_special_assignment(model: &SemanticModel, target: &Expr) -> bool {
|
|||
}
|
||||
|
||||
/// Returns `true` if the a class is an enum, based on its base classes.
|
||||
fn is_enum(model: &SemanticModel, bases: &[Expr]) -> bool {
|
||||
fn is_enum(bases: &[Expr], semantic: &SemanticModel) -> bool {
|
||||
return bases.iter().any(|expr| {
|
||||
model.resolve_call_path(expr).map_or(false, |call_path| {
|
||||
semantic.resolve_call_path(expr).map_or(false, |call_path| {
|
||||
matches!(
|
||||
call_path.as_slice(),
|
||||
[
|
||||
|
@ -323,7 +329,7 @@ pub(crate) fn typed_argument_simple_defaults(checker: &mut Checker, args: &Argum
|
|||
default,
|
||||
true,
|
||||
checker.locator,
|
||||
checker.semantic_model(),
|
||||
checker.semantic(),
|
||||
) {
|
||||
let mut diagnostic =
|
||||
Diagnostic::new(TypedArgumentDefaultInStub, default.range());
|
||||
|
@ -354,7 +360,7 @@ pub(crate) fn typed_argument_simple_defaults(checker: &mut Checker, args: &Argum
|
|||
default,
|
||||
true,
|
||||
checker.locator,
|
||||
checker.semantic_model(),
|
||||
checker.semantic(),
|
||||
) {
|
||||
let mut diagnostic =
|
||||
Diagnostic::new(TypedArgumentDefaultInStub, default.range());
|
||||
|
@ -388,7 +394,7 @@ pub(crate) fn argument_simple_defaults(checker: &mut Checker, args: &Arguments)
|
|||
default,
|
||||
true,
|
||||
checker.locator,
|
||||
checker.semantic_model(),
|
||||
checker.semantic(),
|
||||
) {
|
||||
let mut diagnostic =
|
||||
Diagnostic::new(ArgumentDefaultInStub, default.range());
|
||||
|
@ -419,7 +425,7 @@ pub(crate) fn argument_simple_defaults(checker: &mut Checker, args: &Arguments)
|
|||
default,
|
||||
true,
|
||||
checker.locator,
|
||||
checker.semantic_model(),
|
||||
checker.semantic(),
|
||||
) {
|
||||
let mut diagnostic =
|
||||
Diagnostic::new(ArgumentDefaultInStub, default.range());
|
||||
|
@ -448,21 +454,16 @@ pub(crate) fn assignment_default_in_stub(checker: &mut Checker, targets: &[Expr]
|
|||
if !target.is_name_expr() {
|
||||
return;
|
||||
}
|
||||
if is_special_assignment(checker.semantic_model(), target) {
|
||||
if is_special_assignment(target, checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
if is_type_var_like_call(checker.semantic_model(), value) {
|
||||
if is_type_var_like_call(value, checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
if is_valid_default_value_without_annotation(value) {
|
||||
return;
|
||||
}
|
||||
if is_valid_default_value_with_annotation(
|
||||
value,
|
||||
true,
|
||||
checker.locator,
|
||||
checker.semantic_model(),
|
||||
) {
|
||||
if is_valid_default_value_with_annotation(value, true, checker.locator, checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -484,23 +485,18 @@ pub(crate) fn annotated_assignment_default_in_stub(
|
|||
annotation: &Expr,
|
||||
) {
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.match_typing_expr(annotation, "TypeAlias")
|
||||
{
|
||||
return;
|
||||
}
|
||||
if is_special_assignment(checker.semantic_model(), target) {
|
||||
if is_special_assignment(target, checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
if is_type_var_like_call(checker.semantic_model(), value) {
|
||||
if is_type_var_like_call(value, checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
if is_valid_default_value_with_annotation(
|
||||
value,
|
||||
true,
|
||||
checker.locator,
|
||||
checker.semantic_model(),
|
||||
) {
|
||||
if is_valid_default_value_with_annotation(value, true, checker.locator, checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -527,27 +523,21 @@ pub(crate) fn unannotated_assignment_in_stub(
|
|||
let Expr::Name(ast::ExprName { id, .. }) = target else {
|
||||
return;
|
||||
};
|
||||
if is_special_assignment(checker.semantic_model(), target) {
|
||||
if is_special_assignment(target, checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
if is_type_var_like_call(checker.semantic_model(), value) {
|
||||
if is_type_var_like_call(value, checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
if is_valid_default_value_without_annotation(value) {
|
||||
return;
|
||||
}
|
||||
if !is_valid_default_value_with_annotation(
|
||||
value,
|
||||
true,
|
||||
checker.locator,
|
||||
checker.semantic_model(),
|
||||
) {
|
||||
if !is_valid_default_value_with_annotation(value, true, checker.locator, checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let ScopeKind::Class(ast::StmtClassDef { bases, .. }) = checker.semantic_model().scope().kind
|
||||
{
|
||||
if is_enum(checker.semantic_model(), bases) {
|
||||
if let ScopeKind::Class(ast::StmtClassDef { bases, .. }) = checker.semantic().scope().kind {
|
||||
if is_enum(bases, checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -569,7 +559,7 @@ pub(crate) fn unassigned_special_variable_in_stub(
|
|||
return;
|
||||
};
|
||||
|
||||
if !is_special_assignment(checker.semantic_model(), target) {
|
||||
if !is_special_assignment(target, checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ pub(crate) fn str_or_repr_defined_in_stub(checker: &mut Checker, stmt: &Stmt) {
|
|||
return;
|
||||
}
|
||||
|
||||
if !checker.semantic_model().scope().kind.is_class() {
|
||||
if !checker.semantic().scope().kind.is_class() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -72,12 +72,12 @@ pub(crate) fn str_or_repr_defined_in_stub(checker: &mut Checker, stmt: &Stmt) {
|
|||
return;
|
||||
}
|
||||
|
||||
if is_abstract(checker.semantic_model(), decorator_list) {
|
||||
if is_abstract(decorator_list, checker.semantic()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(returns)
|
||||
.map_or(true, |call_path| {
|
||||
!matches!(call_path.as_slice(), ["" | "builtins", "str"])
|
||||
|
@ -93,8 +93,8 @@ pub(crate) fn str_or_repr_defined_in_stub(checker: &mut Checker, stmt: &Stmt) {
|
|||
identifier_range(stmt, checker.locator),
|
||||
);
|
||||
if checker.patch(diagnostic.kind.rule()) {
|
||||
let stmt = checker.semantic_model().stmt();
|
||||
let parent = checker.semantic_model().stmt_parent();
|
||||
let stmt = checker.semantic().stmt();
|
||||
let parent = checker.semantic().stmt_parent();
|
||||
let edit = delete_stmt(
|
||||
stmt,
|
||||
parent,
|
||||
|
@ -103,7 +103,7 @@ pub(crate) fn str_or_repr_defined_in_stub(checker: &mut Checker, stmt: &Stmt) {
|
|||
checker.stylist,
|
||||
);
|
||||
diagnostic.set_fix(
|
||||
Fix::automatic(edit).isolate(checker.isolation(checker.semantic_model().stmt_parent())),
|
||||
Fix::automatic(edit).isolate(checker.isolation(checker.semantic().stmt_parent())),
|
||||
);
|
||||
}
|
||||
checker.diagnostics.push(diagnostic);
|
||||
|
|
|
@ -103,7 +103,7 @@ pub(crate) fn unrecognized_platform(
|
|||
let diagnostic_unrecognized_platform_check =
|
||||
Diagnostic::new(UnrecognizedPlatformCheck, expr.range());
|
||||
if !checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(left)
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["sys", "platform"]
|
||||
|
|
|
@ -194,9 +194,9 @@ pub(crate) fn unittest_assertion(
|
|||
if checker.patch(diagnostic.kind.rule()) {
|
||||
// We're converting an expression to a statement, so avoid applying the fix if
|
||||
// the assertion is part of a larger expression.
|
||||
if checker.semantic_model().stmt().is_expr_stmt()
|
||||
&& checker.semantic_model().expr_parent().is_none()
|
||||
&& !checker.semantic_model().scope().kind.is_lambda()
|
||||
if checker.semantic().stmt().is_expr_stmt()
|
||||
&& checker.semantic().expr_parent().is_none()
|
||||
&& !checker.semantic().scope().kind.is_lambda()
|
||||
&& !has_comments_in(expr.range(), checker.locator)
|
||||
{
|
||||
if let Ok(stmt) = unittest_assert.generate_assert(args, keywords) {
|
||||
|
@ -219,7 +219,7 @@ pub(crate) fn unittest_assertion(
|
|||
|
||||
/// PT015
|
||||
pub(crate) fn assert_falsy(checker: &mut Checker, stmt: &Stmt, test: &Expr) {
|
||||
if Truthiness::from_expr(test, |id| checker.semantic_model().is_builtin(id)).is_falsey() {
|
||||
if Truthiness::from_expr(test, |id| checker.semantic().is_builtin(id)).is_falsey() {
|
||||
checker
|
||||
.diagnostics
|
||||
.push(Diagnostic::new(PytestAssertAlwaysFalse, stmt.range()));
|
||||
|
|
|
@ -19,7 +19,7 @@ impl Violation for PytestFailWithoutMessage {
|
|||
}
|
||||
|
||||
pub(crate) fn fail_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords: &[Keyword]) {
|
||||
if is_pytest_fail(checker.semantic_model(), func) {
|
||||
if is_pytest_fail(func, checker.semantic()) {
|
||||
let call_args = SimpleCallArgs::new(args, keywords);
|
||||
|
||||
// Allow either `pytest.fail(reason="...")` (introduced in pytest 7.0) or
|
||||
|
|
|
@ -245,11 +245,11 @@ where
|
|||
}
|
||||
|
||||
fn get_fixture_decorator<'a>(
|
||||
model: &SemanticModel,
|
||||
decorators: &'a [Decorator],
|
||||
semantic: &SemanticModel,
|
||||
) -> Option<&'a Decorator> {
|
||||
decorators.iter().find(|decorator| {
|
||||
is_pytest_fixture(model, decorator) || is_pytest_yield_fixture(model, decorator)
|
||||
is_pytest_fixture(decorator, semantic) || is_pytest_yield_fixture(decorator, semantic)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -436,7 +436,7 @@ fn check_test_function_args(checker: &mut Checker, args: &Arguments) {
|
|||
|
||||
/// PT020
|
||||
fn check_fixture_decorator_name(checker: &mut Checker, decorator: &Decorator) {
|
||||
if is_pytest_yield_fixture(checker.semantic_model(), decorator) {
|
||||
if is_pytest_yield_fixture(decorator, checker.semantic()) {
|
||||
checker.diagnostics.push(Diagnostic::new(
|
||||
PytestDeprecatedYieldFixture,
|
||||
decorator.range(),
|
||||
|
@ -504,7 +504,7 @@ pub(crate) fn fixture(
|
|||
decorators: &[Decorator],
|
||||
body: &[Stmt],
|
||||
) {
|
||||
let decorator = get_fixture_decorator(checker.semantic_model(), decorators);
|
||||
let decorator = get_fixture_decorator(decorators, checker.semantic());
|
||||
if let Some(decorator) = decorator {
|
||||
if checker.enabled(Rule::PytestFixtureIncorrectParenthesesStyle)
|
||||
|| checker.enabled(Rule::PytestFixturePositionalArgs)
|
||||
|
@ -522,7 +522,7 @@ pub(crate) fn fixture(
|
|||
if (checker.enabled(Rule::PytestMissingFixtureNameUnderscore)
|
||||
|| checker.enabled(Rule::PytestIncorrectFixtureNameUnderscore)
|
||||
|| checker.enabled(Rule::PytestUselessYieldFixture))
|
||||
&& !is_abstract(checker.semantic_model(), decorators)
|
||||
&& !is_abstract(decorators, checker.semantic())
|
||||
{
|
||||
check_fixture_returns(checker, stmt, name, body);
|
||||
}
|
||||
|
|
|
@ -20,41 +20,41 @@ pub(super) fn get_mark_decorators(
|
|||
})
|
||||
}
|
||||
|
||||
pub(super) fn is_pytest_fail(model: &SemanticModel, call: &Expr) -> bool {
|
||||
model.resolve_call_path(call).map_or(false, |call_path| {
|
||||
pub(super) fn is_pytest_fail(call: &Expr, semantic: &SemanticModel) -> bool {
|
||||
semantic.resolve_call_path(call).map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["pytest", "fail"]
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn is_pytest_fixture(model: &SemanticModel, decorator: &Decorator) -> bool {
|
||||
model
|
||||
pub(super) fn is_pytest_fixture(decorator: &Decorator, semantic: &SemanticModel) -> bool {
|
||||
semantic
|
||||
.resolve_call_path(map_callable(&decorator.expression))
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["pytest", "fixture"]
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn is_pytest_yield_fixture(model: &SemanticModel, decorator: &Decorator) -> bool {
|
||||
model
|
||||
pub(super) fn is_pytest_yield_fixture(decorator: &Decorator, semantic: &SemanticModel) -> bool {
|
||||
semantic
|
||||
.resolve_call_path(map_callable(&decorator.expression))
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["pytest", "yield_fixture"]
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn is_pytest_parametrize(model: &SemanticModel, decorator: &Decorator) -> bool {
|
||||
model
|
||||
pub(super) fn is_pytest_parametrize(decorator: &Decorator, semantic: &SemanticModel) -> bool {
|
||||
semantic
|
||||
.resolve_call_path(map_callable(&decorator.expression))
|
||||
.map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["pytest", "mark", "parametrize"]
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn keyword_is_literal(kw: &Keyword, literal: &str) -> bool {
|
||||
pub(super) fn keyword_is_literal(keyword: &Keyword, literal: &str) -> bool {
|
||||
if let Expr::Constant(ast::ExprConstant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
}) = &kw.value
|
||||
}) = &keyword.value
|
||||
{
|
||||
string == literal
|
||||
} else {
|
||||
|
|
|
@ -419,7 +419,7 @@ fn handle_value_rows(
|
|||
|
||||
pub(crate) fn parametrize(checker: &mut Checker, decorators: &[Decorator]) {
|
||||
for decorator in decorators {
|
||||
if is_pytest_parametrize(checker.semantic_model(), decorator) {
|
||||
if is_pytest_parametrize(decorator, checker.semantic()) {
|
||||
if let Expr::Call(ast::ExprCall { args, .. }) = &decorator.expression {
|
||||
if checker.enabled(Rule::PytestParametrizeNamesWrongType) {
|
||||
if let Some(names) = args.get(0) {
|
||||
|
|
|
@ -47,8 +47,8 @@ impl Violation for PytestRaisesWithoutException {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_pytest_raises(func: &Expr, model: &SemanticModel) -> bool {
|
||||
model.resolve_call_path(func).map_or(false, |call_path| {
|
||||
fn is_pytest_raises(func: &Expr, semantic: &SemanticModel) -> bool {
|
||||
semantic.resolve_call_path(func).map_or(false, |call_path| {
|
||||
call_path.as_slice() == ["pytest", "raises"]
|
||||
})
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ const fn is_non_trivial_with_body(body: &[Stmt]) -> bool {
|
|||
}
|
||||
|
||||
pub(crate) fn raises_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords: &[Keyword]) {
|
||||
if is_pytest_raises(func, checker.semantic_model()) {
|
||||
if is_pytest_raises(func, checker.semantic()) {
|
||||
if checker.enabled(Rule::PytestRaisesWithoutException) {
|
||||
if args.is_empty() && keywords.is_empty() {
|
||||
checker
|
||||
|
@ -100,7 +100,7 @@ pub(crate) fn complex_raises(
|
|||
let mut is_too_complex = false;
|
||||
|
||||
let raises_called = items.iter().any(|item| match &item.context_expr {
|
||||
Expr::Call(ast::ExprCall { func, .. }) => is_pytest_raises(func, checker.semantic_model()),
|
||||
Expr::Call(ast::ExprCall { func, .. }) => is_pytest_raises(func, checker.semantic()),
|
||||
_ => false,
|
||||
});
|
||||
|
||||
|
@ -141,7 +141,7 @@ pub(crate) fn complex_raises(
|
|||
/// PT011
|
||||
fn exception_needs_match(checker: &mut Checker, exception: &Expr) {
|
||||
if let Some(call_path) = checker
|
||||
.semantic_model()
|
||||
.semantic()
|
||||
.resolve_call_path(exception)
|
||||
.and_then(|call_path| {
|
||||
let is_broad_exception = checker
|
||||
|
|
|
@ -398,12 +398,12 @@ const NORETURN_FUNCS: &[&[&str]] = &[
|
|||
];
|
||||
|
||||
/// Return `true` if the `func` is a known function that never returns.
|
||||
fn is_noreturn_func(model: &SemanticModel, func: &Expr) -> bool {
|
||||
model.resolve_call_path(func).map_or(false, |call_path| {
|
||||
fn is_noreturn_func(func: &Expr, semantic: &SemanticModel) -> bool {
|
||||
semantic.resolve_call_path(func).map_or(false, |call_path| {
|
||||
NORETURN_FUNCS
|
||||
.iter()
|
||||
.any(|target| call_path.as_slice() == *target)
|
||||
|| model.match_typing_call_path(&call_path, "assert_never")
|
||||
|| semantic.match_typing_call_path(&call_path, "assert_never")
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -489,7 +489,7 @@ fn implicit_return(checker: &mut Checker, stmt: &Stmt) {
|
|||
if matches!(
|
||||
value.as_ref(),
|
||||
Expr::Call(ast::ExprCall { func, .. })
|
||||
if is_noreturn_func(checker.semantic_model(), func)
|
||||
if is_noreturn_func(func, checker.semantic())
|
||||
) => {}
|
||||
_ => {
|
||||
let mut diagnostic = Diagnostic::new(ImplicitReturn, stmt.range());
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue