Compare commits
52 Commits
simplify-S
...
v0.1.14
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
866bea60a5 | ||
|
|
df617c3093 | ||
|
|
47ad7b4500 | ||
|
|
b3a6f0ce81 | ||
|
|
7be706641d | ||
|
|
848e473f69 | ||
|
|
368e2793b5 | ||
|
|
29c130f326 | ||
|
|
8118d29419 | ||
|
|
45d374d838 | ||
|
|
8788d57030 | ||
|
|
f426c0fdaf | ||
|
|
3aae16f1bd | ||
|
|
3064312818 | ||
|
|
f9191b07c5 | ||
|
|
21f2d0c90b | ||
|
|
2b605527bd | ||
|
|
7ef7e0ddb6 | ||
|
|
2bddde2627 | ||
|
|
9a2f3e2cef | ||
|
|
f9331c7683 | ||
|
|
da275b8572 | ||
|
|
b983ab1c6c | ||
|
|
a1e65a92bd | ||
|
|
64aac5d526 | ||
|
|
896cecddd3 | ||
|
|
0753968ef3 | ||
|
|
66804eca6d | ||
|
|
f8f38b7640 | ||
|
|
2e375860dd | ||
|
|
15740306ea | ||
|
|
6183b8e98b | ||
|
|
0c0d3db1b5 | ||
|
|
953d48b7f4 | ||
|
|
0003c730e0 | ||
|
|
b6ce4f5f3a | ||
|
|
e8d7a6dfce | ||
|
|
ef2798f758 | ||
|
|
957a1f35c4 | ||
|
|
009430e034 | ||
|
|
7504bf347b | ||
|
|
fee64b52ba | ||
|
|
3261d16e61 | ||
|
|
d16c4a2d25 | ||
|
|
1602df1643 | ||
|
|
395cdf04e5 | ||
|
|
3daf6e1b6d | ||
|
|
a31a314b2b | ||
|
|
f9dd7bb190 | ||
|
|
350dcb807a | ||
|
|
55f8f3b2cc | ||
|
|
eb4ed2471b |
2
.github/workflows/ci.yaml
vendored
2
.github/workflows/ci.yaml
vendored
@@ -35,7 +35,7 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: tj-actions/changed-files@v40
|
||||
- uses: tj-actions/changed-files@v41
|
||||
id: changed
|
||||
with:
|
||||
files_yaml: |
|
||||
|
||||
2
.github/workflows/docs.yaml
vendored
2
.github/workflows/docs.yaml
vendored
@@ -47,7 +47,7 @@ jobs:
|
||||
run: mkdocs build --strict -f mkdocs.public.yml
|
||||
- name: "Deploy to Cloudflare Pages"
|
||||
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
|
||||
uses: cloudflare/wrangler-action@v3.3.2
|
||||
uses: cloudflare/wrangler-action@v3.4.1
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
accountId: ${{ secrets.CF_ACCOUNT_ID }}
|
||||
|
||||
2
.github/workflows/playground.yaml
vendored
2
.github/workflows/playground.yaml
vendored
@@ -40,7 +40,7 @@ jobs:
|
||||
working-directory: playground
|
||||
- name: "Deploy to Cloudflare Pages"
|
||||
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
|
||||
uses: cloudflare/wrangler-action@v3.3.2
|
||||
uses: cloudflare/wrangler-action@v3.4.1
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
accountId: ${{ secrets.CF_ACCOUNT_ID }}
|
||||
|
||||
@@ -4,7 +4,7 @@ exclude: |
|
||||
(?x)^(
|
||||
crates/ruff_linter/resources/.*|
|
||||
crates/ruff_linter/src/rules/.*/snapshots/.*|
|
||||
crates/ruff_cli/resources/.*|
|
||||
crates/ruff/resources/.*|
|
||||
crates/ruff_python_formatter/resources/.*|
|
||||
crates/ruff_python_formatter/tests/snapshots/.*|
|
||||
crates/ruff_python_resolver/resources/.*|
|
||||
|
||||
109
CHANGELOG.md
109
CHANGELOG.md
@@ -1,5 +1,114 @@
|
||||
# Changelog
|
||||
|
||||
## 0.1.14
|
||||
|
||||
### Preview features
|
||||
|
||||
- \[`flake8-bugbear`\] Add fix for `duplicate-value` (`B033`) ([#9510](https://github.com/astral-sh/ruff/pull/9510))
|
||||
- \[`flake8-simplify`\] Implement `enumerate-for-loop` (`SIM113`) ([#7777](https://github.com/astral-sh/ruff/pull/7777))
|
||||
- \[`pygrep_hooks`\] Add fix for `deprecated-log-warn` (`PGH002`) ([#9519](https://github.com/astral-sh/ruff/pull/9519))
|
||||
- \[`pylint`\] Implement `import-private-name` (`C2701`) ([#5920](https://github.com/astral-sh/ruff/pull/5920))
|
||||
- \[`refurb`\] Implement `regex-flag-alias` with fix (`FURB167`) ([#9516](https://github.com/astral-sh/ruff/pull/9516))
|
||||
- \[`ruff`\] Add rule and fix to sort contents of `__all__` (`RUF022`) ([#9474](https://github.com/astral-sh/ruff/pull/9474))
|
||||
- \[`tryceratops`\] Add fix for `error-instead-of-exception` (`TRY400`) ([#9520](https://github.com/astral-sh/ruff/pull/9520))
|
||||
|
||||
### Rule changes
|
||||
|
||||
- \[`flake8-pyi`\] Fix `PYI047` false negatives on PEP-695 type aliases ([#9566](https://github.com/astral-sh/ruff/pull/9566))
|
||||
- \[`flake8-pyi`\] Fix `PYI049` false negatives on call-based `TypedDict`s ([#9567](https://github.com/astral-sh/ruff/pull/9567))
|
||||
- \[`pylint`\] Exclude `self` and `cls` when counting method arguments (`PLR0917`) ([#9563](https://github.com/astral-sh/ruff/pull/9563))
|
||||
|
||||
### CLI
|
||||
|
||||
- `--show-settings` displays active settings in a far more readable format ([#9464](https://github.com/astral-sh/ruff/pull/9464))
|
||||
- Add `--extension` support to the formatter ([#9483](https://github.com/astral-sh/ruff/pull/9483))
|
||||
|
||||
### Configuration
|
||||
|
||||
- Ignore preview status for fixable and unfixable selectors ([#9538](https://github.com/astral-sh/ruff/pull/9538))
|
||||
- \[`pycodestyle`\] Use the configured tab size when expanding indents ([#9506](https://github.com/astral-sh/ruff/pull/9506))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- Recursively visit deferred AST nodes ([#9541](https://github.com/astral-sh/ruff/pull/9541))
|
||||
- Visit deferred lambdas before type definitions ([#9540](https://github.com/astral-sh/ruff/pull/9540))
|
||||
- \[`flake8-simplify`\] Avoid some more `enumerate-for-loop` false positives (`SIM113`) ([#9515](https://github.com/astral-sh/ruff/pull/9515))
|
||||
- \[`pandas-vet`\] Limit inplace diagnostics to methods that accept inplace ([#9495](https://github.com/astral-sh/ruff/pull/9495))
|
||||
- \[`pylint`\] Add the `__prepare__` method to the list of recognized dunder method ([#9529](https://github.com/astral-sh/ruff/pull/9529))
|
||||
- \[`pylint`\] Ignore unnecessary dunder calls within dunder definitions ([#9496](https://github.com/astral-sh/ruff/pull/9496))
|
||||
- \[`refurb`\] Avoid bailing when `reimplemented-operator` is called on function (`FURB118`) ([#9556](https://github.com/astral-sh/ruff/pull/9556))
|
||||
- \[`ruff`\] Avoid treating named expressions as static keys (`RUF011`) ([#9494](https://github.com/astral-sh/ruff/pull/9494))
|
||||
|
||||
### Documentation
|
||||
|
||||
- Add instructions on using `noqa` with isort rules ([#9555](https://github.com/astral-sh/ruff/pull/9555))
|
||||
- Documentation update for URL giving 'page not found' ([#9565](https://github.com/astral-sh/ruff/pull/9565))
|
||||
- Fix admonition in dark mode ([#9502](https://github.com/astral-sh/ruff/pull/9502))
|
||||
- Update contributing docs to use `cargo bench -p ruff_benchmark` ([#9535](https://github.com/astral-sh/ruff/pull/9535))
|
||||
- Update emacs integration section to include `emacs-ruff-format` ([#9403](https://github.com/astral-sh/ruff/pull/9403))
|
||||
- \[`flake8-blind-except`\] Document exceptions to `blind-except` rule ([#9580](https://github.com/astral-sh/ruff/pull/9580))
|
||||
|
||||
## 0.1.13
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- Include base pyproject when initializing cache settings ([#9480](https://github.com/astral-sh/ruff/pull/9480))
|
||||
- \[`flake8-simplify`\] Account for possibly-empty f-string values in truthiness logic ([#9484](https://github.com/astral-sh/ruff/pull/9484))
|
||||
- \[`pylint`\] Add the missing period in `unnecessary-dunder-call` ([#9485](https://github.com/astral-sh/ruff/pull/9485))
|
||||
- \[`pylint`\] Fix `__aenter__` message in `unnecessary-dunder-call` ([#9492](https://github.com/astral-sh/ruff/pull/9492))
|
||||
|
||||
## 0.1.12
|
||||
|
||||
### Preview features
|
||||
|
||||
- Formatter: Hug multiline-strings in preview style ([#9243](https://github.com/astral-sh/ruff/pull/9243))
|
||||
- \[`flake8-bandit`\] Add `ssl-with-no-version` (`S504`) ([#9384](https://github.com/astral-sh/ruff/pull/9384))
|
||||
- \[`flake8-bandit`\] Implement `ssl-insecure-version` (`S502`) ([#9390](https://github.com/astral-sh/ruff/pull/9390))
|
||||
- \[`flake8-bandit`\] Implement `ssl-with-bad-defaults` (`S503`) ([#9391](https://github.com/astral-sh/ruff/pull/9391))
|
||||
- \[`flake8-bandit`\] Implement suspicious import rules (`S4XX`) ([#8831](https://github.com/astral-sh/ruff/pull/8831))
|
||||
- \[`flake8-simplify`\] Implement `zip-dict-keys-and-values` (`SIM911`) ([#9460](https://github.com/astral-sh/ruff/pull/9460))
|
||||
- \[`pyflakes`\] Add a fix for `redefined-while-unused` (`F811`) ([#9419](https://github.com/astral-sh/ruff/pull/9419))
|
||||
- \[`pylint`\] Implement `unnecessary-dunder-call` (`C2801`) ([#9166](https://github.com/astral-sh/ruff/pull/9166))
|
||||
- \[`ruff`\] Add `parenthesize-chained-operators` (`RUF021`) to enforce parentheses in `a or b and c` ([#9440](https://github.com/astral-sh/ruff/pull/9440))
|
||||
|
||||
### Rule changes
|
||||
|
||||
- \[`flake8-boolean-trap`\] Allow Boolean positional arguments in setters ([#9429](https://github.com/astral-sh/ruff/pull/9429))
|
||||
- \[`flake8-builtins`\] Restrict `builtin-attribute-shadowing` (`A003`) to actual shadowed references ([#9462](https://github.com/astral-sh/ruff/pull/9462))
|
||||
- \[`flake8-pyi`\] Add fix for `generator-return-from-iter-method` (`PYI058`) ([#9355](https://github.com/astral-sh/ruff/pull/9355))
|
||||
- \[`pyflakes`\] Don't flag `redefined-while-unused` (`F811`) in `if` branches ([#9418](https://github.com/astral-sh/ruff/pull/9418))
|
||||
- \[`pyupgrade`\] Add some additional Python 3.12 typing members to `deprecated-import` ([#9445](https://github.com/astral-sh/ruff/pull/9445))
|
||||
- \[`ruff`\] Add fix for `parenthesize-chained-operators` (`RUF021`) ([#9449](https://github.com/astral-sh/ruff/pull/9449))
|
||||
- \[`ruff`\] Include subscripts and attributes in static key rule (`RUF011`) ([#9416](https://github.com/astral-sh/ruff/pull/9416))
|
||||
- \[`ruff`\] Support variable keys in static dictionary key rule (`RUF011`) ([#9411](https://github.com/astral-sh/ruff/pull/9411))
|
||||
|
||||
### Formatter
|
||||
|
||||
- Generate deterministic IDs when formatting notebooks ([#9359](https://github.com/astral-sh/ruff/pull/9359))
|
||||
- Allow `# fmt: skip` with interspersed same-line comments ([#9395](https://github.com/astral-sh/ruff/pull/9395))
|
||||
- Parenthesize breaking named expressions in match guards ([#9396](https://github.com/astral-sh/ruff/pull/9396))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- Add cell indexes to all diagnostics ([#9387](https://github.com/astral-sh/ruff/pull/9387))
|
||||
- Avoid infinite loop in constant vs. `None` comparisons ([#9376](https://github.com/astral-sh/ruff/pull/9376))
|
||||
- Handle raises with implicit alternate branches ([#9377](https://github.com/astral-sh/ruff/pull/9377))
|
||||
- Ignore trailing quotes for unclosed l-brace errors ([#9388](https://github.com/astral-sh/ruff/pull/9388))
|
||||
- Respect multi-segment submodule imports when resolving qualified names ([#9382](https://github.com/astral-sh/ruff/pull/9382))
|
||||
- Use `DisplayParseError` for stdin parser errors ([#9409](https://github.com/astral-sh/ruff/pull/9409))
|
||||
- Use `comment_ranges` for isort directive extraction ([#9414](https://github.com/astral-sh/ruff/pull/9414))
|
||||
- Use transformed source code for diagnostic locations ([#9408](https://github.com/astral-sh/ruff/pull/9408))
|
||||
- \[`flake8-pyi`\] Exclude `warnings.deprecated` and `typing_extensions.deprecated` arguments ([#9423](https://github.com/astral-sh/ruff/pull/9423))
|
||||
- \[`flake8-pyi`\] Fix false negative for `unused-private-protocol` (`PYI046`) with unused generic protocols ([#9405](https://github.com/astral-sh/ruff/pull/9405))
|
||||
- \[`pydocstyle`\] Disambiguate argument descriptors from section headers ([#9427](https://github.com/astral-sh/ruff/pull/9427))
|
||||
- \[`pylint`\] Homogenize `PLR0914` message to match other `PLR09XX` rules ([#9399](https://github.com/astral-sh/ruff/pull/9399))
|
||||
- \[`ruff`\] Allow `Hashable = None` in type annotations (`RUF013`) ([#9442](https://github.com/astral-sh/ruff/pull/9442))
|
||||
|
||||
### Documentation
|
||||
|
||||
- Fix admonition hyperlink colouring ([#9385](https://github.com/astral-sh/ruff/pull/9385))
|
||||
- Add missing preview link ([#9386](https://github.com/astral-sh/ruff/pull/9386))
|
||||
|
||||
## 0.1.11
|
||||
|
||||
### Preview features
|
||||
|
||||
@@ -81,7 +81,7 @@ pre-commit install
|
||||
After cloning the repository, run Ruff locally from the repository root with:
|
||||
|
||||
```shell
|
||||
cargo run -p ruff_cli -- check /path/to/file.py --no-cache
|
||||
cargo run -p ruff -- check /path/to/file.py --no-cache
|
||||
```
|
||||
|
||||
Prior to opening a pull request, ensure that your code has been auto-formatted,
|
||||
@@ -120,7 +120,7 @@ At the time of writing, the repository includes the following crates:
|
||||
If you're working on a rule, this is the crate for you.
|
||||
- `crates/ruff_benchmark`: binary crate for running micro-benchmarks.
|
||||
- `crates/ruff_cache`: library crate for caching lint results.
|
||||
- `crates/ruff_cli`: binary crate containing Ruff's command-line interface.
|
||||
- `crates/ruff`: binary crate containing Ruff's command-line interface.
|
||||
- `crates/ruff_dev`: binary crate containing utilities used in the development of Ruff itself (e.g.,
|
||||
`cargo dev generate-all`), see the [`cargo dev`](#cargo-dev) section below.
|
||||
- `crates/ruff_diagnostics`: library crate for the rule-independent abstractions in the lint
|
||||
@@ -231,7 +231,7 @@ Once you've completed the code for the rule itself, you can define tests with th
|
||||
For example, if you're adding a new rule named `E402`, you would run:
|
||||
|
||||
```shell
|
||||
cargo run -p ruff_cli -- check crates/ruff_linter/resources/test/fixtures/pycodestyle/E402.py --no-cache --select E402
|
||||
cargo run -p ruff -- check crates/ruff_linter/resources/test/fixtures/pycodestyle/E402.py --no-cache --select E402
|
||||
```
|
||||
|
||||
**Note:** Only a subset of rules are enabled by default. When testing a new rule, ensure that
|
||||
@@ -252,7 +252,7 @@ Once you've completed the code for the rule itself, you can define tests with th
|
||||
|
||||
Ruff's user-facing settings live in a few different places.
|
||||
|
||||
First, the command-line options are defined via the `Args` struct in `crates/ruff_cli/src/args.rs`.
|
||||
First, the command-line options are defined via the `Args` struct in `crates/ruff/src/args.rs`.
|
||||
|
||||
Second, the `pyproject.toml` options are defined in `crates/ruff_workspace/src/options.rs` (via the
|
||||
`Options` struct), `crates/ruff_workspace/src/configuration.rs` (via the `Configuration` struct),
|
||||
@@ -518,10 +518,10 @@ if the benchmark improved/regressed compared to that baseline.
|
||||
|
||||
```shell
|
||||
# Run once on your "baseline" code
|
||||
cargo benchmark --save-baseline=main
|
||||
cargo bench -p ruff_benchmark -- --save-baseline=main
|
||||
|
||||
# Then iterate with
|
||||
cargo benchmark --baseline=main
|
||||
cargo bench -p ruff_benchmark -- --baseline=main
|
||||
```
|
||||
|
||||
#### PR Summary
|
||||
@@ -531,10 +531,10 @@ This is useful to illustrate the improvements of a PR.
|
||||
|
||||
```shell
|
||||
# On main
|
||||
cargo benchmark --save-baseline=main
|
||||
cargo bench -p ruff_benchmark -- --save-baseline=main
|
||||
|
||||
# After applying your changes
|
||||
cargo benchmark --save-baseline=pr
|
||||
cargo bench -p ruff_benchmark -- --save-baseline=pr
|
||||
|
||||
critcmp main pr
|
||||
```
|
||||
@@ -547,10 +547,10 @@ cargo install critcmp
|
||||
|
||||
#### Tips
|
||||
|
||||
- Use `cargo benchmark <filter>` to only run specific benchmarks. For example: `cargo benchmark linter/pydantic`
|
||||
to only run the pydantic tests.
|
||||
- Use `cargo benchmark --quiet` for a more cleaned up output (without statistical relevance)
|
||||
- Use `cargo benchmark --quick` to get faster results (more prone to noise)
|
||||
- Use `cargo bench -p ruff_benchmark <filter>` to only run specific benchmarks. For example: `cargo benchmark lexer`
|
||||
to only run the lexer benchmarks.
|
||||
- Use `cargo bench -p ruff_benchmark -- --quiet` for a more cleaned up output (without statistical relevance)
|
||||
- Use `cargo bench -p ruff_benchmark -- --quick` to get faster results (more prone to noise)
|
||||
|
||||
### Profiling Projects
|
||||
|
||||
@@ -618,7 +618,7 @@ Otherwise, follow the instructions from the linux section.
|
||||
utils with it:
|
||||
|
||||
- `cargo dev print-ast <file>`: Print the AST of a python file using the
|
||||
[RustPython parser](https://github.com/astral-sh/RustPython-Parser/tree/main/parser) that is
|
||||
[RustPython parser](https://github.com/astral-sh/ruff/tree/main/crates/ruff_python_parser) that is
|
||||
mainly used in Ruff. For `if True: pass # comment`, you can see the syntax tree, the byte offsets
|
||||
for start and stop of each node and also how the `:` token, the comment and whitespace are not
|
||||
represented anymore:
|
||||
|
||||
145
Cargo.lock
generated
145
Cargo.lock
generated
@@ -154,9 +154,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "assert_cmd"
|
||||
version = "2.0.12"
|
||||
version = "2.0.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6"
|
||||
checksum = "00ad3f3a942eee60335ab4342358c161ee296829e0d16ff42fc1d6cb07815467"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"bstr",
|
||||
@@ -1146,9 +1146,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.66"
|
||||
version = "0.3.67"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
|
||||
checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
@@ -1990,55 +1990,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.16.20"
|
||||
version = "0.17.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
|
||||
checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"getrandom",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"spin",
|
||||
"untrusted",
|
||||
"web-sys",
|
||||
"winapi",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_benchmark"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"codspeed-criterion-compat",
|
||||
"criterion",
|
||||
"mimalloc",
|
||||
"once_cell",
|
||||
"ruff_linter",
|
||||
"ruff_python_ast",
|
||||
"ruff_python_formatter",
|
||||
"ruff_python_index",
|
||||
"ruff_python_parser",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tikv-jemallocator",
|
||||
"ureq",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_cache"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
"glob",
|
||||
"globset",
|
||||
"itertools 0.12.0",
|
||||
"regex",
|
||||
"ruff_macros",
|
||||
"seahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_cli"
|
||||
version = "0.1.11"
|
||||
name = "ruff"
|
||||
version = "0.1.14"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"argfile",
|
||||
@@ -2087,6 +2053,39 @@ dependencies = [
|
||||
"wild",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_benchmark"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"codspeed-criterion-compat",
|
||||
"criterion",
|
||||
"mimalloc",
|
||||
"once_cell",
|
||||
"ruff_linter",
|
||||
"ruff_python_ast",
|
||||
"ruff_python_formatter",
|
||||
"ruff_python_index",
|
||||
"ruff_python_parser",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tikv-jemallocator",
|
||||
"ureq",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_cache"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
"glob",
|
||||
"globset",
|
||||
"itertools 0.12.0",
|
||||
"regex",
|
||||
"ruff_macros",
|
||||
"seahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff_dev"
|
||||
version = "0.0.0"
|
||||
@@ -2103,7 +2102,7 @@ dependencies = [
|
||||
"pretty_assertions",
|
||||
"rayon",
|
||||
"regex",
|
||||
"ruff_cli",
|
||||
"ruff",
|
||||
"ruff_diagnostics",
|
||||
"ruff_formatter",
|
||||
"ruff_linter",
|
||||
@@ -2165,7 +2164,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_linter"
|
||||
version = "0.1.11"
|
||||
version = "0.1.14"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"annotate-snippets 0.9.2",
|
||||
@@ -2417,7 +2416,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_shrinking"
|
||||
version = "0.1.11"
|
||||
version = "0.1.14"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -2541,9 +2540,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.21.7"
|
||||
version = "0.21.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8"
|
||||
checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba"
|
||||
dependencies = [
|
||||
"log",
|
||||
"ring",
|
||||
@@ -2553,9 +2552,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.101.4"
|
||||
version = "0.101.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d"
|
||||
checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"untrusted",
|
||||
@@ -2620,9 +2619,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "sct"
|
||||
version = "0.7.0"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
|
||||
checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"untrusted",
|
||||
@@ -2636,9 +2635,9 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.20"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
|
||||
checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
@@ -2759,9 +2758,9 @@ checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380"
|
||||
|
||||
[[package]]
|
||||
name = "similar"
|
||||
version = "2.3.0"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2aeaf503862c419d66959f5d7ca015337d864e9c49485d771b732e2a20453597"
|
||||
checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21"
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
@@ -2777,9 +2776,9 @@ checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.5.2"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
@@ -3260,9 +3259,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.7.1"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
|
||||
[[package]]
|
||||
name = "ureq"
|
||||
@@ -3393,9 +3392,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.89"
|
||||
version = "0.2.90"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
|
||||
checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
@@ -3403,9 +3402,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.89"
|
||||
version = "0.2.90"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
|
||||
checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
@@ -3430,9 +3429,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.89"
|
||||
version = "0.2.90"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
|
||||
checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@@ -3440,9 +3439,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.89"
|
||||
version = "0.2.90"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
|
||||
checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3453,9 +3452,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.89"
|
||||
version = "0.2.90"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
|
||||
checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test"
|
||||
@@ -3494,9 +3493,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.25.2"
|
||||
version = "0.25.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc"
|
||||
checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10"
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
|
||||
@@ -16,7 +16,7 @@ aho-corasick = { version = "1.1.2" }
|
||||
annotate-snippets = { version = "0.9.2", features = ["color"] }
|
||||
anyhow = { version = "1.0.79" }
|
||||
argfile = { version = "0.1.6" }
|
||||
assert_cmd = { version = "2.0.8" }
|
||||
assert_cmd = { version = "2.0.13" }
|
||||
bincode = { version = "1.3.3" }
|
||||
bitflags = { version = "2.4.1" }
|
||||
cachedir = { version = "0.3.1" }
|
||||
@@ -50,7 +50,7 @@ insta-cmd = { version = "0.4.0" }
|
||||
is-macro = { version = "0.3.4" }
|
||||
is-wsl = { version = "0.4.0" }
|
||||
itertools = { version = "0.12.0" }
|
||||
js-sys = { version = "0.3.66" }
|
||||
js-sys = { version = "0.3.67" }
|
||||
lalrpop-util = { version = "0.20.0", default-features = false }
|
||||
lexical-parse-float = { version = "0.8.0", features = ["format"] }
|
||||
libcst = { version = "1.1.0", default-features = false }
|
||||
@@ -75,7 +75,7 @@ result-like = { version = "0.5.0" }
|
||||
rustc-hash = { version = "1.1.0" }
|
||||
schemars = { version = "0.8.16" }
|
||||
seahash = { version ="4.1.0"}
|
||||
semver = { version = "1.0.20" }
|
||||
semver = { version = "1.0.21" }
|
||||
serde = { version = "1.0.195", features = ["derive"] }
|
||||
serde-wasm-bindgen = { version = "0.6.3" }
|
||||
serde_json = { version = "1.0.109" }
|
||||
@@ -83,7 +83,7 @@ serde_test = { version = "1.0.152" }
|
||||
serde_with = { version = "3.4.0", default-features = false, features = ["macros"] }
|
||||
shellexpand = { version = "3.0.0" }
|
||||
shlex = { version ="1.2.0"}
|
||||
similar = { version = "2.3.0", features = ["inline"] }
|
||||
similar = { version = "2.4.0", features = ["inline"] }
|
||||
smallvec = { version = "1.11.2" }
|
||||
static_assertions = "1.1.0"
|
||||
strum = { version = "0.25.0", features = ["strum_macros"] }
|
||||
|
||||
@@ -150,7 +150,7 @@ Ruff can also be used as a [pre-commit](https://pre-commit.com/) hook via [`ruff
|
||||
```yaml
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.1.11
|
||||
rev: v0.1.14
|
||||
hooks:
|
||||
# Run the linter.
|
||||
- id: ruff
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_cli"
|
||||
version = "0.1.11"
|
||||
name = "ruff"
|
||||
version = "0.1.14"
|
||||
publish = false
|
||||
authors = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
@@ -10,9 +10,7 @@ documentation = { workspace = true }
|
||||
repository = { workspace = true }
|
||||
license = { workspace = true }
|
||||
readme = "../../README.md"
|
||||
|
||||
[[bin]]
|
||||
name = "ruff"
|
||||
default-run = "ruff"
|
||||
|
||||
[dependencies]
|
||||
ruff_cache = { path = "../ruff_cache" }
|
||||
@@ -83,7 +83,7 @@ pub enum Command {
|
||||
},
|
||||
}
|
||||
|
||||
// The `Parser` derive is for ruff_dev, for ruff_cli `Args` would be sufficient
|
||||
// The `Parser` derive is for ruff_dev, for ruff `Args` would be sufficient
|
||||
#[derive(Clone, Debug, clap::Parser)]
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
pub struct CheckCommand {
|
||||
@@ -290,6 +290,10 @@ pub struct CheckCommand {
|
||||
/// The name of the file when passing it through stdin.
|
||||
#[arg(long, help_heading = "Miscellaneous")]
|
||||
pub stdin_filename: Option<PathBuf>,
|
||||
/// List of mappings from file extension to language (one of ["python", "ipynb", "pyi"]). For
|
||||
/// example, to treat `.ipy` files as IPython notebooks, use `--extension ipy:ipynb`.
|
||||
#[arg(long, value_delimiter = ',')]
|
||||
pub extension: Option<Vec<ExtensionPair>>,
|
||||
/// Exit with status code "0", even upon detecting lint violations.
|
||||
#[arg(
|
||||
short,
|
||||
@@ -352,9 +356,6 @@ pub struct CheckCommand {
|
||||
conflicts_with = "watch",
|
||||
)]
|
||||
pub show_settings: bool,
|
||||
/// List of mappings from file extension to language (one of ["python", "ipynb", "pyi"]).
|
||||
#[arg(long, value_delimiter = ',', hide = true)]
|
||||
pub extension: Option<Vec<ExtensionPair>>,
|
||||
/// Dev-only argument to show fixes
|
||||
#[arg(long, hide = true)]
|
||||
pub ecosystem_ci: bool,
|
||||
@@ -423,6 +424,10 @@ pub struct FormatCommand {
|
||||
/// The name of the file when passing it through stdin.
|
||||
#[arg(long, help_heading = "Miscellaneous")]
|
||||
pub stdin_filename: Option<PathBuf>,
|
||||
/// List of mappings from file extension to language (one of ["python", "ipynb", "pyi"]). For
|
||||
/// example, to treat `.ipy` files as IPython notebooks, use `--extension ipy:ipynb`.
|
||||
#[arg(long, value_delimiter = ',')]
|
||||
pub extension: Option<Vec<ExtensionPair>>,
|
||||
/// The minimum Python version that should be supported.
|
||||
#[arg(long, value_enum)]
|
||||
pub target_version: Option<PythonVersion>,
|
||||
@@ -571,6 +576,7 @@ impl FormatCommand {
|
||||
force_exclude: resolve_bool_arg(self.force_exclude, self.no_force_exclude),
|
||||
target_version: self.target_version,
|
||||
cache_dir: self.cache_dir,
|
||||
extension: self.extension,
|
||||
|
||||
// Unsupported on the formatter CLI, but required on `Overrides`.
|
||||
..CliOverrides::default()
|
||||
@@ -739,7 +745,7 @@ impl ConfigurationTransformer for CliOverrides {
|
||||
config.target_version = Some(*target_version);
|
||||
}
|
||||
if let Some(extension) = &self.extension {
|
||||
config.lint.extension = Some(extension.clone().into_iter().collect());
|
||||
config.extension = Some(extension.iter().cloned().collect());
|
||||
}
|
||||
|
||||
config
|
||||
@@ -106,13 +106,19 @@ pub(crate) fn format(
|
||||
match entry {
|
||||
Ok(resolved_file) => {
|
||||
let path = resolved_file.path();
|
||||
let SourceType::Python(source_type) = SourceType::from(&path) else {
|
||||
// Ignore any non-Python files.
|
||||
return None;
|
||||
};
|
||||
|
||||
let settings = resolver.resolve(path);
|
||||
|
||||
let source_type = match settings.formatter.extension.get(path) {
|
||||
None => match SourceType::from(path) {
|
||||
SourceType::Python(source_type) => source_type,
|
||||
SourceType::Toml(_) => {
|
||||
// Ignore any non-Python files.
|
||||
return None;
|
||||
}
|
||||
},
|
||||
Some(language) => PySourceType::from(language),
|
||||
};
|
||||
|
||||
// Ignore files that are excluded from formatting
|
||||
if (settings.file_resolver.force_exclude || !resolved_file.is_root())
|
||||
&& match_exclusion(
|
||||
@@ -53,16 +53,23 @@ pub(crate) fn format_stdin(cli: &FormatArguments, overrides: &CliOverrides) -> R
|
||||
}
|
||||
|
||||
let path = cli.stdin_filename.as_deref();
|
||||
let settings = &resolver.base_settings().formatter;
|
||||
|
||||
let SourceType::Python(source_type) = path.map(SourceType::from).unwrap_or_default() else {
|
||||
if mode.is_write() {
|
||||
parrot_stdin()?;
|
||||
}
|
||||
return Ok(ExitStatus::Success);
|
||||
let source_type = match path.and_then(|path| settings.extension.get(path)) {
|
||||
None => match path.map(SourceType::from).unwrap_or_default() {
|
||||
SourceType::Python(source_type) => source_type,
|
||||
SourceType::Toml(_) => {
|
||||
if mode.is_write() {
|
||||
parrot_stdin()?;
|
||||
}
|
||||
return Ok(ExitStatus::Success);
|
||||
}
|
||||
},
|
||||
Some(language) => PySourceType::from(language),
|
||||
};
|
||||
|
||||
// Format the file.
|
||||
match format_source_code(path, &resolver.base_settings().formatter, source_type, mode) {
|
||||
match format_source_code(path, settings, source_type, mode) {
|
||||
Ok(result) => match mode {
|
||||
FormatMode::Write => Ok(ExitStatus::Success),
|
||||
FormatMode::Check | FormatMode::Diff => {
|
||||
@@ -35,7 +35,7 @@ pub(crate) fn show_settings(
|
||||
if let Some(settings_path) = pyproject_config.path.as_ref() {
|
||||
writeln!(writer, "Settings path: {settings_path:?}")?;
|
||||
}
|
||||
writeln!(writer, "{settings:#?}")?;
|
||||
write!(writer, "{settings}")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff_cli/src/commands/check.rs
|
||||
source: crates/ruff/src/commands/check.rs
|
||||
---
|
||||
/home/ferris/project/code.py:1:1: E902 Permission denied (os error 13)
|
||||
/home/ferris/project/notebook.ipynb:1:1: E902 Permission denied (os error 13)
|
||||
@@ -17,7 +17,7 @@ use ruff_linter::logging::DisplayParseError;
|
||||
use ruff_linter::message::Message;
|
||||
use ruff_linter::pyproject_toml::lint_pyproject_toml;
|
||||
use ruff_linter::registry::AsRule;
|
||||
use ruff_linter::settings::types::{ExtensionMapping, UnsafeFixes};
|
||||
use ruff_linter::settings::types::UnsafeFixes;
|
||||
use ruff_linter::settings::{flags, LinterSettings};
|
||||
use ruff_linter::source_kind::{SourceError, SourceKind};
|
||||
use ruff_linter::{fs, IOError, SyntaxError};
|
||||
@@ -179,11 +179,6 @@ impl AddAssign for FixMap {
|
||||
}
|
||||
}
|
||||
|
||||
fn override_source_type(path: Option<&Path>, extension: &ExtensionMapping) -> Option<PySourceType> {
|
||||
let ext = path?.extension()?.to_str()?;
|
||||
extension.get(ext).map(PySourceType::from)
|
||||
}
|
||||
|
||||
/// Lint the source code at the given `Path`.
|
||||
pub(crate) fn lint_path(
|
||||
path: &Path,
|
||||
@@ -228,7 +223,7 @@ pub(crate) fn lint_path(
|
||||
|
||||
debug!("Checking: {}", path.display());
|
||||
|
||||
let source_type = match override_source_type(Some(path), &settings.extension) {
|
||||
let source_type = match settings.extension.get(path).map(PySourceType::from) {
|
||||
Some(source_type) => source_type,
|
||||
None => match SourceType::from(path) {
|
||||
SourceType::Toml(TomlSourceType::Pyproject) => {
|
||||
@@ -398,15 +393,14 @@ pub(crate) fn lint_stdin(
|
||||
fix_mode: flags::FixMode,
|
||||
) -> Result<Diagnostics> {
|
||||
// TODO(charlie): Support `pyproject.toml`.
|
||||
let source_type = if let Some(source_type) =
|
||||
override_source_type(path, &settings.linter.extension)
|
||||
{
|
||||
source_type
|
||||
} else {
|
||||
let SourceType::Python(source_type) = path.map(SourceType::from).unwrap_or_default() else {
|
||||
return Ok(Diagnostics::default());
|
||||
};
|
||||
source_type
|
||||
let source_type = match path.and_then(|path| settings.linter.extension.get(path)) {
|
||||
None => match path.map(SourceType::from).unwrap_or_default() {
|
||||
SourceType::Python(source_type) => source_type,
|
||||
SourceType::Toml(_) => {
|
||||
return Ok(Diagnostics::default());
|
||||
}
|
||||
},
|
||||
Some(language) => PySourceType::from(language),
|
||||
};
|
||||
|
||||
// Extract the sources from the file.
|
||||
@@ -3,8 +3,8 @@ use std::process::ExitCode;
|
||||
use clap::{Parser, Subcommand};
|
||||
use colored::Colorize;
|
||||
|
||||
use ruff_cli::args::{Args, Command};
|
||||
use ruff_cli::{run, ExitStatus};
|
||||
use ruff::args::{Args, Command};
|
||||
use ruff::{run, ExitStatus};
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[global_allocator]
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
source: crates/ruff/src/version.rs
|
||||
expression: version
|
||||
---
|
||||
0.0.0
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff_cli/src/version.rs
|
||||
source: crates/ruff/src/version.rs
|
||||
expression: version
|
||||
---
|
||||
0.0.0 (53b0f5d92 2023-10-19)
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff_cli/src/version.rs
|
||||
source: crates/ruff/src/version.rs
|
||||
expression: version
|
||||
---
|
||||
0.0.0+24 (53b0f5d92 2023-10-19)
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff_cli/src/version.rs
|
||||
source: crates/ruff/src/version.rs
|
||||
expression: version
|
||||
---
|
||||
{
|
||||
@@ -1468,3 +1468,73 @@ fn test_notebook_trailing_semicolon() {
|
||||
----- stderr -----
|
||||
"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extension() -> Result<()> {
|
||||
let tempdir = TempDir::new()?;
|
||||
|
||||
let ruff_toml = tempdir.path().join("ruff.toml");
|
||||
fs::write(
|
||||
&ruff_toml,
|
||||
r#"
|
||||
include = ["*.ipy"]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
fs::write(
|
||||
tempdir.path().join("main.ipy"),
|
||||
r#"
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "ad6f36d9-4b7d-4562-8d00-f15a0f1fbb6d",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"x=1"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.12.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
"#,
|
||||
)?;
|
||||
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.current_dir(tempdir.path())
|
||||
.arg("format")
|
||||
.arg("--no-cache")
|
||||
.args(["--config", &ruff_toml.file_name().unwrap().to_string_lossy()])
|
||||
.args(["--extension", "ipy:ipynb"])
|
||||
.arg("."), @r###"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
1 file reformatted
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
Ok(())
|
||||
}
|
||||
@@ -20,9 +20,9 @@ use path_absolutize::path_dedot;
|
||||
use tempfile::TempDir;
|
||||
|
||||
#[cfg(unix)]
|
||||
use ruff_cli::args::Args;
|
||||
use ruff::args::Args;
|
||||
#[cfg(unix)]
|
||||
use ruff_cli::run;
|
||||
use ruff::run;
|
||||
|
||||
const BIN_NAME: &str = "ruff";
|
||||
|
||||
@@ -841,8 +841,9 @@ fn nursery_direct() {
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
-:1:2: E225 Missing whitespace around operator
|
||||
-:1:2: E225 [*] Missing whitespace around operator
|
||||
Found 1 error.
|
||||
[*] 1 fixable with the `--fix` option.
|
||||
|
||||
----- stderr -----
|
||||
warning: Selection of nursery rule `E225` without the `--preview` flag is deprecated.
|
||||
@@ -859,8 +860,9 @@ fn nursery_group_selector() {
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
-:1:1: CPY001 Missing copyright notice at top of file
|
||||
-:1:2: E225 Missing whitespace around operator
|
||||
-:1:2: E225 [*] Missing whitespace around operator
|
||||
Found 2 errors.
|
||||
[*] 1 fixable with the `--fix` option.
|
||||
|
||||
----- stderr -----
|
||||
warning: The `NURSERY` selector has been deprecated. Use the `--preview` flag instead.
|
||||
@@ -1656,3 +1658,65 @@ def log(x, base) -> float:
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fix_preview() -> Result<()> {
|
||||
let tempdir = TempDir::new()?;
|
||||
let ruff_toml = tempdir.path().join("ruff.toml");
|
||||
fs::write(
|
||||
&ruff_toml,
|
||||
r#"
|
||||
[lint]
|
||||
preview = true
|
||||
explicit-preview-rules = true
|
||||
select = ["RUF017"]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let mut cmd = RuffCheck::default().config(&ruff_toml).build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("x = [1, 2, 3]\ny = [4, 5, 6]\nsum([x, y], [])"),
|
||||
@r###"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
-:3:1: RUF017 Avoid quadratic list summation
|
||||
Found 1 error.
|
||||
No fixes available (1 hidden fix can be enabled with the `--unsafe-fixes` option).
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unfixable_preview() -> Result<()> {
|
||||
let tempdir = TempDir::new()?;
|
||||
let ruff_toml = tempdir.path().join("ruff.toml");
|
||||
fs::write(
|
||||
&ruff_toml,
|
||||
r#"
|
||||
[lint]
|
||||
preview = true
|
||||
explicit-preview-rules = true
|
||||
select = ["RUF017"]
|
||||
unfixable = ["RUF"]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let mut cmd = RuffCheck::default().config(&ruff_toml).build();
|
||||
assert_cmd_snapshot!(cmd
|
||||
.pass_stdin("x = [1, 2, 3]\ny = [4, 5, 6]\nsum([x, y], [])"),
|
||||
@r###"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
-:3:1: RUF017 Avoid quadratic list summation
|
||||
Found 1 error.
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -436,3 +436,75 @@ ignore = ["D203", "D212"]
|
||||
"###);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extension() -> Result<()> {
|
||||
let tempdir = TempDir::new()?;
|
||||
|
||||
let ruff_toml = tempdir.path().join("ruff.toml");
|
||||
fs::write(
|
||||
&ruff_toml,
|
||||
r#"
|
||||
include = ["*.ipy"]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
fs::write(
|
||||
tempdir.path().join("main.ipy"),
|
||||
r#"
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "ad6f36d9-4b7d-4562-8d00-f15a0f1fbb6d",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.12.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
"#,
|
||||
)?;
|
||||
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.current_dir(tempdir.path())
|
||||
.arg("check")
|
||||
.args(STDIN_BASE_OPTIONS)
|
||||
.args(["--config", &ruff_toml.file_name().unwrap().to_string_lossy()])
|
||||
.args(["--extension", "ipy:ipynb"])
|
||||
.arg("."), @r###"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
main.ipy:cell 1:1:8: F401 [*] `os` imported but unused
|
||||
Found 1 error.
|
||||
[*] 1 fixable with the `--fix` option.
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
Ok(())
|
||||
}
|
||||
29
crates/ruff/tests/show_settings.rs
Normal file
29
crates/ruff/tests/show_settings.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
use insta_cmd::{assert_cmd_snapshot, get_cargo_bin};
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
const BIN_NAME: &str = "ruff";
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
const TEST_FILTERS: &[(&str, &str)] = &[
|
||||
("\"[^\\*\"]*/pyproject.toml", "\"[BASEPATH]/pyproject.toml"),
|
||||
("\".*/crates", "\"[BASEPATH]/crates"),
|
||||
("\".*/\\.ruff_cache", "\"[BASEPATH]/.ruff_cache"),
|
||||
("\".*/ruff\"", "\"[BASEPATH]\""),
|
||||
];
|
||||
#[cfg(target_os = "windows")]
|
||||
const TEST_FILTERS: &[(&str, &str)] = &[
|
||||
(r#""[^\*"]*\\pyproject.toml"#, "\"[BASEPATH]/pyproject.toml"),
|
||||
(r#"".*\\crates"#, "\"[BASEPATH]/crates"),
|
||||
(r#"".*\\\.ruff_cache"#, "\"[BASEPATH]/.ruff_cache"),
|
||||
(r#"".*\\ruff""#, "\"[BASEPATH]\""),
|
||||
(r#"\\+(\w\w|\s|")"#, "/$1"),
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn display_default_settings() {
|
||||
insta::with_settings!({ filters => TEST_FILTERS.to_vec() }, {
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(["check", "--show-settings", "unformatted.py"]).current_dir(Path::new("./resources/test/fixtures")));
|
||||
});
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff_cli/tests/integration_test.rs
|
||||
source: crates/ruff/tests/integration_test.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
source: crates/ruff_cli/tests/integration_test.rs
|
||||
source: crates/ruff/tests/integration_test.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
@@ -0,0 +1,368 @@
|
||||
---
|
||||
source: crates/ruff/tests/show_settings.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
- check
|
||||
- "--show-settings"
|
||||
- unformatted.py
|
||||
---
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
Resolved settings for: "[BASEPATH]/crates/ruff/resources/test/fixtures/unformatted.py"
|
||||
Settings path: "[BASEPATH]/pyproject.toml"
|
||||
|
||||
# General Settings
|
||||
cache_dir = "[BASEPATH]/.ruff_cache"
|
||||
fix = false
|
||||
fix_only = false
|
||||
output_format = text
|
||||
show_fixes = false
|
||||
show_source = false
|
||||
unsafe_fixes = hint
|
||||
|
||||
# File Resolver Settings
|
||||
file_resolver.exclude = [
|
||||
".bzr",
|
||||
".direnv",
|
||||
".eggs",
|
||||
".git",
|
||||
".git-rewrite",
|
||||
".hg",
|
||||
".ipynb_checkpoints",
|
||||
".mypy_cache",
|
||||
".nox",
|
||||
".pants.d",
|
||||
".pyenv",
|
||||
".pytest_cache",
|
||||
".pytype",
|
||||
".ruff_cache",
|
||||
".svn",
|
||||
".tox",
|
||||
".venv",
|
||||
".vscode",
|
||||
"__pypackages__",
|
||||
"_build",
|
||||
"buck-out",
|
||||
"build",
|
||||
"dist",
|
||||
"node_modules",
|
||||
"site-packages",
|
||||
"venv",
|
||||
]
|
||||
file_resolver.extend_exclude = [
|
||||
"crates/ruff_linter/resources/",
|
||||
"crates/ruff_python_formatter/resources/",
|
||||
]
|
||||
file_resolver.force_exclude = false
|
||||
file_resolver.include = [
|
||||
"*.py",
|
||||
"*.pyi",
|
||||
"**/pyproject.toml",
|
||||
]
|
||||
file_resolver.extend_include = []
|
||||
file_resolver.respect_gitignore = true
|
||||
file_resolver.project_root = "[BASEPATH]"
|
||||
|
||||
# Linter Settings
|
||||
linter.exclude = []
|
||||
linter.project_root = "[BASEPATH]"
|
||||
linter.rules.enabled = [
|
||||
MultipleImportsOnOneLine,
|
||||
ModuleImportNotAtTopOfFile,
|
||||
MultipleStatementsOnOneLineColon,
|
||||
MultipleStatementsOnOneLineSemicolon,
|
||||
UselessSemicolon,
|
||||
NoneComparison,
|
||||
TrueFalseComparison,
|
||||
NotInTest,
|
||||
NotIsTest,
|
||||
TypeComparison,
|
||||
BareExcept,
|
||||
LambdaAssignment,
|
||||
AmbiguousVariableName,
|
||||
AmbiguousClassName,
|
||||
AmbiguousFunctionName,
|
||||
IOError,
|
||||
SyntaxError,
|
||||
UnusedImport,
|
||||
ImportShadowedByLoopVar,
|
||||
UndefinedLocalWithImportStar,
|
||||
LateFutureImport,
|
||||
UndefinedLocalWithImportStarUsage,
|
||||
UndefinedLocalWithNestedImportStarUsage,
|
||||
FutureFeatureNotDefined,
|
||||
PercentFormatInvalidFormat,
|
||||
PercentFormatExpectedMapping,
|
||||
PercentFormatExpectedSequence,
|
||||
PercentFormatExtraNamedArguments,
|
||||
PercentFormatMissingArgument,
|
||||
PercentFormatMixedPositionalAndNamed,
|
||||
PercentFormatPositionalCountMismatch,
|
||||
PercentFormatStarRequiresSequence,
|
||||
PercentFormatUnsupportedFormatCharacter,
|
||||
StringDotFormatInvalidFormat,
|
||||
StringDotFormatExtraNamedArguments,
|
||||
StringDotFormatExtraPositionalArguments,
|
||||
StringDotFormatMissingArguments,
|
||||
StringDotFormatMixingAutomatic,
|
||||
FStringMissingPlaceholders,
|
||||
MultiValueRepeatedKeyLiteral,
|
||||
MultiValueRepeatedKeyVariable,
|
||||
ExpressionsInStarAssignment,
|
||||
MultipleStarredExpressions,
|
||||
AssertTuple,
|
||||
IsLiteral,
|
||||
InvalidPrintSyntax,
|
||||
IfTuple,
|
||||
BreakOutsideLoop,
|
||||
ContinueOutsideLoop,
|
||||
YieldOutsideFunction,
|
||||
ReturnOutsideFunction,
|
||||
DefaultExceptNotLast,
|
||||
ForwardAnnotationSyntaxError,
|
||||
RedefinedWhileUnused,
|
||||
UndefinedName,
|
||||
UndefinedExport,
|
||||
UndefinedLocal,
|
||||
UnusedVariable,
|
||||
UnusedAnnotation,
|
||||
RaiseNotImplemented,
|
||||
]
|
||||
linter.rules.should_fix = [
|
||||
MultipleImportsOnOneLine,
|
||||
ModuleImportNotAtTopOfFile,
|
||||
MultipleStatementsOnOneLineColon,
|
||||
MultipleStatementsOnOneLineSemicolon,
|
||||
UselessSemicolon,
|
||||
NoneComparison,
|
||||
TrueFalseComparison,
|
||||
NotInTest,
|
||||
NotIsTest,
|
||||
TypeComparison,
|
||||
BareExcept,
|
||||
LambdaAssignment,
|
||||
AmbiguousVariableName,
|
||||
AmbiguousClassName,
|
||||
AmbiguousFunctionName,
|
||||
IOError,
|
||||
SyntaxError,
|
||||
UnusedImport,
|
||||
ImportShadowedByLoopVar,
|
||||
UndefinedLocalWithImportStar,
|
||||
LateFutureImport,
|
||||
UndefinedLocalWithImportStarUsage,
|
||||
UndefinedLocalWithNestedImportStarUsage,
|
||||
FutureFeatureNotDefined,
|
||||
PercentFormatInvalidFormat,
|
||||
PercentFormatExpectedMapping,
|
||||
PercentFormatExpectedSequence,
|
||||
PercentFormatExtraNamedArguments,
|
||||
PercentFormatMissingArgument,
|
||||
PercentFormatMixedPositionalAndNamed,
|
||||
PercentFormatPositionalCountMismatch,
|
||||
PercentFormatStarRequiresSequence,
|
||||
PercentFormatUnsupportedFormatCharacter,
|
||||
StringDotFormatInvalidFormat,
|
||||
StringDotFormatExtraNamedArguments,
|
||||
StringDotFormatExtraPositionalArguments,
|
||||
StringDotFormatMissingArguments,
|
||||
StringDotFormatMixingAutomatic,
|
||||
FStringMissingPlaceholders,
|
||||
MultiValueRepeatedKeyLiteral,
|
||||
MultiValueRepeatedKeyVariable,
|
||||
ExpressionsInStarAssignment,
|
||||
MultipleStarredExpressions,
|
||||
AssertTuple,
|
||||
IsLiteral,
|
||||
InvalidPrintSyntax,
|
||||
IfTuple,
|
||||
BreakOutsideLoop,
|
||||
ContinueOutsideLoop,
|
||||
YieldOutsideFunction,
|
||||
ReturnOutsideFunction,
|
||||
DefaultExceptNotLast,
|
||||
ForwardAnnotationSyntaxError,
|
||||
RedefinedWhileUnused,
|
||||
UndefinedName,
|
||||
UndefinedExport,
|
||||
UndefinedLocal,
|
||||
UnusedVariable,
|
||||
UnusedAnnotation,
|
||||
RaiseNotImplemented,
|
||||
]
|
||||
linter.per_file_ignores = {}
|
||||
linter.safety_table.forced_safe = []
|
||||
linter.safety_table.forced_unsafe = []
|
||||
linter.target_version = Py37
|
||||
linter.preview = disabled
|
||||
linter.explicit_preview_rules = false
|
||||
linter.extension.mapping = {}
|
||||
linter.allowed_confusables = []
|
||||
linter.builtins = []
|
||||
linter.dummy_variable_rgx = ^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$
|
||||
linter.external = []
|
||||
linter.ignore_init_module_imports = false
|
||||
linter.logger_objects = []
|
||||
linter.namespace_packages = []
|
||||
linter.src = ["[BASEPATH]"]
|
||||
linter.tab_size = 4
|
||||
linter.line_length = 88
|
||||
linter.task_tags = [
|
||||
TODO,
|
||||
FIXME,
|
||||
XXX,
|
||||
]
|
||||
linter.typing_modules = []
|
||||
|
||||
# Linter Plugins
|
||||
linter.flake8_annotations.mypy_init_return = false
|
||||
linter.flake8_annotations.suppress_dummy_args = false
|
||||
linter.flake8_annotations.suppress_none_returning = false
|
||||
linter.flake8_annotations.allow_star_arg_any = false
|
||||
linter.flake8_annotations.ignore_fully_untyped = false
|
||||
linter.flake8_bandit.hardcoded_tmp_directory = [
|
||||
/tmp,
|
||||
/var/tmp,
|
||||
/dev/shm,
|
||||
]
|
||||
linter.flake8_bandit.check_typed_exception = false
|
||||
linter.flake8_bugbear.extend_immutable_calls = []
|
||||
linter.flake8_builtins.builtins_ignorelist = []
|
||||
linter.flake8_comprehensions.allow_dict_calls_with_keyword_arguments = false
|
||||
linter.flake8_copyright.notice_rgx = (?i)Copyright\s+(\(C\)\s+)?\d{4}(-\d{4})*
|
||||
linter.flake8_copyright.author = none
|
||||
linter.flake8_copyright.min_file_size = 0
|
||||
linter.flake8_errmsg.max_string_length = 0
|
||||
linter.flake8_gettext.functions_names = [
|
||||
_,
|
||||
gettext,
|
||||
ngettext,
|
||||
]
|
||||
linter.flake8_implicit_str_concat.allow_multiline = true
|
||||
linter.flake8_import_conventions.aliases = {"matplotlib": "mpl", "matplotlib.pyplot": "plt", "pandas": "pd", "seaborn": "sns", "tensorflow": "tf", "networkx": "nx", "plotly.express": "px", "polars": "pl", "numpy": "np", "panel": "pn", "pyarrow": "pa", "altair": "alt", "tkinter": "tk", "holoviews": "hv"}
|
||||
linter.flake8_import_conventions.banned_aliases = {}
|
||||
linter.flake8_import_conventions.banned_from = []
|
||||
linter.flake8_pytest_style.fixture_parentheses = true
|
||||
linter.flake8_pytest_style.parametrize_names_type = tuple
|
||||
linter.flake8_pytest_style.parametrize_values_type = list
|
||||
linter.flake8_pytest_style.parametrize_values_row_type = tuple
|
||||
linter.flake8_pytest_style.raises_require_match_for = [
|
||||
BaseException,
|
||||
Exception,
|
||||
ValueError,
|
||||
OSError,
|
||||
IOError,
|
||||
EnvironmentError,
|
||||
socket.error,
|
||||
]
|
||||
linter.flake8_pytest_style.raises_extend_require_match_for = []
|
||||
linter.flake8_pytest_style.mark_parentheses = true
|
||||
linter.flake8_quotes.inline_quotes = double
|
||||
linter.flake8_quotes.multiline_quotes = double
|
||||
linter.flake8_quotes.docstring_quotes = double
|
||||
linter.flake8_quotes.avoid_escape = true
|
||||
linter.flake8_self.ignore_names = [
|
||||
_make,
|
||||
_asdict,
|
||||
_replace,
|
||||
_fields,
|
||||
_field_defaults,
|
||||
_name_,
|
||||
_value_,
|
||||
]
|
||||
linter.flake8_tidy_imports.ban_relative_imports = "parents"
|
||||
linter.flake8_tidy_imports.banned_api = {}
|
||||
linter.flake8_tidy_imports.banned_module_level_imports = []
|
||||
linter.flake8_type_checking.strict = false
|
||||
linter.flake8_type_checking.exempt_modules = [
|
||||
typing,
|
||||
typing_extensions,
|
||||
]
|
||||
linter.flake8_type_checking.runtime_required_base_classes = []
|
||||
linter.flake8_type_checking.runtime_required_decorators = []
|
||||
linter.flake8_type_checking.quote_annotations = false
|
||||
linter.flake8_unused_arguments.ignore_variadic_names = false
|
||||
linter.isort.required_imports = []
|
||||
linter.isort.combine_as_imports = false
|
||||
linter.isort.force_single_line = false
|
||||
linter.isort.force_sort_within_sections = false
|
||||
linter.isort.detect_same_package = true
|
||||
linter.isort.case_sensitive = false
|
||||
linter.isort.force_wrap_aliases = false
|
||||
linter.isort.force_to_top = []
|
||||
linter.isort.known_modules = {}
|
||||
linter.isort.order_by_type = true
|
||||
linter.isort.relative_imports_order = furthest_to_closest
|
||||
linter.isort.single_line_exclusions = []
|
||||
linter.isort.split_on_trailing_comma = true
|
||||
linter.isort.classes = []
|
||||
linter.isort.constants = []
|
||||
linter.isort.variables = []
|
||||
linter.isort.no_lines_before = []
|
||||
linter.isort.lines_after_imports = -1
|
||||
linter.isort.lines_between_types = 0
|
||||
linter.isort.forced_separate = []
|
||||
linter.isort.section_order = [
|
||||
known { type = future },
|
||||
known { type = standard_library },
|
||||
known { type = third_party },
|
||||
known { type = first_party },
|
||||
known { type = local_folder },
|
||||
]
|
||||
linter.isort.no_sections = false
|
||||
linter.isort.from_first = false
|
||||
linter.isort.length_sort = false
|
||||
linter.isort.length_sort_straight = false
|
||||
linter.mccabe.max_complexity = 10
|
||||
linter.pep8_naming.ignore_names = [
|
||||
setUp,
|
||||
tearDown,
|
||||
setUpClass,
|
||||
tearDownClass,
|
||||
setUpModule,
|
||||
tearDownModule,
|
||||
asyncSetUp,
|
||||
asyncTearDown,
|
||||
setUpTestData,
|
||||
failureException,
|
||||
longMessage,
|
||||
maxDiff,
|
||||
]
|
||||
linter.pep8_naming.classmethod_decorators = []
|
||||
linter.pep8_naming.staticmethod_decorators = []
|
||||
linter.pycodestyle.max_line_length = 88
|
||||
linter.pycodestyle.max_doc_length = none
|
||||
linter.pycodestyle.ignore_overlong_task_comments = false
|
||||
linter.pyflakes.extend_generics = []
|
||||
linter.pylint.allow_magic_value_types = [
|
||||
str,
|
||||
bytes,
|
||||
]
|
||||
linter.pylint.allow_dunder_method_names = []
|
||||
linter.pylint.max_args = 5
|
||||
linter.pylint.max_positional_args = 5
|
||||
linter.pylint.max_returns = 6
|
||||
linter.pylint.max_bool_expr = 5
|
||||
linter.pylint.max_branches = 12
|
||||
linter.pylint.max_statements = 50
|
||||
linter.pylint.max_public_methods = 20
|
||||
linter.pylint.max_locals = 15
|
||||
linter.pyupgrade.keep_runtime_typing = false
|
||||
|
||||
# Formatter Settings
|
||||
formatter.exclude = []
|
||||
formatter.target_version = Py37
|
||||
formatter.preview = disabled
|
||||
formatter.line_width = 88
|
||||
formatter.line_ending = auto
|
||||
formatter.indent_style = space
|
||||
formatter.indent_width = 4
|
||||
formatter.quote_style = double
|
||||
formatter.magic_trailing_comma = respect
|
||||
formatter.docstring_code_format = disabled
|
||||
formatter.docstring_code_line_width = dynamic
|
||||
|
||||
----- stderr -----
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# Ruff Benchmarks
|
||||
|
||||
The `ruff_benchmark` crate benchmarks the linter and the formatter on individual files.
|
||||
The `ruff_benchmark` crate benchmarks the linter and the formatter on individual files:
|
||||
|
||||
```shell
|
||||
# Run once on the "baseline".
|
||||
cargo bench -p ruff_benchmark -- --save-baseline=main
|
||||
|
||||
# Compare against the "baseline".
|
||||
cargo bench -p ruff_benchmark -- --baseline=main
|
||||
|
||||
# Run the lexer benchmarks.
|
||||
cargo bench -p ruff_benchmark lexer -- --baseline=main
|
||||
```
|
||||
|
||||
See [CONTRIBUTING.md](../../CONTRIBUTING.md) on how to use these benchmarks.
|
||||
|
||||
@@ -7,7 +7,7 @@ use ruff_benchmark::{TestCase, TestFile, TestFileDownloadError};
|
||||
use ruff_python_formatter::{format_module_ast, PreviewMode, PyFormatOptions};
|
||||
use ruff_python_index::CommentRangesBuilder;
|
||||
use ruff_python_parser::lexer::lex;
|
||||
use ruff_python_parser::{parse_tokens, Mode};
|
||||
use ruff_python_parser::{allocate_tokens_vec, parse_tokens, Mode};
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[global_allocator]
|
||||
@@ -52,7 +52,7 @@ fn benchmark_formatter(criterion: &mut Criterion) {
|
||||
BenchmarkId::from_parameter(case.name()),
|
||||
&case,
|
||||
|b, case| {
|
||||
let mut tokens = Vec::new();
|
||||
let mut tokens = allocate_tokens_vec(case.code());
|
||||
let mut comment_ranges = CommentRangesBuilder::default();
|
||||
|
||||
for result in lex(case.code(), Mode::Module) {
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
source: crates/ruff_cli/src/version.rs
|
||||
expression: version
|
||||
---
|
||||
0.0.0
|
||||
@@ -11,14 +11,14 @@ repository = { workspace = true }
|
||||
license = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
ruff_linter = { path = "../ruff_linter", features = ["schemars"] }
|
||||
ruff_cli = { path = "../ruff_cli" }
|
||||
ruff = { path = "../ruff" }
|
||||
ruff_diagnostics = { path = "../ruff_diagnostics" }
|
||||
ruff_formatter = { path = "../ruff_formatter" }
|
||||
ruff_linter = { path = "../ruff_linter", features = ["schemars"] }
|
||||
ruff_notebook = { path = "../ruff_notebook" }
|
||||
ruff_python_ast = { path = "../ruff_python_ast" }
|
||||
ruff_python_codegen = { path = "../ruff_python_codegen" }
|
||||
ruff_python_formatter = { path = "../ruff_python_formatter" }
|
||||
ruff_notebook = { path = "../ruff_notebook" }
|
||||
ruff_python_parser = { path = "../ruff_python_parser" }
|
||||
ruff_python_stdlib = { path = "../ruff_python_stdlib" }
|
||||
ruff_python_trivia = { path = "../ruff_python_trivia" }
|
||||
|
||||
@@ -27,8 +27,8 @@ use tracing_subscriber::layer::SubscriberExt;
|
||||
use tracing_subscriber::util::SubscriberInitExt;
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
use ruff_cli::args::{CliOverrides, FormatArguments, FormatCommand, LogLevelArgs};
|
||||
use ruff_cli::resolve::resolve;
|
||||
use ruff::args::{CliOverrides, FormatArguments, FormatCommand, LogLevelArgs};
|
||||
use ruff::resolve::resolve;
|
||||
use ruff_formatter::{FormatError, LineWidth, PrintError};
|
||||
use ruff_linter::logging::LogLevel;
|
||||
use ruff_linter::settings::types::{FilePattern, FilePatternSet};
|
||||
@@ -67,7 +67,7 @@ fn find_pyproject_config(
|
||||
Ok(pyproject_config)
|
||||
}
|
||||
|
||||
/// Find files that ruff would check so we can format them. Adapted from `ruff_cli`.
|
||||
/// Find files that ruff would check so we can format them. Adapted from `ruff`.
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn ruff_check_paths<'a>(
|
||||
pyproject_config: &'a PyprojectConfig,
|
||||
@@ -287,7 +287,7 @@ fn setup_logging(log_level_args: &LogLevelArgs, log_file: Option<&Path>) -> io::
|
||||
LogLevel::Quiet => tracing::Level::WARN,
|
||||
LogLevel::Silent => tracing::Level::ERROR,
|
||||
};
|
||||
// 1. `RUST_LOG=`, 2. explicit CLI log level, 3. info, the ruff_cli default
|
||||
// 1. `RUST_LOG=`, 2. explicit CLI log level, 3. info, the ruff default
|
||||
let filter_layer = EnvFilter::try_from_default_env().unwrap_or_else(|_| {
|
||||
EnvFilter::builder()
|
||||
.with_default_directive(log_level.into())
|
||||
@@ -461,7 +461,7 @@ fn format_dev_project(
|
||||
|
||||
// TODO(konstin): Respect black's excludes.
|
||||
|
||||
// Find files to check (or in this case, format twice). Adapted from ruff_cli
|
||||
// Find files to check (or in this case, format twice). Adapted from ruff
|
||||
// First argument is ignored
|
||||
let (cli, overrides) = parse_cli(files)?;
|
||||
let pyproject_config = find_pyproject_config(&cli, &overrides)?;
|
||||
|
||||
@@ -8,7 +8,7 @@ use anyhow::{bail, Context, Result};
|
||||
use clap::CommandFactory;
|
||||
use pretty_assertions::StrComparison;
|
||||
|
||||
use ruff_cli::args;
|
||||
use ruff::args;
|
||||
|
||||
use crate::generate_all::{Mode, REGENERATE_ALL_COMMAND};
|
||||
use crate::ROOT_DIR;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::{Parser, Subcommand};
|
||||
use ruff_cli::check;
|
||||
use ruff::check;
|
||||
use ruff_linter::logging::{set_up_logging, LogLevel};
|
||||
use std::process::ExitCode;
|
||||
|
||||
@@ -56,9 +56,9 @@ enum Command {
|
||||
/// Run a ruff command n times for profiling/benchmarking
|
||||
Repeat {
|
||||
#[clap(flatten)]
|
||||
args: ruff_cli::args::CheckCommand,
|
||||
args: ruff::args::CheckCommand,
|
||||
#[clap(flatten)]
|
||||
log_level_args: ruff_cli::args::LogLevelArgs,
|
||||
log_level_args: ruff::args::LogLevelArgs,
|
||||
/// Run this many times
|
||||
#[clap(long)]
|
||||
repeat: usize,
|
||||
|
||||
@@ -35,6 +35,7 @@ mod source_code;
|
||||
use crate::formatter::Formatter;
|
||||
use crate::group_id::UniqueGroupIdBuilder;
|
||||
use crate::prelude::TagKind;
|
||||
use std::fmt;
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::marker::PhantomData;
|
||||
use std::num::{NonZeroU16, NonZeroU8, TryFromIntError};
|
||||
@@ -113,6 +114,12 @@ impl Default for IndentWidth {
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for IndentWidth {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for IndentWidth {
|
||||
type Error = TryFromIntError;
|
||||
|
||||
@@ -146,6 +153,12 @@ impl Default for LineWidth {
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for LineWidth {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u16> for LineWidth {
|
||||
type Error = TryFromIntError;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_linter"
|
||||
version = "0.1.11"
|
||||
version = "0.1.14"
|
||||
publish = false
|
||||
authors = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
@@ -85,8 +85,6 @@ tempfile = { workspace = true }
|
||||
[features]
|
||||
default = []
|
||||
schemars = ["dep:schemars"]
|
||||
# Enables the UnreachableCode rule
|
||||
unreachable-code = []
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
0
crates/ruff_linter/__init__.py
Normal file
0
crates/ruff_linter/__init__.py
Normal file
0
crates/ruff_linter/resources/__init__.py
Normal file
0
crates/ruff_linter/resources/__init__.py
Normal file
0
crates/ruff_linter/resources/test/__init__.py
Normal file
0
crates/ruff_linter/resources/test/__init__.py
Normal file
0
crates/ruff_linter/resources/test/fixtures/__init__.py
vendored
Normal file
0
crates/ruff_linter/resources/test/fixtures/__init__.py
vendored
Normal file
@@ -2,10 +2,28 @@
|
||||
# Errors.
|
||||
###
|
||||
incorrect_set = {"value1", 23, 5, "value1"}
|
||||
incorrect_set = {1, 1, 2}
|
||||
incorrect_set_multiline = {
|
||||
"value1",
|
||||
23,
|
||||
5,
|
||||
"value1",
|
||||
# B033
|
||||
}
|
||||
incorrect_set = {1, 1}
|
||||
incorrect_set = {1, 1,}
|
||||
incorrect_set = {0, 1, 1,}
|
||||
incorrect_set = {0, 1, 1}
|
||||
incorrect_set = {
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
}
|
||||
|
||||
###
|
||||
# Non-errors.
|
||||
###
|
||||
correct_set = {"value1", 23, 5}
|
||||
correct_set = {5, "5"}
|
||||
correct_set = {5}
|
||||
correct_set = {}
|
||||
|
||||
@@ -20,3 +20,12 @@ else:
|
||||
|
||||
|
||||
def func2(arg: _PrivateTypeAlias) -> None: ...
|
||||
|
||||
type _UnusedPEP695 = int
|
||||
type _UnusedGeneric695[T] = list[T]
|
||||
|
||||
type _UsedPEP695 = str
|
||||
type _UsedGeneric695[T] = tuple[T, ...]
|
||||
|
||||
def func4(arg: _UsedPEP695) -> None: ...
|
||||
def func5(arg: _UsedGeneric695[bytes]) -> None: ...
|
||||
|
||||
@@ -20,3 +20,12 @@ else:
|
||||
|
||||
|
||||
def func2(arg: _PrivateTypeAlias) -> None: ...
|
||||
|
||||
type _UnusedPEP695 = int
|
||||
type _UnusedGeneric695[T] = list[T]
|
||||
|
||||
type _UsedPEP695 = str
|
||||
type _UsedGeneric695[T] = tuple[T, ...]
|
||||
|
||||
def func4(arg: _UsedPEP695) -> None: ...
|
||||
def func5(arg: _UsedGeneric695[bytes]) -> None: ...
|
||||
|
||||
@@ -16,3 +16,8 @@ class _UsedTypedDict(TypedDict):
|
||||
|
||||
class _CustomClass(_UsedTypedDict):
|
||||
bar: list[int]
|
||||
|
||||
_UnusedTypedDict3 = TypedDict("_UnusedTypedDict3", {"foo": int})
|
||||
_UsedTypedDict3 = TypedDict("_UsedTypedDict3", {"bar": bytes})
|
||||
|
||||
def uses_UsedTypedDict3(arg: _UsedTypedDict3) -> None: ...
|
||||
|
||||
@@ -30,3 +30,8 @@ else:
|
||||
|
||||
class _CustomClass2(_UsedTypedDict2):
|
||||
bar: list[int]
|
||||
|
||||
_UnusedTypedDict3 = TypedDict("_UnusedTypedDict3", {"foo": int})
|
||||
_UsedTypedDict3 = TypedDict("_UsedTypedDict3", {"bar": bytes})
|
||||
|
||||
def uses_UsedTypedDict3(arg: _UsedTypedDict3) -> None: ...
|
||||
|
||||
195
crates/ruff_linter/resources/test/fixtures/flake8_simplify/SIM113.py
vendored
Normal file
195
crates/ruff_linter/resources/test/fixtures/flake8_simplify/SIM113.py
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
def func():
|
||||
# SIM113
|
||||
idx = 0
|
||||
for x in range(5):
|
||||
g(x, idx)
|
||||
idx += 1
|
||||
h(x)
|
||||
|
||||
|
||||
def func():
|
||||
# SIM113
|
||||
sum = 0
|
||||
idx = 0
|
||||
for x in range(5):
|
||||
if g(x):
|
||||
break
|
||||
idx += 1
|
||||
sum += h(x, idx)
|
||||
|
||||
|
||||
def func():
|
||||
# SIM113
|
||||
idx = 0
|
||||
for x, y in zip(range(5), range(5)):
|
||||
g(x)
|
||||
h(x, y)
|
||||
idx += 1
|
||||
|
||||
|
||||
def func():
|
||||
# SIM113
|
||||
idx = 0
|
||||
sum = 0
|
||||
for x in range(5):
|
||||
sum += h(x, idx)
|
||||
idx += 1
|
||||
|
||||
|
||||
def func():
|
||||
# SIM113
|
||||
sum, idx = 0, 0
|
||||
for x in range(5):
|
||||
g(x, idx)
|
||||
idx += 1
|
||||
h(x)
|
||||
|
||||
|
||||
def func():
|
||||
# OK (index doesn't start at 0
|
||||
idx = 10
|
||||
for x in range(5):
|
||||
g(x, idx)
|
||||
idx += 1
|
||||
h(x)
|
||||
|
||||
|
||||
def func():
|
||||
# OK (incremented by more than 1)
|
||||
idx = 0
|
||||
for x in range(5):
|
||||
g(x, idx)
|
||||
idx += 2
|
||||
h(x)
|
||||
|
||||
|
||||
def func():
|
||||
# OK (incremented in `if`)
|
||||
idx = 0
|
||||
for x in range(5):
|
||||
if g(x):
|
||||
idx += 1
|
||||
h(x)
|
||||
|
||||
|
||||
def func():
|
||||
# OK (`continue` in match-case)
|
||||
idx = 0
|
||||
for x in range(5):
|
||||
match g(x):
|
||||
case 1:
|
||||
h(x)
|
||||
case 2:
|
||||
continue
|
||||
case _:
|
||||
h(idx)
|
||||
idx += 1
|
||||
|
||||
|
||||
def func():
|
||||
# OK (`continue` inside `with` clause)
|
||||
idx = 0
|
||||
for x in range(5):
|
||||
with context as c:
|
||||
if g(x):
|
||||
continue
|
||||
h(x, idx, c)
|
||||
idx += 1
|
||||
|
||||
|
||||
def func():
|
||||
# OK (incremented in `try` block)
|
||||
idx = 0
|
||||
for x in range(5):
|
||||
try:
|
||||
g(x, idx)
|
||||
except:
|
||||
h(x)
|
||||
continue
|
||||
idx += 1
|
||||
|
||||
|
||||
def func(idx: 0):
|
||||
# OK (index is an argument)
|
||||
for x in range(5):
|
||||
g(x, idx)
|
||||
idx += 1
|
||||
|
||||
|
||||
def func(x: int):
|
||||
# OK (index _may_ be non-zero)
|
||||
if x > 0:
|
||||
idx = 1
|
||||
else:
|
||||
idx = 0
|
||||
for x in range(5):
|
||||
g(x, idx)
|
||||
idx += 1
|
||||
h(x)
|
||||
|
||||
|
||||
def func():
|
||||
# OK
|
||||
idx = 0
|
||||
for x in range(5):
|
||||
g(x, idx)
|
||||
idx += 1
|
||||
idx += 1
|
||||
h(x)
|
||||
|
||||
|
||||
def func():
|
||||
# OK
|
||||
idx = 0
|
||||
for x in range(5):
|
||||
g(x, idx)
|
||||
idx += 1
|
||||
if idx > 10:
|
||||
idx *= 2
|
||||
h(x)
|
||||
|
||||
|
||||
def func():
|
||||
# OK (index used after loop)
|
||||
idx = 0
|
||||
for x in range(5):
|
||||
g(x, idx)
|
||||
idx += 1
|
||||
h(x)
|
||||
print(idx)
|
||||
|
||||
|
||||
def func():
|
||||
# OK (index within nested loop)
|
||||
idx = 0
|
||||
for x in range(5):
|
||||
for y in range(5):
|
||||
g(x, idx)
|
||||
idx += 1
|
||||
|
||||
|
||||
def func():
|
||||
# OK (index used within inner)
|
||||
idx = 0
|
||||
|
||||
def inner():
|
||||
print(idx)
|
||||
|
||||
for x in range(5):
|
||||
for y in range(5):
|
||||
g(x, idx)
|
||||
idx += 1
|
||||
|
||||
|
||||
def func():
|
||||
# OK (index used as nonlocal inner)
|
||||
idx = 0
|
||||
|
||||
def inner():
|
||||
nonlocal idx
|
||||
idx = 3
|
||||
|
||||
for x in range(5):
|
||||
for y in range(5):
|
||||
g(x, idx)
|
||||
idx += 1
|
||||
@@ -160,3 +160,10 @@ def secondToTime(s0: int) -> (int, int, int) or str:
|
||||
|
||||
def secondToTime(s0: int) -> ((int, int, int) or str):
|
||||
m, s = divmod(s0, 60)
|
||||
|
||||
|
||||
# Regression test for: https://github.com/astral-sh/ruff/issues/9479
|
||||
print(f"{a}{b}" or "bar")
|
||||
print(f"{a}{''}" or "bar")
|
||||
print(f"{''}{''}" or "bar")
|
||||
print(f"{1}{''}" or "bar")
|
||||
|
||||
@@ -147,3 +147,9 @@ if (a and [] and False and []) == (a and []): # SIM223
|
||||
|
||||
if f(a and [] and False and []): # SIM223
|
||||
pass
|
||||
|
||||
# Regression test for: https://github.com/astral-sh/ruff/issues/9479
|
||||
print(f"{a}{b}" and "bar")
|
||||
print(f"{a}{''}" and "bar")
|
||||
print(f"{''}{''}" and "bar")
|
||||
print(f"{1}{''}" and "bar")
|
||||
|
||||
23
crates/ruff_linter/resources/test/fixtures/flake8_simplify/SIM911.py
vendored
Normal file
23
crates/ruff_linter/resources/test/fixtures/flake8_simplify/SIM911.py
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
def foo(d: dict[str, str]) -> None:
|
||||
for k, v in zip(d.keys(), d.values()): # SIM911
|
||||
...
|
||||
|
||||
for k, v in zip(d.keys(), d.values(), strict=True): # SIM911
|
||||
...
|
||||
|
||||
for k, v in zip(d.keys(), d.values(), struct=True): # OK
|
||||
...
|
||||
|
||||
|
||||
d1 = d2 = {}
|
||||
|
||||
for k, v in zip(d1.keys(), d2.values()): # OK
|
||||
...
|
||||
|
||||
for k, v in zip(d1.items(), d2.values()): # OK
|
||||
...
|
||||
|
||||
for k, v in zip(d2.keys(), d2.values()): # SIM911
|
||||
...
|
||||
|
||||
items = zip(x.keys(), x.values()) # OK
|
||||
@@ -31,3 +31,6 @@ import torch
|
||||
torch.m.ReLU(inplace=True) # safe because this isn't a pandas call
|
||||
|
||||
(x.drop(["a"], axis=1, inplace=True))
|
||||
|
||||
# This method doesn't take exist in Pandas, so ignore it.
|
||||
x.rotate_z(45, inplace=True)
|
||||
|
||||
10
crates/ruff_linter/resources/test/fixtures/pyflakes/F401_21.py
vendored
Normal file
10
crates/ruff_linter/resources/test/fixtures/pyflakes/F401_21.py
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
"""Test: ensure that we visit type definitions and lambdas recursively."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections import Counter
|
||||
from typing import cast
|
||||
|
||||
|
||||
def get_most_common_fn(k):
|
||||
return lambda c: cast(Counter, c).most_common(k)
|
||||
11
crates/ruff_linter/resources/test/fixtures/pyflakes/F401_22.py
vendored
Normal file
11
crates/ruff_linter/resources/test/fixtures/pyflakes/F401_22.py
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
"""Test: ensure that we visit type definitions and lambdas recursively."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import os
|
||||
from typing import cast
|
||||
|
||||
cast(lambda: re.match, 1)
|
||||
|
||||
cast(lambda: cast(lambda: os.path, 1), 1)
|
||||
@@ -87,6 +87,10 @@ class Apples:
|
||||
def __special_custom_magic__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def __prepare__():
|
||||
pass
|
||||
|
||||
|
||||
def __foo_bar__(): # this is not checked by the [bad-dunder-name] rule
|
||||
...
|
||||
|
||||
1
crates/ruff_linter/resources/test/fixtures/pylint/import_private_name/__init__.py
vendored
Normal file
1
crates/ruff_linter/resources/test/fixtures/pylint/import_private_name/__init__.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
_top_level_secret = 0
|
||||
@@ -0,0 +1,3 @@
|
||||
_sibling_submodule_secret = 1
|
||||
_another_sibling_submodule_secret = 2
|
||||
some_value = 3
|
||||
1
crates/ruff_linter/resources/test/fixtures/pylint/import_private_name/submodule/__init__.py
vendored
Normal file
1
crates/ruff_linter/resources/test/fixtures/pylint/import_private_name/submodule/__init__.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
_submodule_secret = 1
|
||||
46
crates/ruff_linter/resources/test/fixtures/pylint/import_private_name/submodule/__main__.py
vendored
Normal file
46
crates/ruff_linter/resources/test/fixtures/pylint/import_private_name/submodule/__main__.py
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
# Errors.
|
||||
from _a import b
|
||||
from c._d import e
|
||||
from _f.g import h
|
||||
from i import _j
|
||||
from k import _l as m
|
||||
import _aaa
|
||||
import bbb.ccc._ddd as eee # Panicked in https://github.com/astral-sh/ruff/pull/5920
|
||||
|
||||
# Non-errors.
|
||||
import n
|
||||
import o as _p
|
||||
from q import r
|
||||
from s import t as _v
|
||||
from w.x import y
|
||||
from z.aa import bb as _cc
|
||||
from .dd import _ee # Relative import.
|
||||
from .ff._gg import hh # Relative import.
|
||||
from ._ii.jj import kk # Relative import.
|
||||
from __future__ import annotations # __future__ is a special case.
|
||||
from __main__ import main # __main__ is a special case.
|
||||
from ll import __version__ # __version__ is a special case.
|
||||
from import_private_name import _top_level_secret # Can import from self.
|
||||
from import_private_name.submodule import _submodule_secret # Can import from self.
|
||||
from import_private_name.submodule.subsubmodule import (
|
||||
_subsubmodule_secret,
|
||||
) # Can import from self.
|
||||
|
||||
# Non-errors (used for type annotations).
|
||||
from mm import _nn
|
||||
from oo import _pp as qq
|
||||
from _rr import ss
|
||||
from tt._uu import vv
|
||||
from _ww.xx import yy as zz
|
||||
import _ddd as ddd
|
||||
|
||||
some_variable: _nn = None
|
||||
|
||||
def func(arg: qq) -> ss:
|
||||
pass
|
||||
|
||||
class Class:
|
||||
lst: list[ddd]
|
||||
|
||||
def __init__(self, arg: vv) -> "zz":
|
||||
pass
|
||||
@@ -0,0 +1 @@
|
||||
_subsubmodule_secret = 42
|
||||
@@ -1,4 +1,4 @@
|
||||
def f(x, y, z, t, u, v, w, r): # Too many positional arguments (8/3)
|
||||
def f(x, y, z, t, u, v, w, r): # Too many positional arguments (8/5)
|
||||
pass
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ def f(x=1, y=1, z=1): # OK
|
||||
pass
|
||||
|
||||
|
||||
def f(x, y, z, /, u, v, w): # Too many positional arguments (6/3)
|
||||
def f(x, y, z, /, u, v, w): # Too many positional arguments (6/5)
|
||||
pass
|
||||
|
||||
|
||||
@@ -26,5 +26,36 @@ def f(x, y, z, *, u, v, w): # OK
|
||||
pass
|
||||
|
||||
|
||||
def f(x, y, z, a, b, c, *, u, v, w): # Too many positional arguments (6/3)
|
||||
def f(x, y, z, a, b, c, *, u, v, w): # Too many positional arguments (6/5)
|
||||
pass
|
||||
|
||||
|
||||
class C:
|
||||
def f(self, a, b, c, d, e): # OK
|
||||
pass
|
||||
|
||||
def f(self, /, a, b, c, d, e): # OK
|
||||
pass
|
||||
|
||||
def f(weird_self_name, a, b, c, d, e): # OK
|
||||
pass
|
||||
|
||||
def f(self, a, b, c, d, e, g): # Too many positional arguments (6/5)
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def f(self, a, b, c, d, e): # Too many positional arguments (6/5)
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def f(cls, a, b, c, d, e): # OK
|
||||
pass
|
||||
|
||||
def f(*, self, a, b, c, d, e): # OK
|
||||
pass
|
||||
|
||||
def f(self=1, a=1, b=1, c=1, d=1, e=1): # OK
|
||||
pass
|
||||
|
||||
def f(): # OK
|
||||
pass
|
||||
|
||||
@@ -24,6 +24,12 @@ class Thing:
|
||||
super().__init__() # OK
|
||||
super().__class__(stuff=(1, 2, 3)) # OK
|
||||
|
||||
def __getattribute__(self, item):
|
||||
return object.__getattribute__(self, item) # OK
|
||||
|
||||
def do_thing(self, item):
|
||||
return object.__getattribute__(self, item) # PLC2801
|
||||
|
||||
|
||||
blah = lambda: {"a": 1}.__delitem__("a") # OK
|
||||
|
||||
|
||||
22
crates/ruff_linter/resources/test/fixtures/refurb/FURB167.py
vendored
Normal file
22
crates/ruff_linter/resources/test/fixtures/refurb/FURB167.py
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
def func():
|
||||
import re
|
||||
|
||||
# OK
|
||||
if re.match("^hello", "hello world", re.IGNORECASE):
|
||||
pass
|
||||
|
||||
|
||||
def func():
|
||||
import re
|
||||
|
||||
# FURB167
|
||||
if re.match("^hello", "hello world", re.I):
|
||||
pass
|
||||
|
||||
|
||||
def func():
|
||||
from re import match, I
|
||||
|
||||
# FURB167
|
||||
if match("^hello", "hello world", I):
|
||||
pass
|
||||
@@ -10,6 +10,8 @@ constant = 5
|
||||
{value.attribute: value.upper() for value in data for constant in data}
|
||||
{constant[value]: value.upper() for value in data for constant in data}
|
||||
{value[constant]: value.upper() for value in data for constant in data}
|
||||
{local_id: token for token in tokens if (local_id := _extract_local_id(token)) is not None}
|
||||
{key: kwargs.get(key) for key in kwargs.keys() if not params.get(key)}
|
||||
|
||||
# Errors
|
||||
{"key": value.upper() for value in data}
|
||||
@@ -20,3 +22,5 @@ constant = 5
|
||||
{constant + constant: value.upper() for value in data}
|
||||
{constant.attribute: value.upper() for value in data}
|
||||
{constant[0]: value.upper() for value in data}
|
||||
{tokens: token for token in tokens}
|
||||
|
||||
|
||||
@@ -1,185 +0,0 @@
|
||||
def after_return():
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
|
||||
async def also_works_on_async_functions():
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
|
||||
def if_always_true():
|
||||
if True:
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
|
||||
def if_always_false():
|
||||
if False:
|
||||
return "unreachable"
|
||||
return "reachable"
|
||||
|
||||
def if_elif_always_false():
|
||||
if False:
|
||||
return "unreachable"
|
||||
elif False:
|
||||
return "also unreachable"
|
||||
return "reachable"
|
||||
|
||||
def if_elif_always_true():
|
||||
if False:
|
||||
return "unreachable"
|
||||
elif True:
|
||||
return "reachable"
|
||||
return "also unreachable"
|
||||
|
||||
def ends_with_if():
|
||||
if False:
|
||||
return "unreachable"
|
||||
else:
|
||||
return "reachable"
|
||||
|
||||
def infinite_loop():
|
||||
while True:
|
||||
continue
|
||||
return "unreachable"
|
||||
|
||||
''' TODO: we could determine these, but we don't yet.
|
||||
def for_range_return():
|
||||
for i in range(10):
|
||||
if i == 5:
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
|
||||
def for_range_else():
|
||||
for i in range(111):
|
||||
if i == 5:
|
||||
return "reachable"
|
||||
else:
|
||||
return "unreachable"
|
||||
return "also unreachable"
|
||||
|
||||
def for_range_break():
|
||||
for i in range(13):
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
|
||||
def for_range_if_break():
|
||||
for i in range(1110):
|
||||
if True:
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
'''
|
||||
|
||||
def match_wildcard(status):
|
||||
match status:
|
||||
case _:
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
|
||||
def match_case_and_wildcard(status):
|
||||
match status:
|
||||
case 1:
|
||||
return "reachable"
|
||||
case _:
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
|
||||
def raise_exception():
|
||||
raise Exception
|
||||
return "unreachable"
|
||||
|
||||
def while_false():
|
||||
while False:
|
||||
return "unreachable"
|
||||
return "reachable"
|
||||
|
||||
def while_false_else():
|
||||
while False:
|
||||
return "unreachable"
|
||||
else:
|
||||
return "reachable"
|
||||
|
||||
def while_false_else_return():
|
||||
while False:
|
||||
return "unreachable"
|
||||
else:
|
||||
return "reachable"
|
||||
return "also unreachable"
|
||||
|
||||
def while_true():
|
||||
while True:
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
|
||||
def while_true_else():
|
||||
while True:
|
||||
return "reachable"
|
||||
else:
|
||||
return "unreachable"
|
||||
|
||||
def while_true_else_return():
|
||||
while True:
|
||||
return "reachable"
|
||||
else:
|
||||
return "unreachable"
|
||||
return "also unreachable"
|
||||
|
||||
def while_false_var_i():
|
||||
i = 0
|
||||
while False:
|
||||
i += 1
|
||||
return i
|
||||
|
||||
def while_true_var_i():
|
||||
i = 0
|
||||
while True:
|
||||
i += 1
|
||||
return i
|
||||
|
||||
def while_infinite():
|
||||
while True:
|
||||
pass
|
||||
return "unreachable"
|
||||
|
||||
def while_if_true():
|
||||
while True:
|
||||
if True:
|
||||
return "reachable"
|
||||
return "unreachable"
|
||||
|
||||
# Test case found in the Bokeh repository that trigger a false positive.
|
||||
def bokeh1(self, obj: BytesRep) -> bytes:
|
||||
data = obj["data"]
|
||||
|
||||
if isinstance(data, str):
|
||||
return base64.b64decode(data)
|
||||
elif isinstance(data, Buffer):
|
||||
buffer = data
|
||||
else:
|
||||
id = data["id"]
|
||||
|
||||
if id in self._buffers:
|
||||
buffer = self._buffers[id]
|
||||
else:
|
||||
self.error(f"can't resolve buffer '{id}'")
|
||||
|
||||
return buffer.data
|
||||
|
||||
'''
|
||||
TODO: because `try` statements aren't handled this triggers a false positive as
|
||||
the last statement is reached, but the rules thinks it isn't (it doesn't
|
||||
see/process the break statement).
|
||||
|
||||
# Test case found in the Bokeh repository that trigger a false positive.
|
||||
def bokeh2(self, host: str = DEFAULT_HOST, port: int = DEFAULT_PORT) -> None:
|
||||
self.stop_serving = False
|
||||
while True:
|
||||
try:
|
||||
self.server = HTTPServer((host, port), HtmlOnlyHandler)
|
||||
self.host = host
|
||||
self.port = port
|
||||
break
|
||||
except OSError:
|
||||
log.debug(f"port {port} is in use, trying to next one")
|
||||
port += 1
|
||||
|
||||
self.thread = threading.Thread(target=self._run_web_server)
|
||||
'''
|
||||
308
crates/ruff_linter/resources/test/fixtures/ruff/RUF022.py
vendored
Normal file
308
crates/ruff_linter/resources/test/fixtures/ruff/RUF022.py
vendored
Normal file
@@ -0,0 +1,308 @@
|
||||
##################################################
|
||||
# Single-line __all__ definitions (nice 'n' easy!)
|
||||
##################################################
|
||||
|
||||
__all__ = ["d", "c", "b", "a"] # a comment that is untouched
|
||||
__all__ += ["foo", "bar", "antipasti"]
|
||||
__all__ = ("d", "c", "b", "a")
|
||||
|
||||
# Quoting style is retained,
|
||||
# but unnecessary parens are not
|
||||
__all__: list = ['b', "c", ((('a')))]
|
||||
# Trailing commas are also not retained in single-line `__all__` definitions
|
||||
# (but they are in multiline `__all__` definitions)
|
||||
__all__: tuple = ("b", "c", "a",)
|
||||
|
||||
if bool():
|
||||
__all__ += ("x", "m", "a", "s")
|
||||
else:
|
||||
__all__ += "foo3", "foo2", "foo1" # NB: an implicit tuple (without parens)
|
||||
|
||||
__all__: list[str] = ["the", "three", "little", "pigs"]
|
||||
|
||||
__all__ = ("parenthesized_item"), "in", ("an_unparenthesized_tuple")
|
||||
__all__.extend(["foo", "bar"])
|
||||
__all__.extend(("foo", "bar"))
|
||||
__all__.extend((((["foo", "bar"]))))
|
||||
|
||||
####################################
|
||||
# Neat multiline __all__ definitions
|
||||
####################################
|
||||
|
||||
__all__ = (
|
||||
"d0",
|
||||
"c0", # a comment regarding 'c0'
|
||||
"b0",
|
||||
# a comment regarding 'a0':
|
||||
"a0"
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"d",
|
||||
"c", # a comment regarding 'c'
|
||||
"b",
|
||||
# a comment regarding 'a':
|
||||
"a"
|
||||
]
|
||||
|
||||
# we implement an "isort-style sort":
|
||||
# SCEAMING_CASE constants first,
|
||||
# then CamelCase classes,
|
||||
# then anything thats lowercase_snake_case.
|
||||
# This (which is currently alphabetically sorted)
|
||||
# should get reordered accordingly:
|
||||
__all__ = [
|
||||
"APRIL",
|
||||
"AUGUST",
|
||||
"Calendar",
|
||||
"DECEMBER",
|
||||
"Day",
|
||||
"FEBRUARY",
|
||||
"FRIDAY",
|
||||
"HTMLCalendar",
|
||||
"IllegalMonthError",
|
||||
"JANUARY",
|
||||
"JULY",
|
||||
"JUNE",
|
||||
"LocaleHTMLCalendar",
|
||||
"MARCH",
|
||||
"MAY",
|
||||
"MONDAY",
|
||||
"Month",
|
||||
"NOVEMBER",
|
||||
"OCTOBER",
|
||||
"SATURDAY",
|
||||
"SEPTEMBER",
|
||||
"SUNDAY",
|
||||
"THURSDAY",
|
||||
"TUESDAY",
|
||||
"TextCalendar",
|
||||
"WEDNESDAY",
|
||||
"calendar",
|
||||
"timegm",
|
||||
"weekday",
|
||||
"weekheader"]
|
||||
|
||||
##########################################
|
||||
# Messier multiline __all__ definitions...
|
||||
##########################################
|
||||
|
||||
# comment0
|
||||
__all__ = ("d", "a", # comment1
|
||||
# comment2
|
||||
"f", "b",
|
||||
"strangely", # comment3
|
||||
# comment4
|
||||
"formatted",
|
||||
# comment5
|
||||
) # comment6
|
||||
# comment7
|
||||
|
||||
__all__ = [ # comment0
|
||||
# comment1
|
||||
# comment2
|
||||
"dx", "cx", "bx", "ax" # comment3
|
||||
# comment4
|
||||
# comment5
|
||||
# comment6
|
||||
] # comment7
|
||||
|
||||
__all__ = ["register", "lookup", "open", "EncodedFile", "BOM", "BOM_BE",
|
||||
"BOM_LE", "BOM32_BE", "BOM32_LE", "BOM64_BE", "BOM64_LE",
|
||||
"BOM_UTF8", "BOM_UTF16", "BOM_UTF16_LE", "BOM_UTF16_BE",
|
||||
"BOM_UTF32", "BOM_UTF32_LE", "BOM_UTF32_BE",
|
||||
"CodecInfo", "Codec", "IncrementalEncoder", "IncrementalDecoder",
|
||||
"StreamReader", "StreamWriter",
|
||||
"StreamReaderWriter", "StreamRecoder",
|
||||
"getencoder", "getdecoder", "getincrementalencoder",
|
||||
"getincrementaldecoder", "getreader", "getwriter",
|
||||
"encode", "decode", "iterencode", "iterdecode",
|
||||
"strict_errors", "ignore_errors", "replace_errors",
|
||||
"xmlcharrefreplace_errors",
|
||||
"backslashreplace_errors", "namereplace_errors",
|
||||
"register_error", "lookup_error"]
|
||||
|
||||
__all__: tuple[str, ...] = ( # a comment about the opening paren
|
||||
# multiline comment about "bbb" part 1
|
||||
# multiline comment about "bbb" part 2
|
||||
"bbb",
|
||||
# multiline comment about "aaa" part 1
|
||||
# multiline comment about "aaa" part 2
|
||||
"aaa",
|
||||
)
|
||||
|
||||
# we use natural sort for `__all__`,
|
||||
# not alphabetical sort.
|
||||
# Also, this doesn't end with a trailing comma,
|
||||
# so the autofix shouldn't introduce one:
|
||||
__all__ = (
|
||||
"aadvark237",
|
||||
"aadvark10092",
|
||||
"aadvark174", # the very long whitespace span before this comment is retained
|
||||
"aadvark532" # the even longer whitespace span before this comment is retained
|
||||
)
|
||||
|
||||
__all__.extend(( # comment0
|
||||
# comment about foo
|
||||
"foo", # comment about foo
|
||||
# comment about bar
|
||||
"bar" # comment about bar
|
||||
# comment1
|
||||
)) # comment2
|
||||
|
||||
__all__.extend( # comment0
|
||||
# comment1
|
||||
( # comment2
|
||||
# comment about foo
|
||||
"foo", # comment about foo
|
||||
# comment about bar
|
||||
"bar" # comment about bar
|
||||
# comment3
|
||||
) # comment4
|
||||
) # comment2
|
||||
|
||||
__all__.extend([ # comment0
|
||||
# comment about foo
|
||||
"foo", # comment about foo
|
||||
# comment about bar
|
||||
"bar" # comment about bar
|
||||
# comment1
|
||||
]) # comment2
|
||||
|
||||
__all__.extend( # comment0
|
||||
# comment1
|
||||
[ # comment2
|
||||
# comment about foo
|
||||
"foo", # comment about foo
|
||||
# comment about bar
|
||||
"bar" # comment about bar
|
||||
# comment3
|
||||
] # comment4
|
||||
) # comment2
|
||||
|
||||
__all__ = ["Style", "Treeview",
|
||||
# Extensions
|
||||
"LabeledScale", "OptionMenu",
|
||||
]
|
||||
|
||||
__all__ = ["Awaitable", "Coroutine",
|
||||
"AsyncIterable", "AsyncIterator", "AsyncGenerator",
|
||||
]
|
||||
|
||||
__all__ = [
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
]
|
||||
|
||||
#########################################################################
|
||||
# These should be flagged, but not fixed:
|
||||
# - Parenthesized items in multiline definitions are out of scope
|
||||
# - The same goes for any `__all__` definitions with concatenated strings
|
||||
#########################################################################
|
||||
|
||||
__all__ = (
|
||||
"look",
|
||||
(
|
||||
"a_veeeeeeeeeeeeeeeeeeery_long_parenthesized_item"
|
||||
),
|
||||
)
|
||||
|
||||
__all__ = (
|
||||
"b",
|
||||
((
|
||||
"c"
|
||||
)),
|
||||
"a"
|
||||
)
|
||||
|
||||
__all__ = ("don't" "care" "about", "__all__" "with", "concatenated" "strings")
|
||||
|
||||
###################################
|
||||
# These should all not get flagged:
|
||||
###################################
|
||||
|
||||
__all__ = ()
|
||||
__all__ = []
|
||||
__all__ = ("single_item",)
|
||||
__all__ = (
|
||||
"single_item_multiline",
|
||||
)
|
||||
__all__ = ["single_item",]
|
||||
__all__ = ["single_item_no_trailing_comma"]
|
||||
__all__ = [
|
||||
"single_item_multiline_no_trailing_comma"
|
||||
]
|
||||
__all__ = ("not_a_tuple_just_a_string")
|
||||
__all__ = ["a", "b", "c", "d"]
|
||||
__all__ += ["e", "f", "g"]
|
||||
__all__ = ("a", "b", "c", "d")
|
||||
|
||||
if bool():
|
||||
__all__ += ("e", "f", "g")
|
||||
else:
|
||||
__all__ += ["alpha", "omega"]
|
||||
|
||||
class IntroducesNonModuleScope:
|
||||
__all__ = ("b", "a", "e", "d")
|
||||
__all__ = ["b", "a", "e", "d"]
|
||||
__all__ += ["foo", "bar", "antipasti"]
|
||||
__all__.extend(["zebra", "giraffe", "antelope"])
|
||||
|
||||
__all__ = {"look", "a", "set"}
|
||||
__all__ = {"very": "strange", "not": "sorted", "we don't": "care"}
|
||||
["not", "an", "assignment", "just", "an", "expression"]
|
||||
__all__ = (9, 8, 7)
|
||||
__all__ = ( # This is just an empty tuple,
|
||||
# but,
|
||||
# it's very well
|
||||
) # documented
|
||||
|
||||
__all__.append("foo")
|
||||
__all__.extend(["bar", "foo"])
|
||||
__all__.extend([
|
||||
"bar", # comment0
|
||||
"foo" # comment1
|
||||
])
|
||||
__all__.extend(("bar", "foo"))
|
||||
__all__.extend(
|
||||
(
|
||||
"bar",
|
||||
"foo"
|
||||
)
|
||||
)
|
||||
|
||||
# We don't deduplicate elements (yet);
|
||||
# this just ensures that duplicate elements aren't unnecessarily
|
||||
# reordered by an autofix:
|
||||
__all__ = (
|
||||
"duplicate_element", # comment1
|
||||
"duplicate_element", # comment3
|
||||
"duplicate_element", # comment2
|
||||
"duplicate_element", # comment0
|
||||
)
|
||||
|
||||
__all__ =[
|
||||
[]
|
||||
]
|
||||
__all__ [
|
||||
()
|
||||
]
|
||||
__all__ = (
|
||||
()
|
||||
)
|
||||
__all__ = (
|
||||
[]
|
||||
)
|
||||
__all__ = (
|
||||
(),
|
||||
)
|
||||
__all__ = (
|
||||
[],
|
||||
)
|
||||
__all__ = (
|
||||
"foo", [], "bar"
|
||||
)
|
||||
__all__ = [
|
||||
"foo", (), "bar"
|
||||
]
|
||||
@@ -8,7 +8,7 @@ behaviors.
|
||||
Running from the repo root should pick up and enforce the appropriate settings for each package:
|
||||
|
||||
```console
|
||||
∴ cargo run -p ruff_cli -- check crates/ruff_linter/resources/test/project/
|
||||
∴ cargo run -p ruff -- check crates/ruff_linter/resources/test/project/
|
||||
crates/ruff_linter/resources/test/project/examples/.dotfiles/script.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
crates/ruff_linter/resources/test/project/examples/.dotfiles/script.py:1:8: F401 [*] `numpy` imported but unused
|
||||
crates/ruff_linter/resources/test/project/examples/.dotfiles/script.py:2:17: F401 [*] `app.app_file` imported but unused
|
||||
@@ -23,7 +23,7 @@ Found 7 errors.
|
||||
Running from the project directory itself should exhibit the same behavior:
|
||||
|
||||
```console
|
||||
∴ (cd crates/ruff_linter/resources/test/project/ && cargo run -p ruff_cli -- check .)
|
||||
∴ (cd crates/ruff_linter/resources/test/project/ && cargo run -p ruff -- check .)
|
||||
examples/.dotfiles/script.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
examples/.dotfiles/script.py:1:8: F401 [*] `numpy` imported but unused
|
||||
examples/.dotfiles/script.py:2:17: F401 [*] `app.app_file` imported but unused
|
||||
@@ -39,7 +39,7 @@ Running from the sub-package directory should exhibit the same behavior, but omi
|
||||
files:
|
||||
|
||||
```console
|
||||
∴ (cd crates/ruff_linter/resources/test/project/examples/docs && cargo run -p ruff_cli -- check .)
|
||||
∴ (cd crates/ruff_linter/resources/test/project/examples/docs && cargo run -p ruff -- check .)
|
||||
docs/file.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
docs/file.py:8:5: F841 [*] Local variable `x` is assigned to but never used
|
||||
Found 2 errors.
|
||||
@@ -50,7 +50,7 @@ Found 2 errors.
|
||||
file paths from the current working directory:
|
||||
|
||||
```console
|
||||
∴ (cargo run -p ruff_cli -- check --config=crates/ruff_linter/resources/test/project/pyproject.toml crates/ruff_linter/resources/test/project/)
|
||||
∴ (cargo run -p ruff -- check --config=crates/ruff_linter/resources/test/project/pyproject.toml crates/ruff_linter/resources/test/project/)
|
||||
crates/ruff_linter/resources/test/project/examples/.dotfiles/script.py:1:8: F401 [*] `numpy` imported but unused
|
||||
crates/ruff_linter/resources/test/project/examples/.dotfiles/script.py:2:17: F401 [*] `app.app_file` imported but unused
|
||||
crates/ruff_linter/resources/test/project/examples/docs/docs/concepts/file.py:1:8: F401 [*] `os` imported but unused
|
||||
@@ -68,7 +68,7 @@ Running from a parent directory should "ignore" the `exclude` (hence, `concepts/
|
||||
included in the output):
|
||||
|
||||
```console
|
||||
∴ (cd crates/ruff_linter/resources/test/project/examples && cargo run -p ruff_cli -- check --config=docs/ruff.toml .)
|
||||
∴ (cd crates/ruff_linter/resources/test/project/examples && cargo run -p ruff -- check --config=docs/ruff.toml .)
|
||||
docs/docs/concepts/file.py:5:5: F841 [*] Local variable `x` is assigned to but never used
|
||||
docs/docs/file.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
docs/docs/file.py:8:5: F841 [*] Local variable `x` is assigned to but never used
|
||||
@@ -80,7 +80,7 @@ Found 4 errors.
|
||||
Passing an excluded directory directly should report errors in the contained files:
|
||||
|
||||
```console
|
||||
∴ cargo run -p ruff_cli -- check crates/ruff_linter/resources/test/project/examples/excluded/
|
||||
∴ cargo run -p ruff -- check crates/ruff_linter/resources/test/project/examples/excluded/
|
||||
crates/ruff_linter/resources/test/project/examples/excluded/script.py:1:8: F401 [*] `os` imported but unused
|
||||
Found 1 error.
|
||||
[*] 1 potentially fixable with the --fix option.
|
||||
@@ -89,8 +89,8 @@ Found 1 error.
|
||||
Unless we `--force-exclude`:
|
||||
|
||||
```console
|
||||
∴ cargo run -p ruff_cli -- check crates/ruff_linter/resources/test/project/examples/excluded/ --force-exclude
|
||||
∴ cargo run -p ruff -- check crates/ruff_linter/resources/test/project/examples/excluded/ --force-exclude
|
||||
warning: No Python files found under the given path(s)
|
||||
∴ cargo run -p ruff_cli -- check crates/ruff_linter/resources/test/project/examples/excluded/script.py --force-exclude
|
||||
∴ cargo run -p ruff -- check crates/ruff_linter/resources/test/project/examples/excluded/script.py --force-exclude
|
||||
warning: No Python files found under the given path(s)
|
||||
```
|
||||
|
||||
@@ -2,12 +2,12 @@ use ruff_python_ast::Stmt;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::codes::Rule;
|
||||
use crate::rules::{flake8_bugbear, perflint, pyupgrade, refurb};
|
||||
use crate::rules::{flake8_bugbear, flake8_simplify, perflint, pyupgrade, refurb};
|
||||
|
||||
/// Run lint rules over all deferred for-loops in the [`SemanticModel`].
|
||||
pub(crate) fn deferred_for_loops(checker: &mut Checker) {
|
||||
while !checker.deferred.for_loops.is_empty() {
|
||||
let for_loops = std::mem::take(&mut checker.deferred.for_loops);
|
||||
while !checker.analyze.for_loops.is_empty() {
|
||||
let for_loops = std::mem::take(&mut checker.analyze.for_loops);
|
||||
for snapshot in for_loops {
|
||||
checker.semantic.restore(snapshot);
|
||||
|
||||
@@ -27,6 +27,9 @@ pub(crate) fn deferred_for_loops(checker: &mut Checker) {
|
||||
if checker.enabled(Rule::UnnecessaryEnumerate) {
|
||||
refurb::rules::unnecessary_enumerate(checker, stmt_for);
|
||||
}
|
||||
if checker.enabled(Rule::EnumerateForLoop) {
|
||||
flake8_simplify::rules::enumerate_for_loop(checker, stmt_for);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ use crate::rules::{flake8_pie, pylint, refurb};
|
||||
|
||||
/// Run lint rules over all deferred lambdas in the [`SemanticModel`].
|
||||
pub(crate) fn deferred_lambdas(checker: &mut Checker) {
|
||||
while !checker.deferred.lambdas.is_empty() {
|
||||
let lambdas = std::mem::take(&mut checker.deferred.lambdas);
|
||||
while !checker.analyze.lambdas.is_empty() {
|
||||
let lambdas = std::mem::take(&mut checker.analyze.lambdas);
|
||||
for snapshot in lambdas {
|
||||
checker.semantic.restore(snapshot);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user