Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5ab492a70 | ||
|
|
1fc09ebd5c | ||
|
|
6cf047976c | ||
|
|
87465daacc | ||
|
|
a52bed7101 | ||
|
|
20ac823778 | ||
|
|
1028ed3565 | ||
|
|
98897db6ac | ||
|
|
5ce4262112 | ||
|
|
6b2359384d | ||
|
|
d3443d7c19 | ||
|
|
04b1e1de6f | ||
|
|
c93c85300f | ||
|
|
73ed6f8654 | ||
|
|
eb183645f3 | ||
|
|
ef17aa93da | ||
|
|
f366b0147f | ||
|
|
fc88fa35ff |
2
.github/workflows/ci.yaml
vendored
2
.github/workflows/ci.yaml
vendored
@@ -39,7 +39,7 @@ jobs:
|
||||
- run: ./target/release/ruff_dev generate-rules-table
|
||||
- run: ./target/release/ruff_dev generate-options
|
||||
- run: git diff --quiet README.md || echo "::error file=README.md::This file is outdated. You may have to rerun 'cargo dev generate-options' and/or 'cargo dev generate-rules-table'."
|
||||
- run: ./target/release/ruff_dev generate-check-code-prefix && cargo fmt -- src/checks_gen.rs
|
||||
- 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
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
repos:
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.0.185
|
||||
rev: v0.0.187
|
||||
hooks:
|
||||
- id: ruff
|
||||
|
||||
|
||||
16
Cargo.lock
generated
16
Cargo.lock
generated
@@ -724,7 +724,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.185-dev.0"
|
||||
version = "0.0.187-dev.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.0.29",
|
||||
@@ -1845,7 +1845,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.185"
|
||||
version = "0.0.187"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.9.1",
|
||||
"anyhow",
|
||||
@@ -1901,7 +1901,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_dev"
|
||||
version = "0.0.185"
|
||||
version = "0.0.187"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.0.29",
|
||||
@@ -1919,7 +1919,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_macros"
|
||||
version = "0.0.185"
|
||||
version = "0.0.187"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1962,7 +1962,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-ast"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=8d879a53197f9c73062f6160410bdba796a71cbf#8d879a53197f9c73062f6160410bdba796a71cbf"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c01f014b1269eedcf4bdb45d5fbc62ae2beecf31#c01f014b1269eedcf4bdb45d5fbc62ae2beecf31"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"rustpython-common",
|
||||
@@ -1972,7 +1972,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-common"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=8d879a53197f9c73062f6160410bdba796a71cbf#8d879a53197f9c73062f6160410bdba796a71cbf"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c01f014b1269eedcf4bdb45d5fbc62ae2beecf31#c01f014b1269eedcf4bdb45d5fbc62ae2beecf31"
|
||||
dependencies = [
|
||||
"ascii",
|
||||
"cfg-if 1.0.0",
|
||||
@@ -1995,7 +1995,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-compiler-core"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=8d879a53197f9c73062f6160410bdba796a71cbf#8d879a53197f9c73062f6160410bdba796a71cbf"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c01f014b1269eedcf4bdb45d5fbc62ae2beecf31#c01f014b1269eedcf4bdb45d5fbc62ae2beecf31"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitflags",
|
||||
@@ -2012,7 +2012,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-parser"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=8d879a53197f9c73062f6160410bdba796a71cbf#8d879a53197f9c73062f6160410bdba796a71cbf"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c01f014b1269eedcf4bdb45d5fbc62ae2beecf31#c01f014b1269eedcf4bdb45d5fbc62ae2beecf31"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
|
||||
10
Cargo.toml
10
Cargo.toml
@@ -6,7 +6,7 @@ members = [
|
||||
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.185"
|
||||
version = "0.0.187"
|
||||
edition = "2021"
|
||||
rust-version = "1.65.0"
|
||||
|
||||
@@ -43,11 +43,11 @@ 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.185", path = "ruff_macros" }
|
||||
ruff_macros = { version = "0.0.187", path = "ruff_macros" }
|
||||
rustc-hash = { version = "1.1.0" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "8d879a53197f9c73062f6160410bdba796a71cbf" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "8d879a53197f9c73062f6160410bdba796a71cbf" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "8d879a53197f9c73062f6160410bdba796a71cbf" }
|
||||
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" }
|
||||
serde = { version = "1.0.147", features = ["derive"] }
|
||||
serde_json = { version = "1.0.87" }
|
||||
strum = { version = "0.24.1", features = ["strum_macros"] }
|
||||
|
||||
129
README.md
129
README.md
@@ -118,6 +118,8 @@ Ruff is available as [`ruff`](https://pypi.org/project/ruff/) on PyPI:
|
||||
pip install ruff
|
||||
```
|
||||
|
||||
[](https://repology.org/project/ruff-python-linter/versions)
|
||||
|
||||
For **macOS Homebrew** and **Linuxbrew** users, Ruff is also available as [`ruff`](https://formulae.brew.sh/formula/ruff) on Homebrew:
|
||||
|
||||
```shell
|
||||
@@ -157,7 +159,7 @@ Ruff also works with [pre-commit](https://pre-commit.com):
|
||||
```yaml
|
||||
repos:
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.0.185
|
||||
rev: v0.0.187
|
||||
hooks:
|
||||
- id: ruff
|
||||
```
|
||||
@@ -354,7 +356,7 @@ There are a few exceptions to these rules:
|
||||
a default configuration. If a user-specific configuration file exists
|
||||
at `${config_dir}/ruff/pyproject.toml`,
|
||||
that file will be used instead of the default configuration, with `${config_dir}` being
|
||||
determined via the [`dirs](https://docs.rs/dirs/4.0.0/dirs/fn.config_dir.html) crate, and all
|
||||
determined via the [`dirs`](https://docs.rs/dirs/4.0.0/dirs/fn.config_dir.html) crate, and all
|
||||
relative paths being again resolved relative to the _current working directory_.
|
||||
4. Any `pyproject.toml`-supported settings that are provided on the command-line (e.g., via
|
||||
`--select`) will override the settings in _every_ resolved configuration file.
|
||||
@@ -881,9 +883,9 @@ For more, see [pandas-vet](https://pypi.org/project/pandas-vet/0.2.3/) on PyPI.
|
||||
| PDV002 | UseOfInplaceArgument | `inplace=True` should be avoided; it has inconsistent behavior | |
|
||||
| PDV003 | UseOfDotIsNull | `.isna` is preferred to `.isnull`; functionality is equivalent | |
|
||||
| PDV004 | UseOfDotNotNull | `.notna` is preferred to `.notnull`; functionality is equivalent | |
|
||||
| PDV007 | UseOfDotIx | ``ix` i` deprecated; use more explicit `.loc` o` `.iloc` | |
|
||||
| PDV007 | UseOfDotIx | `.ix` is deprecated; use more explicit `.loc` or `.iloc` | |
|
||||
| PDV008 | UseOfDotAt | Use `.loc` instead of `.at`. If speed is important, use numpy. | |
|
||||
| PDV009 | UseOfDotIat | Use `.iloc` instea` of `.iat`. If speed is important, use numpy. | |
|
||||
| PDV009 | UseOfDotIat | Use `.iloc` instead of `.iat`. If speed is important, use numpy. | |
|
||||
| PDV010 | UseOfDotPivotOrUnstack | `.pivot_table` is preferred to `.pivot` or `.unstack`; provides same functionality | |
|
||||
| PDV011 | UseOfDotValues | Use `.to_numpy()` instead of `.values` | |
|
||||
| PDV012 | UseOfDotReadTable | `.read_csv` is preferred to `.read_table`; provides same functionality | |
|
||||
@@ -898,6 +900,8 @@ For more, see [pygrep-hooks](https://github.com/pre-commit/pygrep-hooks) on GitH
|
||||
| Code | Name | Message | Fix |
|
||||
| ---- | ---- | ------- | --- |
|
||||
| PGH001 | NoEval | No builtin `eval()` allowed | |
|
||||
| PGH002 | DeprecatedLogWarn | `warn` is deprecated in favor of `warning` | |
|
||||
| PGH003 | BlanketTypeIgnore | Use specific error codes when ignoring type issues | |
|
||||
|
||||
### Pylint (PLC, PLE, PLR, PLW)
|
||||
|
||||
@@ -933,21 +937,100 @@ For more, see [Pylint](https://pypi.org/project/pylint/2.15.7/) on PyPI.
|
||||
|
||||
### VS Code (Official)
|
||||
|
||||
Download the [Ruff VS Code extension](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff).
|
||||
Download the [Ruff VS Code extension](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff),
|
||||
which supports autofix actions, import sorting, and more.
|
||||
|
||||
### Language Server Protocol
|
||||

|
||||
|
||||
Ruff is available as a [Language Server Protocol (LSP)](https://microsoft.github.io/language-server-protocol/)
|
||||
server, distributed as the [`python-lsp-ruff`](https://github.com/python-lsp/python-lsp-ruff) plugin
|
||||
for [`python-lsp-server`](https://github.com/python-lsp/python-lsp-server), both of which are
|
||||
installable via [PyPI](https://pypi.org/project/python-lsp-ruff/):
|
||||
### Language Server Protocol (Official)
|
||||
|
||||
Ruff supports the [Language Server Protocol](https://microsoft.github.io/language-server-protocol/)
|
||||
via the [`ruff-lsp`](https://github.com/charliermarsh/ruff-lsp) Python package, available on
|
||||
[PyPI](https://pypi.org/project/ruff-lsp/).
|
||||
|
||||
[`ruff-lsp`](https://github.com/charliermarsh/ruff-lsp) enables Ruff to be used with any editor that
|
||||
supports the Language Server Protocol, including [Neovim](https://github.com/charliermarsh/ruff-lsp#example-neovim),
|
||||
[Sublime Text](https://github.com/charliermarsh/ruff-lsp#example-sublime-text), Emacs, and more.
|
||||
|
||||
For example, to use `ruff-lsp` with Neovim, install `ruff-lsp` from PyPI along with
|
||||
[`nvim-lspconfig`](https://github.com/neovim/nvim-lspconfig). Then, add something like the following
|
||||
to your `init.lua`:
|
||||
|
||||
```lua
|
||||
-- See: https://github.com/neovim/nvim-lspconfig/tree/54eb2a070a4f389b1be0f98070f81d23e2b1a715#suggested-configuration
|
||||
local opts = { noremap=true, silent=true }
|
||||
vim.keymap.set('n', '<space>e', vim.diagnostic.open_float, opts)
|
||||
vim.keymap.set('n', '[d', vim.diagnostic.goto_prev, opts)
|
||||
vim.keymap.set('n', ']d', vim.diagnostic.goto_next, opts)
|
||||
vim.keymap.set('n', '<space>q', vim.diagnostic.setloclist, opts)
|
||||
|
||||
-- Use an on_attach function to only map the following keys
|
||||
-- after the language server attaches to the current buffer
|
||||
local on_attach = function(client, bufnr)
|
||||
-- Enable completion triggered by <c-x><c-o>
|
||||
vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')
|
||||
|
||||
-- Mappings.
|
||||
-- See `:help vim.lsp.*` for documentation on any of the below functions
|
||||
local bufopts = { noremap=true, silent=true, buffer=bufnr }
|
||||
vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, bufopts)
|
||||
vim.keymap.set('n', 'gd', vim.lsp.buf.definition, bufopts)
|
||||
vim.keymap.set('n', 'K', vim.lsp.buf.hover, bufopts)
|
||||
vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, bufopts)
|
||||
vim.keymap.set('n', '<C-k>', vim.lsp.buf.signature_help, bufopts)
|
||||
vim.keymap.set('n', '<space>wa', vim.lsp.buf.add_workspace_folder, bufopts)
|
||||
vim.keymap.set('n', '<space>wr', vim.lsp.buf.remove_workspace_folder, bufopts)
|
||||
vim.keymap.set('n', '<space>wl', function()
|
||||
print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
|
||||
end, bufopts)
|
||||
vim.keymap.set('n', '<space>D', vim.lsp.buf.type_definition, bufopts)
|
||||
vim.keymap.set('n', '<space>rn', vim.lsp.buf.rename, bufopts)
|
||||
vim.keymap.set('n', '<space>ca', vim.lsp.buf.code_action, bufopts)
|
||||
vim.keymap.set('n', 'gr', vim.lsp.buf.references, bufopts)
|
||||
vim.keymap.set('n', '<space>f', function() vim.lsp.buf.format { async = true } end, bufopts)
|
||||
end
|
||||
|
||||
-- Configure `ruff-lsp`.
|
||||
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 = {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
require('lspconfig').ruff_lsp.setup {
|
||||
on_attach = on_attach,
|
||||
}
|
||||
```
|
||||
|
||||
Upon successful installation, you should see Ruff's diagnostics surfaced directly in your editor:
|
||||
|
||||

|
||||
|
||||
### Language Server Protocol (Unofficial)
|
||||
|
||||
Ruff is also available as the [`python-lsp-ruff`](https://github.com/python-lsp/python-lsp-ruff)
|
||||
plugin for [`python-lsp-server`](https://github.com/python-lsp/python-lsp-ruff), both of which are
|
||||
installable from PyPI:
|
||||
|
||||
```shell
|
||||
pip install python-lsp-server python-lsp-ruff
|
||||
```
|
||||
|
||||
The LSP server can be used with any editor that supports the Language Server Protocol. For example,
|
||||
to use it with Neovim, you would add something like the following to your `init.lua`:
|
||||
The LSP server can then be used with any editor that supports the Language Server Protocol.
|
||||
|
||||
For example, to use `python-lsp-ruff` with Neovim, add something like the following to your
|
||||
`init.lua`:
|
||||
|
||||
```lua
|
||||
require'lspconfig'.pylsp.setup {
|
||||
@@ -956,6 +1039,15 @@ require'lspconfig'.pylsp.setup {
|
||||
plugins = {
|
||||
ruff = {
|
||||
enabled = true
|
||||
},
|
||||
pycodestyle = {
|
||||
enabled = false
|
||||
},
|
||||
pyflakes = {
|
||||
enabled = false
|
||||
},
|
||||
mccabe = {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -963,9 +1055,6 @@ require'lspconfig'.pylsp.setup {
|
||||
}
|
||||
```
|
||||
|
||||
[`ruffd`](https://github.com/Seamooo/ruffd) is another implementation of the Language Server
|
||||
Protocol (LSP) for Ruff, written in Rust.
|
||||
|
||||
### PyCharm
|
||||
|
||||
Ruff can be installed as an [External Tool](https://www.jetbrains.com/help/pycharm/configuring-third-party-tools.html)
|
||||
@@ -980,8 +1069,8 @@ Ruff should then appear as a runnable action:
|
||||
|
||||
### Vim & Neovim
|
||||
|
||||
Ruff can be integrated into any editor that supports the Language Server Protocol (LSP) (see:
|
||||
[Language Server Protocol](#language-server-protocol)).
|
||||
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)).
|
||||
|
||||
Ruff is also available as part of the [coc-pyright](https://github.com/fannheyward/coc-pyright)
|
||||
extension for `coc.nvim`.
|
||||
@@ -1111,7 +1200,7 @@ natively, including:
|
||||
- [`mccabe`](https://pypi.org/project/mccabe/)
|
||||
- [`pep8-naming`](https://pypi.org/project/pep8-naming/)
|
||||
- [`pydocstyle`](https://pypi.org/project/pydocstyle/)
|
||||
- [`pygrep-hooks`](https://github.com/pre-commit/pygrep-hooks) (1/10)
|
||||
- [`pygrep-hooks`](https://github.com/pre-commit/pygrep-hooks) (3/10)
|
||||
- [`pyupgrade`](https://pypi.org/project/pyupgrade/) (16/33)
|
||||
- [`yesqa`](https://github.com/asottile/yesqa)
|
||||
|
||||
@@ -1167,7 +1256,7 @@ Today, Ruff can be used to replace Flake8 when used with any of the following pl
|
||||
|
||||
Ruff can also replace [`isort`](https://pypi.org/project/isort/),
|
||||
[`yesqa`](https://github.com/asottile/yesqa), [`eradicate`](https://pypi.org/project/eradicate/),
|
||||
[`pygrep-hooks`](https://github.com/pre-commit/pygrep-hooks) (1/10), and a subset of the rules
|
||||
[`pygrep-hooks`](https://github.com/pre-commit/pygrep-hooks) (3/10), and a subset of the rules
|
||||
implemented in [`pyupgrade`](https://pypi.org/project/pyupgrade/) (16/33).
|
||||
|
||||
If you're looking to use Ruff, but rely on an unsupported Flake8 plugin, free to file an Issue.
|
||||
@@ -1488,7 +1577,7 @@ ignored when evaluating (e.g.) unused-variable checks. The default expression ma
|
||||
```toml
|
||||
[tool.ruff]
|
||||
# Only ignore variables named "_".
|
||||
dummy_variable_rgx = "^_$"
|
||||
dummy-variable-rgx = "^_$"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
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.185"
|
||||
version = "0.0.187"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -1975,7 +1975,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.185"
|
||||
version = "0.0.187"
|
||||
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=8d879a53197f9c73062f6160410bdba796a71cbf#8d879a53197f9c73062f6160410bdba796a71cbf"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c01f014b1269eedcf4bdb45d5fbc62ae2beecf31#c01f014b1269eedcf4bdb45d5fbc62ae2beecf31"
|
||||
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=8d879a53197f9c73062f6160410bdba796a71cbf#8d879a53197f9c73062f6160410bdba796a71cbf"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c01f014b1269eedcf4bdb45d5fbc62ae2beecf31#c01f014b1269eedcf4bdb45d5fbc62ae2beecf31"
|
||||
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=8d879a53197f9c73062f6160410bdba796a71cbf#8d879a53197f9c73062f6160410bdba796a71cbf"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c01f014b1269eedcf4bdb45d5fbc62ae2beecf31#c01f014b1269eedcf4bdb45d5fbc62ae2beecf31"
|
||||
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=8d879a53197f9c73062f6160410bdba796a71cbf#8d879a53197f9c73062f6160410bdba796a71cbf"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=c01f014b1269eedcf4bdb45d5fbc62ae2beecf31#c01f014b1269eedcf4bdb45d5fbc62ae2beecf31"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.185-dev.0"
|
||||
version = "0.0.187-dev.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
5
resources/test/fixtures/pycodestyle/E501.py
vendored
5
resources/test/fixtures/pycodestyle/E501.py
vendored
@@ -55,3 +55,8 @@ sit amet consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labor
|
||||
|
||||
# OK
|
||||
# https://loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong.url.com
|
||||
|
||||
# Not OK
|
||||
_ = """
|
||||
Source: https://github.com/PyCQA/pycodestyle/pull/258/files#diff-841c622497a8033d10152bfdfb15b20b92437ecdea21a260944ea86b77b51533
|
||||
"""
|
||||
|
||||
8
resources/test/fixtures/pygrep-hooks/PGH002_0.py
vendored
Normal file
8
resources/test/fixtures/pygrep-hooks/PGH002_0.py
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import logging
|
||||
import warnings
|
||||
from warnings import warn
|
||||
|
||||
warnings.warn("this is ok")
|
||||
warn("by itself is also ok")
|
||||
logging.warning("this is fine")
|
||||
log.warning("this is ok")
|
||||
15
resources/test/fixtures/pygrep-hooks/PGH002_1.py
vendored
Normal file
15
resources/test/fixtures/pygrep-hooks/PGH002_1.py
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import logging
|
||||
from logging import warn
|
||||
|
||||
logging.warn("this is not ok")
|
||||
log.warn("this is also not ok")
|
||||
warn("not ok")
|
||||
|
||||
|
||||
def foo():
|
||||
from logging import warn
|
||||
|
||||
def warn():
|
||||
pass
|
||||
|
||||
warn("has been redefined, but we will still report it")
|
||||
11
resources/test/fixtures/pygrep-hooks/PGH003_0.py
vendored
Normal file
11
resources/test/fixtures/pygrep-hooks/PGH003_0.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
x = 1 # type: ignore
|
||||
x = 1 # type ignore
|
||||
x = 1 # type:ignore
|
||||
|
||||
x = 1
|
||||
x = 1 # type ignore # noqa
|
||||
x = 1 # type: ignore[attr-defined]
|
||||
x = 1 # type: ignore[attr-defined, name-defined]
|
||||
x = 1 # type: ignore[type-mismatch] # noqa
|
||||
x = 1 # type: Union[int, str]
|
||||
x = 1 # type: ignoreme
|
||||
10
resources/test/fixtures/ruff/RUF100.py
vendored
10
resources/test/fixtures/ruff/RUF100.py
vendored
@@ -69,3 +69,13 @@ _ = """Lorem ipsum dolor sit amet.
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.
|
||||
""" # noqa
|
||||
|
||||
# Valid
|
||||
# this is a veryyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy long comment # noqa: E501
|
||||
|
||||
# Valid
|
||||
_ = """Here's a source: https://github.com/ethereum/web3.py/blob/ffe59daf10edc19ee5f05227b25bac8d090e8aa4/web3/_utils/events.py#L201
|
||||
|
||||
May raise:
|
||||
- DeserializationError if the abi string is invalid or abi or log topics/data do not match
|
||||
""" # noqa: E501
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_dev"
|
||||
version = "0.0.185"
|
||||
version = "0.0.187"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
@@ -11,8 +11,8 @@ 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 = "8d879a53197f9c73062f6160410bdba796a71cbf" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "8d879a53197f9c73062f6160410bdba796a71cbf" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "8d879a53197f9c73062f6160410bdba796a71cbf" }
|
||||
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" }
|
||||
strum = { version = "0.24.1", features = ["strum_macros"] }
|
||||
strum_macros = { version = "0.24.3" }
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
//! Generate the `CheckCodePrefix` enum.
|
||||
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::fs::OpenOptions;
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::process::{Command, Output, Stdio};
|
||||
|
||||
use anyhow::Result;
|
||||
use anyhow::{ensure, Result};
|
||||
use clap::Parser;
|
||||
use codegen::{Scope, Type, Variant};
|
||||
use itertools::Itertools;
|
||||
use ruff::checks::{CheckCode, CODE_REDIRECTS, PREFIX_REDIRECTS};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
const FILE: &str = "src/checks_gen.rs";
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
pub struct Cli {
|
||||
@@ -107,7 +107,7 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
for (prefix, codes) in &prefix_to_codes {
|
||||
if let Some(target) = CODE_REDIRECTS.get(&prefix.as_str()) {
|
||||
gen = gen.line(format!(
|
||||
"CheckCodePrefix::{prefix} => {{ eprintln!(\"{{}}{{}} {{}}\", \
|
||||
"CheckCodePrefix::{prefix} => {{ one_time_warning!(\"{{}}{{}} {{}}\", \
|
||||
\"warning\".yellow().bold(), \":\".bold(), \"`{}` has been remapped to \
|
||||
`{}`\".bold()); \n vec![{}] }}",
|
||||
prefix,
|
||||
@@ -119,7 +119,7 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
));
|
||||
} else if let Some(target) = PREFIX_REDIRECTS.get(&prefix.as_str()) {
|
||||
gen = gen.line(format!(
|
||||
"CheckCodePrefix::{prefix} => {{ eprintln!(\"{{}}{{}} {{}}\", \
|
||||
"CheckCodePrefix::{prefix} => {{ one_time_warning!(\"{{}}{{}} {{}}\", \
|
||||
\"warning\".yellow().bold(), \":\".bold(), \"`{}` has been remapped to \
|
||||
`{}`\".bold()); \n vec![{}] }}",
|
||||
prefix,
|
||||
@@ -182,6 +182,8 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
output.push('\n');
|
||||
output.push_str("use crate::checks::CheckCode;");
|
||||
output.push('\n');
|
||||
output.push_str("use crate::one_time_warning;");
|
||||
output.push('\n');
|
||||
output.push('\n');
|
||||
output.push_str(&scope.to_string());
|
||||
output.push('\n');
|
||||
@@ -202,12 +204,25 @@ pub fn main(cli: &Cli) -> Result<()> {
|
||||
output.push('\n');
|
||||
output.push('\n');
|
||||
|
||||
let rustfmt = Command::new("rustfmt")
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()?;
|
||||
write!(rustfmt.stdin.as_ref().unwrap(), "{output}")?;
|
||||
let Output { status, stdout, .. } = rustfmt.wait_with_output()?;
|
||||
ensure!(status.success(), "rustfmt failed with {status}");
|
||||
|
||||
// Write the output to `src/checks_gen.rs` (or stdout).
|
||||
if cli.dry_run {
|
||||
println!("{output}");
|
||||
println!("{}", String::from_utf8(stdout)?);
|
||||
} else {
|
||||
let mut f = OpenOptions::new().write(true).truncate(true).open(FILE)?;
|
||||
write!(f, "{output}")?;
|
||||
let file = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.parent()
|
||||
.expect("Failed to find root directory")
|
||||
.join("src/checks_gen.rs");
|
||||
if fs::read(&file).map_or(true, |old| old != stdout) {
|
||||
fs::write(&file, stdout)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_macros"
|
||||
version = "0.0.185"
|
||||
version = "0.0.187"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -1957,7 +1957,10 @@ where
|
||||
|
||||
// pygrep-hooks
|
||||
if self.settings.enabled.contains(&CheckCode::PGH001) {
|
||||
pygrep_hooks::checks::no_eval(self, func);
|
||||
pygrep_hooks::plugins::no_eval(self, func);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::PGH002) {
|
||||
pygrep_hooks::plugins::deprecated_log_warn(self, func);
|
||||
}
|
||||
|
||||
// pylint
|
||||
|
||||
@@ -2,40 +2,58 @@
|
||||
|
||||
use crate::checks::{Check, CheckCode};
|
||||
use crate::pycodestyle::checks::{line_too_long, no_newline_at_end_of_file};
|
||||
use crate::pygrep_hooks::plugins::blanket_type_ignore;
|
||||
use crate::pyupgrade::checks::unnecessary_coding_comment;
|
||||
use crate::settings::{flags, Settings};
|
||||
|
||||
pub fn check_lines(contents: &str, settings: &Settings, autofix: flags::Autofix) -> Vec<Check> {
|
||||
pub fn check_lines(
|
||||
contents: &str,
|
||||
commented_lines: &[usize],
|
||||
settings: &Settings,
|
||||
autofix: flags::Autofix,
|
||||
) -> Vec<Check> {
|
||||
let mut checks: Vec<Check> = vec![];
|
||||
|
||||
let enforce_unnecessary_coding_comment = settings.enabled.contains(&CheckCode::UP009);
|
||||
let enforce_line_too_long = settings.enabled.contains(&CheckCode::E501);
|
||||
let enforce_no_newline_at_end_of_file = settings.enabled.contains(&CheckCode::W292);
|
||||
let enforce_blanket_type_ignore = settings.enabled.contains(&CheckCode::PGH003);
|
||||
|
||||
for (lineno, line) in contents.lines().enumerate() {
|
||||
// Enforce unnecessary coding comments (UP009).
|
||||
if enforce_unnecessary_coding_comment {
|
||||
if lineno < 2 {
|
||||
if let Some(check) = unnecessary_coding_comment(
|
||||
lineno,
|
||||
line,
|
||||
matches!(autofix, flags::Autofix::Enabled)
|
||||
&& settings.fixable.contains(&CheckCode::UP009),
|
||||
) {
|
||||
checks.push(check);
|
||||
let mut commented_lines_iter = commented_lines.iter().peekable();
|
||||
for (index, line) in contents.lines().enumerate() {
|
||||
while commented_lines_iter
|
||||
.next_if(|lineno| &(index + 1) == *lineno)
|
||||
.is_some()
|
||||
{
|
||||
if enforce_unnecessary_coding_comment {
|
||||
if index < 2 {
|
||||
if let Some(check) = unnecessary_coding_comment(
|
||||
index,
|
||||
line,
|
||||
matches!(autofix, flags::Autofix::Enabled)
|
||||
&& settings.fixable.contains(&CheckCode::UP009),
|
||||
) {
|
||||
checks.push(check);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if enforce_blanket_type_ignore {
|
||||
if commented_lines.contains(&(index + 1)) {
|
||||
if let Some(check) = blanket_type_ignore(index, line) {
|
||||
checks.push(check);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Enforce line length violations (E501).
|
||||
if enforce_line_too_long {
|
||||
if let Some(check) = line_too_long(lineno, line, settings.line_length) {
|
||||
if let Some(check) = line_too_long(index, line, settings.line_length) {
|
||||
checks.push(check);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Enforce newlines at end of files (W292).
|
||||
if enforce_no_newline_at_end_of_file {
|
||||
if let Some(check) = no_newline_at_end_of_file(contents) {
|
||||
checks.push(check);
|
||||
@@ -58,6 +76,7 @@ mod tests {
|
||||
let check_with_max_line_length = |line_length: usize| {
|
||||
check_lines(
|
||||
line,
|
||||
&[],
|
||||
&Settings {
|
||||
line_length,
|
||||
..Settings::for_rule(CheckCode::E501)
|
||||
|
||||
@@ -316,6 +316,8 @@ pub enum CheckCode {
|
||||
RUF100,
|
||||
// pygrep-hooks
|
||||
PGH001,
|
||||
PGH002,
|
||||
PGH003,
|
||||
// pandas-vet
|
||||
PDV002,
|
||||
PDV003,
|
||||
@@ -887,6 +889,8 @@ pub enum CheckKind {
|
||||
BooleanPositionalValueInFunctionCall,
|
||||
// pygrep-hooks
|
||||
NoEval,
|
||||
DeprecatedLogWarn,
|
||||
BlanketTypeIgnore,
|
||||
// flake8-unused-arguments
|
||||
UnusedFunctionArgument(String),
|
||||
UnusedMethodArgument(String),
|
||||
@@ -925,7 +929,9 @@ impl CheckCode {
|
||||
pub fn lint_source(&self) -> &'static LintSource {
|
||||
match self {
|
||||
CheckCode::RUF100 => &LintSource::NoQA,
|
||||
CheckCode::E501 | CheckCode::W292 | CheckCode::UP009 => &LintSource::Lines,
|
||||
CheckCode::E501 | CheckCode::W292 | CheckCode::UP009 | CheckCode::PGH003 => {
|
||||
&LintSource::Lines
|
||||
}
|
||||
CheckCode::ERA001
|
||||
| CheckCode::Q000
|
||||
| CheckCode::Q001
|
||||
@@ -1260,6 +1266,8 @@ impl CheckCode {
|
||||
CheckCode::FBT003 => CheckKind::BooleanPositionalValueInFunctionCall,
|
||||
// pygrep-hooks
|
||||
CheckCode::PGH001 => CheckKind::NoEval,
|
||||
CheckCode::PGH002 => CheckKind::DeprecatedLogWarn,
|
||||
CheckCode::PGH003 => CheckKind::BlanketTypeIgnore,
|
||||
// flake8-unused-arguments
|
||||
CheckCode::ARG001 => CheckKind::UnusedFunctionArgument("...".to_string()),
|
||||
CheckCode::ARG002 => CheckKind::UnusedMethodArgument("...".to_string()),
|
||||
@@ -1504,6 +1512,8 @@ impl CheckCode {
|
||||
CheckCode::PDV015 => CheckCategory::PandasVet,
|
||||
CheckCode::PDV901 => CheckCategory::PandasVet,
|
||||
CheckCode::PGH001 => CheckCategory::PygrepHooks,
|
||||
CheckCode::PGH002 => CheckCategory::PygrepHooks,
|
||||
CheckCode::PGH003 => CheckCategory::PygrepHooks,
|
||||
CheckCode::PLC0414 => CheckCategory::Pylint,
|
||||
CheckCode::PLC2201 => CheckCategory::Pylint,
|
||||
CheckCode::PLC3002 => CheckCategory::Pylint,
|
||||
@@ -1847,6 +1857,8 @@ impl CheckKind {
|
||||
CheckKind::BooleanPositionalValueInFunctionCall => &CheckCode::FBT003,
|
||||
// pygrep-hooks
|
||||
CheckKind::NoEval => &CheckCode::PGH001,
|
||||
CheckKind::DeprecatedLogWarn => &CheckCode::PGH002,
|
||||
CheckKind::BlanketTypeIgnore => &CheckCode::PGH003,
|
||||
// flake8-unused-arguments
|
||||
CheckKind::UnusedFunctionArgument(..) => &CheckCode::ARG001,
|
||||
CheckKind::UnusedMethodArgument(..) => &CheckCode::ARG002,
|
||||
@@ -2684,6 +2696,12 @@ impl CheckKind {
|
||||
}
|
||||
// pygrep-hooks
|
||||
CheckKind::NoEval => "No builtin `eval()` allowed".to_string(),
|
||||
CheckKind::DeprecatedLogWarn => {
|
||||
"`warn` is deprecated in favor of `warning`".to_string()
|
||||
}
|
||||
CheckKind::BlanketTypeIgnore => {
|
||||
"Use specific error codes when ignoring type issues".to_string()
|
||||
}
|
||||
// flake8-unused-arguments
|
||||
CheckKind::UnusedFunctionArgument(name) => {
|
||||
format!("Unused function argument: `{name}`")
|
||||
@@ -2711,13 +2729,13 @@ impl CheckKind {
|
||||
"`.notna` is preferred to `.notnull`; functionality is equivalent".to_string()
|
||||
}
|
||||
CheckKind::UseOfDotIx => {
|
||||
"``ix` i` deprecated; use more explicit `.loc` o` `.iloc`".to_string()
|
||||
"`.ix` is deprecated; use more explicit `.loc` or `.iloc`".to_string()
|
||||
}
|
||||
CheckKind::UseOfDotAt => {
|
||||
"Use `.loc` instead of `.at`. If speed is important, use numpy.".to_string()
|
||||
}
|
||||
CheckKind::UseOfDotIat => {
|
||||
"Use `.iloc` instea` of `.iat`. If speed is important, use numpy.".to_string()
|
||||
"Use `.iloc` instead of `.iat`. If speed is important, use numpy.".to_string()
|
||||
}
|
||||
CheckKind::UseOfDotPivotOrUnstack => "`.pivot_table` is preferred to `.pivot` or \
|
||||
`.unstack`; provides same functionality"
|
||||
|
||||
@@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize};
|
||||
use strum_macros::{AsRefStr, EnumString};
|
||||
|
||||
use crate::checks::CheckCode;
|
||||
use crate::one_time_warning;
|
||||
|
||||
#[derive(
|
||||
EnumString, AsRefStr, Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize,
|
||||
@@ -325,6 +326,8 @@ pub enum CheckCodePrefix {
|
||||
PGH0,
|
||||
PGH00,
|
||||
PGH001,
|
||||
PGH002,
|
||||
PGH003,
|
||||
PLC,
|
||||
PLC0,
|
||||
PLC04,
|
||||
@@ -1243,7 +1246,7 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::I00 => vec![CheckCode::I001],
|
||||
CheckCodePrefix::I001 => vec![CheckCode::I001],
|
||||
CheckCodePrefix::I2 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1252,7 +1255,7 @@ impl CheckCodePrefix {
|
||||
vec![CheckCode::TID252]
|
||||
}
|
||||
CheckCodePrefix::I25 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1261,7 +1264,7 @@ impl CheckCodePrefix {
|
||||
vec![CheckCode::TID252]
|
||||
}
|
||||
CheckCodePrefix::I252 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1274,7 +1277,7 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::ICN00 => vec![CheckCode::ICN001],
|
||||
CheckCodePrefix::ICN001 => vec![CheckCode::ICN001],
|
||||
CheckCodePrefix::M => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1283,7 +1286,7 @@ impl CheckCodePrefix {
|
||||
vec![CheckCode::RUF100]
|
||||
}
|
||||
CheckCodePrefix::M0 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1292,7 +1295,7 @@ impl CheckCodePrefix {
|
||||
vec![CheckCode::RUF100]
|
||||
}
|
||||
CheckCodePrefix::M001 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1424,10 +1427,12 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::PDV9 => vec![CheckCode::PDV901],
|
||||
CheckCodePrefix::PDV90 => vec![CheckCode::PDV901],
|
||||
CheckCodePrefix::PDV901 => vec![CheckCode::PDV901],
|
||||
CheckCodePrefix::PGH => vec![CheckCode::PGH001],
|
||||
CheckCodePrefix::PGH0 => vec![CheckCode::PGH001],
|
||||
CheckCodePrefix::PGH00 => vec![CheckCode::PGH001],
|
||||
CheckCodePrefix::PGH => vec![CheckCode::PGH001, CheckCode::PGH002, CheckCode::PGH003],
|
||||
CheckCodePrefix::PGH0 => vec![CheckCode::PGH001, CheckCode::PGH002, CheckCode::PGH003],
|
||||
CheckCodePrefix::PGH00 => vec![CheckCode::PGH001, CheckCode::PGH002, CheckCode::PGH003],
|
||||
CheckCodePrefix::PGH001 => vec![CheckCode::PGH001],
|
||||
CheckCodePrefix::PGH002 => vec![CheckCode::PGH002],
|
||||
CheckCodePrefix::PGH003 => vec![CheckCode::PGH003],
|
||||
CheckCodePrefix::PLC => {
|
||||
vec![CheckCode::PLC0414, CheckCode::PLC2201, CheckCode::PLC3002]
|
||||
}
|
||||
@@ -1603,7 +1608,7 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::TID25 => vec![CheckCode::TID252],
|
||||
CheckCodePrefix::TID252 => vec![CheckCode::TID252],
|
||||
CheckCodePrefix::U => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1628,7 +1633,7 @@ impl CheckCodePrefix {
|
||||
]
|
||||
}
|
||||
CheckCodePrefix::U0 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1653,7 +1658,7 @@ impl CheckCodePrefix {
|
||||
]
|
||||
}
|
||||
CheckCodePrefix::U00 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1671,7 +1676,7 @@ impl CheckCodePrefix {
|
||||
]
|
||||
}
|
||||
CheckCodePrefix::U001 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1680,7 +1685,7 @@ impl CheckCodePrefix {
|
||||
vec![CheckCode::UP001]
|
||||
}
|
||||
CheckCodePrefix::U003 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1689,7 +1694,7 @@ impl CheckCodePrefix {
|
||||
vec![CheckCode::UP003]
|
||||
}
|
||||
CheckCodePrefix::U004 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1698,7 +1703,7 @@ impl CheckCodePrefix {
|
||||
vec![CheckCode::UP004]
|
||||
}
|
||||
CheckCodePrefix::U005 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1707,7 +1712,7 @@ impl CheckCodePrefix {
|
||||
vec![CheckCode::UP005]
|
||||
}
|
||||
CheckCodePrefix::U006 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1716,7 +1721,7 @@ impl CheckCodePrefix {
|
||||
vec![CheckCode::UP006]
|
||||
}
|
||||
CheckCodePrefix::U007 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1725,7 +1730,7 @@ impl CheckCodePrefix {
|
||||
vec![CheckCode::UP007]
|
||||
}
|
||||
CheckCodePrefix::U008 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1734,7 +1739,7 @@ impl CheckCodePrefix {
|
||||
vec![CheckCode::UP008]
|
||||
}
|
||||
CheckCodePrefix::U009 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1743,7 +1748,7 @@ impl CheckCodePrefix {
|
||||
vec![CheckCode::UP009]
|
||||
}
|
||||
CheckCodePrefix::U01 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1760,7 +1765,7 @@ impl CheckCodePrefix {
|
||||
]
|
||||
}
|
||||
CheckCodePrefix::U010 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1769,7 +1774,7 @@ impl CheckCodePrefix {
|
||||
vec![CheckCode::UP010]
|
||||
}
|
||||
CheckCodePrefix::U011 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1778,7 +1783,7 @@ impl CheckCodePrefix {
|
||||
vec![CheckCode::UP011]
|
||||
}
|
||||
CheckCodePrefix::U012 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1787,7 +1792,7 @@ impl CheckCodePrefix {
|
||||
vec![CheckCode::UP012]
|
||||
}
|
||||
CheckCodePrefix::U013 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1796,7 +1801,7 @@ impl CheckCodePrefix {
|
||||
vec![CheckCode::UP013]
|
||||
}
|
||||
CheckCodePrefix::U014 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1805,7 +1810,7 @@ impl CheckCodePrefix {
|
||||
vec![CheckCode::UP014]
|
||||
}
|
||||
CheckCodePrefix::U015 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -1814,7 +1819,7 @@ impl CheckCodePrefix {
|
||||
vec![CheckCode::UP015]
|
||||
}
|
||||
CheckCodePrefix::U016 => {
|
||||
eprintln!(
|
||||
one_time_warning!(
|
||||
"{}{} {}",
|
||||
"warning".yellow().bold(),
|
||||
":".bold(),
|
||||
@@ -2258,6 +2263,8 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::PGH0 => SuffixLength::One,
|
||||
CheckCodePrefix::PGH00 => SuffixLength::Two,
|
||||
CheckCodePrefix::PGH001 => SuffixLength::Three,
|
||||
CheckCodePrefix::PGH002 => SuffixLength::Three,
|
||||
CheckCodePrefix::PGH003 => SuffixLength::Three,
|
||||
CheckCodePrefix::PLC => SuffixLength::Zero,
|
||||
CheckCodePrefix::PLC0 => SuffixLength::One,
|
||||
CheckCodePrefix::PLC04 => SuffixLength::Two,
|
||||
|
||||
@@ -120,7 +120,7 @@ pub struct Cli {
|
||||
pub autoformat: bool,
|
||||
/// The name of the file when passing it through stdin.
|
||||
#[arg(long)]
|
||||
pub stdin_filename: Option<String>,
|
||||
pub stdin_filename: Option<PathBuf>,
|
||||
/// Explain a rule.
|
||||
#[arg(long)]
|
||||
pub explain: Option<CheckCode>,
|
||||
@@ -203,7 +203,7 @@ pub struct Arguments {
|
||||
pub show_files: bool,
|
||||
pub show_settings: bool,
|
||||
pub silent: bool,
|
||||
pub stdin_filename: Option<String>,
|
||||
pub stdin_filename: Option<PathBuf>,
|
||||
pub verbose: bool,
|
||||
pub watch: bool,
|
||||
}
|
||||
|
||||
@@ -56,9 +56,12 @@ fn duplicate_handler_exceptions<'a>(
|
||||
Range::from_located(expr),
|
||||
);
|
||||
if checker.patch(check.kind.code()) {
|
||||
// TODO(charlie): If we have a single element, remove the tuple.
|
||||
let mut generator = SourceGenerator::new();
|
||||
generator.unparse_expr(&type_pattern(unique_elts), 0);
|
||||
if unique_elts.len() == 1 {
|
||||
generator.unparse_expr(unique_elts[0], 0);
|
||||
} else {
|
||||
generator.unparse_expr(&type_pattern(unique_elts), 0);
|
||||
}
|
||||
if let Ok(content) = generator.generate() {
|
||||
check.amend(Fix::replacement(
|
||||
content,
|
||||
|
||||
@@ -1,52 +1,10 @@
|
||||
use anyhow::{bail, Result};
|
||||
use log::error;
|
||||
use rustpython_ast::{Excepthandler, ExcepthandlerKind, ExprKind, Located};
|
||||
use rustpython_parser::lexer;
|
||||
use rustpython_parser::lexer::Tok;
|
||||
use rustpython_ast::{Excepthandler, ExcepthandlerKind, ExprKind};
|
||||
|
||||
use crate::ast::helpers;
|
||||
use crate::ast::types::Range;
|
||||
use crate::autofix::Fix;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::checks::{Check, CheckKind};
|
||||
use crate::code_gen::SourceGenerator;
|
||||
use crate::SourceCodeLocator;
|
||||
|
||||
/// Given a statement like `except (ValueError,)`, find the range of the
|
||||
/// parenthesized expression.
|
||||
fn match_tuple_range<T>(located: &Located<T>, locator: &SourceCodeLocator) -> Result<Range> {
|
||||
// Extract contents from the source code.
|
||||
let range = Range::from_located(located);
|
||||
let contents = locator.slice_source_code_range(&range);
|
||||
|
||||
// Find the left (opening) and right (closing) parentheses.
|
||||
let mut location = None;
|
||||
let mut end_location = None;
|
||||
let mut count: usize = 0;
|
||||
for (start, tok, end) in lexer::make_tokenizer(&contents).flatten() {
|
||||
if matches!(tok, Tok::Lpar) {
|
||||
if count == 0 {
|
||||
location = Some(helpers::to_absolute(start, range.location));
|
||||
}
|
||||
count += 1;
|
||||
}
|
||||
|
||||
if matches!(tok, Tok::Rpar) {
|
||||
count -= 1;
|
||||
if count == 0 {
|
||||
end_location = Some(helpers::to_absolute(end, range.location));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
let (Some(location), Some(end_location)) = (location, end_location) else {
|
||||
bail!("Unable to find left and right parentheses");
|
||||
};
|
||||
Ok(Range {
|
||||
location,
|
||||
end_location,
|
||||
})
|
||||
}
|
||||
|
||||
/// B013
|
||||
pub fn redundant_tuple_in_exception_handler(checker: &mut Checker, handlers: &[Excepthandler]) {
|
||||
@@ -68,16 +26,11 @@ pub fn redundant_tuple_in_exception_handler(checker: &mut Checker, handlers: &[E
|
||||
let mut generator = SourceGenerator::new();
|
||||
generator.unparse_expr(elt, 0);
|
||||
if let Ok(content) = generator.generate() {
|
||||
match match_tuple_range(handler, checker.locator) {
|
||||
Ok(range) => {
|
||||
check.amend(Fix::replacement(
|
||||
content,
|
||||
range.location,
|
||||
range.end_location,
|
||||
));
|
||||
}
|
||||
Err(e) => error!("Failed to locate parentheses: {e}"),
|
||||
}
|
||||
check.amend(Fix::replacement(
|
||||
content,
|
||||
type_.location,
|
||||
type_.end_location.unwrap(),
|
||||
));
|
||||
}
|
||||
}
|
||||
checker.add_check(check);
|
||||
|
||||
@@ -6,10 +6,10 @@ expression: checks
|
||||
RedundantTupleInExceptionHandler: ValueError
|
||||
location:
|
||||
row: 3
|
||||
column: 8
|
||||
column: 7
|
||||
end_location:
|
||||
row: 3
|
||||
column: 19
|
||||
column: 20
|
||||
fix:
|
||||
content: ValueError
|
||||
location:
|
||||
|
||||
@@ -7,50 +7,50 @@ expression: checks
|
||||
- OSError
|
||||
location:
|
||||
row: 17
|
||||
column: 8
|
||||
column: 7
|
||||
end_location:
|
||||
row: 17
|
||||
column: 24
|
||||
column: 25
|
||||
fix:
|
||||
content: "OSError,"
|
||||
content: OSError
|
||||
location:
|
||||
row: 17
|
||||
column: 8
|
||||
column: 7
|
||||
end_location:
|
||||
row: 17
|
||||
column: 24
|
||||
column: 25
|
||||
- kind:
|
||||
DuplicateHandlerException:
|
||||
- MyError
|
||||
location:
|
||||
row: 28
|
||||
column: 8
|
||||
column: 7
|
||||
end_location:
|
||||
row: 28
|
||||
column: 24
|
||||
column: 25
|
||||
fix:
|
||||
content: "MyError,"
|
||||
content: MyError
|
||||
location:
|
||||
row: 28
|
||||
column: 8
|
||||
column: 7
|
||||
end_location:
|
||||
row: 28
|
||||
column: 24
|
||||
column: 25
|
||||
- kind:
|
||||
DuplicateHandlerException:
|
||||
- re.error
|
||||
location:
|
||||
row: 49
|
||||
column: 8
|
||||
column: 7
|
||||
end_location:
|
||||
row: 49
|
||||
column: 26
|
||||
column: 27
|
||||
fix:
|
||||
content: "re.error,"
|
||||
content: re.error
|
||||
location:
|
||||
row: 49
|
||||
column: 8
|
||||
column: 7
|
||||
end_location:
|
||||
row: 49
|
||||
column: 26
|
||||
column: 27
|
||||
|
||||
|
||||
@@ -126,7 +126,12 @@ pub(crate) fn check_path(
|
||||
.iter()
|
||||
.any(|check_code| matches!(check_code.lint_source(), LintSource::Lines))
|
||||
{
|
||||
checks.extend(check_lines(contents, settings, autofix));
|
||||
checks.extend(check_lines(
|
||||
contents,
|
||||
&directives.commented_lines,
|
||||
settings,
|
||||
autofix,
|
||||
));
|
||||
}
|
||||
|
||||
// Enforce `noqa` directives.
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
use anyhow::Result;
|
||||
use fern;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! one_time_warning {
|
||||
($($arg:tt)*) => {
|
||||
static WARNED: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
|
||||
if !WARNED.swap(true, std::sync::atomic::Ordering::SeqCst) {
|
||||
eprintln!($($arg)*);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! tell_user {
|
||||
($($arg:tt)*) => {
|
||||
|
||||
34
src/main.rs
34
src/main.rs
@@ -35,18 +35,27 @@ use path_absolutize::path_dedot;
|
||||
|
||||
/// Resolve the relevant settings strategy and defaults for the current
|
||||
/// invocation.
|
||||
fn resolve(config: Option<PathBuf>, overrides: &Overrides) -> Result<PyprojectDiscovery> {
|
||||
fn resolve(
|
||||
config: Option<&Path>,
|
||||
overrides: &Overrides,
|
||||
stdin_filename: Option<&Path>,
|
||||
) -> Result<PyprojectDiscovery> {
|
||||
if let Some(pyproject) = config {
|
||||
// First priority: the user specified a `pyproject.toml` file. Use that
|
||||
// `pyproject.toml` for _all_ configuration, and resolve paths relative to the
|
||||
// current working directory. (This matches ESLint's behavior.)
|
||||
let settings = resolve_settings(&pyproject, &Relativity::Cwd, Some(overrides))?;
|
||||
let settings = resolve_settings(pyproject, &Relativity::Cwd, Some(overrides))?;
|
||||
Ok(PyprojectDiscovery::Fixed(settings))
|
||||
} else if let Some(pyproject) = pyproject::find_pyproject_toml(path_dedot::CWD.as_path())? {
|
||||
// Second priority: find a `pyproject.toml` file in the current working path,
|
||||
// and resolve all paths relative to that directory. (With
|
||||
// `Strategy::Hierarchical`, we'll end up finding the "closest" `pyproject.toml`
|
||||
// file for every Python file later on, so these act as the "default" settings.)
|
||||
} else if let Some(pyproject) = pyproject::find_pyproject_toml(
|
||||
stdin_filename
|
||||
.as_ref()
|
||||
.unwrap_or(&path_dedot::CWD.as_path()),
|
||||
)? {
|
||||
// Second priority: find a `pyproject.toml` file in either an ancestor of
|
||||
// `stdin_filename` (if set) or the current working path all paths relative to
|
||||
// that directory. (With `Strategy::Hierarchical`, we'll end up finding
|
||||
// the "closest" `pyproject.toml` file for every Python file later on,
|
||||
// so these act as the "default" settings.)
|
||||
let settings = resolve_settings(&pyproject, &Relativity::Parent, Some(overrides))?;
|
||||
Ok(PyprojectDiscovery::Hierarchical(settings))
|
||||
} else if let Some(pyproject) = pyproject::find_user_pyproject_toml() {
|
||||
@@ -85,7 +94,11 @@ fn inner_main() -> Result<ExitCode> {
|
||||
|
||||
// Construct the "default" settings. These are used when no `pyproject.toml`
|
||||
// files are present, or files are injected from outside of the hierarchy.
|
||||
let pyproject_strategy = resolve(cli.config, &overrides)?;
|
||||
let pyproject_strategy = resolve(
|
||||
cli.config.as_deref(),
|
||||
&overrides,
|
||||
cli.stdin_filename.as_deref(),
|
||||
)?;
|
||||
|
||||
// Extract options that are included in `Settings`, but only apply at the top
|
||||
// level.
|
||||
@@ -207,9 +220,8 @@ fn inner_main() -> Result<ExitCode> {
|
||||
|
||||
// Generate lint violations.
|
||||
let diagnostics = if is_stdin {
|
||||
let filename = cli.stdin_filename.unwrap_or_else(|| "-".to_string());
|
||||
let path = Path::new(&filename);
|
||||
commands::run_stdin(&pyproject_strategy, path, autofix)?
|
||||
let path = cli.stdin_filename.unwrap_or_else(|| PathBuf::from("-"));
|
||||
commands::run_stdin(&pyproject_strategy, &path, autofix)?
|
||||
} else {
|
||||
commands::run(
|
||||
&cli.files,
|
||||
|
||||
@@ -26,7 +26,7 @@ pub fn line_too_long(lineno: usize, line: &str, max_line_length: usize) -> Optio
|
||||
|
||||
// Do not enforce the line length for commented lines that end with a URL
|
||||
// or contain only a single word.
|
||||
if first == "#" || chunks.last().map_or(true, |c| URL_REGEX.is_match(c)) {
|
||||
if first == "#" && chunks.last().map_or(true, |c| URL_REGEX.is_match(c)) {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,4 +46,15 @@ expression: checks
|
||||
row: 43
|
||||
column: 105
|
||||
fix: ~
|
||||
- kind:
|
||||
LineTooLong:
|
||||
- 129
|
||||
- 88
|
||||
location:
|
||||
row: 61
|
||||
column: 88
|
||||
end_location:
|
||||
row: 61
|
||||
column: 129
|
||||
fix: ~
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
pub mod checks;
|
||||
pub mod plugins;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
@@ -14,6 +14,9 @@ mod tests {
|
||||
|
||||
#[test_case(CheckCode::PGH001, Path::new("PGH001_0.py"); "PGH001_0")]
|
||||
#[test_case(CheckCode::PGH001, Path::new("PGH001_1.py"); "PGH001_1")]
|
||||
#[test_case(CheckCode::PGH002, Path::new("PGH002_0.py"); "PGH002_0")]
|
||||
#[test_case(CheckCode::PGH002, Path::new("PGH002_1.py"); "PGH002_1")]
|
||||
#[test_case(CheckCode::PGH003, Path::new("PGH003_0.py"); "PGH003_0")]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let mut checks = test_path(
|
||||
|
||||
22
src/pygrep_hooks/plugins/blanket_type_ignore.rs
Normal file
22
src/pygrep_hooks/plugins/blanket_type_ignore.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use rustpython_ast::Location;
|
||||
|
||||
use crate::ast::types::Range;
|
||||
use crate::checks::{Check, CheckKind};
|
||||
|
||||
static BLANKET_TYPE_IGNORE_REGEX: Lazy<Regex> =
|
||||
Lazy::new(|| Regex::new(r"# type:? *ignore($|\s)").unwrap());
|
||||
|
||||
/// PGH003 - use of blanket type ignore comments
|
||||
pub fn blanket_type_ignore(lineno: usize, line: &str) -> Option<Check> {
|
||||
BLANKET_TYPE_IGNORE_REGEX.find(line).map(|m| {
|
||||
Check::new(
|
||||
CheckKind::BlanketTypeIgnore,
|
||||
Range {
|
||||
location: Location::new(lineno + 1, m.start()),
|
||||
end_location: Location::new(lineno + 1, m.end()),
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
19
src/pygrep_hooks/plugins/deprecated_log_warn.rs
Normal file
19
src/pygrep_hooks/plugins/deprecated_log_warn.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
use rustpython_ast::Expr;
|
||||
|
||||
use crate::ast::helpers::{collect_call_paths, dealias_call_path, match_call_path};
|
||||
use crate::ast::types::Range;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::checks::{Check, CheckKind};
|
||||
|
||||
/// PGH002 - deprecated use of logging.warn
|
||||
pub fn deprecated_log_warn(checker: &mut Checker, func: &Expr) {
|
||||
let call_path = dealias_call_path(collect_call_paths(func), &checker.import_aliases);
|
||||
if call_path == ["log", "warn"]
|
||||
|| match_call_path(&call_path, "logging", "warn", &checker.from_imports)
|
||||
{
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::DeprecatedLogWarn,
|
||||
Range::from_located(func),
|
||||
));
|
||||
}
|
||||
}
|
||||
7
src/pygrep_hooks/plugins/mod.rs
Normal file
7
src/pygrep_hooks/plugins/mod.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
pub use blanket_type_ignore::blanket_type_ignore;
|
||||
pub use deprecated_log_warn::deprecated_log_warn;
|
||||
pub use no_eval::no_eval;
|
||||
|
||||
mod blanket_type_ignore;
|
||||
mod deprecated_log_warn;
|
||||
mod no_eval;
|
||||
@@ -4,6 +4,7 @@ use crate::ast::types::Range;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::checks::{Check, CheckKind};
|
||||
|
||||
/// PGH001 - no eval
|
||||
pub fn no_eval(checker: &mut Checker, func: &Expr) {
|
||||
let ExprKind::Name { id, .. } = &func.node else {
|
||||
return;
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
source: src/pygrep_hooks/mod.rs
|
||||
expression: checks
|
||||
---
|
||||
[]
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
source: src/pygrep_hooks/mod.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind: DeprecatedLogWarn
|
||||
location:
|
||||
row: 4
|
||||
column: 0
|
||||
end_location:
|
||||
row: 4
|
||||
column: 12
|
||||
fix: ~
|
||||
- kind: DeprecatedLogWarn
|
||||
location:
|
||||
row: 5
|
||||
column: 0
|
||||
end_location:
|
||||
row: 5
|
||||
column: 8
|
||||
fix: ~
|
||||
- kind: DeprecatedLogWarn
|
||||
location:
|
||||
row: 6
|
||||
column: 0
|
||||
end_location:
|
||||
row: 6
|
||||
column: 4
|
||||
fix: ~
|
||||
- kind: DeprecatedLogWarn
|
||||
location:
|
||||
row: 15
|
||||
column: 4
|
||||
end_location:
|
||||
row: 15
|
||||
column: 8
|
||||
fix: ~
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
source: src/pygrep_hooks/mod.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind: BlanketTypeIgnore
|
||||
location:
|
||||
row: 1
|
||||
column: 7
|
||||
end_location:
|
||||
row: 1
|
||||
column: 21
|
||||
fix: ~
|
||||
- kind: BlanketTypeIgnore
|
||||
location:
|
||||
row: 2
|
||||
column: 7
|
||||
end_location:
|
||||
row: 2
|
||||
column: 20
|
||||
fix: ~
|
||||
- kind: BlanketTypeIgnore
|
||||
location:
|
||||
row: 3
|
||||
column: 7
|
||||
end_location:
|
||||
row: 3
|
||||
column: 20
|
||||
fix: ~
|
||||
|
||||
@@ -38,7 +38,7 @@ pub struct Options {
|
||||
value_type = "Regex",
|
||||
example = r#"
|
||||
# Only ignore variables named "_".
|
||||
dummy_variable_rgx = "^_$"
|
||||
dummy-variable-rgx = "^_$"
|
||||
"#
|
||||
)]
|
||||
pub dummy_variable_rgx: Option<String>,
|
||||
|
||||
Reference in New Issue
Block a user