diff --git a/crates/ruff/src/autofix/codemods.rs b/crates/ruff/src/autofix/codemods.rs index 6d290d81a0..b73b2d5041 100644 --- a/crates/ruff/src/autofix/codemods.rs +++ b/crates/ruff/src/autofix/codemods.rs @@ -57,11 +57,11 @@ pub(crate) fn remove_imports<'a>( // entire statement. let mut found_star = false; for import in imports { - let full_name = match import_body.module.as_ref() { + let qualified_name = match import_body.module.as_ref() { Some(module_name) => format!("{}.*", compose_module_path(module_name)), None => "*".to_string(), }; - if import == full_name { + if import == qualified_name { found_star = true; } else { bail!("Expected \"*\" for unused import (got: \"{}\")", import); @@ -83,26 +83,26 @@ pub(crate) fn remove_imports<'a>( for import in imports { let alias_index = aliases.iter().position(|alias| { - let full_name = match import_module { + let qualified_name = match import_module { Some((relative, module)) => { let module = module.map(compose_module_path); let member = compose_module_path(&alias.name); - let mut full_name = String::with_capacity( + let mut qualified_name = String::with_capacity( relative.len() + module.as_ref().map_or(0, String::len) + member.len() + 1, ); for _ in 0..relative.len() { - full_name.push('.'); + qualified_name.push('.'); } if let Some(module) = module { - full_name.push_str(&module); - full_name.push('.'); + qualified_name.push_str(&module); + qualified_name.push('.'); } - full_name.push_str(&member); - full_name + qualified_name.push_str(&member); + qualified_name } None => compose_module_path(&alias.name), }; - full_name == import + qualified_name == import }); if let Some(index) = alias_index { @@ -170,26 +170,26 @@ pub(crate) fn retain_imports( aliases.retain(|alias| { imports.iter().any(|import| { - let full_name = match import_module { + let qualified_name = match import_module { Some((relative, module)) => { let module = module.map(compose_module_path); let member = compose_module_path(&alias.name); - let mut full_name = String::with_capacity( + let mut qualified_name = String::with_capacity( relative.len() + module.as_ref().map_or(0, String::len) + member.len() + 1, ); for _ in 0..relative.len() { - full_name.push('.'); + qualified_name.push('.'); } if let Some(module) = module { - full_name.push_str(&module); - full_name.push('.'); + qualified_name.push_str(&module); + qualified_name.push('.'); } - full_name.push_str(&member); - full_name + qualified_name.push_str(&member); + qualified_name } None => compose_module_path(&alias.name), }; - full_name == *import + qualified_name == *import }) }); diff --git a/crates/ruff/src/checkers/ast/mod.rs b/crates/ruff/src/checkers/ast/mod.rs index fd2b99e1b3..80066088ee 100644 --- a/crates/ruff/src/checkers/ast/mod.rs +++ b/crates/ruff/src/checkers/ast/mod.rs @@ -848,23 +848,25 @@ where } } } else if alias.name.contains('.') && alias.asname.is_none() { - // Given `import foo.bar`, `name` would be "foo", and `full_name` would be + // Given `import foo.bar`, `name` would be "foo", and `qualified_name` would be // "foo.bar". let name = alias.name.split('.').next().unwrap(); - let full_name = &alias.name; + let qualified_name = &alias.name; self.add_binding( name, alias.range(), - BindingKind::SubmoduleImportation(SubmoduleImportation { full_name }), + BindingKind::SubmoduleImportation(SubmoduleImportation { + qualified_name, + }), BindingFlags::empty(), ); } else { let name = alias.asname.as_ref().unwrap_or(&alias.name); - let full_name = &alias.name; + let qualified_name = &alias.name; self.add_binding( name, alias.range(), - BindingKind::Importation(Importation { full_name }), + BindingKind::Importation(Importation { qualified_name }), if alias .asname .as_ref() @@ -1150,16 +1152,16 @@ where } } - // Given `from foo import bar`, `name` would be "bar" and `full_name` would + // Given `from foo import bar`, `name` would be "bar" and `qualified_name` would // be "foo.bar". Given `from foo import bar as baz`, `name` would be "baz" - // and `full_name` would be "foo.bar". + // and `qualified_name` would be "foo.bar". let name = alias.asname.as_ref().unwrap_or(&alias.name); - let full_name = + let qualified_name = helpers::format_import_from_member(level, module, &alias.name); self.add_binding( name, alias.range(), - BindingKind::FromImportation(FromImportation { full_name }), + BindingKind::FromImportation(FromImportation { qualified_name }), if alias .asname .as_ref() @@ -1195,12 +1197,12 @@ where } if self.enabled(Rule::UnconventionalImportAlias) { - let full_name = + let qualified_name = helpers::format_import_from_member(level, module, &alias.name); if let Some(diagnostic) = flake8_import_conventions::rules::conventional_import_alias( stmt, - &full_name, + &qualified_name, alias.asname.as_deref(), &self.settings.flake8_import_conventions.aliases, ) @@ -1211,12 +1213,12 @@ where if self.enabled(Rule::BannedImportAlias) { if let Some(asname) = &alias.asname { - let full_name = + let qualified_name = helpers::format_import_from_member(level, module, &alias.name); if let Some(diagnostic) = flake8_import_conventions::rules::banned_import_alias( stmt, - &full_name, + &qualified_name, asname, &self.settings.flake8_import_conventions.banned_aliases, ) diff --git a/crates/ruff/src/importer/mod.rs b/crates/ruff/src/importer/mod.rs index 9df741641f..ba923aed3f 100644 --- a/crates/ruff/src/importer/mod.rs +++ b/crates/ruff/src/importer/mod.rs @@ -88,7 +88,7 @@ impl<'a> Importer<'a> { ) -> Result { // Generate the modified import statement. let content = autofix::codemods::retain_imports( - &[import.full_name], + &[import.qualified_name], import.stmt, self.locator, self.stylist, @@ -120,7 +120,7 @@ impl<'a> Importer<'a> { ) -> Result { // Generate the modified import statement. let content = autofix::codemods::retain_imports( - &[import.full_name], + &[import.qualified_name], import.stmt, self.locator, self.stylist, @@ -447,7 +447,7 @@ pub(crate) struct StmtImport<'a> { /// The import statement. pub(crate) stmt: &'a Stmt, /// The "full name" of the imported module or member. - pub(crate) full_name: &'a str, + pub(crate) qualified_name: &'a str, } /// The result of an [`Importer::get_or_import_symbol`] call. diff --git a/crates/ruff/src/rules/flake8_type_checking/rules/runtime_import_in_type_checking_block.rs b/crates/ruff/src/rules/flake8_type_checking/rules/runtime_import_in_type_checking_block.rs index ec51578b43..a6c0497596 100644 --- a/crates/ruff/src/rules/flake8_type_checking/rules/runtime_import_in_type_checking_block.rs +++ b/crates/ruff/src/rules/flake8_type_checking/rules/runtime_import_in_type_checking_block.rs @@ -39,7 +39,7 @@ use crate::registry::AsRule; /// - [PEP 535](https://peps.python.org/pep-0563/#runtime-annotation-resolution-and-type-checking) #[violation] pub struct RuntimeImportInTypeCheckingBlock { - full_name: String, + qualified_name: String, } impl Violation for RuntimeImportInTypeCheckingBlock { @@ -47,9 +47,9 @@ impl Violation for RuntimeImportInTypeCheckingBlock { #[derive_message_formats] fn message(&self) -> String { - let RuntimeImportInTypeCheckingBlock { full_name } = self; + let RuntimeImportInTypeCheckingBlock { qualified_name } = self; format!( - "Move import `{full_name}` out of type-checking block. Import is used for more than type hinting." + "Move import `{qualified_name}` out of type-checking block. Import is used for more than type hinting." ) } @@ -84,7 +84,7 @@ pub(crate) fn runtime_import_in_type_checking_block( { let mut diagnostic = Diagnostic::new( RuntimeImportInTypeCheckingBlock { - full_name: qualified_name.to_string(), + qualified_name: qualified_name.to_string(), }, binding.range, ); @@ -110,7 +110,7 @@ pub(crate) fn runtime_import_in_type_checking_block( let add_import_edit = checker.importer.runtime_import_edit( &StmtImport { stmt, - full_name: qualified_name, + qualified_name, }, reference.range().start(), )?; diff --git a/crates/ruff/src/rules/flake8_type_checking/rules/typing_only_runtime_import.rs b/crates/ruff/src/rules/flake8_type_checking/rules/typing_only_runtime_import.rs index 2f74e14aee..a9186c91db 100644 --- a/crates/ruff/src/rules/flake8_type_checking/rules/typing_only_runtime_import.rs +++ b/crates/ruff/src/rules/flake8_type_checking/rules/typing_only_runtime_import.rs @@ -45,7 +45,7 @@ use crate::rules::isort::{categorize, ImportSection, ImportType}; /// - [PEP 536](https://peps.python.org/pep-0563/#runtime-annotation-resolution-and-type-checking) #[violation] pub struct TypingOnlyFirstPartyImport { - full_name: String, + qualified_name: String, } impl Violation for TypingOnlyFirstPartyImport { @@ -55,7 +55,7 @@ impl Violation for TypingOnlyFirstPartyImport { fn message(&self) -> String { format!( "Move application import `{}` into a type-checking block", - self.full_name + self.qualified_name ) } @@ -101,7 +101,7 @@ impl Violation for TypingOnlyFirstPartyImport { /// - [PEP 536](https://peps.python.org/pep-0563/#runtime-annotation-resolution-and-type-checking) #[violation] pub struct TypingOnlyThirdPartyImport { - full_name: String, + qualified_name: String, } impl Violation for TypingOnlyThirdPartyImport { @@ -111,7 +111,7 @@ impl Violation for TypingOnlyThirdPartyImport { fn message(&self) -> String { format!( "Move third-party import `{}` into a type-checking block", - self.full_name + self.qualified_name ) } @@ -157,7 +157,7 @@ impl Violation for TypingOnlyThirdPartyImport { /// - [PEP 536](https://peps.python.org/pep-0563/#runtime-annotation-resolution-and-type-checking) #[violation] pub struct TypingOnlyStandardLibraryImport { - full_name: String, + qualified_name: String, } impl Violation for TypingOnlyStandardLibraryImport { @@ -167,7 +167,7 @@ impl Violation for TypingOnlyStandardLibraryImport { fn message(&self) -> String { format!( "Move standard library import `{}` into a type-checking block", - self.full_name + self.qualified_name ) } @@ -274,7 +274,7 @@ pub(crate) fn typing_only_runtime_import( ImportSection::Known(ImportType::LocalFolder | ImportType::FirstParty) => { Diagnostic::new( TypingOnlyFirstPartyImport { - full_name: qualified_name.to_string(), + qualified_name: qualified_name.to_string(), }, binding.range, ) @@ -282,14 +282,14 @@ pub(crate) fn typing_only_runtime_import( ImportSection::Known(ImportType::ThirdParty) | ImportSection::UserDefined(_) => { Diagnostic::new( TypingOnlyThirdPartyImport { - full_name: qualified_name.to_string(), + qualified_name: qualified_name.to_string(), }, binding.range, ) } ImportSection::Known(ImportType::StandardLibrary) => Diagnostic::new( TypingOnlyStandardLibraryImport { - full_name: qualified_name.to_string(), + qualified_name: qualified_name.to_string(), }, binding.range, ), @@ -319,7 +319,7 @@ pub(crate) fn typing_only_runtime_import( let add_import_edit = checker.importer.typing_import_edit( &StmtImport { stmt, - full_name: qualified_name, + qualified_name, }, reference.range().start(), checker.semantic_model(), diff --git a/crates/ruff/src/rules/pandas_vet/helpers.rs b/crates/ruff/src/rules/pandas_vet/helpers.rs index 1ec93a6d80..9622571434 100644 --- a/crates/ruff/src/rules/pandas_vet/helpers.rs +++ b/crates/ruff/src/rules/pandas_vet/helpers.rs @@ -40,11 +40,9 @@ pub(crate) fn test_expression(expr: &Expr, model: &SemanticModel) -> Resolution | BindingKind::LoopVar | BindingKind::Global | BindingKind::Nonlocal => Resolution::RelevantLocal, - BindingKind::Importation(Importation { full_name: module }) - if module == "pandas" => - { - Resolution::PandasModule - } + BindingKind::Importation(Importation { + qualified_name: module, + }) if module == "pandas" => Resolution::PandasModule, _ => Resolution::IrrelevantBinding, } }) diff --git a/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs b/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs index 9295bd6b62..ebb56710ce 100644 --- a/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs +++ b/crates/ruff/src/rules/pandas_vet/rules/inplace_argument.rs @@ -71,7 +71,7 @@ pub(crate) fn inplace_argument( matches!( binding.kind, BindingKind::Importation(Importation { - full_name: "pandas" + qualified_name: "pandas" }) ) }); diff --git a/crates/ruff/src/rules/pyflakes/rules/unused_import.rs b/crates/ruff/src/rules/pyflakes/rules/unused_import.rs index c204dfc0dd..be08c5a1c4 100644 --- a/crates/ruff/src/rules/pyflakes/rules/unused_import.rs +++ b/crates/ruff/src/rules/pyflakes/rules/unused_import.rs @@ -165,7 +165,9 @@ pub(crate) fn unused_import(checker: &Checker, scope: &Scope, diagnostics: &mut let fix = if !in_init && !in_except_handler && checker.patch(Rule::UnusedImport) { autofix::edits::remove_unused_imports( - unused_imports.iter().map(|(full_name, _)| *full_name), + unused_imports + .iter() + .map(|(qualified_name, _)| *qualified_name), stmt, parent, checker.locator, @@ -177,10 +179,10 @@ pub(crate) fn unused_import(checker: &Checker, scope: &Scope, diagnostics: &mut None }; - for (full_name, range) in unused_imports { + for (qualified_name, range) in unused_imports { let mut diagnostic = Diagnostic::new( UnusedImport { - name: full_name.to_string(), + name: qualified_name.to_string(), context: if in_except_handler { Some(UnusedImportContext::ExceptHandler) } else if in_init { @@ -217,10 +219,10 @@ pub(crate) fn unused_import(checker: &Checker, scope: &Scope, diagnostics: &mut let multiple = unused_imports.len() > 1; let in_except_handler = exceptions.intersects(Exceptions::MODULE_NOT_FOUND_ERROR | Exceptions::IMPORT_ERROR); - for (full_name, range) in unused_imports { + for (qualified_name, range) in unused_imports { let mut diagnostic = Diagnostic::new( UnusedImport { - name: full_name.to_string(), + name: qualified_name.to_string(), context: if in_except_handler { Some(UnusedImportContext::ExceptHandler) } else if in_init { diff --git a/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs b/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs index ffc4ed6ddc..b2c5c62394 100644 --- a/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs +++ b/crates/ruff/src/rules/pyupgrade/rules/deprecated_import.rs @@ -493,14 +493,14 @@ impl<'a> ImportReplacer<'a> { fn format_import_from(names: &[&Alias], module: &str) -> String { // Construct the whitespace strings. // Generate the formatted names. - let full_names: String = names + let qualified_names: String = names .iter() .map(|name| match &name.asname { Some(asname) => format!("{} as {}", name.name, asname), None => format!("{}", name.name), }) .join(", "); - format!("from {module} import {full_names}") + format!("from {module} import {qualified_names}") } } diff --git a/crates/ruff_python_ast/src/helpers.rs b/crates/ruff_python_ast/src/helpers.rs index c74d96ac12..0f3340c1f7 100644 --- a/crates/ruff_python_ast/src/helpers.rs +++ b/crates/ruff_python_ast/src/helpers.rs @@ -800,7 +800,7 @@ pub fn format_import_from(level: Option, module: Option<&str>) -> String { /// assert_eq!(format_import_from_member(Some(1), Some("foo"), "bar"), ".foo.bar".to_string()); /// ``` pub fn format_import_from_member(level: Option, module: Option<&str>, member: &str) -> String { - let mut full_name = String::with_capacity( + let mut qualified_name = String::with_capacity( (level.unwrap_or(0) as usize) + module.as_ref().map_or(0, |module| module.len()) + 1 @@ -808,15 +808,15 @@ pub fn format_import_from_member(level: Option, module: Option<&str>, membe ); if let Some(level) = level { for _ in 0..level { - full_name.push('.'); + qualified_name.push('.'); } } if let Some(module) = module { - full_name.push_str(module); - full_name.push('.'); + qualified_name.push_str(module); + qualified_name.push('.'); } - full_name.push_str(member); - full_name + qualified_name.push_str(member); + qualified_name } /// Create a module path from a (package, path) pair. diff --git a/crates/ruff_python_semantic/src/binding.rs b/crates/ruff_python_semantic/src/binding.rs index 61a864e09c..dd862e8ce6 100644 --- a/crates/ruff_python_semantic/src/binding.rs +++ b/crates/ruff_python_semantic/src/binding.rs @@ -48,36 +48,36 @@ impl<'a> Binding<'a> { /// Return `true` if this binding redefines the given binding. pub fn redefines(&self, existing: &'a Binding) -> bool { match &self.kind { - BindingKind::Importation(Importation { full_name }) => { + BindingKind::Importation(Importation { qualified_name }) => { if let BindingKind::SubmoduleImportation(SubmoduleImportation { - full_name: existing, + qualified_name: existing, }) = &existing.kind { - return full_name == existing; + return qualified_name == existing; } } - BindingKind::FromImportation(FromImportation { full_name }) => { + BindingKind::FromImportation(FromImportation { qualified_name }) => { if let BindingKind::SubmoduleImportation(SubmoduleImportation { - full_name: existing, + qualified_name: existing, }) = &existing.kind { - return full_name == existing; + return qualified_name == existing; } } - BindingKind::SubmoduleImportation(SubmoduleImportation { full_name }) => { + BindingKind::SubmoduleImportation(SubmoduleImportation { qualified_name }) => { match &existing.kind { BindingKind::Importation(Importation { - full_name: existing, + qualified_name: existing, }) | BindingKind::SubmoduleImportation(SubmoduleImportation { - full_name: existing, + qualified_name: existing, }) => { - return full_name == existing; + return qualified_name == existing; } BindingKind::FromImportation(FromImportation { - full_name: existing, + qualified_name: existing, }) => { - return full_name == existing; + return qualified_name == existing; } _ => {} } @@ -104,10 +104,12 @@ impl<'a> Binding<'a> { /// Returns the fully-qualified symbol name, if this symbol was imported from another module. pub fn qualified_name(&self) -> Option<&str> { match &self.kind { - BindingKind::Importation(Importation { full_name }) => Some(full_name), - BindingKind::FromImportation(FromImportation { full_name }) => Some(full_name), - BindingKind::SubmoduleImportation(SubmoduleImportation { full_name }) => { - Some(full_name) + BindingKind::Importation(Importation { qualified_name }) => Some(qualified_name), + BindingKind::FromImportation(FromImportation { qualified_name }) => { + Some(qualified_name) + } + BindingKind::SubmoduleImportation(SubmoduleImportation { qualified_name }) => { + Some(qualified_name) } _ => None, } @@ -117,14 +119,14 @@ impl<'a> Binding<'a> { /// symbol was imported from another module. pub fn module_name(&self) -> Option<&str> { match &self.kind { - BindingKind::Importation(Importation { full_name }) - | BindingKind::SubmoduleImportation(SubmoduleImportation { full_name }) => { - Some(full_name.split('.').next().unwrap_or(full_name)) + BindingKind::Importation(Importation { qualified_name }) + | BindingKind::SubmoduleImportation(SubmoduleImportation { qualified_name }) => { + Some(qualified_name.split('.').next().unwrap_or(qualified_name)) } - BindingKind::FromImportation(FromImportation { full_name }) => Some( - full_name + BindingKind::FromImportation(FromImportation { qualified_name }) => Some( + qualified_name .rsplit_once('.') - .map_or(full_name, |(module, _)| module), + .map_or(qualified_name, |(module, _)| module), ), _ => None, } @@ -241,9 +243,9 @@ pub struct Export<'a> { #[derive(Clone, Debug)] pub struct Importation<'a> { /// The full name of the module being imported. - /// Ex) Given `import foo`, `full_name` would be "foo". - /// Ex) Given `import foo as bar`, `full_name` would be "foo". - pub full_name: &'a str, + /// Ex) Given `import foo`, `qualified_name` would be "foo". + /// Ex) Given `import foo as bar`, `qualified_name` would be "foo". + pub qualified_name: &'a str, } /// A binding for a member imported from a module, keyed on the name to which the member is bound. @@ -252,9 +254,9 @@ pub struct Importation<'a> { #[derive(Clone, Debug)] pub struct FromImportation { /// The full name of the member being imported. - /// Ex) Given `from foo import bar`, `full_name` would be "foo.bar". - /// Ex) Given `from foo import bar as baz`, `full_name` would be "foo.bar". - pub full_name: String, + /// Ex) Given `from foo import bar`, `qualified_name` would be "foo.bar". + /// Ex) Given `from foo import bar as baz`, `qualified_name` would be "foo.bar". + pub qualified_name: String, } /// A binding for a submodule imported from a module, keyed on the name of the parent module. @@ -262,8 +264,8 @@ pub struct FromImportation { #[derive(Clone, Debug)] pub struct SubmoduleImportation<'a> { /// The full name of the submodule being imported. - /// Ex) Given `import foo.bar`, `full_name` would be "foo.bar". - pub full_name: &'a str, + /// Ex) Given `import foo.bar`, `qualified_name` would be "foo.bar". + pub qualified_name: &'a str, } #[derive(Clone, Debug, is_macro::Is)] diff --git a/crates/ruff_python_semantic/src/model.rs b/crates/ruff_python_semantic/src/model.rs index 589e06624c..7b23c81b6a 100644 --- a/crates/ruff_python_semantic/src/model.rs +++ b/crates/ruff_python_semantic/src/model.rs @@ -327,7 +327,9 @@ impl<'a> SemanticModel<'a> { let head = call_path.first()?; let binding = self.find_binding(head)?; match &binding.kind { - BindingKind::Importation(Importation { full_name: name }) => { + BindingKind::Importation(Importation { + qualified_name: name, + }) => { if name.starts_with('.') { let mut source_path = from_relative_import(self.module_path?, name); if source_path.is_empty() { @@ -342,13 +344,17 @@ impl<'a> SemanticModel<'a> { Some(source_path) } } - BindingKind::SubmoduleImportation(SubmoduleImportation { full_name: name }) => { + BindingKind::SubmoduleImportation(SubmoduleImportation { + qualified_name: name, + }) => { let name = name.split('.').next().unwrap_or(name); let mut source_path: CallPath = from_unqualified_name(name); source_path.extend(call_path.into_iter().skip(1)); Some(source_path) } - BindingKind::FromImportation(FromImportation { full_name: name }) => { + BindingKind::FromImportation(FromImportation { + qualified_name: name, + }) => { if name.starts_with('.') { let mut source_path = from_relative_import(self.module_path?, name); if source_path.is_empty() { @@ -397,8 +403,8 @@ impl<'a> SemanticModel<'a> { // Ex) Given `module="sys"` and `object="exit"`: // `import sys` -> `sys.exit` // `import sys as sys2` -> `sys2.exit` - BindingKind::Importation(Importation { full_name }) => { - if full_name == &module { + BindingKind::Importation(Importation { qualified_name }) => { + if qualified_name == &module { if let Some(source) = binding.source { // Verify that `sys` isn't bound in an inner scope. if self @@ -418,8 +424,9 @@ impl<'a> SemanticModel<'a> { // Ex) Given `module="os.path"` and `object="join"`: // `from os.path import join` -> `join` // `from os.path import join as join2` -> `join2` - BindingKind::FromImportation(FromImportation { full_name }) => { - if let Some((target_module, target_member)) = full_name.split_once('.') { + BindingKind::FromImportation(FromImportation { qualified_name }) => { + if let Some((target_module, target_member)) = qualified_name.split_once('.') + { if target_module == module && target_member == member { if let Some(source) = binding.source { // Verify that `join` isn't bound in an inner scope.