Apply preview

This commit is contained in:
Dan 2025-11-13 20:34:25 -05:00
parent 7cb1196535
commit 17bbb535de
6 changed files with 61 additions and 21 deletions

View file

@ -254,6 +254,11 @@ pub(crate) const fn is_b006_check_guaranteed_mutable_expr_enabled(
settings.preview.is_enabled()
}
// https://github.com/astral-sh/ruff/pull/21373
pub(crate) const fn is_import_conventions_preview_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}
// github.com/astral-sh/ruff/issues/20004
pub(crate) const fn is_b006_unsafe_fix_preserve_assignment_expr_enabled(
settings: &LinterSettings,

View file

@ -12,20 +12,20 @@ mod tests {
use crate::assert_diagnostics;
use crate::registry::Rule;
use crate::rules::flake8_import_conventions::settings::{BannedAliases, default_aliases};
use crate::settings::LinterSettings;
use crate::settings::{LinterSettings, types::PreviewMode};
use crate::test::test_path;
#[test]
fn defaults() -> Result<()> {
let mut settings = LinterSettings {
flake8_import_conventions: super::settings::Settings::default(),
..LinterSettings::for_rules([Rule::UnconventionalImportAlias, Rule::BannedImportAlias])
};
// Enable preview mode to test preview-only conventions
settings.preview = PreviewMode::Enabled;
let diagnostics = test_path(
Path::new("flake8_import_conventions/defaults.py"),
&LinterSettings {
flake8_import_conventions: super::settings::Settings::default(),
..LinterSettings::for_rules([
Rule::UnconventionalImportAlias,
Rule::BannedImportAlias,
])
},
&settings,
)?;
assert_diagnostics!(diagnostics);
Ok(())

View file

@ -6,7 +6,8 @@ use ruff_text_size::Ranged;
use crate::Violation;
use crate::checkers::ast::Checker;
use crate::rules::flake8_import_conventions::settings::BannedAliases;
use crate::preview::is_import_conventions_preview_enabled;
use crate::rules::flake8_import_conventions::settings::{BannedAliases, preview_banned_aliases};
/// ## What it does
/// Checks for imports that use non-standard naming conventions, like
@ -56,7 +57,17 @@ pub(crate) fn banned_import_alias(
asname: &str,
banned_conventions: &FxHashMap<String, BannedAliases>,
) {
if let Some(banned_aliases) = banned_conventions.get(name) {
// Merge preview banned aliases if preview mode is enabled
let banned_aliases = if is_import_conventions_preview_enabled(checker.settings()) {
banned_conventions.get(name).cloned().or_else(|| {
let preview_banned = preview_banned_aliases();
preview_banned.get(name).cloned()
})
} else {
banned_conventions.get(name).cloned()
};
if let Some(banned_aliases) = banned_aliases.as_ref() {
if banned_aliases
.iter()
.any(|banned_alias| banned_alias == asname)

View file

@ -5,6 +5,8 @@ use ruff_python_semantic::{Binding, Imported};
use ruff_text_size::Ranged;
use crate::checkers::ast::Checker;
use crate::preview::is_import_conventions_preview_enabled;
use crate::rules::flake8_import_conventions::settings::preview_aliases;
use crate::{Fix, FixAvailability, Violation};
use crate::renamer::Renamer;
@ -66,12 +68,26 @@ pub(crate) fn unconventional_import_alias(
return;
};
let qualified_name = import.qualified_name().to_string();
let Some(expected_alias) = conventions.get(qualified_name.as_str()) else {
// Merge preview conventions if preview mode is enabled
let expected_alias = if is_import_conventions_preview_enabled(checker.settings()) {
conventions
.get(qualified_name.as_str())
.cloned()
.or_else(|| {
let preview_aliases_map = preview_aliases();
preview_aliases_map.get(qualified_name.as_str()).cloned()
})
} else {
conventions.get(qualified_name.as_str()).cloned()
};
let Some(expected_alias) = expected_alias else {
return;
};
let name = binding.name(checker.source());
if name == expected_alias {
if name == expected_alias.as_str() {
return;
}
@ -83,12 +99,12 @@ pub(crate) fn unconventional_import_alias(
binding.range(),
);
if !import.is_submodule_import() {
if checker.semantic().is_available(expected_alias) {
if checker.semantic().is_available(&expected_alias) {
diagnostic.try_set_fix(|| {
let scope = &checker.semantic().scopes[binding.scope];
let (edit, rest) = Renamer::rename(
name,
expected_alias,
&expected_alias,
scope,
checker.semantic(),
checker.stylist(),

View file

@ -18,9 +18,7 @@ const CONVENTIONAL_ALIASES: &[(&str, &str)] = &[
("numpy.typing", "npt"),
("pandas", "pd"),
("plotly.express", "px"),
("plotly.graph_objects", "go"),
("seaborn", "sns"),
("statsmodels.api", "sm"),
("tensorflow", "tf"),
("tkinter", "tk"),
("holoviews", "hv"),
@ -30,6 +28,9 @@ const CONVENTIONAL_ALIASES: &[(&str, &str)] = &[
("xml.etree.ElementTree", "ET"),
];
const PREVIEW_ALIASES: &[(&str, &str)] =
&[("plotly.graph_objects", "go"), ("statsmodels.api", "sm")];
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, CacheKey)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
@ -75,7 +76,14 @@ pub fn default_aliases() -> FxHashMap<String, String> {
.collect::<FxHashMap<_, _>>()
}
pub fn default_banned_aliases() -> FxHashMap<String, BannedAliases> {
pub fn preview_aliases() -> FxHashMap<String, String> {
PREVIEW_ALIASES
.iter()
.map(|(k, v)| ((*k).to_string(), (*v).to_string()))
.collect::<FxHashMap<_, _>>()
}
pub fn preview_banned_aliases() -> FxHashMap<String, BannedAliases> {
FxHashMap::from_iter([(
"geopandas".to_string(),
BannedAliases::from_iter(["gpd".to_string()]),
@ -86,7 +94,7 @@ impl Default for Settings {
fn default() -> Self {
Self {
aliases: default_aliases(),
banned_aliases: default_banned_aliases(),
banned_aliases: FxHashMap::default(),
banned_from: FxHashSet::default(),
}
}

View file

@ -1534,7 +1534,7 @@ pub struct Flake8ImportConventionsOptions {
/// The conventional aliases for imports. These aliases can be extended by
/// the [`extend-aliases`](#lint_flake8-import-conventions_extend-aliases) option.
#[option(
default = r#"{"altair": "alt", "matplotlib": "mpl", "matplotlib.pyplot": "plt", "numpy": "np", "numpy.typing": "npt", "pandas": "pd", "plotly.express": "px", "plotly.graph_objects": "go", "seaborn": "sns", "statsmodels.api": "sm", "tensorflow": "tf", "tkinter": "tk", "holoviews": "hv", "panel": "pn", "polars": "pl", "pyarrow": "pa", "xml.etree.ElementTree": "ET"}"#,
default = r#"{"altair": "alt", "matplotlib": "mpl", "matplotlib.pyplot": "plt", "numpy": "np", "numpy.typing": "npt", "pandas": "pd", "plotly.express": "px", "seaborn": "sns", "tensorflow": "tf", "tkinter": "tk", "holoviews": "hv", "panel": "pn", "polars": "pl", "pyarrow": "pa", "xml.etree.ElementTree": "ET"}"#,
value_type = "dict[str, str]",
scope = "aliases",
example = r#"
@ -1564,7 +1564,7 @@ pub struct Flake8ImportConventionsOptions {
/// A mapping from module to its banned import aliases.
#[option(
default = r#"{"geopandas": ["gpd"]}"#,
default = r#"{}"#,
value_type = "dict[str, list[str]]",
scope = "banned-aliases",
example = r#"
@ -1687,7 +1687,7 @@ impl Flake8ImportConventionsOptions {
aliases: normalized_aliases,
banned_aliases: self
.banned_aliases
.unwrap_or_else(flake8_import_conventions::settings::default_banned_aliases),
.unwrap_or_else(FxHashMap::default),
banned_from: self.banned_from.unwrap_or_default(),
})
}