Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New pycodestyle.max-line-length option #8039

Merged
merged 2 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions crates/ruff_cli/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use ruff_linter::settings::types::{
};
use ruff_linter::{RuleParser, RuleSelector, RuleSelectorParser};
use ruff_workspace::configuration::{Configuration, RuleSelection};
use ruff_workspace::options::PycodestyleOptions;
use ruff_workspace::resolver::ConfigurationTransformer;

#[derive(Debug, Parser)]
Expand Down Expand Up @@ -685,8 +686,12 @@ impl ConfigurationTransformer for CliOverrides {
if let Some(force_exclude) = &self.force_exclude {
config.force_exclude = Some(*force_exclude);
}
if let Some(line_length) = &self.line_length {
config.line_length = Some(*line_length);
if let Some(line_length) = self.line_length {
config.line_length = Some(line_length);
config.lint.pycodestyle = Some(PycodestyleOptions {
max_line_length: Some(line_length),
..config.lint.pycodestyle.unwrap_or_default()
});
}
if let Some(preview) = &self.preview {
config.preview = Some(*preview);
Expand Down
38 changes: 38 additions & 0 deletions crates/ruff_cli/tests/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,3 +270,41 @@ if __name__ == "__main__":
"###);
Ok(())
}

#[test]
fn line_too_long_width_override() -> Result<()> {
let tempdir = TempDir::new()?;
let ruff_toml = tempdir.path().join("ruff.toml");
fs::write(
&ruff_toml,
r#"
line-length = 80
select = ["E501"]

[pycodestyle]
max-line-length = 100
"#,
)?;

assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
.args(STDIN_BASE_OPTIONS)
.arg("--config")
.arg(&ruff_toml)
.args(["--stdin-filename", "test.py"])
.arg("-")
.pass_stdin(r#"
# longer than 80, but less than 100
_ = "---------------------------------------------------------------------------亜亜亜亜亜亜"
# longer than 100
_ = "---------------------------------------------------------------------------亜亜亜亜亜亜亜亜亜亜亜亜亜亜"
"#), @r###"
success: false
exit_code: 1
----- stdout -----
test.py:5:91: E501 Line too long (109 > 100)
Found 1 error.

----- stderr -----
"###);
Ok(())
}
6 changes: 5 additions & 1 deletion crates/ruff_linter/src/checkers/physical_lines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ mod tests {

use crate::line_width::LineLength;
use crate::registry::Rule;
use crate::rules::pycodestyle;
use crate::settings::LinterSettings;

use super::check_physical_lines;
Expand All @@ -114,7 +115,10 @@ mod tests {
&indexer,
&[],
&LinterSettings {
line_length,
pycodestyle: pycodestyle::settings::Settings {
max_line_length: line_length,
..pycodestyle::settings::Settings::default()
},
..LinterSettings::for_rule(Rule::LineTooLong)
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ pub(crate) fn multiple_with_statements(
content,
with_stmt.into(),
checker.locator(),
checker.settings.line_length,
checker.settings.pycodestyle.max_line_length,
checker.settings.tab_size,
)
}) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ pub(crate) fn nested_if_statements(
content,
(&nested_if).into(),
checker.locator(),
checker.settings.line_length,
checker.settings.pycodestyle.max_line_length,
checker.settings.tab_size,
)
}) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ pub(crate) fn if_else_block_instead_of_dict_get(checker: &mut Checker, stmt_if:
&contents,
stmt_if.into(),
checker.locator(),
checker.settings.line_length,
checker.settings.pycodestyle.max_line_length,
checker.settings.tab_size,
) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ pub(crate) fn if_else_block_instead_of_if_exp(checker: &mut Checker, stmt_if: &a
&contents,
stmt_if.into(),
checker.locator(),
checker.settings.line_length,
checker.settings.pycodestyle.max_line_length,
checker.settings.tab_size,
) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub(crate) fn convert_for_loop_to_any_all(checker: &mut Checker, stmt: &Stmt) {
&contents,
stmt.into(),
checker.locator(),
checker.settings.line_length,
checker.settings.pycodestyle.max_line_length,
checker.settings.tab_size,
) {
return;
Expand Down Expand Up @@ -188,7 +188,7 @@ pub(crate) fn convert_for_loop_to_any_all(checker: &mut Checker, stmt: &Stmt) {
.slice(TextRange::new(line_start, stmt.start())),
)
.add_str(&contents)
> checker.settings.line_length
> checker.settings.pycodestyle.max_line_length
{
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ pub(crate) fn organize_imports(
block,
comments,
locator,
settings.line_length,
settings.pycodestyle.max_line_length,
LineWidthBuilder::new(settings.tab_size).add_str(indentation),
stylist,
&settings.src,
Expand Down
6 changes: 5 additions & 1 deletion crates/ruff_linter/src/rules/pycodestyle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ mod tests {

use crate::line_width::LineLength;
use crate::registry::Rule;
use crate::rules::pycodestyle;
use crate::settings::types::PreviewMode;
use crate::test::test_path;
use crate::{assert_messages, settings};
Expand Down Expand Up @@ -229,7 +230,10 @@ mod tests {
Path::new("pycodestyle/E501_2.py"),
&settings::LinterSettings {
tab_size: NonZeroU8::new(tab_size).unwrap().into(),
line_length: LineLength::try_from(6).unwrap(),
pycodestyle: pycodestyle::settings::Settings {
max_line_length: LineLength::try_from(6).unwrap(),
..pycodestyle::settings::Settings::default()
},
..settings::LinterSettings::for_rule(Rule::LineTooLong)
},
)?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ use crate::settings::LinterSettings;
///
/// ## Options
/// - `line-length`
/// - `pycodestyle.max-line-length`
/// - `task-tags`
/// - `pycodestyle.ignore-overlong-task-comments`
///
Expand All @@ -68,7 +69,7 @@ pub(crate) fn line_too_long(
indexer: &Indexer,
settings: &LinterSettings,
) -> Option<Diagnostic> {
let limit = settings.line_length;
let limit = settings.pycodestyle.max_line_length;

Overlong::try_from_line(
line,
Expand Down
1 change: 1 addition & 0 deletions crates/ruff_linter/src/rules/pycodestyle/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::line_width::LineLength;

#[derive(Debug, Default, CacheKey)]
pub struct Settings {
pub max_line_length: LineLength,
pub max_doc_length: Option<LineLength>,
pub ignore_overlong_task_comments: bool,
}
2 changes: 1 addition & 1 deletion crates/ruff_linter/src/rules/pyupgrade/rules/f_strings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ pub(crate) fn f_strings(
&contents,
template.into(),
checker.locator(),
checker.settings.line_length,
checker.settings.pycodestyle.max_line_length,
checker.settings.tab_size,
) {
return;
Expand Down
4 changes: 1 addition & 3 deletions crates/ruff_linter/src/settings/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::rules::{
use crate::settings::types::{FilePatternSet, PerFileIgnore, PythonVersion};
use crate::{codes, RuleSelector};

use super::line_width::{LineLength, TabSize};
use super::line_width::TabSize;

use self::rule_table::RuleTable;
use self::types::PreviewMode;
Expand Down Expand Up @@ -56,7 +56,6 @@ pub struct LinterSettings {
pub dummy_variable_rgx: Regex,
pub external: FxHashSet<String>,
pub ignore_init_module_imports: bool,
pub line_length: LineLength,
pub logger_objects: Vec<String>,
pub namespace_packages: Vec<PathBuf>,
pub src: Vec<PathBuf>,
Expand Down Expand Up @@ -147,7 +146,6 @@ impl LinterSettings {

external: HashSet::default(),
ignore_init_module_imports: false,
line_length: LineLength::default(),
logger_objects: vec![],
namespace_packages: vec![],

Expand Down
16 changes: 11 additions & 5 deletions crates/ruff_workspace/src/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use ruff_linter::line_width::{LineLength, TabSize};
use ruff_linter::registry::RuleNamespace;
use ruff_linter::registry::{Rule, RuleSet, INCOMPATIBLE_CODES};
use ruff_linter::rule_selector::{PreviewOptions, Specificity};
use ruff_linter::rules::pycodestyle;
use ruff_linter::settings::rule_table::RuleTable;
use ruff_linter::settings::types::{
FilePattern, FilePatternSet, PerFileIgnore, PreviewMode, PythonVersion, SerializationFormat,
Expand Down Expand Up @@ -183,6 +184,8 @@ impl Configuration {
let lint = self.lint;
let lint_preview = lint.preview.unwrap_or(global_preview);

let line_length = self.line_length.unwrap_or_default();

Ok(Settings {
cache_dir: self
.cache_dir
Expand Down Expand Up @@ -225,7 +228,6 @@ impl Configuration {
.unwrap_or_else(|| DUMMY_VARIABLE_RGX.clone()),
external: FxHashSet::from_iter(lint.external.unwrap_or_default()),
ignore_init_module_imports: lint.ignore_init_module_imports.unwrap_or_default(),
line_length: self.line_length.unwrap_or_default(),
tab_size: self.tab_size.unwrap_or_default(),
namespace_packages: self.namespace_packages.unwrap_or_default(),
per_file_ignores: resolve_per_file_ignores(
Expand Down Expand Up @@ -346,10 +348,14 @@ impl Configuration {
.map(Pep8NamingOptions::try_into_settings)
.transpose()?
.unwrap_or_default(),
pycodestyle: lint
.pycodestyle
.map(PycodestyleOptions::into_settings)
.unwrap_or_default(),
pycodestyle: if let Some(pycodestyle) = lint.pycodestyle {
pycodestyle.into_settings(line_length)
} else {
pycodestyle::settings::Settings {
max_line_length: line_length,
..pycodestyle::settings::Settings::default()
}
},
pydocstyle: lint
.pydocstyle
.map(PydocstyleOptions::into_settings)
Expand Down
41 changes: 35 additions & 6 deletions crates/ruff_workspace/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub struct Options {
/// this base configuration file, then merge in any properties defined
/// in the current configuration file.
#[option(
default = r#"None"#,
default = r#"null"#,
value_type = "str",
example = r#"
# Extend the `pyproject.toml` file in the parent directory.
Expand Down Expand Up @@ -132,7 +132,7 @@ pub struct Options {
/// results across many environments, e.g., with a `pyproject.toml`
/// file).
#[option(
default = "None",
default = "null",
value_type = "str",
example = r#"
required-version = "0.0.193"
Expand Down Expand Up @@ -362,6 +362,8 @@ pub struct Options {
/// Note: While the formatter will attempt to format lines such that they remain
/// within the `line-length`, it isn't a hard upper bound, and formatted lines may
/// exceed the `line-length`.
///
/// See [`pycodestyle.max-line-length`](#pycodestyle-max-line-length) to configure different lengths for `E501` and the formatter.
#[option(
default = "88",
value_type = "int",
Expand Down Expand Up @@ -1043,7 +1045,7 @@ pub struct Flake8CopyrightOptions {

/// Author to enforce within the copyright notice. If provided, the
/// author must be present immediately following the copyright notice.
#[option(default = "None", value_type = "str", example = r#"author = "Ruff""#)]
#[option(default = "null", value_type = "str", example = r#"author = "Ruff""#)]
pub author: Option<String>,

/// A minimum file size (in bytes) required for a copyright notice to
Expand Down Expand Up @@ -2247,6 +2249,32 @@ impl Pep8NamingOptions {
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct PycodestyleOptions {
/// The maximum line length to allow for [`line-too-long`](https://docs.astral.sh/ruff/rules/line-too-long/) violations. By default,
/// this is set to the value of the [`line-length`](#line-length) option.
///
/// Use this option when you want to detect extra-long lines that the formatter can't automatically split by setting
/// `pycodestyle.line-length` to a value larger than [`line-length`](#line-length).
///
/// ```toml
/// line-length = 88 # The formatter wraps lines at a length of 88
///
/// [pycodestyle]
/// max-line-length = 100 # E501 reports lines that exceed the length of 100.
/// ```
///
/// The length is determined by the number of characters per line, except for lines containing East Asian characters or emojis.
/// For these lines, the [unicode width](https://unicode.org/reports/tr11/) of each character is added up to determine the length.
///
/// See the [`line-too-long`](https://docs.astral.sh/ruff/rules/line-too-long/) rule for more information.
#[option(
default = "null",
value_type = "int",
example = r#"
max-line-length = 100
"#
)]
pub max_line_length: Option<LineLength>,

/// The maximum line length to allow for [`doc-line-too-long`](https://docs.astral.sh/ruff/rules/doc-line-too-long/) violations within
/// documentation (`W505`), including standalone comments. By default,
/// this is set to null which disables reporting violations.
Expand All @@ -2256,7 +2284,7 @@ pub struct PycodestyleOptions {
///
/// See the [`doc-line-too-long`](https://docs.astral.sh/ruff/rules/doc-line-too-long/) rule for more information.
#[option(
default = "None",
default = "null",
value_type = "int",
example = r#"
max-doc-length = 88
Expand All @@ -2278,9 +2306,10 @@ pub struct PycodestyleOptions {
}

impl PycodestyleOptions {
pub fn into_settings(self) -> pycodestyle::settings::Settings {
pub fn into_settings(self, global_line_length: LineLength) -> pycodestyle::settings::Settings {
pycodestyle::settings::Settings {
max_doc_length: self.max_doc_length,
max_line_length: self.max_line_length.unwrap_or(global_line_length),
ignore_overlong_task_comments: self.ignore_overlong_task_comments.unwrap_or_default(),
}
}
Expand Down Expand Up @@ -2321,7 +2350,7 @@ pub struct PydocstyleOptions {
/// enabling _additional_ rules on top of a convention is currently
/// unsupported.
#[option(
default = r#"None"#,
default = r#"null"#,
value_type = r#""google" | "numpy" | "pep257""#,
example = r#"
# Use Google-style docstrings.
Expand Down
13 changes: 12 additions & 1 deletion ruff.schema.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading