Commit Graph

178 Commits

Author SHA1 Message Date
Charlie Marsh
8e1fac620e Add flake8-builtins options to README (#2173) 2023-01-25 15:43:26 -05:00
Florian Best
dc1aa8dd1d Suggest input format in error case (#2167) 2023-01-25 14:55:04 -05:00
Charlie Marsh
38de46ae3c Treat Python 3.7 as minimum supported version (#2159) 2023-01-25 12:36:50 -05:00
Martin Fischer
269926cec4 refactor: Move redirects out of RuleCodePrefix
This commit removes rule redirects such as ("U" -> "UP") from the
RuleCodePrefix enum because they complicated the generation of that enum
(which we want to change to be prefix-agnostic in the future).

To preserve backwards compatibility redirects are now resolved
before the strum-generated RuleCodePrefix::from_str is invoked.

This change also brings two other advantages:

* Redirects are now only defined once
  (previously they had to be defined twice:
  once in ruff_macros/src/rule_code_prefix.rs
  and a second time in src/registry.rs).

* The deprecated redirects will no longer be suggested in IDE
  autocompletion within pyproject.toml since they are now no
  longer part of the ruff.schema.json.
2023-01-24 09:26:19 -05:00
Martin Fischer
28018442f6 refactor: Move ALL from RuleCodePrefix to RuleSelector 2023-01-24 09:26:19 -05:00
Martin Fischer
abc9810e2b refactor: Turn RuleSelector into a newtype around RuleCodePrefix
Yet another refactor to let us implement the many-to-many mapping
between codes and rules in a prefix-agnostic way.

We want to break up the RuleCodePrefix[1] enum into smaller enums.
To facilitate that this commit  introduces a new wrapping type around
RuleCodePrefix so that we can start breaking it apart.

[1]: Actually `RuleCodePrefix` is the previous name of the autogenerated
enum ... I renamed it in b19258a243 to
RuleSelector since `ALL` isn't a prefix. This commit now renames it back
but only because the new `RuleSelector` wrapper type, introduced in this
commit, will let us move the `ALL` variant from `RuleCodePrefix` to
`RuleSelector` in the next commit.
2023-01-24 09:26:19 -05:00
Martin Fischer
ca58c72fc9 refactor: Convention::codes to rules_to_be_ignored 2023-01-24 07:37:34 -05:00
Martin Fischer
c40f14620a refactor: Get rid of registry::CATEGORIES 2023-01-24 07:37:34 -05:00
Martin Fischer
04300ce258 refactor: Rename SuffixLength enum to Specificity 2023-01-24 07:37:34 -05:00
Martin Fischer
ead5f948d3 refactor: Move Colorize imports where they're used 2023-01-24 07:37:34 -05:00
Martin Fischer
3de2a57416 refactor: Use ..Options::default() for tests 2023-01-24 07:37:34 -05:00
Charlie Marsh
cc63a4be6a Allow flagging of multiline implicit string concatenations (#2117)
At present, `ISC001` and `ISC002` flag concatenations like the following:

```py
"a" "b"  # ISC001
"a" \
  "b"  # ISC002
```

However, multiline concatenations are allowed.

This PR adds a setting:

```toml
[tool.ruff.flake8-implicit-str-concat]
allow-multiline = false
```

Which extends `ISC002` to _also_ flag multiline concatenations, like:

```py
(
  "a"  # ISC002
  "b"
)
```

Note that this is backwards compatible, as `allow-multiline` defaults to `true`.
2023-01-24 00:01:01 -05:00
Charlie Marsh
549a5d44bc Upgrade to toml v0.6.0 (#2116)
Closes #1894.
2023-01-23 19:22:42 -05:00
Charlie Marsh
f40ae943a7 Fix bad documentation message for init option 2023-01-22 19:25:23 -05:00
Martin Fischer
87443e6301 Support prefix "PL" to select all of Pylint 2023-01-22 11:51:29 -05:00
Martin Fischer
4f12b31dc8 refactor: Drop RuleSelector::codes in favor of IntoIterator impl 2023-01-22 11:51:29 -05:00
Martin Fischer
9f14e7c830 refactor: Update some variable/field/method names 2023-01-22 11:51:29 -05:00
Martin Fischer
4cc492a17a refactor: Encapsulate PerFileIgnore impl details 2023-01-22 11:51:29 -05:00
Martin Fischer
028436af81 refactor: Group Configuration struct fields 2023-01-22 11:51:29 -05:00
Martin Fischer
da4994aa73 refactor: impl From<&Configuration> for RuleTable 2023-01-22 11:51:29 -05:00
Martin Fischer
4dcb491bec refactor: Avoid some unnecessary allocations 2023-01-22 11:51:29 -05:00
Maksudul Haque
0c30768288 [flake8-builtins] Add builtins-ignorelist Option (#2061)
Closes #2053.
2023-01-21 11:09:04 -05:00
Charlie Marsh
465943adf7 Revert "Upgrade to toml v0.5.11" (#2058)
This _did_ fix https://github.com/charliermarsh/ruff/issues/1894, but was a little premature. `toml` doesn't actually depend on `toml-edit` yet, and `v0.5.11` was mostly about deprecations AFAICT. So upgrading might solve that issue, but could introduce other incompatibilities, and I'd like to minimize churn. I expect that `toml` will have a new release soon, so we can revert this revert.

Reverts charliermarsh/ruff#2040.
2023-01-21 07:54:56 -05:00
Martin Fischer
b19258a243 refactor: Rename RuleCodePrefix to RuleSelector
More accurate since the enum also encompasses:

* ALL (which isn't a prefix at all)

* fully-qualified rule codes (which aren't prefixes unless you say
  they're a prefix to the empty string but that's not intuitive)
2023-01-20 20:25:57 -05:00
Charlie Marsh
20a9252e92 Upgrade to toml v0.5.11 (#2040)
In #1680, we moved over to `toml_edit`. But it looks like `toml` now uses `toml_edit`, and has implemented some improvements (e.g., this closes #1894).
2023-01-20 17:20:45 -05:00
Damien Allen
6ddfe50ac4 Added pylint formatter (#1995)
Fixes: #1953

@charliermarsh thank you for the tips in the issue.

I'm not very familiar with Rust, so please excuse if my string formatting syntax is messy.

In terms of testing, I compared output of `flake8 --format=pylint ` and `cargo run --format=pylint` on the same code and the output syntax seems to check out.
2023-01-19 08:01:27 -05:00
Martin Fischer
6649225167 rule 8/8: Automatically rewrite RuleCode to Rule
# This commit was automatically generated by running the following
# script (followed by `cargo +nightly fmt`):

import glob
import re
from typing import NamedTuple

class Rule(NamedTuple):
    code: str
    name: str
    path: str

def rules() -> list[Rule]:
    """Returns all the rules defined in `src/registry.rs`."""
    file = open('src/registry.rs')

    rules = []

    while next(file) != 'ruff_macros::define_rule_mapping!(\n':
        continue

    while (line := next(file)) != ');\n':
        line = line.strip().rstrip(',')
        if line.startswith('//'):
            continue
        code, path = line.split(' => ')
        name = path.rsplit('::')[-1]
        rules.append(Rule(code, name, path))

    return rules

code2name = {r.code: r.name for r in rules()}

for pattern in ('src/**/*.rs', 'ruff_cli/**/*.rs', 'ruff_dev/**/*.rs', 'scripts/add_*.py'):
    for name in glob.glob(pattern, recursive=True):
        with open(name) as f:
            text = f.read()

        text = re.sub('Rule(?:Code)?::([A-Z]\w+)', lambda m: 'Rule::' + code2name[m.group(1)], text)
        text = re.sub(r'(?<!"<FilePattern>:<)RuleCode\b', 'Rule', text)
        text = re.sub('(use crate::registry::{.*, Rule), Rule(.*)', r'\1\2', text) # fix duplicate import

        with open(name, 'w') as f:
            f.write(text)
2023-01-18 23:51:48 -05:00
Charlie Marsh
d33424ec9d Enable suppression of magic values by type (#1987)
Closes #1949.
2023-01-18 20:44:24 -05:00
Martin Fischer
30e133f3d8 refactor: Declare defaults once in settings::defaults 2023-01-17 09:20:57 -05:00
Martin Fischer
aa812de07e refactor: Implement Default for Settings 2023-01-17 09:20:57 -05:00
Martin Fischer
57ac6a8444 refactor: Make resolve_codes take IntoIterator instead of Iterator 2023-01-17 09:20:57 -05:00
Martin Fischer
a6566b1b34 refactor: Merge Settings.enabled and Settings.fixable
The Settings struct previously contained the fields:

     pub enabled: HashableHashSet<RuleCode>,
     pub fixable: HashableHashSet<RuleCode>,

This commit merges both fields into one by introducing a new
RuleTable type, wrapping HashableHashMap<RuleCode, bool>,
which has the following benefits:

1. It makes the invalid state that a rule is
   disabled but fixable unrepresentable.

2. It encapsulates the implementation details of the table.
   (It currently uses an FxHashMap but that may change.)

3. It results in more readable code.

       settings.rules.enabled(rule)
       settings.rules.should_fix(rule)

   is more readable than:

       settings.enabled.contains(rule)
       settings.fixable.contains(rule)
2023-01-17 09:20:57 -05:00
Martin Fischer
580da1fa6b refactor: Group Settings fields 2023-01-17 09:20:57 -05:00
Martin Fischer
2fce580693 refactor: Move flake8_tidy_imports Settings to mod.rs 2023-01-16 11:27:24 -05:00
Martin Fischer
8862565a0f refactor: Split ruff::rules::flake8_tidy_imports::rules 2023-01-16 11:27:24 -05:00
Martin Fischer
ee655c1a88 refactor: Rename BannedApi to ApiBan to distinguish it from the violation struct 2023-01-16 11:27:24 -05:00
Martin Fischer
8c18b28bc4 Derive Hash instead of implementing it by hand
The caching mechanism of the CLI (ruff_cli::cache) relies on
ruff::settings::Settings implementing the Hash trait.

The ruff::settings::Settings struct previously couldn't automatically
derive the Hash implementation via the #[derive(Hash)] macro attribute
since some of its field types intentionally[1][2] don't implement Hash
(namely regex::Regex, globset::GlobMatcher and globset::GlobSet and
HashMap and HashSet from the standard library).

The code therefore previously implemented the Hash trait by hand for the
whole struct. Implementing Hash by hand for structs that are subject to
change is a bad idea since it's very easy to forget to update the Hash
implementation when adding a new field to the struct. And the Hash
implementation indeed was already incorrect by omitting several fields
from the hash.

This commit introduces wrapper types for Regex, GlobMatcher, GlobSet,
HashSet & HashMap that implement Hash so that we can still add
#[derive(Hash)] to the Settings struct, guaranteeing a correct hash
implementation.

[1]: https://github.com/rust-lang/regex/issues/364#issuecomment-301082076
[2]: The standard library doesn't impl<T: Hash + Ord> Hash for HashSet<T>
     presumably since sorted() requires an allocation and Hash
     implementations are generally expected to work without allocations.
2023-01-16 01:42:55 -05:00
Martin Fischer
d75d6d7c7c refactor: Split CliSettings from Settings
We want to automatically derive Hash for the library settings, which
requires us to split off all the settings unused by the library
(since these shouldn't affect the hash used by ruff_cli::cache).
2023-01-15 15:19:42 -05:00
Martin Fischer
ef80ab205c Mark Settings::for_rule(s) as test-only 2023-01-15 15:19:42 -05:00
Charlie Marsh
5c6753e69e Remove some Clippy allows (#1888) 2023-01-15 02:32:36 -05:00
Charlie Marsh
a01edad1c4 Remove --max-complexity from the CLI (#1877) 2023-01-14 18:27:23 -05:00
Martin Fischer
cfa25ea4b0 Make ruff::rules private 2023-01-14 18:23:59 -05:00
Martin Fischer
3b36030461 Introduce ruff::rules module
Resolves #1547.
2023-01-14 11:48:02 -05:00
Charlie Marsh
027382f891 Add support for namespace packages (#1859)
Closes #1817.
2023-01-14 07:31:57 -05:00
Martin Fischer
82aff5f9ec Split off ruff_cli crate from ruff library
This lets you test the ruff linters or use the ruff library
without having to compile the ~100 additional dependencies
that are needed by the CLI.

Because we set the following in the [workspace] section of Cargo.toml:

   default-members = [".", "ruff_cli"]

`cargo run` still runs the CLI and `cargo test` still tests
the code in src/ as well as the code in the new ruff_cli crate.
(But you can now also run `cargo test -p ruff` to only test the linters.)
2023-01-13 21:37:54 -05:00
Jan Katins
ef17c82998 Document the way extend-ignore/select are applied (#1839)
Closes: https://github.com/charliermarsh/ruff/issues/1838
2023-01-12 19:44:03 -05:00
Martin Fischer
74f14182ea Decouple resolver module from cli::Overrides 2023-01-12 13:09:59 -05:00
Charlie Marsh
b36d4a15b0 Modify visibility and shuffle around some modules (#1807) 2023-01-11 23:57:05 -05:00
Charlie Marsh
e11ef54bda Improve globset documentation and help message (#1808)
Closes #1545.
2023-01-11 23:41:56 -05:00
Charlie Marsh
f450e2e79d Implement doc line length enforcement (#1804)
This PR implements `W505` (`DocLineTooLong`), which is similar to `E501`
(`LineTooLong`) but confined to doc lines.

I based the "doc line" definition on pycodestyle, which defines a doc
line as a standalone comment or string statement. Our definition is a
bit more liberal, since we consider any string statement a doc line
(even if it's part of a multi-line statement) -- but that seems fine to
me.

Note that, unusually, this rule requires custom extraction from both the
token stream (to find standalone comments) and the AST (to find string
statements).

Closes #1784.
2023-01-11 22:32:14 -05:00