Compare commits

...

12 Commits

Author SHA1 Message Date
Charlie Marsh
1028ed3565 Bump version to 0.0.186 2022-12-18 14:30:30 -05:00
Anders Kaseorg
98897db6ac Add packaging status badge from repology (#1276) 2022-12-18 14:27:29 -05:00
Honkertonken
5ce4262112 Readme : Fix incorrect exmaple. (#1277) 2022-12-18 12:04:48 -05:00
Charlie Marsh
6b2359384d Print redirect warnings exactly once per code (#1280) 2022-12-18 12:03:49 -05:00
Harutaka Kawamura
d3443d7c19 Update RustPython to use correct Tuple location (#1278) 2022-12-18 08:53:57 -05:00
Anders Kaseorg
04b1e1de6f README: Add missing backtick (#1274) 2022-12-18 00:29:33 -05:00
Anders Kaseorg
c93c85300f Repair corrupted PDV007, PDV009 messages (#1273) 2022-12-18 00:29:12 -05:00
Charlie Marsh
73ed6f8654 Touch-up README 2022-12-17 21:38:45 -05:00
Charlie Marsh
eb183645f3 Add ruff-lsp to README (#1272)
Add ruff-lsp to README
2022-12-17 21:37:11 -05:00
Charlie Marsh
ef17aa93da Add ruff-lsp to README (#1272) 2022-12-17 21:37:00 -05:00
Charlie Marsh
f366b0147f Add ruff-lsp to README (#1272) 2022-12-17 21:35:44 -05:00
Charlie Marsh
fc88fa35ff Add instructions for Sublime Text installation (#1271) 2022-12-17 16:22:50 -05:00
17 changed files with 202 additions and 146 deletions

View File

@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.185
rev: v0.0.186
hooks:
- id: ruff

16
Cargo.lock generated
View File

@@ -724,7 +724,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flake8-to-ruff"
version = "0.0.185-dev.0"
version = "0.0.186-dev.0"
dependencies = [
"anyhow",
"clap 4.0.29",
@@ -1845,7 +1845,7 @@ dependencies = [
[[package]]
name = "ruff"
version = "0.0.185"
version = "0.0.186"
dependencies = [
"annotate-snippets 0.9.1",
"anyhow",
@@ -1901,7 +1901,7 @@ dependencies = [
[[package]]
name = "ruff_dev"
version = "0.0.185"
version = "0.0.186"
dependencies = [
"anyhow",
"clap 4.0.29",
@@ -1919,7 +1919,7 @@ dependencies = [
[[package]]
name = "ruff_macros"
version = "0.0.185"
version = "0.0.186"
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",

View File

@@ -6,7 +6,7 @@ members = [
[package]
name = "ruff"
version = "0.0.185"
version = "0.0.186"
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.186", 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"] }

123
README.md
View File

@@ -118,6 +118,8 @@ Ruff is available as [`ruff`](https://pypi.org/project/ruff/) on PyPI:
pip install ruff
```
[![Packaging status](https://repology.org/badge/vertical-allrepos/ruff-python-linter.svg?exclude_unsupported=1)](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.186
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 | |
@@ -933,21 +935,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
![](https://user-images.githubusercontent.com/1309177/205175763-cf34871d-5c05-4abf-9916-440afc82dbf8.gif)
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:
![Code Actions available in Neovim](https://user-images.githubusercontent.com/1309177/208278707-25fa37e4-079d-4597-ad35-b95dba066960.png)
### 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 +1037,15 @@ require'lspconfig'.pylsp.setup {
plugins = {
ruff = {
enabled = true
},
pycodestyle = {
enabled = false
},
pyflakes = {
enabled = false
},
mccabe = {
enabled = false
}
}
}
@@ -963,9 +1053,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 +1067,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`.
@@ -1488,7 +1575,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 = "^_$"
```
---

View File

@@ -771,7 +771,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flake8_to_ruff"
version = "0.0.185"
version = "0.0.186"
dependencies = [
"anyhow",
"clap",
@@ -1975,7 +1975,7 @@ dependencies = [
[[package]]
name = "ruff"
version = "0.0.185"
version = "0.0.186"
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",

View File

@@ -1,6 +1,6 @@
[package]
name = "flake8-to-ruff"
version = "0.0.185-dev.0"
version = "0.0.186-dev.0"
edition = "2021"
[lib]

View File

@@ -1,6 +1,6 @@
[package]
name = "ruff_dev"
version = "0.0.185"
version = "0.0.186"
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" }

View File

@@ -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');

View File

@@ -1,6 +1,6 @@
[package]
name = "ruff_macros"
version = "0.0.185"
version = "0.0.186"
edition = "2021"
[lib]

View File

@@ -2711,13 +2711,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"

View File

@@ -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,
@@ -1243,7 +1244,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 +1253,7 @@ impl CheckCodePrefix {
vec![CheckCode::TID252]
}
CheckCodePrefix::I25 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1261,7 +1262,7 @@ impl CheckCodePrefix {
vec![CheckCode::TID252]
}
CheckCodePrefix::I252 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1274,7 +1275,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 +1284,7 @@ impl CheckCodePrefix {
vec![CheckCode::RUF100]
}
CheckCodePrefix::M0 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1292,7 +1293,7 @@ impl CheckCodePrefix {
vec![CheckCode::RUF100]
}
CheckCodePrefix::M001 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1603,7 +1604,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 +1629,7 @@ impl CheckCodePrefix {
]
}
CheckCodePrefix::U0 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1653,7 +1654,7 @@ impl CheckCodePrefix {
]
}
CheckCodePrefix::U00 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1671,7 +1672,7 @@ impl CheckCodePrefix {
]
}
CheckCodePrefix::U001 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1680,7 +1681,7 @@ impl CheckCodePrefix {
vec![CheckCode::UP001]
}
CheckCodePrefix::U003 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1689,7 +1690,7 @@ impl CheckCodePrefix {
vec![CheckCode::UP003]
}
CheckCodePrefix::U004 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1698,7 +1699,7 @@ impl CheckCodePrefix {
vec![CheckCode::UP004]
}
CheckCodePrefix::U005 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1707,7 +1708,7 @@ impl CheckCodePrefix {
vec![CheckCode::UP005]
}
CheckCodePrefix::U006 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1716,7 +1717,7 @@ impl CheckCodePrefix {
vec![CheckCode::UP006]
}
CheckCodePrefix::U007 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1725,7 +1726,7 @@ impl CheckCodePrefix {
vec![CheckCode::UP007]
}
CheckCodePrefix::U008 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1734,7 +1735,7 @@ impl CheckCodePrefix {
vec![CheckCode::UP008]
}
CheckCodePrefix::U009 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1743,7 +1744,7 @@ impl CheckCodePrefix {
vec![CheckCode::UP009]
}
CheckCodePrefix::U01 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1760,7 +1761,7 @@ impl CheckCodePrefix {
]
}
CheckCodePrefix::U010 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1769,7 +1770,7 @@ impl CheckCodePrefix {
vec![CheckCode::UP010]
}
CheckCodePrefix::U011 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1778,7 +1779,7 @@ impl CheckCodePrefix {
vec![CheckCode::UP011]
}
CheckCodePrefix::U012 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1787,7 +1788,7 @@ impl CheckCodePrefix {
vec![CheckCode::UP012]
}
CheckCodePrefix::U013 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1796,7 +1797,7 @@ impl CheckCodePrefix {
vec![CheckCode::UP013]
}
CheckCodePrefix::U014 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1805,7 +1806,7 @@ impl CheckCodePrefix {
vec![CheckCode::UP014]
}
CheckCodePrefix::U015 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),
@@ -1814,7 +1815,7 @@ impl CheckCodePrefix {
vec![CheckCode::UP015]
}
CheckCodePrefix::U016 => {
eprintln!(
one_time_warning!(
"{}{} {}",
"warning".yellow().bold(),
":".bold(),

View File

@@ -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,

View File

@@ -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);

View File

@@ -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:

View File

@@ -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

View File

@@ -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)*) => {

View File

@@ -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>,