Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2315db7d13 | ||
|
|
f1a183c171 | ||
|
|
509c6d5ec7 | ||
|
|
6695988b59 | ||
|
|
e3867b172d | ||
|
|
4b8e30f350 | ||
|
|
8fd0d8e9d8 | ||
|
|
70895a8f1e | ||
|
|
f2c9f94f73 | ||
|
|
605c6069e2 | ||
|
|
92c2981b6d | ||
|
|
4ad8db3d61 |
12
.github/workflows/ci.yaml
vendored
12
.github/workflows/ci.yaml
vendored
@@ -116,18 +116,12 @@ jobs:
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- run: cargo install cargo-insta
|
||||
- run: pip install black[d]==22.12.0
|
||||
- name: Run tests
|
||||
run: |
|
||||
export INSTA_SNAPSHOT_REFERENCES_FILE="$(mktemp)"
|
||||
cargo test --all
|
||||
USED_SNAPSHOTS=$(cat $INSTA_SNAPSHOT_REFERENCES_FILE | xargs realpath --relative-to $PWD)
|
||||
UNUSED_SNAPSHOTS=$(cat <(git ls-files '*.snap') <(echo "$USED_SNAPSHOTS") | sort | uniq -u)
|
||||
if [ ! -z "$UNUSED_SNAPSHOTS" ]; then
|
||||
echo "Found unused snapshots:"
|
||||
echo "$UNUSED_SNAPSHOTS"
|
||||
exit 1
|
||||
fi
|
||||
cargo insta test --all --delete-unreferenced-snapshots
|
||||
git diff --exit-code
|
||||
- run: cargo test --package ruff --test black_compatibility_test -- --ignored
|
||||
|
||||
# TODO(charlie): Re-enable the `wasm-pack` tests.
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -181,3 +181,4 @@ cython_debug/
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
.idea/
|
||||
.vimspector.json
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
repos:
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.0.205
|
||||
rev: v0.0.206
|
||||
hooks:
|
||||
- id: ruff
|
||||
|
||||
|
||||
16
Cargo.lock
generated
16
Cargo.lock
generated
@@ -750,7 +750,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.205-dev.0"
|
||||
version = "0.0.206-dev.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.0.32",
|
||||
@@ -1878,7 +1878,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.205"
|
||||
version = "0.0.206"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.9.1",
|
||||
"anyhow",
|
||||
@@ -1946,7 +1946,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_dev"
|
||||
version = "0.0.205"
|
||||
version = "0.0.206"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.0.32",
|
||||
@@ -1967,7 +1967,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_macros"
|
||||
version = "0.0.205"
|
||||
version = "0.0.206"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2010,7 +2010,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-ast"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=8cb2b8292062adf13bde1b863a9b02c9f0bda3dd#8cb2b8292062adf13bde1b863a9b02c9f0bda3dd"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=71becd4059fdce4bce7010f1208ed3b1c883abba#71becd4059fdce4bce7010f1208ed3b1c883abba"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"rustpython-common",
|
||||
@@ -2020,7 +2020,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-common"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=8cb2b8292062adf13bde1b863a9b02c9f0bda3dd#8cb2b8292062adf13bde1b863a9b02c9f0bda3dd"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=71becd4059fdce4bce7010f1208ed3b1c883abba#71becd4059fdce4bce7010f1208ed3b1c883abba"
|
||||
dependencies = [
|
||||
"ascii",
|
||||
"cfg-if 1.0.0",
|
||||
@@ -2043,7 +2043,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-compiler-core"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=8cb2b8292062adf13bde1b863a9b02c9f0bda3dd#8cb2b8292062adf13bde1b863a9b02c9f0bda3dd"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=71becd4059fdce4bce7010f1208ed3b1c883abba#71becd4059fdce4bce7010f1208ed3b1c883abba"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitflags",
|
||||
@@ -2060,7 +2060,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-parser"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=8cb2b8292062adf13bde1b863a9b02c9f0bda3dd#8cb2b8292062adf13bde1b863a9b02c9f0bda3dd"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=71becd4059fdce4bce7010f1208ed3b1c883abba#71becd4059fdce4bce7010f1208ed3b1c883abba"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
|
||||
10
Cargo.toml
10
Cargo.toml
@@ -6,7 +6,7 @@ members = [
|
||||
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.205"
|
||||
version = "0.0.206"
|
||||
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.65.0"
|
||||
@@ -51,11 +51,11 @@ path-absolutize = { version = "3.0.14", features = ["once_cell_cache", "use_unix
|
||||
quick-junit = { version = "0.3.2" }
|
||||
regex = { version = "1.6.0" }
|
||||
ropey = { version = "1.5.0", features = ["cr_lines", "simd"], default-features = false }
|
||||
ruff_macros = { version = "0.0.205", path = "ruff_macros" }
|
||||
ruff_macros = { version = "0.0.206", path = "ruff_macros" }
|
||||
rustc-hash = { version = "1.1.0" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "8cb2b8292062adf13bde1b863a9b02c9f0bda3dd" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "8cb2b8292062adf13bde1b863a9b02c9f0bda3dd" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "8cb2b8292062adf13bde1b863a9b02c9f0bda3dd" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "71becd4059fdce4bce7010f1208ed3b1c883abba" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "71becd4059fdce4bce7010f1208ed3b1c883abba" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "71becd4059fdce4bce7010f1208ed3b1c883abba" }
|
||||
schemars = { version = "0.8.11" }
|
||||
semver = { version = "1.0.16" }
|
||||
serde = { version = "1.0.147", features = ["derive"] }
|
||||
|
||||
14
README.md
14
README.md
@@ -8,7 +8,11 @@
|
||||
An extremely fast Python linter, written in Rust.
|
||||
|
||||
<p align="center">
|
||||
<img alt="Bar chart with benchmark results" src="https://user-images.githubusercontent.com/1309177/187504482-6d9df992-a81d-4e86-9f6a-d958741c8182.svg">
|
||||
<picture align="center">
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/1309177/210156880-a97c2a0d-2c03-4393-8695-36547935a94e.svg">
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://user-images.githubusercontent.com/1309177/210156881-a88fd142-5008-4695-9407-d028cec3eff7.svg">
|
||||
<img alt="Shows a bar chart with benchmark results." src="https://user-images.githubusercontent.com/1309177/210156881-a88fd142-5008-4695-9407-d028cec3eff7.svg">
|
||||
</picture>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
@@ -169,7 +173,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.205'
|
||||
rev: 'v0.0.206'
|
||||
hooks:
|
||||
- id: ruff
|
||||
# Respect `exclude` and `extend-exclude` settings.
|
||||
@@ -682,7 +686,9 @@ For more, see [pyupgrade](https://pypi.org/project/pyupgrade/3.2.0/) on PyPI.
|
||||
| UP021 | ReplaceUniversalNewlines | `universal_newlines` is deprecated, use `text` | 🛠 |
|
||||
| UP022 | ReplaceStdoutStderr | Sending stdout and stderr to pipe is deprecated, use `capture_output` | 🛠 |
|
||||
| UP023 | RewriteCElementTree | `cElementTree` is deprecated, use `ElementTree` | 🛠 |
|
||||
| UP024 | OSErrorAlias | Replace aliased errors with `OSError` | 🛠 |
|
||||
| UP025 | RewriteUnicodeLiteral | Remove unicode literals from strings | 🛠 |
|
||||
| UP026 | RewriteMockImport | `mock` is deprecated, use `unittest.mock` | 🛠 |
|
||||
|
||||
### pep8-naming (N)
|
||||
|
||||
@@ -1301,7 +1307,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/) (20/33)
|
||||
- [`pyupgrade`](https://pypi.org/project/pyupgrade/) (21/33)
|
||||
- [`yesqa`](https://github.com/asottile/yesqa)
|
||||
|
||||
Note that, in some cases, Ruff uses different error code prefixes than would be found in the
|
||||
@@ -1360,7 +1366,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) (3/10), and a subset of the rules
|
||||
implemented in [`pyupgrade`](https://pypi.org/project/pyupgrade/) (20/33).
|
||||
implemented in [`pyupgrade`](https://pypi.org/project/pyupgrade/) (21/33).
|
||||
|
||||
If you're looking to use Ruff, but rely on an unsupported Flake8 plugin, free to file an Issue.
|
||||
|
||||
|
||||
4
flake8_to_ruff/Cargo.lock
generated
4
flake8_to_ruff/Cargo.lock
generated
@@ -771,7 +771,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8_to_ruff"
|
||||
version = "0.0.205"
|
||||
version = "0.0.206"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -1975,7 +1975,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.205"
|
||||
version = "0.0.206"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.205-dev.0"
|
||||
version = "0.0.206-dev.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "maturin"
|
||||
|
||||
[project]
|
||||
name = "ruff"
|
||||
version = "0.0.205"
|
||||
version = "0.0.206"
|
||||
description = "An extremely fast Python linter, written in Rust."
|
||||
authors = [
|
||||
{ name = "Charlie Marsh", email = "charlie.r.marsh@gmail.com" },
|
||||
|
||||
11
resources/test/fixtures/flake8_return/RET504.py
vendored
11
resources/test/fixtures/flake8_return/RET504.py
vendored
@@ -137,6 +137,14 @@ def x():
|
||||
return a
|
||||
|
||||
|
||||
# Considered OK, since attribute assignments can have side effects.
|
||||
class X:
|
||||
def x(self):
|
||||
a = self.property
|
||||
self.property = None
|
||||
return a
|
||||
|
||||
|
||||
# Test cases for using value for assignment then returning it
|
||||
# See:https://github.com/afonasev/flake8-return/issues/47
|
||||
def resolve_from_url(self, url: str) -> dict:
|
||||
@@ -238,13 +246,16 @@ def close(self):
|
||||
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
|
||||
|
||||
22
resources/test/fixtures/pydocstyle/D400.py
vendored
22
resources/test/fixtures/pydocstyle/D400.py
vendored
@@ -35,7 +35,6 @@ def f():
|
||||
...
|
||||
|
||||
|
||||
|
||||
def f():
|
||||
r"Here's a line without a period"
|
||||
...
|
||||
@@ -71,3 +70,24 @@ def f():
|
||||
Here's a line without a period,
|
||||
but here's the next line with trailing space """
|
||||
...
|
||||
|
||||
|
||||
def f(rounds: list[int], number: int) -> bool:
|
||||
"""
|
||||
:param rounds: list - rounds played.
|
||||
:param number: int - round number.
|
||||
:return: bool - was the round played?
|
||||
"""
|
||||
return number in rounds
|
||||
|
||||
|
||||
def f(rounds: list[int], number: int) -> bool:
|
||||
"""
|
||||
Args:
|
||||
rounds (list): rounds played.
|
||||
number (int): round number.
|
||||
|
||||
Returns:
|
||||
bool: was the round played?
|
||||
"""
|
||||
return number in rounds
|
||||
|
||||
3
resources/test/fixtures/pyflakes/F541.py
vendored
3
resources/test/fixtures/pyflakes/F541.py
vendored
@@ -20,7 +20,8 @@ v = 23.234234
|
||||
|
||||
# OK
|
||||
f"{v:0.2f}"
|
||||
f"{f'{v:0.2f}'}"
|
||||
|
||||
# OK (false negatives)
|
||||
# Errors
|
||||
f"{v:{f'0.2f'}}"
|
||||
f"{f''}"
|
||||
|
||||
3
resources/test/fixtures/pyflakes/F821_0.py
vendored
3
resources/test/fixtures/pyflakes/F821_0.py
vendored
@@ -89,7 +89,8 @@ A = (
|
||||
f'B'
|
||||
f'{B}'
|
||||
)
|
||||
|
||||
C = f'{A:{B}}'
|
||||
C = f'{A:{f"{B}"}}'
|
||||
|
||||
from typing import Annotated, Literal
|
||||
|
||||
|
||||
98
resources/test/fixtures/pyupgrade/UP024_0.py
vendored
Normal file
98
resources/test/fixtures/pyupgrade/UP024_0.py
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
import mmap, select, socket
|
||||
from mmap import error
|
||||
# These should be fixed
|
||||
try:
|
||||
pass
|
||||
except EnvironmentError:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except WindowsError:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except mmap.error:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except select.error:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except socket.error:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except error:
|
||||
pass
|
||||
|
||||
# Should NOT be in parentheses when replaced
|
||||
|
||||
try:
|
||||
pass
|
||||
except (IOError,):
|
||||
pass
|
||||
try:
|
||||
pass
|
||||
except (mmap.error,):
|
||||
pass
|
||||
try:
|
||||
pass
|
||||
except (EnvironmentError, IOError, OSError, select.error):
|
||||
pass
|
||||
|
||||
# Should be kept in parentheses (because multiple)
|
||||
|
||||
try:
|
||||
pass
|
||||
except (IOError, KeyError, OSError):
|
||||
pass
|
||||
|
||||
# First should change, second should not
|
||||
from .mmap import error
|
||||
try:
|
||||
pass
|
||||
except (IOError, error):
|
||||
pass
|
||||
# These should not change
|
||||
|
||||
from foo import error
|
||||
|
||||
try:
|
||||
pass
|
||||
except (OSError, error):
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except AssertionError:
|
||||
pass
|
||||
try:
|
||||
pass
|
||||
except (mmap).error:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (OSError, KeyError):
|
||||
pass
|
||||
17
resources/test/fixtures/pyupgrade/UP024_1.py
vendored
Normal file
17
resources/test/fixtures/pyupgrade/UP024_1.py
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import mmap, socket, select
|
||||
|
||||
try:
|
||||
pass
|
||||
except (OSError, mmap.error, IOError):
|
||||
pass
|
||||
except (OSError, socket.error, KeyError):
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (
|
||||
OSError,
|
||||
select.error,
|
||||
IOError,
|
||||
):
|
||||
pass
|
||||
50
resources/test/fixtures/pyupgrade/UP024_2.py
vendored
Normal file
50
resources/test/fixtures/pyupgrade/UP024_2.py
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
# These should not change
|
||||
raise ValueError
|
||||
raise ValueError(1)
|
||||
|
||||
from .mmap import error
|
||||
raise error
|
||||
|
||||
# Testing the modules
|
||||
import socket, mmap, select
|
||||
raise socket.error
|
||||
raise mmap.error
|
||||
raise select.error
|
||||
|
||||
raise socket.error()
|
||||
raise mmap.error(1)
|
||||
raise select.error(1, 2)
|
||||
|
||||
raise socket.error(
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
)
|
||||
|
||||
from mmap import error
|
||||
raise error
|
||||
|
||||
from socket import error
|
||||
raise error(1)
|
||||
|
||||
from select import error
|
||||
raise error(1, 2)
|
||||
|
||||
# Testing the names
|
||||
raise EnvironmentError
|
||||
raise IOError
|
||||
raise WindowsError
|
||||
|
||||
raise EnvironmentError()
|
||||
raise IOError(1)
|
||||
raise WindowsError(1, 2)
|
||||
|
||||
raise EnvironmentError(
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
)
|
||||
|
||||
raise WindowsError
|
||||
raise EnvironmentError(1)
|
||||
raise IOError(1, 2)
|
||||
74
resources/test/fixtures/pyupgrade/UP026.py
vendored
Normal file
74
resources/test/fixtures/pyupgrade/UP026.py
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
# These should be changed
|
||||
if True:
|
||||
import mock
|
||||
|
||||
if True:
|
||||
import mock, sys
|
||||
|
||||
# This goes to from unitest import mock
|
||||
import mock.mock
|
||||
|
||||
# Mock should go on a new line as `from unittest import mock`
|
||||
import contextlib, mock, sys
|
||||
|
||||
# Mock should go on a new line as `from unittest import mock`
|
||||
import mock, sys
|
||||
x = "This code should be preserved one line below the mock"
|
||||
|
||||
# Mock should go on a new line as `from unittest import mock`
|
||||
from mock import mock
|
||||
|
||||
# Should keep trailing comma
|
||||
from mock import (
|
||||
mock,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
)
|
||||
|
||||
# Should not get a trailing comma
|
||||
from mock import (
|
||||
mock,
|
||||
a,
|
||||
b,
|
||||
c
|
||||
)
|
||||
|
||||
if True:
|
||||
if False:
|
||||
from mock import (
|
||||
mock,
|
||||
a,
|
||||
b,
|
||||
c
|
||||
)
|
||||
|
||||
# These should not change:
|
||||
import os, io
|
||||
|
||||
# Mock should go on a new line as `from unittest import mock`
|
||||
import mock, mock
|
||||
|
||||
# Mock should go on a new line as `from unittest import mock as foo`
|
||||
import mock as foo
|
||||
|
||||
# Mock should go on a new line as `from unittest import mock as foo`
|
||||
from mock import mock as foo
|
||||
|
||||
if True:
|
||||
# This should yield multiple, aliased imports.
|
||||
import mock as foo, mock as bar, mock
|
||||
|
||||
# This should yield multiple, aliased imports, and preserve `os`.
|
||||
import mock as foo, mock as bar, mock, os
|
||||
|
||||
if True:
|
||||
# This should yield multiple, aliased imports.
|
||||
from mock import mock as foo, mock as bar, mock
|
||||
|
||||
|
||||
# This should be unchanged.
|
||||
x = mock.Mock()
|
||||
|
||||
# This should change to `mock.Mock`().
|
||||
x = mock.mock.Mock()
|
||||
@@ -909,7 +909,9 @@
|
||||
"UP021",
|
||||
"UP022",
|
||||
"UP023",
|
||||
"UP024",
|
||||
"UP025",
|
||||
"UP026",
|
||||
"W",
|
||||
"W2",
|
||||
"W29",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_dev"
|
||||
version = "0.0.205"
|
||||
version = "0.0.206"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
@@ -11,9 +11,9 @@ 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 = "8cb2b8292062adf13bde1b863a9b02c9f0bda3dd" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "8cb2b8292062adf13bde1b863a9b02c9f0bda3dd" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "8cb2b8292062adf13bde1b863a9b02c9f0bda3dd" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "71becd4059fdce4bce7010f1208ed3b1c883abba" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "71becd4059fdce4bce7010f1208ed3b1c883abba" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "71becd4059fdce4bce7010f1208ed3b1c883abba" }
|
||||
schemars = { version = "0.8.11" }
|
||||
serde_json = {version="1.0.91"}
|
||||
strum = { version = "0.24.1", features = ["strum_macros"] }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_macros"
|
||||
version = "0.0.205"
|
||||
version = "0.0.206"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -335,20 +335,17 @@ pub fn to_absolute(relative: Location, base: Location) -> Location {
|
||||
|
||||
/// Return `true` if a `Stmt` has leading content.
|
||||
pub fn match_leading_content(stmt: &Stmt, locator: &SourceCodeLocator) -> bool {
|
||||
let range = Range {
|
||||
location: Location::new(stmt.location.row(), 0),
|
||||
end_location: stmt.location,
|
||||
};
|
||||
let range = Range::new(Location::new(stmt.location.row(), 0), stmt.location);
|
||||
let prefix = locator.slice_source_code_range(&range);
|
||||
prefix.chars().any(|char| !char.is_whitespace())
|
||||
}
|
||||
|
||||
/// Return `true` if a `Stmt` has trailing content.
|
||||
pub fn match_trailing_content(stmt: &Stmt, locator: &SourceCodeLocator) -> bool {
|
||||
let range = Range {
|
||||
location: stmt.end_location.unwrap(),
|
||||
end_location: Location::new(stmt.end_location.unwrap().row() + 1, 0),
|
||||
};
|
||||
let range = Range::new(
|
||||
stmt.end_location.unwrap(),
|
||||
Location::new(stmt.end_location.unwrap().row() + 1, 0),
|
||||
);
|
||||
let suffix = locator.slice_source_code_range(&range);
|
||||
for char in suffix.chars() {
|
||||
if char == '#' {
|
||||
@@ -384,10 +381,7 @@ pub fn identifier_range(stmt: &Stmt, locator: &SourceCodeLocator) -> Range {
|
||||
let contents = locator.slice_source_code_range(&Range::from_located(stmt));
|
||||
for (start, tok, end) in lexer::make_tokenizer_located(&contents, stmt.location).flatten() {
|
||||
if matches!(tok, Tok::Name { .. }) {
|
||||
return Range {
|
||||
location: start,
|
||||
end_location: end,
|
||||
};
|
||||
return Range::new(start, end);
|
||||
}
|
||||
}
|
||||
error!("Failed to find identifier for {:?}", stmt);
|
||||
@@ -419,20 +413,15 @@ pub fn excepthandler_name_range(
|
||||
match (name, type_) {
|
||||
(Some(_), Some(type_)) => {
|
||||
let type_end_location = type_.end_location.unwrap();
|
||||
let contents = locator.slice_source_code_range(&Range {
|
||||
location: type_end_location,
|
||||
end_location: body[0].location,
|
||||
});
|
||||
let contents =
|
||||
locator.slice_source_code_range(&Range::new(type_end_location, body[0].location));
|
||||
let range = lexer::make_tokenizer_located(&contents, type_end_location)
|
||||
.flatten()
|
||||
.tuple_windows()
|
||||
.find(|(tok, next_tok)| {
|
||||
matches!(tok.1, Tok::As) && matches!(next_tok.1, Tok::Name { .. })
|
||||
})
|
||||
.map(|((..), (location, _, end_location))| Range {
|
||||
location,
|
||||
end_location,
|
||||
});
|
||||
.map(|((..), (location, _, end_location))| Range::new(location, end_location));
|
||||
range
|
||||
}
|
||||
_ => None,
|
||||
@@ -506,10 +495,10 @@ pub fn preceded_by_continuation(stmt: &Stmt, locator: &SourceCodeLocator) -> boo
|
||||
// make conservative choices.
|
||||
// TODO(charlie): Come up with a more robust strategy.
|
||||
if stmt.location.row() > 1 {
|
||||
let range = Range {
|
||||
location: Location::new(stmt.location.row() - 1, 0),
|
||||
end_location: Location::new(stmt.location.row(), 0),
|
||||
};
|
||||
let range = Range::new(
|
||||
Location::new(stmt.location.row() - 1, 0),
|
||||
Location::new(stmt.location.row(), 0),
|
||||
);
|
||||
let line = locator.slice_source_code_range(&range);
|
||||
if line.trim().ends_with('\\') {
|
||||
return true;
|
||||
@@ -733,10 +722,7 @@ y = 2
|
||||
let locator = SourceCodeLocator::new(contents);
|
||||
assert_eq!(
|
||||
identifier_range(stmt, &locator),
|
||||
Range {
|
||||
location: Location::new(1, 4),
|
||||
end_location: Location::new(1, 5),
|
||||
}
|
||||
Range::new(Location::new(1, 4), Location::new(1, 5),)
|
||||
);
|
||||
|
||||
let contents = r#"
|
||||
@@ -750,10 +736,7 @@ def \
|
||||
let locator = SourceCodeLocator::new(contents);
|
||||
assert_eq!(
|
||||
identifier_range(stmt, &locator),
|
||||
Range {
|
||||
location: Location::new(2, 2),
|
||||
end_location: Location::new(2, 3),
|
||||
}
|
||||
Range::new(Location::new(2, 2), Location::new(2, 3),)
|
||||
);
|
||||
|
||||
let contents = "class Class(): pass".trim();
|
||||
@@ -762,10 +745,7 @@ def \
|
||||
let locator = SourceCodeLocator::new(contents);
|
||||
assert_eq!(
|
||||
identifier_range(stmt, &locator),
|
||||
Range {
|
||||
location: Location::new(1, 6),
|
||||
end_location: Location::new(1, 11),
|
||||
}
|
||||
Range::new(Location::new(1, 6), Location::new(1, 11),)
|
||||
);
|
||||
|
||||
let contents = "class Class: pass".trim();
|
||||
@@ -774,10 +754,7 @@ def \
|
||||
let locator = SourceCodeLocator::new(contents);
|
||||
assert_eq!(
|
||||
identifier_range(stmt, &locator),
|
||||
Range {
|
||||
location: Location::new(1, 6),
|
||||
end_location: Location::new(1, 11),
|
||||
}
|
||||
Range::new(Location::new(1, 6), Location::new(1, 11),)
|
||||
);
|
||||
|
||||
let contents = r#"
|
||||
@@ -791,10 +768,7 @@ class Class():
|
||||
let locator = SourceCodeLocator::new(contents);
|
||||
assert_eq!(
|
||||
identifier_range(stmt, &locator),
|
||||
Range {
|
||||
location: Location::new(2, 6),
|
||||
end_location: Location::new(2, 11),
|
||||
}
|
||||
Range::new(Location::new(2, 6), Location::new(2, 11),)
|
||||
);
|
||||
|
||||
let contents = r#"x = y + 1"#.trim();
|
||||
@@ -803,10 +777,7 @@ class Class():
|
||||
let locator = SourceCodeLocator::new(contents);
|
||||
assert_eq!(
|
||||
identifier_range(stmt, &locator),
|
||||
Range {
|
||||
location: Location::new(1, 0),
|
||||
end_location: Location::new(1, 9),
|
||||
}
|
||||
Range::new(Location::new(1, 0), Location::new(1, 9),)
|
||||
);
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -22,12 +22,16 @@ pub struct Range {
|
||||
}
|
||||
|
||||
impl Range {
|
||||
pub fn from_located<T>(located: &Located<T>) -> Self {
|
||||
Range {
|
||||
location: located.location,
|
||||
end_location: located.end_location.unwrap(),
|
||||
pub fn new(location: Location, end_location: Location) -> Self {
|
||||
Self {
|
||||
location,
|
||||
end_location,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_located<T>(located: &Located<T>) -> Self {
|
||||
Range::new(located.location, located.end_location.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -38,6 +38,9 @@ pub trait Visitor<'a> {
|
||||
fn visit_excepthandler(&mut self, excepthandler: &'a Excepthandler) {
|
||||
walk_excepthandler(self, excepthandler);
|
||||
}
|
||||
fn visit_format_spec(&mut self, format_spec: &'a Expr) {
|
||||
walk_expr(self, format_spec);
|
||||
}
|
||||
fn visit_arguments(&mut self, arguments: &'a Arguments) {
|
||||
walk_arguments(self, arguments);
|
||||
}
|
||||
@@ -387,7 +390,7 @@ pub fn walk_expr<'a, V: Visitor<'a> + ?Sized>(visitor: &mut V, expr: &'a Expr) {
|
||||
} => {
|
||||
visitor.visit_expr(value);
|
||||
if let Some(expr) = format_spec {
|
||||
visitor.visit_expr(expr);
|
||||
visitor.visit_format_spec(expr);
|
||||
}
|
||||
}
|
||||
ExprKind::JoinedStr { values } => {
|
||||
|
||||
@@ -9,10 +9,10 @@ use crate::checkers::ast::Checker;
|
||||
/// Extract the leading indentation from a line.
|
||||
pub fn indentation<'a, T>(checker: &'a Checker, located: &'a Located<T>) -> Cow<'a, str> {
|
||||
let range = Range::from_located(located);
|
||||
checker.locator.slice_source_code_range(&Range {
|
||||
location: Location::new(range.location.row(), 0),
|
||||
end_location: Location::new(range.location.row(), range.location.column()),
|
||||
})
|
||||
checker.locator.slice_source_code_range(&Range::new(
|
||||
Location::new(range.location.row(), 0),
|
||||
Location::new(range.location.row(), range.location.column()),
|
||||
))
|
||||
}
|
||||
|
||||
/// Extract the leading words from a line of text.
|
||||
|
||||
@@ -68,10 +68,7 @@ fn apply_fixes<'a>(
|
||||
}
|
||||
|
||||
// Add all contents from `last_pos` to `fix.location`.
|
||||
let slice = locator.slice_source_code_range(&Range {
|
||||
location: last_pos,
|
||||
end_location: fix.location,
|
||||
});
|
||||
let slice = locator.slice_source_code_range(&Range::new(last_pos, fix.location));
|
||||
output.append(&slice);
|
||||
|
||||
// Add the patch itself.
|
||||
|
||||
@@ -91,7 +91,6 @@ pub struct Checker<'a> {
|
||||
in_type_definition: bool,
|
||||
in_deferred_string_type_definition: bool,
|
||||
in_deferred_type_definition: bool,
|
||||
in_f_string: bool,
|
||||
in_literal: bool,
|
||||
in_subscript: bool,
|
||||
seen_import_boundary: bool,
|
||||
@@ -148,7 +147,6 @@ impl<'a> Checker<'a> {
|
||||
in_type_definition: false,
|
||||
in_deferred_string_type_definition: false,
|
||||
in_deferred_type_definition: false,
|
||||
in_f_string: false,
|
||||
in_literal: false,
|
||||
in_subscript: false,
|
||||
seen_import_boundary: false,
|
||||
@@ -215,10 +213,10 @@ impl<'a> Checker<'a> {
|
||||
return false;
|
||||
}
|
||||
let noqa_lineno = self.noqa_line_for.get(&lineno).unwrap_or(&lineno);
|
||||
let line = self.locator.slice_source_code_range(&Range {
|
||||
location: Location::new(*noqa_lineno, 0),
|
||||
end_location: Location::new(noqa_lineno + 1, 0),
|
||||
});
|
||||
let line = self.locator.slice_source_code_range(&Range::new(
|
||||
Location::new(*noqa_lineno, 0),
|
||||
Location::new(noqa_lineno + 1, 0),
|
||||
));
|
||||
match noqa::extract_noqa_directive(&line) {
|
||||
Directive::None => false,
|
||||
Directive::All(..) => true,
|
||||
@@ -643,6 +641,9 @@ where
|
||||
if self.settings.enabled.contains(&CheckCode::UP023) {
|
||||
pyupgrade::plugins::replace_c_element_tree(self, stmt);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::UP026) {
|
||||
pyupgrade::plugins::rewrite_mock_import(self, stmt);
|
||||
}
|
||||
|
||||
for alias in names {
|
||||
if alias.node.name.contains('.') && alias.node.asname.is_none() {
|
||||
@@ -854,6 +855,9 @@ where
|
||||
pyupgrade::plugins::unnecessary_future_import(self, stmt, names);
|
||||
}
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::UP026) {
|
||||
pyupgrade::plugins::rewrite_mock_import(self, stmt);
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::TID251) {
|
||||
if let Some(module) = module {
|
||||
@@ -1107,6 +1111,11 @@ where
|
||||
flake8_errmsg::plugins::string_in_exception(self, exc);
|
||||
}
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::UP024) {
|
||||
if let Some(item) = exc {
|
||||
pyupgrade::plugins::os_error_alias(self, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
StmtKind::AugAssign { target, .. } => {
|
||||
self.handle_node_load(target);
|
||||
@@ -1191,6 +1200,9 @@ where
|
||||
if self.settings.enabled.contains(&CheckCode::B013) {
|
||||
flake8_bugbear::plugins::redundant_tuple_in_exception_handler(self, handlers);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::UP024) {
|
||||
pyupgrade::plugins::os_error_alias(self, handlers);
|
||||
}
|
||||
}
|
||||
StmtKind::Assign { targets, value, .. } => {
|
||||
if self.settings.enabled.contains(&CheckCode::E731) {
|
||||
@@ -1472,7 +1484,6 @@ where
|
||||
|
||||
self.push_expr(expr);
|
||||
|
||||
let prev_in_f_string = self.in_f_string;
|
||||
let prev_in_literal = self.in_literal;
|
||||
let prev_in_type_definition = self.in_type_definition;
|
||||
|
||||
@@ -1595,6 +1606,10 @@ where
|
||||
if self.settings.enabled.contains(&CheckCode::UP019) {
|
||||
pyupgrade::plugins::typing_text_str_alias(self, expr);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::UP026) {
|
||||
pyupgrade::plugins::rewrite_mock_attribute(self, expr);
|
||||
}
|
||||
|
||||
if self.settings.enabled.contains(&CheckCode::YTT202) {
|
||||
flake8_2020::plugins::name_or_attribute(self, expr);
|
||||
}
|
||||
@@ -1716,6 +1731,9 @@ where
|
||||
if self.settings.enabled.contains(&CheckCode::UP022) {
|
||||
pyupgrade::plugins::replace_stdout_stderr(self, expr, keywords);
|
||||
}
|
||||
if self.settings.enabled.contains(&CheckCode::UP024) {
|
||||
pyupgrade::plugins::os_error_alias(self, expr);
|
||||
}
|
||||
|
||||
// flake8-print
|
||||
if self.settings.enabled.contains(&CheckCode::T201)
|
||||
@@ -2159,9 +2177,7 @@ where
|
||||
}
|
||||
}
|
||||
ExprKind::JoinedStr { values } => {
|
||||
// Conversion flags are parsed as f-strings without placeholders, so skip
|
||||
// nested f-strings, which would lead to false positives.
|
||||
if !self.in_f_string && self.settings.enabled.contains(&CheckCode::F541) {
|
||||
if self.settings.enabled.contains(&CheckCode::F541) {
|
||||
if !values
|
||||
.iter()
|
||||
.any(|value| matches!(value.node, ExprKind::FormattedValue { .. }))
|
||||
@@ -2665,9 +2681,7 @@ where
|
||||
self.in_subscript = prev_in_subscript;
|
||||
}
|
||||
ExprKind::JoinedStr { .. } => {
|
||||
self.in_f_string = true;
|
||||
visitor::walk_expr(self, expr);
|
||||
self.in_f_string = prev_in_f_string;
|
||||
}
|
||||
_ => visitor::walk_expr(self, expr),
|
||||
}
|
||||
@@ -2686,7 +2700,6 @@ where
|
||||
|
||||
self.in_type_definition = prev_in_type_definition;
|
||||
self.in_literal = prev_in_literal;
|
||||
self.in_f_string = prev_in_f_string;
|
||||
|
||||
self.pop_expr();
|
||||
}
|
||||
@@ -2790,6 +2803,17 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_format_spec(&mut self, format_spec: &'b Expr) {
|
||||
match &format_spec.node {
|
||||
ExprKind::JoinedStr { values } => {
|
||||
for value in values {
|
||||
self.visit_expr(value);
|
||||
}
|
||||
}
|
||||
_ => unreachable!("Unexpected expression for format_spec"),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_arguments(&mut self, arguments: &'b Arguments) {
|
||||
if self.settings.enabled.contains(&CheckCode::B006) {
|
||||
flake8_bugbear::plugins::mutable_argument_default(self, arguments);
|
||||
@@ -3869,10 +3893,10 @@ impl<'a> Checker<'a> {
|
||||
let content = self
|
||||
.locator
|
||||
.slice_source_code_range(&Range::from_located(expr));
|
||||
let indentation = self.locator.slice_source_code_range(&Range {
|
||||
location: Location::new(expr.location.row(), 0),
|
||||
end_location: Location::new(expr.location.row(), expr.location.column()),
|
||||
});
|
||||
let indentation = self.locator.slice_source_code_range(&Range::new(
|
||||
Location::new(expr.location.row(), 0),
|
||||
Location::new(expr.location.row(), expr.location.column()),
|
||||
));
|
||||
let body = pydocstyle::helpers::raw_contents(&content);
|
||||
let docstring = Docstring {
|
||||
kind: definition.kind,
|
||||
|
||||
@@ -102,10 +102,7 @@ pub fn check_noqa(
|
||||
if matches.is_empty() {
|
||||
let mut check = Check::new(
|
||||
CheckKind::UnusedNOQA(None),
|
||||
Range {
|
||||
location: Location::new(row + 1, start),
|
||||
end_location: Location::new(row + 1, end),
|
||||
},
|
||||
Range::new(Location::new(row + 1, start), Location::new(row + 1, end)),
|
||||
);
|
||||
if matches!(autofix, flags::Autofix::Enabled)
|
||||
&& settings.fixable.contains(check.kind.code())
|
||||
@@ -169,10 +166,7 @@ pub fn check_noqa(
|
||||
.map(|code| (*code).to_string())
|
||||
.collect(),
|
||||
})),
|
||||
Range {
|
||||
location: Location::new(row + 1, start),
|
||||
end_location: Location::new(row + 1, end),
|
||||
},
|
||||
Range::new(Location::new(row + 1, start), Location::new(row + 1, end)),
|
||||
);
|
||||
if matches!(autofix, flags::Autofix::Enabled)
|
||||
&& settings.fixable.contains(check.kind.code())
|
||||
|
||||
@@ -236,7 +236,9 @@ pub enum CheckCode {
|
||||
UP021,
|
||||
UP022,
|
||||
UP023,
|
||||
UP024,
|
||||
UP025,
|
||||
UP026,
|
||||
// pydocstyle
|
||||
D100,
|
||||
D101,
|
||||
@@ -703,6 +705,12 @@ pub struct UnusedCodes {
|
||||
pub unmatched: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum MockReference {
|
||||
Import,
|
||||
Attribute,
|
||||
}
|
||||
|
||||
#[derive(AsRefStr, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum CheckKind {
|
||||
// pycodestyle errors
|
||||
@@ -907,7 +915,9 @@ pub enum CheckKind {
|
||||
ReplaceUniversalNewlines,
|
||||
ReplaceStdoutStderr,
|
||||
RewriteCElementTree,
|
||||
OSErrorAlias(Option<String>),
|
||||
RewriteUnicodeLiteral,
|
||||
RewriteMockImport(MockReference),
|
||||
// pydocstyle
|
||||
BlankLineAfterLastSection(String),
|
||||
BlankLineAfterSection(String),
|
||||
@@ -1301,7 +1311,9 @@ impl CheckCode {
|
||||
CheckCode::UP021 => CheckKind::ReplaceUniversalNewlines,
|
||||
CheckCode::UP022 => CheckKind::ReplaceStdoutStderr,
|
||||
CheckCode::UP023 => CheckKind::RewriteCElementTree,
|
||||
CheckCode::UP024 => CheckKind::OSErrorAlias(None),
|
||||
CheckCode::UP025 => CheckKind::RewriteUnicodeLiteral,
|
||||
CheckCode::UP026 => CheckKind::RewriteMockImport(MockReference::Import),
|
||||
// pydocstyle
|
||||
CheckCode::D100 => CheckKind::PublicModule,
|
||||
CheckCode::D101 => CheckKind::PublicClass,
|
||||
@@ -1733,7 +1745,9 @@ impl CheckCode {
|
||||
CheckCode::UP021 => CheckCategory::Pyupgrade,
|
||||
CheckCode::UP022 => CheckCategory::Pyupgrade,
|
||||
CheckCode::UP023 => CheckCategory::Pyupgrade,
|
||||
CheckCode::UP024 => CheckCategory::Pyupgrade,
|
||||
CheckCode::UP025 => CheckCategory::Pyupgrade,
|
||||
CheckCode::UP026 => CheckCategory::Pyupgrade,
|
||||
CheckCode::W292 => CheckCategory::Pycodestyle,
|
||||
CheckCode::W605 => CheckCategory::Pycodestyle,
|
||||
CheckCode::YTT101 => CheckCategory::Flake82020,
|
||||
@@ -1955,7 +1969,9 @@ impl CheckKind {
|
||||
CheckKind::ReplaceUniversalNewlines => &CheckCode::UP021,
|
||||
CheckKind::ReplaceStdoutStderr => &CheckCode::UP022,
|
||||
CheckKind::RewriteCElementTree => &CheckCode::UP023,
|
||||
CheckKind::OSErrorAlias(..) => &CheckCode::UP024,
|
||||
CheckKind::RewriteUnicodeLiteral => &CheckCode::UP025,
|
||||
CheckKind::RewriteMockImport(..) => &CheckCode::UP026,
|
||||
// pydocstyle
|
||||
CheckKind::BlankLineAfterLastSection(..) => &CheckCode::D413,
|
||||
CheckKind::BlankLineAfterSection(..) => &CheckCode::D410,
|
||||
@@ -2715,7 +2731,11 @@ impl CheckKind {
|
||||
CheckKind::RewriteCElementTree => {
|
||||
"`cElementTree` is deprecated, use `ElementTree`".to_string()
|
||||
}
|
||||
CheckKind::OSErrorAlias(..) => "Replace aliased errors with `OSError`".to_string(),
|
||||
CheckKind::RewriteUnicodeLiteral => "Remove unicode literals from strings".to_string(),
|
||||
CheckKind::RewriteMockImport(..) => {
|
||||
"`mock` is deprecated, use `unittest.mock`".to_string()
|
||||
}
|
||||
// pydocstyle
|
||||
CheckKind::FitsOnOneLine => "One-line docstring should fit on one line".to_string(),
|
||||
CheckKind::BlankLineAfterSummary => {
|
||||
@@ -3129,8 +3149,8 @@ impl CheckKind {
|
||||
matches!(
|
||||
self,
|
||||
CheckKind::AmbiguousUnicodeCharacterString(..)
|
||||
| CheckKind::AmbiguousUnicodeCharacterDocstring(..)
|
||||
| CheckKind::AmbiguousUnicodeCharacterComment(..)
|
||||
| CheckKind::AmbiguousUnicodeCharacterDocstring(..)
|
||||
| CheckKind::BlankLineAfterLastSection(..)
|
||||
| CheckKind::BlankLineAfterSection(..)
|
||||
| CheckKind::BlankLineAfterSummary
|
||||
@@ -3156,12 +3176,7 @@ impl CheckKind {
|
||||
| CheckKind::MisplacedComparisonConstant(..)
|
||||
| CheckKind::MissingReturnTypeSpecialMethod(..)
|
||||
| CheckKind::NativeLiterals(..)
|
||||
| CheckKind::OpenAlias
|
||||
| CheckKind::NewLineAfterLastParagraph
|
||||
| CheckKind::ReplaceUniversalNewlines
|
||||
| CheckKind::ReplaceStdoutStderr
|
||||
| CheckKind::RewriteCElementTree
|
||||
| CheckKind::RewriteUnicodeLiteral
|
||||
| CheckKind::NewLineAfterSectionName(..)
|
||||
| CheckKind::NoBlankLineAfterFunction(..)
|
||||
| CheckKind::NoBlankLineBeforeClass(..)
|
||||
@@ -3174,16 +3189,23 @@ impl CheckKind {
|
||||
| CheckKind::NoneComparison(..)
|
||||
| CheckKind::NotInTest
|
||||
| CheckKind::NotIsTest
|
||||
| CheckKind::OSErrorAlias(..)
|
||||
| CheckKind::OneBlankLineAfterClass(..)
|
||||
| CheckKind::OneBlankLineBeforeClass(..)
|
||||
| CheckKind::OpenAlias
|
||||
| CheckKind::PEP3120UnnecessaryCodingComment
|
||||
| CheckKind::PPrintFound
|
||||
| CheckKind::PrintFound
|
||||
| CheckKind::PercentFormatExtraNamedArguments(..)
|
||||
| CheckKind::PrintFound
|
||||
| CheckKind::RaiseNotImplemented
|
||||
| CheckKind::RedundantOpenModes(..)
|
||||
| CheckKind::RedundantTupleInExceptionHandler(..)
|
||||
| CheckKind::RemoveSixCompat
|
||||
| CheckKind::ReplaceStdoutStderr
|
||||
| CheckKind::ReplaceUniversalNewlines
|
||||
| CheckKind::RewriteCElementTree
|
||||
| CheckKind::RewriteMockImport(..)
|
||||
| CheckKind::RewriteUnicodeLiteral
|
||||
| CheckKind::SectionNameEndsInColon(..)
|
||||
| CheckKind::SectionNotOverIndented(..)
|
||||
| CheckKind::SectionUnderlineAfterName(..)
|
||||
@@ -3295,6 +3317,10 @@ impl CheckKind {
|
||||
}
|
||||
CheckKind::RewriteCElementTree => Some("Replace with `ElementTree`".to_string()),
|
||||
CheckKind::RewriteUnicodeLiteral => Some("Remove unicode prefix".to_string()),
|
||||
CheckKind::RewriteMockImport(reference_type) => Some(match reference_type {
|
||||
MockReference::Import => "Import from `unittest.mock` instead".to_string(),
|
||||
MockReference::Attribute => "Replace `mock.mock` with `mock`".to_string(),
|
||||
}),
|
||||
CheckKind::NewLineAfterSectionName(name) => {
|
||||
Some(format!("Add newline after \"{name}\""))
|
||||
}
|
||||
@@ -3313,6 +3339,10 @@ impl CheckKind {
|
||||
CheckKind::OneBlankLineAfterClass(..) => {
|
||||
Some("Insert 1 blank line after class docstring".to_string())
|
||||
}
|
||||
CheckKind::OSErrorAlias(name) => Some(match name {
|
||||
None => "Replace with builtin `OSError`".to_string(),
|
||||
Some(name) => format!("Replace `{name}` with builtin `OSError`"),
|
||||
}),
|
||||
CheckKind::NoBlankLinesBetweenHeaderAndContent(..) => {
|
||||
Some("Remove blank line(s)".to_string())
|
||||
}
|
||||
|
||||
@@ -540,7 +540,9 @@ pub enum CheckCodePrefix {
|
||||
UP021,
|
||||
UP022,
|
||||
UP023,
|
||||
UP024,
|
||||
UP025,
|
||||
UP026,
|
||||
W,
|
||||
W2,
|
||||
W29,
|
||||
@@ -773,7 +775,9 @@ impl CheckCodePrefix {
|
||||
CheckCode::UP021,
|
||||
CheckCode::UP022,
|
||||
CheckCode::UP023,
|
||||
CheckCode::UP024,
|
||||
CheckCode::UP025,
|
||||
CheckCode::UP026,
|
||||
CheckCode::D100,
|
||||
CheckCode::D101,
|
||||
CheckCode::D102,
|
||||
@@ -2452,7 +2456,9 @@ impl CheckCodePrefix {
|
||||
CheckCode::UP021,
|
||||
CheckCode::UP022,
|
||||
CheckCode::UP023,
|
||||
CheckCode::UP024,
|
||||
CheckCode::UP025,
|
||||
CheckCode::UP026,
|
||||
]
|
||||
}
|
||||
CheckCodePrefix::U0 => {
|
||||
@@ -2485,7 +2491,9 @@ impl CheckCodePrefix {
|
||||
CheckCode::UP021,
|
||||
CheckCode::UP022,
|
||||
CheckCode::UP023,
|
||||
CheckCode::UP024,
|
||||
CheckCode::UP025,
|
||||
CheckCode::UP026,
|
||||
]
|
||||
}
|
||||
CheckCodePrefix::U00 => {
|
||||
@@ -2702,7 +2710,9 @@ impl CheckCodePrefix {
|
||||
CheckCode::UP021,
|
||||
CheckCode::UP022,
|
||||
CheckCode::UP023,
|
||||
CheckCode::UP024,
|
||||
CheckCode::UP025,
|
||||
CheckCode::UP026,
|
||||
],
|
||||
CheckCodePrefix::UP0 => vec![
|
||||
CheckCode::UP001,
|
||||
@@ -2727,7 +2737,9 @@ impl CheckCodePrefix {
|
||||
CheckCode::UP021,
|
||||
CheckCode::UP022,
|
||||
CheckCode::UP023,
|
||||
CheckCode::UP024,
|
||||
CheckCode::UP025,
|
||||
CheckCode::UP026,
|
||||
],
|
||||
CheckCodePrefix::UP00 => vec![
|
||||
CheckCode::UP001,
|
||||
@@ -2774,13 +2786,17 @@ impl CheckCodePrefix {
|
||||
CheckCode::UP021,
|
||||
CheckCode::UP022,
|
||||
CheckCode::UP023,
|
||||
CheckCode::UP024,
|
||||
CheckCode::UP025,
|
||||
CheckCode::UP026,
|
||||
],
|
||||
CheckCodePrefix::UP020 => vec![CheckCode::UP020],
|
||||
CheckCodePrefix::UP021 => vec![CheckCode::UP021],
|
||||
CheckCodePrefix::UP022 => vec![CheckCode::UP022],
|
||||
CheckCodePrefix::UP023 => vec![CheckCode::UP023],
|
||||
CheckCodePrefix::UP024 => vec![CheckCode::UP024],
|
||||
CheckCodePrefix::UP025 => vec![CheckCode::UP025],
|
||||
CheckCodePrefix::UP026 => vec![CheckCode::UP026],
|
||||
CheckCodePrefix::W => vec![CheckCode::W292, CheckCode::W605],
|
||||
CheckCodePrefix::W2 => vec![CheckCode::W292],
|
||||
CheckCodePrefix::W29 => vec![CheckCode::W292],
|
||||
@@ -3352,7 +3368,9 @@ impl CheckCodePrefix {
|
||||
CheckCodePrefix::UP021 => SuffixLength::Three,
|
||||
CheckCodePrefix::UP022 => SuffixLength::Three,
|
||||
CheckCodePrefix::UP023 => SuffixLength::Three,
|
||||
CheckCodePrefix::UP024 => SuffixLength::Three,
|
||||
CheckCodePrefix::UP025 => SuffixLength::Three,
|
||||
CheckCodePrefix::UP026 => SuffixLength::Three,
|
||||
CheckCodePrefix::W => SuffixLength::Zero,
|
||||
CheckCodePrefix::W2 => SuffixLength::One,
|
||||
CheckCodePrefix::W29 => SuffixLength::Two,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use anyhow::{bail, Result};
|
||||
use libcst_native::{Expr, Module, SmallStatement, Statement};
|
||||
use libcst_native::{Expr, Import, ImportFrom, Module, SmallStatement, Statement};
|
||||
|
||||
pub fn match_module(module_text: &str) -> Result<Module> {
|
||||
match libcst_native::parse_module(module_text, None) {
|
||||
@@ -19,3 +19,27 @@ pub fn match_expr<'a, 'b>(module: &'a mut Module<'b>) -> Result<&'a mut Expr<'b>
|
||||
bail!("Expected Statement::Simple")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn match_import<'a, 'b>(module: &'a mut Module<'b>) -> Result<&'a mut Import<'b>> {
|
||||
if let Some(Statement::Simple(expr)) = module.body.first_mut() {
|
||||
if let Some(SmallStatement::Import(expr)) = expr.body.first_mut() {
|
||||
Ok(expr)
|
||||
} else {
|
||||
bail!("Expected SmallStatement::Expr")
|
||||
}
|
||||
} else {
|
||||
bail!("Expected Statement::Simple")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn match_import_from<'a, 'b>(module: &'a mut Module<'b>) -> Result<&'a mut ImportFrom<'b>> {
|
||||
if let Some(Statement::Simple(expr)) = module.body.first_mut() {
|
||||
if let Some(SmallStatement::ImportFrom(expr)) = expr.body.first_mut() {
|
||||
Ok(expr)
|
||||
} else {
|
||||
bail!("Expected SmallStatement::Expr")
|
||||
}
|
||||
} else {
|
||||
bail!("Expected Statement::Simple")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,10 +110,7 @@ pub fn extract_isort_directives(lxr: &[LexResult], locator: &SourceCodeLocator)
|
||||
}
|
||||
|
||||
// TODO(charlie): Modify RustPython to include the comment text in the token.
|
||||
let comment_text = locator.slice_source_code_range(&Range {
|
||||
location: start,
|
||||
end_location: end,
|
||||
});
|
||||
let comment_text = locator.slice_source_code_range(&Range::new(start, end));
|
||||
|
||||
if comment_text == "# isort: split" {
|
||||
splits.push(start.row());
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// See: https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals.
|
||||
/// See: <https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals>
|
||||
|
||||
pub const TRIPLE_QUOTE_PREFIXES: &[&str] = &[
|
||||
"u\"\"\"", "u'''", "r\"\"\"", "r'''", "U\"\"\"", "U'''", "R\"\"\"", "R'''", "\"\"\"", "'''",
|
||||
|
||||
@@ -5,21 +5,21 @@ use crate::docstrings::google::{GOOGLE_SECTION_NAMES, LOWERCASE_GOOGLE_SECTION_N
|
||||
use crate::docstrings::numpy::{LOWERCASE_NUMPY_SECTION_NAMES, NUMPY_SECTION_NAMES};
|
||||
|
||||
pub(crate) enum SectionStyle {
|
||||
NumPy,
|
||||
Numpy,
|
||||
Google,
|
||||
}
|
||||
|
||||
impl SectionStyle {
|
||||
pub(crate) fn section_names(&self) -> &Lazy<FxHashSet<&'static str>> {
|
||||
match self {
|
||||
SectionStyle::NumPy => &NUMPY_SECTION_NAMES,
|
||||
SectionStyle::Numpy => &NUMPY_SECTION_NAMES,
|
||||
SectionStyle::Google => &GOOGLE_SECTION_NAMES,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn lowercase_section_names(&self) -> &Lazy<FxHashSet<&'static str>> {
|
||||
match self {
|
||||
SectionStyle::NumPy => &LOWERCASE_NUMPY_SECTION_NAMES,
|
||||
SectionStyle::Numpy => &LOWERCASE_NUMPY_SECTION_NAMES,
|
||||
SectionStyle::Google => &LOWERCASE_GOOGLE_SECTION_NAMES,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,20 +28,11 @@ pub fn commented_out_code(
|
||||
) -> Option<Check> {
|
||||
let location = Location::new(start.row(), 0);
|
||||
let end_location = Location::new(end.row() + 1, 0);
|
||||
let line = locator.slice_source_code_range(&Range {
|
||||
location,
|
||||
end_location,
|
||||
});
|
||||
let line = locator.slice_source_code_range(&Range::new(location, end_location));
|
||||
|
||||
// Verify that the comment is on its own line, and that it contains code.
|
||||
if is_standalone_comment(&line) && comment_contains_code(&line) {
|
||||
let mut check = Check::new(
|
||||
CheckKind::CommentedOutCode,
|
||||
Range {
|
||||
location: start,
|
||||
end_location: end,
|
||||
},
|
||||
);
|
||||
let mut check = Check::new(CheckKind::CommentedOutCode, Range::new(start, end));
|
||||
if matches!(autofix, flags::Autofix::Enabled)
|
||||
&& settings.fixable.contains(&CheckCode::ERA001)
|
||||
{
|
||||
|
||||
@@ -49,7 +49,7 @@ expression: checks
|
||||
column: 1
|
||||
end_location:
|
||||
row: 6
|
||||
column: 13
|
||||
column: 8
|
||||
fix: ~
|
||||
parent: ~
|
||||
- kind:
|
||||
|
||||
@@ -47,10 +47,7 @@ pub fn quotes(
|
||||
is_docstring: bool,
|
||||
settings: &Settings,
|
||||
) -> Option<Check> {
|
||||
let text = locator.slice_source_code_range(&Range {
|
||||
location: start,
|
||||
end_location: end,
|
||||
});
|
||||
let text = locator.slice_source_code_range(&Range::new(start, end));
|
||||
|
||||
// Remove any prefixes (e.g., remove `u` from `u"foo"`).
|
||||
let last_quote_char = text.chars().last().unwrap();
|
||||
@@ -76,10 +73,7 @@ pub fn quotes(
|
||||
|
||||
Some(Check::new(
|
||||
CheckKind::BadQuotesDocstring(settings.docstring_quotes.clone()),
|
||||
Range {
|
||||
location: start,
|
||||
end_location: end,
|
||||
},
|
||||
Range::new(start, end),
|
||||
))
|
||||
} else if is_multiline {
|
||||
// If our string is or contains a known good string, ignore it.
|
||||
@@ -94,10 +88,7 @@ pub fn quotes(
|
||||
|
||||
Some(Check::new(
|
||||
CheckKind::BadQuotesMultilineString(settings.multiline_quotes.clone()),
|
||||
Range {
|
||||
location: start,
|
||||
end_location: end,
|
||||
},
|
||||
Range::new(start, end),
|
||||
))
|
||||
} else {
|
||||
let string_contents = &raw_text[1..raw_text.len() - 1];
|
||||
@@ -112,10 +103,7 @@ pub fn quotes(
|
||||
{
|
||||
return Some(Check::new(
|
||||
CheckKind::AvoidQuoteEscape,
|
||||
Range {
|
||||
location: start,
|
||||
end_location: end,
|
||||
},
|
||||
Range::new(start, end),
|
||||
));
|
||||
}
|
||||
return None;
|
||||
@@ -125,10 +113,7 @@ pub fn quotes(
|
||||
if !string_contents.contains(good_single(&settings.inline_quotes)) {
|
||||
return Some(Check::new(
|
||||
CheckKind::BadQuotesInlineString(settings.inline_quotes.clone()),
|
||||
Range {
|
||||
location: start,
|
||||
end_location: end,
|
||||
},
|
||||
Range::new(start, end),
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,18 @@ impl<'a> ReturnVisitor<'a> {
|
||||
.push(expr.location);
|
||||
return;
|
||||
}
|
||||
ExprKind::Attribute { .. } => {
|
||||
// Attribute assignments are often side-effects (e.g., `self.property = value`),
|
||||
// so we conservatively treat them as references to every known
|
||||
// variable.
|
||||
for name in self.stack.assigns.keys() {
|
||||
self.stack
|
||||
.refs
|
||||
.entry(name)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(expr.location);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
visitor::walk_expr(self, expr);
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
use rustpython_ast::{Cmpop, Expr, ExprKind};
|
||||
|
||||
use crate::ast::helpers::create_expr;
|
||||
use crate::ast::types::Range;
|
||||
use crate::autofix::Fix;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::checks::{Check, CheckCode, CheckKind};
|
||||
use crate::checks::{Check, CheckKind};
|
||||
use crate::source_code_generator::SourceCodeGenerator;
|
||||
|
||||
/// SIM118
|
||||
fn key_in_dict(checker: &mut Checker, left: &Expr, right: &Expr, range: Range) {
|
||||
@@ -29,13 +31,21 @@ fn key_in_dict(checker: &mut Checker, left: &Expr, right: &Expr, range: Range) {
|
||||
CheckKind::KeyInDict(left.to_string(), value.to_string()),
|
||||
range,
|
||||
);
|
||||
if checker.patch(&CheckCode::SIM118) {
|
||||
let content = right.to_string().replace(".keys()", "");
|
||||
check.amend(Fix::replacement(
|
||||
content,
|
||||
right.location,
|
||||
right.end_location.unwrap(),
|
||||
));
|
||||
if checker.patch(check.kind.code()) {
|
||||
let mut generator = SourceCodeGenerator::new(
|
||||
checker.style.indentation(),
|
||||
checker.style.quote(),
|
||||
checker.style.line_ending(),
|
||||
);
|
||||
generator.unparse_expr(&create_expr(value.node.clone()), 0);
|
||||
|
||||
if let Ok(content) = generator.generate() {
|
||||
check.amend(Fix::replacement(
|
||||
content,
|
||||
right.location,
|
||||
right.end_location.unwrap(),
|
||||
));
|
||||
}
|
||||
}
|
||||
checker.add_check(check);
|
||||
}
|
||||
@@ -46,10 +56,7 @@ pub fn key_in_dict_for(checker: &mut Checker, target: &Expr, iter: &Expr) {
|
||||
checker,
|
||||
target,
|
||||
iter,
|
||||
Range {
|
||||
location: target.location,
|
||||
end_location: iter.end_location.unwrap(),
|
||||
},
|
||||
Range::new(target.location, iter.end_location.unwrap()),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,10 +22,7 @@ pub fn collect_comments<'a>(range: &Range, locator: &'a SourceCodeLocator) -> Ve
|
||||
.filter_map(|(start, tok, end)| {
|
||||
if matches!(tok, Tok::Comment) {
|
||||
Some(Comment {
|
||||
value: locator.slice_source_code_range(&Range {
|
||||
location: start,
|
||||
end_location: end,
|
||||
}),
|
||||
value: locator.slice_source_code_range(&Range::new(start, end)),
|
||||
location: start,
|
||||
end_location: end,
|
||||
})
|
||||
|
||||
@@ -23,12 +23,12 @@ use crate::SourceCodeLocator;
|
||||
mod categorize;
|
||||
mod comments;
|
||||
pub mod format;
|
||||
mod helpers;
|
||||
pub mod helpers;
|
||||
pub mod plugins;
|
||||
pub mod settings;
|
||||
mod sorting;
|
||||
pub mod track;
|
||||
mod types;
|
||||
pub mod types;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AnnotatedAliasData<'a> {
|
||||
|
||||
@@ -19,18 +19,12 @@ use crate::{Check, Settings, SourceCodeLocator};
|
||||
fn extract_range(body: &[&Stmt]) -> Range {
|
||||
let location = body.first().unwrap().location;
|
||||
let end_location = body.last().unwrap().end_location.unwrap();
|
||||
Range {
|
||||
location,
|
||||
end_location,
|
||||
}
|
||||
Range::new(location, end_location)
|
||||
}
|
||||
|
||||
fn extract_indentation_range(body: &[&Stmt]) -> Range {
|
||||
let location = body.first().unwrap().location;
|
||||
Range {
|
||||
location: Location::new(location.row(), 0),
|
||||
end_location: location,
|
||||
}
|
||||
Range::new(Location::new(location.row(), 0), location)
|
||||
}
|
||||
|
||||
/// I001
|
||||
@@ -57,10 +51,10 @@ pub fn check_imports(
|
||||
|
||||
// Extract comments. Take care to grab any inline comments from the last line.
|
||||
let comments = comments::collect_comments(
|
||||
&Range {
|
||||
location: range.location,
|
||||
end_location: Location::new(range.end_location.row() + 1, 0),
|
||||
},
|
||||
&Range::new(
|
||||
range.location,
|
||||
Location::new(range.end_location.row() + 1, 0),
|
||||
),
|
||||
locator,
|
||||
);
|
||||
|
||||
@@ -90,10 +84,10 @@ pub fn check_imports(
|
||||
);
|
||||
|
||||
// Expand the span the entire range, including leading and trailing space.
|
||||
let range = Range {
|
||||
location: Location::new(range.location.row(), 0),
|
||||
end_location: Location::new(range.end_location.row() + 1 + num_trailing_lines, 0),
|
||||
};
|
||||
let range = Range::new(
|
||||
Location::new(range.location.row(), 0),
|
||||
Location::new(range.end_location.row() + 1 + num_trailing_lines, 0),
|
||||
);
|
||||
let actual = dedent(&locator.slice_source_code_range(&range));
|
||||
if actual == dedent(&expected) {
|
||||
None
|
||||
|
||||
@@ -120,10 +120,7 @@ pub(crate) fn check_path(
|
||||
if settings.enabled.contains(&CheckCode::E999) {
|
||||
checks.push(Check::new(
|
||||
CheckKind::SyntaxError(parse_error.error.to_string()),
|
||||
Range {
|
||||
location: parse_error.location,
|
||||
end_location: parse_error.location,
|
||||
},
|
||||
Range::new(parse_error.location, parse_error.location),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,22 +55,18 @@ pub struct Source {
|
||||
|
||||
impl Source {
|
||||
pub fn from_check(check: &Check, locator: &SourceCodeLocator) -> Self {
|
||||
let source = locator.slice_source_code_range(&Range {
|
||||
location: Location::new(check.location.row(), 0),
|
||||
// Checks can already extend one-past-the-end per Ropey's semantics. If they do, though,
|
||||
// then they'll end at the start of a line. We need to avoid extending by yet another
|
||||
// line past-the-end.
|
||||
end_location: if check.end_location.column() == 0 {
|
||||
check.end_location
|
||||
} else {
|
||||
Location::new(check.end_location.row() + 1, 0)
|
||||
},
|
||||
});
|
||||
let location = Location::new(check.location.row(), 0);
|
||||
// Checks can already extend one-past-the-end per Ropey's semantics. If they do,
|
||||
// though, then they'll end at the start of a line. We need to avoid
|
||||
// extending by yet another line past-the-end.
|
||||
let end_location = if check.end_location.column() == 0 {
|
||||
check.end_location
|
||||
} else {
|
||||
Location::new(check.end_location.row() + 1, 0)
|
||||
};
|
||||
let source = locator.slice_source_code_range(&Range::new(location, end_location));
|
||||
let num_chars_in_range = locator
|
||||
.slice_source_code_range(&Range {
|
||||
location: check.location,
|
||||
end_location: check.end_location,
|
||||
})
|
||||
.slice_source_code_range(&Range::new(check.location, check.end_location))
|
||||
.chars()
|
||||
.count();
|
||||
Source {
|
||||
|
||||
25
src/noqa.rs
25
src/noqa.rs
@@ -248,10 +248,7 @@ mod tests {
|
||||
|
||||
let checks = vec![Check::new(
|
||||
CheckKind::UnusedVariable("x".to_string()),
|
||||
Range {
|
||||
location: Location::new(1, 0),
|
||||
end_location: Location::new(1, 0),
|
||||
},
|
||||
Range::new(Location::new(1, 0), Location::new(1, 0)),
|
||||
)];
|
||||
let contents = "x = 1";
|
||||
let noqa_line_for = IntMap::default();
|
||||
@@ -269,17 +266,11 @@ mod tests {
|
||||
let checks = vec![
|
||||
Check::new(
|
||||
CheckKind::AmbiguousVariableName("x".to_string()),
|
||||
Range {
|
||||
location: Location::new(1, 0),
|
||||
end_location: Location::new(1, 0),
|
||||
},
|
||||
Range::new(Location::new(1, 0), Location::new(1, 0)),
|
||||
),
|
||||
Check::new(
|
||||
CheckKind::UnusedVariable("x".to_string()),
|
||||
Range {
|
||||
location: Location::new(1, 0),
|
||||
end_location: Location::new(1, 0),
|
||||
},
|
||||
Range::new(Location::new(1, 0), Location::new(1, 0)),
|
||||
),
|
||||
];
|
||||
let contents = "x = 1 # noqa: E741\n";
|
||||
@@ -298,17 +289,11 @@ mod tests {
|
||||
let checks = vec![
|
||||
Check::new(
|
||||
CheckKind::AmbiguousVariableName("x".to_string()),
|
||||
Range {
|
||||
location: Location::new(1, 0),
|
||||
end_location: Location::new(1, 0),
|
||||
},
|
||||
Range::new(Location::new(1, 0), Location::new(1, 0)),
|
||||
),
|
||||
Check::new(
|
||||
CheckKind::UnusedVariable("x".to_string()),
|
||||
Range {
|
||||
location: Location::new(1, 0),
|
||||
end_location: Location::new(1, 0),
|
||||
},
|
||||
Range::new(Location::new(1, 0), Location::new(1, 0)),
|
||||
),
|
||||
];
|
||||
let contents = "x = 1 # noqa";
|
||||
|
||||
@@ -34,10 +34,10 @@ pub fn line_too_long(lineno: usize, line: &str, max_line_length: usize) -> Optio
|
||||
|
||||
Some(Check::new(
|
||||
CheckKind::LineTooLong(line_length, max_line_length),
|
||||
Range {
|
||||
location: Location::new(lineno + 1, max_line_length),
|
||||
end_location: Location::new(lineno + 1, line_length),
|
||||
},
|
||||
Range::new(
|
||||
Location::new(lineno + 1, max_line_length),
|
||||
Location::new(lineno + 1, line_length),
|
||||
),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -162,10 +162,7 @@ pub fn no_newline_at_end_of_file(contents: &str, autofix: bool) -> Option<Check>
|
||||
let location = Location::new(contents.lines().count(), line.len());
|
||||
let mut check = Check::new(
|
||||
CheckKind::NoNewLineAtEndOfFile,
|
||||
Range {
|
||||
location,
|
||||
end_location: location,
|
||||
},
|
||||
Range::new(location, location),
|
||||
);
|
||||
if autofix {
|
||||
check.amend(Fix::insertion("\n".to_string(), location));
|
||||
@@ -203,10 +200,7 @@ pub fn invalid_escape_sequence(
|
||||
) -> Vec<Check> {
|
||||
let mut checks = vec![];
|
||||
|
||||
let text = locator.slice_source_code_range(&Range {
|
||||
location: start,
|
||||
end_location: end,
|
||||
});
|
||||
let text = locator.slice_source_code_range(&Range::new(start, end));
|
||||
|
||||
// Determine whether the string is single- or triple-quoted.
|
||||
let quote = extract_quote(&text);
|
||||
@@ -249,10 +243,7 @@ pub fn invalid_escape_sequence(
|
||||
let end_location = Location::new(location.row(), location.column() + 2);
|
||||
let mut check = Check::new(
|
||||
CheckKind::InvalidEscapeSequence(next_char),
|
||||
Range {
|
||||
location,
|
||||
end_location,
|
||||
},
|
||||
Range::new(location, end_location),
|
||||
);
|
||||
if autofix {
|
||||
check.amend(Fix::insertion(r"\".to_string(), location));
|
||||
|
||||
@@ -329,10 +329,10 @@ pub fn do_not_assign_lambda(checker: &mut Checker, target: &Expr, value: &Expr,
|
||||
{
|
||||
match function(id, args, body, checker.style) {
|
||||
Ok(content) => {
|
||||
let first_line = checker.locator.slice_source_code_range(&Range {
|
||||
location: Location::new(stmt.location.row(), 0),
|
||||
end_location: Location::new(stmt.location.row() + 1, 0),
|
||||
});
|
||||
let first_line = checker.locator.slice_source_code_range(&Range::new(
|
||||
Location::new(stmt.location.row(), 0),
|
||||
Location::new(stmt.location.row() + 1, 0),
|
||||
));
|
||||
let indentation = &leading_space(&first_line);
|
||||
let mut indented = String::new();
|
||||
for (idx, line) in content.lines().enumerate() {
|
||||
|
||||
@@ -249,7 +249,7 @@ expression: checks
|
||||
column: 4
|
||||
end_location:
|
||||
row: 74
|
||||
column: 10
|
||||
column: 5
|
||||
fix: ~
|
||||
parent: ~
|
||||
|
||||
|
||||
@@ -34,10 +34,7 @@ pub fn not_missing(
|
||||
if checker.settings.enabled.contains(&CheckCode::D100) {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::PublicModule,
|
||||
Range {
|
||||
location: Location::new(1, 0),
|
||||
end_location: Location::new(1, 0),
|
||||
},
|
||||
Range::new(Location::new(1, 0), Location::new(1, 0)),
|
||||
));
|
||||
}
|
||||
false
|
||||
@@ -46,10 +43,7 @@ pub fn not_missing(
|
||||
if checker.settings.enabled.contains(&CheckCode::D104) {
|
||||
checker.add_check(Check::new(
|
||||
CheckKind::PublicPackage,
|
||||
Range {
|
||||
location: Location::new(1, 0),
|
||||
end_location: Location::new(1, 0),
|
||||
},
|
||||
Range::new(Location::new(1, 0), Location::new(1, 0)),
|
||||
));
|
||||
}
|
||||
false
|
||||
@@ -412,10 +406,10 @@ pub fn indent(checker: &mut Checker, docstring: &Docstring) {
|
||||
{
|
||||
let mut check = Check::new(
|
||||
CheckKind::NoUnderIndentation,
|
||||
Range {
|
||||
location: Location::new(docstring.expr.location.row() + i, 0),
|
||||
end_location: Location::new(docstring.expr.location.row() + i, 0),
|
||||
},
|
||||
Range::new(
|
||||
Location::new(docstring.expr.location.row() + i, 0),
|
||||
Location::new(docstring.expr.location.row() + i, 0),
|
||||
),
|
||||
);
|
||||
if checker.patch(check.kind.code()) {
|
||||
check.amend(Fix::replacement(
|
||||
@@ -462,10 +456,10 @@ pub fn indent(checker: &mut Checker, docstring: &Docstring) {
|
||||
// enables autofix.
|
||||
let mut check = Check::new(
|
||||
CheckKind::NoOverIndentation,
|
||||
Range {
|
||||
location: Location::new(docstring.expr.location.row() + i, 0),
|
||||
end_location: Location::new(docstring.expr.location.row() + i, 0),
|
||||
},
|
||||
Range::new(
|
||||
Location::new(docstring.expr.location.row() + i, 0),
|
||||
Location::new(docstring.expr.location.row() + i, 0),
|
||||
),
|
||||
);
|
||||
if checker.patch(check.kind.code()) {
|
||||
check.amend(Fix::replacement(
|
||||
@@ -486,10 +480,10 @@ pub fn indent(checker: &mut Checker, docstring: &Docstring) {
|
||||
if line_indent.len() > docstring.indentation.len() {
|
||||
let mut check = Check::new(
|
||||
CheckKind::NoOverIndentation,
|
||||
Range {
|
||||
location: Location::new(docstring.expr.location.row() + i, 0),
|
||||
end_location: Location::new(docstring.expr.location.row() + i, 0),
|
||||
},
|
||||
Range::new(
|
||||
Location::new(docstring.expr.location.row() + i, 0),
|
||||
Location::new(docstring.expr.location.row() + i, 0),
|
||||
),
|
||||
);
|
||||
if checker.patch(check.kind.code()) {
|
||||
check.amend(Fix::replacement(
|
||||
@@ -671,9 +665,35 @@ pub fn ends_with_period(checker: &mut Checker, docstring: &Docstring) {
|
||||
let contents = docstring.contents;
|
||||
let body = docstring.body;
|
||||
|
||||
if let Some(first_line) = body.trim().lines().next() {
|
||||
let trimmed = first_line.trim();
|
||||
|
||||
// Avoid false-positives: `:param`, etc.
|
||||
for prefix in [":param", ":type", ":raises", ":return", ":rtype"] {
|
||||
if trimmed.starts_with(prefix) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid false-positives: `Args:`, etc.
|
||||
for style in [SectionStyle::Google, SectionStyle::Numpy] {
|
||||
for section_name in style.section_names().iter() {
|
||||
if let Some(suffix) = trimmed.strip_suffix(section_name) {
|
||||
if suffix.is_empty() {
|
||||
return;
|
||||
}
|
||||
if suffix == ":" {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(index) = logical_line(body) {
|
||||
let line = body.lines().nth(index).unwrap();
|
||||
let trimmed = line.trim_end();
|
||||
|
||||
if !trimmed.ends_with('.') {
|
||||
let mut check =
|
||||
Check::new(CheckKind::EndsInPeriod, Range::from_located(docstring.expr));
|
||||
@@ -718,7 +738,7 @@ pub fn no_signature(checker: &mut Checker, docstring: &Docstring) {
|
||||
|
||||
let body = docstring.body;
|
||||
|
||||
let Some(first_line) = body.lines().next() else {
|
||||
let Some(first_line) = body.trim().lines().next() else {
|
||||
return;
|
||||
};
|
||||
if !first_line.contains(&format!("{name}(")) {
|
||||
@@ -791,6 +811,31 @@ pub fn ends_with_punctuation(checker: &mut Checker, docstring: &Docstring) {
|
||||
let contents = docstring.contents;
|
||||
let body = docstring.body;
|
||||
|
||||
if let Some(first_line) = body.trim().lines().next() {
|
||||
let trimmed = first_line.trim();
|
||||
|
||||
// Avoid false-positives: `:param`, etc.
|
||||
for prefix in [":param", ":type", ":raises", ":return", ":rtype"] {
|
||||
if trimmed.starts_with(prefix) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid false-positives: `Args:`, etc.
|
||||
for style in [SectionStyle::Google, SectionStyle::Numpy] {
|
||||
for section_name in style.section_names().iter() {
|
||||
if let Some(suffix) = trimmed.strip_suffix(section_name) {
|
||||
if suffix.is_empty() {
|
||||
return;
|
||||
}
|
||||
if suffix == ":" {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(index) = logical_line(body) {
|
||||
let line = body.lines().nth(index).unwrap();
|
||||
let trimmed = line.trim_end();
|
||||
@@ -875,14 +920,14 @@ pub fn sections(checker: &mut Checker, docstring: &Docstring, convention: Option
|
||||
}
|
||||
}
|
||||
Some(Convention::Numpy) => {
|
||||
for context in §ion_contexts(&lines, &SectionStyle::NumPy) {
|
||||
for context in §ion_contexts(&lines, &SectionStyle::Numpy) {
|
||||
numpy_section(checker, docstring, context);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
// First, interpret as NumPy-style sections.
|
||||
let mut found_numpy_section = false;
|
||||
for context in §ion_contexts(&lines, &SectionStyle::NumPy) {
|
||||
for context in §ion_contexts(&lines, &SectionStyle::Numpy) {
|
||||
found_numpy_section = true;
|
||||
numpy_section(checker, docstring, context);
|
||||
}
|
||||
@@ -1424,7 +1469,7 @@ fn parameters_section(checker: &mut Checker, docstring: &Docstring, context: &Se
|
||||
}
|
||||
|
||||
fn numpy_section(checker: &mut Checker, docstring: &Docstring, context: &SectionContext) {
|
||||
common_section(checker, docstring, context, &SectionStyle::NumPy);
|
||||
common_section(checker, docstring, context, &SectionStyle::Numpy);
|
||||
|
||||
if checker.settings.enabled.contains(&CheckCode::D406) {
|
||||
let suffix = context
|
||||
|
||||
@@ -100,98 +100,98 @@ expression: checks
|
||||
parent: ~
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 40
|
||||
row: 39
|
||||
column: 4
|
||||
end_location:
|
||||
row: 40
|
||||
row: 39
|
||||
column: 37
|
||||
fix:
|
||||
content: "."
|
||||
location:
|
||||
row: 40
|
||||
row: 39
|
||||
column: 36
|
||||
end_location:
|
||||
row: 40
|
||||
row: 39
|
||||
column: 36
|
||||
parent: ~
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 45
|
||||
row: 44
|
||||
column: 4
|
||||
end_location:
|
||||
row: 45
|
||||
row: 44
|
||||
column: 41
|
||||
fix:
|
||||
content: "."
|
||||
location:
|
||||
row: 45
|
||||
row: 44
|
||||
column: 38
|
||||
end_location:
|
||||
row: 45
|
||||
row: 44
|
||||
column: 38
|
||||
parent: ~
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 50
|
||||
row: 49
|
||||
column: 4
|
||||
end_location:
|
||||
row: 53
|
||||
row: 52
|
||||
column: 7
|
||||
fix:
|
||||
content: "."
|
||||
location:
|
||||
row: 52
|
||||
row: 51
|
||||
column: 28
|
||||
end_location:
|
||||
row: 52
|
||||
row: 51
|
||||
column: 28
|
||||
parent: ~
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 58
|
||||
row: 57
|
||||
column: 4
|
||||
end_location:
|
||||
row: 58
|
||||
row: 57
|
||||
column: 41
|
||||
fix:
|
||||
content: "."
|
||||
location:
|
||||
row: 58
|
||||
row: 57
|
||||
column: 38
|
||||
end_location:
|
||||
row: 58
|
||||
row: 57
|
||||
column: 38
|
||||
parent: ~
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 63
|
||||
row: 62
|
||||
column: 4
|
||||
end_location:
|
||||
row: 65
|
||||
row: 64
|
||||
column: 31
|
||||
fix:
|
||||
content: "."
|
||||
location:
|
||||
row: 65
|
||||
row: 64
|
||||
column: 28
|
||||
end_location:
|
||||
row: 65
|
||||
row: 64
|
||||
column: 28
|
||||
parent: ~
|
||||
- kind: EndsInPeriod
|
||||
location:
|
||||
row: 70
|
||||
row: 69
|
||||
column: 4
|
||||
end_location:
|
||||
row: 72
|
||||
row: 71
|
||||
column: 52
|
||||
fix:
|
||||
content: "."
|
||||
location:
|
||||
row: 72
|
||||
row: 71
|
||||
column: 48
|
||||
end_location:
|
||||
row: 72
|
||||
row: 71
|
||||
column: 48
|
||||
parent: ~
|
||||
|
||||
|
||||
@@ -38,4 +38,22 @@ expression: checks
|
||||
column: 16
|
||||
fix: ~
|
||||
parent: ~
|
||||
- kind: FStringMissingPlaceholders
|
||||
location:
|
||||
row: 26
|
||||
column: 6
|
||||
end_location:
|
||||
row: 26
|
||||
column: 13
|
||||
fix: ~
|
||||
parent: ~
|
||||
- kind: FStringMissingPlaceholders
|
||||
location:
|
||||
row: 27
|
||||
column: 3
|
||||
end_location:
|
||||
row: 27
|
||||
column: 6
|
||||
fix: ~
|
||||
parent: ~
|
||||
|
||||
|
||||
@@ -82,33 +82,53 @@ expression: checks
|
||||
column: 8
|
||||
fix: ~
|
||||
parent: ~
|
||||
- kind:
|
||||
UndefinedName: B
|
||||
location:
|
||||
row: 92
|
||||
column: 10
|
||||
end_location:
|
||||
row: 92
|
||||
column: 11
|
||||
fix: ~
|
||||
parent: ~
|
||||
- kind:
|
||||
UndefinedName: B
|
||||
location:
|
||||
row: 93
|
||||
column: 13
|
||||
end_location:
|
||||
row: 93
|
||||
column: 14
|
||||
fix: ~
|
||||
parent: ~
|
||||
- kind:
|
||||
UndefinedName: PEP593Test123
|
||||
location:
|
||||
row: 114
|
||||
row: 115
|
||||
column: 8
|
||||
end_location:
|
||||
row: 114
|
||||
row: 115
|
||||
column: 23
|
||||
fix: ~
|
||||
parent: ~
|
||||
- kind:
|
||||
UndefinedName: foo
|
||||
location:
|
||||
row: 122
|
||||
row: 123
|
||||
column: 13
|
||||
end_location:
|
||||
row: 122
|
||||
row: 123
|
||||
column: 18
|
||||
fix: ~
|
||||
parent: ~
|
||||
- kind:
|
||||
UndefinedName: bar
|
||||
location:
|
||||
row: 122
|
||||
row: 123
|
||||
column: 20
|
||||
end_location:
|
||||
row: 122
|
||||
row: 123
|
||||
column: 25
|
||||
fix: ~
|
||||
parent: ~
|
||||
|
||||
@@ -13,10 +13,10 @@ pub fn blanket_noqa(lineno: usize, line: &str) -> Option<Check> {
|
||||
BLANKET_NOQA_REGEX.find(line).map(|m| {
|
||||
Check::new(
|
||||
CheckKind::BlanketNOQA,
|
||||
Range {
|
||||
location: Location::new(lineno + 1, m.start()),
|
||||
end_location: Location::new(lineno + 1, m.end()),
|
||||
},
|
||||
Range::new(
|
||||
Location::new(lineno + 1, m.start()),
|
||||
Location::new(lineno + 1, m.end()),
|
||||
),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -13,10 +13,10 @@ 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()),
|
||||
},
|
||||
Range::new(
|
||||
Location::new(lineno + 1, m.start()),
|
||||
Location::new(lineno + 1, m.end()),
|
||||
),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -170,10 +170,7 @@ pub fn unnecessary_coding_comment(lineno: usize, line: &str, autofix: bool) -> O
|
||||
if CODING_COMMENT_REGEX.is_match(line) {
|
||||
let mut check = Check::new(
|
||||
CheckKind::PEP3120UnnecessaryCodingComment,
|
||||
Range {
|
||||
location: Location::new(lineno + 1, 0),
|
||||
end_location: Location::new(lineno + 2, 0),
|
||||
},
|
||||
Range::new(Location::new(lineno + 1, 0), Location::new(lineno + 2, 0)),
|
||||
);
|
||||
if autofix {
|
||||
check.amend(Fix::deletion(
|
||||
@@ -216,10 +213,7 @@ pub fn unnecessary_lru_cache_params(
|
||||
continue;
|
||||
}
|
||||
|
||||
let range = Range {
|
||||
location: func.end_location.unwrap(),
|
||||
end_location: expr.end_location.unwrap(),
|
||||
};
|
||||
let range = Range::new(func.end_location.unwrap(), expr.end_location.unwrap());
|
||||
// Ex) `functools.lru_cache()`
|
||||
if keywords.is_empty() {
|
||||
return Some(Check::new(CheckKind::UnnecessaryLRUCacheParams, range));
|
||||
|
||||
@@ -42,7 +42,11 @@ mod tests {
|
||||
#[test_case(CheckCode::UP021, Path::new("UP021.py"); "UP021")]
|
||||
#[test_case(CheckCode::UP022, Path::new("UP022.py"); "UP022")]
|
||||
#[test_case(CheckCode::UP023, Path::new("UP023.py"); "UP023")]
|
||||
#[test_case(CheckCode::UP024, Path::new("UP024_0.py"); "UP024_0")]
|
||||
#[test_case(CheckCode::UP024, Path::new("UP024_1.py"); "UP024_1")]
|
||||
#[test_case(CheckCode::UP024, Path::new("UP024_2.py"); "UP024_2")]
|
||||
#[test_case(CheckCode::UP025, Path::new("UP025.py"); "UP025")]
|
||||
#[test_case(CheckCode::UP026, Path::new("UP026.py"); "UP026")]
|
||||
fn checks(check_code: CheckCode, path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}_{}", check_code.as_ref(), path.to_string_lossy());
|
||||
let checks = test_path(
|
||||
|
||||
@@ -4,11 +4,13 @@ pub use datetime_utc_alias::datetime_utc_alias;
|
||||
pub use deprecated_unittest_alias::deprecated_unittest_alias;
|
||||
pub use native_literals::native_literals;
|
||||
pub use open_alias::open_alias;
|
||||
pub use os_error_alias::os_error_alias;
|
||||
pub use redundant_open_modes::redundant_open_modes;
|
||||
pub use remove_six_compat::remove_six_compat;
|
||||
pub use replace_stdout_stderr::replace_stdout_stderr;
|
||||
pub use replace_universal_newlines::replace_universal_newlines;
|
||||
pub use rewrite_c_element_tree::replace_c_element_tree;
|
||||
pub use rewrite_mock_import::{rewrite_mock_attribute, rewrite_mock_import};
|
||||
pub use rewrite_unicode_literal::rewrite_unicode_literal;
|
||||
pub use super_call_with_parameters::super_call_with_parameters;
|
||||
pub use type_of_primitive::type_of_primitive;
|
||||
@@ -27,11 +29,13 @@ mod datetime_utc_alias;
|
||||
mod deprecated_unittest_alias;
|
||||
mod native_literals;
|
||||
mod open_alias;
|
||||
mod os_error_alias;
|
||||
mod redundant_open_modes;
|
||||
mod remove_six_compat;
|
||||
mod replace_stdout_stderr;
|
||||
mod replace_universal_newlines;
|
||||
mod rewrite_c_element_tree;
|
||||
mod rewrite_mock_import;
|
||||
mod rewrite_unicode_literal;
|
||||
mod super_call_with_parameters;
|
||||
mod type_of_primitive;
|
||||
|
||||
236
src/pyupgrade/plugins/os_error_alias.rs
Normal file
236
src/pyupgrade/plugins/os_error_alias.rs
Normal file
@@ -0,0 +1,236 @@
|
||||
#![allow(clippy::len_zero, clippy::needless_pass_by_value)]
|
||||
|
||||
use itertools::Itertools;
|
||||
use rustpython_ast::{Excepthandler, ExcepthandlerKind, Expr, ExprKind, Located};
|
||||
|
||||
use crate::ast::helpers::{compose_call_path, match_module_member};
|
||||
use crate::ast::types::Range;
|
||||
use crate::autofix::Fix;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::checks::{Check, CheckKind};
|
||||
|
||||
const ERROR_NAMES: &[&str] = &["EnvironmentError", "IOError", "WindowsError"];
|
||||
const ERROR_MODULES: &[&str] = &["mmap", "select", "socket"];
|
||||
|
||||
fn get_correct_name(original: &str) -> String {
|
||||
if ERROR_NAMES.contains(&original) {
|
||||
"OSError".to_string()
|
||||
} else {
|
||||
original.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
fn get_before_replace(elts: &[Expr]) -> Vec<String> {
|
||||
elts.iter()
|
||||
.map(|elt| {
|
||||
if let ExprKind::Name { id, .. } = &elt.node {
|
||||
id.to_string()
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn check_module(checker: &Checker, expr: &Expr) -> (Vec<String>, Vec<String>) {
|
||||
let mut replacements: Vec<String> = vec![];
|
||||
let mut before_replace: Vec<String> = vec![];
|
||||
for module in ERROR_MODULES.iter() {
|
||||
if match_module_member(
|
||||
expr,
|
||||
module,
|
||||
"error",
|
||||
&checker.from_imports,
|
||||
&checker.import_aliases,
|
||||
) {
|
||||
replacements.push("OSError".to_string());
|
||||
before_replace.push(format!("{module}.error"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
(replacements, before_replace)
|
||||
}
|
||||
|
||||
fn handle_name_or_attribute(
|
||||
checker: &Checker,
|
||||
item: &Expr,
|
||||
replacements: &mut Vec<String>,
|
||||
before_replace: &mut Vec<String>,
|
||||
) {
|
||||
match &item.node {
|
||||
ExprKind::Name { id, .. } => {
|
||||
let (temp_replacements, temp_before_replace) = check_module(checker, item);
|
||||
replacements.extend(temp_replacements);
|
||||
before_replace.extend(temp_before_replace);
|
||||
if replacements.is_empty() {
|
||||
let new_name = get_correct_name(id);
|
||||
replacements.push(new_name);
|
||||
before_replace.push(id.to_string());
|
||||
}
|
||||
}
|
||||
ExprKind::Attribute { .. } => {
|
||||
let (temp_replacements, temp_before_replace) = check_module(checker, item);
|
||||
replacements.extend(temp_replacements);
|
||||
before_replace.extend(temp_before_replace);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles one block of an except (use a loop if there are multile blocks)
|
||||
fn handle_except_block(checker: &mut Checker, handler: &Located<ExcepthandlerKind>) {
|
||||
let ExcepthandlerKind::ExceptHandler { type_, .. } = &handler.node;
|
||||
let Some(error_handlers) = type_.as_ref() else {
|
||||
return;
|
||||
};
|
||||
// The first part creates list of all the exceptions being caught, and
|
||||
// what they should be changed to
|
||||
let mut replacements: Vec<String> = vec![];
|
||||
let mut before_replace: Vec<String> = vec![];
|
||||
match &error_handlers.node {
|
||||
ExprKind::Name { .. } | ExprKind::Attribute { .. } => {
|
||||
handle_name_or_attribute(
|
||||
checker,
|
||||
error_handlers,
|
||||
&mut replacements,
|
||||
&mut before_replace,
|
||||
);
|
||||
}
|
||||
ExprKind::Tuple { elts, .. } => {
|
||||
before_replace = get_before_replace(elts);
|
||||
for elt in elts {
|
||||
match &elt.node {
|
||||
ExprKind::Name { id, .. } => {
|
||||
let new_name = get_correct_name(id);
|
||||
replacements.push(new_name);
|
||||
}
|
||||
ExprKind::Attribute { .. } => {
|
||||
let (new_replacements, new_before_replace) = check_module(checker, elt);
|
||||
replacements.extend(new_replacements);
|
||||
before_replace.extend(new_before_replace);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => return,
|
||||
}
|
||||
replacements = replacements
|
||||
.iter()
|
||||
.unique()
|
||||
.map(std::string::ToString::to_string)
|
||||
.collect();
|
||||
before_replace = before_replace
|
||||
.iter()
|
||||
.filter(|x| !x.is_empty())
|
||||
.map(std::string::ToString::to_string)
|
||||
.collect();
|
||||
|
||||
// This part checks if there are differences between what there is and
|
||||
// what there should be. Where differences, the changes are applied
|
||||
handle_making_changes(checker, error_handlers, &before_replace, &replacements);
|
||||
}
|
||||
|
||||
fn handle_making_changes(
|
||||
checker: &mut Checker,
|
||||
target: &Expr,
|
||||
before_replace: &[String],
|
||||
replacements: &[String],
|
||||
) {
|
||||
if before_replace != replacements && replacements.len() > 0 {
|
||||
let range = Range::new(target.location, target.end_location.unwrap());
|
||||
let contents = checker.locator.slice_source_code_range(&range);
|
||||
// Pyyupgrade does not want imports changed if a module only is
|
||||
// surrounded by parentheses. For example: `except mmap.error:`
|
||||
// would be changed, but: `(mmap).error:` would not. One issue with
|
||||
// this implementation is that any valid changes will also be
|
||||
// ignored. Let me know if you want me to go with a more
|
||||
// complicated solution that avoids this.
|
||||
if contents.contains(").") {
|
||||
return;
|
||||
}
|
||||
let mut final_str: String;
|
||||
if replacements.len() == 1 {
|
||||
final_str = replacements.get(0).unwrap().to_string();
|
||||
} else {
|
||||
final_str = replacements.join(", ");
|
||||
final_str.insert(0, '(');
|
||||
final_str.push(')');
|
||||
}
|
||||
let mut check = Check::new(CheckKind::OSErrorAlias(compose_call_path(target)), range);
|
||||
if checker.patch(check.kind.code()) {
|
||||
check.amend(Fix::replacement(
|
||||
final_str,
|
||||
range.location,
|
||||
range.end_location,
|
||||
));
|
||||
}
|
||||
checker.add_check(check);
|
||||
}
|
||||
}
|
||||
|
||||
// This is a hacky way to handle the different variable types we get since
|
||||
// raise and try are very different. Would love input on a cleaner way
|
||||
pub trait OSErrorAliasChecker {
|
||||
fn check_error(&self, checker: &mut Checker)
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
impl OSErrorAliasChecker for &Vec<Excepthandler> {
|
||||
fn check_error(&self, checker: &mut Checker) {
|
||||
// Each separate except block is a separate error and fix
|
||||
for handler in self.iter() {
|
||||
handle_except_block(checker, handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OSErrorAliasChecker for &Box<Expr> {
|
||||
fn check_error(&self, checker: &mut Checker) {
|
||||
let mut replacements: Vec<String> = vec![];
|
||||
let mut before_replace: Vec<String> = vec![];
|
||||
match &self.node {
|
||||
ExprKind::Name { .. } | ExprKind::Attribute { .. } => {
|
||||
handle_name_or_attribute(checker, self, &mut replacements, &mut before_replace);
|
||||
}
|
||||
_ => return,
|
||||
}
|
||||
handle_making_changes(checker, self, &before_replace, &replacements);
|
||||
}
|
||||
}
|
||||
|
||||
impl OSErrorAliasChecker for &Expr {
|
||||
fn check_error(&self, checker: &mut Checker) {
|
||||
let mut replacements: Vec<String> = vec![];
|
||||
let mut before_replace: Vec<String> = vec![];
|
||||
let change_target: &Expr;
|
||||
match &self.node {
|
||||
ExprKind::Name { .. } | ExprKind::Attribute { .. } => {
|
||||
change_target = self;
|
||||
handle_name_or_attribute(checker, self, &mut replacements, &mut before_replace);
|
||||
}
|
||||
ExprKind::Call { func, .. } => {
|
||||
change_target = func;
|
||||
match &func.node {
|
||||
ExprKind::Name { .. } | ExprKind::Attribute { .. } => {
|
||||
handle_name_or_attribute(
|
||||
checker,
|
||||
func,
|
||||
&mut replacements,
|
||||
&mut before_replace,
|
||||
);
|
||||
}
|
||||
_ => return,
|
||||
}
|
||||
}
|
||||
_ => return,
|
||||
}
|
||||
handle_making_changes(checker, change_target, &before_replace, &replacements);
|
||||
}
|
||||
}
|
||||
|
||||
/// UP024
|
||||
pub fn os_error_alias<U: OSErrorAliasChecker>(checker: &mut Checker, handlers: U) {
|
||||
handlers.check_error(checker);
|
||||
}
|
||||
@@ -107,10 +107,8 @@ fn create_remove_param_fix(
|
||||
expr: &Expr,
|
||||
mode_param: &Expr,
|
||||
) -> Result<Fix> {
|
||||
let content = locator.slice_source_code_range(&Range {
|
||||
location: expr.location,
|
||||
end_location: expr.end_location.unwrap(),
|
||||
});
|
||||
let content =
|
||||
locator.slice_source_code_range(&Range::new(expr.location, expr.end_location.unwrap()));
|
||||
// Find the last comma before mode_param and create a deletion fix
|
||||
// starting from the comma and ending after mode_param.
|
||||
let mut fix_start: Option<Location> = None;
|
||||
|
||||
@@ -65,10 +65,10 @@ fn replace_by_str_literal(
|
||||
let content = format!(
|
||||
"{}{}",
|
||||
if binary { "b" } else { "" },
|
||||
locator.slice_source_code_range(&Range {
|
||||
location: arg.location,
|
||||
end_location: arg.end_location.unwrap(),
|
||||
})
|
||||
locator.slice_source_code_range(&Range::new(
|
||||
arg.location,
|
||||
arg.end_location.unwrap(),
|
||||
))
|
||||
);
|
||||
check.amend(Fix::replacement(
|
||||
content,
|
||||
|
||||
@@ -87,10 +87,12 @@ pub fn replace_stdout_stderr(checker: &mut Checker, expr: &Expr, kwargs: &[Keywo
|
||||
stderr
|
||||
};
|
||||
let mut contents = String::from("capture_output=True");
|
||||
if let Some(middle) = extract_middle(&checker.locator.slice_source_code_range(&Range {
|
||||
location: first.end_location.unwrap(),
|
||||
end_location: last.location,
|
||||
})) {
|
||||
if let Some(middle) =
|
||||
extract_middle(&checker.locator.slice_source_code_range(&Range::new(
|
||||
first.end_location.unwrap(),
|
||||
last.location,
|
||||
)))
|
||||
{
|
||||
if middle.multi_line {
|
||||
contents.push(',');
|
||||
contents.push('\n');
|
||||
|
||||
@@ -16,13 +16,13 @@ pub fn replace_universal_newlines(checker: &mut Checker, expr: &Expr, kwargs: &[
|
||||
&checker.import_aliases,
|
||||
) {
|
||||
let Some(kwarg) = find_keyword(kwargs, "universal_newlines") else { return; };
|
||||
let range = Range {
|
||||
location: kwarg.location,
|
||||
end_location: Location::new(
|
||||
let range = Range::new(
|
||||
kwarg.location,
|
||||
Location::new(
|
||||
kwarg.location.row(),
|
||||
kwarg.location.column() + "universal_newlines".len(),
|
||||
),
|
||||
};
|
||||
);
|
||||
let mut check = Check::new(CheckKind::ReplaceUniversalNewlines, range);
|
||||
if checker.patch(check.kind.code()) {
|
||||
check.amend(Fix::replacement(
|
||||
|
||||
275
src/pyupgrade/plugins/rewrite_mock_import.rs
Normal file
275
src/pyupgrade/plugins/rewrite_mock_import.rs
Normal file
@@ -0,0 +1,275 @@
|
||||
use anyhow::Result;
|
||||
use libcst_native::{
|
||||
AsName, AssignTargetExpression, Attribute, Codegen, CodegenState, Dot, Expression, Import,
|
||||
ImportAlias, ImportFrom, ImportNames, Name, NameOrAttribute, ParenthesizableWhitespace,
|
||||
};
|
||||
use log::error;
|
||||
use rustpython_ast::{Expr, ExprKind, Stmt, StmtKind};
|
||||
|
||||
use crate::ast::helpers::collect_call_paths;
|
||||
use crate::ast::types::Range;
|
||||
use crate::ast::whitespace::indentation;
|
||||
use crate::autofix::Fix;
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::checks::{Check, CheckCode, CheckKind, MockReference};
|
||||
use crate::cst::matchers::{match_import, match_import_from, match_module};
|
||||
use crate::source_code_locator::SourceCodeLocator;
|
||||
use crate::source_code_style::SourceCodeStyleDetector;
|
||||
|
||||
/// Return a vector of all non-`mock` imports.
|
||||
fn clean_import_aliases(aliases: Vec<ImportAlias>) -> (Vec<ImportAlias>, Vec<Option<AsName>>) {
|
||||
let mut clean_aliases: Vec<ImportAlias> = vec![];
|
||||
let mut mock_aliases: Vec<Option<AsName>> = vec![];
|
||||
for alias in aliases {
|
||||
match &alias.name {
|
||||
// Ex) `import mock`
|
||||
NameOrAttribute::N(name_struct) => {
|
||||
if name_struct.value == "mock" {
|
||||
mock_aliases.push(alias.asname.clone());
|
||||
continue;
|
||||
}
|
||||
clean_aliases.push(alias);
|
||||
}
|
||||
// Ex) `import mock.mock`
|
||||
NameOrAttribute::A(attribute_struct) => {
|
||||
if let Expression::Name(name_struct) = &*attribute_struct.value {
|
||||
if name_struct.value == "mock" && attribute_struct.attr.value == "mock" {
|
||||
mock_aliases.push(alias.asname.clone());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
clean_aliases.push(alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
(clean_aliases, mock_aliases)
|
||||
}
|
||||
|
||||
/// Return `true` if the aliases contain `mock`.
|
||||
fn includes_mock_member(aliases: &[ImportAlias]) -> bool {
|
||||
for alias in aliases {
|
||||
let ImportAlias { name, .. } = &alias;
|
||||
// Ex) `import mock.mock`
|
||||
if let NameOrAttribute::A(attribute_struct) = name {
|
||||
if let Expression::Name(name_struct) = &*attribute_struct.value {
|
||||
if name_struct.value == "mock" && attribute_struct.attr.value == "mock" {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn format_mocks(
|
||||
aliases: Vec<Option<AsName>>,
|
||||
indent: &str,
|
||||
stylist: &SourceCodeStyleDetector,
|
||||
) -> String {
|
||||
let mut content = String::new();
|
||||
for alias in aliases {
|
||||
match alias {
|
||||
None => {
|
||||
if !content.is_empty() {
|
||||
content.push_str(stylist.line_ending());
|
||||
content.push_str(indent);
|
||||
}
|
||||
content.push_str("from unittest import mock");
|
||||
}
|
||||
Some(as_name) => {
|
||||
if let AssignTargetExpression::Name(name) = as_name.name {
|
||||
if !content.is_empty() {
|
||||
content.push_str(stylist.line_ending());
|
||||
content.push_str(indent);
|
||||
}
|
||||
content.push_str("from unittest import mock as ");
|
||||
content.push_str(name.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
content
|
||||
}
|
||||
|
||||
/// Format the `import mock` rewrite.
|
||||
fn format_import(
|
||||
stmt: &Stmt,
|
||||
indent: &str,
|
||||
locator: &SourceCodeLocator,
|
||||
stylist: &SourceCodeStyleDetector,
|
||||
) -> Result<String> {
|
||||
let module_text = locator.slice_source_code_range(&Range::from_located(stmt));
|
||||
let mut tree = match_module(&module_text)?;
|
||||
let mut import = match_import(&mut tree)?;
|
||||
|
||||
let Import { names, .. } = import.clone();
|
||||
let (clean_aliases, mock_aliases) = clean_import_aliases(names);
|
||||
|
||||
Ok(if clean_aliases.is_empty() {
|
||||
format_mocks(mock_aliases, indent, stylist)
|
||||
} else {
|
||||
import.names = clean_aliases;
|
||||
|
||||
let mut state = CodegenState::default();
|
||||
tree.codegen(&mut state);
|
||||
|
||||
let mut content = state.to_string();
|
||||
content.push_str(stylist.line_ending());
|
||||
content.push_str(indent);
|
||||
content.push_str(&format_mocks(mock_aliases, indent, stylist));
|
||||
content
|
||||
})
|
||||
}
|
||||
|
||||
/// Format the `from mock import ...` rewrite.
|
||||
fn format_import_from(
|
||||
stmt: &Stmt,
|
||||
indent: &str,
|
||||
locator: &SourceCodeLocator,
|
||||
stylist: &SourceCodeStyleDetector,
|
||||
) -> Result<String> {
|
||||
let module_text = locator.slice_source_code_range(&Range::from_located(stmt));
|
||||
let mut tree = match_module(&module_text).unwrap();
|
||||
let mut import = match_import_from(&mut tree)?;
|
||||
|
||||
let ImportFrom {
|
||||
names: ImportNames::Aliases(names),
|
||||
..
|
||||
} = import.clone() else {
|
||||
unreachable!("Expected ImportNames::Aliases");
|
||||
};
|
||||
|
||||
let has_mock_member = includes_mock_member(&names);
|
||||
let (clean_aliases, mock_aliases) = clean_import_aliases(names);
|
||||
|
||||
Ok(if clean_aliases.is_empty() {
|
||||
format_mocks(mock_aliases, indent, stylist)
|
||||
} else {
|
||||
import.names = ImportNames::Aliases(clean_aliases);
|
||||
import.module = Some(NameOrAttribute::A(Box::new(Attribute {
|
||||
value: Box::new(Expression::Name(Box::new(Name {
|
||||
value: "unittest",
|
||||
lpar: vec![],
|
||||
rpar: vec![],
|
||||
}))),
|
||||
attr: Name {
|
||||
value: "mock",
|
||||
lpar: vec![],
|
||||
rpar: vec![],
|
||||
},
|
||||
dot: Dot {
|
||||
whitespace_before: ParenthesizableWhitespace::default(),
|
||||
whitespace_after: ParenthesizableWhitespace::default(),
|
||||
},
|
||||
lpar: vec![],
|
||||
rpar: vec![],
|
||||
})));
|
||||
|
||||
let mut state = CodegenState::default();
|
||||
tree.codegen(&mut state);
|
||||
|
||||
let mut content = state.to_string();
|
||||
if has_mock_member {
|
||||
content.push_str(stylist.line_ending());
|
||||
content.push_str(indent);
|
||||
content.push_str(&format_mocks(mock_aliases, indent, stylist));
|
||||
}
|
||||
content
|
||||
})
|
||||
}
|
||||
|
||||
/// UP026
|
||||
pub fn rewrite_mock_attribute(checker: &mut Checker, expr: &Expr) {
|
||||
if let ExprKind::Attribute { value, .. } = &expr.node {
|
||||
if collect_call_paths(value) == ["mock", "mock"] {
|
||||
let mut check = Check::new(
|
||||
CheckKind::RewriteMockImport(MockReference::Attribute),
|
||||
Range::from_located(value),
|
||||
);
|
||||
if checker.patch(&CheckCode::UP026) {
|
||||
check.amend(Fix::replacement(
|
||||
"mock".to_string(),
|
||||
value.location,
|
||||
value.end_location.unwrap(),
|
||||
));
|
||||
}
|
||||
checker.add_check(check);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// UP026
|
||||
pub fn rewrite_mock_import(checker: &mut Checker, stmt: &Stmt) {
|
||||
match &stmt.node {
|
||||
StmtKind::Import { names } => {
|
||||
// Find all `mock` imports.
|
||||
if names
|
||||
.iter()
|
||||
.any(|name| name.node.name == "mock" || name.node.name == "mock.mock")
|
||||
{
|
||||
// Generate the fix, if needed, which is shared between all `mock` imports.
|
||||
let content = if checker.patch(&CheckCode::UP026) {
|
||||
let indent = indentation(checker, stmt);
|
||||
match format_import(stmt, &indent, checker.locator, checker.style) {
|
||||
Ok(content) => Some(content),
|
||||
Err(e) => {
|
||||
error!("Failed to rewrite `mock` import: {e}");
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Add a `Check` for each `mock` import.
|
||||
for name in names {
|
||||
if name.node.name == "mock" || name.node.name == "mock.mock" {
|
||||
let mut check = Check::new(
|
||||
CheckKind::RewriteMockImport(MockReference::Import),
|
||||
Range::from_located(name),
|
||||
);
|
||||
if let Some(content) = content.as_ref() {
|
||||
check.amend(Fix::replacement(
|
||||
content.clone(),
|
||||
stmt.location,
|
||||
stmt.end_location.unwrap(),
|
||||
));
|
||||
}
|
||||
checker.add_check(check);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
StmtKind::ImportFrom {
|
||||
module: Some(module),
|
||||
level,
|
||||
..
|
||||
} => {
|
||||
if level.map_or(false, |level| level > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if module == "mock" {
|
||||
let mut check = Check::new(
|
||||
CheckKind::RewriteMockImport(MockReference::Import),
|
||||
Range::from_located(stmt),
|
||||
);
|
||||
if checker.patch(&CheckCode::UP026) {
|
||||
let indent = indentation(checker, stmt);
|
||||
match format_import_from(stmt, &indent, checker.locator, checker.style) {
|
||||
Ok(content) => {
|
||||
check.amend(Fix::replacement(
|
||||
content,
|
||||
stmt.location,
|
||||
stmt.end_location.unwrap(),
|
||||
));
|
||||
}
|
||||
Err(e) => error!("Failed to rewrite `mock` import: {e}"),
|
||||
}
|
||||
}
|
||||
checker.add_check(check);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
@@ -84,10 +84,10 @@ fn replace_with_bytes_literal(
|
||||
) -> Check {
|
||||
let mut check = Check::new(CheckKind::UnnecessaryEncodeUTF8, Range::from_located(expr));
|
||||
if patch {
|
||||
let content = locator.slice_source_code_range(&Range {
|
||||
location: constant.location,
|
||||
end_location: constant.end_location.unwrap(),
|
||||
});
|
||||
let content = locator.slice_source_code_range(&Range::new(
|
||||
constant.location,
|
||||
constant.end_location.unwrap(),
|
||||
));
|
||||
let content = format!(
|
||||
"b{}",
|
||||
content.trim_start_matches('u').trim_start_matches('U')
|
||||
|
||||
@@ -80,7 +80,7 @@ pub fn unnecessary_future_import(checker: &mut Checker, stmt: &Stmt, names: &[Lo
|
||||
}
|
||||
check.amend(fix);
|
||||
}
|
||||
Err(e) => error!("Failed to remove __future__ import: {e}"),
|
||||
Err(e) => error!("Failed to remove `__future__` import: {e}"),
|
||||
}
|
||||
}
|
||||
checker.add_check(check);
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
---
|
||||
source: src/pyupgrade/mod.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
OSErrorAlias: EnvironmentError
|
||||
location:
|
||||
row: 6
|
||||
column: 7
|
||||
end_location:
|
||||
row: 6
|
||||
column: 23
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 6
|
||||
column: 7
|
||||
end_location:
|
||||
row: 6
|
||||
column: 23
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: IOError
|
||||
location:
|
||||
row: 11
|
||||
column: 7
|
||||
end_location:
|
||||
row: 11
|
||||
column: 14
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 11
|
||||
column: 7
|
||||
end_location:
|
||||
row: 11
|
||||
column: 14
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: WindowsError
|
||||
location:
|
||||
row: 16
|
||||
column: 7
|
||||
end_location:
|
||||
row: 16
|
||||
column: 19
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 16
|
||||
column: 7
|
||||
end_location:
|
||||
row: 16
|
||||
column: 19
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: mmap.error
|
||||
location:
|
||||
row: 21
|
||||
column: 7
|
||||
end_location:
|
||||
row: 21
|
||||
column: 17
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 21
|
||||
column: 7
|
||||
end_location:
|
||||
row: 21
|
||||
column: 17
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: select.error
|
||||
location:
|
||||
row: 26
|
||||
column: 7
|
||||
end_location:
|
||||
row: 26
|
||||
column: 19
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 26
|
||||
column: 7
|
||||
end_location:
|
||||
row: 26
|
||||
column: 19
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: socket.error
|
||||
location:
|
||||
row: 31
|
||||
column: 7
|
||||
end_location:
|
||||
row: 31
|
||||
column: 19
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 31
|
||||
column: 7
|
||||
end_location:
|
||||
row: 31
|
||||
column: 19
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: error
|
||||
location:
|
||||
row: 36
|
||||
column: 7
|
||||
end_location:
|
||||
row: 36
|
||||
column: 12
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 36
|
||||
column: 7
|
||||
end_location:
|
||||
row: 36
|
||||
column: 12
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: ~
|
||||
location:
|
||||
row: 43
|
||||
column: 7
|
||||
end_location:
|
||||
row: 43
|
||||
column: 17
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 43
|
||||
column: 7
|
||||
end_location:
|
||||
row: 43
|
||||
column: 17
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: ~
|
||||
location:
|
||||
row: 47
|
||||
column: 7
|
||||
end_location:
|
||||
row: 47
|
||||
column: 20
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 47
|
||||
column: 7
|
||||
end_location:
|
||||
row: 47
|
||||
column: 20
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: ~
|
||||
location:
|
||||
row: 51
|
||||
column: 7
|
||||
end_location:
|
||||
row: 51
|
||||
column: 57
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 51
|
||||
column: 7
|
||||
end_location:
|
||||
row: 51
|
||||
column: 57
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: ~
|
||||
location:
|
||||
row: 58
|
||||
column: 7
|
||||
end_location:
|
||||
row: 58
|
||||
column: 35
|
||||
fix:
|
||||
content: "(OSError, KeyError)"
|
||||
location:
|
||||
row: 58
|
||||
column: 7
|
||||
end_location:
|
||||
row: 58
|
||||
column: 35
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: ~
|
||||
location:
|
||||
row: 65
|
||||
column: 7
|
||||
end_location:
|
||||
row: 65
|
||||
column: 23
|
||||
fix:
|
||||
content: "(OSError, error)"
|
||||
location:
|
||||
row: 65
|
||||
column: 7
|
||||
end_location:
|
||||
row: 65
|
||||
column: 23
|
||||
parent: ~
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
source: src/pyupgrade/mod.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
OSErrorAlias: ~
|
||||
location:
|
||||
row: 5
|
||||
column: 7
|
||||
end_location:
|
||||
row: 5
|
||||
column: 37
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 5
|
||||
column: 7
|
||||
end_location:
|
||||
row: 5
|
||||
column: 37
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: ~
|
||||
location:
|
||||
row: 7
|
||||
column: 7
|
||||
end_location:
|
||||
row: 7
|
||||
column: 40
|
||||
fix:
|
||||
content: "(OSError, KeyError)"
|
||||
location:
|
||||
row: 7
|
||||
column: 7
|
||||
end_location:
|
||||
row: 7
|
||||
column: 40
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: ~
|
||||
location:
|
||||
row: 12
|
||||
column: 7
|
||||
end_location:
|
||||
row: 16
|
||||
column: 1
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 12
|
||||
column: 7
|
||||
end_location:
|
||||
row: 16
|
||||
column: 1
|
||||
parent: ~
|
||||
|
||||
@@ -0,0 +1,345 @@
|
||||
---
|
||||
source: src/pyupgrade/mod.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
OSErrorAlias: socket.error
|
||||
location:
|
||||
row: 10
|
||||
column: 6
|
||||
end_location:
|
||||
row: 10
|
||||
column: 18
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 10
|
||||
column: 6
|
||||
end_location:
|
||||
row: 10
|
||||
column: 18
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: mmap.error
|
||||
location:
|
||||
row: 11
|
||||
column: 6
|
||||
end_location:
|
||||
row: 11
|
||||
column: 16
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 11
|
||||
column: 6
|
||||
end_location:
|
||||
row: 11
|
||||
column: 16
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: select.error
|
||||
location:
|
||||
row: 12
|
||||
column: 6
|
||||
end_location:
|
||||
row: 12
|
||||
column: 18
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 12
|
||||
column: 6
|
||||
end_location:
|
||||
row: 12
|
||||
column: 18
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: socket.error
|
||||
location:
|
||||
row: 14
|
||||
column: 6
|
||||
end_location:
|
||||
row: 14
|
||||
column: 18
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 14
|
||||
column: 6
|
||||
end_location:
|
||||
row: 14
|
||||
column: 18
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: mmap.error
|
||||
location:
|
||||
row: 15
|
||||
column: 6
|
||||
end_location:
|
||||
row: 15
|
||||
column: 16
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 15
|
||||
column: 6
|
||||
end_location:
|
||||
row: 15
|
||||
column: 16
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: select.error
|
||||
location:
|
||||
row: 16
|
||||
column: 6
|
||||
end_location:
|
||||
row: 16
|
||||
column: 18
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 16
|
||||
column: 6
|
||||
end_location:
|
||||
row: 16
|
||||
column: 18
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: socket.error
|
||||
location:
|
||||
row: 18
|
||||
column: 6
|
||||
end_location:
|
||||
row: 18
|
||||
column: 18
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 18
|
||||
column: 6
|
||||
end_location:
|
||||
row: 18
|
||||
column: 18
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: error
|
||||
location:
|
||||
row: 25
|
||||
column: 6
|
||||
end_location:
|
||||
row: 25
|
||||
column: 11
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 25
|
||||
column: 6
|
||||
end_location:
|
||||
row: 25
|
||||
column: 11
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: error
|
||||
location:
|
||||
row: 28
|
||||
column: 6
|
||||
end_location:
|
||||
row: 28
|
||||
column: 11
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 28
|
||||
column: 6
|
||||
end_location:
|
||||
row: 28
|
||||
column: 11
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: error
|
||||
location:
|
||||
row: 31
|
||||
column: 6
|
||||
end_location:
|
||||
row: 31
|
||||
column: 11
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 31
|
||||
column: 6
|
||||
end_location:
|
||||
row: 31
|
||||
column: 11
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: EnvironmentError
|
||||
location:
|
||||
row: 34
|
||||
column: 6
|
||||
end_location:
|
||||
row: 34
|
||||
column: 22
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 34
|
||||
column: 6
|
||||
end_location:
|
||||
row: 34
|
||||
column: 22
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: IOError
|
||||
location:
|
||||
row: 35
|
||||
column: 6
|
||||
end_location:
|
||||
row: 35
|
||||
column: 13
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 35
|
||||
column: 6
|
||||
end_location:
|
||||
row: 35
|
||||
column: 13
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: WindowsError
|
||||
location:
|
||||
row: 36
|
||||
column: 6
|
||||
end_location:
|
||||
row: 36
|
||||
column: 18
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 36
|
||||
column: 6
|
||||
end_location:
|
||||
row: 36
|
||||
column: 18
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: EnvironmentError
|
||||
location:
|
||||
row: 38
|
||||
column: 6
|
||||
end_location:
|
||||
row: 38
|
||||
column: 22
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 38
|
||||
column: 6
|
||||
end_location:
|
||||
row: 38
|
||||
column: 22
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: IOError
|
||||
location:
|
||||
row: 39
|
||||
column: 6
|
||||
end_location:
|
||||
row: 39
|
||||
column: 13
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 39
|
||||
column: 6
|
||||
end_location:
|
||||
row: 39
|
||||
column: 13
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: WindowsError
|
||||
location:
|
||||
row: 40
|
||||
column: 6
|
||||
end_location:
|
||||
row: 40
|
||||
column: 18
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 40
|
||||
column: 6
|
||||
end_location:
|
||||
row: 40
|
||||
column: 18
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: EnvironmentError
|
||||
location:
|
||||
row: 42
|
||||
column: 6
|
||||
end_location:
|
||||
row: 42
|
||||
column: 22
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 42
|
||||
column: 6
|
||||
end_location:
|
||||
row: 42
|
||||
column: 22
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: WindowsError
|
||||
location:
|
||||
row: 48
|
||||
column: 6
|
||||
end_location:
|
||||
row: 48
|
||||
column: 18
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 48
|
||||
column: 6
|
||||
end_location:
|
||||
row: 48
|
||||
column: 18
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: EnvironmentError
|
||||
location:
|
||||
row: 49
|
||||
column: 6
|
||||
end_location:
|
||||
row: 49
|
||||
column: 22
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 49
|
||||
column: 6
|
||||
end_location:
|
||||
row: 49
|
||||
column: 22
|
||||
parent: ~
|
||||
- kind:
|
||||
OSErrorAlias: IOError
|
||||
location:
|
||||
row: 50
|
||||
column: 6
|
||||
end_location:
|
||||
row: 50
|
||||
column: 13
|
||||
fix:
|
||||
content: OSError
|
||||
location:
|
||||
row: 50
|
||||
column: 6
|
||||
end_location:
|
||||
row: 50
|
||||
column: 13
|
||||
parent: ~
|
||||
|
||||
@@ -0,0 +1,362 @@
|
||||
---
|
||||
source: src/pyupgrade/mod.rs
|
||||
expression: checks
|
||||
---
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 3
|
||||
column: 11
|
||||
end_location:
|
||||
row: 3
|
||||
column: 15
|
||||
fix:
|
||||
content: from unittest import mock
|
||||
location:
|
||||
row: 3
|
||||
column: 4
|
||||
end_location:
|
||||
row: 3
|
||||
column: 15
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 6
|
||||
column: 11
|
||||
end_location:
|
||||
row: 6
|
||||
column: 15
|
||||
fix:
|
||||
content: "import sys\n from unittest import mock"
|
||||
location:
|
||||
row: 6
|
||||
column: 4
|
||||
end_location:
|
||||
row: 6
|
||||
column: 20
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 9
|
||||
column: 7
|
||||
end_location:
|
||||
row: 9
|
||||
column: 16
|
||||
fix:
|
||||
content: from unittest import mock
|
||||
location:
|
||||
row: 9
|
||||
column: 0
|
||||
end_location:
|
||||
row: 9
|
||||
column: 16
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 12
|
||||
column: 19
|
||||
end_location:
|
||||
row: 12
|
||||
column: 23
|
||||
fix:
|
||||
content: "import contextlib, sys\nfrom unittest import mock"
|
||||
location:
|
||||
row: 12
|
||||
column: 0
|
||||
end_location:
|
||||
row: 12
|
||||
column: 28
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 15
|
||||
column: 7
|
||||
end_location:
|
||||
row: 15
|
||||
column: 11
|
||||
fix:
|
||||
content: "import sys\nfrom unittest import mock"
|
||||
location:
|
||||
row: 15
|
||||
column: 0
|
||||
end_location:
|
||||
row: 15
|
||||
column: 16
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 19
|
||||
column: 0
|
||||
end_location:
|
||||
row: 19
|
||||
column: 21
|
||||
fix:
|
||||
content: from unittest import mock
|
||||
location:
|
||||
row: 19
|
||||
column: 0
|
||||
end_location:
|
||||
row: 19
|
||||
column: 21
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 22
|
||||
column: 0
|
||||
end_location:
|
||||
row: 27
|
||||
column: 1
|
||||
fix:
|
||||
content: "from unittest.mock import (\n a,\n b,\n c,\n)"
|
||||
location:
|
||||
row: 22
|
||||
column: 0
|
||||
end_location:
|
||||
row: 27
|
||||
column: 1
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 30
|
||||
column: 0
|
||||
end_location:
|
||||
row: 35
|
||||
column: 1
|
||||
fix:
|
||||
content: "from unittest.mock import (\n a,\n b,\n c\n)"
|
||||
location:
|
||||
row: 30
|
||||
column: 0
|
||||
end_location:
|
||||
row: 35
|
||||
column: 1
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 39
|
||||
column: 8
|
||||
end_location:
|
||||
row: 44
|
||||
column: 9
|
||||
fix:
|
||||
content: "from unittest.mock import (\n a,\n b,\n c\n )"
|
||||
location:
|
||||
row: 39
|
||||
column: 8
|
||||
end_location:
|
||||
row: 44
|
||||
column: 9
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 50
|
||||
column: 7
|
||||
end_location:
|
||||
row: 50
|
||||
column: 11
|
||||
fix:
|
||||
content: "from unittest import mock\nfrom unittest import mock"
|
||||
location:
|
||||
row: 50
|
||||
column: 0
|
||||
end_location:
|
||||
row: 50
|
||||
column: 17
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 50
|
||||
column: 13
|
||||
end_location:
|
||||
row: 50
|
||||
column: 17
|
||||
fix:
|
||||
content: "from unittest import mock\nfrom unittest import mock"
|
||||
location:
|
||||
row: 50
|
||||
column: 0
|
||||
end_location:
|
||||
row: 50
|
||||
column: 17
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 53
|
||||
column: 7
|
||||
end_location:
|
||||
row: 53
|
||||
column: 18
|
||||
fix:
|
||||
content: from unittest import mock as foo
|
||||
location:
|
||||
row: 53
|
||||
column: 0
|
||||
end_location:
|
||||
row: 53
|
||||
column: 18
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 56
|
||||
column: 0
|
||||
end_location:
|
||||
row: 56
|
||||
column: 28
|
||||
fix:
|
||||
content: from unittest import mock as foo
|
||||
location:
|
||||
row: 56
|
||||
column: 0
|
||||
end_location:
|
||||
row: 56
|
||||
column: 28
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 60
|
||||
column: 11
|
||||
end_location:
|
||||
row: 60
|
||||
column: 22
|
||||
fix:
|
||||
content: "from unittest import mock as foo\n from unittest import mock as bar\n from unittest import mock"
|
||||
location:
|
||||
row: 60
|
||||
column: 4
|
||||
end_location:
|
||||
row: 60
|
||||
column: 41
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 60
|
||||
column: 24
|
||||
end_location:
|
||||
row: 60
|
||||
column: 35
|
||||
fix:
|
||||
content: "from unittest import mock as foo\n from unittest import mock as bar\n from unittest import mock"
|
||||
location:
|
||||
row: 60
|
||||
column: 4
|
||||
end_location:
|
||||
row: 60
|
||||
column: 41
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 60
|
||||
column: 37
|
||||
end_location:
|
||||
row: 60
|
||||
column: 41
|
||||
fix:
|
||||
content: "from unittest import mock as foo\n from unittest import mock as bar\n from unittest import mock"
|
||||
location:
|
||||
row: 60
|
||||
column: 4
|
||||
end_location:
|
||||
row: 60
|
||||
column: 41
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 63
|
||||
column: 11
|
||||
end_location:
|
||||
row: 63
|
||||
column: 22
|
||||
fix:
|
||||
content: "import os\n from unittest import mock as foo\n from unittest import mock as bar\n from unittest import mock"
|
||||
location:
|
||||
row: 63
|
||||
column: 4
|
||||
end_location:
|
||||
row: 63
|
||||
column: 45
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 63
|
||||
column: 24
|
||||
end_location:
|
||||
row: 63
|
||||
column: 35
|
||||
fix:
|
||||
content: "import os\n from unittest import mock as foo\n from unittest import mock as bar\n from unittest import mock"
|
||||
location:
|
||||
row: 63
|
||||
column: 4
|
||||
end_location:
|
||||
row: 63
|
||||
column: 45
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 63
|
||||
column: 37
|
||||
end_location:
|
||||
row: 63
|
||||
column: 41
|
||||
fix:
|
||||
content: "import os\n from unittest import mock as foo\n from unittest import mock as bar\n from unittest import mock"
|
||||
location:
|
||||
row: 63
|
||||
column: 4
|
||||
end_location:
|
||||
row: 63
|
||||
column: 45
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Import
|
||||
location:
|
||||
row: 67
|
||||
column: 4
|
||||
end_location:
|
||||
row: 67
|
||||
column: 51
|
||||
fix:
|
||||
content: "from unittest import mock as foo\n from unittest import mock as bar\n from unittest import mock"
|
||||
location:
|
||||
row: 67
|
||||
column: 4
|
||||
end_location:
|
||||
row: 67
|
||||
column: 51
|
||||
parent: ~
|
||||
- kind:
|
||||
RewriteMockImport: Attribute
|
||||
location:
|
||||
row: 74
|
||||
column: 4
|
||||
end_location:
|
||||
row: 74
|
||||
column: 13
|
||||
fix:
|
||||
content: mock
|
||||
location:
|
||||
row: 74
|
||||
column: 4
|
||||
end_location:
|
||||
row: 74
|
||||
column: 13
|
||||
parent: ~
|
||||
|
||||
@@ -1614,10 +1614,7 @@ pub fn ambiguous_unicode_character(
|
||||
) -> Vec<Check> {
|
||||
let mut checks = vec![];
|
||||
|
||||
let text = locator.slice_source_code_range(&Range {
|
||||
location: start,
|
||||
end_location: end,
|
||||
});
|
||||
let text = locator.slice_source_code_range(&Range::new(start, end));
|
||||
|
||||
let mut col_offset = 0;
|
||||
let mut row_offset = 0;
|
||||
@@ -1648,10 +1645,7 @@ pub fn ambiguous_unicode_character(
|
||||
representant,
|
||||
),
|
||||
},
|
||||
Range {
|
||||
location,
|
||||
end_location,
|
||||
},
|
||||
Range::new(location, end_location),
|
||||
);
|
||||
if settings.enabled.contains(check.kind.code()) {
|
||||
if matches!(autofix, flags::Autofix::Enabled)
|
||||
|
||||
@@ -125,10 +125,7 @@ fn detect_indentation(contents: &str, locator: &SourceCodeLocator) -> Option<Ind
|
||||
for (_start, tok, end) in lexer::make_tokenizer(contents).flatten() {
|
||||
if let Tok::Indent { .. } = tok {
|
||||
let start = Location::new(end.row(), 0);
|
||||
let whitespace = locator.slice_source_code_range(&Range {
|
||||
location: start,
|
||||
end_location: end,
|
||||
});
|
||||
let whitespace = locator.slice_source_code_range(&Range::new(start, end));
|
||||
return Some(Indentation(whitespace.to_string()));
|
||||
}
|
||||
}
|
||||
@@ -139,10 +136,7 @@ fn detect_indentation(contents: &str, locator: &SourceCodeLocator) -> Option<Ind
|
||||
fn detect_quote(contents: &str, locator: &SourceCodeLocator) -> Option<Quote> {
|
||||
for (start, tok, end) in lexer::make_tokenizer(contents).flatten() {
|
||||
if let Tok::String { .. } = tok {
|
||||
let content = locator.slice_source_code_range(&Range {
|
||||
location: start,
|
||||
end_location: end,
|
||||
});
|
||||
let content = locator.slice_source_code_range(&Range::new(start, end));
|
||||
if let Some(pattern) = leading_quote(&content) {
|
||||
if pattern.contains('\'') {
|
||||
return Some(Quote::Single);
|
||||
|
||||
Reference in New Issue
Block a user