Compare commits
135 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a0e1926f2 | ||
|
|
4473c7e905 | ||
|
|
20930b3675 | ||
|
|
fb1a638a96 | ||
|
|
16964409a8 | ||
|
|
aacfc9ee0b | ||
|
|
bd14f92898 | ||
|
|
cc116b0192 | ||
|
|
0d27c0be27 | ||
|
|
60359c6adf | ||
|
|
77692e4b5f | ||
|
|
731f3a74a9 | ||
|
|
03275c9c98 | ||
|
|
8d99e317b8 | ||
|
|
d4d67e3014 | ||
|
|
e9a236f740 | ||
|
|
ebb31dc29b | ||
|
|
b9e92affb1 | ||
|
|
68fbd0f029 | ||
|
|
8d01efb571 | ||
|
|
da5a25b421 | ||
|
|
bfdab4ac94 | ||
|
|
d1389894a4 | ||
|
|
8b277138de | ||
|
|
e0fe34c523 | ||
|
|
995fee5ddd | ||
|
|
99906c16db | ||
|
|
b6cb35414e | ||
|
|
b351221049 | ||
|
|
afb6f55b8d | ||
|
|
03a8ece954 | ||
|
|
8aeec35bfb | ||
|
|
93259acb31 | ||
|
|
ca7fe686d5 | ||
|
|
5dd9e99a4b | ||
|
|
8f0270acfe | ||
|
|
7ce38840a2 | ||
|
|
8ab8217ca5 | ||
|
|
5d3ff69053 | ||
|
|
726399b2b3 | ||
|
|
8329237f19 | ||
|
|
cd5882c66d | ||
|
|
0c05488740 | ||
|
|
1425b21d93 | ||
|
|
e5a59f41b0 | ||
|
|
8647bec3cb | ||
|
|
14042800c2 | ||
|
|
21986e89fd | ||
|
|
c4014ef2d3 | ||
|
|
9ffd20707f | ||
|
|
6d5aa344a1 | ||
|
|
e9be5fc7be | ||
|
|
f74050e5b1 | ||
|
|
90b2d85c85 | ||
|
|
ccf848705d | ||
|
|
3b535fcc74 | ||
|
|
06321fd240 | ||
|
|
cdae2f0e67 | ||
|
|
f52691a90a | ||
|
|
07e47bef4b | ||
|
|
86b61806a5 | ||
|
|
31ce37dd8e | ||
|
|
2cf6d05586 | ||
|
|
65c34c56d6 | ||
|
|
2315db7d13 | ||
|
|
f1a183c171 | ||
|
|
509c6d5ec7 | ||
|
|
6695988b59 | ||
|
|
e3867b172d | ||
|
|
4b8e30f350 | ||
|
|
8fd0d8e9d8 | ||
|
|
70895a8f1e | ||
|
|
f2c9f94f73 | ||
|
|
605c6069e2 | ||
|
|
92c2981b6d | ||
|
|
4ad8db3d61 | ||
|
|
0e8c237167 | ||
|
|
960c5e2006 | ||
|
|
9ba17fbf92 | ||
|
|
bfdf972a5d | ||
|
|
0c215365ae | ||
|
|
815284f890 | ||
|
|
6880338a9a | ||
|
|
68b749c67d | ||
|
|
c0fc55b812 | ||
|
|
ba9cf70917 | ||
|
|
f73dfbbfd3 | ||
|
|
62c273cd22 | ||
|
|
938ad9a39e | ||
|
|
14248cb8cb | ||
|
|
3a280039e1 | ||
|
|
4e9e58bdc0 | ||
|
|
926b5494ad | ||
|
|
6717b48ca5 | ||
|
|
f7bb5bc858 | ||
|
|
3e23fd1487 | ||
|
|
01c74e0629 | ||
|
|
1e3cf87f67 | ||
|
|
248447e139 | ||
|
|
95f139583a | ||
|
|
74903f23d6 | ||
|
|
3ee20a70d3 | ||
|
|
4c2fbb7ac0 | ||
|
|
7a66f98590 | ||
|
|
a2bf3916f3 | ||
|
|
c9aa7b9308 | ||
|
|
d880ca6cc6 | ||
|
|
080f99b908 | ||
|
|
a7dc491ff1 | ||
|
|
cdc8f8c91a | ||
|
|
138c46e793 | ||
|
|
a86c57a832 | ||
|
|
818582fe8a | ||
|
|
90574c1088 | ||
|
|
3061a35e7c | ||
|
|
87681697ae | ||
|
|
e9ec2a7b36 | ||
|
|
b0bb75dc1c | ||
|
|
ebca5c2df8 | ||
|
|
16b10c42f0 | ||
|
|
4a6e5d1549 | ||
|
|
b078050732 | ||
|
|
5f796b39b4 | ||
|
|
9d34da23bd | ||
|
|
bde12c3bb3 | ||
|
|
f735660801 | ||
|
|
34cd22dfc1 | ||
|
|
9fafe16a55 | ||
|
|
e9a4cb1c1d | ||
|
|
9db825c731 | ||
|
|
2c7464604a | ||
|
|
cd2099f772 | ||
|
|
091d36cd30 | ||
|
|
02f156c6cb | ||
|
|
9f7350961e |
23
.github/workflows/ci.yaml
vendored
23
.github/workflows/ci.yaml
vendored
@@ -38,10 +38,9 @@ jobs:
|
||||
- run: cargo build --all --release
|
||||
- run: ./target/release/ruff_dev generate-all
|
||||
- run: git diff --quiet README.md || echo "::error file=README.md::This file is outdated. Run 'cargo +nightly dev generate-all'."
|
||||
- run: git diff --quiet src/checks_gen.rs || echo "::error file=src/checks_gen.rs::This file is outdated. Run 'cargo +nightly dev generate-all'."
|
||||
- run: git diff --quiet src/registry_gen.rs || echo "::error file=src/registry_gen.rs::This file is outdated. Run 'cargo +nightly dev generate-all'."
|
||||
- run: git diff --quiet ruff.schema.json || echo "::error file=ruff.schema.json::This file is outdated. Run 'cargo +nightly dev generate-all'."
|
||||
- run: git diff --quiet playground/src/ruff_options.ts || echo "::error file=playground/src/ruff_options.ts::This file is outdated. Run 'cargo +nightly dev generate-all'."
|
||||
- run: git diff --exit-code -- README.md src/checks_gen.rs ruff.schema.json playground/src/ruff_options.ts
|
||||
- run: git diff --exit-code -- README.md src/registry_gen.rs ruff.schema.json
|
||||
|
||||
cargo-fmt:
|
||||
name: "cargo fmt"
|
||||
@@ -117,8 +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
|
||||
- run: cargo test --all
|
||||
- name: Run tests
|
||||
run: |
|
||||
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.
|
||||
@@ -178,3 +181,15 @@ jobs:
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- run: maturin build -b bin
|
||||
|
||||
typos:
|
||||
name: Spell Check with Typos
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Actions Repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Check spelling of file.txt
|
||||
uses: crate-ci/typos@master
|
||||
with:
|
||||
files: .
|
||||
|
||||
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.200
|
||||
rev: v0.0.210
|
||||
hooks:
|
||||
- id: ruff
|
||||
|
||||
|
||||
@@ -9,6 +9,15 @@ free to submit a PR. For larger changes (e.g., new lint rules, new functionality
|
||||
options), consider submitting an [Issue](https://github.com/charliermarsh/ruff/issues) outlining
|
||||
your proposed change.
|
||||
|
||||
If you're looking for a place to start, we recommend implementing a new lint rule (see:
|
||||
[_Adding a new lint rule_](#example-adding-a-new-lint-rule), which will allow you to learn from and
|
||||
pattern-match against the examples in the existing codebase. Many lint rules are inspired by
|
||||
existing Python plugins, which can be used as a reference implementation.
|
||||
|
||||
As a concrete example: consider taking on one of the rules in [`flake8-simplify`](https://github.com/charliermarsh/ruff/issues/998),
|
||||
and looking to the originating [Python source](https://github.com/MartinThoma/flake8-simplify) for
|
||||
guidance.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Ruff is written in Rust. You'll need to install the
|
||||
@@ -47,57 +56,55 @@ prior to merging.
|
||||
|
||||
There are four phases to adding a new lint rule:
|
||||
|
||||
1. Define the rule in `src/checks.rs`.
|
||||
1. Define the rule in `src/registry.rs`.
|
||||
2. Define the _logic_ for triggering the rule in `src/checkers/ast.rs` (for AST-based checks),
|
||||
`src/checkers/tokens.rs` (for token-based checks), or `src/checkers/lines.rs` (for text-based checks).
|
||||
3. Add a test fixture.
|
||||
4. Update the generated files (documentation and generated code).
|
||||
|
||||
To define the rule, open up `src/checks.rs`. You'll need to define both a `CheckCode` and
|
||||
To define the rule, open up `src/registry.rs`. You'll need to define both a `CheckCode` and
|
||||
`CheckKind`. As an example, you can grep for `E402` and `ModuleImportNotAtTopOfFile`, and follow the
|
||||
pattern implemented therein.
|
||||
|
||||
To trigger the rule, you'll likely want to augment the logic in `src/check_ast.rs`, which defines
|
||||
To trigger the rule, you'll likely want to augment the logic in `src/checkers/ast.rs`, which defines
|
||||
the Python AST visitor, responsible for iterating over the abstract syntax tree and collecting
|
||||
lint-rule violations as it goes. If you need to inspect the AST, you can run
|
||||
`cargo +nightly dev print-ast` with a Python file. Grep for the `Check::new` invocations to
|
||||
understand how other, similar rules are implemented.
|
||||
|
||||
To add a test fixture, create a file under `resources/test/fixtures`, named to match the `CheckCode`
|
||||
you defined earlier (e.g., `E402.py`). This file should contain a variety of violations and
|
||||
non-violations designed to evaluate and demonstrate the behavior of your lint rule. Run Ruff locally
|
||||
with (e.g.) `cargo run resources/test/fixtures/E402.py --no-cache`. Once you're satisfied with the
|
||||
output, codify the behavior as a snapshot test by adding a new `testcase` macro to the `mod tests`
|
||||
section of `src/linter.rs`, like so:
|
||||
To add a test fixture, create a file under `resources/test/fixtures/[plugin-name]`, named to match
|
||||
the `CheckCode` you defined earlier (e.g., `E402.py`). This file should contain a variety of
|
||||
violations and non-violations designed to evaluate and demonstrate the behavior of your lint rule.
|
||||
|
||||
```rust
|
||||
#[test_case(CheckCode::A001, Path::new("A001.py"); "A001")]
|
||||
...
|
||||
```
|
||||
Run `cargo +nightly dev generate-all` to generate the code for your new fixture. Then run Ruff
|
||||
locally with (e.g.) `cargo run resources/test/fixtures/pycodestyle/E402.py --no-cache --select E402`.
|
||||
|
||||
Then, run `cargo test`. Your test will fail, but you'll be prompted to follow-up with
|
||||
`cargo insta review`. Accept the generated snapshot, then commit the snapshot file alongside the
|
||||
rest of your changes.
|
||||
Once you're satisfied with the output, codify the behavior as a snapshot test by adding a new
|
||||
`test_case` macro in the relevant `src/[plugin-name]/mod.rs` file. Then, run `cargo test`. Your
|
||||
test will fail, but you'll be prompted to follow-up with `cargo insta review`. Accept the generated
|
||||
snapshot, then commit the snapshot file alongside the rest of your changes.
|
||||
|
||||
Finally, regenerate the documentation and generated code with `cargo +nightly dev generate-all`.
|
||||
|
||||
### Example: Adding a new configuration option
|
||||
|
||||
Ruff's user-facing settings live in two places: first, the command-line options defined with
|
||||
[clap](https://docs.rs/clap/latest/clap/) via the `Cli` struct in `src/main.rs`; and second, the
|
||||
`Config` struct defined `src/pyproject.rs`, which is responsible for extracting user-defined
|
||||
settings from a `pyproject.toml` file.
|
||||
Ruff's user-facing settings live in a few different places.
|
||||
|
||||
Ultimately, these two sources of configuration are merged into the `Settings` struct defined
|
||||
in `src/settings.rs`, which is then threaded through the codebase.
|
||||
First, the command-line options are defined via the `Cli` struct in `src/cli.rs`.
|
||||
|
||||
To add a new configuration option, you'll likely want to _both_ add a CLI option to `src/main.rs`
|
||||
_and_ a `pyproject.toml` parameter to `src/pyproject.rs`. If you want to pattern-match against an
|
||||
existing example, grep for `dummy_variable_rgx`, which defines a regular expression to match against
|
||||
acceptable unused variables (e.g., `_`).
|
||||
Second, the `pyproject.toml` options are defined in `src/settings/options.rs` (via the `Options`
|
||||
struct), `src/settings/configuration.rs` (via the `Configuration` struct), and `src/settings/mod.rs`
|
||||
(via the `Settings` struct). These represent, respectively: the schema used to parse the
|
||||
`pyproject.toml` file; an internal, intermediate representation; and the final, internal
|
||||
representation used to power Ruff.
|
||||
|
||||
If the new plugin's configuration should be cached between runs, you'll need to add it to the
|
||||
`Hash` implementation for `Settings` in `src/settings/mod.rs`.
|
||||
To add a new configuration option, you'll likely want to modify these latter few files (along with
|
||||
`cli.rs`, if appropriate). If you want to pattern-match against an existing example, grep for
|
||||
`dummy_variable_rgx`, which defines a regular expression to match against acceptable unused
|
||||
variables (e.g., `_`).
|
||||
|
||||
Note that plugin-specific configuration options are defined in their own modules (e.g.,
|
||||
`src/flake8_unused_arguments/settings.rs`).
|
||||
|
||||
You may also want to add the new configuration option to the `flake8-to-ruff` tool, which is
|
||||
responsible for converting `flake8` configuration files to Ruff's TOML format. This logic
|
||||
|
||||
39
Cargo.lock
generated
39
Cargo.lock
generated
@@ -356,9 +356,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clearscreen"
|
||||
version = "1.0.10"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c969a6b6dadff9f3349b1f783f553e2411104763ca4789e1c6ca6a41f46a57b0"
|
||||
checksum = "41aa24cc5e1d6b3fc49ad4cd540b522fedcbe88bc6f259ff16e20e7010b6f8c7"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"terminfo",
|
||||
@@ -397,12 +397,6 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "common-path"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2382f75942f4b3be3690fe4f86365e9c853c1587d6ee58212cebf6e2a9ccd101"
|
||||
|
||||
[[package]]
|
||||
name = "configparser"
|
||||
version = "3.0.2"
|
||||
@@ -750,7 +744,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.200-dev.0"
|
||||
version = "0.0.210-dev.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.0.32",
|
||||
@@ -1274,13 +1268,14 @@ checksum = "d906846a98739ed9d73d66e62c2641eef8321f1734b7a1156ab045a0248fb2b3"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.24.3"
|
||||
version = "0.26.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069"
|
||||
checksum = "46a58d1d356c6597d08cde02c2f09d785b09e28711837b1ed667dc652c08a694"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1878,7 +1873,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.200"
|
||||
version = "0.0.210"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.9.1",
|
||||
"anyhow",
|
||||
@@ -1893,7 +1888,6 @@ dependencies = [
|
||||
"clap_complete_command",
|
||||
"clearscreen",
|
||||
"colored",
|
||||
"common-path",
|
||||
"console_error_panic_hook",
|
||||
"console_log",
|
||||
"criterion",
|
||||
@@ -1913,6 +1907,7 @@ dependencies = [
|
||||
"nohash-hasher",
|
||||
"notify",
|
||||
"num-bigint",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"path-absolutize",
|
||||
"quick-junit",
|
||||
@@ -1946,7 +1941,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_dev"
|
||||
version = "0.0.200"
|
||||
version = "0.0.210"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap 4.0.32",
|
||||
@@ -1967,7 +1962,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_macros"
|
||||
version = "0.0.200"
|
||||
version = "0.0.210"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2010,7 +2005,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-ast"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=68d26955b3e24198a150315e7959719b03709dee#68d26955b3e24198a150315e7959719b03709dee"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=4d53c7cb27c0379adf8b51c4d3d0d2174f41d590#4d53c7cb27c0379adf8b51c4d3d0d2174f41d590"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"rustpython-common",
|
||||
@@ -2020,11 +2015,13 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-common"
|
||||
version = "0.0.0"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=68d26955b3e24198a150315e7959719b03709dee#68d26955b3e24198a150315e7959719b03709dee"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=4d53c7cb27c0379adf8b51c4d3d0d2174f41d590#4d53c7cb27c0379adf8b51c4d3d0d2174f41d590"
|
||||
dependencies = [
|
||||
"ascii",
|
||||
"bitflags",
|
||||
"cfg-if 1.0.0",
|
||||
"hexf-parse",
|
||||
"itertools",
|
||||
"lexical-parse-float",
|
||||
"libc",
|
||||
"lock_api",
|
||||
@@ -2043,7 +2040,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-compiler-core"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=68d26955b3e24198a150315e7959719b03709dee#68d26955b3e24198a150315e7959719b03709dee"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=4d53c7cb27c0379adf8b51c4d3d0d2174f41d590#4d53c7cb27c0379adf8b51c4d3d0d2174f41d590"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitflags",
|
||||
@@ -2060,7 +2057,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "rustpython-parser"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=68d26955b3e24198a150315e7959719b03709dee#68d26955b3e24198a150315e7959719b03709dee"
|
||||
source = "git+https://github.com/RustPython/RustPython.git?rev=4d53c7cb27c0379adf8b51c4d3d0d2174f41d590#4d53c7cb27c0379adf8b51c4d3d0d2174f41d590"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
@@ -2638,9 +2635,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||
|
||||
[[package]]
|
||||
name = "update-informer"
|
||||
version = "0.5.0"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f154aee470c0882ea0f3b1cc2a46c5f4d24f282655f7b0cec065614fe24c447f"
|
||||
checksum = "152ff185ca29f7f487c51ca785b0f1d85970c4581f4cdd12ed499227890200f5"
|
||||
dependencies = [
|
||||
"directories",
|
||||
"semver",
|
||||
|
||||
16
Cargo.toml
16
Cargo.toml
@@ -6,7 +6,7 @@ members = [
|
||||
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.200"
|
||||
version = "0.0.210"
|
||||
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.65.0"
|
||||
@@ -32,7 +32,6 @@ chrono = { version = "0.4.21", default-features = false, features = ["clock"] }
|
||||
clap = { version = "4.0.1", features = ["derive"] }
|
||||
clap_complete_command = { version = "0.4.0" }
|
||||
colored = { version = "2.0.0" }
|
||||
common-path = { version = "1.0.0" }
|
||||
dirs = { version = "4.0.0" }
|
||||
fern = { version = "0.6.1" }
|
||||
filetime = { version = "0.2.17" }
|
||||
@@ -46,16 +45,17 @@ natord = { version = "1.0.9" }
|
||||
nohash-hasher = { version = "0.2.0" }
|
||||
notify = { version = "5.0.0" }
|
||||
num-bigint = { version = "0.4.3" }
|
||||
num-traits = "0.2.15"
|
||||
once_cell = { version = "1.16.0" }
|
||||
path-absolutize = { version = "3.0.14", features = ["once_cell_cache", "use_unix_paths_on_wasm"] }
|
||||
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.200", path = "ruff_macros" }
|
||||
ruff_macros = { version = "0.0.210", path = "ruff_macros" }
|
||||
rustc-hash = { version = "1.1.0" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "68d26955b3e24198a150315e7959719b03709dee" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "68d26955b3e24198a150315e7959719b03709dee" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "68d26955b3e24198a150315e7959719b03709dee" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "4d53c7cb27c0379adf8b51c4d3d0d2174f41d590" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "4d53c7cb27c0379adf8b51c4d3d0d2174f41d590" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "4d53c7cb27c0379adf8b51c4d3d0d2174f41d590" }
|
||||
schemars = { version = "0.8.11" }
|
||||
semver = { version = "1.0.16" }
|
||||
serde = { version = "1.0.147", features = ["derive"] }
|
||||
@@ -70,9 +70,9 @@ toml = { version = "0.5.9" }
|
||||
walkdir = { version = "2.3.2" }
|
||||
|
||||
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
||||
clearscreen = { version = "1.0.10" }
|
||||
clearscreen = { version = "2.0.0" }
|
||||
rayon = { version = "1.5.3" }
|
||||
update-informer = { version = "0.5.0", default-features = false, features = ["pypi"], optional = true }
|
||||
update-informer = { version = "0.6.0", default-features = false, features = ["pypi"], optional = true }
|
||||
|
||||
# https://docs.rs/getrandom/0.2.7/getrandom/#webassembly-support
|
||||
# For (future) wasm-pack support
|
||||
|
||||
25
LICENSE
25
LICENSE
@@ -388,6 +388,31 @@ are:
|
||||
SOFTWARE.
|
||||
"""
|
||||
|
||||
- flake8-implicit-str-concat, licensed as follows:
|
||||
"""
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019 Dylan Turner
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
"""
|
||||
|
||||
- flake8-import-conventions, licensed as follows:
|
||||
"""
|
||||
MIT License
|
||||
|
||||
433
README.md
433
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">
|
||||
@@ -22,8 +26,9 @@ An extremely fast Python linter, written in Rust.
|
||||
- 📦 Built-in caching, to avoid re-analyzing unchanged files
|
||||
- 🔧 Autofix support, for automatic error correction (e.g., automatically remove unused imports)
|
||||
- ⚖️ [Near-parity](#how-does-ruff-compare-to-flake8) with the built-in Flake8 rule set
|
||||
- 🔌 Native re-implementations of popular Flake8 plugins, like [`flake8-bugbear`](https://pypi.org/project/flake8-bugbear/)
|
||||
- 🌎 Monorepo-friendly configuration via hierarchical and cascading settings
|
||||
- 🔌 Native re-implementations of dozens of Flake8 plugins, like [`flake8-bugbear`](https://pypi.org/project/flake8-bugbear/)
|
||||
- ⌨️ First-party editor integrations for [VS Code](https://github.com/charliermarsh/ruff-vscode) and [more](https://github.com/charliermarsh/ruff-lsp)
|
||||
- 🌎 Monorepo-friendly, with [hierarchical and cascading configuration](#pyprojecttoml-discovery)
|
||||
|
||||
Ruff aims to be orders of magnitude faster than alternative tools while integrating more
|
||||
functionality behind a single, common interface.
|
||||
@@ -44,11 +49,14 @@ Ruff is extremely actively developed and used in major open-source projects like
|
||||
- [Bokeh](https://github.com/bokeh/bokeh)
|
||||
- [Zulip](https://github.com/zulip/zulip)
|
||||
- [Pydantic](https://github.com/pydantic/pydantic)
|
||||
- [Sphinx](https://github.com/sphinx-doc/sphinx)
|
||||
- [Hatch](https://github.com/pypa/hatch)
|
||||
- [Jupyter](https://github.com/jupyter-server/jupyter_server)
|
||||
- [Synapse](https://github.com/matrix-org/synapse)
|
||||
- [Ibis](https://github.com/ibis-project/ibis)
|
||||
- [Saleor](https://github.com/saleor/saleor)
|
||||
- [Polars](https://github.com/pola-rs/polars)
|
||||
- [Ibis](https://github.com/ibis-project/ibis)
|
||||
- [`pyca/cryptography`](https://github.com/pyca/cryptography)
|
||||
|
||||
Read the [launch blog post](https://notes.crmarsh.com/python-tooling-could-be-much-much-faster).
|
||||
|
||||
@@ -94,8 +102,10 @@ of [Conda](https://docs.conda.io/en/latest/):
|
||||
1. [flake8-comprehensions (C4)](#flake8-comprehensions-c4)
|
||||
1. [flake8-debugger (T10)](#flake8-debugger-t10)
|
||||
1. [flake8-errmsg (EM)](#flake8-errmsg-em)
|
||||
1. [flake8-implicit-str-concat (ISC)](#flake8-implicit-str-concat-isc)
|
||||
1. [flake8-import-conventions (ICN)](#flake8-import-conventions-icn)
|
||||
1. [flake8-print (T20)](#flake8-print-t20)
|
||||
1. [flake8-pytest-style (PT)](#flake8-pytest-style-pt)
|
||||
1. [flake8-quotes (Q)](#flake8-quotes-q)
|
||||
1. [flake8-return (RET)](#flake8-return-ret)
|
||||
1. [flake8-simplify (SIM)](#flake8-simplify-sim)
|
||||
@@ -106,6 +116,7 @@ of [Conda](https://docs.conda.io/en/latest/):
|
||||
1. [pandas-vet (PD)](#pandas-vet-pd)
|
||||
1. [pygrep-hooks (PGH)](#pygrep-hooks-pgh)
|
||||
1. [Pylint (PLC, PLE, PLR, PLW)](#pylint-plc-ple-plr-plw)
|
||||
1. [flake8-pie (PIE)](#flake8-pie-pie)
|
||||
1. [Ruff-specific rules (RUF)](#ruff-specific-rules-ruf)<!-- End auto-generated table of contents. -->
|
||||
1. [Editor Integrations](#editor-integrations)
|
||||
1. [FAQ](#faq)
|
||||
@@ -151,9 +162,9 @@ pacman -S ruff
|
||||
To run Ruff, try any of the following:
|
||||
|
||||
```shell
|
||||
ruff path/to/code/to/check.py
|
||||
ruff path/to/code/
|
||||
ruff path/to/code/*.py
|
||||
ruff path/to/code/to/check.py # Run Ruff over `check.py`
|
||||
ruff path/to/code/ # Run Ruff over all files in `/path/to/code` (and any subdirectories)
|
||||
ruff path/to/code/*.py # Run Ruff over all `.py` files in `/path/to/code`
|
||||
```
|
||||
|
||||
You can run Ruff in `--watch` mode to automatically re-run on-change:
|
||||
@@ -167,7 +178,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.200'
|
||||
rev: 'v0.0.210'
|
||||
hooks:
|
||||
- id: ruff
|
||||
# Respect `exclude` and `extend-exclude` settings.
|
||||
@@ -268,7 +279,7 @@ alternative docstring formats. Enabling `ALL` without further configuration may
|
||||
behavior, especially for the `pydocstyle` plugin.
|
||||
|
||||
As an alternative to `pyproject.toml`, Ruff will also respect a `ruff.toml` file, which implements
|
||||
an equivalent schema (though the `[tool.ruff]` hierarchy can be omitted). For example, the above
|
||||
an equivalent schema (though the `[tool.ruff]` hierarchy can be omitted). For example, the
|
||||
`pyproject.toml` described above would be represented via the following `ruff.toml`:
|
||||
|
||||
```toml
|
||||
@@ -298,6 +309,7 @@ ruff path/to/code/ --select F401 --select F403
|
||||
|
||||
See `ruff --help` for more:
|
||||
|
||||
<!-- Begin auto-generated cli help. -->
|
||||
```shell
|
||||
Ruff: An extremely fast Python linter.
|
||||
|
||||
@@ -328,11 +340,11 @@ Options:
|
||||
-n, --no-cache
|
||||
Disable cache reads
|
||||
--select <SELECT>
|
||||
List of error codes to enable
|
||||
Comma-separated list of error codes to enable (or ALL, to enable all checks)
|
||||
--extend-select <EXTEND_SELECT>
|
||||
Like --select, but adds additional error codes on top of the selected ones
|
||||
--ignore <IGNORE>
|
||||
List of error codes to ignore
|
||||
Comma-separated list of error codes to disable
|
||||
--extend-ignore <EXTEND_IGNORE>
|
||||
Like --ignore, but adds additional error codes on top of the ignored ones
|
||||
--exclude <EXCLUDE>
|
||||
@@ -347,6 +359,10 @@ Options:
|
||||
List of mappings from file pattern to code to exclude
|
||||
--format <FORMAT>
|
||||
Output serialization format for error messages [possible values: text, json, junit, grouped, github, gitlab]
|
||||
--stdin-filename <STDIN_FILENAME>
|
||||
The name of the file when passing it through stdin
|
||||
--cache-dir <CACHE_DIR>
|
||||
Path to the cache directory
|
||||
--show-source
|
||||
Show violations with source code
|
||||
--respect-gitignore
|
||||
@@ -355,12 +371,6 @@ Options:
|
||||
Enforce exclusions, even for paths passed to Ruff directly on the command-line
|
||||
--update-check
|
||||
Enable or disable automatic update checks
|
||||
--show-files
|
||||
See the files Ruff will be run against with the current settings
|
||||
--show-settings
|
||||
See the settings Ruff will use to check a given Python file
|
||||
--add-noqa
|
||||
Enable automatic additions of noqa directives to failing lines
|
||||
--dummy-variable-rgx <DUMMY_VARIABLE_RGX>
|
||||
Regular expression matching the name of dummy variables
|
||||
--target-version <TARGET_VERSION>
|
||||
@@ -368,18 +378,23 @@ Options:
|
||||
--line-length <LINE_LENGTH>
|
||||
Set the line-length for length-associated checks and automatic formatting
|
||||
--max-complexity <MAX_COMPLEXITY>
|
||||
Max McCabe complexity allowed for a function
|
||||
--stdin-filename <STDIN_FILENAME>
|
||||
The name of the file when passing it through stdin
|
||||
Maximum McCabe complexity allowed for a given function
|
||||
--add-noqa
|
||||
Enable automatic additions of `noqa` directives to failing lines
|
||||
--clean
|
||||
Clear any caches in the current directory or any subdirectories
|
||||
--explain <EXPLAIN>
|
||||
Explain a rule
|
||||
--cache-dir <CACHE_DIR>
|
||||
Path to the cache directory
|
||||
--show-files
|
||||
See the files Ruff will be run against with the current settings
|
||||
--show-settings
|
||||
See the settings Ruff will use to check a given Python file
|
||||
-h, --help
|
||||
Print help information
|
||||
-V, --version
|
||||
Print version information
|
||||
```
|
||||
<!-- End auto-generated cli help. -->
|
||||
|
||||
### `pyproject.toml` discovery
|
||||
|
||||
@@ -391,7 +406,7 @@ directory hierarchy is used for every individual file, with all paths in the `py
|
||||
|
||||
There are a few exceptions to these rules:
|
||||
|
||||
1. In locating the "closest" `pyproject.toml` file for a given path, Ruff ignore any
|
||||
1. In locating the "closest" `pyproject.toml` file for a given path, Ruff ignores any
|
||||
`pyproject.toml` files that lack a `[tool.ruff]` section.
|
||||
2. If a configuration file is passed directly via `--config`, those settings are used for across
|
||||
files. Any relative paths in that configuration file (like `exclude` globs or `src` paths) are
|
||||
@@ -436,7 +451,7 @@ For example, `ruff /path/to/excluded/file.py` will always check `file.py`.
|
||||
### Ignoring errors
|
||||
|
||||
To omit a lint check entirely, add it to the "ignore" list via [`ignore`](#ignore) or
|
||||
[`extend-ignore`](#extend-ignore), either on the command-line or in your `project.toml` file.
|
||||
[`extend-ignore`](#extend-ignore), either on the command-line or in your `pyproject.toml` file.
|
||||
|
||||
To ignore an error inline, Ruff uses a `noqa` system similar to [Flake8](https://flake8.pycqa.org/en/3.1.1/user/ignoring-errors.html).
|
||||
To ignore an individual error, add `# noqa: {code}` to the end of the line, like so:
|
||||
@@ -533,13 +548,13 @@ For more, see [Pyflakes](https://pypi.org/project/pyflakes/2.5.0/) on PyPI.
|
||||
| F523 | StringDotFormatExtraPositionalArguments | '...'.format(...) has unused arguments at position(s): ... | |
|
||||
| F524 | StringDotFormatMissingArguments | '...'.format(...) is missing argument(s) for placeholder(s): ... | |
|
||||
| F525 | StringDotFormatMixingAutomatic | '...'.format(...) mixes automatic and manual numbering | |
|
||||
| F541 | FStringMissingPlaceholders | f-string without any placeholders | |
|
||||
| F541 | FStringMissingPlaceholders | f-string without any placeholders | 🛠 |
|
||||
| F601 | MultiValueRepeatedKeyLiteral | Dictionary key literal repeated | |
|
||||
| F602 | MultiValueRepeatedKeyVariable | Dictionary key `...` repeated | |
|
||||
| F621 | ExpressionsInStarAssignment | Too many expressions in star-unpacking assignment | |
|
||||
| F622 | TwoStarredExpressions | Two starred expressions in assignment | |
|
||||
| F631 | AssertTuple | Assert test is a non-empty tuple, which is always `True` | |
|
||||
| F632 | IsLiteral | Use `==` and `!=` to compare constant literals | 🛠 |
|
||||
| F632 | IsLiteral | Use `==` to compare constant literals | 🛠 |
|
||||
| F633 | InvalidPrintSyntax | Use of `>>` is invalid with `print` function | |
|
||||
| F634 | IfTuple | If test is a tuple, which is always `True` | |
|
||||
| F701 | BreakOutsideLoop | `break` outside loop | |
|
||||
@@ -552,7 +567,6 @@ For more, see [Pyflakes](https://pypi.org/project/pyflakes/2.5.0/) on PyPI.
|
||||
| F821 | UndefinedName | Undefined name `...` | |
|
||||
| F822 | UndefinedExport | Undefined name `...` in `__all__` | |
|
||||
| F823 | UndefinedLocal | Local variable `...` referenced before assignment | |
|
||||
| F831 | DuplicateArgumentName | Duplicate argument name in function definition | |
|
||||
| F841 | UnusedVariable | Local variable `...` is assigned to but never used | |
|
||||
| F842 | UnusedAnnotation | Local variable `...` is annotated but never used | |
|
||||
| F901 | RaiseNotImplemented | `raise NotImplemented` should be `raise NotImplementedError` | 🛠 |
|
||||
@@ -572,7 +586,7 @@ For more, see [pycodestyle](https://pypi.org/project/pycodestyle/2.9.1/) on PyPI
|
||||
| E714 | NotIsTest | Test for object identity should be `is not` | 🛠 |
|
||||
| E721 | TypeComparison | Do not compare types, use `isinstance()` | |
|
||||
| E722 | DoNotUseBareExcept | Do not use bare `except` | |
|
||||
| E731 | DoNotAssignLambda | Do not assign a lambda expression, use a def | 🛠 |
|
||||
| E731 | DoNotAssignLambda | Do not assign a `lambda` expression, use a `def` | 🛠 |
|
||||
| E741 | AmbiguousVariableName | Ambiguous variable name: `...` | |
|
||||
| E742 | AmbiguousClassName | Ambiguous class name: `...` | |
|
||||
| E743 | AmbiguousFunctionName | Ambiguous function name: `...` | |
|
||||
@@ -657,7 +671,7 @@ For more, see [pyupgrade](https://pypi.org/project/pyupgrade/3.2.0/) on PyPI.
|
||||
| ---- | ---- | ------- | --- |
|
||||
| UP001 | UselessMetaclassType | `__metaclass__ = type` is implied | 🛠 |
|
||||
| UP003 | TypeOfPrimitive | Use `str` instead of `type(...)` | 🛠 |
|
||||
| UP004 | UselessObjectInheritance | Class `...` inherits from object | 🛠 |
|
||||
| UP004 | UselessObjectInheritance | Class `...` inherits from `object` | 🛠 |
|
||||
| UP005 | DeprecatedUnittestAlias | `assertEquals` is deprecated, use `assertEqual` | 🛠 |
|
||||
| UP006 | UsePEP585Annotation | Use `list` instead of `List` for type annotations | 🛠 |
|
||||
| UP007 | UsePEP604Annotation | Use `X \| Y` for type annotations | 🛠 |
|
||||
@@ -671,12 +685,17 @@ For more, see [pyupgrade](https://pypi.org/project/pyupgrade/3.2.0/) on PyPI.
|
||||
| UP015 | RedundantOpenModes | Unnecessary open mode parameters | 🛠 |
|
||||
| UP016 | RemoveSixCompat | Unnecessary `six` compatibility usage | 🛠 |
|
||||
| UP017 | DatetimeTimezoneUTC | Use `datetime.UTC` alias | 🛠 |
|
||||
| UP018 | NativeLiterals | Unnecessary call to `str` and `bytes` | 🛠 |
|
||||
| UP018 | NativeLiterals | Unnecessary call to `str` | 🛠 |
|
||||
| UP019 | TypingTextStrAlias | `typing.Text` is deprecated, use `str` | 🛠 |
|
||||
| UP020 | OpenAlias | Use builtin `open` | 🛠 |
|
||||
| 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` | 🛠 |
|
||||
| UP027 | RewriteListComprehension | Replace unpacked list comprehension with a generator expression | 🛠 |
|
||||
| UP028 | RewriteYieldFrom | Replace `yield` over `for` loop with `yield from` | 🛠 |
|
||||
|
||||
### pep8-naming (N)
|
||||
|
||||
@@ -852,6 +871,16 @@ For more, see [flake8-errmsg](https://pypi.org/project/flake8-errmsg/0.4.0/) on
|
||||
| EM102 | FStringInException | Exception must not use an f-string literal, assign to variable first | |
|
||||
| EM103 | DotFormatInException | Exception must not use a `.format()` string directly, assign to variable first | |
|
||||
|
||||
### flake8-implicit-str-concat (ISC)
|
||||
|
||||
For more, see [flake8-implicit-str-concat](https://pypi.org/project/flake8-implicit-str-concat/0.3.0/) on PyPI.
|
||||
|
||||
| Code | Name | Message | Fix |
|
||||
| ---- | ---- | ------- | --- |
|
||||
| ISC001 | SingleLineImplicitStringConcatenation | Implicitly concatenated string literals on one line | |
|
||||
| ISC002 | MultiLineImplicitStringConcatenation | Implicitly concatenated string literals over continuation line | |
|
||||
| ISC003 | ExplicitStringConcatenation | Explicitly concatenated string should be implicitly concatenated | |
|
||||
|
||||
### flake8-import-conventions (ICN)
|
||||
|
||||
| Code | Name | Message | Fix |
|
||||
@@ -867,6 +896,38 @@ For more, see [flake8-print](https://pypi.org/project/flake8-print/5.0.0/) on Py
|
||||
| T201 | PrintFound | `print` found | 🛠 |
|
||||
| T203 | PPrintFound | `pprint` found | 🛠 |
|
||||
|
||||
### flake8-pytest-style (PT)
|
||||
|
||||
For more, see [flake8-pytest-style](https://pypi.org/project/flake8-pytest-style/1.6.0/) on PyPI.
|
||||
|
||||
| Code | Name | Message | Fix |
|
||||
| ---- | ---- | ------- | --- |
|
||||
| PT001 | IncorrectFixtureParenthesesStyle | Use `@pytest.fixture()` over `@pytest.fixture` | 🛠 |
|
||||
| PT002 | FixturePositionalArgs | Configuration for fixture `...` specified via positional args, use kwargs | |
|
||||
| PT003 | ExtraneousScopeFunction | `scope='function'` is implied in `@pytest.fixture()` | |
|
||||
| PT004 | MissingFixtureNameUnderscore | Fixture `...` does not return anything, add leading underscore | |
|
||||
| PT005 | IncorrectFixtureNameUnderscore | Fixture `...` returns a value, remove leading underscore | |
|
||||
| PT006 | ParametrizeNamesWrongType | Wrong name(s) type in `@pytest.mark.parametrize`, expected `tuple` | 🛠 |
|
||||
| PT007 | ParametrizeValuesWrongType | Wrong values type in `@pytest.mark.parametrize` expected `list` of `tuple` | |
|
||||
| PT008 | PatchWithLambda | Use `return_value=` instead of patching with lambda | |
|
||||
| PT009 | UnittestAssertion | Use a regular assert instead of unittest-style '...' | |
|
||||
| PT010 | RaisesWithoutException | set the expected exception in `pytest.raises()` | |
|
||||
| PT011 | RaisesTooBroad | `pytest.raises(...)` is too broad, set the `match` parameter or use a more specific exception | |
|
||||
| PT012 | RaisesWithMultipleStatements | `pytest.raises()` block should contain a single simple statement | |
|
||||
| PT013 | IncorrectPytestImport | Found incorrect import of pytest, use simple `import pytest` instead | |
|
||||
| PT015 | AssertAlwaysFalse | Assertion always fails, replace with `pytest.fail()` | |
|
||||
| PT016 | FailWithoutMessage | No message passed to `pytest.fail()` | |
|
||||
| PT017 | AssertInExcept | Found assertion on exception ... in except block, use pytest.raises() instead | |
|
||||
| PT018 | CompositeAssertion | Assertion should be broken down into multiple parts | |
|
||||
| PT019 | FixtureParamWithoutValue | Fixture ... without value is injected as parameter, use @pytest.mark.usefixtures instead | |
|
||||
| PT020 | DeprecatedYieldFixture | `@pytest.yield_fixture` is deprecated, use `@pytest.fixture` | |
|
||||
| PT021 | FixtureFinalizerCallback | Use `yield` instead of `request.addfinalizer` | |
|
||||
| PT022 | UselessYieldFixture | No teardown in fixture ..., use `return` instead of `yield` | 🛠 |
|
||||
| PT023 | IncorrectMarkParenthesesStyle | Use `@pytest.mark....` over `@pytest.mark....()` | 🛠 |
|
||||
| PT024 | UnnecessaryAsyncioMarkOnFixture | `pytest.mark.asyncio` is unnecessary for fixtures | |
|
||||
| PT025 | ErroneousUseFixturesOnFixture | `pytest.mark.usefixtures` has no effect on fixtures | |
|
||||
| PT026 | UseFixturesWithoutParameters | Useless `pytest.mark.usefixtures` without parameters | 🛠 |
|
||||
|
||||
### flake8-quotes (Q)
|
||||
|
||||
For more, see [flake8-quotes](https://pypi.org/project/flake8-quotes/3.3.1/) on PyPI.
|
||||
@@ -900,6 +961,9 @@ For more, see [flake8-simplify](https://pypi.org/project/flake8-simplify/0.19.3/
|
||||
| Code | Name | Message | Fix |
|
||||
| ---- | ---- | ------- | --- |
|
||||
| SIM118 | KeyInDict | Use `key in dict` instead of `key in dict.keys()` | 🛠 |
|
||||
| SIM222 | OrTrue | Use `True` instead of `... or True` | 🛠 |
|
||||
| SIM223 | AndFalse | Use `False` instead of `... and False` | 🛠 |
|
||||
| SIM300 | YodaConditions | Use `left == right` instead of `right == left (Yoda-conditions)` | 🛠 |
|
||||
|
||||
### flake8-tidy-imports (TID)
|
||||
|
||||
@@ -907,6 +971,7 @@ For more, see [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports
|
||||
|
||||
| Code | Name | Message | Fix |
|
||||
| ---- | ---- | ------- | --- |
|
||||
| TID251 | BannedApi | `...` is banned: ... | |
|
||||
| TID252 | BannedRelativeImport | Relative imports are banned | |
|
||||
|
||||
### flake8-unused-arguments (ARG)
|
||||
@@ -994,13 +1059,23 @@ For more, see [Pylint](https://pypi.org/project/pylint/2.15.7/) on PyPI.
|
||||
| PLW0120 | UselessElseOnLoop | Else clause on loop without a break statement, remove the else and de-indent all the code inside it | |
|
||||
| PLW0602 | GlobalVariableNotAssigned | Using global for `...` but no assignment is done | |
|
||||
|
||||
### flake8-pie (PIE)
|
||||
|
||||
For more, see [flake8-pie](https://pypi.org/project/flake8-pie/0.16.0/) on PyPI.
|
||||
|
||||
| Code | Name | Message | Fix |
|
||||
| ---- | ---- | ------- | --- |
|
||||
| PIE790 | NoUnnecessaryPass | Unnecessary `pass` statement | 🛠 |
|
||||
| PIE794 | DupeClassFieldDefinitions | Class field `...` is defined multiple times | 🛠 |
|
||||
| PIE807 | PreferListBuiltin | Prefer `list()` over useless lambda | 🛠 |
|
||||
|
||||
### Ruff-specific rules (RUF)
|
||||
|
||||
| Code | Name | Message | Fix |
|
||||
| ---- | ---- | ------- | --- |
|
||||
| RUF001 | AmbiguousUnicodeCharacterString | String contains ambiguous unicode character '𝐁' (did you mean 'B'?) | 🛠 |
|
||||
| RUF002 | AmbiguousUnicodeCharacterDocstring | Docstring contains ambiguous unicode character '𝐁' (did you mean 'B'?) | 🛠 |
|
||||
| RUF003 | AmbiguousUnicodeCharacterComment | Comment contains ambiguous unicode character '𝐁' (did you mean 'B'?) | |
|
||||
| RUF003 | AmbiguousUnicodeCharacterComment | Comment contains ambiguous unicode character '𝐁' (did you mean 'B'?) | 🛠 |
|
||||
| RUF004 | KeywordArgumentBeforeStarArgument | Keyword argument `...` must come after starred arguments | |
|
||||
| RUF100 | UnusedNOQA | Unused blanket `noqa` directive | 🛠 |
|
||||
|
||||
@@ -1271,10 +1346,13 @@ natively, including:
|
||||
- [`flake8-docstrings`](https://pypi.org/project/flake8-docstrings/)
|
||||
- [`flake8-eradicate`](https://pypi.org/project/flake8-eradicate/)
|
||||
- [`flake8-errmsg`](https://pypi.org/project/flake8-errmsg/)
|
||||
- [`flake8-implicit-str-concat`](https://pypi.org/project/flake8-implicit-str-concat/)
|
||||
- [`flake8-import-conventions`](https://github.com/joaopalmeiro/flake8-import-conventions)
|
||||
- [`flake8-pie`](https://pypi.org/project/flake8-pie/) (3/7)
|
||||
- [`flake8-print`](https://pypi.org/project/flake8-print/)
|
||||
- [`flake8-quotes`](https://pypi.org/project/flake8-quotes/)
|
||||
- [`flake8-return`](https://pypi.org/project/flake8-return/)
|
||||
- [`flake8-simplify`](https://pypi.org/project/flake8-simplify/) (4/37)
|
||||
- [`flake8-super`](https://pypi.org/project/flake8-super/)
|
||||
- [`flake8-tidy-imports`](https://pypi.org/project/flake8-tidy-imports/) (1/3)
|
||||
- [`isort`](https://pypi.org/project/isort/)
|
||||
@@ -1282,7 +1360,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
|
||||
@@ -1326,10 +1404,13 @@ Today, Ruff can be used to replace Flake8 when used with any of the following pl
|
||||
- [`flake8-docstrings`](https://pypi.org/project/flake8-docstrings/)
|
||||
- [`flake8-eradicate`](https://pypi.org/project/flake8-eradicate/)
|
||||
- [`flake8-errmsg`](https://pypi.org/project/flake8-errmsg/)
|
||||
- [`flake8-implicit-str-concat`](https://pypi.org/project/flake8-implicit-str-concat/)
|
||||
- [`flake8-import-conventions`](https://github.com/joaopalmeiro/flake8-import-conventions)
|
||||
- [`flake8-pie`](https://pypi.org/project/flake8-pie/) (3/7)
|
||||
- [`flake8-print`](https://pypi.org/project/flake8-print/)
|
||||
- [`flake8-quotes`](https://pypi.org/project/flake8-quotes/)
|
||||
- [`flake8-return`](https://pypi.org/project/flake8-return/)
|
||||
- [`flake8-simplify`](https://pypi.org/project/flake8-simplify/) (4/37)
|
||||
- [`flake8-super`](https://pypi.org/project/flake8-super/)
|
||||
- [`flake8-tidy-imports`](https://pypi.org/project/flake8-tidy-imports/) (1/3)
|
||||
- [`mccabe`](https://pypi.org/project/mccabe/)
|
||||
@@ -1339,9 +1420,9 @@ 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.
|
||||
If you're looking to use Ruff, but rely on an unsupported Flake8 plugin, feel free to file an Issue.
|
||||
|
||||
### Do I need to install Rust to use Ruff?
|
||||
|
||||
@@ -1404,85 +1485,35 @@ Found 3 error(s).
|
||||
|
||||
### Does Ruff support NumPy- or Google-style docstrings?
|
||||
|
||||
Yes! To enable a specific docstring convention, start by enabling all `pydocstyle` error codes, and
|
||||
then selectively disabling based on your [preferred convention](https://www.pydocstyle.org/en/latest/error_codes.html#default-conventions).
|
||||
Yes! To enable specific docstring convention, add the following to your `pyproject.toml`:
|
||||
|
||||
For example, if you're coming from `flake8-docstrings`, the following configuration is equivalent to
|
||||
`--docstring-convention=numpy`:
|
||||
```toml
|
||||
[tool.ruff.pydocstyle]
|
||||
convention = "google" # Accepts: "google", "numpy", or "pep257".
|
||||
```
|
||||
|
||||
For example, if you're coming from `flake8-docstrings`, and your originating configuration uses
|
||||
`--docstring-convention=numpy`, you'd instead set `convention = "numpy"` in your `pyproject.toml`,
|
||||
as above.
|
||||
|
||||
Alongside `convention`, you'll want to explicitly enable the `D` error code class, like so:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
extend-select = ["D"]
|
||||
extend-ignore = [
|
||||
"D107",
|
||||
"D203",
|
||||
"D212",
|
||||
"D213",
|
||||
"D402",
|
||||
"D413",
|
||||
"D415",
|
||||
"D416",
|
||||
"D417",
|
||||
select = [
|
||||
"D",
|
||||
]
|
||||
```
|
||||
|
||||
Similarly, the following is equivalent to `--docstring-convention=google`:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
extend-select = ["D"]
|
||||
extend-ignore = [
|
||||
"D203",
|
||||
"D204",
|
||||
"D213",
|
||||
"D215",
|
||||
"D400",
|
||||
"D404",
|
||||
"D406",
|
||||
"D407",
|
||||
"D408",
|
||||
"D409",
|
||||
"D413",
|
||||
]
|
||||
```
|
||||
|
||||
Similarly, the following is equivalent to `--docstring-convention=pep8`:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
extend-select = ["D"]
|
||||
extend-ignore = [
|
||||
"D203",
|
||||
"D212",
|
||||
"D213",
|
||||
"D214",
|
||||
"D215",
|
||||
"D404",
|
||||
"D405",
|
||||
"D406",
|
||||
"D407",
|
||||
"D408",
|
||||
"D409",
|
||||
"D410",
|
||||
"D411",
|
||||
"D413",
|
||||
"D415",
|
||||
"D416",
|
||||
"D417",
|
||||
]
|
||||
```
|
||||
|
||||
Note that Ruff _also_ supports a [`convention`](#convention) setting:
|
||||
|
||||
```toml
|
||||
[tool.ruff.pydocstyle]
|
||||
convention = "google"
|
||||
```
|
||||
|
||||
However, this setting is purely used to implement robust detection of Google and NumPy-style
|
||||
sections, and thus avoid the [false negatives](https://github.com/PyCQA/pydocstyle/issues/459) seen
|
||||
in `pydocstyle`; it does not affect which errors are enabled, which is driven by the `select` and
|
||||
`ignore` settings, as described above.
|
||||
Setting a `convention` force-disables any rules that are incompatible with that convention, no
|
||||
matter how they're provided, which avoids accidental incompatibilities and simplifies configuration.
|
||||
|
||||
### How can I tell what settings Ruff is using to check my code?
|
||||
|
||||
Run `ruff /path/to/code.py --show-settings` to view the resolved settings for a given file.
|
||||
|
||||
## Development
|
||||
|
||||
@@ -1651,7 +1682,6 @@ Summary
|
||||
|
||||
<!-- Sections automatically generated by `cargo dev generate-options`. -->
|
||||
<!-- Begin auto-generated options sections. -->
|
||||
|
||||
#### [`allowed-confusables`](#allowed-confusables)
|
||||
|
||||
A list of allowed "confusable" Unicode characters to ignore when
|
||||
@@ -2380,6 +2410,157 @@ will be added to the `aliases` mapping.
|
||||
|
||||
---
|
||||
|
||||
### `flake8-pytest-style`
|
||||
|
||||
#### [`fixture-parentheses`](#fixture-parentheses)
|
||||
|
||||
Boolean flag specifying whether `@pytest.fixture()` without parameters
|
||||
should have parentheses. If the option is set to `true` (the
|
||||
default), `@pytest.fixture()` is valid and `@pytest.fixture` is an
|
||||
error. If set to `false`, `@pytest.fixture` is valid and
|
||||
`@pytest.fixture()` is an error.
|
||||
|
||||
**Default value**: `true`
|
||||
|
||||
**Type**: `bool`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff.flake8-pytest-style]
|
||||
fixture-parentheses = true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`mark-parentheses`](#mark-parentheses)
|
||||
|
||||
Boolean flag specifying whether `@pytest.mark.foo()` without parameters
|
||||
should have parentheses. If the option is set to `true` (the
|
||||
default), `@pytest.mark.foo()` is valid and `@pytest.mark.foo` is an
|
||||
error. If set to `false`, `@pytest.fixture` is valid and
|
||||
`@pytest.mark.foo()` is an error.
|
||||
|
||||
**Default value**: `true`
|
||||
|
||||
**Type**: `bool`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff.flake8-pytest-style]
|
||||
mark-parentheses = true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`parametrize-names-type`](#parametrize-names-type)
|
||||
|
||||
Expected type for multiple argument names in `@pytest.mark.parametrize`.
|
||||
The following values are supported:
|
||||
* `csv` — a comma-separated list, e.g.
|
||||
`@pytest.mark.parametrize('name1,name2', ...)`
|
||||
* `tuple` (default) — e.g. `@pytest.mark.parametrize(('name1', 'name2'),
|
||||
...)`
|
||||
* `list` — e.g. `@pytest.mark.parametrize(['name1', 'name2'], ...)`
|
||||
|
||||
**Default value**: `tuple`
|
||||
|
||||
**Type**: `ParametrizeNameType`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff.flake8-pytest-style]
|
||||
parametrize-names-type = "list"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`parametrize-values-row-type`](#parametrize-values-row-type)
|
||||
|
||||
Expected type for each row of values in `@pytest.mark.parametrize` in
|
||||
case of multiple parameters. The following values are supported:
|
||||
* `tuple` (default) — e.g. `@pytest.mark.parametrize(('name1', 'name2'),
|
||||
[(1, 2), (3, 4)])`
|
||||
* `list` — e.g. `@pytest.mark.parametrize(('name1', 'name2'), [[1, 2],
|
||||
[3, 4]])`
|
||||
|
||||
**Default value**: `tuple`
|
||||
|
||||
**Type**: `ParametrizeValuesRowType`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff.flake8-pytest-style]
|
||||
parametrize-values-row-type = "list"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`parametrize-values-type`](#parametrize-values-type)
|
||||
|
||||
Expected type for the list of values rows in `@pytest.mark.parametrize`.
|
||||
The following values are supported:
|
||||
* `tuple` — e.g. `@pytest.mark.parametrize('name', (1, 2, 3))`
|
||||
* `list` (default) — e.g. `@pytest.mark.parametrize('name', [1, 2, 3])`
|
||||
|
||||
**Default value**: `list`
|
||||
|
||||
**Type**: `ParametrizeValuesType`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff.flake8-pytest-style]
|
||||
parametrize-values-type = "tuple"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`raises-extend-require-match-for`](#raises-extend-require-match-for)
|
||||
|
||||
List of additional exception names that require a match= parameter in a
|
||||
`pytest.raises()` call. This extends the default list of exceptions
|
||||
that require a match= parameter.
|
||||
This option is useful if you want to extend the default list of
|
||||
exceptions that require a match= parameter without having to specify
|
||||
the entire list.
|
||||
Note that this option does not remove any exceptions from the default
|
||||
list.
|
||||
|
||||
**Default value**: `[]`
|
||||
|
||||
**Type**: `Vec<String>`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff.flake8-pytest-style]
|
||||
raises-extend-require-match-for = ["requests.RequestException"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`raises-require-match-for`](#raises-require-match-for)
|
||||
|
||||
List of exception names that require a match= parameter in a
|
||||
`pytest.raises()` call.
|
||||
|
||||
**Default value**: `["BaseException", "Exception", "ValueError", "OSError", "IOError", "EnvironmentError", "socket.error"]`
|
||||
|
||||
**Type**: `Vec<String>`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff.flake8-pytest-style]
|
||||
raises-require-match-for = ["requests.RequestException"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `flake8-quotes`
|
||||
|
||||
#### [`avoid-escape`](#avoid-escape)
|
||||
@@ -2477,6 +2658,27 @@ ban-relative-imports = "all"
|
||||
|
||||
---
|
||||
|
||||
#### [`banned-api`](#banned-api)
|
||||
|
||||
Specific modules or module members that may not be imported or accessed.
|
||||
Note that this check is only meant to flag accidental uses,
|
||||
and can be circumvented via `eval` or `importlib`.
|
||||
|
||||
**Default value**: `{}`
|
||||
|
||||
**Type**: `HashMap<String, BannedApi>`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff.flake8-tidy-imports]
|
||||
[tool.ruff.flake8-tidy-imports.banned-api]
|
||||
"cgi".msg = "The cgi module is deprecated, see https://peps.python.org/pep-0594/#cgi."
|
||||
"typing.TypedDict".msg = "Use typing_extensions.TypedDict instead."
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `flake8-unused-arguments`
|
||||
|
||||
#### [`ignore-variadic-names`](#ignore-variadic-names)
|
||||
@@ -2620,6 +2822,24 @@ known-third-party = ["src"]
|
||||
|
||||
---
|
||||
|
||||
#### [`order-by-type`](#order-by-type)
|
||||
|
||||
Order imports by type, which is determined by case, in addition to
|
||||
alphabetically.
|
||||
|
||||
**Default value**: `true`
|
||||
|
||||
**Type**: `bool`
|
||||
|
||||
**Example usage**:
|
||||
|
||||
```toml
|
||||
[tool.ruff.isort]
|
||||
order-by-type = true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### [`single-line-exclusions`](#single-line-exclusions)
|
||||
|
||||
One or more modules to exclude from the single line rule.
|
||||
@@ -2742,9 +2962,8 @@ staticmethod-decorators = ["staticmethod", "stcmthd"]
|
||||
|
||||
#### [`convention`](#convention)
|
||||
|
||||
Whether to use Google-style or Numpy-style conventions when detecting
|
||||
docstring sections. By default, conventions will be inferred from
|
||||
the available sections.
|
||||
Whether to use Google-style or NumPy-style conventions or the PEP257
|
||||
defaults when analyzing docstring sections.
|
||||
|
||||
**Default value**: `None`
|
||||
|
||||
|
||||
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.200"
|
||||
version = "0.0.210"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -1975,7 +1975,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.200"
|
||||
version = "0.0.210"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bincode",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.200-dev.0"
|
||||
version = "0.0.210-dev.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
|
||||
43
flake8_to_ruff/examples/manim.ini
Normal file
43
flake8_to_ruff/examples/manim.ini
Normal file
@@ -0,0 +1,43 @@
|
||||
[flake8]
|
||||
# Exclude the grpc generated code
|
||||
exclude = ./manim/grpc/gen/*
|
||||
max-complexity = 15
|
||||
max-line-length = 88
|
||||
statistics = True
|
||||
# Prevents some flake8-rst-docstrings errors
|
||||
rst-roles = attr,class,func,meth,mod,obj,ref,doc,exc
|
||||
rst-directives = manim, SEEALSO, seealso
|
||||
docstring-convention=numpy
|
||||
|
||||
select = A,A00,B,B9,C4,C90,D,E,F,F,PT,RST,SIM,W
|
||||
|
||||
# General Compatibility
|
||||
extend-ignore = E203, W503, D202, D212, D213, D404
|
||||
|
||||
# Misc
|
||||
F401, F403, F405, F841, E501, E731, E402, F811, F821,
|
||||
|
||||
# Plug-in: flake8-builtins
|
||||
A001, A002, A003,
|
||||
|
||||
# Plug-in: flake8-bugbear
|
||||
B006, B007, B008, B009, B010, B903, B950,
|
||||
|
||||
# Plug-in: flake8-simplify
|
||||
SIM105, SIM106, SIM119,
|
||||
|
||||
# Plug-in: flake8-comprehensions
|
||||
C901
|
||||
|
||||
# Plug-in: flake8-pytest-style
|
||||
PT001, PT004, PT006, PT011, PT018, PT022, PT023,
|
||||
|
||||
# Plug-in: flake8-docstrings
|
||||
D100, D101, D102, D103, D104, D105, D106, D107,
|
||||
D200, D202, D204, D205, D209,
|
||||
D301,
|
||||
D400, D401, D402, D403, D405, D406, D407, D409, D411, D412, D414,
|
||||
|
||||
# Plug-in: flake8-rst-docstrings
|
||||
RST201, RST203, RST210, RST212, RST213, RST215,
|
||||
RST301, RST303,
|
||||
@@ -1,15 +1,18 @@
|
||||
use std::collections::{BTreeSet, HashMap};
|
||||
|
||||
use anyhow::Result;
|
||||
use ruff::checks_gen::CheckCodePrefix;
|
||||
use ruff::flake8_pytest_style::types::{
|
||||
ParametrizeNameType, ParametrizeValuesRowType, ParametrizeValuesType,
|
||||
};
|
||||
use ruff::flake8_quotes::settings::Quote;
|
||||
use ruff::flake8_tidy_imports::settings::Strictness;
|
||||
use ruff::pydocstyle::settings::Convention;
|
||||
use ruff::registry_gen::CheckCodePrefix;
|
||||
use ruff::settings::options::Options;
|
||||
use ruff::settings::pyproject::Pyproject;
|
||||
use ruff::{
|
||||
flake8_annotations, flake8_bugbear, flake8_errmsg, flake8_quotes, flake8_tidy_imports, mccabe,
|
||||
pep8_naming, pydocstyle,
|
||||
flake8_annotations, flake8_bugbear, flake8_errmsg, flake8_pytest_style, flake8_quotes,
|
||||
flake8_tidy_imports, mccabe, pep8_naming, pydocstyle,
|
||||
};
|
||||
|
||||
use crate::black::Black;
|
||||
@@ -49,6 +52,19 @@ pub fn convert(
|
||||
}
|
||||
}
|
||||
|
||||
// Infer plugins, if not provided.
|
||||
let plugins = plugins.unwrap_or_else(|| {
|
||||
let from_options = plugin::infer_plugins_from_options(flake8);
|
||||
if !from_options.is_empty() {
|
||||
eprintln!("Inferred plugins from settings: {from_options:#?}");
|
||||
}
|
||||
let from_codes = plugin::infer_plugins_from_codes(&referenced_codes);
|
||||
if !from_codes.is_empty() {
|
||||
eprintln!("Inferred plugins from referenced check codes: {from_codes:#?}");
|
||||
}
|
||||
from_options.into_iter().chain(from_codes).collect()
|
||||
});
|
||||
|
||||
// Check if the user has specified a `select`. If not, we'll add our own
|
||||
// default `select`, and populate it based on user plugins.
|
||||
let mut select = flake8
|
||||
@@ -58,22 +74,7 @@ pub fn convert(
|
||||
.as_ref()
|
||||
.map(|value| BTreeSet::from_iter(parser::parse_prefix_codes(value)))
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
plugin::resolve_select(
|
||||
flake8,
|
||||
&plugins.unwrap_or_else(|| {
|
||||
let from_options = plugin::infer_plugins_from_options(flake8);
|
||||
if !from_options.is_empty() {
|
||||
eprintln!("Inferred plugins from settings: {from_options:#?}");
|
||||
}
|
||||
let from_codes = plugin::infer_plugins_from_codes(&referenced_codes);
|
||||
if !from_codes.is_empty() {
|
||||
eprintln!("Inferred plugins from referenced check codes: {from_codes:#?}");
|
||||
}
|
||||
from_options.into_iter().chain(from_codes).collect()
|
||||
}),
|
||||
)
|
||||
});
|
||||
.unwrap_or_else(|| plugin::resolve_select(&plugins));
|
||||
let mut ignore = flake8
|
||||
.get("ignore")
|
||||
.and_then(|value| {
|
||||
@@ -88,6 +89,7 @@ pub fn convert(
|
||||
let mut flake8_annotations = flake8_annotations::settings::Options::default();
|
||||
let mut flake8_bugbear = flake8_bugbear::settings::Options::default();
|
||||
let mut flake8_errmsg = flake8_errmsg::settings::Options::default();
|
||||
let mut flake8_pytest_style = flake8_pytest_style::settings::Options::default();
|
||||
let mut flake8_quotes = flake8_quotes::settings::Options::default();
|
||||
let mut flake8_tidy_imports = flake8_tidy_imports::settings::Options::default();
|
||||
let mut mccabe = mccabe::settings::Options::default();
|
||||
@@ -164,17 +166,17 @@ pub fn convert(
|
||||
// flake8-quotes
|
||||
"quotes" | "inline-quotes" | "inline_quotes" => match value.trim() {
|
||||
"'" | "single" => flake8_quotes.inline_quotes = Some(Quote::Single),
|
||||
"\"" | "double" => flake8_quotes.inline_quotes = Some(Quote::Single),
|
||||
"\"" | "double" => flake8_quotes.inline_quotes = Some(Quote::Double),
|
||||
_ => eprintln!("Unexpected '{key}' value: {value}"),
|
||||
},
|
||||
"multiline-quotes" | "multiline_quotes" => match value.trim() {
|
||||
"'" | "single" => flake8_quotes.multiline_quotes = Some(Quote::Single),
|
||||
"\"" | "double" => flake8_quotes.multiline_quotes = Some(Quote::Single),
|
||||
"\"" | "double" => flake8_quotes.multiline_quotes = Some(Quote::Double),
|
||||
_ => eprintln!("Unexpected '{key}' value: {value}"),
|
||||
},
|
||||
"docstring-quotes" | "docstring_quotes" => match value.trim() {
|
||||
"'" | "single" => flake8_quotes.docstring_quotes = Some(Quote::Single),
|
||||
"\"" | "double" => flake8_quotes.docstring_quotes = Some(Quote::Single),
|
||||
"\"" | "double" => flake8_quotes.docstring_quotes = Some(Quote::Double),
|
||||
_ => eprintln!("Unexpected '{key}' value: {value}"),
|
||||
},
|
||||
"avoid-escape" | "avoid_escape" => match parser::parse_bool(value.as_ref()) {
|
||||
@@ -205,7 +207,8 @@ pub fn convert(
|
||||
"docstring-convention" => match value.trim() {
|
||||
"google" => pydocstyle.convention = Some(Convention::Google),
|
||||
"numpy" => pydocstyle.convention = Some(Convention::Numpy),
|
||||
"pep257" | "all" => pydocstyle.convention = None,
|
||||
"pep257" => pydocstyle.convention = Some(Convention::Pep257),
|
||||
"all" => pydocstyle.convention = None,
|
||||
_ => eprintln!("Unexpected '{key}' value: {value}"),
|
||||
},
|
||||
// mccabe
|
||||
@@ -222,6 +225,66 @@ pub fn convert(
|
||||
Err(e) => eprintln!("Unable to parse '{key}' property: {e}"),
|
||||
}
|
||||
}
|
||||
// flake8-pytest-style
|
||||
"pytest-fixture-no-parentheses" | "pytest_fixture_no_parentheses " => {
|
||||
match parser::parse_bool(value.as_ref()) {
|
||||
Ok(bool) => flake8_pytest_style.fixture_parentheses = Some(!bool),
|
||||
Err(e) => eprintln!("Unable to parse '{key}' property: {e}"),
|
||||
}
|
||||
}
|
||||
"pytest-parametrize-names-type" | "pytest_parametrize_names_type" => {
|
||||
match value.trim() {
|
||||
"csv" => {
|
||||
flake8_pytest_style.parametrize_names_type =
|
||||
Some(ParametrizeNameType::CSV);
|
||||
}
|
||||
"tuple" => {
|
||||
flake8_pytest_style.parametrize_names_type =
|
||||
Some(ParametrizeNameType::Tuple);
|
||||
}
|
||||
"list" => {
|
||||
flake8_pytest_style.parametrize_names_type =
|
||||
Some(ParametrizeNameType::List);
|
||||
}
|
||||
_ => eprintln!("Unexpected '{key}' value: {value}"),
|
||||
}
|
||||
}
|
||||
"pytest-parametrize-values-type" | "pytest_parametrize_values_type" => {
|
||||
match value.trim() {
|
||||
"tuple" => {
|
||||
flake8_pytest_style.parametrize_values_type =
|
||||
Some(ParametrizeValuesType::Tuple);
|
||||
}
|
||||
"list" => {
|
||||
flake8_pytest_style.parametrize_values_type =
|
||||
Some(ParametrizeValuesType::List);
|
||||
}
|
||||
_ => eprintln!("Unexpected '{key}' value: {value}"),
|
||||
}
|
||||
}
|
||||
"pytest-parametrize-values-row-type" | "pytest_parametrize_values_row_type" => {
|
||||
match value.trim() {
|
||||
"tuple" => {
|
||||
flake8_pytest_style.parametrize_values_row_type =
|
||||
Some(ParametrizeValuesRowType::Tuple);
|
||||
}
|
||||
"list" => {
|
||||
flake8_pytest_style.parametrize_values_row_type =
|
||||
Some(ParametrizeValuesRowType::List);
|
||||
}
|
||||
_ => eprintln!("Unexpected '{key}' value: {value}"),
|
||||
}
|
||||
}
|
||||
"pytest-raises-require-match-for" | "pytest_raises_require_match_for" => {
|
||||
flake8_pytest_style.raises_require_match_for =
|
||||
Some(parser::parse_strings(value.as_ref()));
|
||||
}
|
||||
"pytest-mark-no-parentheses" | "pytest_mark_no_parentheses" => {
|
||||
match parser::parse_bool(value.as_ref()) {
|
||||
Ok(bool) => flake8_pytest_style.mark_parentheses = Some(!bool),
|
||||
Err(e) => eprintln!("Unable to parse '{key}' property: {e}"),
|
||||
}
|
||||
}
|
||||
// Unknown
|
||||
_ => eprintln!("Skipping unsupported property: {key}"),
|
||||
}
|
||||
@@ -240,6 +303,9 @@ pub fn convert(
|
||||
if flake8_errmsg != flake8_errmsg::settings::Options::default() {
|
||||
options.flake8_errmsg = Some(flake8_errmsg);
|
||||
}
|
||||
if flake8_pytest_style != flake8_pytest_style::settings::Options::default() {
|
||||
options.flake8_pytest_style = Some(flake8_pytest_style);
|
||||
}
|
||||
if flake8_quotes != flake8_quotes::settings::Options::default() {
|
||||
options.flake8_quotes = Some(flake8_quotes);
|
||||
}
|
||||
@@ -278,8 +344,8 @@ mod tests {
|
||||
use std::collections::HashMap;
|
||||
|
||||
use anyhow::Result;
|
||||
use ruff::checks_gen::CheckCodePrefix;
|
||||
use ruff::pydocstyle::settings::Convention;
|
||||
use ruff::registry_gen::CheckCodePrefix;
|
||||
use ruff::settings::options::Options;
|
||||
use ruff::settings::pyproject::Pyproject;
|
||||
use ruff::{flake8_quotes, pydocstyle};
|
||||
@@ -328,6 +394,7 @@ mod tests {
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
flake8_pytest_style: None,
|
||||
flake8_quotes: None,
|
||||
flake8_tidy_imports: None,
|
||||
flake8_import_conventions: None,
|
||||
@@ -387,6 +454,7 @@ mod tests {
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
flake8_pytest_style: None,
|
||||
flake8_quotes: None,
|
||||
flake8_tidy_imports: None,
|
||||
flake8_import_conventions: None,
|
||||
@@ -446,6 +514,7 @@ mod tests {
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
flake8_pytest_style: None,
|
||||
flake8_quotes: None,
|
||||
flake8_tidy_imports: None,
|
||||
flake8_import_conventions: None,
|
||||
@@ -505,6 +574,7 @@ mod tests {
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
flake8_pytest_style: None,
|
||||
flake8_quotes: None,
|
||||
flake8_tidy_imports: None,
|
||||
flake8_import_conventions: None,
|
||||
@@ -564,6 +634,7 @@ mod tests {
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
flake8_pytest_style: None,
|
||||
flake8_quotes: Some(flake8_quotes::settings::Options {
|
||||
inline_quotes: Some(flake8_quotes::settings::Quote::Single),
|
||||
multiline_quotes: None,
|
||||
@@ -619,42 +690,7 @@ mod tests {
|
||||
required_version: None,
|
||||
respect_gitignore: None,
|
||||
select: Some(vec![
|
||||
CheckCodePrefix::D100,
|
||||
CheckCodePrefix::D101,
|
||||
CheckCodePrefix::D102,
|
||||
CheckCodePrefix::D103,
|
||||
CheckCodePrefix::D104,
|
||||
CheckCodePrefix::D105,
|
||||
CheckCodePrefix::D106,
|
||||
CheckCodePrefix::D200,
|
||||
CheckCodePrefix::D201,
|
||||
CheckCodePrefix::D202,
|
||||
CheckCodePrefix::D204,
|
||||
CheckCodePrefix::D205,
|
||||
CheckCodePrefix::D206,
|
||||
CheckCodePrefix::D207,
|
||||
CheckCodePrefix::D208,
|
||||
CheckCodePrefix::D209,
|
||||
CheckCodePrefix::D210,
|
||||
CheckCodePrefix::D211,
|
||||
CheckCodePrefix::D214,
|
||||
CheckCodePrefix::D215,
|
||||
CheckCodePrefix::D300,
|
||||
CheckCodePrefix::D301,
|
||||
CheckCodePrefix::D400,
|
||||
CheckCodePrefix::D403,
|
||||
CheckCodePrefix::D404,
|
||||
CheckCodePrefix::D405,
|
||||
CheckCodePrefix::D406,
|
||||
CheckCodePrefix::D407,
|
||||
CheckCodePrefix::D408,
|
||||
CheckCodePrefix::D409,
|
||||
CheckCodePrefix::D410,
|
||||
CheckCodePrefix::D411,
|
||||
CheckCodePrefix::D412,
|
||||
CheckCodePrefix::D414,
|
||||
CheckCodePrefix::D418,
|
||||
CheckCodePrefix::D419,
|
||||
CheckCodePrefix::D,
|
||||
CheckCodePrefix::E,
|
||||
CheckCodePrefix::F,
|
||||
CheckCodePrefix::W,
|
||||
@@ -667,6 +703,7 @@ mod tests {
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
flake8_pytest_style: None,
|
||||
flake8_quotes: None,
|
||||
flake8_tidy_imports: None,
|
||||
flake8_import_conventions: None,
|
||||
@@ -729,6 +766,7 @@ mod tests {
|
||||
flake8_annotations: None,
|
||||
flake8_bugbear: None,
|
||||
flake8_errmsg: None,
|
||||
flake8_pytest_style: None,
|
||||
flake8_quotes: Some(flake8_quotes::settings::Options {
|
||||
inline_quotes: Some(flake8_quotes::settings::Quote::Single),
|
||||
multiline_quotes: None,
|
||||
|
||||
@@ -3,8 +3,8 @@ use std::str::FromStr;
|
||||
use anyhow::{bail, Result};
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use ruff::checks::PREFIX_REDIRECTS;
|
||||
use ruff::checks_gen::CheckCodePrefix;
|
||||
use ruff::registry::PREFIX_REDIRECTS;
|
||||
use ruff::registry_gen::CheckCodePrefix;
|
||||
use ruff::settings::types::PatternPrefixPair;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
@@ -201,7 +201,7 @@ pub fn collect_per_file_ignores(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use anyhow::Result;
|
||||
use ruff::checks_gen::CheckCodePrefix;
|
||||
use ruff::registry_gen::CheckCodePrefix;
|
||||
use ruff::settings::types::PatternPrefixPair;
|
||||
|
||||
use crate::parser::{parse_files_to_codes_mapping, parse_prefix_codes, parse_strings};
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use ruff::checks_gen::CheckCodePrefix;
|
||||
use ruff::registry_gen::CheckCodePrefix;
|
||||
|
||||
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq)]
|
||||
pub enum Plugin {
|
||||
@@ -16,16 +16,18 @@ pub enum Plugin {
|
||||
Flake8Datetimez,
|
||||
Flake8Debugger,
|
||||
Flake8Docstrings,
|
||||
Flake8ErrMsg,
|
||||
Flake8Eradicate,
|
||||
Flake8ErrMsg,
|
||||
Flake8ImplicitStrConcat,
|
||||
Flake8Print,
|
||||
Flake8PytestStyle,
|
||||
Flake8Quotes,
|
||||
Flake8Return,
|
||||
Flake8Simplify,
|
||||
Flake8TidyImports,
|
||||
McCabe,
|
||||
PandasVet,
|
||||
PEP8Naming,
|
||||
PandasVet,
|
||||
Pyupgrade,
|
||||
}
|
||||
|
||||
@@ -45,7 +47,9 @@ impl FromStr for Plugin {
|
||||
"flake8-docstrings" => Ok(Plugin::Flake8Docstrings),
|
||||
"flake8-eradicate" => Ok(Plugin::Flake8Eradicate),
|
||||
"flake8-errmsg" => Ok(Plugin::Flake8ErrMsg),
|
||||
"flake8-implicit-str-concat" => Ok(Plugin::Flake8ImplicitStrConcat),
|
||||
"flake8-print" => Ok(Plugin::Flake8Print),
|
||||
"flake8-pytest-style" => Ok(Plugin::Flake8PytestStyle),
|
||||
"flake8-quotes" => Ok(Plugin::Flake8Quotes),
|
||||
"flake8-return" => Ok(Plugin::Flake8Return),
|
||||
"flake8-simplify" => Ok(Plugin::Flake8Simplify),
|
||||
@@ -76,14 +80,16 @@ impl fmt::Debug for Plugin {
|
||||
Plugin::Flake8Docstrings => "flake8-docstrings",
|
||||
Plugin::Flake8Eradicate => "flake8-eradicate",
|
||||
Plugin::Flake8ErrMsg => "flake8-errmsg",
|
||||
Plugin::Flake8ImplicitStrConcat => "flake8-implicit-str-concat",
|
||||
Plugin::Flake8Print => "flake8-print",
|
||||
Plugin::Flake8PytestStyle => "flake8-pytest-style",
|
||||
Plugin::Flake8Quotes => "flake8-quotes",
|
||||
Plugin::Flake8Return => "flake8-return",
|
||||
Plugin::Flake8Simplify => "flake8-simplify",
|
||||
Plugin::Flake8TidyImports => "flake8-tidy-imports",
|
||||
Plugin::McCabe => "mccabe",
|
||||
Plugin::PandasVet => "pandas-vet",
|
||||
Plugin::PEP8Naming => "pep8-naming",
|
||||
Plugin::PandasVet => "pandas-vet",
|
||||
Plugin::Pyupgrade => "pyupgrade",
|
||||
}
|
||||
)
|
||||
@@ -91,7 +97,7 @@ impl fmt::Debug for Plugin {
|
||||
}
|
||||
|
||||
impl Plugin {
|
||||
pub fn default(&self) -> CheckCodePrefix {
|
||||
pub fn prefix(&self) -> CheckCodePrefix {
|
||||
match self {
|
||||
Plugin::Flake8Annotations => CheckCodePrefix::ANN,
|
||||
Plugin::Flake8Bandit => CheckCodePrefix::S,
|
||||
@@ -106,7 +112,9 @@ impl Plugin {
|
||||
// TODO(charlie): Handle rename of `E` to `ERA`.
|
||||
Plugin::Flake8Eradicate => CheckCodePrefix::ERA,
|
||||
Plugin::Flake8ErrMsg => CheckCodePrefix::EM,
|
||||
Plugin::Flake8ImplicitStrConcat => CheckCodePrefix::ISC,
|
||||
Plugin::Flake8Print => CheckCodePrefix::T2,
|
||||
Plugin::Flake8PytestStyle => CheckCodePrefix::PT,
|
||||
Plugin::Flake8Quotes => CheckCodePrefix::Q,
|
||||
Plugin::Flake8Return => CheckCodePrefix::RET,
|
||||
Plugin::Flake8Simplify => CheckCodePrefix::SIM,
|
||||
@@ -117,52 +125,12 @@ impl Plugin {
|
||||
Plugin::Pyupgrade => CheckCodePrefix::UP,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn select(&self, flake8: &HashMap<String, Option<String>>) -> Vec<CheckCodePrefix> {
|
||||
match self {
|
||||
Plugin::Flake8Annotations => vec![CheckCodePrefix::ANN],
|
||||
Plugin::Flake8Bandit => vec![CheckCodePrefix::S],
|
||||
Plugin::Flake8BlindExcept => vec![CheckCodePrefix::BLE],
|
||||
Plugin::Flake8Bugbear => vec![CheckCodePrefix::B],
|
||||
Plugin::Flake8Builtins => vec![CheckCodePrefix::A],
|
||||
Plugin::Flake8Comprehensions => vec![CheckCodePrefix::C4],
|
||||
Plugin::Flake8Datetimez => vec![CheckCodePrefix::DTZ],
|
||||
Plugin::Flake8Debugger => vec![CheckCodePrefix::T1],
|
||||
Plugin::Flake8Docstrings => {
|
||||
// Use the user-provided docstring.
|
||||
for key in ["docstring-convention", "docstring_convention"] {
|
||||
if let Some(Some(value)) = flake8.get(key) {
|
||||
match DocstringConvention::from_str(value) {
|
||||
Ok(convention) => return convention.select(),
|
||||
Err(e) => {
|
||||
eprintln!("Unexpected '{key}' value: {value} ({e}");
|
||||
return vec![];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Default to PEP8.
|
||||
DocstringConvention::PEP8.select()
|
||||
}
|
||||
Plugin::Flake8Eradicate => vec![CheckCodePrefix::ERA],
|
||||
Plugin::Flake8ErrMsg => vec![CheckCodePrefix::EM],
|
||||
Plugin::Flake8Print => vec![CheckCodePrefix::T2],
|
||||
Plugin::Flake8Quotes => vec![CheckCodePrefix::Q],
|
||||
Plugin::Flake8Return => vec![CheckCodePrefix::RET],
|
||||
Plugin::Flake8Simplify => vec![CheckCodePrefix::SIM],
|
||||
Plugin::Flake8TidyImports => vec![CheckCodePrefix::TID],
|
||||
Plugin::McCabe => vec![CheckCodePrefix::C9],
|
||||
Plugin::PandasVet => vec![CheckCodePrefix::PD],
|
||||
Plugin::PEP8Naming => vec![CheckCodePrefix::N],
|
||||
Plugin::Pyupgrade => vec![CheckCodePrefix::UP],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum DocstringConvention {
|
||||
All,
|
||||
PEP8,
|
||||
NumPy,
|
||||
Pep257,
|
||||
Numpy,
|
||||
Google,
|
||||
}
|
||||
|
||||
@@ -172,168 +140,14 @@ impl FromStr for DocstringConvention {
|
||||
fn from_str(string: &str) -> Result<Self, Self::Err> {
|
||||
match string {
|
||||
"all" => Ok(DocstringConvention::All),
|
||||
"pep8" => Ok(DocstringConvention::PEP8),
|
||||
"numpy" => Ok(DocstringConvention::NumPy),
|
||||
"pep257" => Ok(DocstringConvention::Pep257),
|
||||
"numpy" => Ok(DocstringConvention::Numpy),
|
||||
"google" => Ok(DocstringConvention::Google),
|
||||
_ => Err(anyhow!("Unknown docstring convention: {string}")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DocstringConvention {
|
||||
fn select(&self) -> Vec<CheckCodePrefix> {
|
||||
match self {
|
||||
DocstringConvention::All => vec![CheckCodePrefix::D],
|
||||
DocstringConvention::PEP8 => vec![
|
||||
// All errors except D203, D212, D213, D214, D215, D404, D405, D406, D407, D408,
|
||||
// D409, D410, D411, D413, D415, D416 and D417.
|
||||
CheckCodePrefix::D100,
|
||||
CheckCodePrefix::D101,
|
||||
CheckCodePrefix::D102,
|
||||
CheckCodePrefix::D103,
|
||||
CheckCodePrefix::D104,
|
||||
CheckCodePrefix::D105,
|
||||
CheckCodePrefix::D106,
|
||||
CheckCodePrefix::D107,
|
||||
CheckCodePrefix::D200,
|
||||
CheckCodePrefix::D201,
|
||||
CheckCodePrefix::D202,
|
||||
// CheckCodePrefix::D203,
|
||||
CheckCodePrefix::D204,
|
||||
CheckCodePrefix::D205,
|
||||
CheckCodePrefix::D206,
|
||||
CheckCodePrefix::D207,
|
||||
CheckCodePrefix::D208,
|
||||
CheckCodePrefix::D209,
|
||||
CheckCodePrefix::D210,
|
||||
CheckCodePrefix::D211,
|
||||
// CheckCodePrefix::D212,
|
||||
// CheckCodePrefix::D213,
|
||||
// CheckCodePrefix::D214,
|
||||
// CheckCodePrefix::D215,
|
||||
CheckCodePrefix::D300,
|
||||
CheckCodePrefix::D301,
|
||||
CheckCodePrefix::D400,
|
||||
CheckCodePrefix::D402,
|
||||
CheckCodePrefix::D403,
|
||||
// CheckCodePrefix::D404,
|
||||
// CheckCodePrefix::D405,
|
||||
// CheckCodePrefix::D406,
|
||||
// CheckCodePrefix::D407,
|
||||
// CheckCodePrefix::D408,
|
||||
// CheckCodePrefix::D409,
|
||||
// CheckCodePrefix::D410,
|
||||
// CheckCodePrefix::D411,
|
||||
CheckCodePrefix::D412,
|
||||
// CheckCodePrefix::D413,
|
||||
CheckCodePrefix::D414,
|
||||
// CheckCodePrefix::D415,
|
||||
// CheckCodePrefix::D416,
|
||||
// CheckCodePrefix::D417,
|
||||
CheckCodePrefix::D418,
|
||||
CheckCodePrefix::D419,
|
||||
],
|
||||
DocstringConvention::NumPy => vec![
|
||||
// All errors except D107, D203, D212, D213, D402, D413, D415, D416, and D417.
|
||||
CheckCodePrefix::D100,
|
||||
CheckCodePrefix::D101,
|
||||
CheckCodePrefix::D102,
|
||||
CheckCodePrefix::D103,
|
||||
CheckCodePrefix::D104,
|
||||
CheckCodePrefix::D105,
|
||||
CheckCodePrefix::D106,
|
||||
// CheckCodePrefix::D107,
|
||||
CheckCodePrefix::D200,
|
||||
CheckCodePrefix::D201,
|
||||
CheckCodePrefix::D202,
|
||||
// CheckCodePrefix::D203,
|
||||
CheckCodePrefix::D204,
|
||||
CheckCodePrefix::D205,
|
||||
CheckCodePrefix::D206,
|
||||
CheckCodePrefix::D207,
|
||||
CheckCodePrefix::D208,
|
||||
CheckCodePrefix::D209,
|
||||
CheckCodePrefix::D210,
|
||||
CheckCodePrefix::D211,
|
||||
// CheckCodePrefix::D212,
|
||||
// CheckCodePrefix::D213,
|
||||
CheckCodePrefix::D214,
|
||||
CheckCodePrefix::D215,
|
||||
CheckCodePrefix::D300,
|
||||
CheckCodePrefix::D301,
|
||||
CheckCodePrefix::D400,
|
||||
// CheckCodePrefix::D402,
|
||||
CheckCodePrefix::D403,
|
||||
CheckCodePrefix::D404,
|
||||
CheckCodePrefix::D405,
|
||||
CheckCodePrefix::D406,
|
||||
CheckCodePrefix::D407,
|
||||
CheckCodePrefix::D408,
|
||||
CheckCodePrefix::D409,
|
||||
CheckCodePrefix::D410,
|
||||
CheckCodePrefix::D411,
|
||||
CheckCodePrefix::D412,
|
||||
// CheckCodePrefix::D413,
|
||||
CheckCodePrefix::D414,
|
||||
// CheckCodePrefix::D415,
|
||||
// CheckCodePrefix::D416,
|
||||
// CheckCodePrefix::D417,
|
||||
CheckCodePrefix::D418,
|
||||
CheckCodePrefix::D419,
|
||||
],
|
||||
DocstringConvention::Google => vec![
|
||||
// All errors except D203, D204, D213, D215, D400, D401, D404, D406, D407, D408,
|
||||
// D409 and D413.
|
||||
CheckCodePrefix::D100,
|
||||
CheckCodePrefix::D101,
|
||||
CheckCodePrefix::D102,
|
||||
CheckCodePrefix::D103,
|
||||
CheckCodePrefix::D104,
|
||||
CheckCodePrefix::D105,
|
||||
CheckCodePrefix::D106,
|
||||
CheckCodePrefix::D107,
|
||||
CheckCodePrefix::D200,
|
||||
CheckCodePrefix::D201,
|
||||
CheckCodePrefix::D202,
|
||||
// CheckCodePrefix::D203,
|
||||
// CheckCodePrefix::D204,
|
||||
CheckCodePrefix::D205,
|
||||
CheckCodePrefix::D206,
|
||||
CheckCodePrefix::D207,
|
||||
CheckCodePrefix::D208,
|
||||
CheckCodePrefix::D209,
|
||||
CheckCodePrefix::D210,
|
||||
CheckCodePrefix::D211,
|
||||
CheckCodePrefix::D212,
|
||||
// CheckCodePrefix::D213,
|
||||
CheckCodePrefix::D214,
|
||||
// CheckCodePrefix::D215,
|
||||
CheckCodePrefix::D300,
|
||||
CheckCodePrefix::D301,
|
||||
// CheckCodePrefix::D400,
|
||||
CheckCodePrefix::D402,
|
||||
CheckCodePrefix::D403,
|
||||
// CheckCodePrefix::D404,
|
||||
CheckCodePrefix::D405,
|
||||
// CheckCodePrefix::D406,
|
||||
// CheckCodePrefix::D407,
|
||||
// CheckCodePrefix::D408,
|
||||
// CheckCodePrefix::D409,
|
||||
CheckCodePrefix::D410,
|
||||
CheckCodePrefix::D411,
|
||||
CheckCodePrefix::D412,
|
||||
// CheckCodePrefix::D413,
|
||||
CheckCodePrefix::D414,
|
||||
CheckCodePrefix::D415,
|
||||
CheckCodePrefix::D416,
|
||||
CheckCodePrefix::D417,
|
||||
CheckCodePrefix::D418,
|
||||
CheckCodePrefix::D419,
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Infer the enabled plugins based on user-provided options.
|
||||
///
|
||||
/// For example, if the user specified a `mypy-init-return` setting, we should
|
||||
@@ -389,6 +203,25 @@ pub fn infer_plugins_from_options(flake8: &HashMap<String, Option<String>>) -> V
|
||||
"eradicate-whitelist-extend" | "eradicate_whitelist_extend" => {
|
||||
plugins.insert(Plugin::Flake8Eradicate);
|
||||
}
|
||||
// flake8-pytest-style
|
||||
"pytest-fixture-no-parentheses" | "pytest_fixture_no_parentheses " => {
|
||||
plugins.insert(Plugin::Flake8PytestStyle);
|
||||
}
|
||||
"pytest-parametrize-names-type" | "pytest_parametrize_names_type" => {
|
||||
plugins.insert(Plugin::Flake8PytestStyle);
|
||||
}
|
||||
"pytest-parametrize-values-type" | "pytest_parametrize_values_type" => {
|
||||
plugins.insert(Plugin::Flake8PytestStyle);
|
||||
}
|
||||
"pytest-parametrize-values-row-type" | "pytest_parametrize_values_row_type" => {
|
||||
plugins.insert(Plugin::Flake8PytestStyle);
|
||||
}
|
||||
"pytest-raises-require-match-for" | "pytest_raises_require_match_for" => {
|
||||
plugins.insert(Plugin::Flake8PytestStyle);
|
||||
}
|
||||
"pytest-mark-no-parentheses" | "pytest_mark_no_parentheses" => {
|
||||
plugins.insert(Plugin::Flake8PytestStyle);
|
||||
}
|
||||
// flake8-quotes
|
||||
"quotes" | "inline-quotes" | "inline_quotes" => {
|
||||
plugins.insert(Plugin::Flake8Quotes);
|
||||
@@ -449,6 +282,7 @@ pub fn infer_plugins_from_codes(codes: &BTreeSet<CheckCodePrefix>) -> Vec<Plugin
|
||||
Plugin::Flake8Docstrings,
|
||||
Plugin::Flake8Eradicate,
|
||||
Plugin::Flake8ErrMsg,
|
||||
Plugin::Flake8ImplicitStrConcat,
|
||||
Plugin::Flake8Print,
|
||||
Plugin::Flake8Quotes,
|
||||
Plugin::Flake8Return,
|
||||
@@ -463,7 +297,7 @@ pub fn infer_plugins_from_codes(codes: &BTreeSet<CheckCodePrefix>) -> Vec<Plugin
|
||||
if prefix
|
||||
.codes()
|
||||
.iter()
|
||||
.any(|code| plugin.default().codes().contains(code))
|
||||
.any(|code| plugin.prefix().codes().contains(code))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -474,18 +308,9 @@ pub fn infer_plugins_from_codes(codes: &BTreeSet<CheckCodePrefix>) -> Vec<Plugin
|
||||
}
|
||||
|
||||
/// Resolve the set of enabled `CheckCodePrefix` values for the given plugins.
|
||||
pub fn resolve_select(
|
||||
flake8: &HashMap<String, Option<String>>,
|
||||
plugins: &[Plugin],
|
||||
) -> BTreeSet<CheckCodePrefix> {
|
||||
// Include default Pyflakes and pycodestyle checks.
|
||||
let mut select = BTreeSet::from([CheckCodePrefix::E, CheckCodePrefix::F, CheckCodePrefix::W]);
|
||||
|
||||
// Add prefix codes for every plugin.
|
||||
for plugin in plugins {
|
||||
select.extend(plugin.select(flake8));
|
||||
}
|
||||
|
||||
pub fn resolve_select(plugins: &[Plugin]) -> BTreeSet<CheckCodePrefix> {
|
||||
let mut select = BTreeSet::from([CheckCodePrefix::F, CheckCodePrefix::E, CheckCodePrefix::W]);
|
||||
select.extend(plugins.iter().map(Plugin::prefix));
|
||||
select
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
src/ruff_options.ts
|
||||
3
playground/.prettierrc.json
Normal file
3
playground/.prettierrc.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"trailingComma": "all"
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
<title>Ruff Playground</title>
|
||||
<link
|
||||
rel="icon"
|
||||
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🛠️</text></svg>"
|
||||
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>⚡</text></svg>"
|
||||
/>
|
||||
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
|
||||
</head>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { persist, restore } from "./config";
|
||||
import { DEFAULT_CONFIG_SOURCE, DEFAULT_PYTHON_SOURCE } from "../constants";
|
||||
import { DEFAULT_PYTHON_SOURCE } from "../constants";
|
||||
import init, { check, Check, currentVersion, defaultSettings } from "../pkg";
|
||||
import { ErrorMessage } from "./ErrorMessage";
|
||||
import Header from "./Header";
|
||||
import init, { check, current_version, Check } from "../pkg";
|
||||
import { useTheme } from "./theme";
|
||||
import { persist, restore, stringify } from "./settings";
|
||||
import SettingsEditor from "./SettingsEditor";
|
||||
import SourceEditor from "./SourceEditor";
|
||||
import Themes from "./Themes";
|
||||
import MonacoThemes from "./MonacoThemes";
|
||||
|
||||
type Tab = "Source" | "Settings";
|
||||
|
||||
@@ -15,17 +16,18 @@ export default function Editor() {
|
||||
const [version, setVersion] = useState<string | null>(null);
|
||||
const [tab, setTab] = useState<Tab>("Source");
|
||||
const [edit, setEdit] = useState<number>(0);
|
||||
const [configSource, setConfigSource] = useState<string | null>(null);
|
||||
const [settingsSource, setSettingsSource] = useState<string | null>(null);
|
||||
const [pythonSource, setPythonSource] = useState<string | null>(null);
|
||||
const [checks, setChecks] = useState<Check[]>([]);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [theme, setTheme] = useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
init().then(() => setInitialized(true));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!initialized || configSource == null || pythonSource == null) {
|
||||
if (!initialized || settingsSource == null || pythonSource == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -33,7 +35,7 @@ export default function Editor() {
|
||||
let checks: Check[];
|
||||
|
||||
try {
|
||||
config = JSON.parse(configSource);
|
||||
config = JSON.parse(settingsSource);
|
||||
} catch (e) {
|
||||
setChecks([]);
|
||||
setError((e as Error).message);
|
||||
@@ -49,73 +51,85 @@ export default function Editor() {
|
||||
|
||||
setError(null);
|
||||
setChecks(checks);
|
||||
}, [initialized, configSource, pythonSource]);
|
||||
|
||||
useEffect(() => {
|
||||
if (configSource == null || pythonSource == null) {
|
||||
const payload = restore();
|
||||
if (payload) {
|
||||
const [configSource, pythonSource] = payload;
|
||||
setConfigSource(configSource);
|
||||
setPythonSource(pythonSource);
|
||||
} else {
|
||||
setConfigSource(DEFAULT_CONFIG_SOURCE);
|
||||
setPythonSource(DEFAULT_PYTHON_SOURCE);
|
||||
}
|
||||
}
|
||||
}, [configSource, pythonSource]);
|
||||
}, [initialized, settingsSource, pythonSource]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
setVersion(current_version());
|
||||
}, [initialized]);
|
||||
if (settingsSource == null || pythonSource == null) {
|
||||
const payload = restore();
|
||||
if (payload) {
|
||||
const [settingsSource, pythonSource] = payload;
|
||||
setSettingsSource(settingsSource);
|
||||
setPythonSource(pythonSource);
|
||||
} else {
|
||||
setSettingsSource(stringify(defaultSettings()));
|
||||
setPythonSource(DEFAULT_PYTHON_SOURCE);
|
||||
}
|
||||
}
|
||||
}, [initialized, settingsSource, pythonSource]);
|
||||
|
||||
const handleShare = useCallback(() => {
|
||||
if (!initialized || configSource == null || pythonSource == null) {
|
||||
useEffect(() => {
|
||||
if (!initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
persist(configSource, pythonSource);
|
||||
}, [initialized, configSource, pythonSource]);
|
||||
setVersion(currentVersion());
|
||||
}, [initialized]);
|
||||
|
||||
const handleShare = useCallback(() => {
|
||||
if (!initialized || settingsSource == null || pythonSource == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
persist(settingsSource, pythonSource);
|
||||
}, [initialized, settingsSource, pythonSource]);
|
||||
|
||||
const handlePythonSourceChange = useCallback((pythonSource: string) => {
|
||||
setEdit((edit) => edit + 1);
|
||||
setPythonSource(pythonSource);
|
||||
}, []);
|
||||
|
||||
const handleConfigSourceChange = useCallback((configSource: string) => {
|
||||
const handleSettingsSourceChange = useCallback((settingsSource: string) => {
|
||||
setEdit((edit) => edit + 1);
|
||||
setConfigSource(configSource);
|
||||
setSettingsSource(settingsSource);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<main className={"h-full w-full flex flex-auto"}>
|
||||
<main
|
||||
className={
|
||||
"h-full w-full flex flex-auto bg-ayu-background dark:bg-ayu-background-dark"
|
||||
}
|
||||
>
|
||||
<Header
|
||||
edit={edit}
|
||||
version={version}
|
||||
tab={tab}
|
||||
onChange={setTab}
|
||||
theme={theme}
|
||||
version={version}
|
||||
onChangeTab={setTab}
|
||||
onChangeTheme={setTheme}
|
||||
onShare={initialized ? handleShare : undefined}
|
||||
/>
|
||||
|
||||
<Themes />
|
||||
<MonacoThemes />
|
||||
|
||||
<div className={"mt-12 relative flex-auto"}>
|
||||
{initialized && configSource != null && pythonSource != null ? (
|
||||
{initialized && settingsSource != null && pythonSource != null ? (
|
||||
<>
|
||||
<SourceEditor
|
||||
visible={tab === "Source"}
|
||||
source={pythonSource}
|
||||
theme={theme}
|
||||
checks={checks}
|
||||
onChange={handlePythonSourceChange}
|
||||
/>
|
||||
<SettingsEditor
|
||||
visible={tab === "Settings"}
|
||||
source={configSource}
|
||||
onChange={handleConfigSourceChange}
|
||||
source={settingsSource}
|
||||
theme={theme}
|
||||
onChange={handleSettingsSourceChange}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
|
||||
@@ -18,7 +18,7 @@ export function ErrorMessage({ children }: { children: string }) {
|
||||
children.startsWith("Error: ")
|
||||
? children.slice("Error: ".length)
|
||||
: children,
|
||||
120
|
||||
120,
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -1,26 +1,51 @@
|
||||
import classNames from "classnames";
|
||||
import RepoButton from "./RepoButton";
|
||||
import ThemeButton from "./ThemeButton";
|
||||
import ShareButton from "./ShareButton";
|
||||
import { Theme } from "./theme";
|
||||
import VersionTag from "./VersionTag";
|
||||
|
||||
export type Tab = "Source" | "Settings";
|
||||
|
||||
export default function Header({
|
||||
edit,
|
||||
version,
|
||||
tab,
|
||||
onChange,
|
||||
theme,
|
||||
version,
|
||||
onChangeTab,
|
||||
onChangeTheme,
|
||||
onShare,
|
||||
}: {
|
||||
edit: number;
|
||||
version: string | null;
|
||||
tab: Tab;
|
||||
onChange: (tab: Tab) => void;
|
||||
theme: Theme;
|
||||
version: string | null;
|
||||
onChangeTab: (tab: Tab) => void;
|
||||
onChangeTheme: (theme: Theme) => void;
|
||||
onShare?: () => void;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className="w-full flex items-center justify-between flex-none pl-5 sm:pl-6 pr-4 lg:pr-6 absolute z-10 top-0 left-0 -mb-px antialiased border-b border-gray-200 dark:border-gray-800"
|
||||
style={{ background: "#f8f9fa" }}
|
||||
className={classNames(
|
||||
"w-full",
|
||||
"flex",
|
||||
"items-center",
|
||||
"justify-between",
|
||||
"flex-none",
|
||||
"pl-5",
|
||||
"sm:pl-6",
|
||||
"pr-4",
|
||||
"lg:pr-6",
|
||||
"absolute",
|
||||
"z-10",
|
||||
"top-0",
|
||||
"left-0",
|
||||
"-mb-px",
|
||||
"antialiased",
|
||||
"border-b",
|
||||
"border-gray-200",
|
||||
"dark:border-gray-800",
|
||||
)}
|
||||
>
|
||||
<div className="flex space-x-5">
|
||||
<button
|
||||
@@ -28,15 +53,15 @@ export default function Header({
|
||||
className={classNames(
|
||||
"relative flex py-3 text-sm leading-6 font-semibold focus:outline-none",
|
||||
tab === "Source"
|
||||
? "text-ayu"
|
||||
: "text-gray-700 hover:text-gray-900 focus:text-gray-900 dark:text-gray-300 dark:hover:text-white"
|
||||
? "text-ayu-accent"
|
||||
: "text-gray-700 hover:text-gray-900 focus:text-gray-900 dark:text-gray-300 dark:hover:text-white",
|
||||
)}
|
||||
onClick={() => onChange("Source")}
|
||||
onClick={() => onChangeTab("Source")}
|
||||
>
|
||||
<span
|
||||
className={classNames(
|
||||
"absolute bottom-0 inset-x-0 bg-ayu h-0.5 rounded-full transition-opacity duration-150",
|
||||
tab === "Source" ? "opacity-100" : "opacity-0"
|
||||
"absolute bottom-0 inset-x-0 bg-ayu-accent h-0.5 rounded-full transition-opacity duration-150",
|
||||
tab === "Source" ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
Source
|
||||
@@ -46,27 +71,34 @@ export default function Header({
|
||||
className={classNames(
|
||||
"relative flex py-3 text-sm leading-6 font-semibold focus:outline-none",
|
||||
tab === "Settings"
|
||||
? "text-ayu"
|
||||
: "text-gray-700 hover:text-gray-900 focus:text-gray-900 dark:text-gray-300 dark:hover:text-white"
|
||||
? "text-ayu-accent"
|
||||
: "text-gray-700 hover:text-gray-900 focus:text-gray-900 dark:text-gray-300 dark:hover:text-white",
|
||||
)}
|
||||
onClick={() => onChange("Settings")}
|
||||
onClick={() => onChangeTab("Settings")}
|
||||
>
|
||||
<span
|
||||
className={classNames(
|
||||
"absolute bottom-0 inset-x-0 bg-ayu h-0.5 rounded-full transition-opacity duration-150",
|
||||
tab === "Settings" ? "opacity-100" : "opacity-0"
|
||||
"absolute bottom-0 inset-x-0 bg-ayu-accent h-0.5 rounded-full transition-opacity duration-150",
|
||||
tab === "Settings" ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
Settings
|
||||
</button>
|
||||
</div>
|
||||
<div className={"flex items-center min-w-0"}>
|
||||
{version ? (
|
||||
<div className={"flex items-center"}>
|
||||
<div className={"hidden sm:flex items-center"}>
|
||||
<VersionTag>v{version}</VersionTag>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<div className={"hidden sm:flex items-center min-w-0"}>
|
||||
<ShareButton key={edit} onShare={onShare} />
|
||||
<div className="hidden sm:block mx-6 lg:mx-4 w-px h-6 bg-gray-200 dark:bg-gray-700" />
|
||||
<RepoButton />
|
||||
<div className="hidden sm:block mx-6 lg:mx-4 w-px h-6 bg-gray-200 dark:bg-gray-700" />
|
||||
<div className="hidden sm:block">
|
||||
<ShareButton key={edit} onShare={onShare} />
|
||||
</div>
|
||||
<div className="hidden sm:block mx-6 lg:mx-4 w-px h-6 bg-gray-200 dark:bg-gray-700" />
|
||||
<ThemeButton theme={theme} onChange={onChangeTheme} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
/**
|
||||
* Non-rendering component that loads the Monaco editor themes.
|
||||
*/
|
||||
|
||||
import { useMonaco } from "@monaco-editor/react";
|
||||
import { useEffect } from "react";
|
||||
|
||||
export default function Themes() {
|
||||
export default function MonacoThemes() {
|
||||
const monaco = useMonaco();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -631,7 +635,642 @@ export default function Themes() {
|
||||
foreground: "#787b8099",
|
||||
token: "punctuation.definition.markdown",
|
||||
},
|
||||
// Edits.
|
||||
// Manual changes.
|
||||
{
|
||||
foreground: "#fa8d3e",
|
||||
token: "number",
|
||||
},
|
||||
],
|
||||
encodedTokensColors: [],
|
||||
});
|
||||
|
||||
// Generated via `monaco-vscode-textmate-theme-converter`.
|
||||
// See: https://github.com/ayu-theme/vscode-ayu/blob/91839e8a9dfa78d61e58dbcf9b52272a01fee66a/ayu-dark.json.
|
||||
monaco?.editor.defineTheme("Ayu-Dark", {
|
||||
inherit: false,
|
||||
base: "vs-dark",
|
||||
colors: {
|
||||
focusBorder: "#e6b450b3",
|
||||
foreground: "#565b66",
|
||||
"widget.shadow": "#00000080",
|
||||
"selection.background": "#409fff4d",
|
||||
"icon.foreground": "#565b66",
|
||||
errorForeground: "#d95757",
|
||||
descriptionForeground: "#565b66",
|
||||
"textBlockQuote.background": "#0f131a",
|
||||
"textLink.foreground": "#e6b450",
|
||||
"textLink.activeForeground": "#e6b450",
|
||||
"textPreformat.foreground": "#bfbdb6",
|
||||
"button.background": "#e6b450",
|
||||
"button.foreground": "#0b0e14",
|
||||
"button.hoverBackground": "#e1af4b",
|
||||
"button.secondaryBackground": "#565b6633",
|
||||
"button.secondaryForeground": "#bfbdb6",
|
||||
"button.secondaryHoverBackground": "#565b6680",
|
||||
"dropdown.background": "#0d1017",
|
||||
"dropdown.foreground": "#565b66",
|
||||
"dropdown.border": "#565b6645",
|
||||
"input.background": "#0d1017",
|
||||
"input.border": "#565b6645",
|
||||
"input.foreground": "#bfbdb6",
|
||||
"input.placeholderForeground": "#565b6680",
|
||||
"inputOption.activeBorder": "#e6b4504d",
|
||||
"inputOption.activeBackground": "#e6b45033",
|
||||
"inputOption.activeForeground": "#e6b450",
|
||||
"inputValidation.errorBackground": "#0d1017",
|
||||
"inputValidation.errorBorder": "#d95757",
|
||||
"inputValidation.infoBackground": "#0b0e14",
|
||||
"inputValidation.infoBorder": "#39bae6",
|
||||
"inputValidation.warningBackground": "#0b0e14",
|
||||
"inputValidation.warningBorder": "#ffb454",
|
||||
"scrollbar.shadow": "#11151c00",
|
||||
"scrollbarSlider.background": "#565b6666",
|
||||
"scrollbarSlider.hoverBackground": "#565b6699",
|
||||
"scrollbarSlider.activeBackground": "#565b66b3",
|
||||
"badge.background": "#e6b45033",
|
||||
"badge.foreground": "#e6b450",
|
||||
"progressBar.background": "#e6b450",
|
||||
"list.activeSelectionBackground": "#47526640",
|
||||
"list.activeSelectionForeground": "#bfbdb6",
|
||||
"list.focusBackground": "#47526640",
|
||||
"list.focusForeground": "#bfbdb6",
|
||||
"list.focusOutline": "#47526640",
|
||||
"list.highlightForeground": "#e6b450",
|
||||
"list.deemphasizedForeground": "#d95757",
|
||||
"list.hoverBackground": "#47526640",
|
||||
"list.inactiveSelectionBackground": "#47526633",
|
||||
"list.inactiveSelectionForeground": "#565b66",
|
||||
"list.invalidItemForeground": "#565b664d",
|
||||
"list.errorForeground": "#d95757",
|
||||
"tree.indentGuidesStroke": "#6c738080",
|
||||
"listFilterWidget.background": "#0f131a",
|
||||
"listFilterWidget.outline": "#e6b450",
|
||||
"listFilterWidget.noMatchesOutline": "#d95757",
|
||||
"list.filterMatchBackground": "#5f4c7266",
|
||||
"list.filterMatchBorder": "#6c598066",
|
||||
"activityBar.background": "#0b0e14",
|
||||
"activityBar.foreground": "#565b66cc",
|
||||
"activityBar.inactiveForeground": "#565b6699",
|
||||
"activityBar.border": "#0b0e14",
|
||||
"activityBar.activeBorder": "#e6b450b3",
|
||||
"activityBarBadge.background": "#e6b450",
|
||||
"activityBarBadge.foreground": "#0b0e14",
|
||||
"sideBar.background": "#0b0e14",
|
||||
"sideBar.border": "#0b0e14",
|
||||
"sideBarTitle.foreground": "#565b66",
|
||||
"sideBarSectionHeader.background": "#0b0e14",
|
||||
"sideBarSectionHeader.foreground": "#565b66",
|
||||
"sideBarSectionHeader.border": "#0b0e14",
|
||||
"minimap.background": "#0b0e14",
|
||||
"minimap.selectionHighlight": "#409fff4d",
|
||||
"minimap.errorHighlight": "#d95757",
|
||||
"minimap.findMatchHighlight": "#6c5980",
|
||||
"minimapGutter.addedBackground": "#7fd962",
|
||||
"minimapGutter.modifiedBackground": "#73b8ff",
|
||||
"minimapGutter.deletedBackground": "#f26d78",
|
||||
"editorGroup.border": "#11151c",
|
||||
"editorGroup.background": "#0f131a",
|
||||
"editorGroupHeader.noTabsBackground": "#0b0e14",
|
||||
"editorGroupHeader.tabsBackground": "#0b0e14",
|
||||
"editorGroupHeader.tabsBorder": "#0b0e14",
|
||||
"tab.activeBackground": "#0b0e14",
|
||||
"tab.activeForeground": "#bfbdb6",
|
||||
"tab.border": "#0b0e14",
|
||||
"tab.activeBorder": "#e6b450",
|
||||
"tab.unfocusedActiveBorder": "#565b66",
|
||||
"tab.inactiveBackground": "#0b0e14",
|
||||
"tab.inactiveForeground": "#565b66",
|
||||
"tab.unfocusedActiveForeground": "#565b66",
|
||||
"tab.unfocusedInactiveForeground": "#565b66",
|
||||
"editor.background": "#0b0e14",
|
||||
"editor.foreground": "#bfbdb6",
|
||||
"editorLineNumber.foreground": "#6c738099",
|
||||
"editorLineNumber.activeForeground": "#6c7380e6",
|
||||
"editorCursor.foreground": "#e6b450",
|
||||
"editor.inactiveSelectionBackground": "#409fff21",
|
||||
"editor.selectionBackground": "#409fff4d",
|
||||
"editor.selectionHighlightBackground": "#7fd96226",
|
||||
"editor.selectionHighlightBorder": "#7fd96200",
|
||||
"editor.wordHighlightBackground": "#73b8ff14",
|
||||
"editor.wordHighlightStrongBackground": "#7fd96214",
|
||||
"editor.wordHighlightBorder": "#73b8ff80",
|
||||
"editor.wordHighlightStrongBorder": "#7fd96280",
|
||||
"editor.findMatchBackground": "#6c5980",
|
||||
"editor.findMatchBorder": "#6c5980",
|
||||
"editor.findMatchHighlightBackground": "#6c598066",
|
||||
"editor.findMatchHighlightBorder": "#5f4c7266",
|
||||
"editor.findRangeHighlightBackground": "#6c598040",
|
||||
"editor.rangeHighlightBackground": "#6c598033",
|
||||
"editor.lineHighlightBackground": "#131721",
|
||||
"editorLink.activeForeground": "#e6b450",
|
||||
"editorWhitespace.foreground": "#6c738099",
|
||||
"editorIndentGuide.background": "#6c738033",
|
||||
"editorIndentGuide.activeBackground": "#6c738080",
|
||||
"editorRuler.foreground": "#6c738033",
|
||||
"editorCodeLens.foreground": "#acb6bf8c",
|
||||
"editorBracketMatch.background": "#6c73804d",
|
||||
"editorBracketMatch.border": "#6c73804d",
|
||||
"editor.snippetTabstopHighlightBackground": "#7fd96233",
|
||||
"editorOverviewRuler.border": "#11151c",
|
||||
"editorOverviewRuler.modifiedForeground": "#73b8ff",
|
||||
"editorOverviewRuler.addedForeground": "#7fd962",
|
||||
"editorOverviewRuler.deletedForeground": "#f26d78",
|
||||
"editorOverviewRuler.errorForeground": "#d95757",
|
||||
"editorOverviewRuler.warningForeground": "#e6b450",
|
||||
"editorOverviewRuler.bracketMatchForeground": "#6c7380b3",
|
||||
"editorOverviewRuler.wordHighlightForeground": "#73b8ff66",
|
||||
"editorOverviewRuler.wordHighlightStrongForeground": "#7fd96266",
|
||||
"editorOverviewRuler.findMatchForeground": "#6c5980",
|
||||
"editorError.foreground": "#d95757",
|
||||
"editorWarning.foreground": "#e6b450",
|
||||
"editorGutter.modifiedBackground": "#73b8ffcc",
|
||||
"editorGutter.addedBackground": "#7fd962cc",
|
||||
"editorGutter.deletedBackground": "#f26d78cc",
|
||||
"diffEditor.insertedTextBackground": "#7fd9621f",
|
||||
"diffEditor.removedTextBackground": "#f26d781f",
|
||||
"diffEditor.diagonalFill": "#11151c",
|
||||
"editorWidget.background": "#0f131a",
|
||||
"editorWidget.border": "#11151c",
|
||||
"editorHoverWidget.background": "#0f131a",
|
||||
"editorHoverWidget.border": "#11151c",
|
||||
"editorSuggestWidget.background": "#0f131a",
|
||||
"editorSuggestWidget.border": "#11151c",
|
||||
"editorSuggestWidget.highlightForeground": "#e6b450",
|
||||
"editorSuggestWidget.selectedBackground": "#47526640",
|
||||
"debugExceptionWidget.border": "#11151c",
|
||||
"debugExceptionWidget.background": "#0f131a",
|
||||
"editorMarkerNavigation.background": "#0f131a",
|
||||
"peekView.border": "#47526640",
|
||||
"peekViewTitle.background": "#47526640",
|
||||
"peekViewTitleDescription.foreground": "#565b66",
|
||||
"peekViewTitleLabel.foreground": "#bfbdb6",
|
||||
"peekViewEditor.background": "#0f131a",
|
||||
"peekViewEditor.matchHighlightBackground": "#6c598066",
|
||||
"peekViewEditor.matchHighlightBorder": "#5f4c7266",
|
||||
"peekViewResult.background": "#0f131a",
|
||||
"peekViewResult.fileForeground": "#bfbdb6",
|
||||
"peekViewResult.lineForeground": "#565b66",
|
||||
"peekViewResult.matchHighlightBackground": "#6c598066",
|
||||
"peekViewResult.selectionBackground": "#47526640",
|
||||
"panel.background": "#0b0e14",
|
||||
"panel.border": "#11151c",
|
||||
"panelTitle.activeBorder": "#e6b450",
|
||||
"panelTitle.activeForeground": "#bfbdb6",
|
||||
"panelTitle.inactiveForeground": "#565b66",
|
||||
"statusBar.background": "#0b0e14",
|
||||
"statusBar.foreground": "#565b66",
|
||||
"statusBar.border": "#0b0e14",
|
||||
"statusBar.debuggingBackground": "#f29668",
|
||||
"statusBar.debuggingForeground": "#0d1017",
|
||||
"statusBar.noFolderBackground": "#0f131a",
|
||||
"statusBarItem.activeBackground": "#565b6633",
|
||||
"statusBarItem.hoverBackground": "#565b6633",
|
||||
"statusBarItem.prominentBackground": "#11151c",
|
||||
"statusBarItem.prominentHoverBackground": "#00000030",
|
||||
"statusBarItem.remoteBackground": "#e6b450",
|
||||
"statusBarItem.remoteForeground": "#0d1017",
|
||||
"titleBar.activeBackground": "#0b0e14",
|
||||
"titleBar.activeForeground": "#bfbdb6",
|
||||
"titleBar.inactiveBackground": "#0b0e14",
|
||||
"titleBar.inactiveForeground": "#565b66",
|
||||
"titleBar.border": "#0b0e14",
|
||||
"extensionButton.prominentForeground": "#0d1017",
|
||||
"extensionButton.prominentBackground": "#e6b450",
|
||||
"extensionButton.prominentHoverBackground": "#e1af4b",
|
||||
"pickerGroup.border": "#11151c",
|
||||
"pickerGroup.foreground": "#565b6680",
|
||||
"debugToolBar.background": "#0f131a",
|
||||
"debugIcon.breakpointForeground": "#f29668",
|
||||
"debugIcon.breakpointDisabledForeground": "#f2966880",
|
||||
"debugConsoleInputIcon.foreground": "#e6b450",
|
||||
"welcomePage.tileBackground": "#0b0e14",
|
||||
"welcomePage.tileShadow": "#00000080",
|
||||
"welcomePage.progress.background": "#131721",
|
||||
"welcomePage.buttonBackground": "#e6b45066",
|
||||
"walkThrough.embeddedEditorBackground": "#0f131a",
|
||||
"gitDecoration.modifiedResourceForeground": "#73b8ffb3",
|
||||
"gitDecoration.deletedResourceForeground": "#f26d78b3",
|
||||
"gitDecoration.untrackedResourceForeground": "#7fd962b3",
|
||||
"gitDecoration.ignoredResourceForeground": "#565b6680",
|
||||
"gitDecoration.conflictingResourceForeground": "",
|
||||
"gitDecoration.submoduleResourceForeground": "#d2a6ffb3",
|
||||
"settings.headerForeground": "#bfbdb6",
|
||||
"settings.modifiedItemIndicator": "#73b8ff",
|
||||
"keybindingLabel.background": "#565b661a",
|
||||
"keybindingLabel.foreground": "#bfbdb6",
|
||||
"keybindingLabel.border": "#bfbdb61a",
|
||||
"keybindingLabel.bottomBorder": "#bfbdb61a",
|
||||
"terminal.background": "#0b0e14",
|
||||
"terminal.foreground": "#bfbdb6",
|
||||
"terminal.ansiBlack": "#11151c",
|
||||
"terminal.ansiRed": "#ea6c73",
|
||||
"terminal.ansiGreen": "#7fd962",
|
||||
"terminal.ansiYellow": "#f9af4f",
|
||||
"terminal.ansiBlue": "#53bdfa",
|
||||
"terminal.ansiMagenta": "#cda1fa",
|
||||
"terminal.ansiCyan": "#90e1c6",
|
||||
"terminal.ansiWhite": "#c7c7c7",
|
||||
"terminal.ansiBrightBlack": "#686868",
|
||||
"terminal.ansiBrightRed": "#f07178",
|
||||
"terminal.ansiBrightGreen": "#aad94c",
|
||||
"terminal.ansiBrightYellow": "#ffb454",
|
||||
"terminal.ansiBrightBlue": "#59c2ff",
|
||||
"terminal.ansiBrightMagenta": "#d2a6ff",
|
||||
"terminal.ansiBrightCyan": "#95e6cb",
|
||||
"terminal.ansiBrightWhite": "#ffffff",
|
||||
},
|
||||
rules: [
|
||||
{
|
||||
fontStyle: "italic",
|
||||
foreground: "#acb6bf8c",
|
||||
token: "comment",
|
||||
},
|
||||
{
|
||||
foreground: "#aad94c",
|
||||
token: "string",
|
||||
},
|
||||
{
|
||||
foreground: "#aad94c",
|
||||
token: "constant.other.symbol",
|
||||
},
|
||||
{
|
||||
foreground: "#95e6cb",
|
||||
token: "string.regexp",
|
||||
},
|
||||
{
|
||||
foreground: "#95e6cb",
|
||||
token: "constant.character",
|
||||
},
|
||||
{
|
||||
foreground: "#95e6cb",
|
||||
token: "constant.other",
|
||||
},
|
||||
{
|
||||
foreground: "#d2a6ff",
|
||||
token: "constant.numeric",
|
||||
},
|
||||
{
|
||||
foreground: "#d2a6ff",
|
||||
token: "constant.language",
|
||||
},
|
||||
{
|
||||
foreground: "#bfbdb6",
|
||||
token: "variable",
|
||||
},
|
||||
{
|
||||
foreground: "#bfbdb6",
|
||||
token: "variable.parameter.function-call",
|
||||
},
|
||||
{
|
||||
foreground: "#f07178",
|
||||
token: "variable.member",
|
||||
},
|
||||
{
|
||||
fontStyle: "italic",
|
||||
foreground: "#39bae6",
|
||||
token: "variable.language",
|
||||
},
|
||||
{
|
||||
foreground: "#ff8f40",
|
||||
token: "storage",
|
||||
},
|
||||
{
|
||||
foreground: "#ff8f40",
|
||||
token: "keyword",
|
||||
},
|
||||
{
|
||||
foreground: "#f29668",
|
||||
token: "keyword.operator",
|
||||
},
|
||||
{
|
||||
foreground: "#bfbdb6b3",
|
||||
token: "punctuation.separator",
|
||||
},
|
||||
{
|
||||
foreground: "#bfbdb6b3",
|
||||
token: "punctuation.terminator",
|
||||
},
|
||||
{
|
||||
foreground: "#bfbdb6",
|
||||
token: "punctuation.section",
|
||||
},
|
||||
{
|
||||
foreground: "#f29668",
|
||||
token: "punctuation.accessor",
|
||||
},
|
||||
{
|
||||
foreground: "#ff8f40",
|
||||
token: "punctuation.definition.template-expression",
|
||||
},
|
||||
{
|
||||
foreground: "#ff8f40",
|
||||
token: "punctuation.section.embedded",
|
||||
},
|
||||
{
|
||||
foreground: "#bfbdb6",
|
||||
token: "meta.embedded",
|
||||
},
|
||||
{
|
||||
foreground: "#59c2ff",
|
||||
token: "source.java storage.type",
|
||||
},
|
||||
{
|
||||
foreground: "#59c2ff",
|
||||
token: "source.haskell storage.type",
|
||||
},
|
||||
{
|
||||
foreground: "#59c2ff",
|
||||
token: "source.c storage.type",
|
||||
},
|
||||
{
|
||||
foreground: "#39bae6",
|
||||
token: "entity.other.inherited-class",
|
||||
},
|
||||
{
|
||||
foreground: "#ff8f40",
|
||||
token: "storage.type.function",
|
||||
},
|
||||
{
|
||||
foreground: "#39bae6",
|
||||
token: "source.java storage.type.primitive",
|
||||
},
|
||||
{
|
||||
foreground: "#ffb454",
|
||||
token: "entity.name.function",
|
||||
},
|
||||
{
|
||||
foreground: "#d2a6ff",
|
||||
token: "variable.parameter",
|
||||
},
|
||||
{
|
||||
foreground: "#d2a6ff",
|
||||
token: "meta.parameter",
|
||||
},
|
||||
{
|
||||
foreground: "#ffb454",
|
||||
token: "variable.function",
|
||||
},
|
||||
{
|
||||
foreground: "#ffb454",
|
||||
token: "variable.annotation",
|
||||
},
|
||||
{
|
||||
foreground: "#ffb454",
|
||||
token: "meta.function-call.generic",
|
||||
},
|
||||
{
|
||||
foreground: "#ffb454",
|
||||
token: "support.function.go",
|
||||
},
|
||||
{
|
||||
foreground: "#f07178",
|
||||
token: "support.function",
|
||||
},
|
||||
{
|
||||
foreground: "#f07178",
|
||||
token: "support.macro",
|
||||
},
|
||||
{
|
||||
foreground: "#aad94c",
|
||||
token: "entity.name.import",
|
||||
},
|
||||
{
|
||||
foreground: "#aad94c",
|
||||
token: "entity.name.package",
|
||||
},
|
||||
{
|
||||
foreground: "#59c2ff",
|
||||
token: "entity.name",
|
||||
},
|
||||
{
|
||||
foreground: "#39bae6",
|
||||
token: "entity.name.tag",
|
||||
},
|
||||
{
|
||||
foreground: "#39bae6",
|
||||
token: "meta.tag.sgml",
|
||||
},
|
||||
{
|
||||
foreground: "#59c2ff",
|
||||
token: "support.class.component",
|
||||
},
|
||||
{
|
||||
foreground: "#39bae680",
|
||||
token: "punctuation.definition.tag.end",
|
||||
},
|
||||
{
|
||||
foreground: "#39bae680",
|
||||
token: "punctuation.definition.tag.begin",
|
||||
},
|
||||
{
|
||||
foreground: "#39bae680",
|
||||
token: "punctuation.definition.tag",
|
||||
},
|
||||
{
|
||||
foreground: "#ffb454",
|
||||
token: "entity.other.attribute-name",
|
||||
},
|
||||
{
|
||||
fontStyle: "italic",
|
||||
foreground: "#f29668",
|
||||
token: "support.constant",
|
||||
},
|
||||
{
|
||||
foreground: "#39bae6",
|
||||
token: "support.type",
|
||||
},
|
||||
{
|
||||
foreground: "#39bae6",
|
||||
token: "support.class",
|
||||
},
|
||||
{
|
||||
foreground: "#39bae6",
|
||||
token: "source.go storage.type",
|
||||
},
|
||||
{
|
||||
foreground: "#e6b673",
|
||||
token: "meta.decorator variable.other",
|
||||
},
|
||||
{
|
||||
foreground: "#e6b673",
|
||||
token: "meta.decorator punctuation.decorator",
|
||||
},
|
||||
{
|
||||
foreground: "#e6b673",
|
||||
token: "storage.type.annotation",
|
||||
},
|
||||
{
|
||||
foreground: "#d95757",
|
||||
token: "invalid",
|
||||
},
|
||||
{
|
||||
foreground: "#c594c5",
|
||||
token: "meta.diff",
|
||||
},
|
||||
{
|
||||
foreground: "#c594c5",
|
||||
token: "meta.diff.header",
|
||||
},
|
||||
{
|
||||
foreground: "#ffb454",
|
||||
token: "source.ruby variable.other.readwrite",
|
||||
},
|
||||
{
|
||||
foreground: "#59c2ff",
|
||||
token: "source.css entity.name.tag",
|
||||
},
|
||||
{
|
||||
foreground: "#59c2ff",
|
||||
token: "source.sass entity.name.tag",
|
||||
},
|
||||
{
|
||||
foreground: "#59c2ff",
|
||||
token: "source.scss entity.name.tag",
|
||||
},
|
||||
{
|
||||
foreground: "#59c2ff",
|
||||
token: "source.less entity.name.tag",
|
||||
},
|
||||
{
|
||||
foreground: "#59c2ff",
|
||||
token: "source.stylus entity.name.tag",
|
||||
},
|
||||
{
|
||||
foreground: "#acb6bf8c",
|
||||
token: "source.css support.type",
|
||||
},
|
||||
{
|
||||
foreground: "#acb6bf8c",
|
||||
token: "source.sass support.type",
|
||||
},
|
||||
{
|
||||
foreground: "#acb6bf8c",
|
||||
token: "source.scss support.type",
|
||||
},
|
||||
{
|
||||
foreground: "#acb6bf8c",
|
||||
token: "source.less support.type",
|
||||
},
|
||||
{
|
||||
foreground: "#acb6bf8c",
|
||||
token: "source.stylus support.type",
|
||||
},
|
||||
{
|
||||
fontStyle: "normal",
|
||||
foreground: "#39bae6",
|
||||
token: "support.type.property-name",
|
||||
},
|
||||
{
|
||||
foreground: "#acb6bf8c",
|
||||
token: "constant.numeric.line-number.find-in-files - match",
|
||||
},
|
||||
{
|
||||
foreground: "#ff8f40",
|
||||
token: "constant.numeric.line-number.match",
|
||||
},
|
||||
{
|
||||
foreground: "#aad94c",
|
||||
token: "entity.name.filename.find-in-files",
|
||||
},
|
||||
{
|
||||
foreground: "#d95757",
|
||||
token: "message.error",
|
||||
},
|
||||
{
|
||||
fontStyle: "bold",
|
||||
foreground: "#aad94c",
|
||||
token: "markup.heading",
|
||||
},
|
||||
{
|
||||
fontStyle: "bold",
|
||||
foreground: "#aad94c",
|
||||
token: "markup.heading entity.name",
|
||||
},
|
||||
{
|
||||
foreground: "#39bae6",
|
||||
token: "markup.underline.link",
|
||||
},
|
||||
{
|
||||
foreground: "#39bae6",
|
||||
token: "string.other.link",
|
||||
},
|
||||
{
|
||||
fontStyle: "italic",
|
||||
foreground: "#f07178",
|
||||
token: "markup.italic",
|
||||
},
|
||||
{
|
||||
fontStyle: "bold",
|
||||
foreground: "#f07178",
|
||||
token: "markup.bold",
|
||||
},
|
||||
{
|
||||
fontStyle: "bold italic",
|
||||
token: "markup.italic markup.bold",
|
||||
},
|
||||
{
|
||||
fontStyle: "bold italic",
|
||||
token: "markup.bold markup.italic",
|
||||
},
|
||||
{
|
||||
background: "#bfbdb605",
|
||||
token: "markup.raw",
|
||||
},
|
||||
{
|
||||
background: "#bfbdb60f",
|
||||
token: "markup.raw.inline",
|
||||
},
|
||||
{
|
||||
fontStyle: "bold",
|
||||
background: "#bfbdb60f",
|
||||
foreground: "#acb6bf8c",
|
||||
token: "meta.separator",
|
||||
},
|
||||
{
|
||||
foreground: "#95e6cb",
|
||||
fontStyle: "italic",
|
||||
token: "markup.quote",
|
||||
},
|
||||
{
|
||||
foreground: "#ffb454",
|
||||
token: "markup.list punctuation.definition.list.begin",
|
||||
},
|
||||
{
|
||||
foreground: "#7fd962",
|
||||
token: "markup.inserted",
|
||||
},
|
||||
{
|
||||
foreground: "#73b8ff",
|
||||
token: "markup.changed",
|
||||
},
|
||||
{
|
||||
foreground: "#f26d78",
|
||||
token: "markup.deleted",
|
||||
},
|
||||
{
|
||||
foreground: "#e6b673",
|
||||
token: "markup.strike",
|
||||
},
|
||||
{
|
||||
background: "#bfbdb60f",
|
||||
foreground: "#39bae6",
|
||||
token: "markup.table",
|
||||
},
|
||||
{
|
||||
foreground: "#f29668",
|
||||
token: "text.html.markdown markup.inline.raw",
|
||||
},
|
||||
{
|
||||
background: "#acb6bf8c",
|
||||
foreground: "#acb6bf8c",
|
||||
token: "text.html.markdown meta.dummy.line-break",
|
||||
},
|
||||
{
|
||||
background: "#bfbdb6",
|
||||
foreground: "#acb6bf8c",
|
||||
token: "punctuation.definition.markdown",
|
||||
},
|
||||
// Manual changes.
|
||||
{
|
||||
foreground: "#fa8d3e",
|
||||
token: "number",
|
||||
27
playground/src/Editor/RepoButton.tsx
Normal file
27
playground/src/Editor/RepoButton.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
export default function RepoButton() {
|
||||
return (
|
||||
<a
|
||||
className={"hover:text-ayu-accent/70 text-ayu-accent"}
|
||||
href={"https://github.com/charliermarsh/ruff"}
|
||||
target={"_blank"}
|
||||
rel={"noreferrer"}
|
||||
>
|
||||
<svg
|
||||
xmlns={"http://www.w3.org/2000/svg"}
|
||||
width={"24"}
|
||||
height={"24"}
|
||||
viewBox={"0 0 16 16"}
|
||||
fill={"none"}
|
||||
>
|
||||
<path
|
||||
fillRule={"evenodd"}
|
||||
clipRule={"evenodd"}
|
||||
d={
|
||||
"M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z"
|
||||
}
|
||||
fill={"currentColor"}
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
@@ -5,14 +5,17 @@
|
||||
import Editor, { useMonaco } from "@monaco-editor/react";
|
||||
import { useCallback, useEffect } from "react";
|
||||
import schema from "../../../ruff.schema.json";
|
||||
import { Theme } from "./theme";
|
||||
|
||||
export default function SettingsEditor({
|
||||
visible,
|
||||
source,
|
||||
theme,
|
||||
onChange,
|
||||
}: {
|
||||
visible: boolean;
|
||||
source: string;
|
||||
theme: Theme;
|
||||
onChange: (source: string) => void;
|
||||
}) {
|
||||
const monaco = useMonaco();
|
||||
@@ -33,7 +36,7 @@ export default function SettingsEditor({
|
||||
(value: string | undefined) => {
|
||||
onChange(value ?? "");
|
||||
},
|
||||
[onChange]
|
||||
[onChange],
|
||||
);
|
||||
return (
|
||||
<Editor
|
||||
@@ -47,7 +50,7 @@ export default function SettingsEditor({
|
||||
wrapperProps={visible ? {} : { style: { display: "none" } }}
|
||||
language={"json"}
|
||||
value={source}
|
||||
theme={"Ayu-Light"}
|
||||
theme={theme === "light" ? "Ayu-Light" : "Ayu-Dark"}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -13,7 +13,7 @@ export default function ShareButton({ onShare }: { onShare?: () => void }) {
|
||||
return copied ? (
|
||||
<button
|
||||
type="button"
|
||||
className="relative flex-none rounded-md text-sm font-semibold leading-6 py-1.5 px-3 cursor-auto text-ayu shadow-copied dark:bg-ayu/10"
|
||||
className="relative flex-none rounded-md text-sm font-semibold leading-6 py-1.5 px-3 cursor-auto text-ayu-accent shadow-copied dark:bg-ayu-accent/10"
|
||||
>
|
||||
<span
|
||||
className="absolute inset-0 flex items-center justify-center invisible"
|
||||
@@ -28,7 +28,7 @@ export default function ShareButton({ onShare }: { onShare?: () => void }) {
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
className="relative flex-none rounded-md text-sm font-semibold leading-6 py-1.5 px-3 enabled:hover:bg-ayu/80 bg-ayu text-white shadow-sm dark:shadow-highlight/20 disabled:opacity-50"
|
||||
className="relative flex-none rounded-md text-sm font-semibold leading-6 py-1.5 px-3 enabled:hover:bg-ayu-accent/70 bg-ayu-accent text-white shadow-sm dark:shadow-highlight/20 disabled:opacity-50"
|
||||
disabled={!onShare || copied}
|
||||
onClick={
|
||||
onShare
|
||||
|
||||
@@ -6,18 +6,19 @@ import Editor, { useMonaco } from "@monaco-editor/react";
|
||||
import { MarkerSeverity, MarkerTag } from "monaco-editor";
|
||||
import { useCallback, useEffect } from "react";
|
||||
import { Check } from "../pkg";
|
||||
|
||||
export type Mode = "JSON" | "Python";
|
||||
import { Theme } from "./theme";
|
||||
|
||||
export default function SourceEditor({
|
||||
visible,
|
||||
source,
|
||||
theme,
|
||||
checks,
|
||||
onChange,
|
||||
}: {
|
||||
visible: boolean;
|
||||
source: string;
|
||||
checks: Check[];
|
||||
theme: Theme;
|
||||
onChange: (pythonSource: string) => void;
|
||||
}) {
|
||||
const monaco = useMonaco();
|
||||
@@ -43,7 +44,7 @@ export default function SourceEditor({
|
||||
check.code === "F401" || check.code === "F841"
|
||||
? [MarkerTag.Unnecessary]
|
||||
: [],
|
||||
}))
|
||||
})),
|
||||
);
|
||||
|
||||
const codeActionProvider = monaco?.languages.registerCodeActionProvider(
|
||||
@@ -55,7 +56,9 @@ export default function SourceEditor({
|
||||
.filter((check) => position.startLineNumber === check.location.row)
|
||||
.filter((check) => check.fix)
|
||||
.map((check) => ({
|
||||
title: `Fix ${check.code}`,
|
||||
title: check.fix
|
||||
? `${check.code}: ${check.fix.message}` ?? `Fix ${check.code}`
|
||||
: "Autofix",
|
||||
id: `fix-${check.code}`,
|
||||
kind: "quickfix",
|
||||
edit: check.fix
|
||||
@@ -80,7 +83,7 @@ export default function SourceEditor({
|
||||
}));
|
||||
return { actions, dispose: () => {} };
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
return () => {
|
||||
@@ -92,7 +95,7 @@ export default function SourceEditor({
|
||||
(value: string | undefined) => {
|
||||
onChange(value ?? "");
|
||||
},
|
||||
[onChange]
|
||||
[onChange],
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -104,9 +107,9 @@ export default function SourceEditor({
|
||||
roundedSelection: false,
|
||||
scrollBeyondLastLine: false,
|
||||
}}
|
||||
wrapperProps={visible ? {} : { style: { display: "none" } }}
|
||||
theme={"Ayu-Light"}
|
||||
language={"python"}
|
||||
wrapperProps={visible ? {} : { style: { display: "none" } }}
|
||||
theme={theme === "light" ? "Ayu-Light" : "Ayu-Dark"}
|
||||
value={source}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
|
||||
49
playground/src/Editor/ThemeButton.tsx
Normal file
49
playground/src/Editor/ThemeButton.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Button to toggle between light and dark mode themes.
|
||||
*/
|
||||
import { Theme } from "./theme";
|
||||
|
||||
export default function ThemeButton({
|
||||
theme,
|
||||
onChange,
|
||||
}: {
|
||||
theme: Theme;
|
||||
onChange: (theme: Theme) => void;
|
||||
}) {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className="ml-4 sm:ml-0 ring-1 ring-gray-900/5 shadow-sm hover:bg-gray-50 dark:ring-0 dark:bg-gray-800 dark:hover:bg-gray-700 dark:shadow-highlight/4 group focus:outline-none focus-visible:ring-2 rounded-md focus-visible:ring-ayu-accent dark:focus-visible:ring-2 dark:focus-visible:ring-gray-400"
|
||||
onClick={() => onChange(theme === "light" ? "dark" : "light")}
|
||||
>
|
||||
<span className="sr-only">
|
||||
<span className="dark:hidden">Switch to dark theme</span>
|
||||
<span className="hidden dark:inline">Switch to light theme</span>
|
||||
</span>
|
||||
<svg
|
||||
width="36"
|
||||
height="36"
|
||||
viewBox="-6 -6 36 36"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="stroke-ayu-accent fill-ayu-accent/10 group-hover:stroke-ayu-accent/80 dark:stroke-gray-400 dark:fill-gray-400/20 dark:group-hover:stroke-gray-300"
|
||||
>
|
||||
<g className="dark:opacity-0">
|
||||
<path d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"></path>
|
||||
<path
|
||||
d="M12 4v.01M17.66 6.345l-.007.007M20.005 12.005h-.01M17.66 17.665l-.007-.007M12 20.01V20M6.34 17.665l.007-.007M3.995 12.005h.01M6.34 6.344l.007.007"
|
||||
fill="none"
|
||||
/>
|
||||
</g>
|
||||
<g className="opacity-0 dark:opacity-100">
|
||||
<path d="M16 12a4 4 0 1 1-8 0 4 4 0 0 1 8 0Z" />
|
||||
<path
|
||||
d="M12 3v1M18.66 5.345l-.828.828M21.005 12.005h-1M18.66 18.665l-.828-.828M12 21.01V20M5.34 18.666l.835-.836M2.995 12.005h1.01M5.34 5.344l.835.836"
|
||||
fill="none"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -17,7 +17,7 @@ export default function VersionTag({ children }: { children: ReactNode }) {
|
||||
"items-center",
|
||||
"dark:bg-gray-800",
|
||||
"dark:text-gray-400",
|
||||
"dark:shadow-highlight/4"
|
||||
"dark:shadow-highlight/4",
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
import lzstring from "lz-string";
|
||||
import { OptionGroup } from "../ruff_options";
|
||||
|
||||
export type Config = { [K: string]: any };
|
||||
|
||||
/**
|
||||
* Parse an encoded value from the options export.
|
||||
*
|
||||
* TODO(charlie): Use JSON for the default values.
|
||||
*/
|
||||
function parse(value: any): any {
|
||||
if (value == "None") {
|
||||
return null;
|
||||
}
|
||||
return JSON.parse(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* The default configuration for the playground.
|
||||
*/
|
||||
export function defaultConfig(availableOptions: OptionGroup[]): Config {
|
||||
const config: Config = {};
|
||||
for (const group of availableOptions) {
|
||||
if (group.name == "globals") {
|
||||
for (const field of group.fields) {
|
||||
config[field.name] = parse(field.default);
|
||||
}
|
||||
} else {
|
||||
config[group.name] = {};
|
||||
for (const field of group.fields) {
|
||||
config[group.name][field.name] = parse(field.default);
|
||||
}
|
||||
}
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist the configuration to a URL.
|
||||
*/
|
||||
export function persist(configSource: string, pythonSource: string) {
|
||||
window.location.hash = lzstring.compressToEncodedURIComponent(
|
||||
configSource + "$$$" + pythonSource
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the configuration from a URL.
|
||||
*/
|
||||
export function restore(): [string, string] | null {
|
||||
const value = lzstring.decompressFromEncodedURIComponent(
|
||||
window.location.hash.slice(1)
|
||||
);
|
||||
|
||||
if (value) {
|
||||
const parts = value.split("$$$");
|
||||
const configSource = parts[0];
|
||||
const pythonSource = parts[1];
|
||||
return [configSource, pythonSource];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
50
playground/src/Editor/settings.ts
Normal file
50
playground/src/Editor/settings.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import lzstring from "lz-string";
|
||||
|
||||
export type Settings = { [K: string]: any };
|
||||
|
||||
/**
|
||||
* Stringify a settings object to JSON.
|
||||
*/
|
||||
export function stringify(settings: Settings): string {
|
||||
return JSON.stringify(
|
||||
settings,
|
||||
(k, v) => {
|
||||
if (v instanceof Map) {
|
||||
return Object.fromEntries(v.entries());
|
||||
} else {
|
||||
return v;
|
||||
}
|
||||
},
|
||||
2,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist the configuration to a URL.
|
||||
*/
|
||||
export async function persist(settingsSource: string, pythonSource: string) {
|
||||
const hash = lzstring.compressToEncodedURIComponent(
|
||||
settingsSource + "$$$" + pythonSource,
|
||||
);
|
||||
await navigator.clipboard.writeText(
|
||||
window.location.href.split("#")[0] + "#" + hash,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the configuration from a URL.
|
||||
*/
|
||||
export function restore(): [string, string] | null {
|
||||
const value = lzstring.decompressFromEncodedURIComponent(
|
||||
window.location.hash.slice(1),
|
||||
);
|
||||
|
||||
if (value) {
|
||||
const parts = value.split("$$$");
|
||||
const settingsSource = parts[0];
|
||||
const pythonSource = parts[1];
|
||||
return [settingsSource, pythonSource];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
35
playground/src/Editor/theme.ts
Normal file
35
playground/src/Editor/theme.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Light and dark mode theming.
|
||||
*/
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
export type Theme = "dark" | "light";
|
||||
|
||||
export function useTheme(): [Theme, (theme: Theme) => void] {
|
||||
const [localTheme, setLocalTheme] = useState<Theme>("light");
|
||||
|
||||
const setTheme = (mode: Theme) => {
|
||||
if (mode === "dark") {
|
||||
document.body.classList.add("dark");
|
||||
} else {
|
||||
document.body.classList.remove("dark");
|
||||
}
|
||||
localStorage.setItem("theme", mode);
|
||||
setLocalTheme(mode);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const initialTheme = localStorage.getItem("theme");
|
||||
if (initialTheme === "dark") {
|
||||
setTheme("dark");
|
||||
} else if (initialTheme === "light") {
|
||||
setTheme("light");
|
||||
} else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
||||
setTheme("dark");
|
||||
} else {
|
||||
setTheme("light");
|
||||
}
|
||||
}, []);
|
||||
|
||||
return [localTheme, setTheme];
|
||||
}
|
||||
7
playground/src/Editor/utils.ts
Normal file
7
playground/src/Editor/utils.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export async function copyTextToClipboard(text: string) {
|
||||
if ("clipboard" in navigator) {
|
||||
return await navigator.clipboard.writeText(text);
|
||||
} else {
|
||||
return document.execCommand("copy", true, text);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,3 @@
|
||||
import { defaultConfig } from "./Editor/config";
|
||||
import { AVAILABLE_OPTIONS } from "./ruff_options";
|
||||
|
||||
export const DEFAULT_PYTHON_SOURCE =
|
||||
"import os\n" +
|
||||
"\n" +
|
||||
@@ -32,9 +29,3 @@ export const DEFAULT_PYTHON_SOURCE =
|
||||
"# 13\n" +
|
||||
"# 21\n" +
|
||||
"# 34\n";
|
||||
|
||||
export const DEFAULT_CONFIG_SOURCE = JSON.stringify(
|
||||
defaultConfig(AVAILABLE_OPTIONS),
|
||||
null,
|
||||
2
|
||||
);
|
||||
|
||||
@@ -6,5 +6,5 @@ import "./index.css";
|
||||
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
|
||||
<React.StrictMode>
|
||||
<Editor />
|
||||
</React.StrictMode>
|
||||
</React.StrictMode>,
|
||||
);
|
||||
|
||||
@@ -1,244 +0,0 @@
|
||||
|
||||
// This file is auto-generated by `cargo dev generate-playground-options`.
|
||||
export interface OptionGroup {
|
||||
name: string;
|
||||
fields: {
|
||||
name: string;
|
||||
default: string;
|
||||
type: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
export const AVAILABLE_OPTIONS: OptionGroup[] = [
|
||||
{"name": "globals", "fields": [
|
||||
{
|
||||
"name": "allowed-confusables",
|
||||
"default": '[]',
|
||||
"type": 'Vec<char>',
|
||||
},
|
||||
{
|
||||
"name": "dummy-variable-rgx",
|
||||
"default": '"^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"',
|
||||
"type": 'Regex',
|
||||
},
|
||||
{
|
||||
"name": "extend-ignore",
|
||||
"default": '[]',
|
||||
"type": 'Vec<CheckCodePrefix>',
|
||||
},
|
||||
{
|
||||
"name": "extend-select",
|
||||
"default": '[]',
|
||||
"type": 'Vec<CheckCodePrefix>',
|
||||
},
|
||||
{
|
||||
"name": "external",
|
||||
"default": '[]',
|
||||
"type": 'Vec<String>',
|
||||
},
|
||||
{
|
||||
"name": "fix-only",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
{
|
||||
"name": "ignore",
|
||||
"default": '[]',
|
||||
"type": 'Vec<CheckCodePrefix>',
|
||||
},
|
||||
{
|
||||
"name": "line-length",
|
||||
"default": '88',
|
||||
"type": 'usize',
|
||||
},
|
||||
{
|
||||
"name": "required-version",
|
||||
"default": 'None',
|
||||
"type": 'String',
|
||||
},
|
||||
{
|
||||
"name": "select",
|
||||
"default": '["E", "F"]',
|
||||
"type": 'Vec<CheckCodePrefix>',
|
||||
},
|
||||
{
|
||||
"name": "target-version",
|
||||
"default": '"py310"',
|
||||
"type": 'PythonVersion',
|
||||
},
|
||||
{
|
||||
"name": "unfixable",
|
||||
"default": '[]',
|
||||
"type": 'Vec<CheckCodePrefix>',
|
||||
},
|
||||
{
|
||||
"name": "update-check",
|
||||
"default": 'true',
|
||||
"type": 'bool',
|
||||
},
|
||||
]},
|
||||
{"name": "flake8-annotations", "fields": [
|
||||
{
|
||||
"name": "allow-star-arg-any",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
{
|
||||
"name": "mypy-init-return",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
{
|
||||
"name": "suppress-dummy-args",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
{
|
||||
"name": "suppress-none-returning",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
]},
|
||||
{"name": "flake8-bugbear", "fields": [
|
||||
{
|
||||
"name": "extend-immutable-calls",
|
||||
"default": '[]',
|
||||
"type": 'Vec<String>',
|
||||
},
|
||||
]},
|
||||
{"name": "flake8-errmsg", "fields": [
|
||||
{
|
||||
"name": "max-string-length",
|
||||
"default": '0',
|
||||
"type": 'usize',
|
||||
},
|
||||
]},
|
||||
{"name": "flake8-import-conventions", "fields": [
|
||||
{
|
||||
"name": "aliases",
|
||||
"default": '{"altair": "alt", "matplotlib.pyplot": "plt", "numpy": "np", "pandas": "pd", "seaborn": "sns"}',
|
||||
"type": 'FxHashMap<String, String>',
|
||||
},
|
||||
{
|
||||
"name": "extend-aliases",
|
||||
"default": '{}',
|
||||
"type": 'FxHashMap<String, String>',
|
||||
},
|
||||
]},
|
||||
{"name": "flake8-quotes", "fields": [
|
||||
{
|
||||
"name": "avoid-escape",
|
||||
"default": 'true',
|
||||
"type": 'bool',
|
||||
},
|
||||
{
|
||||
"name": "docstring-quotes",
|
||||
"default": '"double"',
|
||||
"type": 'Quote',
|
||||
},
|
||||
{
|
||||
"name": "inline-quotes",
|
||||
"default": '"double"',
|
||||
"type": 'Quote',
|
||||
},
|
||||
{
|
||||
"name": "multiline-quotes",
|
||||
"default": '"double"',
|
||||
"type": 'Quote',
|
||||
},
|
||||
]},
|
||||
{"name": "flake8-tidy-imports", "fields": [
|
||||
{
|
||||
"name": "ban-relative-imports",
|
||||
"default": '"parents"',
|
||||
"type": 'Strictness',
|
||||
},
|
||||
]},
|
||||
{"name": "flake8-unused-arguments", "fields": [
|
||||
{
|
||||
"name": "ignore-variadic-names",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
]},
|
||||
{"name": "isort", "fields": [
|
||||
{
|
||||
"name": "combine-as-imports",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
{
|
||||
"name": "extra-standard-library",
|
||||
"default": '[]',
|
||||
"type": 'Vec<String>',
|
||||
},
|
||||
{
|
||||
"name": "force-single-line",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
{
|
||||
"name": "force-wrap-aliases",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
{
|
||||
"name": "known-first-party",
|
||||
"default": '[]',
|
||||
"type": 'Vec<String>',
|
||||
},
|
||||
{
|
||||
"name": "known-third-party",
|
||||
"default": '[]',
|
||||
"type": 'Vec<String>',
|
||||
},
|
||||
{
|
||||
"name": "single-line-exclusions",
|
||||
"default": '[]',
|
||||
"type": 'Vec<String>',
|
||||
},
|
||||
{
|
||||
"name": "split-on-trailing-comma",
|
||||
"default": 'true',
|
||||
"type": 'bool',
|
||||
},
|
||||
]},
|
||||
{"name": "mccabe", "fields": [
|
||||
{
|
||||
"name": "max-complexity",
|
||||
"default": '10',
|
||||
"type": 'usize',
|
||||
},
|
||||
]},
|
||||
{"name": "pep8-naming", "fields": [
|
||||
{
|
||||
"name": "classmethod-decorators",
|
||||
"default": '["classmethod"]',
|
||||
"type": 'Vec<String>',
|
||||
},
|
||||
{
|
||||
"name": "ignore-names",
|
||||
"default": '["setUp", "tearDown", "setUpClass", "tearDownClass", "setUpModule", "tearDownModule", "asyncSetUp", "asyncTearDown", "setUpTestData", "failureException", "longMessage", "maxDiff"]',
|
||||
"type": 'Vec<String>',
|
||||
},
|
||||
{
|
||||
"name": "staticmethod-decorators",
|
||||
"default": '["staticmethod"]',
|
||||
"type": 'Vec<String>',
|
||||
},
|
||||
]},
|
||||
{"name": "pydocstyle", "fields": [
|
||||
{
|
||||
"name": "convention",
|
||||
"default": 'None',
|
||||
"type": 'Convention',
|
||||
},
|
||||
]},
|
||||
{"name": "pyupgrade", "fields": [
|
||||
{
|
||||
"name": "keep-runtime-typing",
|
||||
"default": 'false',
|
||||
"type": 'bool',
|
||||
},
|
||||
]},
|
||||
];
|
||||
2
playground/src/third-party.d.ts
vendored
2
playground/src/third-party.d.ts
vendored
@@ -1,6 +1,6 @@
|
||||
declare module "lz-string" {
|
||||
function decompressFromEncodedURIComponent(
|
||||
input: string | null
|
||||
input: string | null,
|
||||
): string | null;
|
||||
function compressToEncodedURIComponent(input: string | null): string;
|
||||
}
|
||||
|
||||
@@ -2,11 +2,16 @@
|
||||
const defaultTheme = require("tailwindcss/defaultTheme");
|
||||
|
||||
module.exports = {
|
||||
darkMode: "class",
|
||||
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
ayu: "#f07171",
|
||||
"ayu-accent": "#fa8d3e",
|
||||
"ayu-background": {
|
||||
DEFAULT: "#f8f9fa",
|
||||
dark: "#0b0e14",
|
||||
},
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ["Inter var", ...defaultTheme.fontFamily.sans],
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
[build-system]
|
||||
requires = ["maturin>=0.14,<0.15"]
|
||||
build-backend = "maturin"
|
||||
|
||||
[project]
|
||||
name = "ruff"
|
||||
version = "0.0.210"
|
||||
description = "An extremely fast Python linter, written in Rust."
|
||||
authors = [
|
||||
{ name = "Charlie Marsh", email = "charlie.r.marsh@gmail.com" },
|
||||
]
|
||||
maintainers = [
|
||||
{ name = "Charlie Marsh", email = "charlie.r.marsh@gmail.com" },
|
||||
]
|
||||
requires-python = ">=3.7"
|
||||
license = { file = "LICENSE" }
|
||||
keywords = ["automation", "flake8", "pycodestyle", "pyflakes", "pylint", "clippy"]
|
||||
classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
@@ -17,30 +31,8 @@ classifiers = [
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
"Topic :: Software Development :: Quality Assurance",
|
||||
]
|
||||
author = "Charlie Marsh"
|
||||
author_email = "charlie.r.marsh@gmail.com"
|
||||
description = "An extremely fast Python linter, written in Rust."
|
||||
requires-python = ">=3.7"
|
||||
|
||||
[project.urls]
|
||||
repository = "https://github.com/charliermarsh/ruff"
|
||||
|
||||
[build-system]
|
||||
requires = ["maturin>=0.14,<0.15"]
|
||||
build-backend = "maturin"
|
||||
urls = { repository = "https://github.com/charliermarsh/ruff-lsp" }
|
||||
|
||||
[tool.maturin]
|
||||
bindings = "bin"
|
||||
strip = true
|
||||
|
||||
[tool.ruff]
|
||||
update-check = true
|
||||
|
||||
[tool.ruff.isort]
|
||||
force-wrap-aliases = true
|
||||
combine-as-imports = true
|
||||
force-single-line = true
|
||||
single-line-exclusions = ["os", "logging.handlers"]
|
||||
|
||||
[tool.ruff.pydocstyle]
|
||||
convention = "google"
|
||||
|
||||
@@ -51,3 +51,12 @@ secret == "s3cr3t"
|
||||
token == "s3cr3t"
|
||||
secrete == "s3cr3t"
|
||||
password == safe == "s3cr3t"
|
||||
|
||||
if token == "1\n2":
|
||||
pass
|
||||
|
||||
if token == "3\t4":
|
||||
pass
|
||||
|
||||
if token == "5\r6":
|
||||
pass
|
||||
|
||||
36
resources/test/fixtures/flake8_implicit_str_concat/ISC.py
vendored
Normal file
36
resources/test/fixtures/flake8_implicit_str_concat/ISC.py
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
_ = "a" "b" "c"
|
||||
|
||||
_ = "abc" + "def"
|
||||
|
||||
_ = "abc" \
|
||||
"def"
|
||||
|
||||
_ = (
|
||||
"abc" +
|
||||
"def"
|
||||
)
|
||||
|
||||
_ = (
|
||||
f"abc" +
|
||||
"def"
|
||||
)
|
||||
|
||||
_ = (
|
||||
b"abc" +
|
||||
b"def"
|
||||
)
|
||||
|
||||
_ = (
|
||||
"abc"
|
||||
"def"
|
||||
)
|
||||
|
||||
_ = (
|
||||
f"abc"
|
||||
"def"
|
||||
)
|
||||
|
||||
_ = (
|
||||
b"abc"
|
||||
b"def"
|
||||
)
|
||||
120
resources/test/fixtures/flake8_pie/PIE790.py
vendored
Normal file
120
resources/test/fixtures/flake8_pie/PIE790.py
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
class Foo:
|
||||
"""buzz"""
|
||||
|
||||
pass # PIE790
|
||||
|
||||
|
||||
if foo:
|
||||
"""foo"""
|
||||
pass # PIE790
|
||||
|
||||
|
||||
def multi_statement() -> None:
|
||||
"""This is a function."""
|
||||
pass; print("hello")
|
||||
|
||||
|
||||
if foo:
|
||||
pass
|
||||
else:
|
||||
"""bar"""
|
||||
pass # PIE790
|
||||
|
||||
|
||||
while True:
|
||||
pass
|
||||
else:
|
||||
"""bar"""
|
||||
pass # PIE790
|
||||
|
||||
|
||||
for _ in range(10):
|
||||
pass
|
||||
else:
|
||||
"""bar"""
|
||||
pass # PIE790
|
||||
|
||||
|
||||
async for _ in range(10):
|
||||
pass
|
||||
else:
|
||||
"""bar"""
|
||||
pass # PIE790
|
||||
|
||||
|
||||
def foo() -> None:
|
||||
"""
|
||||
buzz
|
||||
"""
|
||||
|
||||
pass # PIE790
|
||||
|
||||
|
||||
async def foo():
|
||||
"""
|
||||
buzz
|
||||
"""
|
||||
|
||||
pass # PIE790
|
||||
|
||||
|
||||
try:
|
||||
"""
|
||||
buzz
|
||||
"""
|
||||
pass # PIE790
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
bar()
|
||||
except ValueError:
|
||||
"""bar"""
|
||||
pass # PIE790
|
||||
|
||||
|
||||
for _ in range(10):
|
||||
"""buzz"""
|
||||
pass # PIE790
|
||||
|
||||
async for _ in range(10):
|
||||
"""buzz"""
|
||||
pass # PIE790
|
||||
|
||||
while cond:
|
||||
"""buzz"""
|
||||
pass # PIE790
|
||||
|
||||
|
||||
with bar:
|
||||
"""buzz"""
|
||||
pass # PIE790
|
||||
|
||||
async with bar:
|
||||
"""buzz"""
|
||||
pass # PIE790
|
||||
|
||||
|
||||
class Foo:
|
||||
# bar
|
||||
pass
|
||||
|
||||
|
||||
if foo:
|
||||
# foo
|
||||
pass
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
foo()
|
||||
except NetworkError:
|
||||
pass
|
||||
|
||||
|
||||
def foo() -> None:
|
||||
pass
|
||||
33
resources/test/fixtures/flake8_pie/PIE794.py
vendored
Normal file
33
resources/test/fixtures/flake8_pie/PIE794.py
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
class Foo(BaseModel):
|
||||
name = StringField()
|
||||
# ....
|
||||
name = StringField() # PIE794
|
||||
|
||||
def remove(self) -> None:
|
||||
...
|
||||
|
||||
|
||||
class Foo(BaseModel):
|
||||
name: str = StringField()
|
||||
# ....
|
||||
name = StringField() # PIE794
|
||||
|
||||
def foo(self) -> None:
|
||||
...
|
||||
|
||||
|
||||
class User(BaseModel):
|
||||
bar: str = StringField()
|
||||
foo: bool = BooleanField()
|
||||
# ...
|
||||
bar = StringField() # PIE794
|
||||
|
||||
|
||||
class User(BaseModel):
|
||||
@property
|
||||
def buzz(self) -> str:
|
||||
...
|
||||
|
||||
@buzz.setter
|
||||
def buzz(self, value: str | int) -> None:
|
||||
...
|
||||
20
resources/test/fixtures/flake8_pie/PIE807.py
vendored
Normal file
20
resources/test/fixtures/flake8_pie/PIE807.py
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
@dataclass
|
||||
class Foo:
|
||||
foo: List[str] = field(default_factory=lambda: []) # PIE807
|
||||
|
||||
|
||||
class FooTable(BaseTable):
|
||||
bar = fields.ListField(default=lambda: []) # PIE807
|
||||
|
||||
|
||||
class FooTable(BaseTable):
|
||||
bar = fields.ListField(lambda: []) # PIE807
|
||||
|
||||
|
||||
@dataclass
|
||||
class Foo:
|
||||
foo: List[str] = field(default_factory=list)
|
||||
|
||||
|
||||
class FooTable(BaseTable):
|
||||
bar = fields.ListField(list)
|
||||
78
resources/test/fixtures/flake8_pytest_style/PT001.py
vendored
Normal file
78
resources/test/fixtures/flake8_pytest_style/PT001.py
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
import pytest
|
||||
from pytest import fixture
|
||||
from pytest import fixture as aliased
|
||||
|
||||
|
||||
# `import pytest`
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def no_parentheses():
|
||||
return 42
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def parentheses_no_params():
|
||||
return 42
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def parentheses_with_params():
|
||||
return 42
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
|
||||
)
|
||||
def parentheses_no_params_multiline():
|
||||
return 42
|
||||
|
||||
|
||||
# `from pytest import fixture`
|
||||
|
||||
|
||||
@fixture
|
||||
def imported_from_no_parentheses():
|
||||
return 42
|
||||
|
||||
|
||||
@fixture()
|
||||
def imported_from_parentheses_no_params():
|
||||
return 42
|
||||
|
||||
|
||||
@fixture(scope="module")
|
||||
def imported_from_parentheses_with_params():
|
||||
return 42
|
||||
|
||||
|
||||
@fixture(
|
||||
|
||||
)
|
||||
def imported_from_parentheses_no_params_multiline():
|
||||
return 42
|
||||
|
||||
|
||||
# `from pytest import fixture as aliased`
|
||||
|
||||
|
||||
@aliased
|
||||
def aliased_no_parentheses():
|
||||
return 42
|
||||
|
||||
|
||||
@aliased()
|
||||
def aliased_parentheses_no_params():
|
||||
return 42
|
||||
|
||||
|
||||
@aliased(scope="module")
|
||||
def aliased_parentheses_with_params():
|
||||
return 42
|
||||
|
||||
|
||||
@aliased(
|
||||
|
||||
)
|
||||
def aliased_parentheses_no_params_multiline():
|
||||
return 42
|
||||
21
resources/test/fixtures/flake8_pytest_style/PT002.py
vendored
Normal file
21
resources/test/fixtures/flake8_pytest_style/PT002.py
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def my_fixture(): # OK no args
|
||||
return 0
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def my_fixture(): # OK only kwargs
|
||||
return 0
|
||||
|
||||
|
||||
@pytest.fixture("module")
|
||||
def my_fixture(): # Error only args
|
||||
return 0
|
||||
|
||||
|
||||
@pytest.fixture("module", autouse=True)
|
||||
def my_fixture(): # Error mixed
|
||||
return 0
|
||||
16
resources/test/fixtures/flake8_pytest_style/PT003.py
vendored
Normal file
16
resources/test/fixtures/flake8_pytest_style/PT003.py
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def ok_no_scope():
|
||||
...
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def ok_other_scope():
|
||||
...
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def error():
|
||||
...
|
||||
58
resources/test/fixtures/flake8_pytest_style/PT004.py
vendored
Normal file
58
resources/test/fixtures/flake8_pytest_style/PT004.py
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
import abc
|
||||
from abc import abstractmethod
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def _patch_something(mocker): # OK simple
|
||||
mocker.patch("some.thing")
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def _patch_something(mocker): # OK with return
|
||||
if something:
|
||||
return
|
||||
mocker.patch("some.thing")
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def _activate_context(): # OK with yield
|
||||
with context:
|
||||
yield
|
||||
|
||||
|
||||
class BaseTest:
|
||||
@pytest.fixture()
|
||||
@abc.abstractmethod
|
||||
def my_fixture(): # OK abstract with import abc
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class BaseTest:
|
||||
@pytest.fixture()
|
||||
@abstractmethod
|
||||
def my_fixture(): # OK abstract with from import
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def my_fixture(): # OK ignoring yield from
|
||||
yield from some_generator()
|
||||
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def my_fixture(): # OK ignoring yield value
|
||||
yield 1
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def patch_something(mocker): # Error simple
|
||||
mocker.patch("some.thing")
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def activate_context(): # Error with yield
|
||||
with context:
|
||||
yield
|
||||
57
resources/test/fixtures/flake8_pytest_style/PT005.py
vendored
Normal file
57
resources/test/fixtures/flake8_pytest_style/PT005.py
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
import abc
|
||||
from abc import abstractmethod
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def my_fixture(mocker): # OK with return
|
||||
return 0
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def activate_context(): # OK with yield
|
||||
with get_context() as context:
|
||||
yield context
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def _any_fixture(mocker): # Ok nested function
|
||||
def nested_function():
|
||||
return 1
|
||||
|
||||
mocker.patch("...", nested_function)
|
||||
|
||||
|
||||
class BaseTest:
|
||||
@pytest.fixture()
|
||||
@abc.abstractmethod
|
||||
def _my_fixture(): # OK abstract with import abc
|
||||
return NotImplemented
|
||||
|
||||
|
||||
class BaseTest:
|
||||
@pytest.fixture()
|
||||
@abstractmethod
|
||||
def _my_fixture(): # OK abstract with from import
|
||||
return NotImplemented
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def _my_fixture(mocker): # Error with return
|
||||
return 0
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def _activate_context(): # Error with yield
|
||||
with get_context() as context:
|
||||
yield context
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def _activate_context(): # Error with conditional yield from
|
||||
if some_condition:
|
||||
with get_context() as context:
|
||||
yield context
|
||||
else:
|
||||
yield from other_context()
|
||||
51
resources/test/fixtures/flake8_pytest_style/PT006.py
vendored
Normal file
51
resources/test/fixtures/flake8_pytest_style/PT006.py
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.parametrize("param", [1, 2, 3])
|
||||
def test_always_ok(param):
|
||||
...
|
||||
|
||||
|
||||
@pytest.mark.parametrize("param1,param2", [(1, 2), (3, 4)])
|
||||
def test_csv(param1, param2):
|
||||
...
|
||||
|
||||
|
||||
@pytest.mark.parametrize(" param1, , param2 , ", [(1, 2), (3, 4)])
|
||||
def test_csv_with_whitespace(param1, param2):
|
||||
...
|
||||
|
||||
|
||||
@pytest.mark.parametrize("param1,param2", [(1, 2), (3, 4)])
|
||||
def test_csv_bad_quotes(param1, param2):
|
||||
...
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("param1", "param2"), [(1, 2), (3, 4)])
|
||||
def test_tuple(param1, param2):
|
||||
...
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("param1",), [1, 2, 3])
|
||||
def test_tuple_one_elem(param1, param2):
|
||||
...
|
||||
|
||||
|
||||
@pytest.mark.parametrize(["param1", "param2"], [(1, 2), (3, 4)])
|
||||
def test_list(param1, param2):
|
||||
...
|
||||
|
||||
|
||||
@pytest.mark.parametrize(["param1"], [1, 2, 3])
|
||||
def test_list_one_elem(param1, param2):
|
||||
...
|
||||
|
||||
|
||||
@pytest.mark.parametrize([some_expr, another_expr], [1, 2, 3])
|
||||
def test_list_expressions(param1, param2):
|
||||
...
|
||||
|
||||
|
||||
@pytest.mark.parametrize([some_expr, "param2"], [1, 2, 3])
|
||||
def test_list_mixed_expr_literal(param1, param2):
|
||||
...
|
||||
55
resources/test/fixtures/flake8_pytest_style/PT007.py
vendored
Normal file
55
resources/test/fixtures/flake8_pytest_style/PT007.py
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.parametrize("param", (1, 2))
|
||||
def test_tuple(param):
|
||||
...
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("param1", "param2"),
|
||||
(
|
||||
(1, 2),
|
||||
(3, 4),
|
||||
),
|
||||
)
|
||||
def test_tuple_of_tuples(param1, param2):
|
||||
...
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("param1", "param2"),
|
||||
(
|
||||
[1, 2],
|
||||
[3, 4],
|
||||
),
|
||||
)
|
||||
def test_tuple_of_lists(param1, param2):
|
||||
...
|
||||
|
||||
|
||||
@pytest.mark.parametrize("param", [1, 2])
|
||||
def test_list(param):
|
||||
...
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("param1", "param2"),
|
||||
[
|
||||
(1, 2),
|
||||
(3, 4),
|
||||
],
|
||||
)
|
||||
def test_list_of_tuples(param1, param2):
|
||||
...
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("param1", "param2"),
|
||||
[
|
||||
[1, 2],
|
||||
[3, 4],
|
||||
],
|
||||
)
|
||||
def test_list_of_lists(param1, param2):
|
||||
...
|
||||
48
resources/test/fixtures/flake8_pytest_style/PT008.py
vendored
Normal file
48
resources/test/fixtures/flake8_pytest_style/PT008.py
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
# OK
|
||||
|
||||
mocker.patch("module.name", not_lambda)
|
||||
module_mocker.patch("module.name", not_lambda)
|
||||
mocker.patch.object(obj, "attr", not_lambda)
|
||||
module_mocker.patch.object(obj, "attr", not_lambda)
|
||||
|
||||
mocker.patch("module.name", return_value=None)
|
||||
module_mocker.patch("module.name", return_value=None)
|
||||
mocker.patch.object(obj, "attr", return_value=None)
|
||||
module_mocker.patch.object(obj, "attr", return_value=None)
|
||||
|
||||
mocker.patch("module.name", lambda x, y: x)
|
||||
module_mocker.patch("module.name", lambda x, y: x)
|
||||
mocker.patch.object(obj, "attr", lambda x, y: x)
|
||||
module_mocker.patch.object(obj, "attr", lambda x, y: x)
|
||||
|
||||
mocker.patch("module.name", lambda *args: args)
|
||||
module_mocker.patch("module.name", lambda *args: args)
|
||||
mocker.patch.object(obj, "attr", lambda *args: args)
|
||||
module_mocker.patch.object(obj, "attr", lambda *args: args)
|
||||
|
||||
mocker.patch("module.name", lambda **kwargs: kwargs)
|
||||
module_mocker.patch("module.name", lambda **kwargs: kwargs)
|
||||
mocker.patch.object(obj, "attr", lambda **kwargs: kwargs)
|
||||
module_mocker.patch.object(obj, "attr", lambda **kwargs: kwargs)
|
||||
|
||||
mocker.patch("module.name", lambda x, /, y: x)
|
||||
module_mocker.patch("module.name", lambda x, /, y: x)
|
||||
mocker.patch.object(obj, "attr", lambda x, /, y: x)
|
||||
module_mocker.patch.object(obj, "attr", lambda x, /, y: x)
|
||||
|
||||
# Error
|
||||
|
||||
mocker.patch("module.name", lambda: None)
|
||||
module_mocker.patch("module.name", lambda: None)
|
||||
mocker.patch.object(obj, "attr", lambda: None)
|
||||
module_mocker.patch.object(obj, "attr", lambda: None)
|
||||
|
||||
mocker.patch("module.name", lambda x, y: None)
|
||||
module_mocker.patch("module.name", lambda x, y: None)
|
||||
mocker.patch.object(obj, "attr", lambda x, y: None)
|
||||
module_mocker.patch.object(obj, "attr", lambda x, y: None)
|
||||
|
||||
mocker.patch("module.name", lambda *args, **kwargs: None)
|
||||
module_mocker.patch("module.name", lambda *args, **kwargs: None)
|
||||
mocker.patch.object(obj, "attr", lambda *args, **kwargs: None)
|
||||
module_mocker.patch.object(obj, "attr", lambda *args, **kwargs: None)
|
||||
9
resources/test/fixtures/flake8_pytest_style/PT009.py
vendored
Normal file
9
resources/test/fixtures/flake8_pytest_style/PT009.py
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import pytest
|
||||
|
||||
|
||||
def test_xxx():
|
||||
assert 1 == 1 # OK no parameters
|
||||
|
||||
|
||||
def test_xxx():
|
||||
self.assertEqual(1, 1) # Error
|
||||
11
resources/test/fixtures/flake8_pytest_style/PT010.py
vendored
Normal file
11
resources/test/fixtures/flake8_pytest_style/PT010.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
import pytest
|
||||
|
||||
|
||||
def test_ok():
|
||||
with pytest.raises():
|
||||
pass
|
||||
|
||||
|
||||
def test_error():
|
||||
with pytest.raises(UnicodeError):
|
||||
pass
|
||||
32
resources/test/fixtures/flake8_pytest_style/PT011.py
vendored
Normal file
32
resources/test/fixtures/flake8_pytest_style/PT011.py
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
import socket
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def test_ok():
|
||||
with pytest.raises(ValueError, match="Can't divide by 0"):
|
||||
raise ValueError("Can't divide by 0")
|
||||
|
||||
|
||||
def test_ok_different_error_from_config():
|
||||
with pytest.raises(ZeroDivisionError):
|
||||
raise ZeroDivisionError("Can't divide by 0")
|
||||
|
||||
|
||||
def test_error_no_argument_given():
|
||||
with pytest.raises(ValueError):
|
||||
raise ValueError("Can't divide 1 by 0")
|
||||
|
||||
with pytest.raises(socket.error):
|
||||
raise ValueError("Can't divide 1 by 0")
|
||||
|
||||
|
||||
def test_error_match_is_empty():
|
||||
with pytest.raises(ValueError, match=None):
|
||||
raise ValueError("Can't divide 1 by 0")
|
||||
|
||||
with pytest.raises(ValueError, match=""):
|
||||
raise ValueError("Can't divide 1 by 0")
|
||||
|
||||
with pytest.raises(ValueError, match=f""):
|
||||
raise ValueError("Can't divide 1 by 0")
|
||||
64
resources/test/fixtures/flake8_pytest_style/PT012.py
vendored
Normal file
64
resources/test/fixtures/flake8_pytest_style/PT012.py
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
import pytest
|
||||
|
||||
|
||||
def test_ok():
|
||||
with pytest.raises(AttributeError):
|
||||
[].size
|
||||
|
||||
|
||||
async def test_ok_trivial_with():
|
||||
with pytest.raises(AttributeError):
|
||||
with context_manager_under_test():
|
||||
pass
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
async with context_manager_under_test():
|
||||
pass
|
||||
|
||||
|
||||
def test_ok_complex_single_call():
|
||||
with pytest.raises(AttributeError):
|
||||
my_func(
|
||||
[].size,
|
||||
[].size,
|
||||
)
|
||||
|
||||
|
||||
def test_error_multiple_statements():
|
||||
with pytest.raises(AttributeError):
|
||||
len([])
|
||||
[].size
|
||||
|
||||
|
||||
async def test_error_complex_statement():
|
||||
with pytest.raises(AttributeError):
|
||||
if True:
|
||||
[].size
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
for i in []:
|
||||
[].size
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
async for i in []:
|
||||
[].size
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
while True:
|
||||
[].size
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
with context_manager_under_test():
|
||||
[].size
|
||||
|
||||
with pytest.raises(AttributeError):
|
||||
async with context_manager_under_test():
|
||||
[].size
|
||||
|
||||
|
||||
def test_error_try():
|
||||
with pytest.raises(AttributeError):
|
||||
try:
|
||||
[].size
|
||||
except:
|
||||
raise
|
||||
13
resources/test/fixtures/flake8_pytest_style/PT013.py
vendored
Normal file
13
resources/test/fixtures/flake8_pytest_style/PT013.py
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# OK
|
||||
|
||||
import pytest
|
||||
import pytest as pytest
|
||||
from notpytest import fixture
|
||||
from . import fixture
|
||||
from .pytest import fixture
|
||||
|
||||
# Error
|
||||
|
||||
import pytest as other_name
|
||||
from pytest import fixture
|
||||
from pytest import fixture as other_name
|
||||
25
resources/test/fixtures/flake8_pytest_style/PT015.py
vendored
Normal file
25
resources/test/fixtures/flake8_pytest_style/PT015.py
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
import pytest
|
||||
|
||||
|
||||
def test_ok():
|
||||
assert [0]
|
||||
|
||||
|
||||
def test_error():
|
||||
assert None
|
||||
assert False
|
||||
assert 0
|
||||
assert 0.0
|
||||
assert ""
|
||||
assert f""
|
||||
assert []
|
||||
assert ()
|
||||
assert {}
|
||||
assert list()
|
||||
assert set()
|
||||
assert tuple()
|
||||
assert dict()
|
||||
assert frozenset()
|
||||
assert list([])
|
||||
assert set(set())
|
||||
assert tuple("")
|
||||
17
resources/test/fixtures/flake8_pytest_style/PT016.py
vendored
Normal file
17
resources/test/fixtures/flake8_pytest_style/PT016.py
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import pytest
|
||||
|
||||
|
||||
def test_xxx():
|
||||
pytest.fail("this is a failure") # Test OK arg
|
||||
|
||||
|
||||
def test_xxx():
|
||||
pytest.fail(msg="this is a failure") # Test OK kwarg
|
||||
|
||||
|
||||
def test_xxx(): # Error
|
||||
pytest.fail()
|
||||
pytest.fail("")
|
||||
pytest.fail(f"")
|
||||
pytest.fail(msg="")
|
||||
pytest.fail(msg=f"")
|
||||
19
resources/test/fixtures/flake8_pytest_style/PT017.py
vendored
Normal file
19
resources/test/fixtures/flake8_pytest_style/PT017.py
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
import pytest
|
||||
|
||||
|
||||
def test_ok():
|
||||
try:
|
||||
something()
|
||||
except Exception as e:
|
||||
something_else()
|
||||
|
||||
with pytest.raises(ZeroDivisionError) as e:
|
||||
1 / 0
|
||||
assert e.value.message
|
||||
|
||||
|
||||
def test_error():
|
||||
try:
|
||||
something()
|
||||
except Exception as e:
|
||||
assert e.message, "blah blah"
|
||||
18
resources/test/fixtures/flake8_pytest_style/PT018.py
vendored
Normal file
18
resources/test/fixtures/flake8_pytest_style/PT018.py
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import pytest
|
||||
|
||||
|
||||
def test_ok():
|
||||
assert something
|
||||
assert something or something_else
|
||||
assert something or something_else and something_third
|
||||
assert not (something and something_else)
|
||||
|
||||
|
||||
def test_error():
|
||||
assert something and something_else
|
||||
assert something and something_else and something_third
|
||||
assert something and not something_else
|
||||
assert something and (something_else or something_third)
|
||||
assert not (something or something_else)
|
||||
assert not (something or something_else or something_third)
|
||||
assert not (something or something_else and something_third)
|
||||
14
resources/test/fixtures/flake8_pytest_style/PT019.py
vendored
Normal file
14
resources/test/fixtures/flake8_pytest_style/PT019.py
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
def test_xxx(fixture): # Ok good param name
|
||||
pass
|
||||
|
||||
|
||||
def xxx(_param): # Ok not a test
|
||||
pass
|
||||
|
||||
|
||||
def test_xxx(_fixture): # Error arg
|
||||
pass
|
||||
|
||||
|
||||
def test_xxx(*, _fixture): # Error kwonly
|
||||
pass
|
||||
21
resources/test/fixtures/flake8_pytest_style/PT020.py
vendored
Normal file
21
resources/test/fixtures/flake8_pytest_style/PT020.py
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def ok_no_parameters():
|
||||
return 0
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def ok_without_parens():
|
||||
return 0
|
||||
|
||||
|
||||
@pytest.yield_fixture()
|
||||
def error_without_parens():
|
||||
return 0
|
||||
|
||||
|
||||
@pytest.yield_fixture
|
||||
def error_with_parens():
|
||||
return 0
|
||||
58
resources/test/fixtures/flake8_pytest_style/PT021.py
vendored
Normal file
58
resources/test/fixtures/flake8_pytest_style/PT021.py
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
import functools
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def my_fixture(): # OK return
|
||||
return 0
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def my_fixture(): # OK yield
|
||||
resource = acquire_resource()
|
||||
yield resource
|
||||
resource.release()
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def my_fixture(): # OK other request
|
||||
request = get_request()
|
||||
request.addfinalizer(finalizer)
|
||||
return request
|
||||
|
||||
|
||||
def create_resource(arg, request): # OK other function
|
||||
resource = Resource(arg)
|
||||
request.addfinalizer(resource.release)
|
||||
return resource
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def resource_factory(request):
|
||||
return functools.partial(create_resource, request=request)
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def resource_factory(request): # OK other function
|
||||
def create_resource(arg) -> Resource:
|
||||
resource = Resource(arg)
|
||||
request.addfinalizer(resource.release)
|
||||
return resource
|
||||
|
||||
return create_resource
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def my_fixture(request): # Error return
|
||||
resource = acquire_resource()
|
||||
request.addfinalizer(resource.release)
|
||||
return resource
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def my_fixture(request): # Error yield
|
||||
resource = acquire_resource()
|
||||
request.addfinalizer(resource.release)
|
||||
yield resource
|
||||
resource # prevent PT022
|
||||
17
resources/test/fixtures/flake8_pytest_style/PT022.py
vendored
Normal file
17
resources/test/fixtures/flake8_pytest_style/PT022.py
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def ok_complex_logic():
|
||||
if some_condition:
|
||||
resource = acquire_resource()
|
||||
yield resource
|
||||
resource.release()
|
||||
return
|
||||
yield None
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def error():
|
||||
resource = acquire_resource()
|
||||
yield resource
|
||||
74
resources/test/fixtures/flake8_pytest_style/PT023.py
vendored
Normal file
74
resources/test/fixtures/flake8_pytest_style/PT023.py
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.foo(scope="module")
|
||||
def ok_with_parameters_regardless_of_config():
|
||||
pass
|
||||
|
||||
|
||||
# Without parentheses
|
||||
|
||||
|
||||
@pytest.mark.foo
|
||||
def test_something():
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.foo
|
||||
class TestClass:
|
||||
def test_something():
|
||||
pass
|
||||
|
||||
|
||||
class TestClass:
|
||||
@pytest.mark.foo
|
||||
def test_something():
|
||||
pass
|
||||
|
||||
|
||||
class TestClass:
|
||||
@pytest.mark.foo
|
||||
class TestNestedClass:
|
||||
def test_something():
|
||||
pass
|
||||
|
||||
|
||||
class TestClass:
|
||||
class TestNestedClass:
|
||||
@pytest.mark.foo
|
||||
def test_something():
|
||||
pass
|
||||
|
||||
|
||||
# With parentheses
|
||||
|
||||
|
||||
@pytest.mark.foo()
|
||||
def test_something():
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.foo()
|
||||
class TestClass:
|
||||
def test_something():
|
||||
pass
|
||||
|
||||
|
||||
class TestClass:
|
||||
@pytest.mark.foo()
|
||||
def test_something():
|
||||
pass
|
||||
|
||||
|
||||
class TestClass:
|
||||
@pytest.mark.foo()
|
||||
class TestNestedClass:
|
||||
def test_something():
|
||||
pass
|
||||
|
||||
|
||||
class TestClass:
|
||||
class TestNestedClass:
|
||||
@pytest.mark.foo()
|
||||
def test_something():
|
||||
pass
|
||||
35
resources/test/fixtures/flake8_pytest_style/PT024.py
vendored
Normal file
35
resources/test/fixtures/flake8_pytest_style/PT024.py
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.asyncio()
|
||||
async def test_something(): # Ok not fixture
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_something(): # Ok not fixture no parens
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.asyncio()
|
||||
@pytest.fixture()
|
||||
async def my_fixture(): # Error before
|
||||
return 0
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.fixture()
|
||||
async def my_fixture(): # Error before no parens
|
||||
return 0
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
@pytest.mark.asyncio()
|
||||
async def my_fixture(): # Error after
|
||||
return 0
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
@pytest.mark.asyncio
|
||||
async def my_fixture(): # Error after no parens
|
||||
return 0
|
||||
18
resources/test/fixtures/flake8_pytest_style/PT025.py
vendored
Normal file
18
resources/test/fixtures/flake8_pytest_style/PT025.py
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("a")
|
||||
def test_something(): # Ok not fixture
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("a")
|
||||
@pytest.fixture()
|
||||
def my_fixture(): # Error before
|
||||
return 0
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
@pytest.mark.usefixtures("a")
|
||||
def my_fixture(): # Error after
|
||||
return 0
|
||||
26
resources/test/fixtures/flake8_pytest_style/PT026.py
vendored
Normal file
26
resources/test/fixtures/flake8_pytest_style/PT026.py
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("a")
|
||||
def test_ok():
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.foo()
|
||||
def test_ok_another_mark_with_parens():
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.foo
|
||||
def test_ok_another_mark_no_parens():
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.usefixtures()
|
||||
def test_error_with_parens():
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.usefixtures
|
||||
def test_error_no_parens():
|
||||
pass
|
||||
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
|
||||
|
||||
@@ -1,12 +1,22 @@
|
||||
key in dict.keys() # SIM118
|
||||
key in obj.keys() # SIM118
|
||||
|
||||
foo["bar"] in dict.keys() # SIM118
|
||||
foo["bar"] in obj.keys() # SIM118
|
||||
|
||||
foo() in dict.keys() # SIM118
|
||||
foo['bar'] in obj.keys() # SIM118
|
||||
|
||||
for key in dict.keys(): # SIM118
|
||||
foo() in obj.keys() # SIM118
|
||||
|
||||
for key in obj.keys(): # SIM118
|
||||
pass
|
||||
|
||||
for key in list(dict.keys()):
|
||||
for key in list(obj.keys()):
|
||||
if some_property(key):
|
||||
del dict[key]
|
||||
del obj[key]
|
||||
|
||||
[k for k in obj.keys()] # SIM118
|
||||
|
||||
{k for k in obj.keys()} # SIM118
|
||||
|
||||
{k: k for k in obj.keys()} # SIM118
|
||||
|
||||
(k for k in obj.keys()) # SIM118
|
||||
|
||||
14
resources/test/fixtures/flake8_simplify/SIM222.py
vendored
Normal file
14
resources/test/fixtures/flake8_simplify/SIM222.py
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
if a or True: # SIM223
|
||||
pass
|
||||
|
||||
if (a or b) or True: # SIM223
|
||||
pass
|
||||
|
||||
if a or (b or True): # SIM223
|
||||
pass
|
||||
|
||||
if a and True:
|
||||
pass
|
||||
|
||||
if True:
|
||||
pass
|
||||
14
resources/test/fixtures/flake8_simplify/SIM223.py
vendored
Normal file
14
resources/test/fixtures/flake8_simplify/SIM223.py
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
if a and False: # SIM223
|
||||
pass
|
||||
|
||||
if (a or b) and False: # SIM223
|
||||
pass
|
||||
|
||||
if a or (b and False): # SIM223
|
||||
pass
|
||||
|
||||
if a or False:
|
||||
pass
|
||||
|
||||
if False:
|
||||
pass
|
||||
12
resources/test/fixtures/flake8_simplify/SIM300.py
vendored
Normal file
12
resources/test/fixtures/flake8_simplify/SIM300.py
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# Errors
|
||||
"yoda" == compare # SIM300
|
||||
'yoda' == compare # SIM300
|
||||
42 == age # SIM300
|
||||
|
||||
# OK
|
||||
compare == "yoda"
|
||||
age == 42
|
||||
x == y
|
||||
"yoda" == compare == 1
|
||||
"yoda" == compare == someothervar
|
||||
"yoda" == "yoda"
|
||||
33
resources/test/fixtures/flake8_tidy_imports/TID251.py
vendored
Normal file
33
resources/test/fixtures/flake8_tidy_imports/TID251.py
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
## Banned modules ##
|
||||
import cgi
|
||||
|
||||
from cgi import *
|
||||
|
||||
from cgi import a, b, c
|
||||
|
||||
# banning a module also bans any submodules
|
||||
import cgi.foo.bar
|
||||
|
||||
from cgi.foo import bar
|
||||
|
||||
from cgi.foo.bar import *
|
||||
|
||||
## Banned module members ##
|
||||
|
||||
from typing import TypedDict
|
||||
|
||||
import typing
|
||||
|
||||
# attribute access is checked
|
||||
typing.TypedDict
|
||||
|
||||
typing.TypedDict.anything
|
||||
|
||||
# function calls are checked
|
||||
typing.TypedDict()
|
||||
|
||||
typing.TypedDict.anything()
|
||||
|
||||
# import aliases are resolved
|
||||
import typing as totally_not_typing
|
||||
totally_not_typing.TypedDict
|
||||
11
resources/test/fixtures/flake8_tidy_imports/TID251_false_positives.py
vendored
Normal file
11
resources/test/fixtures/flake8_tidy_imports/TID251_false_positives.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# module members cannot be imported with that syntax
|
||||
import typing.TypedDict
|
||||
|
||||
# we don't track reassignments
|
||||
import typing, other
|
||||
typing = other
|
||||
typing.TypedDict()
|
||||
|
||||
# yet another false positive
|
||||
def foo(typing):
|
||||
typing.TypedDict()
|
||||
5
resources/test/fixtures/isort/comments.py
vendored
5
resources/test/fixtures/isort/comments.py
vendored
@@ -26,3 +26,8 @@ from A import (
|
||||
|
||||
from D import a_long_name_to_force_multiple_lines # Comment 12
|
||||
from D import another_long_name_to_force_multiple_lines # Comment 13
|
||||
|
||||
from E import a # Comment 1
|
||||
|
||||
from F import a # Comment 1
|
||||
from F import b
|
||||
|
||||
11
resources/test/fixtures/isort/inline_comments.py
vendored
Normal file
11
resources/test/fixtures/isort/inline_comments.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
from a.prometheus.metrics import ( # type:ignore[attr-defined]
|
||||
TERMINAL_CURRENTLY_RUNNING_TOTAL,
|
||||
)
|
||||
|
||||
from b.prometheus.metrics import (
|
||||
TERMINAL_CURRENTLY_RUNNING_TOTAL, # type:ignore[attr-defined]
|
||||
)
|
||||
|
||||
from c.prometheus.metrics import TERMINAL_CURRENTLY_RUNNING_TOTAL # type:ignore[attr-defined]
|
||||
|
||||
from d.prometheus.metrics import TERMINAL_CURRENTLY_RUNNING_TOTAL, OTHER_RUNNING_TOTAL # type:ignore[attr-defined]
|
||||
1
resources/test/fixtures/isort/line_ending_cr.py
vendored
Normal file
1
resources/test/fixtures/isort/line_ending_cr.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
from long_module_name import member_one, member_two, member_three, member_four, member_five
|
||||
2
resources/test/fixtures/isort/line_ending_crlf.py
vendored
Normal file
2
resources/test/fixtures/isort/line_ending_crlf.py
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
from long_module_name import member_one, member_two, member_three, member_four, member_five
|
||||
|
||||
2
resources/test/fixtures/isort/line_ending_lf.py
vendored
Normal file
2
resources/test/fixtures/isort/line_ending_lf.py
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
from long_module_name import member_one, member_two, member_three, member_four, member_five
|
||||
|
||||
0
resources/test/fixtures/pydocstyle/D104/__init__.py
vendored
Normal file
0
resources/test/fixtures/pydocstyle/D104/__init__.py
vendored
Normal file
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
|
||||
|
||||
45
resources/test/fixtures/pydocstyle/D417.py
vendored
45
resources/test/fixtures/pydocstyle/D417.py
vendored
@@ -1,5 +1,5 @@
|
||||
def f(x, y, z):
|
||||
"""Do f.
|
||||
"""Do something.
|
||||
|
||||
Args:
|
||||
x: the value
|
||||
@@ -12,7 +12,7 @@ def f(x, y, z):
|
||||
|
||||
|
||||
def f(x, y, z):
|
||||
"""Do f.
|
||||
"""Do something.
|
||||
|
||||
Args:
|
||||
x:
|
||||
@@ -25,7 +25,7 @@ def f(x, y, z):
|
||||
|
||||
|
||||
def f(x, y, z):
|
||||
"""Do f.
|
||||
"""Do something.
|
||||
|
||||
Args:
|
||||
x:
|
||||
@@ -37,7 +37,7 @@ def f(x, y, z):
|
||||
|
||||
|
||||
def f(x, y, z):
|
||||
"""Do f.
|
||||
"""Do something.
|
||||
|
||||
Args:
|
||||
x: the value def
|
||||
@@ -50,7 +50,7 @@ def f(x, y, z):
|
||||
|
||||
|
||||
def f(x, y, z):
|
||||
"""Do f.
|
||||
"""Do something.
|
||||
|
||||
Args:
|
||||
x: the value
|
||||
@@ -63,7 +63,7 @@ def f(x, y, z):
|
||||
|
||||
|
||||
def f(x, y, z):
|
||||
"""Do g.
|
||||
"""Do something.
|
||||
|
||||
Args:
|
||||
x: the value
|
||||
@@ -75,10 +75,41 @@ def f(x, y, z):
|
||||
|
||||
|
||||
def f(x, y, z):
|
||||
"""Do h.
|
||||
"""Do something.
|
||||
|
||||
Args:
|
||||
x: the value
|
||||
z: A final argument
|
||||
"""
|
||||
return x
|
||||
|
||||
|
||||
def f(x, *args, **kwargs):
|
||||
"""Do something.
|
||||
|
||||
Args:
|
||||
x: the value
|
||||
*args: variable arguments
|
||||
**kwargs: keyword arguments
|
||||
"""
|
||||
return x
|
||||
|
||||
|
||||
def f(x, *args, **kwargs):
|
||||
"""Do something.
|
||||
|
||||
Args:
|
||||
*args: variable arguments
|
||||
**kwargs: keyword arguments
|
||||
"""
|
||||
return x
|
||||
|
||||
|
||||
def f(x, *args, **kwargs):
|
||||
"""Do something.
|
||||
|
||||
Args:
|
||||
x: the value
|
||||
**kwargs: keyword arguments
|
||||
"""
|
||||
return x
|
||||
|
||||
@@ -376,7 +376,7 @@ class TestGoogle: # noqa: D203
|
||||
Etiam at tellus a tellus faucibus maximus. Curabitur tellus
|
||||
mauris, semper id vehicula ac, feugiat ut tortor.
|
||||
verbose (bool):
|
||||
If True, print out as much infromation as possible.
|
||||
If True, print out as much information as possible.
|
||||
If False, print out concise "one-liner" information.
|
||||
|
||||
"""
|
||||
|
||||
68
resources/test/fixtures/pyflakes/F401_7.py
vendored
68
resources/test/fixtures/pyflakes/F401_7.py
vendored
@@ -1,16 +1,66 @@
|
||||
"""Test: noqa directives."""
|
||||
|
||||
from module import (
|
||||
A, # noqa: F401
|
||||
B,
|
||||
# This should ignore both errors.
|
||||
from typing import ( # noqa: F401
|
||||
List,
|
||||
Sequence,
|
||||
)
|
||||
|
||||
from module import (
|
||||
A, # noqa: F401
|
||||
B, # noqa: F401
|
||||
# This should ignore both errors.
|
||||
from typing import ( # noqa
|
||||
List,
|
||||
Sequence,
|
||||
)
|
||||
|
||||
from module import (
|
||||
A,
|
||||
B,
|
||||
# This should ignore both errors.
|
||||
from typing import (
|
||||
List, # noqa: F401
|
||||
Sequence, # noqa: F401
|
||||
)
|
||||
|
||||
# This should ignore both errors.
|
||||
from typing import (
|
||||
List, # noqa
|
||||
Sequence, # noqa
|
||||
)
|
||||
|
||||
# This should ignore the first error.
|
||||
from typing import (
|
||||
Mapping, # noqa: F401
|
||||
Union,
|
||||
)
|
||||
|
||||
# This should ignore both errors.
|
||||
from typing import ( # noqa
|
||||
List,
|
||||
Sequence,
|
||||
)
|
||||
|
||||
# This should ignore the error, but the inner noqa should be marked as unused.
|
||||
from typing import ( # noqa: F401
|
||||
Optional, # noqa: F401
|
||||
)
|
||||
|
||||
# This should ignore the error, but the inner noqa should be marked as unused.
|
||||
from typing import ( # noqa
|
||||
Optional, # noqa: F401
|
||||
)
|
||||
|
||||
# This should ignore the error, but mark F501 as unused.
|
||||
from typing import ( # noqa: F401
|
||||
Dict, # noqa: F501
|
||||
)
|
||||
|
||||
# This should ignore the error, but mark F501 as unused.
|
||||
from typing import ( # noqa: F501
|
||||
Tuple, # noqa: F401
|
||||
)
|
||||
|
||||
# This should ignore both errors.
|
||||
from typing import Any, AnyStr # noqa: F401
|
||||
|
||||
# This should ignore both errors.
|
||||
from typing import AsyncIterable, AsyncGenerator # noqa
|
||||
|
||||
# This should mark F501 as unused.
|
||||
from typing import Awaitable, AwaitableGenerator # noqa: F501
|
||||
|
||||
23
resources/test/fixtures/pyflakes/F541.py
vendored
23
resources/test/fixtures/pyflakes/F541.py
vendored
@@ -1,12 +1,35 @@
|
||||
# OK
|
||||
a = "abc"
|
||||
b = f"ghi{'jkl'}"
|
||||
|
||||
# Errors
|
||||
c = f"def"
|
||||
d = f"def" + "ghi"
|
||||
e = (
|
||||
f"def" +
|
||||
"ghi"
|
||||
)
|
||||
f = (
|
||||
f"a"
|
||||
F"b"
|
||||
"c"
|
||||
rf"d"
|
||||
fr"e"
|
||||
)
|
||||
g = f""
|
||||
|
||||
# OK
|
||||
g = f"ghi{123:{45}}"
|
||||
|
||||
# Error
|
||||
h = "x" "y" f"z"
|
||||
|
||||
v = 23.234234
|
||||
|
||||
# OK
|
||||
f"{v:0.2f}"
|
||||
f"{f'{v:0.2f}'}"
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
3
resources/test/fixtures/pyflakes/F821_8.pyi
vendored
Normal file
3
resources/test/fixtures/pyflakes/F821_8.pyi
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
class Pool:
|
||||
@classmethod
|
||||
def create(cls) -> Pool: ...
|
||||
10
resources/test/fixtures/pyflakes/F831.py
vendored
10
resources/test/fixtures/pyflakes/F831.py
vendored
@@ -1,10 +0,0 @@
|
||||
def foo(x: int, y: int, x: int) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def bar(x: int, y: int, *, x: int) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def baz(x: int, y: int, **x: int) -> None:
|
||||
pass
|
||||
6
resources/test/fixtures/pyflakes/F841_2.py
vendored
Normal file
6
resources/test/fixtures/pyflakes/F841_2.py
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
# test case for https://github.com/charliermarsh/ruff/issues/1552
|
||||
def _():
|
||||
x = 0
|
||||
list()[x:]
|
||||
@@ -18,8 +18,8 @@ def isinstances():
|
||||
|
||||
result = isinstance(var[5], int) or True or isinstance(var[5], float) # [consider-merging-isinstance]
|
||||
|
||||
infered_isinstance = isinstance
|
||||
result = infered_isinstance(var[6], int) or infered_isinstance(var[6], float) or infered_isinstance(var[6], list) and False # [consider-merging-isinstance]
|
||||
inferred_isinstance = isinstance
|
||||
result = inferred_isinstance(var[6], int) or inferred_isinstance(var[6], float) or inferred_isinstance(var[6], list) and False # [consider-merging-isinstance]
|
||||
result = isinstance(var[10], str) or isinstance(var[10], int) and var[8] * 14 or isinstance(var[10], float) and var[5] * 14.4 or isinstance(var[10], list) # [consider-merging-isinstance]
|
||||
result = isinstance(var[11], int) or isinstance(var[11], int) or isinstance(var[11], float) # [consider-merging-isinstance]
|
||||
|
||||
|
||||
13
resources/test/fixtures/pyproject.toml
vendored
13
resources/test/fixtures/pyproject.toml
vendored
@@ -42,6 +42,10 @@ staticmethod-decorators = ["staticmethod"]
|
||||
[tool.ruff.flake8-tidy-imports]
|
||||
ban-relative-imports = "parents"
|
||||
|
||||
[tool.ruff.flake8-tidy-imports.banned-api]
|
||||
"cgi".msg = "The cgi module is deprecated."
|
||||
"typing.TypedDict".msg = "Use typing_extensions.TypedDict instead."
|
||||
|
||||
[tool.ruff.flake8-errmsg]
|
||||
max-string-length = 20
|
||||
|
||||
@@ -50,3 +54,12 @@ pandas = "pd"
|
||||
|
||||
[tool.ruff.flake8-import-conventions.extend-aliases]
|
||||
"dask.dataframe" = "dd"
|
||||
|
||||
[tool.ruff.flake8-pytest-style]
|
||||
fixture-parentheses = false
|
||||
parametrize-names-type = "csv"
|
||||
parametrize-values-type = "tuple"
|
||||
parametrize-values-row-type = "list"
|
||||
raises-require-match-for = ["Exception", "TypeError", "KeyError"]
|
||||
raises-extend-require-match-for = ["requests.RequestException"]
|
||||
mark-parentheses = false
|
||||
|
||||
4
resources/test/fixtures/pyupgrade/UP012.py
vendored
4
resources/test/fixtures/pyupgrade/UP012.py
vendored
@@ -45,8 +45,8 @@ f"foo{bar}".encode(encoding)
|
||||
"unicode text©".encode()
|
||||
"unicode text©".encode(encoding="UTF8") # "unicode text©".encode()
|
||||
|
||||
r"fo\o".encode("utf-8") # br"fo\o"
|
||||
r"foo\o".encode("utf-8") # br"foo\o"
|
||||
u"foo".encode("utf-8") # b"foo"
|
||||
R"fo\o".encode("utf-8") # br"fo\o"
|
||||
R"foo\o".encode("utf-8") # br"foo\o"
|
||||
U"foo".encode("utf-8") # b"foo"
|
||||
print("foo".encode()) # print(b"foo")
|
||||
|
||||
2
resources/test/fixtures/pyupgrade/UP018.py
vendored
2
resources/test/fixtures/pyupgrade/UP018.py
vendored
@@ -7,12 +7,14 @@ str("foo", **k)
|
||||
str("foo", encoding="UTF-8")
|
||||
str("foo"
|
||||
"bar")
|
||||
str(b"foo")
|
||||
bytes("foo", encoding="UTF-8")
|
||||
bytes(*a)
|
||||
bytes("foo", *a)
|
||||
bytes("foo", **a)
|
||||
bytes(b"foo"
|
||||
b"bar")
|
||||
bytes("foo")
|
||||
|
||||
# These become string or byte literals
|
||||
str()
|
||||
|
||||
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)
|
||||
27
resources/test/fixtures/pyupgrade/UP025.py
vendored
Normal file
27
resources/test/fixtures/pyupgrade/UP025.py
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
# These should change
|
||||
x = u"Hello"
|
||||
|
||||
u'world'
|
||||
|
||||
print(u"Hello")
|
||||
|
||||
print(u'world')
|
||||
|
||||
import foo
|
||||
|
||||
foo(u"Hello", U"world", a=u"Hello", b=u"world")
|
||||
|
||||
# These should stay quoted they way they are
|
||||
|
||||
x = u'hello'
|
||||
x = u"""hello"""
|
||||
x = u'''hello'''
|
||||
x = u'Hello "World"'
|
||||
|
||||
# These should not change
|
||||
u = "Hello"
|
||||
|
||||
u = u
|
||||
|
||||
def hello():
|
||||
return"Hello"
|
||||
88
resources/test/fixtures/pyupgrade/UP026.py
vendored
Normal file
88
resources/test/fixtures/pyupgrade/UP026.py
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
# 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,
|
||||
)
|
||||
from mock import (
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
mock,
|
||||
)
|
||||
|
||||
# Should not get a trailing comma
|
||||
from mock import (
|
||||
mock,
|
||||
a,
|
||||
b,
|
||||
c
|
||||
)
|
||||
from mock import (
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
mock
|
||||
)
|
||||
from mock import mock, a, b, c
|
||||
from mock import a, b, c, mock
|
||||
|
||||
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()
|
||||
18
resources/test/fixtures/pyupgrade/UP027.py
vendored
Normal file
18
resources/test/fixtures/pyupgrade/UP027.py
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
# Should change
|
||||
foo, bar, baz = [fn(x) for x in items]
|
||||
|
||||
foo, bar, baz =[fn(x) for x in items]
|
||||
|
||||
foo, bar, baz = [fn(x) for x in items]
|
||||
|
||||
foo, bar, baz = [[i for i in fn(x)] for x in items]
|
||||
|
||||
foo, bar, baz = [
|
||||
fn(x)
|
||||
for x in items
|
||||
]
|
||||
|
||||
# Should not change
|
||||
foo = [fn(x) for x in items]
|
||||
|
||||
x, = [await foo for foo in bar]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user