Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc2110449c | ||
|
|
f6ca49e05f | ||
|
|
9a7331b2e2 | ||
|
|
4888afd423 | ||
|
|
0dc523b081 | ||
|
|
63772e335d | ||
|
|
7f4ff1e38f | ||
|
|
32ebc1d227 | ||
|
|
4ded155dc0 | ||
|
|
201e1250de | ||
|
|
102b049a32 | ||
|
|
74f49eda64 | ||
|
|
9da3e2cca1 | ||
|
|
e290050821 | ||
|
|
bc9ed0a4ef | ||
|
|
20b9b44973 | ||
|
|
6e5a553235 | ||
|
|
2a08a63f17 | ||
|
|
d4290e6721 |
5
.github/workflows/ci.yaml
vendored
5
.github/workflows/ci.yaml
vendored
@@ -42,6 +42,9 @@ jobs:
|
||||
- run: ./target/release/ruff_dev generate-check-code-prefix
|
||||
- run: git diff --quiet src/checks_gen.rs || echo "::error file=src/checks_gen.rs::This file is outdated. You may have to rerun 'cargo dev generate-check-code-prefix'."
|
||||
- run: git diff --exit-code -- README.md src/checks_gen.rs
|
||||
- run: ./target/release/ruff_dev generate-json-schema
|
||||
- run: git diff --quiet ruff.schema.json || echo "::error file=ruff.schema.json::This file is outdated. You may have to rerun 'cargo dev generate-json-schema'."
|
||||
- run: git diff --exit-code -- ruff.schema.json
|
||||
|
||||
cargo_fmt:
|
||||
name: "cargo fmt"
|
||||
@@ -131,7 +134,7 @@ jobs:
|
||||
override: true
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.10"
|
||||
python-version: "3.11"
|
||||
- run: pip install maturin
|
||||
- uses: actions/cache@v3
|
||||
env:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
repos:
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.0.192
|
||||
rev: v0.0.193
|
||||
hooks:
|
||||
- id: ruff
|
||||
|
||||
|
||||
@@ -48,8 +48,8 @@ prior to merging.
|
||||
There are four phases to adding a new lint rule:
|
||||
|
||||
1. Define the rule in `src/checks.rs`.
|
||||
2. Define the _logic_ for triggering the rule in `src/check_ast.rs` (for AST-based checks),
|
||||
`src/check_tokens.rs` (for token-based checks), or `src/check_lines.rs` (for text-based checks).
|
||||
2. Define the _logic_ for triggering the rule in `src/checkers/ast.rs` (for AST-based checks),
|
||||
`src/checkers/tokens.rs` (for token-based checks), or `src/checkers/lines.rs` (for text-based checks).
|
||||
3. Add a test fixture.
|
||||
4. Update the generated files (documentation and generated code).
|
||||
|
||||
@@ -105,7 +105,8 @@ You may also want to add the new configuration option to the `flake8-to-ruff` to
|
||||
responsible for converting `flake8` configuration files to Ruff's TOML format. This logic
|
||||
lives in `flake8_to_ruff/src/converter.rs`.
|
||||
|
||||
To update the documentation for supported configuration options, run `cargo dev generate-options`.
|
||||
Run `cargo dev generate-options` to update the documentation for supported configuration options,
|
||||
and `cargo dev generate-json-schema` to update the JSON schema for `tool.ruff` in `pyproject.toml`.
|
||||
|
||||
## Release process
|
||||
|
||||
|
||||
66
Cargo.lock
generated
66
Cargo.lock
generated
@@ -644,6 +644,12 @@ version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||
|
||||
[[package]]
|
||||
name = "dyn-clone"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9b0705efd4599c15a38151f4721f7bc388306f61084d3bfd50bd07fbca5cb60"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.0"
|
||||
@@ -724,7 +730,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.192-dev.0"
|
||||
version = "0.0.193-dev.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.0.29",
|
||||
@@ -1847,7 +1853,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.192"
|
||||
version = "0.0.193"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.9.1",
|
||||
"anyhow",
|
||||
@@ -1888,6 +1894,7 @@ dependencies = [
|
||||
"rustpython-ast",
|
||||
"rustpython-common",
|
||||
"rustpython-parser",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"shellexpand",
|
||||
@@ -1904,7 +1911,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_dev"
|
||||
version = "0.0.192"
|
||||
version = "0.0.193"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.0.29",
|
||||
@@ -1916,13 +1923,15 @@ dependencies = [
|
||||
"rustpython-ast",
|
||||
"rustpython-common",
|
||||
"rustpython-parser",
|
||||
"schemars",
|
||||
"serde_json",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_macros"
|
||||
version = "0.0.192"
|
||||
version = "0.0.193"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1965,7 +1974,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-ast"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c01f014b1269eedcf4bdb45d5fbc62ae2beecf31#c01f014b1269eedcf4bdb45d5fbc62ae2beecf31"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"rustpython-common",
|
||||
@@ -1975,7 +1984,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-common"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c01f014b1269eedcf4bdb45d5fbc62ae2beecf31#c01f014b1269eedcf4bdb45d5fbc62ae2beecf31"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
|
||||
dependencies = [
|
||||
"ascii",
|
||||
"cfg-if 1.0.0",
|
||||
@@ -1998,7 +2007,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-compiler-core"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c01f014b1269eedcf4bdb45d5fbc62ae2beecf31#c01f014b1269eedcf4bdb45d5fbc62ae2beecf31"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitflags",
|
||||
@@ -2015,7 +2024,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-parser"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c01f014b1269eedcf4bdb45d5fbc62ae2beecf31#c01f014b1269eedcf4bdb45d5fbc62ae2beecf31"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
@@ -2058,6 +2067,30 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schemars"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a5fb6c61f29e723026dc8e923d94c694313212abbecbbe5f55a7748eec5b307"
|
||||
dependencies = [
|
||||
"dyn-clone",
|
||||
"schemars_derive",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "schemars_derive"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f188d036977451159430f3b8dc82ec76364a42b7e289c2b18a9a18f4470058e9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde_derive_internals",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
@@ -2107,10 +2140,21 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.89"
|
||||
name = "serde_derive_internals"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db"
|
||||
checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
|
||||
11
Cargo.toml
11
Cargo.toml
@@ -6,7 +6,7 @@ members = [
|
||||
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.192"
|
||||
version = "0.0.193"
|
||||
edition = "2021"
|
||||
rust-version = "1.65.0"
|
||||
|
||||
@@ -43,11 +43,12 @@ quick-junit = { version = "0.3.2" }
|
||||
rayon = { version = "1.5.3" }
|
||||
regex = { version = "1.6.0" }
|
||||
ropey = { version = "1.5.0", features = ["cr_lines", "simd"], default-features = false }
|
||||
ruff_macros = { version = "0.0.192", path = "ruff_macros" }
|
||||
ruff_macros = { version = "0.0.193", path = "ruff_macros" }
|
||||
rustc-hash = { version = "1.1.0" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "c01f014b1269eedcf4bdb45d5fbc62ae2beecf31" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "c01f014b1269eedcf4bdb45d5fbc62ae2beecf31" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "c01f014b1269eedcf4bdb45d5fbc62ae2beecf31" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "1b6cb170e925a43d605b3fed9f6b878e63e47744" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "1b6cb170e925a43d605b3fed9f6b878e63e47744" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "1b6cb170e925a43d605b3fed9f6b878e63e47744" }
|
||||
schemars = { version = "0.8.11" }
|
||||
serde = { version = "1.0.147", features = ["derive"] }
|
||||
serde_json = { version = "1.0.87" }
|
||||
shellexpand = { version = "3.0.0" }
|
||||
|
||||
333
README.md
333
README.md
@@ -17,7 +17,7 @@ An extremely fast Python linter, written in Rust.
|
||||
|
||||
- ⚡️ 10-100x faster than existing linters
|
||||
- 🐍 Installable via `pip`
|
||||
- 🤝 Python 3.10 compatibility
|
||||
- 🤝 Python 3.11 compatibility
|
||||
- 🛠️ `pyproject.toml` support
|
||||
- 📦 Built-in caching, to avoid re-analyzing unchanged files
|
||||
- 🔧 Autofix support, for automatic error correction (e.g., automatically remove unused imports)
|
||||
@@ -162,7 +162,7 @@ Ruff also works with [pre-commit](https://pre-commit.com):
|
||||
```yaml
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: 'v0.0.192'
|
||||
rev: 'v0.0.193'
|
||||
hooks:
|
||||
- id: ruff
|
||||
# Respect `exclude` and `extend-exclude` settings.
|
||||
@@ -318,6 +318,8 @@ Options:
|
||||
Show violations with source code
|
||||
--respect-gitignore
|
||||
Respect file exclusions via `.gitignore` and other standard ignore files
|
||||
--force-exclude
|
||||
Enforce exclusions, even for paths passed to Ruff directly on the command-line
|
||||
--show-files
|
||||
See the files Ruff will be run against with the current settings
|
||||
--show-settings
|
||||
@@ -336,6 +338,8 @@ Options:
|
||||
The name of the file when passing it through stdin
|
||||
--explain <EXPLAIN>
|
||||
Explain a rule
|
||||
--cache-dir <CACHE_DIR>
|
||||
Path to the cache directory
|
||||
-h, --help
|
||||
Print help information
|
||||
-V, --version
|
||||
@@ -536,8 +540,8 @@ For more, see [pycodestyle](https://pypi.org/project/pycodestyle/2.9.1/) on PyPI
|
||||
| E743 | AmbiguousFunctionName | Ambiguous function name: `...` | |
|
||||
| E902 | IOError | IOError: `...` | |
|
||||
| E999 | SyntaxError | SyntaxError: `...` | |
|
||||
| W292 | NoNewLineAtEndOfFile | No newline at end of file | |
|
||||
| W605 | InvalidEscapeSequence | Invalid escape sequence: '\c' | |
|
||||
| W292 | NoNewLineAtEndOfFile | No newline at end of file | 🛠 |
|
||||
| W605 | InvalidEscapeSequence | Invalid escape sequence: '\c' | 🛠 |
|
||||
|
||||
### mccabe (C90)
|
||||
|
||||
@@ -629,6 +633,7 @@ For more, see [pyupgrade](https://pypi.org/project/pyupgrade/3.2.0/) on PyPI.
|
||||
| UP015 | RedundantOpenModes | Unnecessary open mode parameters | 🛠 |
|
||||
| UP016 | RemoveSixCompat | Unnecessary `six` compatibility usage | 🛠 |
|
||||
| UP017 | DatetimeTimezoneUTC | Use `datetime.UTC` alias | 🛠 |
|
||||
| UP018 | NativeLiterals | Unnecessary call to `str` and `bytes` | 🛠 |
|
||||
|
||||
### pep8-naming (N)
|
||||
|
||||
@@ -952,7 +957,7 @@ For more, see [Pylint](https://pypi.org/project/pylint/2.15.7/) on PyPI.
|
||||
| RUF001 | AmbiguousUnicodeCharacterString | String contains ambiguous unicode character '𝐁' (did you mean 'B'?) | 🛠 |
|
||||
| RUF002 | AmbiguousUnicodeCharacterDocstring | Docstring contains ambiguous unicode character '𝐁' (did you mean 'B'?) | 🛠 |
|
||||
| RUF003 | AmbiguousUnicodeCharacterComment | Comment contains ambiguous unicode character '𝐁' (did you mean 'B'?) | |
|
||||
| RUF100 | UnusedNOQA | Unused `noqa` directive | 🛠 |
|
||||
| RUF100 | UnusedNOQA | Unused blanket `noqa` directive | 🛠 |
|
||||
|
||||
<!-- End auto-generated sections. -->
|
||||
|
||||
@@ -1018,19 +1023,17 @@ local configs = require 'lspconfig.configs'
|
||||
if not configs.ruff_lsp then
|
||||
configs.ruff_lsp = {
|
||||
default_config = {
|
||||
cmd = { "ruff-lsp" },
|
||||
filetypes = {'python'},
|
||||
root_dir = require('lspconfig').util.find_git_ancestor,
|
||||
settings = {
|
||||
ruff_lsp = {
|
||||
-- Any extra CLI arguments for `ruff` go here.
|
||||
args = {}
|
||||
cmd = { 'ruff-lsp' },
|
||||
filetypes = { 'python' },
|
||||
root_dir = require('lspconfig').util.find_git_ancestor,
|
||||
init_options = {
|
||||
settings = {
|
||||
args = {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
require('lspconfig').ruff_lsp.setup {
|
||||
on_attach = on_attach,
|
||||
}
|
||||
@@ -1040,6 +1043,8 @@ Upon successful installation, you should see Ruff's diagnostics surfaced directl
|
||||
|
||||

|
||||
|
||||
To use `ruff-lsp` with other editors, including Sublime Text and Helix, see the [`ruff-lsp` documentation](https://github.com/charliermarsh/ruff-lsp#installation-and-usage).
|
||||
|
||||
### Language Server Protocol (Unofficial)
|
||||
|
||||
Ruff is also available as the [`python-lsp-ruff`](https://github.com/python-lsp/python-lsp-ruff)
|
||||
@@ -1078,24 +1083,15 @@ require'lspconfig'.pylsp.setup {
|
||||
}
|
||||
```
|
||||
|
||||
### PyCharm
|
||||
|
||||
Ruff can be installed as an [External Tool](https://www.jetbrains.com/help/pycharm/configuring-third-party-tools.html)
|
||||
in PyCharm. Open the Preferences pane, then navigate to "Tools", then "External Tools". From there,
|
||||
add a new tool with the following configuration:
|
||||
|
||||

|
||||
|
||||
Ruff should then appear as a runnable action:
|
||||
|
||||

|
||||
|
||||
### Vim & Neovim
|
||||
|
||||
Ruff can be integrated into any editor that supports the Language Server Protocol via [`ruff-lsp`](https://github.com/charliermarsh/ruff-lsp)
|
||||
(see: [Language Server Protocol](#language-server-protocol-official)).
|
||||
(see: [Language Server Protocol](#language-server-protocol-official)), including Vim and Neovim.
|
||||
|
||||
Ruff is also available as part of the [coc-pyright](https://github.com/fannheyward/coc-pyright)
|
||||
It's recommended that you use [`ruff-lsp`](https://github.com/charliermarsh/ruff-lsp), the
|
||||
officially supported LSP server for Ruff.
|
||||
|
||||
However, Ruff is also available as part of the [coc-pyright](https://github.com/fannheyward/coc-pyright)
|
||||
extension for `coc.nvim`.
|
||||
|
||||
<details>
|
||||
@@ -1112,7 +1108,6 @@ tools:
|
||||
format-command: 'ruff --stdin-filename ${INPUT} --config ~/myconfigs/linters/ruff.toml --fix --exit-zero --quiet -'
|
||||
format-stdin: true
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
@@ -1149,9 +1144,26 @@ null_ls.setup({
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
### PyCharm (External Tool)
|
||||
|
||||
Ruff can be installed as an [External Tool](https://www.jetbrains.com/help/pycharm/configuring-third-party-tools.html)
|
||||
in PyCharm. Open the Preferences pane, then navigate to "Tools", then "External Tools". From there,
|
||||
add a new tool with the following configuration:
|
||||
|
||||

|
||||
|
||||
Ruff should then appear as a runnable action:
|
||||
|
||||

|
||||
|
||||
### PyCharm (Unofficial)
|
||||
|
||||
Ruff is also available as the [Ruff](https://plugins.jetbrains.com/plugin/20574-ruff) plugin on the
|
||||
IntelliJ Marketplace (maintained by @koxudaxi).
|
||||
|
||||
### GitHub Actions
|
||||
|
||||
GitHub Actions has everything you need to run Ruff out-of-the-box:
|
||||
@@ -1167,7 +1179,7 @@ jobs:
|
||||
- name: Install Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.10"
|
||||
python-version: "3.11"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
@@ -1225,7 +1237,7 @@ natively, including:
|
||||
- [`pep8-naming`](https://pypi.org/project/pep8-naming/)
|
||||
- [`pydocstyle`](https://pypi.org/project/pydocstyle/)
|
||||
- [`pygrep-hooks`](https://github.com/pre-commit/pygrep-hooks) (3/10)
|
||||
- [`pyupgrade`](https://pypi.org/project/pyupgrade/) (17/33)
|
||||
- [`pyupgrade`](https://pypi.org/project/pyupgrade/) (18/33)
|
||||
- [`yesqa`](https://github.com/asottile/yesqa)
|
||||
|
||||
Note that, in some cases, Ruff uses different error code prefixes than would be found in the
|
||||
@@ -1569,8 +1581,8 @@ Summary
|
||||
|
||||
#### [`allowed-confusables`](#allowed-confusables)
|
||||
|
||||
A list of allowed "confusable" Unicode characters to ignore when enforcing `RUF001`,
|
||||
`RUF002`, and `RUF003`.
|
||||
A list of allowed "confusable" Unicode characters to ignore when
|
||||
enforcing `RUF001`, `RUF002`, and `RUF003`.
|
||||
|
||||
**Default value**: `[]`
|
||||
|
||||
@@ -1587,11 +1599,37 @@ allowed-confusables = ["−", "ρ", "∗"]
|
||||
|
||||
---
|
||||
|
||||
#### [`cache-dir`](#cache-dir)
|
||||
|
||||
A path to the cache directory.
|
||||
|
||||
By default, Ruff stores cache results in a `.ruff_cache` directory in
|
||||
the current project root.
|
||||
|
||||
However, Ruff will also respect the `RUFF_CACHE_DIR` environment
|
||||
variable, which takes precedence over that default.
|
||||
|
||||
This setting will override even the `RUFF_CACHE_DIR` environment
|
||||
variable, if set.
|
||||
|
||||
**Default value**: `.ruff_cache`
|
||||
|
||||
**Type**: `PathBuf`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
cache-dir = "~/.cache/ruff"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`dummy-variable-rgx`](#dummy-variable-rgx)
|
||||
|
||||
A regular expression used to identify "dummy" variables, or those which should be
|
||||
ignored when evaluating (e.g.) unused-variable checks. The default expression matches
|
||||
`_`, `__`, and `_var`, but not `_var_`.
|
||||
A regular expression used to identify "dummy" variables, or those which
|
||||
should be ignored when evaluating (e.g.) unused-variable checks. The
|
||||
default expression matches `_`, `__`, and `_var`, but not `_var_`.
|
||||
|
||||
**Default value**: `"^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"`
|
||||
|
||||
@@ -1613,15 +1651,16 @@ A list of file patterns to exclude from linting.
|
||||
|
||||
Exclusions are based on globs, and can be either:
|
||||
|
||||
- Single-path patterns, like `.mypy_cache` (to exclude any directory named `.mypy_cache` in the
|
||||
tree), `foo.py` (to exclude any file named `foo.py`), or `foo_*.py` (to exclude any file matching
|
||||
`foo_*.py` ).
|
||||
- Relative patterns, like `directory/foo.py` (to exclude that specific file) or `directory/*.py`
|
||||
(to exclude any Python files in `directory`). Note that these paths are relative to the
|
||||
project root (e.g., the directory containing your `pyproject.toml`).
|
||||
- Single-path patterns, like `.mypy_cache` (to exclude any directory
|
||||
named `.mypy_cache` in the tree), `foo.py` (to exclude any file named
|
||||
`foo.py`), or `foo_*.py` (to exclude any file matching `foo_*.py` ).
|
||||
- Relative patterns, like `directory/foo.py` (to exclude that specific
|
||||
file) or `directory/*.py` (to exclude any Python files in
|
||||
`directory`). Note that these paths are relative to the project root
|
||||
(e.g., the directory containing your `pyproject.toml`).
|
||||
|
||||
Note that you'll typically want to use [`extend-exclude`](#extend-exclude) to modify
|
||||
the excluded paths.
|
||||
Note that you'll typically want to use
|
||||
[`extend-exclude`](#extend-exclude) to modify the excluded paths.
|
||||
|
||||
**Default value**: `[".bzr", ".direnv", ".eggs", ".git", ".hg", ".mypy_cache", ".nox", ".pants.d", ".ruff_cache", ".svn", ".tox", ".venv", "__pypackages__", "_build", "buck-out", "build", "dist", "node_modules", "venv"]`
|
||||
|
||||
@@ -1638,12 +1677,13 @@ exclude = [".venv"]
|
||||
|
||||
#### [`extend`](#extend)
|
||||
|
||||
A path to a local `pyproject.toml` file to merge into this configuration. User home
|
||||
directory and environment variables will be expanded.
|
||||
A path to a local `pyproject.toml` file to merge into this
|
||||
configuration. User home directory and environment variables will be
|
||||
expanded.
|
||||
|
||||
To resolve the current `pyproject.toml` file, Ruff will first resolve this base
|
||||
configuration file, then merge in any properties defined in the current configuration
|
||||
file.
|
||||
To resolve the current `pyproject.toml` file, Ruff will first resolve
|
||||
this base configuration file, then merge in any properties defined
|
||||
in the current configuration file.
|
||||
|
||||
**Default value**: `None`
|
||||
|
||||
@@ -1663,7 +1703,8 @@ line-length = 100
|
||||
|
||||
#### [`extend-exclude`](#extend-exclude)
|
||||
|
||||
A list of file patterns to omit from linting, in addition to those specified by `exclude`.
|
||||
A list of file patterns to omit from linting, in addition to those
|
||||
specified by `exclude`.
|
||||
|
||||
**Default value**: `[]`
|
||||
|
||||
@@ -1681,7 +1722,8 @@ extend-exclude = ["tests", "src/bad.py"]
|
||||
|
||||
#### [`extend-ignore`](#extend-ignore)
|
||||
|
||||
A list of check code prefixes to ignore, in addition to those specified by `ignore`.
|
||||
A list of check code prefixes to ignore, in addition to those specified
|
||||
by `ignore`.
|
||||
|
||||
**Default value**: `[]`
|
||||
|
||||
@@ -1699,7 +1741,8 @@ extend-ignore = ["F841"]
|
||||
|
||||
#### [`extend-select`](#extend-select)
|
||||
|
||||
A list of check code prefixes to enable, in addition to those specified by `select`.
|
||||
A list of check code prefixes to enable, in addition to those specified
|
||||
by `select`.
|
||||
|
||||
**Default value**: `[]`
|
||||
|
||||
@@ -1717,9 +1760,10 @@ extend-select = ["B", "Q"]
|
||||
|
||||
#### [`external`](#external)
|
||||
|
||||
A list of check codes that are unsupported by Ruff, but should be preserved when (e.g.)
|
||||
validating `# noqa` directives. Useful for retaining `# noqa` directives that cover plugins not
|
||||
yet implemented in Ruff.
|
||||
A list of check codes that are unsupported by Ruff, but should be
|
||||
preserved when (e.g.) validating `# noqa` directives. Useful for
|
||||
retaining `# noqa` directives that cover plugins not yet implemented
|
||||
in Ruff.
|
||||
|
||||
**Default value**: `[]`
|
||||
|
||||
@@ -1774,14 +1818,16 @@ fixable = ["E", "F"]
|
||||
|
||||
#### [`force-exclude`](#force-exclude)
|
||||
|
||||
Whether to enforce `exclude` and `extend-exclude` patterns, even for paths that are
|
||||
passed to Ruff explicitly. Typically, Ruff will lint any paths passed in directly, even
|
||||
if they would typically be excluded. Setting `force-exclude = true` will cause Ruff to
|
||||
Whether to enforce `exclude` and `extend-exclude` patterns, even for
|
||||
paths that are passed to Ruff explicitly. Typically, Ruff will lint
|
||||
any paths passed in directly, even if they would typically be
|
||||
excluded. Setting `force-exclude = true` will cause Ruff to
|
||||
respect these exclusions unequivocally.
|
||||
|
||||
This is useful for [`pre-commit`](https://pre-commit.com/), which explicitly passes all
|
||||
changed files to the [`ruff-pre-commit`](https://github.com/charliermarsh/ruff-pre-commit)
|
||||
plugin, regardless of whether they're marked as excluded by Ruff's own settings.
|
||||
plugin, regardless of whether they're marked as excluded by Ruff's own
|
||||
settings.
|
||||
|
||||
**Default value**: `false`
|
||||
|
||||
@@ -1798,9 +1844,10 @@ force-exclude = true
|
||||
|
||||
#### [`format`](#format)
|
||||
|
||||
The style in which violation messages should be formatted: `"text"` (default),
|
||||
`"grouped"` (group messages by file), `"json"` (machine-readable), `"junit"`
|
||||
(machine-readable XML), or `"github"` (GitHub Actions annotations).
|
||||
The style in which violation messages should be formatted: `"text"`
|
||||
(default), `"grouped"` (group messages by file), `"json"`
|
||||
(machine-readable), `"junit"` (machine-readable XML), or `"github"`
|
||||
(GitHub Actions annotations).
|
||||
|
||||
**Default value**: `"text"`
|
||||
|
||||
@@ -1818,11 +1865,13 @@ format = "grouped"
|
||||
|
||||
#### [`ignore`](#ignore)
|
||||
|
||||
A list of check code prefixes to ignore. Prefixes can specify exact checks (like
|
||||
`F841`), entire categories (like `F`), or anything in between.
|
||||
A list of check code prefixes to ignore. Prefixes can specify exact
|
||||
checks (like `F841`), entire categories (like `F`), or anything in
|
||||
between.
|
||||
|
||||
When breaking ties between enabled and disabled checks (via `select` and `ignore`,
|
||||
respectively), more specific prefixes override less specific prefixes.
|
||||
When breaking ties between enabled and disabled checks (via `select` and
|
||||
`ignore`, respectively), more specific prefixes override less
|
||||
specific prefixes.
|
||||
|
||||
**Default value**: `[]`
|
||||
|
||||
@@ -1840,10 +1889,11 @@ ignore = ["F841"]
|
||||
|
||||
#### [`ignore-init-module-imports`](#ignore-init-module-imports)
|
||||
|
||||
Avoid automatically removing unused imports in `__init__.py` files. Such imports will
|
||||
still be +flagged, but with a dedicated message suggesting that the import is either
|
||||
added to the module' +`__all__` symbol, or re-exported with a redundant alias (e.g.,
|
||||
`import os as os`).
|
||||
Avoid automatically removing unused imports in `__init__.py` files. Such
|
||||
imports will still be +flagged, but with a dedicated message
|
||||
suggesting that the import is either added to the module' +`__all__`
|
||||
symbol, or re-exported with a redundant alias (e.g., `import os as
|
||||
os`).
|
||||
|
||||
**Default value**: `false`
|
||||
|
||||
@@ -1860,7 +1910,8 @@ ignore-init-module-imports = true
|
||||
|
||||
#### [`line-length`](#line-length)
|
||||
|
||||
The line length to use when enforcing long-lines violations (like E501).
|
||||
The line length to use when enforcing long-lines violations (like
|
||||
`E501`).
|
||||
|
||||
**Default value**: `88`
|
||||
|
||||
@@ -1878,8 +1929,8 @@ line-length = 120
|
||||
|
||||
#### [`per-file-ignores`](#per-file-ignores)
|
||||
|
||||
A list of mappings from file pattern to check code prefixes to exclude, when considering
|
||||
any matching files.
|
||||
A list of mappings from file pattern to check code prefixes to exclude,
|
||||
when considering any matching files.
|
||||
|
||||
**Default value**: `{}`
|
||||
|
||||
@@ -1899,8 +1950,9 @@ any matching files.
|
||||
|
||||
#### [`respect-gitignore`](#respect-gitignore)
|
||||
|
||||
Whether to automatically exclude files that are ignored by `.ignore`, `.gitignore`,
|
||||
`.git/info/exclude`, and global `gitignore` files. Enabled by default.
|
||||
Whether to automatically exclude files that are ignored by `.ignore`,
|
||||
`.gitignore`, `.git/info/exclude`, and global `gitignore` files.
|
||||
Enabled by default.
|
||||
|
||||
**Default value**: `true`
|
||||
|
||||
@@ -1917,11 +1969,13 @@ respect_gitignore = false
|
||||
|
||||
#### [`select`](#select)
|
||||
|
||||
A list of check code prefixes to enable. Prefixes can specify exact checks (like
|
||||
`F841`), entire categories (like `F`), or anything in between.
|
||||
A list of check code prefixes to enable. Prefixes can specify exact
|
||||
checks (like `F841`), entire categories (like `F`), or anything in
|
||||
between.
|
||||
|
||||
When breaking ties between enabled and disabled checks (via `select` and `ignore`,
|
||||
respectively), more specific prefixes override less specific prefixes.
|
||||
When breaking ties between enabled and disabled checks (via `select` and
|
||||
`ignore`, respectively), more specific prefixes override less
|
||||
specific prefixes.
|
||||
|
||||
**Default value**: `["E", "F"]`
|
||||
|
||||
@@ -1939,8 +1993,8 @@ select = ["E", "F", "B", "Q"]
|
||||
|
||||
#### [`show-source`](#show-source)
|
||||
|
||||
Whether to show source code snippets when reporting lint error violations (overridden by
|
||||
the `--show-source` command-line flag).
|
||||
Whether to show source code snippets when reporting lint error
|
||||
violations (overridden by the `--show-source` command-line flag).
|
||||
|
||||
**Default value**: `false`
|
||||
|
||||
@@ -1958,7 +2012,8 @@ show-source = true
|
||||
|
||||
#### [`src`](#src)
|
||||
|
||||
The source code paths to consider, e.g., when resolving first- vs. third-party imports.
|
||||
The source code paths to consider, e.g., when resolving first- vs.
|
||||
third-party imports.
|
||||
|
||||
As an example: given a Python package structure like:
|
||||
|
||||
@@ -1972,13 +2027,15 @@ my_package/
|
||||
bar.py
|
||||
```
|
||||
|
||||
The `src` directory should be included in `source` (e.g., `source = ["src"]`), such that
|
||||
when resolving imports, `my_package.foo` is considered a first-party import.
|
||||
The `src` directory should be included in `source` (e.g., `source =
|
||||
["src"]`), such that when resolving imports, `my_package.foo` is
|
||||
considered a first-party import.
|
||||
|
||||
This field supports globs. For example, if you have a series of Python packages in
|
||||
a `python_modules` directory, `src = ["python_modules/*"]` would expand to incorporate
|
||||
all of the packages in that directory. User home directory and environment variables
|
||||
will also be expanded.
|
||||
This field supports globs. For example, if you have a series of Python
|
||||
packages in a `python_modules` directory, `src =
|
||||
["python_modules/*"]` would expand to incorporate all of the
|
||||
packages in that directory. User home directory and environment
|
||||
variables will also be expanded.
|
||||
|
||||
**Default value**: `["."]`
|
||||
|
||||
@@ -1996,9 +2053,10 @@ src = ["src", "test"]
|
||||
|
||||
#### [`target-version`](#target-version)
|
||||
|
||||
The Python version to target, e.g., when considering automatic code upgrades, like
|
||||
rewriting type annotations. Note that the target version will _not_ be inferred from the
|
||||
_current_ Python version, and instead must be specified explicitly (as seen below).
|
||||
The Python version to target, e.g., when considering automatic code
|
||||
upgrades, like rewriting type annotations. Note that the target
|
||||
version will _not_ be inferred from the _current_ Python version,
|
||||
and instead must be specified explicitly (as seen below).
|
||||
|
||||
**Default value**: `"py310"`
|
||||
|
||||
@@ -2036,7 +2094,8 @@ unfixable = ["F401"]
|
||||
|
||||
#### [`allow-star-arg-any`](#allow-star-arg-any)
|
||||
|
||||
Whether to suppress `ANN401` for dynamically typed `*args` and `**kwargs` arguments.
|
||||
Whether to suppress `ANN401` for dynamically typed `*args` and
|
||||
`**kwargs` arguments.
|
||||
|
||||
**Default value**: `false`
|
||||
|
||||
@@ -2053,8 +2112,8 @@ allow-star-arg-any = true
|
||||
|
||||
#### [`mypy-init-return`](#mypy-init-return)
|
||||
|
||||
Whether to allow the omission of a return type hint for `__init__` if at least one
|
||||
argument is annotated.
|
||||
Whether to allow the omission of a return type hint for `__init__` if at
|
||||
least one argument is annotated.
|
||||
|
||||
**Default value**: `false`
|
||||
|
||||
@@ -2071,8 +2130,8 @@ mypy-init-return = true
|
||||
|
||||
#### [`suppress-dummy-args`](#suppress-dummy-args)
|
||||
|
||||
Whether to suppress `ANN000`-level errors for arguments matching the "dummy" variable
|
||||
regex (like `_`).
|
||||
Whether to suppress `ANN000`-level errors for arguments matching the
|
||||
"dummy" variable regex (like `_`).
|
||||
|
||||
**Default value**: `false`
|
||||
|
||||
@@ -2089,11 +2148,12 @@ suppress-dummy-args = true
|
||||
|
||||
#### [`suppress-none-returning`](#suppress-none-returning)
|
||||
|
||||
Whether to suppress `ANN200`-level errors for functions that meet either of the
|
||||
following criteria:
|
||||
Whether to suppress `ANN200`-level errors for functions that meet either
|
||||
of the following criteria:
|
||||
|
||||
- Contain no `return` statement.
|
||||
- Explicit `return` statement(s) all return `None` (explicitly or implicitly).
|
||||
- Explicit `return` statement(s) all return `None` (explicitly or
|
||||
implicitly).
|
||||
|
||||
**Default value**: `false`
|
||||
|
||||
@@ -2112,8 +2172,8 @@ suppress-none-returning = true
|
||||
|
||||
#### [`extend-immutable-calls`](#extend-immutable-calls)
|
||||
|
||||
Additional callable functions to consider "immutable" when evaluating, e.g.,
|
||||
`no-mutable-default-argument` checks (`B006`).
|
||||
Additional callable functions to consider "immutable" when evaluating,
|
||||
e.g., `no-mutable-default-argument` checks (`B006`).
|
||||
|
||||
**Default value**: `[]`
|
||||
|
||||
@@ -2152,7 +2212,8 @@ max-string-length = 20
|
||||
|
||||
#### [`aliases`](#aliases)
|
||||
|
||||
The conventional aliases for imports. These aliases can be extended by the `extend_aliases` option.
|
||||
The conventional aliases for imports. These aliases can be extended by
|
||||
the `extend_aliases` option.
|
||||
|
||||
**Default value**: `{"altair": "alt", "matplotlib.pyplot": "plt", "numpy": "np", "pandas": "pd", "seaborn": "sns"}`
|
||||
|
||||
@@ -2174,7 +2235,8 @@ seaborn = "sns"
|
||||
|
||||
#### [`extend-aliases`](#extend-aliases)
|
||||
|
||||
A mapping of modules to their conventional import aliases. These aliases will be added to the `aliases` mapping.
|
||||
A mapping of modules to their conventional import aliases. These aliases
|
||||
will be added to the `aliases` mapping.
|
||||
|
||||
**Default value**: `{}`
|
||||
|
||||
@@ -2194,8 +2256,8 @@ A mapping of modules to their conventional import aliases. These aliases will be
|
||||
|
||||
#### [`avoid-escape`](#avoid-escape)
|
||||
|
||||
Whether to avoid using single quotes if a string contains single quotes, or vice-versa
|
||||
with double quotes, as per [PEP8](https://peps.python.org/pep-0008/#string-quotes).
|
||||
Whether to avoid using single quotes if a string contains single quotes,
|
||||
or vice-versa with double quotes, as per [PEP8](https://peps.python.org/pep-0008/#string-quotes).
|
||||
This minimizes the need to escape quotation marks within strings.
|
||||
|
||||
**Default value**: `true`
|
||||
@@ -2214,7 +2276,8 @@ avoid-escape = false
|
||||
|
||||
#### [`docstring-quotes`](#docstring-quotes)
|
||||
|
||||
Quote style to prefer for docstrings (either "single" (`'`) or "double" (`"`)).
|
||||
Quote style to prefer for docstrings (either "single" (`'`) or "double"
|
||||
(`"`)).
|
||||
|
||||
**Default value**: `"double"`
|
||||
|
||||
@@ -2231,7 +2294,8 @@ docstring-quotes = "single"
|
||||
|
||||
#### [`inline-quotes`](#inline-quotes)
|
||||
|
||||
Quote style to prefer for inline strings (either "single" (`'`) or "double" (`"`)).
|
||||
Quote style to prefer for inline strings (either "single" (`'`) or
|
||||
"double" (`"`)).
|
||||
|
||||
**Default value**: `"double"`
|
||||
|
||||
@@ -2248,7 +2312,8 @@ inline-quotes = "single"
|
||||
|
||||
#### [`multiline-quotes`](#multiline-quotes)
|
||||
|
||||
Quote style to prefer for multiline strings (either "single" (`'`) or "double" (`"`)).
|
||||
Quote style to prefer for multiline strings (either "single" (`'`) or
|
||||
"double" (`"`)).
|
||||
|
||||
**Default value**: `"double"`
|
||||
|
||||
@@ -2267,8 +2332,8 @@ multiline-quotes = "single"
|
||||
|
||||
#### [`ban-relative-imports`](#ban-relative-imports)
|
||||
|
||||
Whether to ban all relative imports (`"all"`), or only those imports that extend into
|
||||
the parent module and beyond (`"parents"`).
|
||||
Whether to ban all relative imports (`"all"`), or only those imports
|
||||
that extend into the parent module and beyond (`"parents"`).
|
||||
|
||||
**Default value**: `"parents"`
|
||||
|
||||
@@ -2325,8 +2390,8 @@ combine-as-imports = true
|
||||
|
||||
#### [`extra-standard-library`](#extra-standard-library)
|
||||
|
||||
A list of modules to consider standard-library, in addition to those known to Ruff in
|
||||
advance.
|
||||
A list of modules to consider standard-library, in addition to those
|
||||
known to Ruff in advance.
|
||||
|
||||
**Default value**: `[]`
|
||||
|
||||
@@ -2343,9 +2408,10 @@ extra-standard-library = ["path"]
|
||||
|
||||
#### [`force-wrap-aliases`](#force-wrap-aliases)
|
||||
|
||||
Force `import from` statements with multiple members and at least one alias (e.g.,
|
||||
`import A as B`) to wrap such that every line contains exactly one member. For example,
|
||||
this formatting would be retained, rather than condensing to a single line:
|
||||
Force `import from` statements with multiple members and at least one
|
||||
alias (e.g., `import A as B`) to wrap such that every line contains
|
||||
exactly one member. For example, this formatting would be retained,
|
||||
rather than condensing to a single line:
|
||||
|
||||
```py
|
||||
from .utils import (
|
||||
@@ -2354,9 +2420,10 @@ from .utils import (
|
||||
)
|
||||
```
|
||||
|
||||
Note that this setting is only effective when combined with `combine-as-imports = true`.
|
||||
When `combine-as-imports` isn't enabled, every aliased `import from` will be given its
|
||||
own line, in which case, wrapping is not necessary.
|
||||
Note that this setting is only effective when combined with
|
||||
`combine-as-imports = true`. When `combine-as-imports` isn't
|
||||
enabled, every aliased `import from` will be given its own line, in
|
||||
which case, wrapping is not necessary.
|
||||
|
||||
**Default value**: `false`
|
||||
|
||||
@@ -2374,8 +2441,8 @@ combine-as-imports = true
|
||||
|
||||
#### [`known-first-party`](#known-first-party)
|
||||
|
||||
A list of modules to consider first-party, regardless of whether they can be identified
|
||||
as such via introspection of the local filesystem.
|
||||
A list of modules to consider first-party, regardless of whether they
|
||||
can be identified as such via introspection of the local filesystem.
|
||||
|
||||
**Default value**: `[]`
|
||||
|
||||
@@ -2392,8 +2459,8 @@ known-first-party = ["src"]
|
||||
|
||||
#### [`known-third-party`](#known-third-party)
|
||||
|
||||
A list of modules to consider third-party, regardless of whether they can be identified
|
||||
as such via introspection of the local filesystem.
|
||||
A list of modules to consider third-party, regardless of whether they
|
||||
can be identified as such via introspection of the local filesystem.
|
||||
|
||||
**Default value**: `[]`
|
||||
|
||||
@@ -2432,9 +2499,10 @@ max-complexity = 5
|
||||
|
||||
#### [`classmethod-decorators`](#classmethod-decorators)
|
||||
|
||||
A list of decorators that, when applied to a method, indicate that the method should be
|
||||
treated as a class method. For example, Ruff will expect that any method decorated by a
|
||||
decorator in this list takes a `cls` argument as its first argument.
|
||||
A list of decorators that, when applied to a method, indicate that the
|
||||
method should be treated as a class method. For example, Ruff will
|
||||
expect that any method decorated by a decorator in this list takes a
|
||||
`cls` argument as its first argument.
|
||||
|
||||
**Default value**: `["classmethod"]`
|
||||
|
||||
@@ -2469,9 +2537,10 @@ ignore-names = ["callMethod"]
|
||||
|
||||
#### [`staticmethod-decorators`](#staticmethod-decorators)
|
||||
|
||||
A list of decorators that, when applied to a method, indicate that the method should be
|
||||
treated as a static method. For example, Ruff will expect that any method decorated by a
|
||||
decorator in this list has no `self` or `cls` argument.
|
||||
A list of decorators that, when applied to a method, indicate that the
|
||||
method should be treated as a static method. For example, Ruff will
|
||||
expect that any method decorated by a decorator in this list has no
|
||||
`self` or `cls` argument.
|
||||
|
||||
**Default value**: `["staticmethod"]`
|
||||
|
||||
@@ -2491,7 +2560,11 @@ staticmethod-decorators = ["staticmethod", "stcmthd"]
|
||||
|
||||
#### [`keep-runtime-typing`](#keep-runtime-typing)
|
||||
|
||||
Whether to avoid PEP 585 (`List[int]` -> `list[int]`) and PEP 604 (`Optional[str]` -> `str | None`) rewrites even if a file imports `from __future__ import annotations`. Note that this setting is only applicable when the target Python version is below 3.9 and 3.10 respectively.
|
||||
Whether to avoid PEP 585 (`List[int]` -> `list[int]`) and PEP 604
|
||||
(`Optional[str]` -> `str | None`) rewrites even if a file imports `from
|
||||
__future__ import annotations`. Note that this setting is only
|
||||
applicable when the target Python version is below 3.9 and 3.10
|
||||
respectively.
|
||||
|
||||
**Default value**: `false`
|
||||
|
||||
|
||||
12
flake8_to_ruff/Cargo.lock
generated
12
flake8_to_ruff/Cargo.lock
generated
@@ -771,7 +771,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8_to_ruff"
|
||||
version = "0.0.192"
|
||||
version = "0.0.193"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -1975,7 +1975,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.192"
|
||||
version = "0.0.193"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
@@ -2028,7 +2028,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-ast"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c01f014b1269eedcf4bdb45d5fbc62ae2beecf31#c01f014b1269eedcf4bdb45d5fbc62ae2beecf31"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"rustpython-common",
|
||||
@@ -2038,7 +2038,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-common"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c01f014b1269eedcf4bdb45d5fbc62ae2beecf31#c01f014b1269eedcf4bdb45d5fbc62ae2beecf31"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
|
||||
dependencies = [
|
||||
"ascii",
|
||||
"cfg-if 1.0.0",
|
||||
@@ -2061,7 +2061,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-compiler-core"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c01f014b1269eedcf4bdb45d5fbc62ae2beecf31#c01f014b1269eedcf4bdb45d5fbc62ae2beecf31"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitflags",
|
||||
@@ -2078,7 +2078,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-parser"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c01f014b1269eedcf4bdb45d5fbc62ae2beecf31#c01f014b1269eedcf4bdb45d5fbc62ae2beecf31"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.192-dev.0"
|
||||
version = "0.0.193-dev.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -12,6 +12,7 @@ classifiers = [
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
"Topic :: Software Development :: Quality Assurance",
|
||||
|
||||
@@ -67,10 +67,7 @@ pub fn convert(
|
||||
}
|
||||
let from_codes = plugin::infer_plugins_from_codes(&referenced_codes);
|
||||
if !from_codes.is_empty() {
|
||||
eprintln!(
|
||||
"Inferred plugins from referenced check codes: {:#?}",
|
||||
from_codes
|
||||
);
|
||||
eprintln!("Inferred plugins from referenced check codes: {from_codes:#?}");
|
||||
}
|
||||
from_options.into_iter().chain(from_codes).collect()
|
||||
}),
|
||||
@@ -315,6 +312,7 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
@@ -369,6 +367,7 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
@@ -423,6 +422,7 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
@@ -477,6 +477,7 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
@@ -531,6 +532,7 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
@@ -629,6 +631,7 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
@@ -684,6 +687,7 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
|
||||
@@ -12,6 +12,7 @@ classifiers = [
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
"Topic :: Software Development :: Quality Assurance",
|
||||
|
||||
12
resources/test/fixtures/flake8_return/RET504.py
vendored
12
resources/test/fixtures/flake8_return/RET504.py
vendored
@@ -237,3 +237,15 @@ def close(self):
|
||||
any_failed = True
|
||||
report(traceback.format_exc())
|
||||
return any_failed
|
||||
|
||||
def global_assignment():
|
||||
global X
|
||||
X = 1
|
||||
return X
|
||||
|
||||
def nonlocal_assignment():
|
||||
X = 1
|
||||
def inner():
|
||||
nonlocal X
|
||||
X = 1
|
||||
return X
|
||||
|
||||
4
resources/test/fixtures/pycodestyle/E721.py
vendored
4
resources/test/fixtures/pycodestyle/E721.py
vendored
@@ -15,7 +15,7 @@ import types
|
||||
if type(res) is not types.ListType:
|
||||
pass
|
||||
#: E721
|
||||
assert type(res) == type(False) or type(res) == type(None)
|
||||
assert type(res) == type(False)
|
||||
#: E721
|
||||
assert type(res) == type([])
|
||||
#: E721
|
||||
@@ -52,3 +52,5 @@ if isinstance(res, types.MethodType):
|
||||
pass
|
||||
if type(a) != type(b) or type(a) == type(ccc):
|
||||
pass
|
||||
|
||||
assert type(res) == type(None)
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
def fn() -> None:
|
||||
pass
|
||||
print("Newline present (no W292)")
|
||||
|
||||
0
resources/test/fixtures/pycodestyle/W292_3.py
vendored
Normal file
0
resources/test/fixtures/pycodestyle/W292_3.py
vendored
Normal file
1
resources/test/fixtures/pycodestyle/W292_4.py
vendored
Normal file
1
resources/test/fixtures/pycodestyle/W292_4.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
25
resources/test/fixtures/pyupgrade/UP018.py
vendored
Normal file
25
resources/test/fixtures/pyupgrade/UP018.py
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# These remain unchanged
|
||||
str(1)
|
||||
str(*a)
|
||||
str("foo", *a)
|
||||
str(**k)
|
||||
str("foo", **k)
|
||||
str("foo", encoding="UTF-8")
|
||||
str("foo"
|
||||
"bar")
|
||||
bytes("foo", encoding="UTF-8")
|
||||
bytes(*a)
|
||||
bytes("foo", *a)
|
||||
bytes("foo", **a)
|
||||
bytes(b"foo"
|
||||
b"bar")
|
||||
|
||||
# These become string or byte literals
|
||||
str()
|
||||
str("foo")
|
||||
str("""
|
||||
foo""")
|
||||
bytes()
|
||||
bytes(b"foo")
|
||||
bytes(b"""
|
||||
foo""")
|
||||
4
resources/test/fixtures/ruff/RUF100.py
vendored
4
resources/test/fixtures/ruff/RUF100.py
vendored
@@ -15,8 +15,8 @@ def f() -> None:
|
||||
# Invalid
|
||||
d = 1 # noqa: F841, E501
|
||||
|
||||
# Invalid (and unimplemented)
|
||||
d = 1 # noqa: F841, W191
|
||||
# Invalid (and unimplemented or not enabled)
|
||||
d = 1 # noqa: F841, W191, F821
|
||||
|
||||
# Invalid (but external)
|
||||
d = 1 # noqa: F841, V101
|
||||
|
||||
1194
ruff.schema.json
Normal file
1194
ruff.schema.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_dev"
|
||||
version = "0.0.192"
|
||||
version = "0.0.193"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
@@ -11,8 +11,10 @@ itertools = { version = "0.10.5" }
|
||||
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "f2f0b7a487a8725d161fe8b3ed73a6758b21e177" }
|
||||
once_cell = { version = "1.16.0" }
|
||||
ruff = { path = ".." }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "c01f014b1269eedcf4bdb45d5fbc62ae2beecf31" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "c01f014b1269eedcf4bdb45d5fbc62ae2beecf31" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "c01f014b1269eedcf4bdb45d5fbc62ae2beecf31" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "1b6cb170e925a43d605b3fed9f6b878e63e47744" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "1b6cb170e925a43d605b3fed9f6b878e63e47744" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "1b6cb170e925a43d605b3fed9f6b878e63e47744" }
|
||||
schemars = { version = "0.8.11" }
|
||||
serde_json = {version="1.0.91"}
|
||||
strum = { version = "0.24.1", features = ["strum_macros"] }
|
||||
strum_macros = { version = "0.24.3" }
|
||||
|
||||
@@ -65,7 +65,8 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
.derive("Ord")
|
||||
.derive("Clone")
|
||||
.derive("Serialize")
|
||||
.derive("Deserialize");
|
||||
.derive("Deserialize")
|
||||
.derive("JsonSchema");
|
||||
for prefix in prefix_to_codes.keys() {
|
||||
gen = gen.push_variant(Variant::new(prefix.to_string()));
|
||||
}
|
||||
@@ -138,8 +139,7 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
_ => panic!("Invalid prefix: {prefix}"),
|
||||
};
|
||||
gen = gen.line(format!(
|
||||
"CheckCodePrefix::{prefix} => SuffixLength::{},",
|
||||
specificity
|
||||
"CheckCodePrefix::{prefix} => SuffixLength::{specificity},"
|
||||
));
|
||||
}
|
||||
gen.line("}");
|
||||
@@ -152,6 +152,8 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
output.push('\n');
|
||||
output.push_str("use colored::Colorize;");
|
||||
output.push('\n');
|
||||
output.push_str("use schemars::JsonSchema;");
|
||||
output.push('\n');
|
||||
output.push_str("use serde::{Deserialize, Serialize};");
|
||||
output.push('\n');
|
||||
output.push_str("use strum_macros::{AsRefStr, EnumString};");
|
||||
|
||||
30
ruff_dev/src/generate_json_schema.rs
Normal file
30
ruff_dev/src/generate_json_schema.rs
Normal file
@@ -0,0 +1,30 @@
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::Args;
|
||||
use ruff::settings::options::Options;
|
||||
use schemars::schema_for;
|
||||
|
||||
#[derive(Args)]
|
||||
pub struct Cli {
|
||||
/// Write the generated table to stdout (rather than to `ruff.schema.json`).
|
||||
#[arg(long)]
|
||||
dry_run: bool,
|
||||
}
|
||||
|
||||
pub fn main(cli: &Cli) -> Result<()> {
|
||||
let schema = schema_for!(Options);
|
||||
let schema_string = serde_json::to_string_pretty(&schema).unwrap();
|
||||
|
||||
if cli.dry_run {
|
||||
println!("{schema_string}");
|
||||
} else {
|
||||
let file = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.parent()
|
||||
.expect("Failed to find root directory")
|
||||
.join("ruff.schema.json");
|
||||
fs::write(file, schema_string.as_bytes())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -12,6 +12,7 @@
|
||||
)]
|
||||
|
||||
pub mod generate_check_code_prefix;
|
||||
pub mod generate_json_schema;
|
||||
pub mod generate_options;
|
||||
pub mod generate_rules_table;
|
||||
pub mod generate_source_code;
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
use anyhow::Result;
|
||||
use clap::{Parser, Subcommand};
|
||||
use ruff_dev::{
|
||||
generate_check_code_prefix, generate_options, generate_rules_table, generate_source_code,
|
||||
print_ast, print_cst, print_tokens,
|
||||
generate_check_code_prefix, generate_json_schema, generate_options, generate_rules_table,
|
||||
generate_source_code, print_ast, print_cst, print_tokens,
|
||||
};
|
||||
|
||||
#[derive(Parser)]
|
||||
@@ -30,6 +30,8 @@ struct Cli {
|
||||
enum Commands {
|
||||
/// Generate the `CheckCodePrefix` enum.
|
||||
GenerateCheckCodePrefix(generate_check_code_prefix::Cli),
|
||||
/// Generate JSON schema for the TOML configuration file.
|
||||
GenerateJSONSchema(generate_json_schema::Cli),
|
||||
/// Generate a Markdown-compatible table of supported lint rules.
|
||||
GenerateRulesTable(generate_rules_table::Cli),
|
||||
/// Generate a Markdown-compatible listing of configuration options.
|
||||
@@ -48,6 +50,7 @@ fn main() -> Result<()> {
|
||||
let cli = Cli::parse();
|
||||
match &cli.command {
|
||||
Commands::GenerateCheckCodePrefix(args) => generate_check_code_prefix::main(args)?,
|
||||
Commands::GenerateJSONSchema(args) => generate_json_schema::main(args)?,
|
||||
Commands::GenerateRulesTable(args) => generate_rules_table::main(args)?,
|
||||
Commands::GenerateSourceCode(args) => generate_source_code::main(args)?,
|
||||
Commands::GenerateOptions(args) => generate_options::main(args)?,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_macros"
|
||||
version = "0.0.192"
|
||||
version = "0.0.193"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -13,13 +13,14 @@
|
||||
|
||||
use quote::{quote, quote_spanned};
|
||||
use syn::parse::{Parse, ParseStream};
|
||||
use syn::spanned::Spanned;
|
||||
use syn::token::Comma;
|
||||
use syn::{
|
||||
parse_macro_input, AngleBracketedGenericArguments, Attribute, Data, DataStruct, DeriveInput,
|
||||
Field, Fields, Lit, LitStr, Path, PathArguments, PathSegment, Token, Type, TypePath,
|
||||
};
|
||||
|
||||
#[proc_macro_derive(ConfigurationOptions, attributes(option, option_group))]
|
||||
#[proc_macro_derive(ConfigurationOptions, attributes(option, doc, option_group))]
|
||||
pub fn derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
|
||||
@@ -39,11 +40,28 @@ fn derive_impl(input: DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
|
||||
let mut output = vec![];
|
||||
|
||||
for field in fields.named.iter() {
|
||||
if let Some(attr) = field.attrs.iter().find(|a| a.path.is_ident("option")) {
|
||||
output.push(handle_option(field, attr)?);
|
||||
let docs: Vec<&Attribute> = field
|
||||
.attrs
|
||||
.iter()
|
||||
.filter(|attr| attr.path.is_ident("doc"))
|
||||
.collect();
|
||||
|
||||
if docs.is_empty() {
|
||||
return Err(syn::Error::new(
|
||||
field.span(),
|
||||
"Missing documentation for field",
|
||||
));
|
||||
}
|
||||
|
||||
if let Some(attr) = field.attrs.iter().find(|attr| attr.path.is_ident("option")) {
|
||||
output.push(handle_option(field, attr, docs)?);
|
||||
};
|
||||
|
||||
if field.attrs.iter().any(|a| a.path.is_ident("option_group")) {
|
||||
if field
|
||||
.attrs
|
||||
.iter()
|
||||
.any(|attr| attr.path.is_ident("option_group"))
|
||||
{
|
||||
output.push(handle_option_group(field)?);
|
||||
};
|
||||
}
|
||||
@@ -70,8 +88,10 @@ fn derive_impl(input: DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
|
||||
/// deriving `ConfigurationOptions`, create code that calls retrieves options
|
||||
/// from that group: `Foobar::get_available_options()`
|
||||
fn handle_option_group(field: &Field) -> syn::Result<proc_macro2::TokenStream> {
|
||||
// unwrap is safe because we're only going over named fields
|
||||
let ident = field.ident.as_ref().unwrap();
|
||||
let ident = field
|
||||
.ident
|
||||
.as_ref()
|
||||
.expect("Expected to handle named fields");
|
||||
|
||||
match &field.ty {
|
||||
Type::Path(TypePath {
|
||||
@@ -103,17 +123,49 @@ fn handle_option_group(field: &Field) -> syn::Result<proc_macro2::TokenStream> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a `doc` attribute into it a string literal.
|
||||
fn parse_doc(doc: &Attribute) -> syn::Result<String> {
|
||||
let doc = doc
|
||||
.parse_meta()
|
||||
.map_err(|e| syn::Error::new(doc.span(), e))?;
|
||||
|
||||
match doc {
|
||||
syn::Meta::NameValue(syn::MetaNameValue {
|
||||
lit: Lit::Str(lit_str),
|
||||
..
|
||||
}) => Ok(lit_str.value()),
|
||||
_ => Err(syn::Error::new(doc.span(), "Expected doc attribute.")),
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse an `#[option(doc="...", default="...", value_type="...",
|
||||
/// example="...")]` attribute and return data in the form of an `OptionField`.
|
||||
fn handle_option(field: &Field, attr: &Attribute) -> syn::Result<proc_macro2::TokenStream> {
|
||||
// unwrap is safe because we're only going over named fields
|
||||
let ident = field.ident.as_ref().unwrap();
|
||||
fn handle_option(
|
||||
field: &Field,
|
||||
attr: &Attribute,
|
||||
docs: Vec<&Attribute>,
|
||||
) -> syn::Result<proc_macro2::TokenStream> {
|
||||
// Convert the list of `doc` attributes into a single string.
|
||||
let doc = textwrap::dedent(
|
||||
&docs
|
||||
.into_iter()
|
||||
.map(parse_doc)
|
||||
.collect::<syn::Result<Vec<_>>>()?
|
||||
.join("\n"),
|
||||
)
|
||||
.trim_matches('\n')
|
||||
.to_string();
|
||||
|
||||
let ident = field
|
||||
.ident
|
||||
.as_ref()
|
||||
.expect("Expected to handle named fields");
|
||||
|
||||
let FieldAttributes {
|
||||
doc,
|
||||
default,
|
||||
value_type,
|
||||
example,
|
||||
..
|
||||
} = attr.parse_args::<FieldAttributes>()?;
|
||||
let kebab_name = LitStr::new(&ident.to_string().replace('_', "-"), ident.span());
|
||||
|
||||
@@ -130,7 +182,6 @@ fn handle_option(field: &Field, attr: &Attribute) -> syn::Result<proc_macro2::To
|
||||
|
||||
#[derive(Debug)]
|
||||
struct FieldAttributes {
|
||||
doc: String,
|
||||
default: String,
|
||||
value_type: String,
|
||||
example: String,
|
||||
@@ -138,8 +189,6 @@ struct FieldAttributes {
|
||||
|
||||
impl Parse for FieldAttributes {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let doc = _parse_key_value(input, "doc")?;
|
||||
input.parse::<Comma>()?;
|
||||
let default = _parse_key_value(input, "default")?;
|
||||
input.parse::<Comma>()?;
|
||||
let value_type = _parse_key_value(input, "value_type")?;
|
||||
@@ -150,7 +199,6 @@ impl Parse for FieldAttributes {
|
||||
}
|
||||
|
||||
Ok(FieldAttributes {
|
||||
doc: textwrap::dedent(&doc).trim_matches('\n').to_string(),
|
||||
default,
|
||||
value_type,
|
||||
example: textwrap::dedent(&example).trim_matches('\n').to_string(),
|
||||
|
||||
27
src/cache.rs
27
src/cache.rs
@@ -3,7 +3,7 @@ use std::fs;
|
||||
use std::fs::{create_dir_all, File, Metadata};
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use anyhow::Result;
|
||||
use filetime::FileTime;
|
||||
@@ -36,8 +36,12 @@ struct CheckResult {
|
||||
messages: Vec<Message>,
|
||||
}
|
||||
|
||||
fn cache_dir() -> &'static Path {
|
||||
Path::new(CACHE_DIR.as_ref().map_or(".ruff_cache", String::as_str))
|
||||
/// Return the cache directory for a given project root. Defers to the
|
||||
/// `RUFF_CACHE_DIR` environment variable, if set.
|
||||
pub fn cache_dir(project_root: &Path) -> PathBuf {
|
||||
CACHE_DIR
|
||||
.as_ref()
|
||||
.map_or_else(|| project_root.join(".ruff_cache"), PathBuf::from)
|
||||
}
|
||||
|
||||
fn content_dir() -> &'static Path {
|
||||
@@ -53,10 +57,8 @@ fn cache_key<P: AsRef<Path>>(path: P, settings: &Settings, autofix: fixer::Mode)
|
||||
hasher.finish()
|
||||
}
|
||||
|
||||
/// Initialize the cache directory.
|
||||
pub fn init() -> Result<()> {
|
||||
let path = cache_dir();
|
||||
|
||||
/// Initialize the cache at the specified `Path`.
|
||||
pub fn init(path: &Path) -> Result<()> {
|
||||
// Create the cache directories.
|
||||
create_dir_all(path.join(content_dir()))?;
|
||||
|
||||
@@ -75,15 +77,15 @@ pub fn init() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_sync(key: u64, value: &[u8]) -> Result<(), std::io::Error> {
|
||||
fn write_sync(cache_dir: &Path, key: u64, value: &[u8]) -> Result<(), std::io::Error> {
|
||||
fs::write(
|
||||
cache_dir().join(content_dir()).join(format!("{key:x}")),
|
||||
cache_dir.join(content_dir()).join(format!("{key:x}")),
|
||||
value,
|
||||
)
|
||||
}
|
||||
|
||||
fn read_sync(key: u64) -> Result<Vec<u8>, std::io::Error> {
|
||||
fs::read(cache_dir().join(content_dir()).join(format!("{key:x}")))
|
||||
fn read_sync(cache_dir: &Path, key: u64) -> Result<Vec<u8>, std::io::Error> {
|
||||
fs::read(cache_dir.join(content_dir()).join(format!("{key:x}")))
|
||||
}
|
||||
|
||||
/// Get a value from the cache.
|
||||
@@ -98,7 +100,7 @@ pub fn get<P: AsRef<Path>>(
|
||||
return None;
|
||||
};
|
||||
|
||||
let encoded = read_sync(cache_key(path, settings, autofix)).ok()?;
|
||||
let encoded = read_sync(&settings.cache_dir, cache_key(path, settings, autofix)).ok()?;
|
||||
let (mtime, messages) = match bincode::deserialize::<CheckResult>(&encoded[..]) {
|
||||
Ok(CheckResult {
|
||||
metadata: CacheMetadata { mtime },
|
||||
@@ -135,6 +137,7 @@ pub fn set<P: AsRef<Path>>(
|
||||
messages,
|
||||
};
|
||||
if let Err(e) = write_sync(
|
||||
&settings.cache_dir,
|
||||
cache_key(path, settings, autofix),
|
||||
&bincode::serialize(&check_result).unwrap(),
|
||||
) {
|
||||
|
||||
@@ -1067,17 +1067,11 @@ where
|
||||
}
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::EM101)
|
||||
| self.settings.enabled.contains(&CheckCode::EM102)
|
||||
| self.settings.enabled.contains(&CheckCode::EM103)
|
||||
|| self.settings.enabled.contains(&CheckCode::EM102)
|
||||
|| self.settings.enabled.contains(&CheckCode::EM103)
|
||||
{
|
||||
if let Some(exc) = exc {
|
||||
self.add_checks(
|
||||
flake8_errmsg::checks::check_string_in_exception(
|
||||
exc,
|
||||
self.settings.flake8_errmsg.max_string_length,
|
||||
)
|
||||
.into_iter(),
|
||||
);
|
||||
flake8_errmsg::plugins::string_in_exception(self, exc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1157,7 +1151,7 @@ where
|
||||
if self.settings.enabled.contains(&CheckCode::B014)
|
||||
|| self.settings.enabled.contains(&CheckCode::B025)
|
||||
{
|
||||
flake8_bugbear::plugins::duplicate_exceptions(self, stmt, handlers);
|
||||
flake8_bugbear::plugins::duplicate_exceptions(self, handlers);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::B013) {
|
||||
flake8_bugbear::plugins::redundant_tuple_in_exception_handler(self, handlers);
|
||||
@@ -1650,6 +1644,9 @@ where
|
||||
if self.settings.enabled.contains(&CheckCode::UP016) {
|
||||
pyupgrade::plugins::remove_six_compat(self, expr);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::UP018) {
|
||||
pyupgrade::plugins::native_literals(self, expr, func, args, keywords);
|
||||
}
|
||||
|
||||
// flake8-super
|
||||
if self.settings.enabled.contains(&CheckCode::UP008) {
|
||||
|
||||
@@ -55,7 +55,11 @@ pub fn check_lines(
|
||||
}
|
||||
|
||||
if enforce_no_newline_at_end_of_file {
|
||||
if let Some(check) = no_newline_at_end_of_file(contents) {
|
||||
if let Some(check) = no_newline_at_end_of_file(
|
||||
contents,
|
||||
matches!(autofix, flags::Autofix::Enabled)
|
||||
&& settings.fixable.contains(&CheckCode::W292),
|
||||
) {
|
||||
checks.push(check);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
//! `NoQA` enforcement and validation.
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use nohash_hasher::IntMap;
|
||||
use rustpython_parser::ast::Location;
|
||||
|
||||
use crate::ast::types::Range;
|
||||
use crate::autofix::Fix;
|
||||
use crate::checks::{Check, CheckCode, CheckKind, CODE_REDIRECTS};
|
||||
use crate::checks::{Check, CheckCode, CheckKind, UnusedCodes, CODE_REDIRECTS};
|
||||
use crate::noqa;
|
||||
use crate::noqa::{is_file_exempt, Directive};
|
||||
use crate::settings::{flags, Settings};
|
||||
@@ -98,18 +100,29 @@ pub fn check_noqa(
|
||||
}
|
||||
}
|
||||
Directive::Codes(spaces, start, end, codes) => {
|
||||
let mut invalid_codes = vec![];
|
||||
let mut disabled_codes = vec![];
|
||||
let mut unknown_codes = vec![];
|
||||
let mut unmatched_codes = vec![];
|
||||
let mut valid_codes = vec![];
|
||||
let mut self_ignore = false;
|
||||
for code in codes {
|
||||
let code = CODE_REDIRECTS.get(code).map_or(code, AsRef::as_ref);
|
||||
if code == CheckCode::RUF100.as_ref() {
|
||||
self_ignore = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if matches.contains(&code) || settings.external.contains(code) {
|
||||
valid_codes.push(code);
|
||||
} else {
|
||||
if matches.contains(&code) || settings.external.contains(code) {
|
||||
valid_codes.push(code);
|
||||
if let Ok(check_code) = CheckCode::from_str(code) {
|
||||
if settings.enabled.contains(&check_code) {
|
||||
unmatched_codes.push(code);
|
||||
} else {
|
||||
disabled_codes.push(code);
|
||||
}
|
||||
} else {
|
||||
invalid_codes.push(code);
|
||||
unknown_codes.push(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,14 +131,25 @@ pub fn check_noqa(
|
||||
continue;
|
||||
}
|
||||
|
||||
if !invalid_codes.is_empty() {
|
||||
if !(disabled_codes.is_empty()
|
||||
&& unknown_codes.is_empty()
|
||||
&& unmatched_codes.is_empty())
|
||||
{
|
||||
let mut check = Check::new(
|
||||
CheckKind::UnusedNOQA(Some(
|
||||
invalid_codes
|
||||
CheckKind::UnusedNOQA(Some(UnusedCodes {
|
||||
disabled: disabled_codes
|
||||
.iter()
|
||||
.map(|code| (*code).to_string())
|
||||
.collect(),
|
||||
)),
|
||||
unknown: unknown_codes
|
||||
.iter()
|
||||
.map(|code| (*code).to_string())
|
||||
.collect(),
|
||||
unmatched: unmatched_codes
|
||||
.iter()
|
||||
.map(|code| (*code).to_string())
|
||||
.collect(),
|
||||
})),
|
||||
Range {
|
||||
location: Location::new(row + 1, start),
|
||||
end_location: Location::new(row + 1, end),
|
||||
|
||||
@@ -89,7 +89,11 @@ pub fn check_tokens(
|
||||
if enforce_invalid_escape_sequence {
|
||||
if matches!(tok, Tok::String { .. }) {
|
||||
checks.extend(pycodestyle::checks::invalid_escape_sequence(
|
||||
locator, start, end,
|
||||
locator,
|
||||
start,
|
||||
end,
|
||||
matches!(autofix, flags::Autofix::Enabled)
|
||||
&& settings.fixable.contains(&CheckCode::W605),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
268
src/checks.rs
268
src/checks.rs
@@ -1,5 +1,4 @@
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
use itertools::Itertools;
|
||||
use once_cell::sync::Lazy;
|
||||
@@ -226,6 +225,7 @@ pub enum CheckCode {
|
||||
UP015,
|
||||
UP016,
|
||||
UP017,
|
||||
UP018,
|
||||
// pydocstyle
|
||||
D100,
|
||||
D101,
|
||||
@@ -635,6 +635,13 @@ impl fmt::Display for Branch {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct UnusedCodes {
|
||||
pub unknown: Vec<String>,
|
||||
pub disabled: Vec<String>,
|
||||
pub unmatched: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(AsRefStr, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum CheckKind {
|
||||
// pycodestyle errors
|
||||
@@ -829,6 +836,7 @@ pub enum CheckKind {
|
||||
RedundantOpenModes,
|
||||
RemoveSixCompat,
|
||||
DatetimeTimezoneUTC,
|
||||
NativeLiterals,
|
||||
// pydocstyle
|
||||
BlankLineAfterLastSection(String),
|
||||
BlankLineAfterSection(String),
|
||||
@@ -941,7 +949,7 @@ pub enum CheckKind {
|
||||
AmbiguousUnicodeCharacterString(char, char),
|
||||
AmbiguousUnicodeCharacterDocstring(char, char),
|
||||
AmbiguousUnicodeCharacterComment(char, char),
|
||||
UnusedNOQA(Option<Vec<String>>),
|
||||
UnusedNOQA(Option<UnusedCodes>),
|
||||
// flake8-datetimez
|
||||
CallDatetimeWithoutTzinfo,
|
||||
CallDatetimeToday,
|
||||
@@ -1203,6 +1211,7 @@ impl CheckCode {
|
||||
CheckCode::UP015 => CheckKind::RedundantOpenModes,
|
||||
CheckCode::UP016 => CheckKind::RemoveSixCompat,
|
||||
CheckCode::UP017 => CheckKind::DatetimeTimezoneUTC,
|
||||
CheckCode::UP018 => CheckKind::NativeLiterals,
|
||||
// pydocstyle
|
||||
CheckCode::D100 => CheckKind::PublicModule,
|
||||
CheckCode::D101 => CheckKind::PublicClass,
|
||||
@@ -1621,6 +1630,7 @@ impl CheckCode {
|
||||
CheckCode::UP015 => CheckCategory::Pyupgrade,
|
||||
CheckCode::UP016 => CheckCategory::Pyupgrade,
|
||||
CheckCode::UP017 => CheckCategory::Pyupgrade,
|
||||
CheckCode::UP018 => CheckCategory::Pyupgrade,
|
||||
CheckCode::W292 => CheckCategory::Pycodestyle,
|
||||
CheckCode::W605 => CheckCategory::Pycodestyle,
|
||||
CheckCode::YTT101 => CheckCategory::Flake82020,
|
||||
@@ -1642,9 +1652,9 @@ impl CheckKind {
|
||||
pub fn code(&self) -> &'static CheckCode {
|
||||
match self {
|
||||
// pycodestyle errors
|
||||
CheckKind::AmbiguousClassName(_) => &CheckCode::E742,
|
||||
CheckKind::AmbiguousFunctionName(_) => &CheckCode::E743,
|
||||
CheckKind::AmbiguousVariableName(_) => &CheckCode::E741,
|
||||
CheckKind::AmbiguousClassName(..) => &CheckCode::E742,
|
||||
CheckKind::AmbiguousFunctionName(..) => &CheckCode::E743,
|
||||
CheckKind::AmbiguousVariableName(..) => &CheckCode::E741,
|
||||
CheckKind::AssertTuple => &CheckCode::F631,
|
||||
CheckKind::BreakOutsideLoop => &CheckCode::F701,
|
||||
CheckKind::ContinueOutsideLoop => &CheckCode::F702,
|
||||
@@ -1653,14 +1663,14 @@ impl CheckKind {
|
||||
CheckKind::DoNotUseBareExcept => &CheckCode::E722,
|
||||
CheckKind::DuplicateArgumentName => &CheckCode::F831,
|
||||
CheckKind::FStringMissingPlaceholders => &CheckCode::F541,
|
||||
CheckKind::ForwardAnnotationSyntaxError(_) => &CheckCode::F722,
|
||||
CheckKind::FutureFeatureNotDefined(_) => &CheckCode::F407,
|
||||
CheckKind::IOError(_) => &CheckCode::E902,
|
||||
CheckKind::ForwardAnnotationSyntaxError(..) => &CheckCode::F722,
|
||||
CheckKind::FutureFeatureNotDefined(..) => &CheckCode::F407,
|
||||
CheckKind::IOError(..) => &CheckCode::E902,
|
||||
CheckKind::IfTuple => &CheckCode::F634,
|
||||
CheckKind::ImportShadowedByLoopVar(..) => &CheckCode::F402,
|
||||
CheckKind::ImportStarNotPermitted(_) => &CheckCode::F406,
|
||||
CheckKind::ImportStarNotPermitted(..) => &CheckCode::F406,
|
||||
CheckKind::ImportStarUsage(..) => &CheckCode::F405,
|
||||
CheckKind::ImportStarUsed(_) => &CheckCode::F403,
|
||||
CheckKind::ImportStarUsed(..) => &CheckCode::F403,
|
||||
CheckKind::InvalidPrintSyntax => &CheckCode::F633,
|
||||
CheckKind::IsLiteral => &CheckCode::F632,
|
||||
CheckKind::LateFutureImport => &CheckCode::F404,
|
||||
@@ -1668,42 +1678,42 @@ impl CheckKind {
|
||||
CheckKind::MultipleImportsOnOneLine => &CheckCode::E401,
|
||||
CheckKind::ModuleImportNotAtTopOfFile => &CheckCode::E402,
|
||||
CheckKind::MultiValueRepeatedKeyLiteral => &CheckCode::F601,
|
||||
CheckKind::MultiValueRepeatedKeyVariable(_) => &CheckCode::F602,
|
||||
CheckKind::NoneComparison(_) => &CheckCode::E711,
|
||||
CheckKind::MultiValueRepeatedKeyVariable(..) => &CheckCode::F602,
|
||||
CheckKind::NoneComparison(..) => &CheckCode::E711,
|
||||
CheckKind::NotInTest => &CheckCode::E713,
|
||||
CheckKind::NotIsTest => &CheckCode::E714,
|
||||
CheckKind::PercentFormatExpectedMapping => &CheckCode::F502,
|
||||
CheckKind::PercentFormatExpectedSequence => &CheckCode::F503,
|
||||
CheckKind::PercentFormatExtraNamedArguments(_) => &CheckCode::F504,
|
||||
CheckKind::PercentFormatInvalidFormat(_) => &CheckCode::F501,
|
||||
CheckKind::PercentFormatMissingArgument(_) => &CheckCode::F505,
|
||||
CheckKind::PercentFormatExtraNamedArguments(..) => &CheckCode::F504,
|
||||
CheckKind::PercentFormatInvalidFormat(..) => &CheckCode::F501,
|
||||
CheckKind::PercentFormatMissingArgument(..) => &CheckCode::F505,
|
||||
CheckKind::PercentFormatMixedPositionalAndNamed => &CheckCode::F506,
|
||||
CheckKind::PercentFormatPositionalCountMismatch(..) => &CheckCode::F507,
|
||||
CheckKind::PercentFormatStarRequiresSequence => &CheckCode::F508,
|
||||
CheckKind::PercentFormatUnsupportedFormatCharacter(_) => &CheckCode::F509,
|
||||
CheckKind::PercentFormatUnsupportedFormatCharacter(..) => &CheckCode::F509,
|
||||
CheckKind::RaiseNotImplemented => &CheckCode::F901,
|
||||
CheckKind::ReturnOutsideFunction => &CheckCode::F706,
|
||||
CheckKind::StringDotFormatExtraNamedArguments(_) => &CheckCode::F522,
|
||||
CheckKind::StringDotFormatExtraPositionalArguments(_) => &CheckCode::F523,
|
||||
CheckKind::StringDotFormatInvalidFormat(_) => &CheckCode::F521,
|
||||
CheckKind::StringDotFormatMissingArguments(_) => &CheckCode::F524,
|
||||
CheckKind::StringDotFormatExtraNamedArguments(..) => &CheckCode::F522,
|
||||
CheckKind::StringDotFormatExtraPositionalArguments(..) => &CheckCode::F523,
|
||||
CheckKind::StringDotFormatInvalidFormat(..) => &CheckCode::F521,
|
||||
CheckKind::StringDotFormatMissingArguments(..) => &CheckCode::F524,
|
||||
CheckKind::StringDotFormatMixingAutomatic => &CheckCode::F525,
|
||||
CheckKind::SyntaxError(_) => &CheckCode::E999,
|
||||
CheckKind::SyntaxError(..) => &CheckCode::E999,
|
||||
CheckKind::ExpressionsInStarAssignment => &CheckCode::F621,
|
||||
CheckKind::TrueFalseComparison(..) => &CheckCode::E712,
|
||||
CheckKind::TwoStarredExpressions => &CheckCode::F622,
|
||||
CheckKind::TypeComparison => &CheckCode::E721,
|
||||
CheckKind::UndefinedExport(_) => &CheckCode::F822,
|
||||
CheckKind::UndefinedLocal(_) => &CheckCode::F823,
|
||||
CheckKind::UndefinedExport(..) => &CheckCode::F822,
|
||||
CheckKind::UndefinedLocal(..) => &CheckCode::F823,
|
||||
CheckKind::RedefinedWhileUnused(..) => &CheckCode::F811,
|
||||
CheckKind::UndefinedName(_) => &CheckCode::F821,
|
||||
CheckKind::UndefinedName(..) => &CheckCode::F821,
|
||||
CheckKind::UnusedImport(..) => &CheckCode::F401,
|
||||
CheckKind::UnusedVariable(_) => &CheckCode::F841,
|
||||
CheckKind::UnusedAnnotation(_) => &CheckCode::F842,
|
||||
CheckKind::YieldOutsideFunction(_) => &CheckCode::F704,
|
||||
CheckKind::UnusedVariable(..) => &CheckCode::F841,
|
||||
CheckKind::UnusedAnnotation(..) => &CheckCode::F842,
|
||||
CheckKind::YieldOutsideFunction(..) => &CheckCode::F704,
|
||||
// pycodestyle warnings
|
||||
CheckKind::NoNewLineAtEndOfFile => &CheckCode::W292,
|
||||
CheckKind::InvalidEscapeSequence(_) => &CheckCode::W605,
|
||||
CheckKind::InvalidEscapeSequence(..) => &CheckCode::W605,
|
||||
// pylint
|
||||
CheckKind::AwaitOutsideAsync => &CheckCode::PLE1142,
|
||||
CheckKind::ConsiderMergingIsinstance(..) => &CheckCode::PLR1701,
|
||||
@@ -1712,96 +1722,96 @@ impl CheckKind {
|
||||
CheckKind::MisplacedComparisonConstant(..) => &CheckCode::PLC2201,
|
||||
CheckKind::PropertyWithParameters => &CheckCode::PLR0206,
|
||||
CheckKind::UnnecessaryDirectLambdaCall => &CheckCode::PLC3002,
|
||||
CheckKind::UseSysExit(_) => &CheckCode::PLR1722,
|
||||
CheckKind::UseSysExit(..) => &CheckCode::PLR1722,
|
||||
CheckKind::NonlocalWithoutBinding(..) => &CheckCode::PLE0117,
|
||||
CheckKind::UsedPriorGlobalDeclaration(..) => &CheckCode::PLE0118,
|
||||
CheckKind::UselessElseOnLoop => &CheckCode::PLW0120,
|
||||
CheckKind::UselessImportAlias => &CheckCode::PLC0414,
|
||||
// flake8-builtins
|
||||
CheckKind::BuiltinVariableShadowing(_) => &CheckCode::A001,
|
||||
CheckKind::BuiltinArgumentShadowing(_) => &CheckCode::A002,
|
||||
CheckKind::BuiltinAttributeShadowing(_) => &CheckCode::A003,
|
||||
CheckKind::BuiltinVariableShadowing(..) => &CheckCode::A001,
|
||||
CheckKind::BuiltinArgumentShadowing(..) => &CheckCode::A002,
|
||||
CheckKind::BuiltinAttributeShadowing(..) => &CheckCode::A003,
|
||||
// flake8-bugbear
|
||||
CheckKind::AbstractBaseClassWithoutAbstractMethod(_) => &CheckCode::B024,
|
||||
CheckKind::AbstractBaseClassWithoutAbstractMethod(..) => &CheckCode::B024,
|
||||
CheckKind::AssignmentToOsEnviron => &CheckCode::B003,
|
||||
CheckKind::CachedInstanceMethod => &CheckCode::B019,
|
||||
CheckKind::CannotRaiseLiteral => &CheckCode::B016,
|
||||
CheckKind::DoNotAssertFalse => &CheckCode::B011,
|
||||
CheckKind::DuplicateHandlerException(_) => &CheckCode::B014,
|
||||
CheckKind::DuplicateTryBlockException(_) => &CheckCode::B025,
|
||||
CheckKind::EmptyMethodWithoutAbstractDecorator(_) => &CheckCode::B027,
|
||||
CheckKind::DuplicateHandlerException(..) => &CheckCode::B014,
|
||||
CheckKind::DuplicateTryBlockException(..) => &CheckCode::B025,
|
||||
CheckKind::EmptyMethodWithoutAbstractDecorator(..) => &CheckCode::B027,
|
||||
CheckKind::FStringDocstring => &CheckCode::B021,
|
||||
CheckKind::FunctionCallArgumentDefault(_) => &CheckCode::B008,
|
||||
CheckKind::FunctionUsesLoopVariable(_) => &CheckCode::B023,
|
||||
CheckKind::FunctionCallArgumentDefault(..) => &CheckCode::B008,
|
||||
CheckKind::FunctionUsesLoopVariable(..) => &CheckCode::B023,
|
||||
CheckKind::GetAttrWithConstant => &CheckCode::B009,
|
||||
CheckKind::JumpStatementInFinally(_) => &CheckCode::B012,
|
||||
CheckKind::LoopVariableOverridesIterator(_) => &CheckCode::B020,
|
||||
CheckKind::JumpStatementInFinally(..) => &CheckCode::B012,
|
||||
CheckKind::LoopVariableOverridesIterator(..) => &CheckCode::B020,
|
||||
CheckKind::MutableArgumentDefault => &CheckCode::B006,
|
||||
CheckKind::NoAssertRaisesException => &CheckCode::B017,
|
||||
CheckKind::RaiseWithoutFromInsideExcept => &CheckCode::B904,
|
||||
CheckKind::ZipWithoutExplicitStrict => &CheckCode::B905,
|
||||
CheckKind::RedundantTupleInExceptionHandler(_) => &CheckCode::B013,
|
||||
CheckKind::RedundantTupleInExceptionHandler(..) => &CheckCode::B013,
|
||||
CheckKind::SetAttrWithConstant => &CheckCode::B010,
|
||||
CheckKind::StarArgUnpackingAfterKeywordArg => &CheckCode::B026,
|
||||
CheckKind::StripWithMultiCharacters => &CheckCode::B005,
|
||||
CheckKind::UnaryPrefixIncrement => &CheckCode::B002,
|
||||
CheckKind::UnreliableCallableCheck => &CheckCode::B004,
|
||||
CheckKind::UnusedLoopControlVariable(_) => &CheckCode::B007,
|
||||
CheckKind::UnusedLoopControlVariable(..) => &CheckCode::B007,
|
||||
CheckKind::UselessComparison => &CheckCode::B015,
|
||||
CheckKind::UselessContextlibSuppress => &CheckCode::B022,
|
||||
CheckKind::UselessExpression => &CheckCode::B018,
|
||||
// flake8-blind-except
|
||||
CheckKind::BlindExcept(_) => &CheckCode::BLE001,
|
||||
CheckKind::BlindExcept(..) => &CheckCode::BLE001,
|
||||
// flake8-comprehensions
|
||||
CheckKind::UnnecessaryGeneratorList => &CheckCode::C400,
|
||||
CheckKind::UnnecessaryGeneratorSet => &CheckCode::C401,
|
||||
CheckKind::UnnecessaryGeneratorDict => &CheckCode::C402,
|
||||
CheckKind::UnnecessaryListComprehensionSet => &CheckCode::C403,
|
||||
CheckKind::UnnecessaryListComprehensionDict => &CheckCode::C404,
|
||||
CheckKind::UnnecessaryLiteralSet(_) => &CheckCode::C405,
|
||||
CheckKind::UnnecessaryLiteralDict(_) => &CheckCode::C406,
|
||||
CheckKind::UnnecessaryCollectionCall(_) => &CheckCode::C408,
|
||||
CheckKind::UnnecessaryLiteralSet(..) => &CheckCode::C405,
|
||||
CheckKind::UnnecessaryLiteralDict(..) => &CheckCode::C406,
|
||||
CheckKind::UnnecessaryCollectionCall(..) => &CheckCode::C408,
|
||||
CheckKind::UnnecessaryLiteralWithinTupleCall(..) => &CheckCode::C409,
|
||||
CheckKind::UnnecessaryLiteralWithinListCall(..) => &CheckCode::C410,
|
||||
CheckKind::UnnecessaryListCall => &CheckCode::C411,
|
||||
CheckKind::UnnecessaryCallAroundSorted(_) => &CheckCode::C413,
|
||||
CheckKind::UnnecessaryCallAroundSorted(..) => &CheckCode::C413,
|
||||
CheckKind::UnnecessaryDoubleCastOrProcess(..) => &CheckCode::C414,
|
||||
CheckKind::UnnecessarySubscriptReversal(_) => &CheckCode::C415,
|
||||
CheckKind::UnnecessarySubscriptReversal(..) => &CheckCode::C415,
|
||||
CheckKind::UnnecessaryComprehension(..) => &CheckCode::C416,
|
||||
CheckKind::UnnecessaryMap(_) => &CheckCode::C417,
|
||||
CheckKind::UnnecessaryMap(..) => &CheckCode::C417,
|
||||
// flake8-debugger
|
||||
CheckKind::Debugger(_) => &CheckCode::T100,
|
||||
CheckKind::Debugger(..) => &CheckCode::T100,
|
||||
// flake8-tidy-imports
|
||||
CheckKind::BannedRelativeImport(_) => &CheckCode::TID252,
|
||||
CheckKind::BannedRelativeImport(..) => &CheckCode::TID252,
|
||||
// flake8-return
|
||||
CheckKind::UnnecessaryReturnNone => &CheckCode::RET501,
|
||||
CheckKind::ImplicitReturnValue => &CheckCode::RET502,
|
||||
CheckKind::ImplicitReturn => &CheckCode::RET503,
|
||||
CheckKind::UnnecessaryAssign => &CheckCode::RET504,
|
||||
CheckKind::SuperfluousElseReturn(_) => &CheckCode::RET505,
|
||||
CheckKind::SuperfluousElseRaise(_) => &CheckCode::RET506,
|
||||
CheckKind::SuperfluousElseContinue(_) => &CheckCode::RET507,
|
||||
CheckKind::SuperfluousElseBreak(_) => &CheckCode::RET508,
|
||||
CheckKind::SuperfluousElseReturn(..) => &CheckCode::RET505,
|
||||
CheckKind::SuperfluousElseRaise(..) => &CheckCode::RET506,
|
||||
CheckKind::SuperfluousElseContinue(..) => &CheckCode::RET507,
|
||||
CheckKind::SuperfluousElseBreak(..) => &CheckCode::RET508,
|
||||
// flake8-print
|
||||
CheckKind::PrintFound => &CheckCode::T201,
|
||||
CheckKind::PPrintFound => &CheckCode::T203,
|
||||
// flake8-quotes
|
||||
CheckKind::BadQuotesInlineString(_) => &CheckCode::Q000,
|
||||
CheckKind::BadQuotesMultilineString(_) => &CheckCode::Q001,
|
||||
CheckKind::BadQuotesDocstring(_) => &CheckCode::Q002,
|
||||
CheckKind::BadQuotesInlineString(..) => &CheckCode::Q000,
|
||||
CheckKind::BadQuotesMultilineString(..) => &CheckCode::Q001,
|
||||
CheckKind::BadQuotesDocstring(..) => &CheckCode::Q002,
|
||||
CheckKind::AvoidQuoteEscape => &CheckCode::Q003,
|
||||
// flake8-annotations
|
||||
CheckKind::MissingTypeFunctionArgument(_) => &CheckCode::ANN001,
|
||||
CheckKind::MissingTypeArgs(_) => &CheckCode::ANN002,
|
||||
CheckKind::MissingTypeKwargs(_) => &CheckCode::ANN003,
|
||||
CheckKind::MissingTypeSelf(_) => &CheckCode::ANN101,
|
||||
CheckKind::MissingTypeCls(_) => &CheckCode::ANN102,
|
||||
CheckKind::MissingReturnTypePublicFunction(_) => &CheckCode::ANN201,
|
||||
CheckKind::MissingReturnTypePrivateFunction(_) => &CheckCode::ANN202,
|
||||
CheckKind::MissingReturnTypeSpecialMethod(_) => &CheckCode::ANN204,
|
||||
CheckKind::MissingReturnTypeStaticMethod(_) => &CheckCode::ANN205,
|
||||
CheckKind::MissingReturnTypeClassMethod(_) => &CheckCode::ANN206,
|
||||
CheckKind::DynamicallyTypedExpression(_) => &CheckCode::ANN401,
|
||||
CheckKind::MissingTypeFunctionArgument(..) => &CheckCode::ANN001,
|
||||
CheckKind::MissingTypeArgs(..) => &CheckCode::ANN002,
|
||||
CheckKind::MissingTypeKwargs(..) => &CheckCode::ANN003,
|
||||
CheckKind::MissingTypeSelf(..) => &CheckCode::ANN101,
|
||||
CheckKind::MissingTypeCls(..) => &CheckCode::ANN102,
|
||||
CheckKind::MissingReturnTypePublicFunction(..) => &CheckCode::ANN201,
|
||||
CheckKind::MissingReturnTypePrivateFunction(..) => &CheckCode::ANN202,
|
||||
CheckKind::MissingReturnTypeSpecialMethod(..) => &CheckCode::ANN204,
|
||||
CheckKind::MissingReturnTypeStaticMethod(..) => &CheckCode::ANN205,
|
||||
CheckKind::MissingReturnTypeClassMethod(..) => &CheckCode::ANN206,
|
||||
CheckKind::DynamicallyTypedExpression(..) => &CheckCode::ANN401,
|
||||
// flake8-2020
|
||||
CheckKind::SysVersionSlice3Referenced => &CheckCode::YTT101,
|
||||
CheckKind::SysVersion2Referenced => &CheckCode::YTT102,
|
||||
@@ -1816,29 +1826,30 @@ impl CheckKind {
|
||||
// flake8-simplify
|
||||
CheckKind::KeyInDict(..) => &CheckCode::SIM118,
|
||||
// pyupgrade
|
||||
CheckKind::TypeOfPrimitive(_) => &CheckCode::UP003,
|
||||
CheckKind::TypeOfPrimitive(..) => &CheckCode::UP003,
|
||||
CheckKind::UselessMetaclassType => &CheckCode::UP001,
|
||||
CheckKind::DeprecatedUnittestAlias(..) => &CheckCode::UP005,
|
||||
CheckKind::UsePEP585Annotation(_) => &CheckCode::UP006,
|
||||
CheckKind::UsePEP585Annotation(..) => &CheckCode::UP006,
|
||||
CheckKind::UsePEP604Annotation => &CheckCode::UP007,
|
||||
CheckKind::UselessObjectInheritance(_) => &CheckCode::UP004,
|
||||
CheckKind::UselessObjectInheritance(..) => &CheckCode::UP004,
|
||||
CheckKind::SuperCallWithParameters => &CheckCode::UP008,
|
||||
CheckKind::PEP3120UnnecessaryCodingComment => &CheckCode::UP009,
|
||||
CheckKind::UnnecessaryFutureImport(_) => &CheckCode::UP010,
|
||||
CheckKind::UnnecessaryFutureImport(..) => &CheckCode::UP010,
|
||||
CheckKind::UnnecessaryLRUCacheParams => &CheckCode::UP011,
|
||||
CheckKind::UnnecessaryEncodeUTF8 => &CheckCode::UP012,
|
||||
CheckKind::ConvertTypedDictFunctionalToClass(_) => &CheckCode::UP013,
|
||||
CheckKind::ConvertNamedTupleFunctionalToClass(_) => &CheckCode::UP014,
|
||||
CheckKind::ConvertTypedDictFunctionalToClass(..) => &CheckCode::UP013,
|
||||
CheckKind::ConvertNamedTupleFunctionalToClass(..) => &CheckCode::UP014,
|
||||
CheckKind::RedundantOpenModes => &CheckCode::UP015,
|
||||
CheckKind::RemoveSixCompat => &CheckCode::UP016,
|
||||
CheckKind::DatetimeTimezoneUTC => &CheckCode::UP017,
|
||||
CheckKind::NativeLiterals => &CheckCode::UP018,
|
||||
// pydocstyle
|
||||
CheckKind::BlankLineAfterLastSection(_) => &CheckCode::D413,
|
||||
CheckKind::BlankLineAfterSection(_) => &CheckCode::D410,
|
||||
CheckKind::BlankLineBeforeSection(_) => &CheckCode::D411,
|
||||
CheckKind::CapitalizeSectionName(_) => &CheckCode::D405,
|
||||
CheckKind::DashedUnderlineAfterSection(_) => &CheckCode::D407,
|
||||
CheckKind::DocumentAllArguments(_) => &CheckCode::D417,
|
||||
CheckKind::BlankLineAfterLastSection(..) => &CheckCode::D413,
|
||||
CheckKind::BlankLineAfterSection(..) => &CheckCode::D410,
|
||||
CheckKind::BlankLineBeforeSection(..) => &CheckCode::D411,
|
||||
CheckKind::CapitalizeSectionName(..) => &CheckCode::D405,
|
||||
CheckKind::DashedUnderlineAfterSection(..) => &CheckCode::D407,
|
||||
CheckKind::DocumentAllArguments(..) => &CheckCode::D417,
|
||||
CheckKind::EndsInPeriod => &CheckCode::D400,
|
||||
CheckKind::EndsInPunctuation => &CheckCode::D415,
|
||||
CheckKind::FirstLineCapitalized => &CheckCode::D403,
|
||||
@@ -1848,21 +1859,21 @@ impl CheckKind {
|
||||
CheckKind::MultiLineSummaryFirstLine => &CheckCode::D212,
|
||||
CheckKind::MultiLineSummarySecondLine => &CheckCode::D213,
|
||||
CheckKind::NewLineAfterLastParagraph => &CheckCode::D209,
|
||||
CheckKind::NewLineAfterSectionName(_) => &CheckCode::D406,
|
||||
CheckKind::NoBlankLineAfterFunction(_) => &CheckCode::D202,
|
||||
CheckKind::NewLineAfterSectionName(..) => &CheckCode::D406,
|
||||
CheckKind::NoBlankLineAfterFunction(..) => &CheckCode::D202,
|
||||
CheckKind::BlankLineAfterSummary => &CheckCode::D205,
|
||||
CheckKind::NoBlankLineBeforeClass(_) => &CheckCode::D211,
|
||||
CheckKind::NoBlankLineBeforeFunction(_) => &CheckCode::D201,
|
||||
CheckKind::NoBlankLinesBetweenHeaderAndContent(_) => &CheckCode::D412,
|
||||
CheckKind::NoBlankLineBeforeClass(..) => &CheckCode::D211,
|
||||
CheckKind::NoBlankLineBeforeFunction(..) => &CheckCode::D201,
|
||||
CheckKind::NoBlankLinesBetweenHeaderAndContent(..) => &CheckCode::D412,
|
||||
CheckKind::NoOverIndentation => &CheckCode::D208,
|
||||
CheckKind::NoSignature => &CheckCode::D402,
|
||||
CheckKind::NoSurroundingWhitespace => &CheckCode::D210,
|
||||
CheckKind::NoThisPrefix => &CheckCode::D404,
|
||||
CheckKind::NoUnderIndentation => &CheckCode::D207,
|
||||
CheckKind::NonEmpty => &CheckCode::D419,
|
||||
CheckKind::NonEmptySection(_) => &CheckCode::D414,
|
||||
CheckKind::OneBlankLineAfterClass(_) => &CheckCode::D204,
|
||||
CheckKind::OneBlankLineBeforeClass(_) => &CheckCode::D203,
|
||||
CheckKind::NonEmptySection(..) => &CheckCode::D414,
|
||||
CheckKind::OneBlankLineAfterClass(..) => &CheckCode::D204,
|
||||
CheckKind::OneBlankLineBeforeClass(..) => &CheckCode::D203,
|
||||
CheckKind::PublicClass => &CheckCode::D101,
|
||||
CheckKind::PublicFunction => &CheckCode::D103,
|
||||
CheckKind::PublicInit => &CheckCode::D107,
|
||||
@@ -1870,18 +1881,18 @@ impl CheckKind {
|
||||
CheckKind::PublicModule => &CheckCode::D100,
|
||||
CheckKind::PublicNestedClass => &CheckCode::D106,
|
||||
CheckKind::PublicPackage => &CheckCode::D104,
|
||||
CheckKind::SectionNameEndsInColon(_) => &CheckCode::D416,
|
||||
CheckKind::SectionNotOverIndented(_) => &CheckCode::D214,
|
||||
CheckKind::SectionUnderlineAfterName(_) => &CheckCode::D408,
|
||||
CheckKind::SectionUnderlineMatchesSectionLength(_) => &CheckCode::D409,
|
||||
CheckKind::SectionUnderlineNotOverIndented(_) => &CheckCode::D215,
|
||||
CheckKind::SectionNameEndsInColon(..) => &CheckCode::D416,
|
||||
CheckKind::SectionNotOverIndented(..) => &CheckCode::D214,
|
||||
CheckKind::SectionUnderlineAfterName(..) => &CheckCode::D408,
|
||||
CheckKind::SectionUnderlineMatchesSectionLength(..) => &CheckCode::D409,
|
||||
CheckKind::SectionUnderlineNotOverIndented(..) => &CheckCode::D215,
|
||||
CheckKind::SkipDocstring => &CheckCode::D418,
|
||||
CheckKind::UsesRPrefixForBackslashedContent => &CheckCode::D301,
|
||||
CheckKind::UsesTripleQuotes => &CheckCode::D300,
|
||||
// pep8-naming
|
||||
CheckKind::InvalidClassName(_) => &CheckCode::N801,
|
||||
CheckKind::InvalidFunctionName(_) => &CheckCode::N802,
|
||||
CheckKind::InvalidArgumentName(_) => &CheckCode::N803,
|
||||
CheckKind::InvalidClassName(..) => &CheckCode::N801,
|
||||
CheckKind::InvalidFunctionName(..) => &CheckCode::N802,
|
||||
CheckKind::InvalidArgumentName(..) => &CheckCode::N803,
|
||||
CheckKind::InvalidFirstArgumentNameForClassMethod => &CheckCode::N804,
|
||||
CheckKind::InvalidFirstArgumentNameForMethod => &CheckCode::N805,
|
||||
CheckKind::NonLowercaseVariableInFunction(..) => &CheckCode::N806,
|
||||
@@ -1954,7 +1965,7 @@ impl CheckKind {
|
||||
CheckKind::AmbiguousUnicodeCharacterString(..) => &CheckCode::RUF001,
|
||||
CheckKind::AmbiguousUnicodeCharacterDocstring(..) => &CheckCode::RUF002,
|
||||
CheckKind::AmbiguousUnicodeCharacterComment(..) => &CheckCode::RUF003,
|
||||
CheckKind::UnusedNOQA(_) => &CheckCode::RUF100,
|
||||
CheckKind::UnusedNOQA(..) => &CheckCode::RUF100,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2555,6 +2566,7 @@ impl CheckKind {
|
||||
CheckKind::RedundantOpenModes => "Unnecessary open mode parameters".to_string(),
|
||||
CheckKind::RemoveSixCompat => "Unnecessary `six` compatibility usage".to_string(),
|
||||
CheckKind::DatetimeTimezoneUTC => "Use `datetime.UTC` alias".to_string(),
|
||||
CheckKind::NativeLiterals => "Unnecessary call to `str` and `bytes`".to_string(),
|
||||
CheckKind::ConvertTypedDictFunctionalToClass(name) => {
|
||||
format!("Convert `{name}` from `TypedDict` functional to class syntax")
|
||||
}
|
||||
@@ -2599,13 +2611,13 @@ impl CheckKind {
|
||||
CheckKind::NoBlankLineAfterFunction(num_lines) => {
|
||||
format!("No blank lines allowed after function docstring (found {num_lines})")
|
||||
}
|
||||
CheckKind::NoBlankLineBeforeClass(_) => {
|
||||
CheckKind::NoBlankLineBeforeClass(..) => {
|
||||
"No blank lines allowed before class docstring".to_string()
|
||||
}
|
||||
CheckKind::OneBlankLineBeforeClass(_) => {
|
||||
CheckKind::OneBlankLineBeforeClass(..) => {
|
||||
"1 blank line required before class docstring".to_string()
|
||||
}
|
||||
CheckKind::OneBlankLineAfterClass(_) => {
|
||||
CheckKind::OneBlankLineAfterClass(..) => {
|
||||
"1 blank line required after class docstring".to_string()
|
||||
}
|
||||
CheckKind::PublicModule => "Missing docstring in public module".to_string(),
|
||||
@@ -2851,19 +2863,44 @@ impl CheckKind {
|
||||
)
|
||||
}
|
||||
CheckKind::UnusedNOQA(codes) => match codes {
|
||||
None => "Unused `noqa` directive".to_string(),
|
||||
None => "Unused blanket `noqa` directive".to_string(),
|
||||
Some(codes) => {
|
||||
let codes = codes
|
||||
.iter()
|
||||
.map(|code| {
|
||||
if CheckCode::from_str(code).is_ok() {
|
||||
code.to_string()
|
||||
} else {
|
||||
format!("{code} (not implemented)")
|
||||
}
|
||||
})
|
||||
.join(", ");
|
||||
format!("Unused `noqa` directive for: {codes}")
|
||||
let mut codes_by_reason = vec![];
|
||||
if !codes.unmatched.is_empty() {
|
||||
codes_by_reason.push(format!(
|
||||
"unused: {}",
|
||||
codes
|
||||
.unmatched
|
||||
.iter()
|
||||
.map(|code| format!("`{code}`"))
|
||||
.join(", ")
|
||||
));
|
||||
}
|
||||
if !codes.disabled.is_empty() {
|
||||
codes_by_reason.push(format!(
|
||||
"non-enabled: {}",
|
||||
codes
|
||||
.disabled
|
||||
.iter()
|
||||
.map(|code| format!("`{code}`"))
|
||||
.join(", ")
|
||||
));
|
||||
}
|
||||
if !codes.unknown.is_empty() {
|
||||
codes_by_reason.push(format!(
|
||||
"unknown: {}",
|
||||
codes
|
||||
.unknown
|
||||
.iter()
|
||||
.map(|code| format!("`{code}`"))
|
||||
.join(", ")
|
||||
));
|
||||
}
|
||||
if codes_by_reason.is_empty() {
|
||||
"Unused `noqa` directive".to_string()
|
||||
} else {
|
||||
format!("Unused `noqa` directive ({})", codes_by_reason.join("; "))
|
||||
}
|
||||
}
|
||||
},
|
||||
// flake8-datetimez
|
||||
@@ -2956,6 +2993,7 @@ impl CheckKind {
|
||||
| CheckKind::ConvertNamedTupleFunctionalToClass(..)
|
||||
| CheckKind::ConvertTypedDictFunctionalToClass(..)
|
||||
| CheckKind::DashedUnderlineAfterSection(..)
|
||||
| CheckKind::DatetimeTimezoneUTC
|
||||
| CheckKind::DeprecatedUnittestAlias(..)
|
||||
| CheckKind::DoNotAssertFalse
|
||||
| CheckKind::DoNotAssignLambda
|
||||
@@ -2965,16 +3003,19 @@ impl CheckKind {
|
||||
| CheckKind::GetAttrWithConstant
|
||||
| CheckKind::ImplicitReturn
|
||||
| CheckKind::ImplicitReturnValue
|
||||
| CheckKind::InvalidEscapeSequence(..)
|
||||
| CheckKind::IsLiteral
|
||||
| CheckKind::KeyInDict(..)
|
||||
| CheckKind::MisplacedComparisonConstant(..)
|
||||
| CheckKind::MissingReturnTypeSpecialMethod(..)
|
||||
| CheckKind::NativeLiterals
|
||||
| CheckKind::NewLineAfterLastParagraph
|
||||
| CheckKind::NewLineAfterSectionName(..)
|
||||
| CheckKind::NoBlankLineAfterFunction(..)
|
||||
| CheckKind::NoBlankLineBeforeClass(..)
|
||||
| CheckKind::NoBlankLineBeforeFunction(..)
|
||||
| CheckKind::NoBlankLinesBetweenHeaderAndContent(..)
|
||||
| CheckKind::NoNewLineAtEndOfFile
|
||||
| CheckKind::NoOverIndentation
|
||||
| CheckKind::NoSurroundingWhitespace
|
||||
| CheckKind::NoUnderIndentation
|
||||
@@ -2991,7 +3032,6 @@ impl CheckKind {
|
||||
| CheckKind::RedundantOpenModes
|
||||
| CheckKind::RedundantTupleInExceptionHandler(..)
|
||||
| CheckKind::RemoveSixCompat
|
||||
| CheckKind::DatetimeTimezoneUTC
|
||||
| CheckKind::SectionNameEndsInColon(..)
|
||||
| CheckKind::SectionNotOverIndented(..)
|
||||
| CheckKind::SectionUnderlineAfterName(..)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! File automatically generated by `examples/generate_check_code_prefix.rs`.
|
||||
|
||||
use colored::Colorize;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum_macros::{AsRefStr, EnumString};
|
||||
|
||||
@@ -8,7 +9,17 @@ use crate::checks::CheckCode;
|
||||
use crate::one_time_warning;
|
||||
|
||||
#[derive(
|
||||
EnumString, AsRefStr, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize,
|
||||
EnumString,
|
||||
AsRefStr,
|
||||
Debug,
|
||||
PartialEq,
|
||||
Eq,
|
||||
PartialOrd,
|
||||
Ord,
|
||||
Clone,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
JsonSchema,
|
||||
)]
|
||||
pub enum CheckCodePrefix {
|
||||
A,
|
||||
@@ -513,6 +524,7 @@ pub enum CheckCodePrefix {
|
||||
UP015,
|
||||
UP016,
|
||||
UP017,
|
||||
UP018,
|
||||
W,
|
||||
W2,
|
||||
W29,
|
||||
@@ -2088,6 +2100,7 @@ impl CheckCodePrefix {
|
||||
CheckCode::UP015,
|
||||
CheckCode::UP016,
|
||||
CheckCode::UP017,
|
||||
CheckCode::UP018,
|
||||
]
|
||||
}
|
||||
CheckCodePrefix::U0 => {
|
||||
@@ -2114,6 +2127,7 @@ impl CheckCodePrefix {
|
||||
CheckCode::UP015,
|
||||
CheckCode::UP016,
|
||||
CheckCode::UP017,
|
||||
CheckCode::UP018,
|
||||
]
|
||||
}
|
||||
CheckCodePrefix::U00 => {
|
||||
@@ -2222,6 +2236,7 @@ impl CheckCodePrefix {
|
||||
CheckCode::UP015,
|
||||
CheckCode::UP016,
|
||||
CheckCode::UP017,
|
||||
CheckCode::UP018,
|
||||
]
|
||||
}
|
||||
CheckCodePrefix::U010 => {
|
||||
@@ -2313,6 +2328,7 @@ impl CheckCodePrefix {
|
||||
CheckCode::UP015,
|
||||
CheckCode::UP016,
|
||||
CheckCode::UP017,
|
||||
CheckCode::UP018,
|
||||
],
|
||||
CheckCodePrefix::UP0 => vec![
|
||||
CheckCode::UP001,
|
||||
@@ -2331,6 +2347,7 @@ impl CheckCodePrefix {
|
||||
CheckCode::UP015,
|
||||
CheckCode::UP016,
|
||||
CheckCode::UP017,
|
||||
CheckCode::UP018,
|
||||
],
|
||||
CheckCodePrefix::UP00 => vec![
|
||||
CheckCode::UP001,
|
||||
@@ -2359,6 +2376,7 @@ impl CheckCodePrefix {
|
||||
CheckCode::UP015,
|
||||
CheckCode::UP016,
|
||||
CheckCode::UP017,
|
||||
CheckCode::UP018,
|
||||
],
|
||||
CheckCodePrefix::UP010 => vec![CheckCode::UP010],
|
||||
CheckCodePrefix::UP011 => vec![CheckCode::UP011],
|
||||
@@ -2368,6 +2386,7 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::UP015 => vec![CheckCode::UP015],
|
||||
CheckCodePrefix::UP016 => vec![CheckCode::UP016],
|
||||
CheckCodePrefix::UP017 => vec![CheckCode::UP017],
|
||||
CheckCodePrefix::UP018 => vec![CheckCode::UP018],
|
||||
CheckCodePrefix::W => vec![CheckCode::W292, CheckCode::W605],
|
||||
CheckCodePrefix::W2 => vec![CheckCode::W292],
|
||||
CheckCodePrefix::W29 => vec![CheckCode::W292],
|
||||
@@ -2923,6 +2942,7 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::UP015 => SuffixLength::Three,
|
||||
CheckCodePrefix::UP016 => SuffixLength::Three,
|
||||
CheckCodePrefix::UP017 => SuffixLength::Three,
|
||||
CheckCodePrefix::UP018 => SuffixLength::Three,
|
||||
CheckCodePrefix::W => SuffixLength::Zero,
|
||||
CheckCodePrefix::W2 => SuffixLength::One,
|
||||
CheckCodePrefix::W29 => SuffixLength::Two,
|
||||
|
||||
@@ -133,6 +133,9 @@ pub struct Cli {
|
||||
/// Generate shell completion
|
||||
#[arg(long, hide = true, value_name = "SHELL")]
|
||||
pub generate_shell_completion: Option<clap_complete_command::Shell>,
|
||||
/// Path to the cache directory.
|
||||
#[arg(long)]
|
||||
pub cache_dir: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl Cli {
|
||||
@@ -180,6 +183,7 @@ impl Cli {
|
||||
fix: resolve_bool_arg(self.fix, self.no_fix),
|
||||
format: self.format,
|
||||
force_exclude: resolve_bool_arg(self.force_exclude, self.no_force_exclude),
|
||||
cache_dir: self.cache_dir,
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -238,6 +242,7 @@ pub struct Overrides {
|
||||
pub fix: Option<bool>,
|
||||
pub format: Option<SerializationFormat>,
|
||||
pub force_exclude: Option<bool>,
|
||||
pub cache_dir: Option<PathBuf>,
|
||||
}
|
||||
|
||||
/// Map the CLI settings to a `LogLevel`.
|
||||
|
||||
@@ -20,7 +20,7 @@ use crate::message::Message;
|
||||
use crate::resolver::{FileDiscovery, PyprojectDiscovery};
|
||||
use crate::settings::flags;
|
||||
use crate::settings::types::SerializationFormat;
|
||||
use crate::{packages, resolver};
|
||||
use crate::{cache, packages, resolver};
|
||||
|
||||
/// Run the linter over a collection of files.
|
||||
pub fn run(
|
||||
@@ -47,6 +47,30 @@ pub fn run(
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
// Initialize the cache.
|
||||
if matches!(cache, flags::Cache::Enabled) {
|
||||
match &pyproject_strategy {
|
||||
PyprojectDiscovery::Fixed(settings) => {
|
||||
if let Err(e) = cache::init(&settings.cache_dir) {
|
||||
error!(
|
||||
"Failed to initialize cache at {}: {e:?}",
|
||||
settings.cache_dir.to_string_lossy()
|
||||
);
|
||||
}
|
||||
}
|
||||
PyprojectDiscovery::Hierarchical(default) => {
|
||||
for settings in std::iter::once(default).chain(resolver.iter()) {
|
||||
if let Err(e) = cache::init(&settings.cache_dir) {
|
||||
error!(
|
||||
"Failed to initialize cache at {}: {e:?}",
|
||||
settings.cache_dir.to_string_lossy()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let start = Instant::now();
|
||||
let mut diagnostics: Diagnostics = par_iter(&paths)
|
||||
.map(|entry| {
|
||||
|
||||
@@ -1,51 +1,53 @@
|
||||
//! Settings for the `flake-annotations` plugin.
|
||||
|
||||
use ruff_macros::ConfigurationOptions;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, JsonSchema,
|
||||
)]
|
||||
#[serde(
|
||||
deny_unknown_fields,
|
||||
rename_all = "kebab-case",
|
||||
rename = "Flake8AnnotationsOptions"
|
||||
)]
|
||||
pub struct Options {
|
||||
#[option(
|
||||
doc = r#"
|
||||
Whether to allow the omission of a return type hint for `__init__` if at least one
|
||||
argument is annotated.
|
||||
"#,
|
||||
default = "false",
|
||||
value_type = "bool",
|
||||
example = "mypy-init-return = true"
|
||||
)]
|
||||
/// Whether to allow the omission of a return type hint for `__init__` if at
|
||||
/// least one argument is annotated.
|
||||
pub mypy_init_return: Option<bool>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
Whether to suppress `ANN000`-level errors for arguments matching the "dummy" variable
|
||||
regex (like `_`).
|
||||
"#,
|
||||
default = "false",
|
||||
value_type = "bool",
|
||||
example = "suppress-dummy-args = true"
|
||||
)]
|
||||
/// Whether to suppress `ANN000`-level errors for arguments matching the
|
||||
/// "dummy" variable regex (like `_`).
|
||||
pub suppress_dummy_args: Option<bool>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
Whether to suppress `ANN200`-level errors for functions that meet either of the
|
||||
following criteria:
|
||||
|
||||
- Contain no `return` statement.
|
||||
- Explicit `return` statement(s) all return `None` (explicitly or implicitly).
|
||||
"#,
|
||||
default = "false",
|
||||
value_type = "bool",
|
||||
example = "suppress-none-returning = true"
|
||||
)]
|
||||
/// Whether to suppress `ANN200`-level errors for functions that meet either
|
||||
/// of the following criteria:
|
||||
///
|
||||
/// - Contain no `return` statement.
|
||||
/// - Explicit `return` statement(s) all return `None` (explicitly or
|
||||
/// implicitly).
|
||||
pub suppress_none_returning: Option<bool>,
|
||||
#[option(
|
||||
doc = "Whether to suppress `ANN401` for dynamically typed `*args` and `**kwargs` \
|
||||
arguments.",
|
||||
default = "false",
|
||||
value_type = "bool",
|
||||
example = "allow-star-arg-any = true"
|
||||
)]
|
||||
/// Whether to suppress `ANN401` for dynamically typed `*args` and
|
||||
/// `**kwargs` arguments.
|
||||
pub allow_star_arg_any: Option<bool>,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use itertools::Itertools;
|
||||
use rustc_hash::FxHashSet;
|
||||
use rustpython_ast::{
|
||||
Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind, Location, Stmt,
|
||||
};
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use rustpython_ast::{Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind, Location};
|
||||
|
||||
use crate::ast::helpers;
|
||||
use crate::ast::types::Range;
|
||||
@@ -26,17 +24,17 @@ fn duplicate_handler_exceptions<'a>(
|
||||
checker: &mut Checker,
|
||||
expr: &'a Expr,
|
||||
elts: &'a [Expr],
|
||||
) -> FxHashSet<Vec<&'a str>> {
|
||||
let mut seen: FxHashSet<Vec<&str>> = FxHashSet::default();
|
||||
) -> FxHashMap<Vec<&'a str>, &'a Expr> {
|
||||
let mut seen: FxHashMap<Vec<&str>, &Expr> = FxHashMap::default();
|
||||
let mut duplicates: FxHashSet<Vec<&str>> = FxHashSet::default();
|
||||
let mut unique_elts: Vec<&Expr> = Vec::default();
|
||||
for type_ in elts {
|
||||
let call_path = helpers::collect_call_paths(type_);
|
||||
if !call_path.is_empty() {
|
||||
if seen.contains(&call_path) {
|
||||
if seen.contains_key(&call_path) {
|
||||
duplicates.insert(call_path);
|
||||
} else {
|
||||
seen.insert(call_path);
|
||||
seen.entry(call_path).or_insert(type_);
|
||||
unique_elts.push(type_);
|
||||
}
|
||||
}
|
||||
@@ -77,9 +75,9 @@ fn duplicate_handler_exceptions<'a>(
|
||||
seen
|
||||
}
|
||||
|
||||
pub fn duplicate_exceptions(checker: &mut Checker, stmt: &Stmt, handlers: &[Excepthandler]) {
|
||||
pub fn duplicate_exceptions(checker: &mut Checker, handlers: &[Excepthandler]) {
|
||||
let mut seen: FxHashSet<Vec<&str>> = FxHashSet::default();
|
||||
let mut duplicates: FxHashSet<Vec<&str>> = FxHashSet::default();
|
||||
let mut duplicates: FxHashMap<Vec<&str>, Vec<&Expr>> = FxHashMap::default();
|
||||
for handler in handlers {
|
||||
let ExcepthandlerKind::ExceptHandler { type_: Some(type_), .. } = &handler.node else {
|
||||
continue;
|
||||
@@ -89,16 +87,16 @@ pub fn duplicate_exceptions(checker: &mut Checker, stmt: &Stmt, handlers: &[Exce
|
||||
let call_path = helpers::collect_call_paths(type_);
|
||||
if !call_path.is_empty() {
|
||||
if seen.contains(&call_path) {
|
||||
duplicates.insert(call_path);
|
||||
duplicates.entry(call_path).or_default().push(type_);
|
||||
} else {
|
||||
seen.insert(call_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
ExprKind::Tuple { elts, .. } => {
|
||||
for name in duplicate_handler_exceptions(checker, type_, elts) {
|
||||
for (name, expr) in duplicate_handler_exceptions(checker, type_, elts) {
|
||||
if seen.contains(&name) {
|
||||
duplicates.insert(name);
|
||||
duplicates.entry(name).or_default().push(expr);
|
||||
} else {
|
||||
seen.insert(name);
|
||||
}
|
||||
@@ -109,11 +107,13 @@ pub fn duplicate_exceptions(checker: &mut Checker, stmt: &Stmt, handlers: &[Exce
|
||||
}
|
||||
|
||||
if checker.settings.enabled.contains(&CheckCode::B025) {
|
||||
for duplicate in duplicates.into_iter().sorted() {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::DuplicateTryBlockException(duplicate.join(".")),
|
||||
Range::from_located(stmt),
|
||||
));
|
||||
for (name, exprs) in duplicates {
|
||||
for expr in exprs {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::DuplicateTryBlockException(name.join(".")),
|
||||
Range::from_located(expr),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
//! Settings for the `flake8-bugbear` plugin.
|
||||
|
||||
use ruff_macros::ConfigurationOptions;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, JsonSchema,
|
||||
)]
|
||||
#[serde(
|
||||
deny_unknown_fields,
|
||||
rename_all = "kebab-case",
|
||||
rename = "Flake8BugbearOptions"
|
||||
)]
|
||||
pub struct Options {
|
||||
#[option(
|
||||
doc = r#"
|
||||
Additional callable functions to consider "immutable" when evaluating, e.g.,
|
||||
`no-mutable-default-argument` checks (`B006`).
|
||||
"#,
|
||||
default = r#"[]"#,
|
||||
value_type = "Vec<String>",
|
||||
example = r#"
|
||||
@@ -18,6 +21,8 @@ pub struct Options {
|
||||
extend-immutable-calls = ["fastapi.Depends", "fastapi.Query"]
|
||||
"#
|
||||
)]
|
||||
/// Additional callable functions to consider "immutable" when evaluating,
|
||||
/// e.g., `no-mutable-default-argument` checks (`B006`).
|
||||
pub extend_immutable_calls: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
|
||||
@@ -5,37 +5,37 @@ expression: checks
|
||||
- kind:
|
||||
DuplicateTryBlockException: ValueError
|
||||
location:
|
||||
row: 15
|
||||
column: 0
|
||||
row: 19
|
||||
column: 7
|
||||
end_location:
|
||||
row: 20
|
||||
column: 9
|
||||
row: 19
|
||||
column: 17
|
||||
fix: ~
|
||||
- kind:
|
||||
DuplicateTryBlockException: pickle.PickleError
|
||||
location:
|
||||
row: 22
|
||||
column: 0
|
||||
row: 28
|
||||
column: 7
|
||||
end_location:
|
||||
row: 29
|
||||
column: 9
|
||||
fix: ~
|
||||
- kind:
|
||||
DuplicateTryBlockException: TypeError
|
||||
location:
|
||||
row: 31
|
||||
column: 0
|
||||
end_location:
|
||||
row: 38
|
||||
column: 9
|
||||
row: 28
|
||||
column: 25
|
||||
fix: ~
|
||||
- kind:
|
||||
DuplicateTryBlockException: ValueError
|
||||
location:
|
||||
row: 31
|
||||
column: 0
|
||||
row: 35
|
||||
column: 7
|
||||
end_location:
|
||||
row: 38
|
||||
column: 9
|
||||
row: 35
|
||||
column: 17
|
||||
fix: ~
|
||||
- kind:
|
||||
DuplicateTryBlockException: TypeError
|
||||
location:
|
||||
row: 37
|
||||
column: 17
|
||||
end_location:
|
||||
row: 37
|
||||
column: 26
|
||||
fix: ~
|
||||
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
use rustpython_ast::{Constant, Expr, ExprKind};
|
||||
|
||||
use crate::ast::types::Range;
|
||||
use crate::checks::{Check, CheckKind};
|
||||
|
||||
pub fn check_string_in_exception(exc: &Expr, max_string_length: usize) -> Vec<Check> {
|
||||
let mut checks = vec![];
|
||||
|
||||
if let ExprKind::Call { args, .. } = &exc.node {
|
||||
if let Some(first) = args.first() {
|
||||
match &first.node {
|
||||
// Check for string literals
|
||||
ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} => {
|
||||
if string.len() > max_string_length {
|
||||
checks.push(Check::new(
|
||||
CheckKind::RawStringInException,
|
||||
Range::from_located(first),
|
||||
));
|
||||
}
|
||||
}
|
||||
// Check for f-strings
|
||||
ExprKind::JoinedStr { .. } => checks.push(Check::new(
|
||||
CheckKind::FStringInException,
|
||||
Range::from_located(first),
|
||||
)),
|
||||
// Check for .format() calls
|
||||
ExprKind::Call { func, .. } => {
|
||||
if let ExprKind::Attribute { value, attr, .. } = &func.node {
|
||||
if attr == "format" && matches!(value.node, ExprKind::Constant { .. }) {
|
||||
checks.push(Check::new(
|
||||
CheckKind::DotFormatInException,
|
||||
Range::from_located(first),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checks
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
pub mod checks;
|
||||
pub mod plugins;
|
||||
pub mod settings;
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
52
src/flake8_errmsg/plugins.rs
Normal file
52
src/flake8_errmsg/plugins.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
use rustpython_ast::{Constant, Expr, ExprKind};
|
||||
|
||||
use crate::ast::types::Range;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::checks::{Check, CheckCode, CheckKind};
|
||||
|
||||
/// EM101, EM102, EM103
|
||||
pub fn string_in_exception(checker: &mut Checker, exc: &Expr) {
|
||||
if let ExprKind::Call { args, .. } = &exc.node {
|
||||
if let Some(first) = args.first() {
|
||||
match &first.node {
|
||||
// Check for string literals
|
||||
ExprKind::Constant {
|
||||
value: Constant::Str(string),
|
||||
..
|
||||
} => {
|
||||
if checker.settings.enabled.contains(&CheckCode::EM101) {
|
||||
if string.len() > checker.settings.flake8_errmsg.max_string_length {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::RawStringInException,
|
||||
Range::from_located(first),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check for f-strings
|
||||
ExprKind::JoinedStr { .. } => {
|
||||
if checker.settings.enabled.contains(&CheckCode::EM102) {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::FStringInException,
|
||||
Range::from_located(first),
|
||||
));
|
||||
}
|
||||
}
|
||||
// Check for .format() calls
|
||||
ExprKind::Call { func, .. } => {
|
||||
if checker.settings.enabled.contains(&CheckCode::EM103) {
|
||||
if let ExprKind::Attribute { value, attr, .. } = &func.node {
|
||||
if attr == "format" && matches!(value.node, ExprKind::Constant { .. }) {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::DotFormatInException,
|
||||
Range::from_located(first),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,24 @@
|
||||
//! Settings for the `flake8-errmsg` plugin.
|
||||
|
||||
use ruff_macros::ConfigurationOptions;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, JsonSchema,
|
||||
)]
|
||||
#[serde(
|
||||
deny_unknown_fields,
|
||||
rename_all = "kebab-case",
|
||||
rename = "Flake8ErrMsgOptions"
|
||||
)]
|
||||
pub struct Options {
|
||||
#[option(
|
||||
doc = r#"
|
||||
Maximum string length for string literals in exception messages.
|
||||
"#,
|
||||
default = "0",
|
||||
value_type = "usize",
|
||||
example = "max-string-length = 20"
|
||||
)]
|
||||
/// Maximum string length for string literals in exception messages.
|
||||
pub max_string_length: Option<usize>,
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ use std::hash::{Hash, Hasher};
|
||||
use itertools::Itertools;
|
||||
use ruff_macros::ConfigurationOptions;
|
||||
use rustc_hash::FxHashMap;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
const CONVENTIONAL_ALIASES: &[(&str, &str)] = &[
|
||||
@@ -15,12 +16,16 @@ const CONVENTIONAL_ALIASES: &[(&str, &str)] = &[
|
||||
("seaborn", "sns"),
|
||||
];
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, JsonSchema,
|
||||
)]
|
||||
#[serde(
|
||||
deny_unknown_fields,
|
||||
rename_all = "kebab-case",
|
||||
rename = "Flake8ImportConventionsOptions"
|
||||
)]
|
||||
pub struct Options {
|
||||
#[option(
|
||||
doc = "The conventional aliases for imports. These aliases can be extended by the \
|
||||
`extend_aliases` option.",
|
||||
default = r#"{"altair": "alt", "matplotlib.pyplot": "plt", "numpy": "np", "pandas": "pd", "seaborn": "sns"}"#,
|
||||
value_type = "FxHashMap<String, String>",
|
||||
example = r#"
|
||||
@@ -32,10 +37,10 @@ pub struct Options {
|
||||
seaborn = "sns"
|
||||
"#
|
||||
)]
|
||||
/// The conventional aliases for imports. These aliases can be extended by
|
||||
/// the `extend_aliases` option.
|
||||
pub aliases: Option<FxHashMap<String, String>>,
|
||||
#[option(
|
||||
doc = "A mapping of modules to their conventional import aliases. These aliases will be \
|
||||
added to the `aliases` mapping.",
|
||||
default = r#"{}"#,
|
||||
value_type = "FxHashMap<String, String>",
|
||||
example = r#"
|
||||
@@ -43,6 +48,8 @@ pub struct Options {
|
||||
"dask.dataframe" = "dd"
|
||||
"#
|
||||
)]
|
||||
/// A mapping of modules to their conventional import aliases. These aliases
|
||||
/// will be added to the `aliases` mapping.
|
||||
pub extend_aliases: Option<FxHashMap<String, String>>,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,57 +1,56 @@
|
||||
//! Settings for the `flake8-quotes` plugin.
|
||||
|
||||
use ruff_macros::ConfigurationOptions;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, JsonSchema)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
pub enum Quote {
|
||||
Single,
|
||||
Double,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, JsonSchema,
|
||||
)]
|
||||
#[serde(
|
||||
deny_unknown_fields,
|
||||
rename_all = "kebab-case",
|
||||
rename = "Flake8QuotesOptions"
|
||||
)]
|
||||
pub struct Options {
|
||||
#[option(
|
||||
doc = r#"
|
||||
Quote style to prefer for inline strings (either "single" (`'`) or "double" (`"`)).
|
||||
"#,
|
||||
default = r#""double""#,
|
||||
value_type = "Quote",
|
||||
example = r#"
|
||||
inline-quotes = "single"
|
||||
"#
|
||||
)]
|
||||
/// Quote style to prefer for inline strings (either "single" (`'`) or
|
||||
/// "double" (`"`)).
|
||||
pub inline_quotes: Option<Quote>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
Quote style to prefer for multiline strings (either "single" (`'`) or "double" (`"`)).
|
||||
"#,
|
||||
default = r#""double""#,
|
||||
value_type = "Quote",
|
||||
example = r#"
|
||||
multiline-quotes = "single"
|
||||
"#
|
||||
)]
|
||||
/// Quote style to prefer for multiline strings (either "single" (`'`) or
|
||||
/// "double" (`"`)).
|
||||
pub multiline_quotes: Option<Quote>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
Quote style to prefer for docstrings (either "single" (`'`) or "double" (`"`)).
|
||||
"#,
|
||||
default = r#""double""#,
|
||||
value_type = "Quote",
|
||||
example = r#"
|
||||
docstring-quotes = "single"
|
||||
"#
|
||||
)]
|
||||
/// Quote style to prefer for docstrings (either "single" (`'`) or "double"
|
||||
/// (`"`)).
|
||||
pub docstring_quotes: Option<Quote>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
Whether to avoid using single quotes if a string contains single quotes, or vice-versa
|
||||
with double quotes, as per [PEP8](https://peps.python.org/pep-0008/#string-quotes).
|
||||
This minimizes the need to escape quotation marks within strings.
|
||||
"#,
|
||||
default = r#"true"#,
|
||||
value_type = "bool",
|
||||
example = r#"
|
||||
@@ -59,6 +58,9 @@ pub struct Options {
|
||||
avoid-escape = false
|
||||
"#
|
||||
)]
|
||||
/// Whether to avoid using single quotes if a string contains single quotes,
|
||||
/// or vice-versa with double quotes, as per [PEP8](https://peps.python.org/pep-0008/#string-quotes).
|
||||
/// This minimizes the need to escape quotation marks within strings.
|
||||
pub avoid_escape: Option<bool>,
|
||||
}
|
||||
|
||||
|
||||
@@ -203,6 +203,10 @@ fn unnecessary_assign(checker: &mut Checker, stack: &Stack, expr: &Expr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if stack.non_locals.contains(id.as_str()) {
|
||||
return;
|
||||
}
|
||||
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::UnnecessaryAssign,
|
||||
Range::from_located(expr),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use rustc_hash::FxHashMap;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use rustpython_ast::{Expr, ExprKind, Location, Stmt, StmtKind};
|
||||
|
||||
use crate::ast::visitor;
|
||||
@@ -10,6 +10,7 @@ pub struct Stack<'a> {
|
||||
pub ifs: Vec<&'a Stmt>,
|
||||
pub elifs: Vec<&'a Stmt>,
|
||||
pub refs: FxHashMap<&'a str, Vec<Location>>,
|
||||
pub non_locals: FxHashSet<&'a str>,
|
||||
pub assigns: FxHashMap<&'a str, Vec<Location>>,
|
||||
pub loops: Vec<(Location, Location)>,
|
||||
pub tries: Vec<(Location, Location)>,
|
||||
@@ -48,6 +49,11 @@ impl<'a> ReturnVisitor<'a> {
|
||||
impl<'a> Visitor<'a> for ReturnVisitor<'a> {
|
||||
fn visit_stmt(&mut self, stmt: &'a Stmt) {
|
||||
match &stmt.node {
|
||||
StmtKind::Global { names } | StmtKind::Nonlocal { names } => {
|
||||
self.stack
|
||||
.non_locals
|
||||
.extend(names.iter().map(std::string::String::as_str));
|
||||
}
|
||||
StmtKind::FunctionDef { .. } | StmtKind::AsyncFunctionDef { .. } => {
|
||||
// Don't recurse.
|
||||
}
|
||||
|
||||
@@ -1,23 +1,26 @@
|
||||
//! Settings for the `flake8-tidy-imports` plugin.
|
||||
|
||||
use ruff_macros::ConfigurationOptions;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, JsonSchema)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
pub enum Strictness {
|
||||
Parents,
|
||||
All,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, JsonSchema,
|
||||
)]
|
||||
#[serde(
|
||||
deny_unknown_fields,
|
||||
rename_all = "kebab-case",
|
||||
rename = "Flake8TidyImportsOptions"
|
||||
)]
|
||||
pub struct Options {
|
||||
#[option(
|
||||
doc = r#"
|
||||
Whether to ban all relative imports (`"all"`), or only those imports that extend into
|
||||
the parent module and beyond (`"parents"`).
|
||||
"#,
|
||||
default = r#""parents""#,
|
||||
value_type = "Strictness",
|
||||
example = r#"
|
||||
@@ -25,6 +28,8 @@ pub struct Options {
|
||||
ban-relative-imports = "all"
|
||||
"#
|
||||
)]
|
||||
/// Whether to ban all relative imports (`"all"`), or only those imports
|
||||
/// that extend into the parent module and beyond (`"parents"`).
|
||||
pub ban_relative_imports: Option<Strictness>,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
//! Settings for the `flake8-unused-arguments` plugin.
|
||||
|
||||
use ruff_macros::ConfigurationOptions;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, JsonSchema,
|
||||
)]
|
||||
#[serde(
|
||||
deny_unknown_fields,
|
||||
rename_all = "kebab-case",
|
||||
rename = "Flake8UnusedArgumentsOptions"
|
||||
)]
|
||||
pub struct Options {
|
||||
#[option(
|
||||
doc = r#"
|
||||
Whether to allow unused variadic arguments, like `*args` and `**kwargs`.
|
||||
"#,
|
||||
default = "false",
|
||||
value_type = "bool",
|
||||
example = "ignore-variadic-names = true"
|
||||
)]
|
||||
/// Whether to allow unused variadic arguments, like `*args` and `**kwargs`.
|
||||
pub ignore_variadic_names: Option<bool>,
|
||||
}
|
||||
|
||||
|
||||
@@ -3,40 +3,19 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use ruff_macros::ConfigurationOptions;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, JsonSchema,
|
||||
)]
|
||||
#[serde(
|
||||
deny_unknown_fields,
|
||||
rename_all = "kebab-case",
|
||||
rename = "IsortOptions"
|
||||
)]
|
||||
pub struct Options {
|
||||
#[option(
|
||||
doc = r#"
|
||||
Combines as imports on the same line. See isort's [`combine-as-imports`](https://pycqa.github.io/isort/docs/configuration/options.html#combine-as-imports)
|
||||
option.
|
||||
"#,
|
||||
default = r#"false"#,
|
||||
value_type = "bool",
|
||||
example = r#"
|
||||
combine-as-imports = true
|
||||
"#
|
||||
)]
|
||||
pub combine_as_imports: Option<bool>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
Force `import from` statements with multiple members and at least one alias (e.g.,
|
||||
`import A as B`) to wrap such that every line contains exactly one member. For example,
|
||||
this formatting would be retained, rather than condensing to a single line:
|
||||
|
||||
```py
|
||||
from .utils import (
|
||||
test_directory as test_directory,
|
||||
test_id as test_id
|
||||
)
|
||||
```
|
||||
|
||||
Note that this setting is only effective when combined with `combine-as-imports = true`.
|
||||
When `combine-as-imports` isn't enabled, every aliased `import from` will be given its
|
||||
own line, in which case, wrapping is not necessary.
|
||||
"#,
|
||||
default = r#"false"#,
|
||||
value_type = "bool",
|
||||
example = r#"
|
||||
@@ -44,42 +23,62 @@ pub struct Options {
|
||||
combine-as-imports = true
|
||||
"#
|
||||
)]
|
||||
/// Force `import from` statements with multiple members and at least one
|
||||
/// alias (e.g., `import A as B`) to wrap such that every line contains
|
||||
/// exactly one member. For example, this formatting would be retained,
|
||||
/// rather than condensing to a single line:
|
||||
///
|
||||
/// ```py
|
||||
/// from .utils import (
|
||||
/// test_directory as test_directory,
|
||||
/// test_id as test_id
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// Note that this setting is only effective when combined with
|
||||
/// `combine-as-imports = true`. When `combine-as-imports` isn't
|
||||
/// enabled, every aliased `import from` will be given its own line, in
|
||||
/// which case, wrapping is not necessary.
|
||||
pub force_wrap_aliases: Option<bool>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
A list of modules to consider first-party, regardless of whether they can be identified
|
||||
as such via introspection of the local filesystem.
|
||||
"#,
|
||||
default = r#"false"#,
|
||||
value_type = "bool",
|
||||
example = r#"
|
||||
combine-as-imports = true
|
||||
"#
|
||||
)]
|
||||
/// Combines as imports on the same line. See isort's [`combine-as-imports`](https://pycqa.github.io/isort/docs/configuration/options.html#combine-as-imports)
|
||||
/// option.
|
||||
pub combine_as_imports: Option<bool>,
|
||||
#[option(
|
||||
default = r#"[]"#,
|
||||
value_type = "Vec<String>",
|
||||
example = r#"
|
||||
known-first-party = ["src"]
|
||||
"#
|
||||
)]
|
||||
/// A list of modules to consider first-party, regardless of whether they
|
||||
/// can be identified as such via introspection of the local filesystem.
|
||||
pub known_first_party: Option<Vec<String>>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
A list of modules to consider third-party, regardless of whether they can be identified
|
||||
as such via introspection of the local filesystem.
|
||||
"#,
|
||||
default = r#"[]"#,
|
||||
value_type = "Vec<String>",
|
||||
example = r#"
|
||||
known-third-party = ["src"]
|
||||
"#
|
||||
)]
|
||||
/// A list of modules to consider third-party, regardless of whether they
|
||||
/// can be identified as such via introspection of the local filesystem.
|
||||
pub known_third_party: Option<Vec<String>>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
A list of modules to consider standard-library, in addition to those known to Ruff in
|
||||
advance.
|
||||
"#,
|
||||
default = r#"[]"#,
|
||||
value_type = "Vec<String>",
|
||||
example = r#"
|
||||
extra-standard-library = ["path"]
|
||||
"#
|
||||
)]
|
||||
/// A list of modules to consider standard-library, in addition to those
|
||||
/// known to Ruff in advance.
|
||||
pub extra_standard_library: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
|
||||
16
src/main.rs
16
src/main.rs
@@ -18,6 +18,7 @@ use std::sync::mpsc::channel;
|
||||
|
||||
use ::ruff::autofix::fixer;
|
||||
use ::ruff::cli::{extract_log_level, Cli, Overrides};
|
||||
use ::ruff::commands;
|
||||
use ::ruff::logging::{set_up_logging, LogLevel};
|
||||
use ::ruff::printer::Printer;
|
||||
use ::ruff::resolver::{resolve_settings, FileDiscovery, PyprojectDiscovery, Relativity};
|
||||
@@ -26,7 +27,6 @@ use ::ruff::settings::types::SerializationFormat;
|
||||
use ::ruff::settings::{pyproject, Settings};
|
||||
#[cfg(feature = "update-informer")]
|
||||
use ::ruff::updates;
|
||||
use ::ruff::{cache, commands};
|
||||
use anyhow::Result;
|
||||
use clap::{CommandFactory, Parser};
|
||||
use colored::Colorize;
|
||||
@@ -123,6 +123,7 @@ fn inner_main() -> Result<ExitCode> {
|
||||
} else {
|
||||
fixer::Mode::None
|
||||
};
|
||||
let cache = !cli.no_cache;
|
||||
|
||||
if let Some(code) = cli.explain {
|
||||
commands::explain(&code, &format)?;
|
||||
@@ -137,13 +138,6 @@ fn inner_main() -> Result<ExitCode> {
|
||||
return Ok(ExitCode::SUCCESS);
|
||||
}
|
||||
|
||||
// Initialize the cache.
|
||||
let mut cache_enabled: bool = !cli.no_cache;
|
||||
if cache_enabled && cache::init().is_err() {
|
||||
eprintln!("Unable to initialize cache; disabling...");
|
||||
cache_enabled = false;
|
||||
}
|
||||
|
||||
let printer = Printer::new(&format, &log_level);
|
||||
if cli.watch {
|
||||
if matches!(autofix, fixer::Mode::Generate | fixer::Mode::Apply) {
|
||||
@@ -168,7 +162,7 @@ fn inner_main() -> Result<ExitCode> {
|
||||
&pyproject_strategy,
|
||||
&file_strategy,
|
||||
&overrides,
|
||||
cache_enabled.into(),
|
||||
cache.into(),
|
||||
fixer::Mode::None,
|
||||
)?;
|
||||
printer.write_continuously(&messages)?;
|
||||
@@ -198,7 +192,7 @@ fn inner_main() -> Result<ExitCode> {
|
||||
&pyproject_strategy,
|
||||
&file_strategy,
|
||||
&overrides,
|
||||
cache_enabled.into(),
|
||||
cache.into(),
|
||||
fixer::Mode::None,
|
||||
)?;
|
||||
printer.write_continuously(&messages)?;
|
||||
@@ -237,7 +231,7 @@ fn inner_main() -> Result<ExitCode> {
|
||||
&pyproject_strategy,
|
||||
&file_strategy,
|
||||
&overrides,
|
||||
cache_enabled.into(),
|
||||
cache.into(),
|
||||
autofix,
|
||||
)?
|
||||
};
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
//! Settings for the `mccabe` plugin.
|
||||
|
||||
use ruff_macros::ConfigurationOptions;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, JsonSchema,
|
||||
)]
|
||||
#[serde(
|
||||
deny_unknown_fields,
|
||||
rename_all = "kebab-case",
|
||||
rename = "McCabeOptions"
|
||||
)]
|
||||
pub struct Options {
|
||||
#[option(
|
||||
doc = "The maximum McCabe complexity to allow before triggering `C901` errors.",
|
||||
default = "10",
|
||||
value_type = "usize",
|
||||
example = r#"
|
||||
@@ -15,6 +21,7 @@ pub struct Options {
|
||||
max-complexity = 5
|
||||
"#
|
||||
)]
|
||||
/// The maximum McCabe complexity to allow before triggering `C901` errors.
|
||||
pub max_complexity: Option<usize>,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! Settings for the `pep8-naming` plugin.
|
||||
|
||||
use ruff_macros::ConfigurationOptions;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
const IGNORE_NAMES: [&str; 12] = [
|
||||
@@ -22,26 +23,25 @@ const CLASSMETHOD_DECORATORS: [&str; 1] = ["classmethod"];
|
||||
|
||||
const STATICMETHOD_DECORATORS: [&str; 1] = ["staticmethod"];
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, JsonSchema,
|
||||
)]
|
||||
#[serde(
|
||||
deny_unknown_fields,
|
||||
rename_all = "kebab-case",
|
||||
rename = "Pep8NamingOptions"
|
||||
)]
|
||||
pub struct Options {
|
||||
#[option(
|
||||
doc = r#"
|
||||
A list of names to ignore when considering `pep8-naming` violations.
|
||||
"#,
|
||||
default = r#"["setUp", "tearDown", "setUpClass", "tearDownClass", "setUpModule", "tearDownModule", "asyncSetUp", "asyncTearDown", "setUpTestData", "failureException", "longMessage", "maxDiff"]"#,
|
||||
value_type = "Vec<String>",
|
||||
example = r#"
|
||||
ignore-names = ["callMethod"]
|
||||
"#
|
||||
)]
|
||||
/// A list of names to ignore when considering `pep8-naming` violations.
|
||||
pub ignore_names: Option<Vec<String>>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
A list of decorators that, when applied to a method, indicate that the method should be
|
||||
treated as a class method. For example, Ruff will expect that any method decorated by a
|
||||
decorator in this list takes a `cls` argument as its first argument.
|
||||
"#,
|
||||
default = r#"["classmethod"]"#,
|
||||
value_type = "Vec<String>",
|
||||
example = r#"
|
||||
@@ -49,13 +49,12 @@ pub struct Options {
|
||||
classmethod-decorators = ["classmethod", "pydantic.validator"]
|
||||
"#
|
||||
)]
|
||||
/// A list of decorators that, when applied to a method, indicate that the
|
||||
/// method should be treated as a class method. For example, Ruff will
|
||||
/// expect that any method decorated by a decorator in this list takes a
|
||||
/// `cls` argument as its first argument.
|
||||
pub classmethod_decorators: Option<Vec<String>>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
A list of decorators that, when applied to a method, indicate that the method should be
|
||||
treated as a static method. For example, Ruff will expect that any method decorated by a
|
||||
decorator in this list has no `self` or `cls` argument.
|
||||
"#,
|
||||
default = r#"["staticmethod"]"#,
|
||||
value_type = "Vec<String>",
|
||||
example = r#"
|
||||
@@ -63,6 +62,10 @@ pub struct Options {
|
||||
staticmethod-decorators = ["staticmethod", "stcmthd"]
|
||||
"#
|
||||
)]
|
||||
/// A list of decorators that, when applied to a method, indicate that the
|
||||
/// method should be treated as a static method. For example, Ruff will
|
||||
/// expect that any method decorated by a decorator in this list has no
|
||||
/// `self` or `cls` argument.
|
||||
pub staticmethod_decorators: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use itertools::izip;
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use rustpython_ast::{Located, Location, Stmt, StmtKind};
|
||||
use rustpython_ast::{Constant, Located, Location, Stmt, StmtKind};
|
||||
use rustpython_parser::ast::{Cmpop, Expr, ExprKind};
|
||||
|
||||
use crate::ast::types::Range;
|
||||
use crate::autofix::Fix;
|
||||
use crate::checks::{Check, CheckKind};
|
||||
use crate::source_code_locator::SourceCodeLocator;
|
||||
|
||||
@@ -54,7 +55,14 @@ pub fn type_comparison(ops: &[Cmpop], comparators: &[Expr], location: Range) ->
|
||||
if id == "type" {
|
||||
if let Some(arg) = args.first() {
|
||||
// Allow comparison for types which are not obvious.
|
||||
if !matches!(arg.node, ExprKind::Name { .. }) {
|
||||
if !matches!(
|
||||
arg.node,
|
||||
ExprKind::Name { .. }
|
||||
| ExprKind::Constant {
|
||||
value: Constant::None,
|
||||
kind: None
|
||||
}
|
||||
) {
|
||||
checks.push(Check::new(CheckKind::TypeComparison, location));
|
||||
}
|
||||
}
|
||||
@@ -134,18 +142,24 @@ pub fn ambiguous_function_name(name: &str, location: Range) -> Option<Check> {
|
||||
}
|
||||
|
||||
/// W292
|
||||
pub fn no_newline_at_end_of_file(contents: &str) -> Option<Check> {
|
||||
pub fn no_newline_at_end_of_file(contents: &str, autofix: bool) -> Option<Check> {
|
||||
if !contents.ends_with('\n') {
|
||||
// Note: if `lines.last()` is `None`, then `contents` is empty (and so we don't
|
||||
// want to raise W292 anyway).
|
||||
if let Some(line) = contents.lines().last() {
|
||||
return Some(Check::new(
|
||||
// Both locations are at the end of the file (and thus the same).
|
||||
let location = Location::new(contents.lines().count(), line.len());
|
||||
let mut check = Check::new(
|
||||
CheckKind::NoNewLineAtEndOfFile,
|
||||
Range {
|
||||
location: Location::new(contents.lines().count(), line.len() + 1),
|
||||
end_location: Location::new(contents.lines().count(), line.len() + 1),
|
||||
location,
|
||||
end_location: location,
|
||||
},
|
||||
));
|
||||
);
|
||||
if autofix {
|
||||
check.amend(Fix::insertion("\n".to_string(), location));
|
||||
}
|
||||
return Some(check);
|
||||
}
|
||||
}
|
||||
None
|
||||
@@ -174,6 +188,7 @@ pub fn invalid_escape_sequence(
|
||||
locator: &SourceCodeLocator,
|
||||
start: Location,
|
||||
end: Location,
|
||||
autofix: bool,
|
||||
) -> Vec<Check> {
|
||||
let mut checks = vec![];
|
||||
|
||||
@@ -221,13 +236,17 @@ pub fn invalid_escape_sequence(
|
||||
};
|
||||
let location = Location::new(start.row() + row_offset, col);
|
||||
let end_location = Location::new(location.row(), location.column() + 2);
|
||||
checks.push(Check::new(
|
||||
let mut check = Check::new(
|
||||
CheckKind::InvalidEscapeSequence(next_char),
|
||||
Range {
|
||||
location,
|
||||
end_location,
|
||||
},
|
||||
));
|
||||
);
|
||||
if autofix {
|
||||
check.amend(Fix::insertion(r"\".to_string(), location));
|
||||
}
|
||||
checks.push(check);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ mod tests {
|
||||
#[test_case(CheckCode::W292, Path::new("W292_0.py"))]
|
||||
#[test_case(CheckCode::W292, Path::new("W292_1.py"))]
|
||||
#[test_case(CheckCode::W292, Path::new("W292_2.py"))]
|
||||
#[test_case(CheckCode::W292, Path::new("W292_3.py"))]
|
||||
#[test_case(CheckCode::W292, Path::new("W292_4.py"))]
|
||||
#[test_case(CheckCode::W605, Path::new("W605_0.py"))]
|
||||
#[test_case(CheckCode::W605, Path::new("W605_1.py"))]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
|
||||
@@ -42,14 +42,6 @@ expression: checks
|
||||
row: 18
|
||||
column: 31
|
||||
fix: ~
|
||||
- kind: TypeComparison
|
||||
location:
|
||||
row: 18
|
||||
column: 35
|
||||
end_location:
|
||||
row: 18
|
||||
column: 58
|
||||
fix: ~
|
||||
- kind: TypeComparison
|
||||
location:
|
||||
row: 20
|
||||
|
||||
@@ -5,9 +5,16 @@ expression: checks
|
||||
- kind: NoNewLineAtEndOfFile
|
||||
location:
|
||||
row: 2
|
||||
column: 9
|
||||
column: 8
|
||||
end_location:
|
||||
row: 2
|
||||
column: 9
|
||||
fix: ~
|
||||
column: 8
|
||||
fix:
|
||||
content: "\n"
|
||||
location:
|
||||
row: 2
|
||||
column: 8
|
||||
end_location:
|
||||
row: 2
|
||||
column: 8
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
source: src/pycodestyle/mod.rs
|
||||
expression: checks
|
||||
---
|
||||
[]
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
source: src/pycodestyle/mod.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind: NoNewLineAtEndOfFile
|
||||
location:
|
||||
row: 1
|
||||
column: 1
|
||||
end_location:
|
||||
row: 1
|
||||
column: 1
|
||||
fix:
|
||||
content: "\n"
|
||||
location:
|
||||
row: 1
|
||||
column: 1
|
||||
end_location:
|
||||
row: 1
|
||||
column: 1
|
||||
|
||||
@@ -10,7 +10,14 @@ expression: checks
|
||||
end_location:
|
||||
row: 2
|
||||
column: 11
|
||||
fix: ~
|
||||
fix:
|
||||
content: "\\"
|
||||
location:
|
||||
row: 2
|
||||
column: 9
|
||||
end_location:
|
||||
row: 2
|
||||
column: 9
|
||||
- kind:
|
||||
InvalidEscapeSequence: "."
|
||||
location:
|
||||
@@ -19,7 +26,14 @@ expression: checks
|
||||
end_location:
|
||||
row: 6
|
||||
column: 2
|
||||
fix: ~
|
||||
fix:
|
||||
content: "\\"
|
||||
location:
|
||||
row: 6
|
||||
column: 0
|
||||
end_location:
|
||||
row: 6
|
||||
column: 0
|
||||
- kind:
|
||||
InvalidEscapeSequence: _
|
||||
location:
|
||||
@@ -28,7 +42,14 @@ expression: checks
|
||||
end_location:
|
||||
row: 11
|
||||
column: 7
|
||||
fix: ~
|
||||
fix:
|
||||
content: "\\"
|
||||
location:
|
||||
row: 11
|
||||
column: 5
|
||||
end_location:
|
||||
row: 11
|
||||
column: 5
|
||||
- kind:
|
||||
InvalidEscapeSequence: _
|
||||
location:
|
||||
@@ -37,5 +58,12 @@ expression: checks
|
||||
end_location:
|
||||
row: 18
|
||||
column: 7
|
||||
fix: ~
|
||||
fix:
|
||||
content: "\\"
|
||||
location:
|
||||
row: 18
|
||||
column: 5
|
||||
end_location:
|
||||
row: 18
|
||||
column: 5
|
||||
|
||||
|
||||
@@ -10,7 +10,14 @@ expression: checks
|
||||
end_location:
|
||||
row: 2
|
||||
column: 11
|
||||
fix: ~
|
||||
fix:
|
||||
content: "\\"
|
||||
location:
|
||||
row: 2
|
||||
column: 9
|
||||
end_location:
|
||||
row: 2
|
||||
column: 9
|
||||
- kind:
|
||||
InvalidEscapeSequence: "."
|
||||
location:
|
||||
@@ -19,7 +26,14 @@ expression: checks
|
||||
end_location:
|
||||
row: 6
|
||||
column: 2
|
||||
fix: ~
|
||||
fix:
|
||||
content: "\\"
|
||||
location:
|
||||
row: 6
|
||||
column: 0
|
||||
end_location:
|
||||
row: 6
|
||||
column: 0
|
||||
- kind:
|
||||
InvalidEscapeSequence: _
|
||||
location:
|
||||
@@ -28,7 +42,14 @@ expression: checks
|
||||
end_location:
|
||||
row: 11
|
||||
column: 7
|
||||
fix: ~
|
||||
fix:
|
||||
content: "\\"
|
||||
location:
|
||||
row: 11
|
||||
column: 5
|
||||
end_location:
|
||||
row: 11
|
||||
column: 5
|
||||
- kind:
|
||||
InvalidEscapeSequence: _
|
||||
location:
|
||||
@@ -37,5 +58,12 @@ expression: checks
|
||||
end_location:
|
||||
row: 18
|
||||
column: 7
|
||||
fix: ~
|
||||
fix:
|
||||
content: "\\"
|
||||
location:
|
||||
row: 18
|
||||
column: 5
|
||||
end_location:
|
||||
row: 18
|
||||
column: 5
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ expression: checks
|
||||
PercentFormatInvalidFormat: incomplete format
|
||||
location:
|
||||
row: 1
|
||||
column: 9
|
||||
column: 0
|
||||
end_location:
|
||||
row: 1
|
||||
column: 25
|
||||
|
||||
@@ -5,7 +5,7 @@ expression: checks
|
||||
- kind: PercentFormatExpectedMapping
|
||||
location:
|
||||
row: 6
|
||||
column: 10
|
||||
column: 0
|
||||
end_location:
|
||||
row: 6
|
||||
column: 19
|
||||
@@ -13,7 +13,7 @@ expression: checks
|
||||
- kind: PercentFormatExpectedMapping
|
||||
location:
|
||||
row: 7
|
||||
column: 10
|
||||
column: 0
|
||||
end_location:
|
||||
row: 7
|
||||
column: 20
|
||||
@@ -21,7 +21,7 @@ expression: checks
|
||||
- kind: PercentFormatExpectedMapping
|
||||
location:
|
||||
row: 8
|
||||
column: 10
|
||||
column: 0
|
||||
end_location:
|
||||
row: 8
|
||||
column: 19
|
||||
@@ -29,7 +29,7 @@ expression: checks
|
||||
- kind: PercentFormatExpectedMapping
|
||||
location:
|
||||
row: 9
|
||||
column: 10
|
||||
column: 0
|
||||
end_location:
|
||||
row: 9
|
||||
column: 22
|
||||
@@ -37,7 +37,7 @@ expression: checks
|
||||
- kind: PercentFormatExpectedMapping
|
||||
location:
|
||||
row: 11
|
||||
column: 10
|
||||
column: 0
|
||||
end_location:
|
||||
row: 11
|
||||
column: 37
|
||||
@@ -45,7 +45,7 @@ expression: checks
|
||||
- kind: PercentFormatExpectedMapping
|
||||
location:
|
||||
row: 12
|
||||
column: 10
|
||||
column: 0
|
||||
end_location:
|
||||
row: 12
|
||||
column: 37
|
||||
@@ -53,7 +53,7 @@ expression: checks
|
||||
- kind: PercentFormatExpectedMapping
|
||||
location:
|
||||
row: 13
|
||||
column: 10
|
||||
column: 0
|
||||
end_location:
|
||||
row: 13
|
||||
column: 37
|
||||
|
||||
@@ -5,7 +5,7 @@ expression: checks
|
||||
- kind: PercentFormatExpectedMapping
|
||||
location:
|
||||
row: 9
|
||||
column: 10
|
||||
column: 0
|
||||
end_location:
|
||||
row: 9
|
||||
column: 21
|
||||
|
||||
@@ -5,7 +5,7 @@ expression: checks
|
||||
- kind: PercentFormatExpectedSequence
|
||||
location:
|
||||
row: 17
|
||||
column: 8
|
||||
column: 0
|
||||
end_location:
|
||||
row: 17
|
||||
column: 24
|
||||
@@ -13,7 +13,7 @@ expression: checks
|
||||
- kind: PercentFormatExpectedSequence
|
||||
location:
|
||||
row: 18
|
||||
column: 8
|
||||
column: 0
|
||||
end_location:
|
||||
row: 18
|
||||
column: 28
|
||||
@@ -21,7 +21,7 @@ expression: checks
|
||||
- kind: PercentFormatExpectedSequence
|
||||
location:
|
||||
row: 23
|
||||
column: 8
|
||||
column: 0
|
||||
end_location:
|
||||
row: 23
|
||||
column: 42
|
||||
|
||||
@@ -5,7 +5,7 @@ expression: checks
|
||||
- kind: PercentFormatExpectedSequence
|
||||
location:
|
||||
row: 10
|
||||
column: 8
|
||||
column: 0
|
||||
end_location:
|
||||
row: 10
|
||||
column: 20
|
||||
|
||||
@@ -7,7 +7,7 @@ expression: checks
|
||||
- b
|
||||
location:
|
||||
row: 3
|
||||
column: 14
|
||||
column: 0
|
||||
end_location:
|
||||
row: 3
|
||||
column: 34
|
||||
@@ -24,7 +24,7 @@ expression: checks
|
||||
- b
|
||||
location:
|
||||
row: 8
|
||||
column: 8
|
||||
column: 0
|
||||
end_location:
|
||||
row: 8
|
||||
column: 29
|
||||
@@ -41,7 +41,7 @@ expression: checks
|
||||
- b
|
||||
location:
|
||||
row: 9
|
||||
column: 8
|
||||
column: 0
|
||||
end_location:
|
||||
row: 9
|
||||
column: 29
|
||||
|
||||
@@ -7,7 +7,7 @@ expression: checks
|
||||
- baz
|
||||
location:
|
||||
row: 8
|
||||
column: 10
|
||||
column: 0
|
||||
end_location:
|
||||
row: 8
|
||||
column: 32
|
||||
|
||||
@@ -7,7 +7,7 @@ expression: checks
|
||||
- bar
|
||||
location:
|
||||
row: 7
|
||||
column: 10
|
||||
column: 0
|
||||
end_location:
|
||||
row: 7
|
||||
column: 14
|
||||
|
||||
@@ -5,7 +5,7 @@ expression: checks
|
||||
- kind: PercentFormatMixedPositionalAndNamed
|
||||
location:
|
||||
row: 2
|
||||
column: 13
|
||||
column: 0
|
||||
end_location:
|
||||
row: 2
|
||||
column: 29
|
||||
@@ -13,7 +13,7 @@ expression: checks
|
||||
- kind: PercentFormatMixedPositionalAndNamed
|
||||
location:
|
||||
row: 3
|
||||
column: 13
|
||||
column: 0
|
||||
end_location:
|
||||
row: 3
|
||||
column: 29
|
||||
@@ -21,7 +21,7 @@ expression: checks
|
||||
- kind: PercentFormatMixedPositionalAndNamed
|
||||
location:
|
||||
row: 11
|
||||
column: 11
|
||||
column: 0
|
||||
end_location:
|
||||
row: 11
|
||||
column: 27
|
||||
|
||||
@@ -8,7 +8,7 @@ expression: checks
|
||||
- 1
|
||||
location:
|
||||
row: 5
|
||||
column: 8
|
||||
column: 0
|
||||
end_location:
|
||||
row: 5
|
||||
column: 14
|
||||
@@ -19,7 +19,7 @@ expression: checks
|
||||
- 3
|
||||
location:
|
||||
row: 6
|
||||
column: 8
|
||||
column: 0
|
||||
end_location:
|
||||
row: 6
|
||||
column: 19
|
||||
|
||||
@@ -5,7 +5,7 @@ expression: checks
|
||||
- kind: PercentFormatStarRequiresSequence
|
||||
location:
|
||||
row: 11
|
||||
column: 11
|
||||
column: 0
|
||||
end_location:
|
||||
row: 11
|
||||
column: 27
|
||||
|
||||
@@ -6,7 +6,7 @@ expression: checks
|
||||
PercentFormatUnsupportedFormatCharacter: j
|
||||
location:
|
||||
row: 4
|
||||
column: 5
|
||||
column: 0
|
||||
end_location:
|
||||
row: 4
|
||||
column: 11
|
||||
|
||||
@@ -37,6 +37,7 @@ mod tests {
|
||||
#[test_case(CheckCode::UP014, Path::new("UP014.py"); "UP014")]
|
||||
#[test_case(CheckCode::UP015, Path::new("UP015.py"); "UP015")]
|
||||
#[test_case(CheckCode::UP016, Path::new("UP016.py"); "UP016")]
|
||||
#[test_case(CheckCode::UP018, Path::new("UP018.py"); "UP018")]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
|
||||
@@ -2,6 +2,7 @@ pub use convert_named_tuple_functional_to_class::convert_named_tuple_functional_
|
||||
pub use convert_typed_dict_functional_to_class::convert_typed_dict_functional_to_class;
|
||||
pub use datetime_utc_alias::datetime_utc_alias;
|
||||
pub use deprecated_unittest_alias::deprecated_unittest_alias;
|
||||
pub use native_literals::native_literals;
|
||||
pub use redundant_open_modes::redundant_open_modes;
|
||||
pub use remove_six_compat::remove_six_compat;
|
||||
pub use super_call_with_parameters::super_call_with_parameters;
|
||||
@@ -18,6 +19,7 @@ mod convert_named_tuple_functional_to_class;
|
||||
mod convert_typed_dict_functional_to_class;
|
||||
mod datetime_utc_alias;
|
||||
mod deprecated_unittest_alias;
|
||||
mod native_literals;
|
||||
mod redundant_open_modes;
|
||||
mod remove_six_compat;
|
||||
mod super_call_with_parameters;
|
||||
|
||||
73
src/pyupgrade/plugins/native_literals.rs
Normal file
73
src/pyupgrade/plugins/native_literals.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
use rustpython_ast::{Constant, Expr, ExprKind, Keyword};
|
||||
use rustpython_parser::lexer;
|
||||
use rustpython_parser::lexer::Tok;
|
||||
|
||||
use crate::ast::types::Range;
|
||||
use crate::autofix::Fix;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::checks::{Check, CheckCode, CheckKind};
|
||||
|
||||
/// UP018
|
||||
pub fn native_literals(
|
||||
checker: &mut Checker,
|
||||
expr: &Expr,
|
||||
func: &Expr,
|
||||
args: &[Expr],
|
||||
keywords: &[Keyword],
|
||||
) {
|
||||
let ExprKind::Name { id, .. } = &func.node else { return; };
|
||||
|
||||
if (id == "str" || id == "bytes")
|
||||
&& keywords.is_empty()
|
||||
&& args.len() <= 1
|
||||
&& checker.is_builtin(id)
|
||||
{
|
||||
let Some(arg) = args.get(0) else {
|
||||
let mut check = Check::new(CheckKind::NativeLiterals, Range::from_located(expr));
|
||||
if checker.patch(&CheckCode::UP018) {
|
||||
check.amend(Fix::replacement(
|
||||
format!("{}\"\"", if id == "bytes" { "b" } else { "" }),
|
||||
expr.location,
|
||||
expr.end_location.unwrap(),
|
||||
));
|
||||
}
|
||||
checker.add_check(check);
|
||||
return;
|
||||
};
|
||||
|
||||
if !matches!(
|
||||
&arg.node,
|
||||
ExprKind::Constant {
|
||||
value: Constant::Str(_) | Constant::Bytes(_),
|
||||
..
|
||||
}
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// rust-python merges adjacent string/bytes literals into one node, but we can't
|
||||
// safely remove the outer call in this situation. We're following pyupgrade
|
||||
// here and skip.
|
||||
let arg_code = checker
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(arg));
|
||||
if lexer::make_tokenizer(&arg_code)
|
||||
.flatten()
|
||||
.filter(|(_, tok, _)| matches!(tok, Tok::String { .. } | Tok::Bytes { .. }))
|
||||
.count()
|
||||
> 1
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let mut check = Check::new(CheckKind::NativeLiterals, Range::from_located(expr));
|
||||
if checker.patch(&CheckCode::UP018) {
|
||||
check.amend(Fix::replacement(
|
||||
arg_code.to_string(),
|
||||
expr.location,
|
||||
expr.end_location.unwrap(),
|
||||
));
|
||||
}
|
||||
checker.add_check(check);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,19 @@
|
||||
//! Settings for the `pyupgrade` plugin.
|
||||
|
||||
use ruff_macros::ConfigurationOptions;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, JsonSchema,
|
||||
)]
|
||||
#[serde(
|
||||
deny_unknown_fields,
|
||||
rename_all = "kebab-case",
|
||||
rename = "PyUpgradeOptions"
|
||||
)]
|
||||
pub struct Options {
|
||||
#[option(
|
||||
doc = r#"
|
||||
Whether to avoid PEP 585 (`List[int]` -> `list[int]`) and PEP 604 (`Optional[str]` -> `str | None`) rewrites even if a file imports `from __future__ import annotations`. Note that this setting is only applicable when the target Python version is below 3.9 and 3.10 respectively.
|
||||
"#,
|
||||
default = r#"false"#,
|
||||
value_type = "bool",
|
||||
example = r#"
|
||||
@@ -17,6 +21,11 @@ pub struct Options {
|
||||
keep-runtime-typing = true
|
||||
"#
|
||||
)]
|
||||
/// Whether to avoid PEP 585 (`List[int]` -> `list[int]`) and PEP 604
|
||||
/// (`Optional[str]` -> `str | None`) rewrites even if a file imports `from
|
||||
/// __future__ import annotations`. Note that this setting is only
|
||||
/// applicable when the target Python version is below 3.9 and 3.10
|
||||
/// respectively.
|
||||
pub keep_runtime_typing: Option<bool>,
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
---
|
||||
source: src/pyupgrade/mod.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind: NativeLiterals
|
||||
location:
|
||||
row: 18
|
||||
column: 0
|
||||
end_location:
|
||||
row: 18
|
||||
column: 5
|
||||
fix:
|
||||
content: "\"\""
|
||||
location:
|
||||
row: 18
|
||||
column: 0
|
||||
end_location:
|
||||
row: 18
|
||||
column: 5
|
||||
- kind: NativeLiterals
|
||||
location:
|
||||
row: 19
|
||||
column: 0
|
||||
end_location:
|
||||
row: 19
|
||||
column: 10
|
||||
fix:
|
||||
content: "\"foo\""
|
||||
location:
|
||||
row: 19
|
||||
column: 0
|
||||
end_location:
|
||||
row: 19
|
||||
column: 10
|
||||
- kind: NativeLiterals
|
||||
location:
|
||||
row: 20
|
||||
column: 0
|
||||
end_location:
|
||||
row: 21
|
||||
column: 7
|
||||
fix:
|
||||
content: "\"\"\"\nfoo\"\"\""
|
||||
location:
|
||||
row: 20
|
||||
column: 0
|
||||
end_location:
|
||||
row: 21
|
||||
column: 7
|
||||
- kind: NativeLiterals
|
||||
location:
|
||||
row: 22
|
||||
column: 0
|
||||
end_location:
|
||||
row: 22
|
||||
column: 7
|
||||
fix:
|
||||
content: "b\"\""
|
||||
location:
|
||||
row: 22
|
||||
column: 0
|
||||
end_location:
|
||||
row: 22
|
||||
column: 7
|
||||
- kind: NativeLiterals
|
||||
location:
|
||||
row: 23
|
||||
column: 0
|
||||
end_location:
|
||||
row: 23
|
||||
column: 13
|
||||
fix:
|
||||
content: "b\"foo\""
|
||||
location:
|
||||
row: 23
|
||||
column: 0
|
||||
end_location:
|
||||
row: 23
|
||||
column: 13
|
||||
- kind: NativeLiterals
|
||||
location:
|
||||
row: 24
|
||||
column: 0
|
||||
end_location:
|
||||
row: 25
|
||||
column: 7
|
||||
fix:
|
||||
content: "b\"\"\"\nfoo\"\"\""
|
||||
location:
|
||||
row: 24
|
||||
column: 0
|
||||
end_location:
|
||||
row: 25
|
||||
column: 7
|
||||
|
||||
@@ -86,6 +86,11 @@ impl Resolver {
|
||||
.unwrap_or(default),
|
||||
}
|
||||
}
|
||||
|
||||
/// Return an iterator over the resolved `Settings` in this `Resolver`.
|
||||
pub fn iter(&self) -> impl Iterator<Item = &Settings> {
|
||||
self.settings.values()
|
||||
}
|
||||
}
|
||||
|
||||
/// Recursively resolve a `Configuration` from a `pyproject.toml` file at the
|
||||
|
||||
@@ -20,7 +20,10 @@ expression: checks
|
||||
column: 17
|
||||
- kind:
|
||||
UnusedNOQA:
|
||||
- E501
|
||||
unknown: []
|
||||
disabled: []
|
||||
unmatched:
|
||||
- E501
|
||||
location:
|
||||
row: 13
|
||||
column: 11
|
||||
@@ -37,8 +40,11 @@ expression: checks
|
||||
column: 23
|
||||
- kind:
|
||||
UnusedNOQA:
|
||||
- F841
|
||||
- E501
|
||||
unknown: []
|
||||
disabled: []
|
||||
unmatched:
|
||||
- F841
|
||||
- E501
|
||||
location:
|
||||
row: 16
|
||||
column: 11
|
||||
@@ -55,14 +61,18 @@ expression: checks
|
||||
column: 29
|
||||
- kind:
|
||||
UnusedNOQA:
|
||||
- F841
|
||||
- W191
|
||||
unknown:
|
||||
- W191
|
||||
disabled:
|
||||
- F821
|
||||
unmatched:
|
||||
- F841
|
||||
location:
|
||||
row: 19
|
||||
column: 11
|
||||
end_location:
|
||||
row: 19
|
||||
column: 29
|
||||
column: 35
|
||||
fix:
|
||||
content: ""
|
||||
location:
|
||||
@@ -70,11 +80,14 @@ expression: checks
|
||||
column: 9
|
||||
end_location:
|
||||
row: 19
|
||||
column: 29
|
||||
column: 35
|
||||
- kind:
|
||||
UnusedNOQA:
|
||||
- F841
|
||||
- V101
|
||||
unknown:
|
||||
- V101
|
||||
disabled: []
|
||||
unmatched:
|
||||
- F841
|
||||
location:
|
||||
row: 22
|
||||
column: 11
|
||||
@@ -91,7 +104,10 @@ expression: checks
|
||||
column: 29
|
||||
- kind:
|
||||
UnusedNOQA:
|
||||
- E501
|
||||
unknown: []
|
||||
disabled: []
|
||||
unmatched:
|
||||
- E501
|
||||
location:
|
||||
row: 26
|
||||
column: 9
|
||||
@@ -117,7 +133,10 @@ expression: checks
|
||||
fix: ~
|
||||
- kind:
|
||||
UnusedNOQA:
|
||||
- E501
|
||||
unknown: []
|
||||
disabled: []
|
||||
unmatched:
|
||||
- E501
|
||||
location:
|
||||
row: 29
|
||||
column: 32
|
||||
@@ -134,7 +153,10 @@ expression: checks
|
||||
column: 44
|
||||
- kind:
|
||||
UnusedNOQA:
|
||||
- F841
|
||||
unknown: []
|
||||
disabled: []
|
||||
unmatched:
|
||||
- F841
|
||||
location:
|
||||
row: 55
|
||||
column: 5
|
||||
@@ -151,7 +173,10 @@ expression: checks
|
||||
column: 23
|
||||
- kind:
|
||||
UnusedNOQA:
|
||||
- E501
|
||||
unknown: []
|
||||
disabled: []
|
||||
unmatched:
|
||||
- E501
|
||||
location:
|
||||
row: 63
|
||||
column: 5
|
||||
|
||||
@@ -46,6 +46,7 @@ pub struct Configuration {
|
||||
pub src: Option<Vec<PathBuf>>,
|
||||
pub target_version: Option<PythonVersion>,
|
||||
pub unfixable: Option<Vec<CheckCodePrefix>>,
|
||||
pub cache_dir: Option<PathBuf>,
|
||||
// Plugins
|
||||
pub flake8_annotations: Option<flake8_annotations::settings::Options>,
|
||||
pub flake8_bugbear: Option<flake8_bugbear::settings::Options>,
|
||||
@@ -130,6 +131,14 @@ impl Configuration {
|
||||
.transpose()?,
|
||||
target_version: options.target_version,
|
||||
unfixable: options.unfixable,
|
||||
cache_dir: options
|
||||
.cache_dir
|
||||
.map(|dir| {
|
||||
let dir = shellexpand::full(&dir);
|
||||
dir.map(|dir| PathBuf::from(dir.as_ref()))
|
||||
})
|
||||
.transpose()
|
||||
.map_err(|e| anyhow!("Invalid `cache-dir` value: {e}"))?,
|
||||
// Plugins
|
||||
flake8_annotations: options.flake8_annotations,
|
||||
flake8_bugbear: options.flake8_bugbear,
|
||||
@@ -184,6 +193,7 @@ impl Configuration {
|
||||
src: self.src.or(config.src),
|
||||
target_version: self.target_version.or(config.target_version),
|
||||
unfixable: self.unfixable.or(config.unfixable),
|
||||
cache_dir: self.cache_dir.or(config.cache_dir),
|
||||
// Plugins
|
||||
flake8_annotations: self.flake8_annotations.or(config.flake8_annotations),
|
||||
flake8_bugbear: self.flake8_bugbear.or(config.flake8_bugbear),
|
||||
@@ -254,6 +264,9 @@ impl Configuration {
|
||||
if let Some(unfixable) = overrides.unfixable {
|
||||
self.unfixable = Some(unfixable);
|
||||
}
|
||||
if let Some(cache_dir) = overrides.cache_dir {
|
||||
self.cache_dir = Some(cache_dir);
|
||||
}
|
||||
// Special-case: `extend_ignore` and `extend_select` are parallel arrays, so
|
||||
// push an empty array if only one of the two is provided.
|
||||
match (overrides.extend_ignore, overrides.extend_select) {
|
||||
|
||||
@@ -13,6 +13,7 @@ use path_absolutize::path_dedot;
|
||||
use regex::Regex;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
use crate::cache::cache_dir;
|
||||
use crate::checks::CheckCode;
|
||||
use crate::checks_gen::{CheckCodePrefix, SuffixLength, CATEGORIES};
|
||||
use crate::settings::configuration::Configuration;
|
||||
@@ -49,6 +50,7 @@ pub struct Settings {
|
||||
pub show_source: bool,
|
||||
pub src: Vec<PathBuf>,
|
||||
pub target_version: PythonVersion,
|
||||
pub cache_dir: PathBuf,
|
||||
// Plugins
|
||||
pub flake8_annotations: flake8_annotations::settings::Settings,
|
||||
pub flake8_bugbear: flake8_bugbear::settings::Settings,
|
||||
@@ -140,6 +142,7 @@ impl Settings {
|
||||
.unwrap_or_else(|| vec![project_root.to_path_buf()]),
|
||||
target_version: config.target_version.unwrap_or(PythonVersion::Py310),
|
||||
show_source: config.show_source.unwrap_or_default(),
|
||||
cache_dir: config.cache_dir.unwrap_or_else(|| cache_dir(project_root)),
|
||||
// Plugins
|
||||
flake8_annotations: config
|
||||
.flake8_annotations
|
||||
@@ -209,6 +212,7 @@ impl Settings {
|
||||
show_source: false,
|
||||
src: vec![path_dedot::CWD.clone()],
|
||||
target_version: PythonVersion::Py310,
|
||||
cache_dir: cache_dir(path_dedot::CWD.as_path()),
|
||||
flake8_annotations: flake8_annotations::settings::Settings::default(),
|
||||
flake8_bugbear: flake8_bugbear::settings::Settings::default(),
|
||||
flake8_errmsg: flake8_errmsg::settings::Settings::default(),
|
||||
@@ -242,6 +246,7 @@ impl Settings {
|
||||
show_source: false,
|
||||
src: vec![path_dedot::CWD.clone()],
|
||||
target_version: PythonVersion::Py310,
|
||||
cache_dir: cache_dir(path_dedot::CWD.as_path()),
|
||||
flake8_annotations: flake8_annotations::settings::Settings::default(),
|
||||
flake8_bugbear: flake8_bugbear::settings::Settings::default(),
|
||||
flake8_errmsg: flake8_errmsg::settings::Settings::default(),
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
use ruff_macros::ConfigurationOptions;
|
||||
use rustc_hash::FxHashMap;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::checks_gen::CheckCodePrefix;
|
||||
@@ -11,14 +12,12 @@ use crate::{
|
||||
flake8_tidy_imports, flake8_unused_arguments, isort, mccabe, pep8_naming, pyupgrade,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions)]
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, Serialize, Deserialize, Default, ConfigurationOptions, JsonSchema,
|
||||
)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
pub struct Options {
|
||||
#[option(
|
||||
doc = r#"
|
||||
A list of allowed "confusable" Unicode characters to ignore when enforcing `RUF001`,
|
||||
`RUF002`, and `RUF003`.
|
||||
"#,
|
||||
default = r#"[]"#,
|
||||
value_type = "Vec<char>",
|
||||
example = r#"
|
||||
@@ -27,13 +26,10 @@ pub struct Options {
|
||||
allowed-confusables = ["−", "ρ", "∗"]
|
||||
"#
|
||||
)]
|
||||
/// A list of allowed "confusable" Unicode characters to ignore when
|
||||
/// enforcing `RUF001`, `RUF002`, and `RUF003`.
|
||||
pub allowed_confusables: Option<Vec<char>>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
A regular expression used to identify "dummy" variables, or those which should be
|
||||
ignored when evaluating (e.g.) unused-variable checks. The default expression matches
|
||||
`_`, `__`, and `_var`, but not `_var_`.
|
||||
"#,
|
||||
default = r#""^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$""#,
|
||||
value_type = "Regex",
|
||||
example = r#"
|
||||
@@ -41,39 +37,33 @@ pub struct Options {
|
||||
dummy-variable-rgx = "^_$"
|
||||
"#
|
||||
)]
|
||||
/// A regular expression used to identify "dummy" variables, or those which
|
||||
/// should be ignored when evaluating (e.g.) unused-variable checks. The
|
||||
/// default expression matches `_`, `__`, and `_var`, but not `_var_`.
|
||||
pub dummy_variable_rgx: Option<String>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
A list of file patterns to exclude from linting.
|
||||
|
||||
Exclusions are based on globs, and can be either:
|
||||
|
||||
- Single-path patterns, like `.mypy_cache` (to exclude any directory named `.mypy_cache` in the
|
||||
tree), `foo.py` (to exclude any file named `foo.py`), or `foo_*.py` (to exclude any file matching
|
||||
`foo_*.py` ).
|
||||
- Relative patterns, like `directory/foo.py` (to exclude that specific file) or `directory/*.py`
|
||||
(to exclude any Python files in `directory`). Note that these paths are relative to the
|
||||
project root (e.g., the directory containing your `pyproject.toml`).
|
||||
|
||||
Note that you'll typically want to use [`extend-exclude`](#extend-exclude) to modify
|
||||
the excluded paths.
|
||||
"#,
|
||||
default = r#"[".bzr", ".direnv", ".eggs", ".git", ".hg", ".mypy_cache", ".nox", ".pants.d", ".ruff_cache", ".svn", ".tox", ".venv", "__pypackages__", "_build", "buck-out", "build", "dist", "node_modules", "venv"]"#,
|
||||
value_type = "Vec<FilePattern>",
|
||||
example = r#"
|
||||
exclude = [".venv"]
|
||||
"#
|
||||
)]
|
||||
/// A list of file patterns to exclude from linting.
|
||||
///
|
||||
/// Exclusions are based on globs, and can be either:
|
||||
///
|
||||
/// - Single-path patterns, like `.mypy_cache` (to exclude any directory
|
||||
/// named `.mypy_cache` in the tree), `foo.py` (to exclude any file named
|
||||
/// `foo.py`), or `foo_*.py` (to exclude any file matching `foo_*.py` ).
|
||||
/// - Relative patterns, like `directory/foo.py` (to exclude that specific
|
||||
/// file) or `directory/*.py` (to exclude any Python files in
|
||||
/// `directory`). Note that these paths are relative to the project root
|
||||
/// (e.g., the directory containing your `pyproject.toml`).
|
||||
///
|
||||
/// Note that you'll typically want to use
|
||||
/// [`extend-exclude`](#extend-exclude) to modify the excluded paths.
|
||||
pub exclude: Option<Vec<String>>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
A path to a local `pyproject.toml` file to merge into this configuration. User home
|
||||
directory and environment variables will be expanded.
|
||||
|
||||
To resolve the current `pyproject.toml` file, Ruff will first resolve this base
|
||||
configuration file, then merge in any properties defined in the current configuration
|
||||
file.
|
||||
"#,
|
||||
default = r#"None"#,
|
||||
value_type = "Path",
|
||||
example = r#"
|
||||
@@ -83,10 +73,15 @@ pub struct Options {
|
||||
line-length = 100
|
||||
"#
|
||||
)]
|
||||
/// A path to a local `pyproject.toml` file to merge into this
|
||||
/// configuration. User home directory and environment variables will be
|
||||
/// expanded.
|
||||
///
|
||||
/// To resolve the current `pyproject.toml` file, Ruff will first resolve
|
||||
/// this base configuration file, then merge in any properties defined
|
||||
/// in the current configuration file.
|
||||
pub extend: Option<String>,
|
||||
#[option(
|
||||
doc = "A list of file patterns to omit from linting, in addition to those specified by \
|
||||
`exclude`.",
|
||||
default = "[]",
|
||||
value_type = "Vec<FilePattern>",
|
||||
example = r#"
|
||||
@@ -94,10 +89,10 @@ pub struct Options {
|
||||
extend-exclude = ["tests", "src/bad.py"]
|
||||
"#
|
||||
)]
|
||||
/// A list of file patterns to omit from linting, in addition to those
|
||||
/// specified by `exclude`.
|
||||
pub extend_exclude: Option<Vec<String>>,
|
||||
#[option(
|
||||
doc = "A list of check code prefixes to ignore, in addition to those specified by \
|
||||
`ignore`.",
|
||||
default = "[]",
|
||||
value_type = "Vec<CheckCodePrefix>",
|
||||
example = r#"
|
||||
@@ -105,10 +100,10 @@ pub struct Options {
|
||||
extend-ignore = ["F841"]
|
||||
"#
|
||||
)]
|
||||
/// A list of check code prefixes to ignore, in addition to those specified
|
||||
/// by `ignore`.
|
||||
pub extend_ignore: Option<Vec<CheckCodePrefix>>,
|
||||
#[option(
|
||||
doc = "A list of check code prefixes to enable, in addition to those specified by \
|
||||
`select`.",
|
||||
default = "[]",
|
||||
value_type = "Vec<CheckCodePrefix>",
|
||||
example = r#"
|
||||
@@ -116,13 +111,10 @@ pub struct Options {
|
||||
extend-select = ["B", "Q"]
|
||||
"#
|
||||
)]
|
||||
/// A list of check code prefixes to enable, in addition to those specified
|
||||
/// by `select`.
|
||||
pub extend_select: Option<Vec<CheckCodePrefix>>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
A list of check codes that are unsupported by Ruff, but should be preserved when (e.g.)
|
||||
validating `# noqa` directives. Useful for retaining `# noqa` directives that cover plugins not
|
||||
yet implemented in Ruff.
|
||||
"#,
|
||||
default = "[]",
|
||||
value_type = "Vec<String>",
|
||||
example = r#"
|
||||
@@ -131,19 +123,16 @@ pub struct Options {
|
||||
external = ["V101"]
|
||||
"#
|
||||
)]
|
||||
/// A list of check codes that are unsupported by Ruff, but should be
|
||||
/// preserved when (e.g.) validating `# noqa` directives. Useful for
|
||||
/// retaining `# noqa` directives that cover plugins not yet implemented
|
||||
/// in Ruff.
|
||||
pub external: Option<Vec<String>>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
Enable autofix behavior by-default when running `ruff` (overridden
|
||||
by the `--fix` and `--no-fix` command-line flags).
|
||||
"#,
|
||||
default = "false",
|
||||
value_type = "bool",
|
||||
example = "fix = true"
|
||||
)]
|
||||
#[option(default = "false", value_type = "bool", example = "fix = true")]
|
||||
/// Enable autofix behavior by-default when running `ruff` (overridden
|
||||
/// by the `--fix` and `--no-fix` command-line flags).
|
||||
pub fix: Option<bool>,
|
||||
#[option(
|
||||
doc = "A list of check code prefixes to consider autofix-able.",
|
||||
default = r#"["A", "ANN", "ARG", "B", "BLE", "C", "D", "E", "ERA", "F", "FBT", "I", "ICN", "N", "PGH", "PLC", "PLE", "PLR", "PLW", "Q", "RET", "RUF", "S", "T", "TID", "UP", "W", "YTT"]"#,
|
||||
value_type = "Vec<CheckCodePrefix>",
|
||||
example = r#"
|
||||
@@ -151,13 +140,9 @@ pub struct Options {
|
||||
fixable = ["E", "F"]
|
||||
"#
|
||||
)]
|
||||
/// A list of check code prefixes to consider autofix-able.
|
||||
pub fixable: Option<Vec<CheckCodePrefix>>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
The style in which violation messages should be formatted: `"text"` (default),
|
||||
`"grouped"` (group messages by file), `"json"` (machine-readable), `"junit"`
|
||||
(machine-readable XML), or `"github"` (GitHub Actions annotations).
|
||||
"#,
|
||||
default = r#""text""#,
|
||||
value_type = "SerializationType",
|
||||
example = r#"
|
||||
@@ -165,33 +150,30 @@ pub struct Options {
|
||||
format = "grouped"
|
||||
"#
|
||||
)]
|
||||
/// The style in which violation messages should be formatted: `"text"`
|
||||
/// (default), `"grouped"` (group messages by file), `"json"`
|
||||
/// (machine-readable), `"junit"` (machine-readable XML), or `"github"`
|
||||
/// (GitHub Actions annotations).
|
||||
pub format: Option<SerializationFormat>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
Whether to enforce `exclude` and `extend-exclude` patterns, even for paths that are
|
||||
passed to Ruff explicitly. Typically, Ruff will lint any paths passed in directly, even
|
||||
if they would typically be excluded. Setting `force-exclude = true` will cause Ruff to
|
||||
respect these exclusions unequivocally.
|
||||
|
||||
This is useful for [`pre-commit`](https://pre-commit.com/), which explicitly passes all
|
||||
changed files to the [`ruff-pre-commit`](https://github.com/charliermarsh/ruff-pre-commit)
|
||||
plugin, regardless of whether they're marked as excluded by Ruff's own settings.
|
||||
"#,
|
||||
default = r#"false"#,
|
||||
value_type = "bool",
|
||||
example = r#"
|
||||
force-exclude = true
|
||||
"#
|
||||
)]
|
||||
/// Whether to enforce `exclude` and `extend-exclude` patterns, even for
|
||||
/// paths that are passed to Ruff explicitly. Typically, Ruff will lint
|
||||
/// any paths passed in directly, even if they would typically be
|
||||
/// excluded. Setting `force-exclude = true` will cause Ruff to
|
||||
/// respect these exclusions unequivocally.
|
||||
///
|
||||
/// This is useful for [`pre-commit`](https://pre-commit.com/), which explicitly passes all
|
||||
/// changed files to the [`ruff-pre-commit`](https://github.com/charliermarsh/ruff-pre-commit)
|
||||
/// plugin, regardless of whether they're marked as excluded by Ruff's own
|
||||
/// settings.
|
||||
pub force_exclude: Option<bool>,
|
||||
#[option(
|
||||
doc = r"
|
||||
A list of check code prefixes to ignore. Prefixes can specify exact checks (like
|
||||
`F841`), entire categories (like `F`), or anything in between.
|
||||
|
||||
When breaking ties between enabled and disabled checks (via `select` and `ignore`,
|
||||
respectively), more specific prefixes override less specific prefixes.
|
||||
",
|
||||
default = "[]",
|
||||
value_type = "Vec<CheckCodePrefix>",
|
||||
example = r#"
|
||||
@@ -199,23 +181,28 @@ pub struct Options {
|
||||
ignore = ["F841"]
|
||||
"#
|
||||
)]
|
||||
/// A list of check code prefixes to ignore. Prefixes can specify exact
|
||||
/// checks (like `F841`), entire categories (like `F`), or anything in
|
||||
/// between.
|
||||
///
|
||||
/// When breaking ties between enabled and disabled checks (via `select` and
|
||||
/// `ignore`, respectively), more specific prefixes override less
|
||||
/// specific prefixes.
|
||||
pub ignore: Option<Vec<CheckCodePrefix>>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
Avoid automatically removing unused imports in `__init__.py` files. Such imports will
|
||||
still be +flagged, but with a dedicated message suggesting that the import is either
|
||||
added to the module' +`__all__` symbol, or re-exported with a redundant alias (e.g.,
|
||||
`import os as os`).
|
||||
"#,
|
||||
default = "false",
|
||||
value_type = "bool",
|
||||
example = r#"
|
||||
ignore-init-module-imports = true
|
||||
"#
|
||||
)]
|
||||
/// Avoid automatically removing unused imports in `__init__.py` files. Such
|
||||
/// imports will still be +flagged, but with a dedicated message
|
||||
/// suggesting that the import is either added to the module' +`__all__`
|
||||
/// symbol, or re-exported with a redundant alias (e.g., `import os as
|
||||
/// os`).
|
||||
pub ignore_init_module_imports: Option<bool>,
|
||||
#[option(
|
||||
doc = "The line length to use when enforcing long-lines violations (like E501).",
|
||||
default = "88",
|
||||
value_type = "usize",
|
||||
example = r#"
|
||||
@@ -223,27 +210,21 @@ pub struct Options {
|
||||
line-length = 120
|
||||
"#
|
||||
)]
|
||||
/// The line length to use when enforcing long-lines violations (like
|
||||
/// `E501`).
|
||||
pub line_length: Option<usize>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
Whether to automatically exclude files that are ignored by `.ignore`, `.gitignore`,
|
||||
`.git/info/exclude`, and global `gitignore` files. Enabled by default.
|
||||
"#,
|
||||
default = "true",
|
||||
value_type = "bool",
|
||||
example = r#"
|
||||
respect_gitignore = false
|
||||
"#
|
||||
)]
|
||||
/// Whether to automatically exclude files that are ignored by `.ignore`,
|
||||
/// `.gitignore`, `.git/info/exclude`, and global `gitignore` files.
|
||||
/// Enabled by default.
|
||||
pub respect_gitignore: Option<bool>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
A list of check code prefixes to enable. Prefixes can specify exact checks (like
|
||||
`F841`), entire categories (like `F`), or anything in between.
|
||||
|
||||
When breaking ties between enabled and disabled checks (via `select` and `ignore`,
|
||||
respectively), more specific prefixes override less specific prefixes.
|
||||
"#,
|
||||
default = r#"["E", "F"]"#,
|
||||
value_type = "Vec<CheckCodePrefix>",
|
||||
example = r#"
|
||||
@@ -251,12 +232,15 @@ pub struct Options {
|
||||
select = ["E", "F", "B", "Q"]
|
||||
"#
|
||||
)]
|
||||
/// A list of check code prefixes to enable. Prefixes can specify exact
|
||||
/// checks (like `F841`), entire categories (like `F`), or anything in
|
||||
/// between.
|
||||
///
|
||||
/// When breaking ties between enabled and disabled checks (via `select` and
|
||||
/// `ignore`, respectively), more specific prefixes override less
|
||||
/// specific prefixes.
|
||||
pub select: Option<Vec<CheckCodePrefix>>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
Whether to show source code snippets when reporting lint error violations (overridden by
|
||||
the `--show-source` command-line flag).
|
||||
"#,
|
||||
default = "false",
|
||||
value_type = "bool",
|
||||
example = r#"
|
||||
@@ -264,31 +248,10 @@ pub struct Options {
|
||||
show-source = true
|
||||
"#
|
||||
)]
|
||||
/// Whether to show source code snippets when reporting lint error
|
||||
/// violations (overridden by the `--show-source` command-line flag).
|
||||
pub show_source: Option<bool>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
The source code paths to consider, e.g., when resolving first- vs. third-party imports.
|
||||
|
||||
As an example: given a Python package structure like:
|
||||
|
||||
```text
|
||||
my_package/
|
||||
pyproject.toml
|
||||
src/
|
||||
my_package/
|
||||
__init__.py
|
||||
foo.py
|
||||
bar.py
|
||||
```
|
||||
|
||||
The `src` directory should be included in `source` (e.g., `source = ["src"]`), such that
|
||||
when resolving imports, `my_package.foo` is considered a first-party import.
|
||||
|
||||
This field supports globs. For example, if you have a series of Python packages in
|
||||
a `python_modules` directory, `src = ["python_modules/*"]` would expand to incorporate
|
||||
all of the packages in that directory. User home directory and environment variables
|
||||
will also be expanded.
|
||||
"#,
|
||||
default = r#"["."]"#,
|
||||
value_type = "Vec<PathBuf>",
|
||||
example = r#"
|
||||
@@ -296,13 +259,32 @@ pub struct Options {
|
||||
src = ["src", "test"]
|
||||
"#
|
||||
)]
|
||||
/// The source code paths to consider, e.g., when resolving first- vs.
|
||||
/// third-party imports.
|
||||
///
|
||||
/// As an example: given a Python package structure like:
|
||||
///
|
||||
/// ```text
|
||||
/// my_package/
|
||||
/// pyproject.toml
|
||||
/// src/
|
||||
/// my_package/
|
||||
/// __init__.py
|
||||
/// foo.py
|
||||
/// bar.py
|
||||
/// ```
|
||||
///
|
||||
/// The `src` directory should be included in `source` (e.g., `source =
|
||||
/// ["src"]`), such that when resolving imports, `my_package.foo` is
|
||||
/// considered a first-party import.
|
||||
///
|
||||
/// This field supports globs. For example, if you have a series of Python
|
||||
/// packages in a `python_modules` directory, `src =
|
||||
/// ["python_modules/*"]` would expand to incorporate all of the
|
||||
/// packages in that directory. User home directory and environment
|
||||
/// variables will also be expanded.
|
||||
pub src: Option<Vec<String>>,
|
||||
#[option(
|
||||
doc = r#"
|
||||
The Python version to target, e.g., when considering automatic code upgrades, like
|
||||
rewriting type annotations. Note that the target version will _not_ be inferred from the
|
||||
_current_ Python version, and instead must be specified explicitly (as seen below).
|
||||
"#,
|
||||
default = r#""py310""#,
|
||||
value_type = "PythonVersion",
|
||||
example = r#"
|
||||
@@ -310,9 +292,12 @@ pub struct Options {
|
||||
target-version = "py37"
|
||||
"#
|
||||
)]
|
||||
/// The Python version to target, e.g., when considering automatic code
|
||||
/// upgrades, like rewriting type annotations. Note that the target
|
||||
/// version will _not_ be inferred from the _current_ Python version,
|
||||
/// and instead must be specified explicitly (as seen below).
|
||||
pub target_version: Option<PythonVersion>,
|
||||
#[option(
|
||||
doc = "A list of check code prefixes to consider un-autofix-able.",
|
||||
default = "[]",
|
||||
value_type = "Vec<CheckCodePrefix>",
|
||||
example = r#"
|
||||
@@ -320,36 +305,60 @@ pub struct Options {
|
||||
unfixable = ["F401"]
|
||||
"#
|
||||
)]
|
||||
/// A list of check code prefixes to consider un-autofix-able.
|
||||
pub unfixable: Option<Vec<CheckCodePrefix>>,
|
||||
// Plugins
|
||||
#[option(
|
||||
default = ".ruff_cache",
|
||||
value_type = "PathBuf",
|
||||
example = r#"cache-dir = "~/.cache/ruff""#
|
||||
)]
|
||||
/// A path to the cache directory.
|
||||
///
|
||||
/// By default, Ruff stores cache results in a `.ruff_cache` directory in
|
||||
/// the current project root.
|
||||
///
|
||||
/// However, Ruff will also respect the `RUFF_CACHE_DIR` environment
|
||||
/// variable, which takes precedence over that default.
|
||||
///
|
||||
/// This setting will override even the `RUFF_CACHE_DIR` environment
|
||||
/// variable, if set.
|
||||
pub cache_dir: Option<String>,
|
||||
/// Plugins
|
||||
#[option_group]
|
||||
/// Options for the `flake8-annotations` plugin.
|
||||
pub flake8_annotations: Option<flake8_annotations::settings::Options>,
|
||||
#[option_group]
|
||||
/// Options for the `flake8-bugbear` plugin.
|
||||
pub flake8_bugbear: Option<flake8_bugbear::settings::Options>,
|
||||
#[option_group]
|
||||
/// Options for the `flake8-errmsg` plugin.
|
||||
pub flake8_errmsg: Option<flake8_errmsg::settings::Options>,
|
||||
#[option_group]
|
||||
/// Options for the `flake8-quotes` plugin.
|
||||
pub flake8_quotes: Option<flake8_quotes::settings::Options>,
|
||||
#[option_group]
|
||||
/// Options for the `flake8-tidy-imports` plugin.
|
||||
pub flake8_tidy_imports: Option<flake8_tidy_imports::settings::Options>,
|
||||
#[option_group]
|
||||
/// Options for the `flake8-import-conventions` plugin.
|
||||
pub flake8_import_conventions: Option<flake8_import_conventions::settings::Options>,
|
||||
#[option_group]
|
||||
/// Options for the `flake8-unused-arguments` plugin.
|
||||
pub flake8_unused_arguments: Option<flake8_unused_arguments::settings::Options>,
|
||||
#[option_group]
|
||||
/// Options for the `isort` plugin.
|
||||
pub isort: Option<isort::settings::Options>,
|
||||
#[option_group]
|
||||
/// Options for the `mccabe` plugin.
|
||||
pub mccabe: Option<mccabe::settings::Options>,
|
||||
#[option_group]
|
||||
/// Options for the `pep8-naming` plugin.
|
||||
pub pep8_naming: Option<pep8_naming::settings::Options>,
|
||||
#[option_group]
|
||||
/// Options for the `pyupgrade` plugin.
|
||||
pub pyupgrade: Option<pyupgrade::settings::Options>,
|
||||
// Tables are required to go last.
|
||||
#[option(
|
||||
doc = r#"
|
||||
A list of mappings from file pattern to check code prefixes to exclude, when considering
|
||||
any matching files.
|
||||
"#,
|
||||
default = "{}",
|
||||
value_type = "HashMap<String, Vec<CheckCodePrefix>>",
|
||||
example = r#"
|
||||
@@ -359,5 +368,7 @@ pub struct Options {
|
||||
"path/to/file.py" = ["E402"]
|
||||
"#
|
||||
)]
|
||||
/// A list of mappings from file pattern to check code prefixes to exclude,
|
||||
/// when considering any matching files.
|
||||
pub per_file_ignores: Option<FxHashMap<String, Vec<CheckCodePrefix>>>,
|
||||
}
|
||||
|
||||
@@ -141,6 +141,7 @@ mod tests {
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
@@ -189,6 +190,7 @@ line-length = 79
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
@@ -237,6 +239,7 @@ exclude = ["foo.py"]
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_errmsg: None,
|
||||
flake8_bugbear: None,
|
||||
@@ -285,6 +288,7 @@ select = ["E501"]
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
@@ -334,6 +338,7 @@ ignore = ["E501"]
|
||||
src: None,
|
||||
target_version: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
@@ -415,6 +420,7 @@ other-attribute = 1
|
||||
format: None,
|
||||
force_exclude: None,
|
||||
unfixable: None,
|
||||
cache_dir: None,
|
||||
per_file_ignores: Some(FxHashMap::from_iter([(
|
||||
"__init__.py".to_string(),
|
||||
vec![CheckCodePrefix::F401]
|
||||
|
||||
@@ -7,13 +7,16 @@ use anyhow::{anyhow, bail, Result};
|
||||
use clap::ValueEnum;
|
||||
use globset::{Glob, GlobSetBuilder};
|
||||
use rustc_hash::FxHashSet;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{de, Deserialize, Deserializer, Serialize};
|
||||
|
||||
use crate::checks::CheckCode;
|
||||
use crate::checks_gen::CheckCodePrefix;
|
||||
use crate::fs;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Serialize, Deserialize, Hash)]
|
||||
#[derive(
|
||||
Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Serialize, Deserialize, Hash, JsonSchema,
|
||||
)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum PythonVersion {
|
||||
Py33,
|
||||
@@ -142,7 +145,7 @@ impl FromStr for PatternPrefixPair {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, ValueEnum, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
#[derive(Clone, Copy, ValueEnum, PartialEq, Eq, Serialize, Deserialize, Debug, JsonSchema)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum SerializationFormat {
|
||||
Text,
|
||||
|
||||
Reference in New Issue
Block a user