Repository: astral-sh/ruff
File: crates/ruff_workspace/src/options.rs (Rust)

Code before:

impl Flake8ImportConventionsOptions {
    pub fn try_into_settings(
        self,
        preview: PreviewMode,
    ) -> anyhow::Result<flake8_import_conventions::settings::Settings> {
        let mut aliases: FxHashMap<String, String> = match self.aliases {
            Some(options_aliases) => options_aliases
                .into_iter()
                .map(|(module, alias)| (module.into_string(), alias.into_string()))
                .collect(),
            None => flake8_import_conventions::settings::default_aliases(),
        };
        if let Some(extend_aliases) = self.extend_aliases {
            aliases.extend(
                extend_aliases
                    .into_iter()
                    .map(|(module, alias)| (module.into_string(), alias.into_string())),
            );
        }

        // Merge preview aliases if preview mode is enabled
        if preview.is_enabled() {
            aliases.extend(flake8_import_conventions::settings::preview_aliases());
        }

        let mut normalized_aliases: FxHashMap<String, String> = FxHashMap::default();
        for (module, alias) in aliases {
            let normalized_alias = alias.nfkc().collect::<String>();
            if normalized_alias == "__debug__" {
                anyhow::bail!(
                    "Invalid alias for module '{module}': alias normalizes to '__debug__', which is not allowed."
                );
            }
            normalized_aliases.insert(module, normalized_alias);
        }

        let mut banned_aliases = self.banned_aliases.unwrap_or_default();

        // Merge preview banned aliases if preview mode is enabled
        if preview.is_enabled() {
            banned_aliases.extend(flake8_import_conventions::settings::preview_banned_aliases());
        }

        Ok(flake8_import_conventions::settings::Settings {
            aliases: normalized_aliases,
            banned_aliases,
            banned_from: self.banned_from.unwrap_or_default(),
        })
    }
}

Review comment (refactor):
I don't think we should set this here. If I understand correctly, this will extend the list of aliases when preview is enabled even if the user provided a set of aliases. We only want to extend the _default_ set in the case where `self.aliases` is `None` above. I think it would make sense for the `default_aliases` helper function to take the `preview` argument and apply it there.

Code after:
pub struct Alias(String);

impl Alias {
    pub fn into_string(self) -> String {
        self.0
    }
}

impl<'de> Deserialize<'de> for Alias {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let name = String::deserialize(deserializer)?;
        // Assigning to "__debug__" is a SyntaxError
        // see the note here:
        // https://docs.python.org/3/library/constants.html#debug__
        if &*name == "__debug__" {
            return Err(de::Error::invalid_value(
                de::Unexpected::Str(&name),
                &"an assignable Python identifier",
            ));
        }
        if is_identifier(&name) {
            Ok(Self(name))
        } else {
            Err(de::Error::invalid_value(
                de::Unexpected::Str(&name),
                &"a Python identifier",
            ))
        }
    }
}

impl Flake8ImportConventionsOptions {
    pub fn try_into_settings(
        self,
        preview: PreviewMode,
    ) -> anyhow::Result<flake8_import_conventions::settings::Settings> {
        let mut aliases: FxHashMap<String, String> = match self.aliases {
            Some(options_aliases) => options_aliases
                .into_iter()
                .map(|(module, alias)| (module.into_string(), alias.into_string()))
                .collect(),
            None => flake8_import_conventions::settings::default_aliases(preview),
        };
        if let Some(extend_aliases) = self.extend_aliases {
            aliases.extend(
                extend_aliases
                    .into_iter()
                    .map(|(module, alias)| (module.into_string(), alias.into_string())),