mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 13:25:17 +00:00
Add --extension
support to the formatter (#9483)
## Summary We added `--extension` to `ruff check`, but it's equally applicable to `ruff format`. Closes https://github.com/astral-sh/ruff/issues/9482. Resolves https://github.com/astral-sh/ruff/discussions/9481. ## Test Plan `cargo test`
This commit is contained in:
parent
d16c4a2d25
commit
3261d16e61
11 changed files with 221 additions and 51 deletions
|
@ -290,6 +290,10 @@ pub struct CheckCommand {
|
||||||
/// The name of the file when passing it through stdin.
|
/// The name of the file when passing it through stdin.
|
||||||
#[arg(long, help_heading = "Miscellaneous")]
|
#[arg(long, help_heading = "Miscellaneous")]
|
||||||
pub stdin_filename: Option<PathBuf>,
|
pub stdin_filename: Option<PathBuf>,
|
||||||
|
/// List of mappings from file extension to language (one of ["python", "ipynb", "pyi"]). For
|
||||||
|
/// example, to treat `.ipy` files as IPython notebooks, use `--extension ipy:ipynb`.
|
||||||
|
#[arg(long, value_delimiter = ',')]
|
||||||
|
pub extension: Option<Vec<ExtensionPair>>,
|
||||||
/// Exit with status code "0", even upon detecting lint violations.
|
/// Exit with status code "0", even upon detecting lint violations.
|
||||||
#[arg(
|
#[arg(
|
||||||
short,
|
short,
|
||||||
|
@ -352,9 +356,6 @@ pub struct CheckCommand {
|
||||||
conflicts_with = "watch",
|
conflicts_with = "watch",
|
||||||
)]
|
)]
|
||||||
pub show_settings: bool,
|
pub show_settings: bool,
|
||||||
/// List of mappings from file extension to language (one of ["python", "ipynb", "pyi"]).
|
|
||||||
#[arg(long, value_delimiter = ',', hide = true)]
|
|
||||||
pub extension: Option<Vec<ExtensionPair>>,
|
|
||||||
/// Dev-only argument to show fixes
|
/// Dev-only argument to show fixes
|
||||||
#[arg(long, hide = true)]
|
#[arg(long, hide = true)]
|
||||||
pub ecosystem_ci: bool,
|
pub ecosystem_ci: bool,
|
||||||
|
@ -423,6 +424,10 @@ pub struct FormatCommand {
|
||||||
/// The name of the file when passing it through stdin.
|
/// The name of the file when passing it through stdin.
|
||||||
#[arg(long, help_heading = "Miscellaneous")]
|
#[arg(long, help_heading = "Miscellaneous")]
|
||||||
pub stdin_filename: Option<PathBuf>,
|
pub stdin_filename: Option<PathBuf>,
|
||||||
|
/// List of mappings from file extension to language (one of ["python", "ipynb", "pyi"]). For
|
||||||
|
/// example, to treat `.ipy` files as IPython notebooks, use `--extension ipy:ipynb`.
|
||||||
|
#[arg(long, value_delimiter = ',')]
|
||||||
|
pub extension: Option<Vec<ExtensionPair>>,
|
||||||
/// The minimum Python version that should be supported.
|
/// The minimum Python version that should be supported.
|
||||||
#[arg(long, value_enum)]
|
#[arg(long, value_enum)]
|
||||||
pub target_version: Option<PythonVersion>,
|
pub target_version: Option<PythonVersion>,
|
||||||
|
@ -571,6 +576,7 @@ impl FormatCommand {
|
||||||
force_exclude: resolve_bool_arg(self.force_exclude, self.no_force_exclude),
|
force_exclude: resolve_bool_arg(self.force_exclude, self.no_force_exclude),
|
||||||
target_version: self.target_version,
|
target_version: self.target_version,
|
||||||
cache_dir: self.cache_dir,
|
cache_dir: self.cache_dir,
|
||||||
|
extension: self.extension,
|
||||||
|
|
||||||
// Unsupported on the formatter CLI, but required on `Overrides`.
|
// Unsupported on the formatter CLI, but required on `Overrides`.
|
||||||
..CliOverrides::default()
|
..CliOverrides::default()
|
||||||
|
@ -739,7 +745,7 @@ impl ConfigurationTransformer for CliOverrides {
|
||||||
config.target_version = Some(*target_version);
|
config.target_version = Some(*target_version);
|
||||||
}
|
}
|
||||||
if let Some(extension) = &self.extension {
|
if let Some(extension) = &self.extension {
|
||||||
config.lint.extension = Some(extension.clone().into_iter().collect());
|
config.extension = Some(extension.iter().cloned().collect());
|
||||||
}
|
}
|
||||||
|
|
||||||
config
|
config
|
||||||
|
|
|
@ -106,13 +106,19 @@ pub(crate) fn format(
|
||||||
match entry {
|
match entry {
|
||||||
Ok(resolved_file) => {
|
Ok(resolved_file) => {
|
||||||
let path = resolved_file.path();
|
let path = resolved_file.path();
|
||||||
let SourceType::Python(source_type) = SourceType::from(&path) else {
|
let settings = resolver.resolve(path);
|
||||||
|
|
||||||
|
let source_type = match settings.formatter.extension.get(path) {
|
||||||
|
None => match SourceType::from(path) {
|
||||||
|
SourceType::Python(source_type) => source_type,
|
||||||
|
SourceType::Toml(_) => {
|
||||||
// Ignore any non-Python files.
|
// Ignore any non-Python files.
|
||||||
return None;
|
return None;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Some(language) => PySourceType::from(language),
|
||||||
};
|
};
|
||||||
|
|
||||||
let settings = resolver.resolve(path);
|
|
||||||
|
|
||||||
// Ignore files that are excluded from formatting
|
// Ignore files that are excluded from formatting
|
||||||
if (settings.file_resolver.force_exclude || !resolved_file.is_root())
|
if (settings.file_resolver.force_exclude || !resolved_file.is_root())
|
||||||
&& match_exclusion(
|
&& match_exclusion(
|
||||||
|
|
|
@ -53,16 +53,23 @@ pub(crate) fn format_stdin(cli: &FormatArguments, overrides: &CliOverrides) -> R
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = cli.stdin_filename.as_deref();
|
let path = cli.stdin_filename.as_deref();
|
||||||
|
let settings = &resolver.base_settings().formatter;
|
||||||
|
|
||||||
let SourceType::Python(source_type) = path.map(SourceType::from).unwrap_or_default() else {
|
let source_type = match path.and_then(|path| settings.extension.get(path)) {
|
||||||
|
None => match path.map(SourceType::from).unwrap_or_default() {
|
||||||
|
SourceType::Python(source_type) => source_type,
|
||||||
|
SourceType::Toml(_) => {
|
||||||
if mode.is_write() {
|
if mode.is_write() {
|
||||||
parrot_stdin()?;
|
parrot_stdin()?;
|
||||||
}
|
}
|
||||||
return Ok(ExitStatus::Success);
|
return Ok(ExitStatus::Success);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Some(language) => PySourceType::from(language),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Format the file.
|
// Format the file.
|
||||||
match format_source_code(path, &resolver.base_settings().formatter, source_type, mode) {
|
match format_source_code(path, settings, source_type, mode) {
|
||||||
Ok(result) => match mode {
|
Ok(result) => match mode {
|
||||||
FormatMode::Write => Ok(ExitStatus::Success),
|
FormatMode::Write => Ok(ExitStatus::Success),
|
||||||
FormatMode::Check | FormatMode::Diff => {
|
FormatMode::Check | FormatMode::Diff => {
|
||||||
|
|
|
@ -17,7 +17,7 @@ use ruff_linter::logging::DisplayParseError;
|
||||||
use ruff_linter::message::Message;
|
use ruff_linter::message::Message;
|
||||||
use ruff_linter::pyproject_toml::lint_pyproject_toml;
|
use ruff_linter::pyproject_toml::lint_pyproject_toml;
|
||||||
use ruff_linter::registry::AsRule;
|
use ruff_linter::registry::AsRule;
|
||||||
use ruff_linter::settings::types::{ExtensionMapping, UnsafeFixes};
|
use ruff_linter::settings::types::UnsafeFixes;
|
||||||
use ruff_linter::settings::{flags, LinterSettings};
|
use ruff_linter::settings::{flags, LinterSettings};
|
||||||
use ruff_linter::source_kind::{SourceError, SourceKind};
|
use ruff_linter::source_kind::{SourceError, SourceKind};
|
||||||
use ruff_linter::{fs, IOError, SyntaxError};
|
use ruff_linter::{fs, IOError, SyntaxError};
|
||||||
|
@ -179,11 +179,6 @@ impl AddAssign for FixMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn override_source_type(path: Option<&Path>, extension: &ExtensionMapping) -> Option<PySourceType> {
|
|
||||||
let ext = path?.extension()?.to_str()?;
|
|
||||||
extension.get(ext).map(PySourceType::from)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Lint the source code at the given `Path`.
|
/// Lint the source code at the given `Path`.
|
||||||
pub(crate) fn lint_path(
|
pub(crate) fn lint_path(
|
||||||
path: &Path,
|
path: &Path,
|
||||||
|
@ -228,7 +223,7 @@ pub(crate) fn lint_path(
|
||||||
|
|
||||||
debug!("Checking: {}", path.display());
|
debug!("Checking: {}", path.display());
|
||||||
|
|
||||||
let source_type = match override_source_type(Some(path), &settings.extension) {
|
let source_type = match settings.extension.get(path).map(PySourceType::from) {
|
||||||
Some(source_type) => source_type,
|
Some(source_type) => source_type,
|
||||||
None => match SourceType::from(path) {
|
None => match SourceType::from(path) {
|
||||||
SourceType::Toml(TomlSourceType::Pyproject) => {
|
SourceType::Toml(TomlSourceType::Pyproject) => {
|
||||||
|
@ -398,15 +393,14 @@ pub(crate) fn lint_stdin(
|
||||||
fix_mode: flags::FixMode,
|
fix_mode: flags::FixMode,
|
||||||
) -> Result<Diagnostics> {
|
) -> Result<Diagnostics> {
|
||||||
// TODO(charlie): Support `pyproject.toml`.
|
// TODO(charlie): Support `pyproject.toml`.
|
||||||
let source_type = if let Some(source_type) =
|
let source_type = match path.and_then(|path| settings.linter.extension.get(path)) {
|
||||||
override_source_type(path, &settings.linter.extension)
|
None => match path.map(SourceType::from).unwrap_or_default() {
|
||||||
{
|
SourceType::Python(source_type) => source_type,
|
||||||
source_type
|
SourceType::Toml(_) => {
|
||||||
} else {
|
|
||||||
let SourceType::Python(source_type) = path.map(SourceType::from).unwrap_or_default() else {
|
|
||||||
return Ok(Diagnostics::default());
|
return Ok(Diagnostics::default());
|
||||||
};
|
}
|
||||||
source_type
|
},
|
||||||
|
Some(language) => PySourceType::from(language),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extract the sources from the file.
|
// Extract the sources from the file.
|
||||||
|
|
|
@ -1468,3 +1468,73 @@ fn test_notebook_trailing_semicolon() {
|
||||||
----- stderr -----
|
----- stderr -----
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extension() -> Result<()> {
|
||||||
|
let tempdir = TempDir::new()?;
|
||||||
|
|
||||||
|
let ruff_toml = tempdir.path().join("ruff.toml");
|
||||||
|
fs::write(
|
||||||
|
&ruff_toml,
|
||||||
|
r#"
|
||||||
|
include = ["*.ipy"]
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
fs::write(
|
||||||
|
tempdir.path().join("main.ipy"),
|
||||||
|
r#"
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "ad6f36d9-4b7d-4562-8d00-f15a0f1fbb6d",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"x=1"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||||
|
.current_dir(tempdir.path())
|
||||||
|
.arg("format")
|
||||||
|
.arg("--no-cache")
|
||||||
|
.args(["--config", &ruff_toml.file_name().unwrap().to_string_lossy()])
|
||||||
|
.args(["--extension", "ipy:ipynb"])
|
||||||
|
.arg("."), @r###"
|
||||||
|
success: true
|
||||||
|
exit_code: 0
|
||||||
|
----- stdout -----
|
||||||
|
1 file reformatted
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
"###);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
@ -436,3 +436,75 @@ ignore = ["D203", "D212"]
|
||||||
"###);
|
"###);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extension() -> Result<()> {
|
||||||
|
let tempdir = TempDir::new()?;
|
||||||
|
|
||||||
|
let ruff_toml = tempdir.path().join("ruff.toml");
|
||||||
|
fs::write(
|
||||||
|
&ruff_toml,
|
||||||
|
r#"
|
||||||
|
include = ["*.ipy"]
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
fs::write(
|
||||||
|
tempdir.path().join("main.ipy"),
|
||||||
|
r#"
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "ad6f36d9-4b7d-4562-8d00-f15a0f1fbb6d",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import os"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||||
|
.current_dir(tempdir.path())
|
||||||
|
.arg("check")
|
||||||
|
.args(STDIN_BASE_OPTIONS)
|
||||||
|
.args(["--config", &ruff_toml.file_name().unwrap().to_string_lossy()])
|
||||||
|
.args(["--extension", "ipy:ipynb"])
|
||||||
|
.arg("."), @r###"
|
||||||
|
success: false
|
||||||
|
exit_code: 1
|
||||||
|
----- stdout -----
|
||||||
|
main.ipy:cell 1:1:8: F401 [*] `os` imported but unused
|
||||||
|
Found 1 error.
|
||||||
|
[*] 1 fixable with the `--fix` option.
|
||||||
|
|
||||||
|
----- stderr -----
|
||||||
|
"###);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ pub mod types;
|
||||||
#[derive(Debug, CacheKey)]
|
#[derive(Debug, CacheKey)]
|
||||||
pub struct LinterSettings {
|
pub struct LinterSettings {
|
||||||
pub exclude: FilePatternSet,
|
pub exclude: FilePatternSet,
|
||||||
|
pub extension: ExtensionMapping,
|
||||||
pub project_root: PathBuf,
|
pub project_root: PathBuf,
|
||||||
|
|
||||||
pub rules: RuleTable,
|
pub rules: RuleTable,
|
||||||
|
@ -50,7 +51,6 @@ pub struct LinterSettings {
|
||||||
pub target_version: PythonVersion,
|
pub target_version: PythonVersion,
|
||||||
pub preview: PreviewMode,
|
pub preview: PreviewMode,
|
||||||
pub explicit_preview_rules: bool,
|
pub explicit_preview_rules: bool,
|
||||||
pub extension: ExtensionMapping,
|
|
||||||
|
|
||||||
// Rule-specific settings
|
// Rule-specific settings
|
||||||
pub allowed_confusables: FxHashSet<char>,
|
pub allowed_confusables: FxHashSet<char>,
|
||||||
|
|
|
@ -388,9 +388,10 @@ pub struct ExtensionMapping {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtensionMapping {
|
impl ExtensionMapping {
|
||||||
/// Return the [`Language`] for the given extension.
|
/// Return the [`Language`] for the given file.
|
||||||
pub fn get(&self, extension: &str) -> Option<Language> {
|
pub fn get(&self, path: &Path) -> Option<Language> {
|
||||||
self.mapping.get(extension).copied()
|
let ext = path.extension()?.to_str()?;
|
||||||
|
self.mapping.get(ext).copied()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,7 @@ pub struct Configuration {
|
||||||
pub output_format: Option<SerializationFormat>,
|
pub output_format: Option<SerializationFormat>,
|
||||||
pub preview: Option<PreviewMode>,
|
pub preview: Option<PreviewMode>,
|
||||||
pub required_version: Option<Version>,
|
pub required_version: Option<Version>,
|
||||||
|
pub extension: Option<ExtensionMapping>,
|
||||||
pub show_fixes: Option<bool>,
|
pub show_fixes: Option<bool>,
|
||||||
pub show_source: Option<bool>,
|
pub show_source: Option<bool>,
|
||||||
|
|
||||||
|
@ -174,6 +175,7 @@ impl Configuration {
|
||||||
|
|
||||||
let formatter = FormatterSettings {
|
let formatter = FormatterSettings {
|
||||||
exclude: FilePatternSet::try_from_iter(format.exclude.unwrap_or_default())?,
|
exclude: FilePatternSet::try_from_iter(format.exclude.unwrap_or_default())?,
|
||||||
|
extension: self.extension.clone().unwrap_or_default(),
|
||||||
preview: format_preview,
|
preview: format_preview,
|
||||||
target_version: match target_version {
|
target_version: match target_version {
|
||||||
PythonVersion::Py37 => ruff_python_formatter::PythonVersion::Py37,
|
PythonVersion::Py37 => ruff_python_formatter::PythonVersion::Py37,
|
||||||
|
@ -241,7 +243,7 @@ impl Configuration {
|
||||||
linter: LinterSettings {
|
linter: LinterSettings {
|
||||||
rules: lint.as_rule_table(lint_preview),
|
rules: lint.as_rule_table(lint_preview),
|
||||||
exclude: FilePatternSet::try_from_iter(lint.exclude.unwrap_or_default())?,
|
exclude: FilePatternSet::try_from_iter(lint.exclude.unwrap_or_default())?,
|
||||||
extension: lint.extension.unwrap_or_default(),
|
extension: self.extension.unwrap_or_default(),
|
||||||
preview: lint_preview,
|
preview: lint_preview,
|
||||||
target_version,
|
target_version,
|
||||||
project_root: project_root.to_path_buf(),
|
project_root: project_root.to_path_buf(),
|
||||||
|
@ -496,6 +498,9 @@ impl Configuration {
|
||||||
.map(|src| resolve_src(&src, project_root))
|
.map(|src| resolve_src(&src, project_root))
|
||||||
.transpose()?,
|
.transpose()?,
|
||||||
target_version: options.target_version,
|
target_version: options.target_version,
|
||||||
|
// `--extension` is a hidden command-line argument that isn't supported in configuration
|
||||||
|
// files at present.
|
||||||
|
extension: None,
|
||||||
|
|
||||||
lint: LintConfiguration::from_options(lint, project_root)?,
|
lint: LintConfiguration::from_options(lint, project_root)?,
|
||||||
format: FormatConfiguration::from_options(
|
format: FormatConfiguration::from_options(
|
||||||
|
@ -538,6 +543,7 @@ impl Configuration {
|
||||||
src: self.src.or(config.src),
|
src: self.src.or(config.src),
|
||||||
target_version: self.target_version.or(config.target_version),
|
target_version: self.target_version.or(config.target_version),
|
||||||
preview: self.preview.or(config.preview),
|
preview: self.preview.or(config.preview),
|
||||||
|
extension: self.extension.or(config.extension),
|
||||||
|
|
||||||
lint: self.lint.combine(config.lint),
|
lint: self.lint.combine(config.lint),
|
||||||
format: self.format.combine(config.format),
|
format: self.format.combine(config.format),
|
||||||
|
@ -549,7 +555,6 @@ impl Configuration {
|
||||||
pub struct LintConfiguration {
|
pub struct LintConfiguration {
|
||||||
pub exclude: Option<Vec<FilePattern>>,
|
pub exclude: Option<Vec<FilePattern>>,
|
||||||
pub preview: Option<PreviewMode>,
|
pub preview: Option<PreviewMode>,
|
||||||
pub extension: Option<ExtensionMapping>,
|
|
||||||
|
|
||||||
// Rule selection
|
// Rule selection
|
||||||
pub extend_per_file_ignores: Vec<PerFileIgnore>,
|
pub extend_per_file_ignores: Vec<PerFileIgnore>,
|
||||||
|
@ -616,9 +621,6 @@ impl LintConfiguration {
|
||||||
.chain(options.common.extend_unfixable.into_iter().flatten())
|
.chain(options.common.extend_unfixable.into_iter().flatten())
|
||||||
.collect();
|
.collect();
|
||||||
Ok(LintConfiguration {
|
Ok(LintConfiguration {
|
||||||
// `--extension` is a hidden command-line argument that isn't supported in configuration
|
|
||||||
// files at present.
|
|
||||||
extension: None,
|
|
||||||
exclude: options.exclude.map(|paths| {
|
exclude: options.exclude.map(|paths| {
|
||||||
paths
|
paths
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -954,7 +956,6 @@ impl LintConfiguration {
|
||||||
Self {
|
Self {
|
||||||
exclude: self.exclude.or(config.exclude),
|
exclude: self.exclude.or(config.exclude),
|
||||||
preview: self.preview.or(config.preview),
|
preview: self.preview.or(config.preview),
|
||||||
extension: self.extension.or(config.extension),
|
|
||||||
rule_selections: config
|
rule_selections: config
|
||||||
.rule_selections
|
.rule_selections
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -1031,6 +1032,7 @@ impl LintConfiguration {
|
||||||
pub struct FormatConfiguration {
|
pub struct FormatConfiguration {
|
||||||
pub exclude: Option<Vec<FilePattern>>,
|
pub exclude: Option<Vec<FilePattern>>,
|
||||||
pub preview: Option<PreviewMode>,
|
pub preview: Option<PreviewMode>,
|
||||||
|
pub extension: Option<ExtensionMapping>,
|
||||||
|
|
||||||
pub indent_style: Option<IndentStyle>,
|
pub indent_style: Option<IndentStyle>,
|
||||||
pub quote_style: Option<QuoteStyle>,
|
pub quote_style: Option<QuoteStyle>,
|
||||||
|
@ -1044,6 +1046,9 @@ impl FormatConfiguration {
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
pub fn from_options(options: FormatOptions, project_root: &Path) -> Result<Self> {
|
pub fn from_options(options: FormatOptions, project_root: &Path) -> Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
// `--extension` is a hidden command-line argument that isn't supported in configuration
|
||||||
|
// files at present.
|
||||||
|
extension: None,
|
||||||
exclude: options.exclude.map(|paths| {
|
exclude: options.exclude.map(|paths| {
|
||||||
paths
|
paths
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -1077,18 +1082,19 @@ impl FormatConfiguration {
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[allow(clippy::needless_pass_by_value)]
|
#[allow(clippy::needless_pass_by_value)]
|
||||||
pub fn combine(self, other: Self) -> Self {
|
pub fn combine(self, config: Self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
exclude: self.exclude.or(other.exclude),
|
exclude: self.exclude.or(config.exclude),
|
||||||
preview: self.preview.or(other.preview),
|
preview: self.preview.or(config.preview),
|
||||||
indent_style: self.indent_style.or(other.indent_style),
|
extension: self.extension.or(config.extension),
|
||||||
quote_style: self.quote_style.or(other.quote_style),
|
indent_style: self.indent_style.or(config.indent_style),
|
||||||
magic_trailing_comma: self.magic_trailing_comma.or(other.magic_trailing_comma),
|
quote_style: self.quote_style.or(config.quote_style),
|
||||||
line_ending: self.line_ending.or(other.line_ending),
|
magic_trailing_comma: self.magic_trailing_comma.or(config.magic_trailing_comma),
|
||||||
docstring_code_format: self.docstring_code_format.or(other.docstring_code_format),
|
line_ending: self.line_ending.or(config.line_ending),
|
||||||
|
docstring_code_format: self.docstring_code_format.or(config.docstring_code_format),
|
||||||
docstring_code_line_width: self
|
docstring_code_line_width: self
|
||||||
.docstring_code_line_width
|
.docstring_code_line_width
|
||||||
.or(other.docstring_code_line_width),
|
.or(config.docstring_code_line_width),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use path_absolutize::path_dedot;
|
use path_absolutize::path_dedot;
|
||||||
use ruff_cache::cache_dir;
|
use ruff_cache::cache_dir;
|
||||||
use ruff_formatter::{FormatOptions, IndentStyle, IndentWidth, LineWidth};
|
use ruff_formatter::{FormatOptions, IndentStyle, IndentWidth, LineWidth};
|
||||||
use ruff_linter::settings::types::{FilePattern, FilePatternSet, SerializationFormat, UnsafeFixes};
|
use ruff_linter::settings::types::{
|
||||||
|
ExtensionMapping, FilePattern, FilePatternSet, SerializationFormat, UnsafeFixes,
|
||||||
|
};
|
||||||
use ruff_linter::settings::LinterSettings;
|
use ruff_linter::settings::LinterSettings;
|
||||||
use ruff_macros::CacheKey;
|
use ruff_macros::CacheKey;
|
||||||
use ruff_python_ast::PySourceType;
|
use ruff_python_ast::PySourceType;
|
||||||
|
@ -116,6 +118,7 @@ impl FileResolverSettings {
|
||||||
#[derive(CacheKey, Clone, Debug)]
|
#[derive(CacheKey, Clone, Debug)]
|
||||||
pub struct FormatterSettings {
|
pub struct FormatterSettings {
|
||||||
pub exclude: FilePatternSet,
|
pub exclude: FilePatternSet,
|
||||||
|
pub extension: ExtensionMapping,
|
||||||
pub preview: PreviewMode,
|
pub preview: PreviewMode,
|
||||||
pub target_version: ruff_python_formatter::PythonVersion,
|
pub target_version: ruff_python_formatter::PythonVersion,
|
||||||
|
|
||||||
|
@ -177,6 +180,7 @@ impl Default for FormatterSettings {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
exclude: FilePatternSet::default(),
|
exclude: FilePatternSet::default(),
|
||||||
|
extension: ExtensionMapping::default(),
|
||||||
target_version: default_options.target_version(),
|
target_version: default_options.target_version(),
|
||||||
preview: PreviewMode::Disabled,
|
preview: PreviewMode::Disabled,
|
||||||
line_width: default_options.line_width(),
|
line_width: default_options.line_width(),
|
||||||
|
|
|
@ -528,6 +528,8 @@ Options:
|
||||||
Enable preview mode; checks will include unstable rules and fixes. Use `--no-preview` to disable
|
Enable preview mode; checks will include unstable rules and fixes. Use `--no-preview` to disable
|
||||||
--config <CONFIG>
|
--config <CONFIG>
|
||||||
Path to the `pyproject.toml` or `ruff.toml` file to use for configuration
|
Path to the `pyproject.toml` or `ruff.toml` file to use for configuration
|
||||||
|
--extension <EXTENSION>
|
||||||
|
List of mappings from file extension to language (one of ["python", "ipynb", "pyi"]). For example, to treat `.ipy` files as IPython notebooks, use `--extension ipy:ipynb`
|
||||||
--statistics
|
--statistics
|
||||||
Show counts for every rule with at least one violation
|
Show counts for every rule with at least one violation
|
||||||
--add-noqa
|
--add-noqa
|
||||||
|
@ -604,6 +606,8 @@ Options:
|
||||||
Avoid writing any formatted files back; instead, exit with a non-zero status code and the difference between the current file and how the formatted file would look like
|
Avoid writing any formatted files back; instead, exit with a non-zero status code and the difference between the current file and how the formatted file would look like
|
||||||
--config <CONFIG>
|
--config <CONFIG>
|
||||||
Path to the `pyproject.toml` or `ruff.toml` file to use for configuration
|
Path to the `pyproject.toml` or `ruff.toml` file to use for configuration
|
||||||
|
--extension <EXTENSION>
|
||||||
|
List of mappings from file extension to language (one of ["python", "ipynb", "pyi"]). For example, to treat `.ipy` files as IPython notebooks, use `--extension ipy:ipynb`
|
||||||
--target-version <TARGET_VERSION>
|
--target-version <TARGET_VERSION>
|
||||||
The minimum Python version that should be supported [possible values: py37, py38, py39, py310, py311, py312]
|
The minimum Python version that should be supported [possible values: py37, py38, py39, py310, py311, py312]
|
||||||
--preview
|
--preview
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue