mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 18:28:56 +00:00
--show-settings
displays active settings in a far more readable format (#9464)
<!-- Thank you for contributing to Ruff! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? - Does this pull request include references to any relevant issues? --> ## Summary Fixes #8334. `Display` has been implemented for `ruff_workspace::Settings`, which gives a much nicer and more readable output to `--show-settings`. Internally, a `display_settings` utility macro has been implemented to reduce the boilerplate of the display code. ### Work to be done - [x] A lot of formatting for `Vec<_>` and `HashSet<_>` types have been stubbed out, using `Debug` as a fallback. There should be a way to add generic formatting support for these types as a modifier in `display_settings`. - [x] Several complex types were also stubbed out and need proper `Display` implementations rather than falling back on `Debug`. - [x] An open question needs to be answered: how important is it that the output be valid TOML? Some types in settings, such as a hash-map from a glob pattern to a multi-variant enum, will be hard to rework into valid _and_ readable TOML. - [x] Tests need to be implemented. ## Test Plan Tests consist of a snapshot test for the default `--show-settings` output and a doctest for `display_settings!`.
This commit is contained in:
parent
fee64b52ba
commit
7504bf347b
39 changed files with 1455 additions and 43 deletions
|
@ -35,7 +35,7 @@ pub(crate) fn show_settings(
|
|||
if let Some(settings_path) = pyproject_config.path.as_ref() {
|
||||
writeln!(writer, "Settings path: {settings_path:?}")?;
|
||||
}
|
||||
writeln!(writer, "{settings:#?}")?;
|
||||
write!(writer, "{settings}")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
29
crates/ruff_cli/tests/show_settings.rs
Normal file
29
crates/ruff_cli/tests/show_settings.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
use insta_cmd::{assert_cmd_snapshot, get_cargo_bin};
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
const BIN_NAME: &str = "ruff";
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
const TEST_FILTERS: &[(&str, &str)] = &[
|
||||
("\"[^\\*\"]*/pyproject.toml", "\"[BASEPATH]/pyproject.toml"),
|
||||
("\".*/crates", "\"[BASEPATH]/crates"),
|
||||
("\".*/\\.ruff_cache", "\"[BASEPATH]/.ruff_cache"),
|
||||
("\".*/ruff\"", "\"[BASEPATH]\""),
|
||||
];
|
||||
#[cfg(target_os = "windows")]
|
||||
const TEST_FILTERS: &[(&str, &str)] = &[
|
||||
(r#""[^\*"]*\\pyproject.toml"#, "\"[BASEPATH]/pyproject.toml"),
|
||||
(r#"".*\\crates"#, "\"[BASEPATH]/crates"),
|
||||
(r#"".*\\\.ruff_cache"#, "\"[BASEPATH]/.ruff_cache"),
|
||||
(r#"".*\\ruff""#, "\"[BASEPATH]\""),
|
||||
(r#"\\+(\w\w|\s|")"#, "/$1"),
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn display_default_settings() {
|
||||
insta::with_settings!({ filters => TEST_FILTERS.to_vec() }, {
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(["check", "--show-settings", "unformatted.py"]).current_dir(Path::new("./resources/test/fixtures")));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,368 @@
|
|||
---
|
||||
source: crates/ruff_cli/tests/show_settings.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
- check
|
||||
- "--show-settings"
|
||||
- unformatted.py
|
||||
---
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
Resolved settings for: "[BASEPATH]/crates/ruff_cli/resources/test/fixtures/unformatted.py"
|
||||
Settings path: "[BASEPATH]/pyproject.toml"
|
||||
|
||||
# General Settings
|
||||
cache_dir = "[BASEPATH]/.ruff_cache"
|
||||
fix = false
|
||||
fix_only = false
|
||||
output_format = text
|
||||
show_fixes = false
|
||||
show_source = false
|
||||
unsafe_fixes = hint
|
||||
|
||||
# File Resolver Settings
|
||||
file_resolver.exclude = [
|
||||
".bzr",
|
||||
".direnv",
|
||||
".eggs",
|
||||
".git",
|
||||
".git-rewrite",
|
||||
".hg",
|
||||
".ipynb_checkpoints",
|
||||
".mypy_cache",
|
||||
".nox",
|
||||
".pants.d",
|
||||
".pyenv",
|
||||
".pytest_cache",
|
||||
".pytype",
|
||||
".ruff_cache",
|
||||
".svn",
|
||||
".tox",
|
||||
".venv",
|
||||
".vscode",
|
||||
"__pypackages__",
|
||||
"_build",
|
||||
"buck-out",
|
||||
"build",
|
||||
"dist",
|
||||
"node_modules",
|
||||
"site-packages",
|
||||
"venv",
|
||||
]
|
||||
file_resolver.extend_exclude = [
|
||||
"crates/ruff_linter/resources/",
|
||||
"crates/ruff_python_formatter/resources/",
|
||||
]
|
||||
file_resolver.force_exclude = false
|
||||
file_resolver.include = [
|
||||
"*.py",
|
||||
"*.pyi",
|
||||
"**/pyproject.toml",
|
||||
]
|
||||
file_resolver.extend_include = []
|
||||
file_resolver.respect_gitignore = true
|
||||
file_resolver.project_root = "[BASEPATH]"
|
||||
|
||||
# Linter Settings
|
||||
linter.exclude = []
|
||||
linter.project_root = "[BASEPATH]"
|
||||
linter.rules.enabled = [
|
||||
MultipleImportsOnOneLine,
|
||||
ModuleImportNotAtTopOfFile,
|
||||
MultipleStatementsOnOneLineColon,
|
||||
MultipleStatementsOnOneLineSemicolon,
|
||||
UselessSemicolon,
|
||||
NoneComparison,
|
||||
TrueFalseComparison,
|
||||
NotInTest,
|
||||
NotIsTest,
|
||||
TypeComparison,
|
||||
BareExcept,
|
||||
LambdaAssignment,
|
||||
AmbiguousVariableName,
|
||||
AmbiguousClassName,
|
||||
AmbiguousFunctionName,
|
||||
IOError,
|
||||
SyntaxError,
|
||||
UnusedImport,
|
||||
ImportShadowedByLoopVar,
|
||||
UndefinedLocalWithImportStar,
|
||||
LateFutureImport,
|
||||
UndefinedLocalWithImportStarUsage,
|
||||
UndefinedLocalWithNestedImportStarUsage,
|
||||
FutureFeatureNotDefined,
|
||||
PercentFormatInvalidFormat,
|
||||
PercentFormatExpectedMapping,
|
||||
PercentFormatExpectedSequence,
|
||||
PercentFormatExtraNamedArguments,
|
||||
PercentFormatMissingArgument,
|
||||
PercentFormatMixedPositionalAndNamed,
|
||||
PercentFormatPositionalCountMismatch,
|
||||
PercentFormatStarRequiresSequence,
|
||||
PercentFormatUnsupportedFormatCharacter,
|
||||
StringDotFormatInvalidFormat,
|
||||
StringDotFormatExtraNamedArguments,
|
||||
StringDotFormatExtraPositionalArguments,
|
||||
StringDotFormatMissingArguments,
|
||||
StringDotFormatMixingAutomatic,
|
||||
FStringMissingPlaceholders,
|
||||
MultiValueRepeatedKeyLiteral,
|
||||
MultiValueRepeatedKeyVariable,
|
||||
ExpressionsInStarAssignment,
|
||||
MultipleStarredExpressions,
|
||||
AssertTuple,
|
||||
IsLiteral,
|
||||
InvalidPrintSyntax,
|
||||
IfTuple,
|
||||
BreakOutsideLoop,
|
||||
ContinueOutsideLoop,
|
||||
YieldOutsideFunction,
|
||||
ReturnOutsideFunction,
|
||||
DefaultExceptNotLast,
|
||||
ForwardAnnotationSyntaxError,
|
||||
RedefinedWhileUnused,
|
||||
UndefinedName,
|
||||
UndefinedExport,
|
||||
UndefinedLocal,
|
||||
UnusedVariable,
|
||||
UnusedAnnotation,
|
||||
RaiseNotImplemented,
|
||||
]
|
||||
linter.rules.should_fix = [
|
||||
MultipleImportsOnOneLine,
|
||||
ModuleImportNotAtTopOfFile,
|
||||
MultipleStatementsOnOneLineColon,
|
||||
MultipleStatementsOnOneLineSemicolon,
|
||||
UselessSemicolon,
|
||||
NoneComparison,
|
||||
TrueFalseComparison,
|
||||
NotInTest,
|
||||
NotIsTest,
|
||||
TypeComparison,
|
||||
BareExcept,
|
||||
LambdaAssignment,
|
||||
AmbiguousVariableName,
|
||||
AmbiguousClassName,
|
||||
AmbiguousFunctionName,
|
||||
IOError,
|
||||
SyntaxError,
|
||||
UnusedImport,
|
||||
ImportShadowedByLoopVar,
|
||||
UndefinedLocalWithImportStar,
|
||||
LateFutureImport,
|
||||
UndefinedLocalWithImportStarUsage,
|
||||
UndefinedLocalWithNestedImportStarUsage,
|
||||
FutureFeatureNotDefined,
|
||||
PercentFormatInvalidFormat,
|
||||
PercentFormatExpectedMapping,
|
||||
PercentFormatExpectedSequence,
|
||||
PercentFormatExtraNamedArguments,
|
||||
PercentFormatMissingArgument,
|
||||
PercentFormatMixedPositionalAndNamed,
|
||||
PercentFormatPositionalCountMismatch,
|
||||
PercentFormatStarRequiresSequence,
|
||||
PercentFormatUnsupportedFormatCharacter,
|
||||
StringDotFormatInvalidFormat,
|
||||
StringDotFormatExtraNamedArguments,
|
||||
StringDotFormatExtraPositionalArguments,
|
||||
StringDotFormatMissingArguments,
|
||||
StringDotFormatMixingAutomatic,
|
||||
FStringMissingPlaceholders,
|
||||
MultiValueRepeatedKeyLiteral,
|
||||
MultiValueRepeatedKeyVariable,
|
||||
ExpressionsInStarAssignment,
|
||||
MultipleStarredExpressions,
|
||||
AssertTuple,
|
||||
IsLiteral,
|
||||
InvalidPrintSyntax,
|
||||
IfTuple,
|
||||
BreakOutsideLoop,
|
||||
ContinueOutsideLoop,
|
||||
YieldOutsideFunction,
|
||||
ReturnOutsideFunction,
|
||||
DefaultExceptNotLast,
|
||||
ForwardAnnotationSyntaxError,
|
||||
RedefinedWhileUnused,
|
||||
UndefinedName,
|
||||
UndefinedExport,
|
||||
UndefinedLocal,
|
||||
UnusedVariable,
|
||||
UnusedAnnotation,
|
||||
RaiseNotImplemented,
|
||||
]
|
||||
linter.per_file_ignores = {}
|
||||
linter.safety_table.forced_safe = []
|
||||
linter.safety_table.forced_unsafe = []
|
||||
linter.target_version = Py37
|
||||
linter.preview = disabled
|
||||
linter.explicit_preview_rules = false
|
||||
linter.extension.mapping = {}
|
||||
linter.allowed_confusables = []
|
||||
linter.builtins = []
|
||||
linter.dummy_variable_rgx = ^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$
|
||||
linter.external = []
|
||||
linter.ignore_init_module_imports = false
|
||||
linter.logger_objects = []
|
||||
linter.namespace_packages = []
|
||||
linter.src = ["[BASEPATH]"]
|
||||
linter.tab_size = 4
|
||||
linter.line_length = 88
|
||||
linter.task_tags = [
|
||||
TODO,
|
||||
FIXME,
|
||||
XXX,
|
||||
]
|
||||
linter.typing_modules = []
|
||||
|
||||
# Linter Plugins
|
||||
linter.flake8_annotations.mypy_init_return = false
|
||||
linter.flake8_annotations.suppress_dummy_args = false
|
||||
linter.flake8_annotations.suppress_none_returning = false
|
||||
linter.flake8_annotations.allow_star_arg_any = false
|
||||
linter.flake8_annotations.ignore_fully_untyped = false
|
||||
linter.flake8_bandit.hardcoded_tmp_directory = [
|
||||
/tmp,
|
||||
/var/tmp,
|
||||
/dev/shm,
|
||||
]
|
||||
linter.flake8_bandit.check_typed_exception = false
|
||||
linter.flake8_bugbear.extend_immutable_calls = []
|
||||
linter.flake8_builtins.builtins_ignorelist = []
|
||||
linter.flake8_comprehensions.allow_dict_calls_with_keyword_arguments = false
|
||||
linter.flake8_copyright.notice_rgx = (?i)Copyright\s+(\(C\)\s+)?\d{4}(-\d{4})*
|
||||
linter.flake8_copyright.author = none
|
||||
linter.flake8_copyright.min_file_size = 0
|
||||
linter.flake8_errmsg.max_string_length = 0
|
||||
linter.flake8_gettext.functions_names = [
|
||||
_,
|
||||
gettext,
|
||||
ngettext,
|
||||
]
|
||||
linter.flake8_implicit_str_concat.allow_multiline = true
|
||||
linter.flake8_import_conventions.aliases = {"matplotlib": "mpl", "matplotlib.pyplot": "plt", "pandas": "pd", "seaborn": "sns", "tensorflow": "tf", "networkx": "nx", "plotly.express": "px", "polars": "pl", "numpy": "np", "panel": "pn", "pyarrow": "pa", "altair": "alt", "tkinter": "tk", "holoviews": "hv"}
|
||||
linter.flake8_import_conventions.banned_aliases = {}
|
||||
linter.flake8_import_conventions.banned_from = []
|
||||
linter.flake8_pytest_style.fixture_parentheses = true
|
||||
linter.flake8_pytest_style.parametrize_names_type = tuple
|
||||
linter.flake8_pytest_style.parametrize_values_type = list
|
||||
linter.flake8_pytest_style.parametrize_values_row_type = tuple
|
||||
linter.flake8_pytest_style.raises_require_match_for = [
|
||||
BaseException,
|
||||
Exception,
|
||||
ValueError,
|
||||
OSError,
|
||||
IOError,
|
||||
EnvironmentError,
|
||||
socket.error,
|
||||
]
|
||||
linter.flake8_pytest_style.raises_extend_require_match_for = []
|
||||
linter.flake8_pytest_style.mark_parentheses = true
|
||||
linter.flake8_quotes.inline_quotes = double
|
||||
linter.flake8_quotes.multiline_quotes = double
|
||||
linter.flake8_quotes.docstring_quotes = double
|
||||
linter.flake8_quotes.avoid_escape = true
|
||||
linter.flake8_self.ignore_names = [
|
||||
_make,
|
||||
_asdict,
|
||||
_replace,
|
||||
_fields,
|
||||
_field_defaults,
|
||||
_name_,
|
||||
_value_,
|
||||
]
|
||||
linter.flake8_tidy_imports.ban_relative_imports = "parents"
|
||||
linter.flake8_tidy_imports.banned_api = {}
|
||||
linter.flake8_tidy_imports.banned_module_level_imports = []
|
||||
linter.flake8_type_checking.strict = false
|
||||
linter.flake8_type_checking.exempt_modules = [
|
||||
typing,
|
||||
typing_extensions,
|
||||
]
|
||||
linter.flake8_type_checking.runtime_required_base_classes = []
|
||||
linter.flake8_type_checking.runtime_required_decorators = []
|
||||
linter.flake8_type_checking.quote_annotations = false
|
||||
linter.flake8_unused_arguments.ignore_variadic_names = false
|
||||
linter.isort.required_imports = []
|
||||
linter.isort.combine_as_imports = false
|
||||
linter.isort.force_single_line = false
|
||||
linter.isort.force_sort_within_sections = false
|
||||
linter.isort.detect_same_package = true
|
||||
linter.isort.case_sensitive = false
|
||||
linter.isort.force_wrap_aliases = false
|
||||
linter.isort.force_to_top = []
|
||||
linter.isort.known_modules = {}
|
||||
linter.isort.order_by_type = true
|
||||
linter.isort.relative_imports_order = furthest_to_closest
|
||||
linter.isort.single_line_exclusions = []
|
||||
linter.isort.split_on_trailing_comma = true
|
||||
linter.isort.classes = []
|
||||
linter.isort.constants = []
|
||||
linter.isort.variables = []
|
||||
linter.isort.no_lines_before = []
|
||||
linter.isort.lines_after_imports = -1
|
||||
linter.isort.lines_between_types = 0
|
||||
linter.isort.forced_separate = []
|
||||
linter.isort.section_order = [
|
||||
known { type = future },
|
||||
known { type = standard_library },
|
||||
known { type = third_party },
|
||||
known { type = first_party },
|
||||
known { type = local_folder },
|
||||
]
|
||||
linter.isort.no_sections = false
|
||||
linter.isort.from_first = false
|
||||
linter.isort.length_sort = false
|
||||
linter.isort.length_sort_straight = false
|
||||
linter.mccabe.max_complexity = 10
|
||||
linter.pep8_naming.ignore_names = [
|
||||
setUp,
|
||||
tearDown,
|
||||
setUpClass,
|
||||
tearDownClass,
|
||||
setUpModule,
|
||||
tearDownModule,
|
||||
asyncSetUp,
|
||||
asyncTearDown,
|
||||
setUpTestData,
|
||||
failureException,
|
||||
longMessage,
|
||||
maxDiff,
|
||||
]
|
||||
linter.pep8_naming.classmethod_decorators = []
|
||||
linter.pep8_naming.staticmethod_decorators = []
|
||||
linter.pycodestyle.max_line_length = 88
|
||||
linter.pycodestyle.max_doc_length = none
|
||||
linter.pycodestyle.ignore_overlong_task_comments = false
|
||||
linter.pyflakes.extend_generics = []
|
||||
linter.pylint.allow_magic_value_types = [
|
||||
str,
|
||||
bytes,
|
||||
]
|
||||
linter.pylint.allow_dunder_method_names = []
|
||||
linter.pylint.max_args = 5
|
||||
linter.pylint.max_positional_args = 5
|
||||
linter.pylint.max_returns = 6
|
||||
linter.pylint.max_bool_expr = 5
|
||||
linter.pylint.max_branches = 12
|
||||
linter.pylint.max_statements = 50
|
||||
linter.pylint.max_public_methods = 20
|
||||
linter.pylint.max_locals = 15
|
||||
linter.pyupgrade.keep_runtime_typing = false
|
||||
|
||||
# Formatter Settings
|
||||
formatter.exclude = []
|
||||
formatter.target_version = Py37
|
||||
formatter.preview = disabled
|
||||
formatter.line_width = 88
|
||||
formatter.line_ending = auto
|
||||
formatter.indent_style = space
|
||||
formatter.indent_width = 4
|
||||
formatter.quote_style = double
|
||||
formatter.magic_trailing_comma = respect
|
||||
formatter.docstring_code_format = disabled
|
||||
formatter.docstring_code_line_width = dynamic
|
||||
|
||||
----- stderr -----
|
||||
|
|
@ -35,6 +35,7 @@ mod source_code;
|
|||
use crate::formatter::Formatter;
|
||||
use crate::group_id::UniqueGroupIdBuilder;
|
||||
use crate::prelude::TagKind;
|
||||
use std::fmt;
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::marker::PhantomData;
|
||||
use std::num::{NonZeroU16, NonZeroU8, TryFromIntError};
|
||||
|
@ -113,6 +114,12 @@ impl Default for IndentWidth {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for IndentWidth {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for IndentWidth {
|
||||
type Error = TryFromIntError;
|
||||
|
||||
|
@ -146,6 +153,12 @@ impl Default for LineWidth {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for LineWidth {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u16> for LineWidth {
|
||||
type Error = TryFromIntError;
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::hash::Hasher;
|
||||
use std::num::{NonZeroU16, NonZeroU8, ParseIntError};
|
||||
use std::str::FromStr;
|
||||
|
@ -39,6 +40,12 @@ impl Default for LineLength {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for LineLength {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl CacheKey for LineLength {
|
||||
fn cache_key(&self, state: &mut CacheKeyHasher) {
|
||||
state.write_u16(self.0.get());
|
||||
|
@ -248,6 +255,12 @@ impl Default for IndentWidth {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for IndentWidth {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NonZeroU8> for IndentWidth {
|
||||
fn from(tab_size: NonZeroU8) -> Self {
|
||||
Self(tab_size)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::registry::Rule;
|
||||
use ruff_macros::CacheKey;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
use std::iter::FusedIterator;
|
||||
|
||||
const RULESET_SIZE: usize = 13;
|
||||
|
@ -269,6 +269,21 @@ impl Debug for RuleSet {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for RuleSet {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
if self.is_empty() {
|
||||
write!(f, "[]")?;
|
||||
} else {
|
||||
writeln!(f, "[")?;
|
||||
for rule in self {
|
||||
writeln!(f, "\t{rule:?},")?;
|
||||
}
|
||||
write!(f, "]")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl FromIterator<Rule> for RuleSet {
|
||||
fn from_iter<T: IntoIterator<Item = Rule>>(iter: T) -> Self {
|
||||
let mut set = RuleSet::empty();
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
//! Settings for the `flake-annotations` plugin.
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Debug, Default, CacheKey)]
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
|
@ -11,3 +13,20 @@ pub struct Settings {
|
|||
pub allow_star_arg_any: bool,
|
||||
pub ignore_fully_untyped: bool,
|
||||
}
|
||||
|
||||
impl Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.flake8_annotations",
|
||||
fields = [
|
||||
self.mypy_init_return,
|
||||
self.suppress_dummy_args,
|
||||
self.suppress_none_returning,
|
||||
self.allow_star_arg_any,
|
||||
self.ignore_fully_untyped
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
//! Settings for the `flake8-bandit` plugin.
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
pub fn default_tmp_dirs() -> Vec<String> {
|
||||
["/tmp", "/var/tmp", "/dev/shm"]
|
||||
|
@ -22,3 +24,17 @@ impl Default for Settings {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.flake8_bandit",
|
||||
fields = [
|
||||
self.hardcoded_tmp_directory | array,
|
||||
self.check_typed_exception
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,23 @@
|
|||
//! Settings for the `flake8-bugbear` plugin.
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Debug, Default, CacheKey)]
|
||||
pub struct Settings {
|
||||
pub extend_immutable_calls: Vec<String>,
|
||||
}
|
||||
|
||||
impl Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.flake8_bugbear",
|
||||
fields = [
|
||||
self.extend_immutable_calls | array
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,23 @@
|
|||
//! Settings for the `flake8-builtins` plugin.
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Debug, Default, CacheKey)]
|
||||
pub struct Settings {
|
||||
pub builtins_ignorelist: Vec<String>,
|
||||
}
|
||||
|
||||
impl Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.flake8_builtins",
|
||||
fields = [
|
||||
self.builtins_ignorelist | array
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,23 @@
|
|||
//! Settings for the `flake8-comprehensions` plugin.
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Debug, Default, CacheKey)]
|
||||
pub struct Settings {
|
||||
pub allow_dict_calls_with_keyword_arguments: bool,
|
||||
}
|
||||
|
||||
impl Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.flake8_comprehensions",
|
||||
fields = [
|
||||
self.allow_dict_calls_with_keyword_arguments
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
|
||||
#[derive(Debug, CacheKey)]
|
||||
|
@ -24,3 +26,18 @@ impl Default for Settings {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.flake8_copyright",
|
||||
fields = [
|
||||
self.notice_rgx,
|
||||
self.author | optional,
|
||||
self.min_file_size,
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,23 @@
|
|||
//! Settings for the `flake8-errmsg` plugin.
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Debug, Default, CacheKey)]
|
||||
pub struct Settings {
|
||||
pub max_string_length: usize,
|
||||
}
|
||||
|
||||
impl Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.flake8_errmsg",
|
||||
fields = [
|
||||
self.max_string_length
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Debug, CacheKey)]
|
||||
pub struct Settings {
|
||||
|
@ -20,3 +22,16 @@ impl Default for Settings {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.flake8_gettext",
|
||||
fields = [
|
||||
self.functions_names | array
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
//! Settings for the `flake8-implicit-str-concat` plugin.
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Debug, CacheKey)]
|
||||
pub struct Settings {
|
||||
|
@ -14,3 +16,16 @@ impl Default for Settings {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.flake8_implicit_str_concat",
|
||||
fields = [
|
||||
self.allow_multiline
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
//! Settings for import conventions.
|
||||
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
|
||||
const CONVENTIONAL_ALIASES: &[(&str, &str)] = &[
|
||||
|
@ -44,3 +46,18 @@ impl Default for Settings {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.flake8_import_conventions",
|
||||
fields = [
|
||||
self.aliases | debug,
|
||||
self.banned_aliases | debug,
|
||||
self.banned_from | array,
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
//! Settings for the `flake8-pytest-style` plugin.
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::fmt::Formatter;
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
|
||||
use crate::settings::types::IdentifierPattern;
|
||||
|
@ -47,6 +49,25 @@ impl Default for Settings {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.flake8_pytest_style",
|
||||
fields = [
|
||||
self.fixture_parentheses,
|
||||
self.parametrize_names_type,
|
||||
self.parametrize_values_type,
|
||||
self.parametrize_values_row_type,
|
||||
self.raises_require_match_for | array,
|
||||
self.raises_extend_require_match_for | array,
|
||||
self.mark_parentheses
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Error returned by the [`TryFrom`] implementation of [`Settings`].
|
||||
#[derive(Debug)]
|
||||
pub enum SettingsError {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
//! Settings for the `flake8-quotes` plugin.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, CacheKey)]
|
||||
|
@ -39,6 +41,22 @@ impl Default for Settings {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.flake8_quotes",
|
||||
fields = [
|
||||
self.inline_quotes,
|
||||
self.multiline_quotes,
|
||||
self.docstring_quotes,
|
||||
self.avoid_escape
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Quote {
|
||||
#[must_use]
|
||||
pub const fn opposite(self) -> Self {
|
||||
|
@ -56,3 +74,12 @@ impl Quote {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Quote {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Double => write!(f, "double"),
|
||||
Self::Single => write!(f, "single"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
//! Settings for the `flake8-self` plugin.
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
// By default, ignore the `namedtuple` methods and attributes, as well as the
|
||||
// _sunder_ names in Enum, which are underscore-prefixed to prevent conflicts
|
||||
|
@ -27,3 +29,16 @@ impl Default for Settings {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.flake8_self",
|
||||
fields = [
|
||||
self.ignore_names | array
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use rustc_hash::FxHashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, CacheKey)]
|
||||
|
@ -22,9 +24,33 @@ pub enum Strictness {
|
|||
All,
|
||||
}
|
||||
|
||||
impl Display for Strictness {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Parents => write!(f, "\"parents\""),
|
||||
Self::All => write!(f, "\"all\""),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, CacheKey, Default)]
|
||||
pub struct Settings {
|
||||
pub ban_relative_imports: Strictness,
|
||||
pub banned_api: FxHashMap<String, ApiBan>,
|
||||
pub banned_module_level_imports: Vec<String>,
|
||||
}
|
||||
|
||||
impl Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.flake8_tidy_imports",
|
||||
fields = [
|
||||
self.ban_relative_imports,
|
||||
self.banned_api | debug,
|
||||
self.banned_module_level_imports | array,
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
//! Settings for the `flake8-type-checking` plugin.
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Debug, CacheKey)]
|
||||
pub struct Settings {
|
||||
|
@ -22,3 +24,20 @@ impl Default for Settings {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.flake8_type_checking",
|
||||
fields = [
|
||||
self.strict,
|
||||
self.exempt_modules | array,
|
||||
self.runtime_required_base_classes | array,
|
||||
self.runtime_required_decorators | array,
|
||||
self.quote_annotations
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,23 @@
|
|||
//! Settings for the `flake8-unused-arguments` plugin.
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Debug, Default, CacheKey)]
|
||||
pub struct Settings {
|
||||
pub ignore_variadic_names: bool,
|
||||
}
|
||||
|
||||
impl Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.flake8_unused_arguments",
|
||||
fields = [
|
||||
self.ignore_variadic_names
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::fmt;
|
||||
use std::hash::BuildHasherDefault;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{fs, iter};
|
||||
|
@ -40,6 +41,18 @@ pub enum ImportType {
|
|||
LocalFolder,
|
||||
}
|
||||
|
||||
impl fmt::Display for ImportType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Future => write!(f, "future"),
|
||||
Self::StandardLibrary => write!(f, "standard_library"),
|
||||
Self::ThirdParty => write!(f, "third_party"),
|
||||
Self::FirstParty => write!(f, "first_party"),
|
||||
Self::LocalFolder => write!(f, "local_folder"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq, Clone, Hash, Serialize, Deserialize, CacheKey)]
|
||||
#[serde(untagged)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
|
@ -48,6 +61,15 @@ pub enum ImportSection {
|
|||
UserDefined(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for ImportSection {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Known(import_type) => write!(f, "known {{ type = {import_type} }}",),
|
||||
Self::UserDefined(string) => fmt::Debug::fmt(string, f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Reason<'a> {
|
||||
NonZeroLevel,
|
||||
|
@ -378,3 +400,18 @@ impl KnownModules {
|
|||
user_defined
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for KnownModules {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.known.is_empty() {
|
||||
write!(f, "{{}}")?;
|
||||
} else {
|
||||
writeln!(f, "{{")?;
|
||||
for (pattern, import_section) in &self.known {
|
||||
writeln!(f, "\t{pattern} => {import_section:?},")?;
|
||||
}
|
||||
write!(f, "}}")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
use std::collections::BTreeSet;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
|
||||
use crate::rules::isort::categorize::KnownModules;
|
||||
|
@ -32,6 +34,15 @@ impl Default for RelativeImportsOrder {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for RelativeImportsOrder {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::ClosestToFurthest => write!(f, "closest_to_furthest"),
|
||||
Self::FurthestToClosest => write!(f, "furthest_to_closest"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, CacheKey)]
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
pub struct Settings {
|
||||
|
@ -94,6 +105,43 @@ impl Default for Settings {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.isort",
|
||||
fields = [
|
||||
self.required_imports | array,
|
||||
self.combine_as_imports,
|
||||
self.force_single_line,
|
||||
self.force_sort_within_sections,
|
||||
self.detect_same_package,
|
||||
self.case_sensitive,
|
||||
self.force_wrap_aliases,
|
||||
self.force_to_top | array,
|
||||
self.known_modules,
|
||||
self.order_by_type,
|
||||
self.relative_imports_order,
|
||||
self.single_line_exclusions | array,
|
||||
self.split_on_trailing_comma,
|
||||
self.classes | array,
|
||||
self.constants | array,
|
||||
self.variables | array,
|
||||
self.no_lines_before | array,
|
||||
self.lines_after_imports,
|
||||
self.lines_between_types,
|
||||
self.forced_separate | array,
|
||||
self.section_order | array,
|
||||
self.no_sections,
|
||||
self.from_first,
|
||||
self.length_sort,
|
||||
self.length_sort_straight
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Error returned by the [`TryFrom`] implementation of [`Settings`].
|
||||
#[derive(Debug)]
|
||||
pub enum SettingsError {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
//! Settings for the `mccabe` plugin.
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Debug, CacheKey)]
|
||||
pub struct Settings {
|
||||
|
@ -16,3 +18,16 @@ impl Default for Settings {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.mccabe",
|
||||
fields = [
|
||||
self.max_complexity
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::fmt::Formatter;
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
|
||||
use crate::settings::types::IdentifierPattern;
|
||||
|
@ -44,6 +46,21 @@ impl Default for Settings {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Settings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.pep8_naming",
|
||||
fields = [
|
||||
self.ignore_names | array,
|
||||
self.classmethod_decorators | array,
|
||||
self.staticmethod_decorators | array
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Error returned by the [`TryFrom`] implementation of [`Settings`].
|
||||
#[derive(Debug)]
|
||||
pub enum SettingsError {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
//! Settings for the `pycodestyle` plugin.
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
use std::fmt;
|
||||
|
||||
use crate::line_width::LineLength;
|
||||
|
||||
|
@ -10,3 +12,18 @@ pub struct Settings {
|
|||
pub max_doc_length: Option<LineLength>,
|
||||
pub ignore_overlong_task_comments: bool,
|
||||
}
|
||||
|
||||
impl fmt::Display for Settings {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.pycodestyle",
|
||||
fields = [
|
||||
self.max_line_length,
|
||||
self.max_doc_length | optional,
|
||||
self.ignore_overlong_task_comments,
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
//! Settings for the `pydocstyle` plugin.
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
use std::fmt;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
|
||||
use crate::registry::Rule;
|
||||
|
@ -71,9 +73,34 @@ impl Convention {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Convention {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Google => write!(f, "google"),
|
||||
Self::Numpy => write!(f, "numpy"),
|
||||
Self::Pep257 => write!(f, "pep257"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, CacheKey)]
|
||||
pub struct Settings {
|
||||
pub convention: Option<Convention>,
|
||||
pub ignore_decorators: BTreeSet<String>,
|
||||
pub property_decorators: BTreeSet<String>,
|
||||
}
|
||||
|
||||
impl fmt::Display for Settings {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.pydocstyle",
|
||||
fields = [
|
||||
self.convention | optional,
|
||||
self.ignore_decorators | debug,
|
||||
self.property_decorators | debug
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,23 @@
|
|||
//! Settings for the `Pyflakes` plugin.
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, Default, CacheKey)]
|
||||
pub struct Settings {
|
||||
pub extend_generics: Vec<String>,
|
||||
}
|
||||
|
||||
impl fmt::Display for Settings {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.pyflakes",
|
||||
fields = [
|
||||
self.extend_generics | debug
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
use rustc_hash::FxHashSet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
use ruff_python_ast::{ExprNumberLiteral, LiteralExpressionRef, Number};
|
||||
|
||||
|
@ -34,6 +36,18 @@ impl ConstantType {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ConstantType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Bytes => write!(f, "bytes"),
|
||||
Self::Complex => write!(f, "complex"),
|
||||
Self::Float => write!(f, "float"),
|
||||
Self::Int => write!(f, "int"),
|
||||
Self::Str => write!(f, "str"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, CacheKey)]
|
||||
pub struct Settings {
|
||||
pub allow_magic_value_types: Vec<ConstantType>,
|
||||
|
@ -64,3 +78,25 @@ impl Default for Settings {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Settings {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.pylint",
|
||||
fields = [
|
||||
self.allow_magic_value_types | array,
|
||||
self.allow_dunder_method_names | array,
|
||||
self.max_args,
|
||||
self.max_positional_args,
|
||||
self.max_returns,
|
||||
self.max_bool_expr,
|
||||
self.max_branches,
|
||||
self.max_statements,
|
||||
self.max_public_methods,
|
||||
self.max_locals
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,23 @@
|
|||
//! Settings for the `pyupgrade` plugin.
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, Default, CacheKey)]
|
||||
pub struct Settings {
|
||||
pub keep_runtime_typing: bool,
|
||||
}
|
||||
|
||||
impl fmt::Display for Settings {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.pyupgrade",
|
||||
fields = [
|
||||
self.keep_runtime_typing
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,7 @@ mod tests {
|
|||
|
||||
use crate::pyproject_toml::lint_pyproject_toml;
|
||||
use crate::registry::Rule;
|
||||
use crate::settings::resolve_per_file_ignores;
|
||||
use crate::settings::types::{PerFileIgnore, PreviewMode, PythonVersion};
|
||||
use crate::settings::types::{PerFileIgnore, PerFileIgnores, PreviewMode, PythonVersion};
|
||||
use crate::test::{test_path, test_resource_path};
|
||||
use crate::{assert_messages, settings};
|
||||
|
||||
|
@ -171,7 +170,7 @@ mod tests {
|
|||
let mut settings =
|
||||
settings::LinterSettings::for_rules(vec![Rule::UnusedNOQA, Rule::UnusedImport]);
|
||||
|
||||
settings.per_file_ignores = resolve_per_file_ignores(vec![PerFileIgnore::new(
|
||||
settings.per_file_ignores = PerFileIgnores::resolve(vec![PerFileIgnore::new(
|
||||
"RUF100_2.py".to_string(),
|
||||
&["F401".parse().unwrap()],
|
||||
None,
|
||||
|
@ -228,7 +227,7 @@ mod tests {
|
|||
let diagnostics = test_path(
|
||||
Path::new("ruff/ruff_per_file_ignores.py"),
|
||||
&settings::LinterSettings {
|
||||
per_file_ignores: resolve_per_file_ignores(vec![PerFileIgnore::new(
|
||||
per_file_ignores: PerFileIgnores::resolve(vec![PerFileIgnore::new(
|
||||
"ruff_per_file_ignores.py".to_string(),
|
||||
&["F401".parse().unwrap(), "RUF100".parse().unwrap()],
|
||||
None,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::fmt::Debug;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
|
||||
use ruff_diagnostics::Applicability;
|
||||
use ruff_macros::CacheKey;
|
||||
|
@ -6,6 +6,7 @@ use rustc_hash::FxHashMap;
|
|||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::{
|
||||
display_settings,
|
||||
registry::{Rule, RuleSet},
|
||||
rule_selector::{PreviewOptions, Specificity},
|
||||
RuleSelector,
|
||||
|
@ -95,6 +96,20 @@ impl FixSafetyTable {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for FixSafetyTable {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.safety_table",
|
||||
fields = [
|
||||
self.forced_safe,
|
||||
self.forced_unsafe
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -2,10 +2,9 @@
|
|||
//! command-line options. Structure is optimized for internal usage, as opposed
|
||||
//! to external visibility or parsing.
|
||||
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use anyhow::Result;
|
||||
use globset::{Glob, GlobMatcher};
|
||||
use once_cell::sync::Lazy;
|
||||
use path_absolutize::path_dedot;
|
||||
use regex::Regex;
|
||||
|
@ -15,7 +14,7 @@ use crate::codes::RuleCodePrefix;
|
|||
use ruff_macros::CacheKey;
|
||||
|
||||
use crate::line_width::LineLength;
|
||||
use crate::registry::{Linter, Rule, RuleSet};
|
||||
use crate::registry::{Linter, Rule};
|
||||
use crate::rules::{
|
||||
flake8_annotations, flake8_bandit, flake8_bugbear, flake8_builtins, flake8_comprehensions,
|
||||
flake8_copyright, flake8_errmsg, flake8_gettext, flake8_implicit_str_concat,
|
||||
|
@ -23,7 +22,7 @@ use crate::rules::{
|
|||
flake8_tidy_imports, flake8_type_checking, flake8_unused_arguments, isort, mccabe, pep8_naming,
|
||||
pycodestyle, pydocstyle, pyflakes, pylint, pyupgrade,
|
||||
};
|
||||
use crate::settings::types::{ExtensionMapping, FilePatternSet, PerFileIgnore, PythonVersion};
|
||||
use crate::settings::types::{ExtensionMapping, FilePatternSet, PerFileIgnores, PythonVersion};
|
||||
use crate::{codes, RuleSelector};
|
||||
|
||||
use super::line_width::IndentWidth;
|
||||
|
@ -38,6 +37,126 @@ pub mod flags;
|
|||
pub mod rule_table;
|
||||
pub mod types;
|
||||
|
||||
/// `display_settings!` is a macro that can display and format struct fields in a readable,
|
||||
/// namespaced format. It's particularly useful at generating `Display` implementations
|
||||
/// for types used in settings.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
/// use ruff_linter::display_settings;
|
||||
/// #[derive(Default)]
|
||||
/// struct Settings {
|
||||
/// option_a: bool,
|
||||
/// sub_settings: SubSettings,
|
||||
/// option_b: String,
|
||||
/// }
|
||||
///
|
||||
/// struct SubSettings {
|
||||
/// name: String
|
||||
/// }
|
||||
///
|
||||
/// impl Default for SubSettings {
|
||||
/// fn default() -> Self {
|
||||
/// Self { name: "Default Name".into() }
|
||||
/// }
|
||||
///
|
||||
/// }
|
||||
///
|
||||
/// impl fmt::Display for SubSettings {
|
||||
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// display_settings! {
|
||||
/// formatter = f,
|
||||
/// namespace = "sub_settings",
|
||||
/// fields = [
|
||||
/// self.name | quoted
|
||||
/// ]
|
||||
/// }
|
||||
/// Ok(())
|
||||
/// }
|
||||
///
|
||||
/// }
|
||||
///
|
||||
/// impl fmt::Display for Settings {
|
||||
/// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// display_settings! {
|
||||
/// formatter = f,
|
||||
/// fields = [
|
||||
/// self.option_a,
|
||||
/// self.sub_settings | nested,
|
||||
/// self.option_b | quoted,
|
||||
/// ]
|
||||
/// }
|
||||
/// Ok(())
|
||||
/// }
|
||||
///
|
||||
/// }
|
||||
///
|
||||
/// const EXPECTED_OUTPUT: &str = r#"option_a = false
|
||||
/// sub_settings.name = "Default Name"
|
||||
/// option_b = ""
|
||||
/// "#;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let settings = Settings::default();
|
||||
/// assert_eq!(format!("{settings}"), EXPECTED_OUTPUT);
|
||||
/// }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! display_settings {
|
||||
(formatter = $fmt:ident, namespace = $namespace:literal, fields = [$($settings:ident.$field:ident $(| $modifier:tt)?),* $(,)?]) => {
|
||||
{
|
||||
const _PREFIX: &str = concat!($namespace, ".");
|
||||
$(
|
||||
display_settings!(@field $fmt, _PREFIX, $settings.$field $(| $modifier)?);
|
||||
)*
|
||||
}
|
||||
};
|
||||
(formatter = $fmt:ident, fields = [$($settings:ident.$field:ident $(| $modifier:tt)?),* $(,)?]) => {
|
||||
{
|
||||
const _PREFIX: &str = "";
|
||||
$(
|
||||
display_settings!(@field $fmt, _PREFIX, $settings.$field $(| $modifier)?);
|
||||
)*
|
||||
}
|
||||
};
|
||||
(@field $fmt:ident, $prefix:ident, $settings:ident.$field:ident | debug) => {
|
||||
writeln!($fmt, "{}{} = {:?}", $prefix, stringify!($field), $settings.$field)?;
|
||||
};
|
||||
(@field $fmt:ident, $prefix:ident, $settings:ident.$field:ident | quoted) => {
|
||||
writeln!($fmt, "{}{} = \"{}\"", $prefix, stringify!($field), $settings.$field)?;
|
||||
};
|
||||
(@field $fmt:ident, $prefix:ident, $settings:ident.$field:ident | nested) => {
|
||||
write!($fmt, "{}", $settings.$field)?;
|
||||
};
|
||||
(@field $fmt:ident, $prefix:ident, $settings:ident.$field:ident | optional) => {
|
||||
{
|
||||
write!($fmt, "{}{} = ", $prefix, stringify!($field))?;
|
||||
match &$settings.$field {
|
||||
Some(value) => writeln!($fmt, "{}", value)?,
|
||||
None => writeln!($fmt, "none")?
|
||||
};
|
||||
}
|
||||
};
|
||||
(@field $fmt:ident, $prefix:ident, $settings:ident.$field:ident | array) => {
|
||||
{
|
||||
write!($fmt, "{}{} = ", $prefix, stringify!($field))?;
|
||||
if $settings.$field.is_empty() {
|
||||
writeln!($fmt, "[]")?;
|
||||
} else {
|
||||
writeln!($fmt, "[")?;
|
||||
for elem in &$settings.$field {
|
||||
writeln!($fmt, "\t{elem},")?;
|
||||
}
|
||||
writeln!($fmt, "]")?;
|
||||
}
|
||||
}
|
||||
};
|
||||
(@field $fmt:ident, $prefix:ident, $settings:ident.$field:ident) => {
|
||||
writeln!($fmt, "{}{} = {}", $prefix, stringify!($field), $settings.$field)?;
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, CacheKey)]
|
||||
pub struct LinterSettings {
|
||||
pub exclude: FilePatternSet,
|
||||
|
@ -45,7 +164,7 @@ pub struct LinterSettings {
|
|||
pub project_root: PathBuf,
|
||||
|
||||
pub rules: RuleTable,
|
||||
pub per_file_ignores: Vec<(GlobMatcher, GlobMatcher, RuleSet)>,
|
||||
pub per_file_ignores: PerFileIgnores,
|
||||
pub fix_safety: FixSafetyTable,
|
||||
|
||||
pub target_version: PythonVersion,
|
||||
|
@ -93,6 +212,73 @@ pub struct LinterSettings {
|
|||
pub pyupgrade: pyupgrade::settings::Settings,
|
||||
}
|
||||
|
||||
impl Display for LinterSettings {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
writeln!(f, "\n# Linter Settings")?;
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter",
|
||||
fields = [
|
||||
self.exclude,
|
||||
self.project_root | debug,
|
||||
|
||||
self.rules | nested,
|
||||
self.per_file_ignores,
|
||||
self.fix_safety | nested,
|
||||
|
||||
self.target_version | debug,
|
||||
self.preview,
|
||||
self.explicit_preview_rules,
|
||||
self.extension | nested,
|
||||
|
||||
self.allowed_confusables | array,
|
||||
self.builtins | array,
|
||||
self.dummy_variable_rgx,
|
||||
self.external | array,
|
||||
self.ignore_init_module_imports,
|
||||
self.logger_objects | array,
|
||||
self.namespace_packages | debug,
|
||||
self.src | debug,
|
||||
self.tab_size,
|
||||
self.line_length,
|
||||
self.task_tags | array,
|
||||
self.typing_modules | array,
|
||||
]
|
||||
}
|
||||
writeln!(f, "\n# Linter Plugins")?;
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter",
|
||||
fields = [
|
||||
self.flake8_annotations | nested,
|
||||
self.flake8_bandit | nested,
|
||||
self.flake8_bugbear | nested,
|
||||
self.flake8_builtins | nested,
|
||||
self.flake8_comprehensions | nested,
|
||||
self.flake8_copyright | nested,
|
||||
self.flake8_errmsg | nested,
|
||||
self.flake8_gettext | nested,
|
||||
self.flake8_implicit_str_concat | nested,
|
||||
self.flake8_import_conventions | nested,
|
||||
self.flake8_pytest_style | nested,
|
||||
self.flake8_quotes | nested,
|
||||
self.flake8_self | nested,
|
||||
self.flake8_tidy_imports | nested,
|
||||
self.flake8_type_checking | nested,
|
||||
self.flake8_unused_arguments | nested,
|
||||
self.isort | nested,
|
||||
self.mccabe | nested,
|
||||
self.pep8_naming | nested,
|
||||
self.pycodestyle | nested,
|
||||
self.pyflakes | nested,
|
||||
self.pylint | nested,
|
||||
self.pyupgrade | nested,
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub const DEFAULT_SELECTORS: &[RuleSelector] = &[
|
||||
RuleSelector::Linter(Linter::Pyflakes),
|
||||
// Only include pycodestyle rules that do not overlap with the formatter
|
||||
|
@ -152,7 +338,7 @@ impl LinterSettings {
|
|||
logger_objects: vec![],
|
||||
namespace_packages: vec![],
|
||||
|
||||
per_file_ignores: vec![],
|
||||
per_file_ignores: PerFileIgnores::default(),
|
||||
fix_safety: FixSafetyTable::default(),
|
||||
|
||||
src: vec![path_dedot::CWD.clone()],
|
||||
|
@ -204,22 +390,3 @@ impl Default for LinterSettings {
|
|||
Self::new(path_dedot::CWD.as_path())
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a list of patterns, create a `GlobSet`.
|
||||
pub fn resolve_per_file_ignores(
|
||||
per_file_ignores: Vec<PerFileIgnore>,
|
||||
) -> Result<Vec<(GlobMatcher, GlobMatcher, RuleSet)>> {
|
||||
per_file_ignores
|
||||
.into_iter()
|
||||
.map(|per_file_ignore| {
|
||||
// Construct absolute path matcher.
|
||||
let absolute =
|
||||
Glob::new(&per_file_ignore.absolute.to_string_lossy())?.compile_matcher();
|
||||
|
||||
// Construct basename matcher.
|
||||
let basename = Glob::new(&per_file_ignore.basename)?.compile_matcher();
|
||||
|
||||
Ok((absolute, basename, per_file_ignore.rules))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::fmt::Debug;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
|
||||
use crate::display_settings;
|
||||
use ruff_macros::CacheKey;
|
||||
|
||||
use crate::registry::{Rule, RuleSet, RuleSetIterator};
|
||||
|
@ -62,6 +63,20 @@ impl RuleTable {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for RuleTable {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.rules",
|
||||
fields = [
|
||||
self.enabled,
|
||||
self.should_fix
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl FromIterator<Rule> for RuleTable {
|
||||
fn from_iter<T: IntoIterator<Item = Rule>>(iter: T) -> Self {
|
||||
let rules = RuleSet::from_iter(iter);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::fmt::{Display, Formatter};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::Deref;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
@ -5,7 +6,7 @@ use std::str::FromStr;
|
|||
use std::string::ToString;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use globset::{Glob, GlobSet, GlobSetBuilder};
|
||||
use globset::{Glob, GlobMatcher, GlobSet, GlobSetBuilder};
|
||||
use pep440_rs::{Version as Pep440Version, VersionSpecifiers};
|
||||
use rustc_hash::FxHashMap;
|
||||
use serde::{de, Deserialize, Deserializer, Serialize};
|
||||
|
@ -17,9 +18,9 @@ use ruff_diagnostics::Applicability;
|
|||
use ruff_macros::CacheKey;
|
||||
use ruff_python_ast::PySourceType;
|
||||
|
||||
use crate::fs;
|
||||
use crate::registry::RuleSet;
|
||||
use crate::rule_selector::RuleSelector;
|
||||
use crate::{display_settings, fs};
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
|
@ -121,6 +122,15 @@ impl From<bool> for PreviewMode {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for PreviewMode {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Disabled => write!(f, "disabled"),
|
||||
Self::Enabled => write!(f, "enabled"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Toggle for unsafe fixes.
|
||||
/// `Hint` will not apply unsafe fixes but a message will be shown when they are available.
|
||||
/// `Disabled` will not apply unsafe fixes or show a message.
|
||||
|
@ -133,6 +143,20 @@ pub enum UnsafeFixes {
|
|||
Enabled,
|
||||
}
|
||||
|
||||
impl Display for UnsafeFixes {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self {
|
||||
Self::Hint => "hint",
|
||||
Self::Disabled => "disabled",
|
||||
Self::Enabled => "enabled",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for UnsafeFixes {
|
||||
fn from(value: bool) -> Self {
|
||||
if value {
|
||||
|
@ -178,6 +202,19 @@ impl FilePattern {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for FilePattern {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{:?}",
|
||||
match self {
|
||||
Self::Builtin(pattern) => pattern,
|
||||
Self::User(pattern, _) => pattern.as_str(),
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for FilePattern {
|
||||
type Err = anyhow::Error;
|
||||
|
||||
|
@ -192,9 +229,14 @@ impl FromStr for FilePattern {
|
|||
pub struct FilePatternSet {
|
||||
set: GlobSet,
|
||||
cache_key: u64,
|
||||
// This field is only for displaying the internals
|
||||
// of `set`.
|
||||
#[allow(clippy::used_underscore_binding)]
|
||||
_set_internals: Vec<FilePattern>,
|
||||
}
|
||||
|
||||
impl FilePatternSet {
|
||||
#[allow(clippy::used_underscore_binding)]
|
||||
pub fn try_from_iter<I>(patterns: I) -> Result<Self, anyhow::Error>
|
||||
where
|
||||
I: IntoIterator<Item = FilePattern>,
|
||||
|
@ -202,7 +244,10 @@ impl FilePatternSet {
|
|||
let mut builder = GlobSetBuilder::new();
|
||||
let mut hasher = CacheKeyHasher::new();
|
||||
|
||||
let mut _set_internals = vec![];
|
||||
|
||||
for pattern in patterns {
|
||||
_set_internals.push(pattern.clone());
|
||||
pattern.cache_key(&mut hasher);
|
||||
pattern.add_to(&mut builder)?;
|
||||
}
|
||||
|
@ -212,10 +257,26 @@ impl FilePatternSet {
|
|||
Ok(FilePatternSet {
|
||||
set,
|
||||
cache_key: hasher.finish(),
|
||||
_set_internals,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FilePatternSet {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
if self._set_internals.is_empty() {
|
||||
write!(f, "[]")?;
|
||||
} else {
|
||||
writeln!(f, "[")?;
|
||||
for pattern in &self._set_internals {
|
||||
writeln!(f, "\t{pattern},")?;
|
||||
}
|
||||
write!(f, "]")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for FilePatternSet {
|
||||
type Target = GlobSet;
|
||||
|
||||
|
@ -395,6 +456,19 @@ impl ExtensionMapping {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for ExtensionMapping {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "linter.extension",
|
||||
fields = [
|
||||
self.mapping | debug
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FxHashMap<String, Language>> for ExtensionMapping {
|
||||
fn from(value: FxHashMap<String, Language>) -> Self {
|
||||
Self { mapping: value }
|
||||
|
@ -429,6 +503,23 @@ pub enum SerializationFormat {
|
|||
Sarif,
|
||||
}
|
||||
|
||||
impl Display for SerializationFormat {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Text => write!(f, "text"),
|
||||
Self::Json => write!(f, "json"),
|
||||
Self::JsonLines => write!(f, "json_lines"),
|
||||
Self::Junit => write!(f, "junit"),
|
||||
Self::Grouped => write!(f, "grouped"),
|
||||
Self::Github => write!(f, "github"),
|
||||
Self::Gitlab => write!(f, "gitlab"),
|
||||
Self::Pylint => write!(f, "pylint"),
|
||||
Self::Azure => write!(f, "azure"),
|
||||
Self::Sarif => write!(f, "sarif"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SerializationFormat {
|
||||
fn default() -> Self {
|
||||
Self::Text
|
||||
|
@ -468,3 +559,55 @@ impl Deref for Version {
|
|||
/// [`fnmatch`](https://docs.python.org/3/library/fnmatch.html) for
|
||||
/// pattern matching.
|
||||
pub type IdentifierPattern = glob::Pattern;
|
||||
|
||||
#[derive(Debug, CacheKey, Default)]
|
||||
pub struct PerFileIgnores {
|
||||
// Ordered as (absolute path matcher, basename matcher, rules)
|
||||
ignores: Vec<(GlobMatcher, GlobMatcher, RuleSet)>,
|
||||
}
|
||||
|
||||
impl PerFileIgnores {
|
||||
/// Given a list of patterns, create a `GlobSet`.
|
||||
pub fn resolve(per_file_ignores: Vec<PerFileIgnore>) -> Result<Self> {
|
||||
let ignores: Result<Vec<_>> = per_file_ignores
|
||||
.into_iter()
|
||||
.map(|per_file_ignore| {
|
||||
// Construct absolute path matcher.
|
||||
let absolute =
|
||||
Glob::new(&per_file_ignore.absolute.to_string_lossy())?.compile_matcher();
|
||||
|
||||
// Construct basename matcher.
|
||||
let basename = Glob::new(&per_file_ignore.basename)?.compile_matcher();
|
||||
|
||||
Ok((absolute, basename, per_file_ignore.rules))
|
||||
})
|
||||
.collect();
|
||||
Ok(Self { ignores: ignores? })
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for PerFileIgnores {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
if self.is_empty() {
|
||||
write!(f, "{{}}")?;
|
||||
} else {
|
||||
writeln!(f, "{{")?;
|
||||
for (absolute, basename, rules) in &self.ignores {
|
||||
writeln!(
|
||||
f,
|
||||
"\t{{ absolute = {absolute:#?}, basename = {basename:#?}, rules = {rules} }},"
|
||||
)?;
|
||||
}
|
||||
write!(f, "}}")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for PerFileIgnores {
|
||||
type Target = Vec<(GlobMatcher, GlobMatcher, RuleSet)>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.ignores
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ use ruff_formatter::printer::{LineEnding, PrinterOptions, SourceMapGeneration};
|
|||
use ruff_formatter::{FormatOptions, IndentStyle, IndentWidth, LineWidth};
|
||||
use ruff_macros::CacheKey;
|
||||
use ruff_python_ast::PySourceType;
|
||||
use std::fmt;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
|
||||
|
@ -241,6 +242,16 @@ pub enum QuoteStyle {
|
|||
Preserve,
|
||||
}
|
||||
|
||||
impl fmt::Display for QuoteStyle {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Single => write!(f, "single"),
|
||||
Self::Double => write!(f, "double"),
|
||||
Self::Preserve => write!(f, "preserve"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for QuoteStyle {
|
||||
type Err = &'static str;
|
||||
|
||||
|
@ -277,6 +288,15 @@ impl MagicTrailingComma {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for MagicTrailingComma {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Respect => write!(f, "respect"),
|
||||
Self::Ignore => write!(f, "ignore"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for MagicTrailingComma {
|
||||
type Err = &'static str;
|
||||
|
||||
|
@ -306,6 +326,15 @@ impl PreviewMode {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PreviewMode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Disabled => write!(f, "disabled"),
|
||||
Self::Enabled => write!(f, "enabled"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default, CacheKey)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
|
||||
|
@ -323,6 +352,15 @@ impl DocstringCode {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for DocstringCode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Disabled => write!(f, "disabled"),
|
||||
Self::Enabled => write!(f, "enabled"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Default, Eq, PartialEq, CacheKey)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
|
||||
|
@ -338,8 +376,8 @@ pub enum DocstringCodeLineWidth {
|
|||
Dynamic,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for DocstringCodeLineWidth {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
impl fmt::Debug for DocstringCodeLineWidth {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
DocstringCodeLineWidth::Fixed(v) => v.value().fmt(f),
|
||||
DocstringCodeLineWidth::Dynamic => "dynamic".fmt(f),
|
||||
|
@ -347,6 +385,15 @@ impl std::fmt::Debug for DocstringCodeLineWidth {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for DocstringCodeLineWidth {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Fixed(width) => width.fmt(f),
|
||||
Self::Dynamic => write!(f, "dynamic"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Responsible for deserializing the `DocstringCodeLineWidth::Dynamic`
|
||||
/// variant.
|
||||
fn deserialize_docstring_code_line_width_dynamic<'de, D>(d: D) -> Result<(), D::Error>
|
||||
|
|
|
@ -25,12 +25,10 @@ use ruff_linter::rule_selector::{PreviewOptions, Specificity};
|
|||
use ruff_linter::rules::pycodestyle;
|
||||
use ruff_linter::settings::rule_table::RuleTable;
|
||||
use ruff_linter::settings::types::{
|
||||
ExtensionMapping, FilePattern, FilePatternSet, PerFileIgnore, PreviewMode, PythonVersion,
|
||||
SerializationFormat, UnsafeFixes, Version,
|
||||
};
|
||||
use ruff_linter::settings::{
|
||||
resolve_per_file_ignores, LinterSettings, DEFAULT_SELECTORS, DUMMY_VARIABLE_RGX, TASK_TAGS,
|
||||
ExtensionMapping, FilePattern, FilePatternSet, PerFileIgnore, PerFileIgnores, PreviewMode,
|
||||
PythonVersion, SerializationFormat, UnsafeFixes, Version,
|
||||
};
|
||||
use ruff_linter::settings::{LinterSettings, DEFAULT_SELECTORS, DUMMY_VARIABLE_RGX, TASK_TAGS};
|
||||
use ruff_linter::{
|
||||
fs, warn_user, warn_user_once, warn_user_once_by_id, RuleSelector, RUFF_PKG_VERSION,
|
||||
};
|
||||
|
@ -260,7 +258,7 @@ impl Configuration {
|
|||
line_length,
|
||||
tab_size: self.indent_width.unwrap_or_default(),
|
||||
namespace_packages: self.namespace_packages.unwrap_or_default(),
|
||||
per_file_ignores: resolve_per_file_ignores(
|
||||
per_file_ignores: PerFileIgnores::resolve(
|
||||
lint.per_file_ignores
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use path_absolutize::path_dedot;
|
||||
use ruff_cache::cache_dir;
|
||||
use ruff_formatter::{FormatOptions, IndentStyle, IndentWidth, LineWidth};
|
||||
use ruff_linter::display_settings;
|
||||
use ruff_linter::settings::types::{
|
||||
ExtensionMapping, FilePattern, FilePatternSet, SerializationFormat, UnsafeFixes,
|
||||
};
|
||||
|
@ -12,6 +13,7 @@ use ruff_python_formatter::{
|
|||
QuoteStyle,
|
||||
};
|
||||
use ruff_source_file::find_newline;
|
||||
use std::fmt;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Debug, CacheKey)]
|
||||
|
@ -55,6 +57,30 @@ impl Default for Settings {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Settings {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "\n# General Settings")?;
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
fields = [
|
||||
// We want the quotes and lossy UTF8 conversion for this path, so
|
||||
// using PathBuf's `Debug` formatter suffices.
|
||||
self.cache_dir | debug,
|
||||
self.fix,
|
||||
self.fix_only,
|
||||
self.output_format,
|
||||
self.show_fixes,
|
||||
self.show_source,
|
||||
self.unsafe_fixes,
|
||||
self.file_resolver | nested,
|
||||
self.linter | nested,
|
||||
self.formatter | nested
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, CacheKey)]
|
||||
pub struct FileResolverSettings {
|
||||
pub exclude: FilePatternSet,
|
||||
|
@ -66,6 +92,26 @@ pub struct FileResolverSettings {
|
|||
pub project_root: PathBuf,
|
||||
}
|
||||
|
||||
impl fmt::Display for FileResolverSettings {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "\n# File Resolver Settings")?;
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "file_resolver",
|
||||
fields = [
|
||||
self.exclude,
|
||||
self.extend_exclude,
|
||||
self.force_exclude,
|
||||
self.include,
|
||||
self.extend_include,
|
||||
self.respect_gitignore,
|
||||
self.project_root | debug,
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) static EXCLUDE: &[FilePattern] = &[
|
||||
FilePattern::Builtin(".bzr"),
|
||||
FilePattern::Builtin(".direnv"),
|
||||
|
@ -195,6 +241,30 @@ impl Default for FormatterSettings {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for FormatterSettings {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "\n# Formatter Settings")?;
|
||||
display_settings! {
|
||||
formatter = f,
|
||||
namespace = "formatter",
|
||||
fields = [
|
||||
self.exclude,
|
||||
self.target_version | debug,
|
||||
self.preview,
|
||||
self.line_width,
|
||||
self.line_ending,
|
||||
self.indent_style,
|
||||
self.indent_width,
|
||||
self.quote_style,
|
||||
self.magic_trailing_comma,
|
||||
self.docstring_code_format,
|
||||
self.docstring_code_line_width,
|
||||
]
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Copy, Clone, Debug, Eq, PartialEq, Default, CacheKey, serde::Serialize, serde::Deserialize,
|
||||
)]
|
||||
|
@ -216,3 +286,14 @@ pub enum LineEnding {
|
|||
/// Line endings will be converted to `\n` on Unix and `\r\n` on Windows.
|
||||
Native,
|
||||
}
|
||||
|
||||
impl fmt::Display for LineEnding {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Auto => write!(f, "auto"),
|
||||
Self::Lf => write!(f, "lf"),
|
||||
Self::CrLf => write!(f, "crlf"),
|
||||
Self::Native => write!(f, "native"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue