Compare commits
2 Commits
dcreager/b
...
amy/missin
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4447bcf468 | ||
|
|
c790c1d957 |
49
.github/workflows/ci.yaml
vendored
@@ -88,6 +88,7 @@ jobs:
|
||||
':!crates/ruff_python_formatter/**' \
|
||||
':!crates/ruff_formatter/**' \
|
||||
':!crates/ruff_dev/**' \
|
||||
':!crates/ruff_db/**' \
|
||||
':scripts/*' \
|
||||
':python/**' \
|
||||
':.github/workflows/ci.yaml' \
|
||||
@@ -452,7 +453,7 @@ jobs:
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- name: "Install cargo-binstall"
|
||||
uses: cargo-bins/cargo-binstall@38e8f5e4c386b611d51e8aa997b9a06a3c8eb67a # v1.15.6
|
||||
uses: cargo-bins/cargo-binstall@20aa316bab4942180bbbabe93237858e8d77f1ed # v1.15.5
|
||||
- name: "Install cargo-fuzz"
|
||||
# Download the latest version from quick install and not the github releases because github releases only has MUSL targets.
|
||||
run: cargo binstall cargo-fuzz --force --disable-strategies crate-meta-data --no-confirm
|
||||
@@ -703,7 +704,7 @@ jobs:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: cargo-bins/cargo-binstall@38e8f5e4c386b611d51e8aa997b9a06a3c8eb67a # v1.15.6
|
||||
- uses: cargo-bins/cargo-binstall@20aa316bab4942180bbbabe93237858e8d77f1ed # v1.15.5
|
||||
- run: cargo binstall --no-confirm cargo-shear
|
||||
- run: cargo shear
|
||||
|
||||
@@ -906,13 +907,10 @@ jobs:
|
||||
run: npm run fmt:check
|
||||
working-directory: playground
|
||||
|
||||
benchmarks-instrumented-ruff:
|
||||
name: "benchmarks instrumented (ruff)"
|
||||
benchmarks-instrumented:
|
||||
runs-on: ubuntu-24.04
|
||||
needs: determine_changes
|
||||
if: |
|
||||
github.ref == 'refs/heads/main' ||
|
||||
(needs.determine_changes.outputs.formatter == 'true' || needs.determine_changes.outputs.linter == 'true')
|
||||
if: ${{ github.repository == 'astral-sh/ruff' && !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }}
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: "Checkout Branch"
|
||||
@@ -932,42 +930,7 @@ jobs:
|
||||
tool: cargo-codspeed
|
||||
|
||||
- name: "Build benchmarks"
|
||||
run: cargo codspeed build --features "codspeed,instrumented" --no-default-features -p ruff_benchmark --bench formatter --bench lexer --bench linter --bench parser
|
||||
|
||||
- name: "Run benchmarks"
|
||||
uses: CodSpeedHQ/action@653fdc30e6c40ffd9739e40c8a0576f4f4523ca1 # v4.0.1
|
||||
with:
|
||||
mode: instrumentation
|
||||
run: cargo codspeed run
|
||||
token: ${{ secrets.CODSPEED_TOKEN }}
|
||||
|
||||
benchmarks-instrumented-ty:
|
||||
name: "benchmarks instrumented (ty)"
|
||||
runs-on: ubuntu-24.04
|
||||
needs: determine_changes
|
||||
if: |
|
||||
github.ref == 'refs/heads/main' ||
|
||||
needs.determine_changes.outputs.ty == 'true'
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: "Checkout Branch"
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||
- uses: astral-sh/setup-uv@b75a909f75acd358c2196fb9a5f1299a9a8868a4 # v6.7.0
|
||||
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
|
||||
- name: "Install codspeed"
|
||||
uses: taiki-e/install-action@67cc679904bee382389bf22082124fa963c6f6bd # v2.61.3
|
||||
with:
|
||||
tool: cargo-codspeed
|
||||
|
||||
- name: "Build benchmarks"
|
||||
run: cargo codspeed build --features "codspeed,instrumented" --no-default-features -p ruff_benchmark --bench ty
|
||||
run: cargo codspeed build --features "codspeed,instrumented" --no-default-features -p ruff_benchmark
|
||||
|
||||
- name: "Run benchmarks"
|
||||
uses: CodSpeedHQ/action@653fdc30e6c40ffd9739e40c8a0576f4f4523ca1 # v4.0.1
|
||||
|
||||
18
.github/workflows/ty-ecosystem-analyzer.yaml
vendored
@@ -64,7 +64,7 @@ jobs:
|
||||
|
||||
cd ..
|
||||
|
||||
uv tool install "git+https://github.com/astral-sh/ecosystem-analyzer@279f8a15b0e7f77213bf9096dbc2335a19ef89c5"
|
||||
uv tool install "git+https://github.com/astral-sh/ecosystem-analyzer@fc0f612798710b0dd69bb7528bc9b361dc60bd43"
|
||||
|
||||
ecosystem-analyzer \
|
||||
--repository ruff \
|
||||
@@ -95,14 +95,6 @@ jobs:
|
||||
--new-name "$REF_NAME" \
|
||||
--output diff-statistics.md
|
||||
|
||||
ecosystem-analyzer \
|
||||
generate-timing-diff \
|
||||
diagnostics-old.json \
|
||||
diagnostics-new.json \
|
||||
--old-name "main (merge base)" \
|
||||
--new-name "$REF_NAME" \
|
||||
--output-html dist/timing.html
|
||||
|
||||
echo '## `ecosystem-analyzer` results' > comment.md
|
||||
echo >> comment.md
|
||||
cat diff-statistics.md >> comment.md
|
||||
@@ -126,7 +118,7 @@ jobs:
|
||||
DEPLOYMENT_URL: ${{ steps.deploy.outputs.pages-deployment-alias-url }}
|
||||
run: |
|
||||
echo >> comment.md
|
||||
echo "**[Full report with detailed diff]($DEPLOYMENT_URL/diff)** ([timing results]($DEPLOYMENT_URL/timing))" >> comment.md
|
||||
echo "**[Full report with detailed diff]($DEPLOYMENT_URL/diff)**" >> comment.md
|
||||
|
||||
- name: Upload comment
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
@@ -145,9 +137,3 @@ jobs:
|
||||
with:
|
||||
name: diff.html
|
||||
path: dist/diff.html
|
||||
|
||||
- name: Upload timing diff
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: timing.html
|
||||
path: dist/timing.html
|
||||
|
||||
5
.github/workflows/ty-ecosystem-report.yaml
vendored
@@ -49,13 +49,12 @@ jobs:
|
||||
|
||||
cd ..
|
||||
|
||||
uv tool install "git+https://github.com/astral-sh/ecosystem-analyzer@279f8a15b0e7f77213bf9096dbc2335a19ef89c5"
|
||||
uv tool install "git+https://github.com/astral-sh/ecosystem-analyzer@27dd66d9e397d986ef9c631119ee09556eab8af9"
|
||||
|
||||
ecosystem-analyzer \
|
||||
--verbose \
|
||||
--repository ruff \
|
||||
analyze \
|
||||
--profile=release \
|
||||
--projects ruff/crates/ty_python_semantic/resources/primer/good.txt \
|
||||
--output ecosystem-diagnostics.json
|
||||
|
||||
@@ -63,7 +62,7 @@ jobs:
|
||||
|
||||
ecosystem-analyzer \
|
||||
generate-report \
|
||||
--max-diagnostics-per-project=1000 \
|
||||
--max-diagnostics-per-project=1200 \
|
||||
ecosystem-diagnostics.json \
|
||||
--output dist/index.html
|
||||
|
||||
|
||||
5
.vscode/settings.json
vendored
@@ -3,7 +3,4 @@
|
||||
"--all-features"
|
||||
],
|
||||
"rust-analyzer.check.command": "clippy",
|
||||
"search.exclude": {
|
||||
"**/*.snap": true
|
||||
}
|
||||
}
|
||||
}
|
||||
151
CHANGELOG.md
@@ -1,156 +1,5 @@
|
||||
# Changelog
|
||||
|
||||
## 0.13.3
|
||||
|
||||
Released on 2025-10-02.
|
||||
|
||||
### Preview features
|
||||
|
||||
- Display diffs for `ruff format --check` and add support for different output formats ([#20443](https://github.com/astral-sh/ruff/pull/20443))
|
||||
- \[`pyflakes`\] Handle some common submodule import situations for `unused-import` (`F401`) ([#20200](https://github.com/astral-sh/ruff/pull/20200))
|
||||
- \[`ruff`\] Do not flag `%r` + `repr()` combinations (`RUF065`) ([#20600](https://github.com/astral-sh/ruff/pull/20600))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- \[`cli`\] Add conflict between `--add-noqa` and `--diff` options ([#20642](https://github.com/astral-sh/ruff/pull/20642))
|
||||
- \[`pylint`\] Exempt required imports from `PLR0402` ([#20381](https://github.com/astral-sh/ruff/pull/20381))
|
||||
- \[`pylint`\] Fix missing `max-nested-blocks` in settings display ([#20574](https://github.com/astral-sh/ruff/pull/20574))
|
||||
- \[`pyupgrade`\] Prevent infinite loop with `I002` and `UP026` ([#20634](https://github.com/astral-sh/ruff/pull/20634))
|
||||
|
||||
### Rule changes
|
||||
|
||||
- \[`flake8-simplify`\] Improve help message clarity (`SIM105`) ([#20548](https://github.com/astral-sh/ruff/pull/20548))
|
||||
|
||||
### Documentation
|
||||
|
||||
- Add the *The Basics* title back to CONTRIBUTING.md ([#20624](https://github.com/astral-sh/ruff/pull/20624))
|
||||
- Fixed documentation for try_consider_else ([#20587](https://github.com/astral-sh/ruff/pull/20587))
|
||||
- \[`isort`\] Clarify dependency between `order-by-type` and `case-sensitive` settings ([#20559](https://github.com/astral-sh/ruff/pull/20559))
|
||||
- \[`pylint`\] Clarify fix safety to include left-hand hashability (`PLR6201`) ([#20518](https://github.com/astral-sh/ruff/pull/20518))
|
||||
|
||||
### Other changes
|
||||
|
||||
- \[`playground`\] Fix quick fixes for empty ranges in playground ([#20599](https://github.com/astral-sh/ruff/pull/20599))
|
||||
|
||||
### Contributors
|
||||
|
||||
- [@TaKO8Ki](https://github.com/TaKO8Ki)
|
||||
- [@ntBre](https://github.com/ntBre)
|
||||
- [@dylwil3](https://github.com/dylwil3)
|
||||
- [@MichaReiser](https://github.com/MichaReiser)
|
||||
- [@danparizher](https://github.com/danparizher)
|
||||
- [@LilMonk](https://github.com/LilMonk)
|
||||
- [@mgiovani](https://github.com/mgiovani)
|
||||
- [@IDrokin117](https://github.com/IDrokin117)
|
||||
|
||||
## 0.13.2
|
||||
|
||||
Released on 2025-09-25.
|
||||
|
||||
### Preview features
|
||||
|
||||
- \[`flake8-async`\] Implement `blocking-path-method` (`ASYNC240`) ([#20264](https://github.com/astral-sh/ruff/pull/20264))
|
||||
- \[`flake8-bugbear`\] Implement `map-without-explicit-strict` (`B912`) ([#20429](https://github.com/astral-sh/ruff/pull/20429))
|
||||
- \[`flake8-bultins`\] Detect class-scope builtin shadowing in decorators, default args, and attribute initializers (`A003`) ([#20178](https://github.com/astral-sh/ruff/pull/20178))
|
||||
- \[`ruff`\] Implement `logging-eager-conversion` (`RUF065`) ([#19942](https://github.com/astral-sh/ruff/pull/19942))
|
||||
- Include `.pyw` files by default when linting and formatting ([#20458](https://github.com/astral-sh/ruff/pull/20458))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- Deduplicate input paths ([#20105](https://github.com/astral-sh/ruff/pull/20105))
|
||||
- \[`flake8-comprehensions`\] Preserve trailing commas for single-element lists (`C409`) ([#19571](https://github.com/astral-sh/ruff/pull/19571))
|
||||
- \[`flake8-pyi`\] Avoid syntax error from conflict with `PIE790` (`PYI021`) ([#20010](https://github.com/astral-sh/ruff/pull/20010))
|
||||
- \[`flake8-simplify`\] Correct fix for positive `maxsplit` without separator (`SIM905`) ([#20056](https://github.com/astral-sh/ruff/pull/20056))
|
||||
- \[`pyupgrade`\] Fix `UP008` not to apply when `__class__` is a local variable ([#20497](https://github.com/astral-sh/ruff/pull/20497))
|
||||
- \[`ruff`\] Fix `B004` to skip invalid `hasattr`/`getattr` calls ([#20486](https://github.com/astral-sh/ruff/pull/20486))
|
||||
- \[`ruff`\] Replace `-nan` with `nan` when using the value to construct a `Decimal` (`FURB164` ) ([#20391](https://github.com/astral-sh/ruff/pull/20391))
|
||||
|
||||
### Documentation
|
||||
|
||||
- Add 'Finding ways to help' to CONTRIBUTING.md ([#20567](https://github.com/astral-sh/ruff/pull/20567))
|
||||
- Update import path to `ruff-wasm-web` ([#20539](https://github.com/astral-sh/ruff/pull/20539))
|
||||
- \[`flake8-bandit`\] Clarify the supported hashing functions (`S324`) ([#20534](https://github.com/astral-sh/ruff/pull/20534))
|
||||
|
||||
### Other changes
|
||||
|
||||
- \[`playground`\] Allow hover quick fixes to appear for overlapping diagnostics ([#20527](https://github.com/astral-sh/ruff/pull/20527))
|
||||
- \[`playground`\] Fix non‑BMP code point handling in quick fixes and markers ([#20526](https://github.com/astral-sh/ruff/pull/20526))
|
||||
|
||||
### Contributors
|
||||
|
||||
- [@BurntSushi](https://github.com/BurntSushi)
|
||||
- [@mtshiba](https://github.com/mtshiba)
|
||||
- [@second-ed](https://github.com/second-ed)
|
||||
- [@danparizher](https://github.com/danparizher)
|
||||
- [@ShikChen](https://github.com/ShikChen)
|
||||
- [@PieterCK](https://github.com/PieterCK)
|
||||
- [@GDYendell](https://github.com/GDYendell)
|
||||
- [@RazerM](https://github.com/RazerM)
|
||||
- [@TaKO8Ki](https://github.com/TaKO8Ki)
|
||||
- [@amyreese](https://github.com/amyreese)
|
||||
- [@ntbre](https://github.com/ntBre)
|
||||
- [@MichaReiser](https://github.com/MichaReiser)
|
||||
|
||||
## 0.13.1
|
||||
|
||||
Released on 2025-09-18.
|
||||
|
||||
### Preview features
|
||||
|
||||
- \[`flake8-simplify`\] Detect unnecessary `None` default for additional key expression types (`SIM910`) ([#20343](https://github.com/astral-sh/ruff/pull/20343))
|
||||
- \[`flake8-use-pathlib`\] Add fix for `PTH123` ([#20169](https://github.com/astral-sh/ruff/pull/20169))
|
||||
- \[`flake8-use-pathlib`\] Fix `PTH101`, `PTH104`, `PTH105`, `PTH121` fixes ([#20143](https://github.com/astral-sh/ruff/pull/20143))
|
||||
- \[`flake8-use-pathlib`\] Make `PTH111` fix unsafe because it can change behavior ([#20215](https://github.com/astral-sh/ruff/pull/20215))
|
||||
- \[`pycodestyle`\] Fix `E301` to only trigger for functions immediately within a class ([#19768](https://github.com/astral-sh/ruff/pull/19768))
|
||||
- \[`refurb`\] Mark `single-item-membership-test` fix as always unsafe (`FURB171`) ([#20279](https://github.com/astral-sh/ruff/pull/20279))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- Handle t-strings for token-based rules and suppression comments ([#20357](https://github.com/astral-sh/ruff/pull/20357))
|
||||
- \[`flake8-bandit`\] Fix truthiness: dict-only `**` displays not truthy for `shell` (`S602`, `S604`, `S609`) ([#20177](https://github.com/astral-sh/ruff/pull/20177))
|
||||
- \[`flake8-simplify`\] Fix diagnostic to show correct method name for `str.rsplit` calls (`SIM905`) ([#20459](https://github.com/astral-sh/ruff/pull/20459))
|
||||
- \[`flynt`\] Use triple quotes for joined raw strings with newlines (`FLY002`) ([#20197](https://github.com/astral-sh/ruff/pull/20197))
|
||||
- \[`pyupgrade`\] Fix false positive when class name is shadowed by local variable (`UP008`) ([#20427](https://github.com/astral-sh/ruff/pull/20427))
|
||||
- \[`pyupgrade`\] Prevent infinite loop with `I002` and `UP026` ([#20327](https://github.com/astral-sh/ruff/pull/20327))
|
||||
- \[`ruff`\] Recognize t-strings, generators, and lambdas in `invalid-index-type` (`RUF016`) ([#20213](https://github.com/astral-sh/ruff/pull/20213))
|
||||
|
||||
### Rule changes
|
||||
|
||||
- \[`RUF102`\] Respect rule redirects in invalid rule code detection ([#20245](https://github.com/astral-sh/ruff/pull/20245))
|
||||
- \[`flake8-bugbear`\] Mark the fix for `unreliable-callable-check` as always unsafe (`B004`) ([#20318](https://github.com/astral-sh/ruff/pull/20318))
|
||||
- \[`ruff`\] Allow dataclass attribute value instantiation from nested frozen dataclass (`RUF009`) ([#20352](https://github.com/astral-sh/ruff/pull/20352))
|
||||
|
||||
### CLI
|
||||
|
||||
- Add fixes to `output-format=sarif` ([#20300](https://github.com/astral-sh/ruff/pull/20300))
|
||||
- Treat panics as fatal diagnostics, sort panics last ([#20258](https://github.com/astral-sh/ruff/pull/20258))
|
||||
|
||||
### Documentation
|
||||
|
||||
- \[`ruff`\] Add `analyze.string-imports-min-dots` to settings ([#20375](https://github.com/astral-sh/ruff/pull/20375))
|
||||
- Update README.md with Albumentations new repository URL ([#20415](https://github.com/astral-sh/ruff/pull/20415))
|
||||
|
||||
### Other changes
|
||||
|
||||
- Bump MSRV to Rust 1.88 ([#20470](https://github.com/astral-sh/ruff/pull/20470))
|
||||
- Enable inline noqa for multiline strings in playground ([#20442](https://github.com/astral-sh/ruff/pull/20442))
|
||||
|
||||
### Contributors
|
||||
|
||||
- [@chirizxc](https://github.com/chirizxc)
|
||||
- [@danparizher](https://github.com/danparizher)
|
||||
- [@IDrokin117](https://github.com/IDrokin117)
|
||||
- [@amyreese](https://github.com/amyreese)
|
||||
- [@AlexWaygood](https://github.com/AlexWaygood)
|
||||
- [@dylwil3](https://github.com/dylwil3)
|
||||
- [@njhearp](https://github.com/njhearp)
|
||||
- [@woodruffw](https://github.com/woodruffw)
|
||||
- [@dcreager](https://github.com/dcreager)
|
||||
- [@TaKO8Ki](https://github.com/TaKO8Ki)
|
||||
- [@BurntSushi](https://github.com/BurntSushi)
|
||||
- [@salahelfarissi](https://github.com/salahelfarissi)
|
||||
- [@MichaReiser](https://github.com/MichaReiser)
|
||||
|
||||
## 0.13.0
|
||||
|
||||
Check out the [blog post](https://astral.sh/blog/ruff-v0.13.0) for a migration
|
||||
|
||||
@@ -7,38 +7,22 @@ Welcome! We're happy to have you here. Thank you in advance for your contributio
|
||||
> This guide is for Ruff. If you're looking to contribute to ty, please see [the ty contributing
|
||||
> guide](https://github.com/astral-sh/ruff/blob/main/crates/ty/CONTRIBUTING.md).
|
||||
|
||||
## Finding ways to help
|
||||
|
||||
We label issues that would be good for a first time contributor as
|
||||
[`good first issue`](https://github.com/astral-sh/ruff/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22).
|
||||
These usually do not require significant experience with Rust or the Ruff code base.
|
||||
|
||||
We label issues that we think are a good opportunity for subsequent contributions as
|
||||
[`help wanted`](https://github.com/astral-sh/ruff/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22).
|
||||
These require varying levels of experience with Rust and Ruff. Often, we want to accomplish these
|
||||
tasks but do not have the resources to do so ourselves.
|
||||
|
||||
You don't need our permission to start on an issue we have labeled as appropriate for community
|
||||
contribution as described above. However, it's a good idea to indicate that you are going to work on
|
||||
an issue to avoid concurrent attempts to solve the same problem.
|
||||
|
||||
Please check in with us before starting work on an issue that has not been labeled as appropriate
|
||||
for community contribution. We're happy to receive contributions for other issues, but it's
|
||||
important to make sure we have consensus on the solution to the problem first.
|
||||
|
||||
Outside of issues with the labels above, issues labeled as
|
||||
[`bug`](https://github.com/astral-sh/ruff/issues?q=is%3Aopen+is%3Aissue+label%3A%22bug%22) are the
|
||||
best candidates for contribution. In contrast, issues labeled with `needs-decision` or
|
||||
`needs-design` are _not_ good candidates for contribution. Please do not open pull requests for
|
||||
issues with these labels.
|
||||
|
||||
Please do not open pull requests for new features without prior discussion. While we appreciate
|
||||
exploration of new features, we will often close these pull requests immediately. Adding a
|
||||
new feature to ruff creates a long-term maintenance burden and requires strong consensus from the ruff
|
||||
team before it is appropriate to begin work on an implementation.
|
||||
|
||||
## The Basics
|
||||
|
||||
Ruff welcomes contributions in the form of pull requests.
|
||||
|
||||
For small changes (e.g., bug fixes), feel free to submit a PR.
|
||||
|
||||
For larger changes (e.g., new lint rules, new functionality, new configuration options), consider
|
||||
creating an [**issue**](https://github.com/astral-sh/ruff/issues) outlining your proposed change.
|
||||
You can also join us on [Discord](https://discord.com/invite/astral-sh) to discuss your idea with the
|
||||
community. We've labeled [beginner-friendly tasks](https://github.com/astral-sh/ruff/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
|
||||
in the issue tracker, along with [bugs](https://github.com/astral-sh/ruff/issues?q=is%3Aissue+is%3Aopen+label%3Abug)
|
||||
and [improvements](https://github.com/astral-sh/ruff/issues?q=is%3Aissue+is%3Aopen+label%3Aaccepted)
|
||||
that are ready for contributions.
|
||||
|
||||
If you have suggestions on how we might improve the contributing documentation, [let us know](https://github.com/astral-sh/ruff/discussions/5693)!
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Ruff is written in Rust. You'll need to install the
|
||||
|
||||
383
Cargo.lock
generated
@@ -23,6 +23,12 @@ version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
@@ -98,9 +104,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-svg"
|
||||
version = "0.1.11"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26b9ec8c976eada1b0f9747a3d7cc4eae3bef10613e443746e7487f26c872fde"
|
||||
checksum = "dc03a770ef506fe1396c0e476120ac0e6523cf14b74218dd5f18cd6833326fa9"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-lossy",
|
||||
@@ -122,9 +128,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.100"
|
||||
version = "1.0.99"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
@@ -278,9 +284,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "boxcar"
|
||||
version = "0.2.14"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36f64beae40a84da1b4b26ff2761a5b895c12adc41dc25aaee1c4f2bbfe97a6e"
|
||||
checksum = "26c4925bc979b677330a8c7fe7a8c94af2dbb4a2d37b4a20a80d884400f46baa"
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
@@ -340,11 +346,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.38"
|
||||
version = "1.2.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80f41ae168f955c12fb8960b057d70d0ca153fb83182b57d86380443527be7e9"
|
||||
checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
"libc",
|
||||
"shlex",
|
||||
@@ -352,9 +357,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.3"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
|
||||
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
@@ -364,13 +369,14 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.42"
|
||||
version = "0.4.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
|
||||
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"num-traits",
|
||||
"windows-link 0.2.0",
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -402,9 +408,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.48"
|
||||
version = "4.5.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae"
|
||||
checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -412,9 +418,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.48"
|
||||
version = "4.5.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9"
|
||||
checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -425,9 +431,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "4.5.58"
|
||||
version = "4.5.55"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75bf0b32ad2e152de789bb635ea4d3078f6b838ad7974143e99b99f45a04af4a"
|
||||
checksum = "a5abde44486daf70c5be8b8f8f1b66c49f86236edf6fa2abadb4d961c4c6229a"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
@@ -644,15 +650,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.16.1"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b430743a6eb14e9764d4260d4c0d8123087d504eeb9c48f2b2a5e810dd369df4"
|
||||
checksum = "2e09ced7ebbccb63b4c65413d821f2e00ce54c5ca4514ddc6b3c892fdbcbc69d"
|
||||
dependencies = [
|
||||
"encode_unicode",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"unicode-width 0.2.1",
|
||||
"windows-sys 0.61.0",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -831,9 +837,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.21.3"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0"
|
||||
checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
@@ -841,9 +847,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.21.3"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4"
|
||||
checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
@@ -855,9 +861,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.21.3"
|
||||
version = "0.20.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"
|
||||
checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
@@ -950,7 +956,7 @@ dependencies = [
|
||||
"libc",
|
||||
"option-ext",
|
||||
"redox_users",
|
||||
"windows-sys 0.61.0",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1031,12 +1037,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.14"
|
||||
version = "0.3.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1047,11 +1053,12 @@ checksum = "5692dd7b5a1978a5aeb0ce83b7655c58ca8efdcb79d21036ea249da95afec2c6"
|
||||
|
||||
[[package]]
|
||||
name = "escargot"
|
||||
version = "0.5.15"
|
||||
version = "0.5.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11c3aea32bc97b500c9ca6a72b768a26e558264303d101d3409cf6d57a9ed0cf"
|
||||
checksum = "83f351750780493fc33fa0ce8ba3c7d61f9736cfa3b3bb9ee2342643ffe40211"
|
||||
dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
@@ -1094,12 +1101,6 @@ dependencies = [
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.1.2"
|
||||
@@ -1167,9 +1168,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "get-size-derive2"
|
||||
version = "0.7.0"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3814abc7da8ab18d2fd820f5b540b5e39b6af0a32de1bdd7c47576693074843"
|
||||
checksum = "75a17a226478b2e8294ded60782c03efe54476aa8cd1371d0e5ad9d1071e74e0"
|
||||
dependencies = [
|
||||
"attribute-derive",
|
||||
"quote",
|
||||
@@ -1178,21 +1179,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "get-size2"
|
||||
version = "0.7.0"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dfe2cec5b5ce8fb94dcdb16a1708baa4d0609cc3ce305ca5d3f6f2ffb59baed"
|
||||
checksum = "5697765925a05c9d401dd04a93dfd662d336cc25fdcc3301220385a1ffcfdde5"
|
||||
dependencies = [
|
||||
"compact_str",
|
||||
"get-size-derive2",
|
||||
"hashbrown 0.16.0",
|
||||
"hashbrown 0.15.5",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getopts"
|
||||
version = "0.2.24"
|
||||
version = "0.2.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df"
|
||||
checksum = "cba6ae63eb948698e300f645f87c70f76630d505f23b8907cf1e193ee85048c1"
|
||||
dependencies = [
|
||||
"unicode-width 0.2.1",
|
||||
]
|
||||
@@ -1218,7 +1219,7 @@ dependencies = [
|
||||
"js-sys",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"wasi 0.14.7+wasi-0.2.4",
|
||||
"wasi 0.14.2+wasi-0.2.4",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
@@ -1279,15 +1280,6 @@ dependencies = [
|
||||
"foldhash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashlink"
|
||||
version = "0.10.0"
|
||||
@@ -1329,9 +1321,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.64"
|
||||
version = "0.1.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
|
||||
checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
@@ -1501,14 +1493,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.11.4"
|
||||
version = "2.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"
|
||||
checksum = "206a8042aec68fa4a62e8d3f7aa4ceb508177d9324faf261e1959e495b7a1921"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.16.0",
|
||||
"hashbrown 0.15.5",
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1517,7 +1508,7 @@ version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70a646d946d06bedbbc4cac4c218acf4bbf2d87757a784857025f4d447e4e1cd"
|
||||
dependencies = [
|
||||
"console 0.16.1",
|
||||
"console 0.16.0",
|
||||
"portable-atomic",
|
||||
"unicode-width 0.2.1",
|
||||
"unit-prefix",
|
||||
@@ -1597,9 +1588,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "inventory"
|
||||
version = "0.3.21"
|
||||
version = "0.3.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e"
|
||||
checksum = "ab08d7cd2c5897f2c949e5383ea7c7db03fb19130ffcfbf7eda795137ae3cb83"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
@@ -1728,9 +1719,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.34"
|
||||
version = "0.1.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
|
||||
checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
|
||||
dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"libc",
|
||||
@@ -1744,9 +1735,9 @@ checksum = "a037eddb7d28de1d0fc42411f501b53b75838d313908078d6698d064f3029b24"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.80"
|
||||
version = "0.3.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "852f13bec5eba4ba9afbeb93fd7c13fe56147f055939ae21c43a29a0ecb2702e"
|
||||
checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
@@ -1821,9 +1812,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.10"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
|
||||
checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"libc",
|
||||
@@ -1844,9 +1835,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.11.0"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
|
||||
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
|
||||
|
||||
[[package]]
|
||||
name = "litemap"
|
||||
@@ -2142,13 +2133,12 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||
|
||||
[[package]]
|
||||
name = "ordermap"
|
||||
version = "0.5.12"
|
||||
version = "0.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b100f7dd605611822d30e182214d3c02fdefce2d801d23993f6b6ba6ca1392af"
|
||||
checksum = "0dcd63f1ae4b091e314a26627c467dd8810d674ba798abc0e566679955776c63"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2299,9 +2289,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.8.2"
|
||||
version = "2.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21e0a3a33733faeaf8651dfee72dd0f388f0c8e5ad496a3478fa5a922f49cfa8"
|
||||
checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"thiserror 2.0.16",
|
||||
@@ -2310,9 +2300,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.8.2"
|
||||
version = "2.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc58706f770acb1dbd0973e6530a3cff4746fb721207feb3a8a6064cd0b6c663"
|
||||
checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
@@ -2320,9 +2310,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.8.2"
|
||||
version = "2.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d4f36811dfe07f7b8573462465d5cb8965fffc2e71ae377a33aecf14c2c9a2f"
|
||||
checksum = "87e404e638f781eb3202dc82db6760c8ae8a1eeef7fb3fa8264b2ef280504966"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
@@ -2333,9 +2323,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.8.2"
|
||||
version = "2.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42919b05089acbd0a5dcd5405fb304d17d1053847b81163d09c4ad18ce8e8420"
|
||||
checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"sha2",
|
||||
@@ -2408,9 +2398,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "potential_utf"
|
||||
version = "0.1.3"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a"
|
||||
checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585"
|
||||
dependencies = [
|
||||
"zerovec",
|
||||
]
|
||||
@@ -2463,9 +2453,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "3.4.0"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983"
|
||||
checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35"
|
||||
dependencies = [
|
||||
"toml_edit",
|
||||
]
|
||||
@@ -2715,15 +2705,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-lite"
|
||||
version = "0.1.7"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "943f41321c63ef1c92fd763bfe054d2668f7f225a5c29f0105903dc2fc04ba30"
|
||||
checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a"
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.6"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
|
||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "ron"
|
||||
@@ -2738,7 +2728,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.13.3"
|
||||
version = "0.13.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"argfile",
|
||||
@@ -2994,7 +2984,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_linter"
|
||||
version = "0.13.3"
|
||||
version = "0.13.0"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"anyhow",
|
||||
@@ -3004,7 +2994,7 @@ dependencies = [
|
||||
"fern",
|
||||
"glob",
|
||||
"globset",
|
||||
"hashbrown 0.16.0",
|
||||
"hashbrown 0.15.5",
|
||||
"imperative",
|
||||
"insta",
|
||||
"is-macro",
|
||||
@@ -3348,7 +3338,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_wasm"
|
||||
version = "0.13.3"
|
||||
version = "0.13.0"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"console_log",
|
||||
@@ -3437,22 +3427,22 @@ checksum = "781442f29170c5c93b7185ad559492601acdc71d5bb0706f5868094f45cfcd08"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.1.2"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
|
||||
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.61.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.22"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
@@ -3463,7 +3453,7 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
[[package]]
|
||||
name = "salsa"
|
||||
version = "0.23.0"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=29ab321b45d00daa4315fa2a06f7207759a8c87e#29ab321b45d00daa4315fa2a06f7207759a8c87e"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=3713cd7eb30821c0c086591832dd6f59f2af7fe7#3713cd7eb30821c0c086591832dd6f59f2af7fe7"
|
||||
dependencies = [
|
||||
"boxcar",
|
||||
"compact_str",
|
||||
@@ -3487,12 +3477,12 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "salsa-macro-rules"
|
||||
version = "0.23.0"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=29ab321b45d00daa4315fa2a06f7207759a8c87e#29ab321b45d00daa4315fa2a06f7207759a8c87e"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=3713cd7eb30821c0c086591832dd6f59f2af7fe7#3713cd7eb30821c0c086591832dd6f59f2af7fe7"
|
||||
|
||||
[[package]]
|
||||
name = "salsa-macros"
|
||||
version = "0.23.0"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=29ab321b45d00daa4315fa2a06f7207759a8c87e#29ab321b45d00daa4315fa2a06f7207759a8c87e"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=3713cd7eb30821c0c086591832dd6f59f2af7fe7#3713cd7eb30821c0c086591832dd6f59f2af7fe7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3547,9 +3537,9 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.226"
|
||||
version = "1.0.223"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd"
|
||||
checksum = "a505d71960adde88e293da5cb5eda57093379f64e61cf77bf0e6a63af07a7bac"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
@@ -3568,18 +3558,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.226"
|
||||
version = "1.0.223"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4"
|
||||
checksum = "20f57cbd357666aa7b3ac84a90b4ea328f1d4ddb6772b430caa5d9e1309bb9e9"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.226"
|
||||
version = "1.0.223"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33"
|
||||
checksum = "3d428d07faf17e306e699ec1e91996e5a165ba5d6bce5b5155173e91a8a01a56"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3623,11 +3613,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "1.0.2"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5417783452c2be558477e104686f7de5dae53dba813c28435e0e70f82d9b04ee"
|
||||
checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3641,9 +3631,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.14.1"
|
||||
version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c522100790450cf78eeac1507263d0a350d4d5b30df0c8e1fe051a10c22b376e"
|
||||
checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
@@ -3652,9 +3642,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_with_macros"
|
||||
version = "3.14.1"
|
||||
version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327ada00f7d64abaac1e55a6911e90cf665aa051b9a561c7006c157f4633135e"
|
||||
checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
@@ -3840,7 +3830,7 @@ dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.61.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3854,12 +3844,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "terminal_size"
|
||||
version = "0.4.3"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0"
|
||||
checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed"
|
||||
dependencies = [
|
||||
"rustix",
|
||||
"windows-sys 0.60.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4019,9 +4009,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.10.0"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
|
||||
checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
@@ -4034,14 +4024,14 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.9.7"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0"
|
||||
checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde_core",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_datetime 0.7.0",
|
||||
"toml_parser",
|
||||
"toml_writer",
|
||||
"winnow",
|
||||
@@ -4049,39 +4039,44 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.7.2"
|
||||
version = "0.6.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1"
|
||||
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.23.6"
|
||||
version = "0.22.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3effe7c0e86fdff4f69cdd2ccc1b96f933e24811c5441d44904e8683e27184b"
|
||||
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"toml_datetime",
|
||||
"toml_parser",
|
||||
"toml_datetime 0.6.11",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.0.3"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627"
|
||||
checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_writer"
|
||||
version = "1.0.3"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d163a63c116ce562a22cda521fcc4d79152e7aba014456fb5eb442f6d6a10109"
|
||||
checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
@@ -4291,7 +4286,6 @@ dependencies = [
|
||||
"tracing",
|
||||
"ty_combine",
|
||||
"ty_python_semantic",
|
||||
"ty_static",
|
||||
"ty_vendored",
|
||||
]
|
||||
|
||||
@@ -4309,7 +4303,7 @@ dependencies = [
|
||||
"drop_bomb",
|
||||
"get-size2",
|
||||
"glob",
|
||||
"hashbrown 0.16.0",
|
||||
"hashbrown 0.15.5",
|
||||
"indexmap",
|
||||
"insta",
|
||||
"itertools 0.14.0",
|
||||
@@ -4449,7 +4443,6 @@ dependencies = [
|
||||
"ruff_source_file",
|
||||
"ruff_text_size",
|
||||
"serde-wasm-bindgen",
|
||||
"tracing",
|
||||
"ty_ide",
|
||||
"ty_project",
|
||||
"ty_python_semantic",
|
||||
@@ -4520,9 +4513,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "unicode-id"
|
||||
version = "0.3.6"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ba288e709927c043cbe476718d37be306be53fb1fafecd0dbe36d072be2580"
|
||||
checksum = "10103c57044730945224467c09f71a4db0071c123a0648cc3e818913bde6b561"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
@@ -4747,27 +4740,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.14.7+wasi-0.2.4"
|
||||
version = "0.14.2+wasi-0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c"
|
||||
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
|
||||
dependencies = [
|
||||
"wasip2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasip2"
|
||||
version = "1.0.1+wasi-0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
|
||||
dependencies = [
|
||||
"wit-bindgen",
|
||||
"wit-bindgen-rt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.103"
|
||||
version = "0.2.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab10a69fbd0a177f5f649ad4d8d3305499c42bab9aef2f7ff592d0ec8f833819"
|
||||
checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
@@ -4778,9 +4762,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.103"
|
||||
version = "0.2.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bb702423545a6007bbc368fde243ba47ca275e549c8a28617f56f6ba53b1d1c"
|
||||
checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
@@ -4792,9 +4776,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.53"
|
||||
version = "0.4.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0b221ff421256839509adbb55998214a70d829d3a28c69b4a6672e9d2a42f67"
|
||||
checksum = "0ca85039a9b469b38336411d6d6ced91f3fc87109a2a27b0c197663f5144dffe"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
@@ -4805,9 +4789,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.103"
|
||||
version = "0.2.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc65f4f411d91494355917b605e1480033152658d71f722a90647f56a70c88a0"
|
||||
checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@@ -4815,9 +4799,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.103"
|
||||
version = "0.2.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffc003a991398a8ee604a401e194b6b3a39677b3173d6e74495eb51b82e99a32"
|
||||
checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -4828,18 +4812,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.103"
|
||||
version = "0.2.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "293c37f4efa430ca14db3721dfbe48d8c33308096bd44d80ebaa775ab71ba1cf"
|
||||
checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test"
|
||||
version = "0.3.53"
|
||||
version = "0.3.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aee0a0f5343de9221a0d233b04520ed8dc2e6728dce180b1dcd9288ec9d9fa3c"
|
||||
checksum = "80cc7f8a4114fdaa0c58383caf973fc126cf004eba25c9dc639bccd3880d55ad"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"minicov",
|
||||
@@ -4850,9 +4834,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test-macro"
|
||||
version = "0.3.53"
|
||||
version = "0.3.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a369369e4360c2884c3168d22bded735c43cccae97bbc147586d4b480edd138d"
|
||||
checksum = "c5ada2ab788d46d4bda04c9d567702a79c8ced14f51f221646a16ed39d0e6a5d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -4861,9 +4845,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.80"
|
||||
version = "0.3.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbe734895e869dc429d78c4b433f8d17d95f8d05317440b4fad5ab2d33e596dc"
|
||||
checksum = "77e4b637749ff0d92b8fad63aa1f7cff3cbe125fd49c175cd6345e7272638b12"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
@@ -4901,22 +4885,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.11"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.0"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57fe7168f7de578d2d8a05b07fd61870d2e73b4020e9f49aa00da8471723497c"
|
||||
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link 0.2.0",
|
||||
"windows-link 0.1.3",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
@@ -4957,20 +4941,20 @@ checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.0"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f"
|
||||
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
|
||||
dependencies = [
|
||||
"windows-link 0.2.0",
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.5.0"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda"
|
||||
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
|
||||
dependencies = [
|
||||
"windows-link 0.2.0",
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5140,9 +5124,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.13"
|
||||
version = "0.7.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
|
||||
checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@@ -5154,10 +5138,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904"
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen"
|
||||
version = "0.46.0"
|
||||
name = "wit-bindgen-rt"
|
||||
version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
||||
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "writeable"
|
||||
@@ -5206,18 +5193,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.27"
|
||||
version = "0.8.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
|
||||
checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.27"
|
||||
version = "0.8.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
|
||||
checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -5312,9 +5299,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zstd-sys"
|
||||
version = "2.0.16+zstd.1.5.7"
|
||||
version = "2.0.15+zstd.1.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748"
|
||||
checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
|
||||
10
Cargo.toml
@@ -5,7 +5,7 @@ resolver = "2"
|
||||
[workspace.package]
|
||||
# Please update rustfmt.toml when bumping the Rust edition
|
||||
edition = "2024"
|
||||
rust-version = "1.88"
|
||||
rust-version = "1.87"
|
||||
homepage = "https://docs.astral.sh/ruff"
|
||||
documentation = "https://docs.astral.sh/ruff"
|
||||
repository = "https://github.com/astral-sh/ruff"
|
||||
@@ -86,7 +86,7 @@ etcetera = { version = "0.10.0" }
|
||||
fern = { version = "0.7.0" }
|
||||
filetime = { version = "0.2.23" }
|
||||
getrandom = { version = "0.3.1" }
|
||||
get-size2 = { version = "0.7.0", features = [
|
||||
get-size2 = { version = "0.6.2", features = [
|
||||
"derive",
|
||||
"smallvec",
|
||||
"hashbrown",
|
||||
@@ -95,7 +95,7 @@ get-size2 = { version = "0.7.0", features = [
|
||||
glob = { version = "0.3.1" }
|
||||
globset = { version = "0.4.14" }
|
||||
globwalk = { version = "0.9.1" }
|
||||
hashbrown = { version = "0.16.0", default-features = false, features = [
|
||||
hashbrown = { version = "0.15.0", default-features = false, features = [
|
||||
"raw-entry",
|
||||
"equivalent",
|
||||
"inline-more",
|
||||
@@ -144,7 +144,7 @@ regex-automata = { version = "0.4.9" }
|
||||
rustc-hash = { version = "2.0.0" }
|
||||
rustc-stable-hash = { version = "0.1.2" }
|
||||
# When updating salsa, make sure to also update the revision in `fuzz/Cargo.toml`
|
||||
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "29ab321b45d00daa4315fa2a06f7207759a8c87e", default-features = false, features = [
|
||||
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "3713cd7eb30821c0c086591832dd6f59f2af7fe7", default-features = false, features = [
|
||||
"compact_str",
|
||||
"macros",
|
||||
"salsa_unstable",
|
||||
@@ -203,7 +203,7 @@ wild = { version = "2" }
|
||||
zip = { version = "0.6.6", default-features = false }
|
||||
|
||||
[workspace.metadata.cargo-shear]
|
||||
ignored = ["getrandom", "ruff_options_metadata", "uuid", "get-size2"]
|
||||
ignored = ["getrandom", "ruff_options_metadata", "uuid"]
|
||||
|
||||
|
||||
[workspace.lints.rust]
|
||||
|
||||
@@ -148,8 +148,8 @@ curl -LsSf https://astral.sh/ruff/install.sh | sh
|
||||
powershell -c "irm https://astral.sh/ruff/install.ps1 | iex"
|
||||
|
||||
# For a specific version.
|
||||
curl -LsSf https://astral.sh/ruff/0.13.3/install.sh | sh
|
||||
powershell -c "irm https://astral.sh/ruff/0.13.3/install.ps1 | iex"
|
||||
curl -LsSf https://astral.sh/ruff/0.13.0/install.sh | sh
|
||||
powershell -c "irm https://astral.sh/ruff/0.13.0/install.ps1 | iex"
|
||||
```
|
||||
|
||||
You can also install Ruff via [Homebrew](https://formulae.brew.sh/formula/ruff), [Conda](https://anaconda.org/conda-forge/ruff),
|
||||
@@ -182,7 +182,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.13.3
|
||||
rev: v0.13.0
|
||||
hooks:
|
||||
# Run the linter.
|
||||
- id: ruff-check
|
||||
|
||||
@@ -31,7 +31,6 @@ extend-ignore-re = [
|
||||
"typ",
|
||||
# TODO: Remove this once the `TYP` redirects are removed from `rule_redirects.rs`
|
||||
"TYP",
|
||||
"ntBre"
|
||||
]
|
||||
|
||||
[default.extend-identifiers]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.13.3"
|
||||
version = "0.13.0"
|
||||
publish = true
|
||||
authors = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
|
||||
@@ -416,7 +416,6 @@ pub struct CheckCommand {
|
||||
conflicts_with = "stdin_filename",
|
||||
conflicts_with = "watch",
|
||||
conflicts_with = "fix",
|
||||
conflicts_with = "diff",
|
||||
)]
|
||||
pub add_noqa: bool,
|
||||
/// See the files Ruff will be run against with the current settings.
|
||||
@@ -538,14 +537,6 @@ pub struct FormatCommand {
|
||||
/// Exit with a non-zero status code if any files were modified via format, even if all files were formatted successfully.
|
||||
#[arg(long, help_heading = "Miscellaneous", alias = "exit-non-zero-on-fix")]
|
||||
pub exit_non_zero_on_format: bool,
|
||||
|
||||
/// Output serialization format for violations, when used with `--check`.
|
||||
/// The default serialization format is "full".
|
||||
///
|
||||
/// Note that this option is currently only respected in preview mode. A warning will be emitted
|
||||
/// if this flag is used on stable.
|
||||
#[arg(long, value_enum, env = "RUFF_OUTPUT_FORMAT")]
|
||||
pub output_format: Option<OutputFormat>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, clap::Parser)]
|
||||
@@ -793,7 +784,6 @@ impl FormatCommand {
|
||||
target_version: self.target_version.map(ast::PythonVersion::from),
|
||||
cache_dir: self.cache_dir,
|
||||
extension: self.extension,
|
||||
output_format: self.output_format,
|
||||
..ExplicitConfigOverrides::default()
|
||||
};
|
||||
|
||||
|
||||
@@ -9,10 +9,11 @@ use ignore::Error;
|
||||
use log::{debug, warn};
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
use rayon::prelude::*;
|
||||
use ruff_linter::message::create_panic_diagnostic;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use ruff_db::diagnostic::Diagnostic;
|
||||
use ruff_db::diagnostic::{
|
||||
Annotation, Diagnostic, DiagnosticId, Span, SubDiagnostic, SubDiagnosticSeverity,
|
||||
};
|
||||
use ruff_db::panic::catch_unwind;
|
||||
use ruff_linter::package::PackageRoot;
|
||||
use ruff_linter::registry::Rule;
|
||||
@@ -194,7 +195,23 @@ fn lint_path(
|
||||
match result {
|
||||
Ok(inner) => inner,
|
||||
Err(error) => {
|
||||
let diagnostic = create_panic_diagnostic(&error, Some(path));
|
||||
let message = match error.payload.as_str() {
|
||||
Some(summary) => format!("Fatal error while linting: {summary}"),
|
||||
_ => "Fatal error while linting".to_owned(),
|
||||
};
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
DiagnosticId::Panic,
|
||||
ruff_db::diagnostic::Severity::Fatal,
|
||||
message,
|
||||
);
|
||||
let span = Span::from(SourceFileBuilder::new(path.to_string_lossy(), "").finish());
|
||||
let mut annotation = Annotation::primary(span);
|
||||
annotation.set_file_level(true);
|
||||
diagnostic.annotate(annotation);
|
||||
diagnostic.sub(SubDiagnostic::new(
|
||||
SubDiagnosticSeverity::Info,
|
||||
format!("{error}"),
|
||||
));
|
||||
Ok(Diagnostics::new(vec![diagnostic], FxHashMap::default()))
|
||||
}
|
||||
}
|
||||
@@ -210,8 +227,7 @@ mod test {
|
||||
use rustc_hash::FxHashMap;
|
||||
use tempfile::TempDir;
|
||||
|
||||
use ruff_db::diagnostic::{DiagnosticFormat, DisplayDiagnosticConfig, DisplayDiagnostics};
|
||||
use ruff_linter::message::EmitterContext;
|
||||
use ruff_linter::message::{Emitter, EmitterContext, TextEmitter};
|
||||
use ruff_linter::registry::Rule;
|
||||
use ruff_linter::settings::types::UnsafeFixes;
|
||||
use ruff_linter::settings::{LinterSettings, flags};
|
||||
@@ -264,16 +280,19 @@ mod test {
|
||||
UnsafeFixes::Enabled,
|
||||
)
|
||||
.unwrap();
|
||||
let mut output = Vec::new();
|
||||
|
||||
let config = DisplayDiagnosticConfig::default()
|
||||
.format(DiagnosticFormat::Concise)
|
||||
.hide_severity(true);
|
||||
let messages = DisplayDiagnostics::new(
|
||||
&EmitterContext::new(&FxHashMap::default()),
|
||||
&config,
|
||||
&diagnostics.inner,
|
||||
)
|
||||
.to_string();
|
||||
TextEmitter::default()
|
||||
.with_show_fix_status(true)
|
||||
.with_color(false)
|
||||
.emit(
|
||||
&mut output,
|
||||
&diagnostics.inner,
|
||||
&EmitterContext::new(&FxHashMap::default()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let messages = String::from_utf8(output).unwrap();
|
||||
|
||||
insta::with_settings!({
|
||||
omit_expression => true,
|
||||
|
||||
@@ -11,19 +11,13 @@ use itertools::Itertools;
|
||||
use log::{error, warn};
|
||||
use rayon::iter::Either::{Left, Right};
|
||||
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||
use ruff_db::diagnostic::{
|
||||
Annotation, Diagnostic, DiagnosticId, DisplayDiagnosticConfig, Severity, Span,
|
||||
};
|
||||
use ruff_linter::message::{EmitterContext, create_panic_diagnostic, render_diagnostics};
|
||||
use ruff_linter::settings::types::OutputFormat;
|
||||
use ruff_notebook::NotebookIndex;
|
||||
use ruff_python_parser::ParseError;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use rustc_hash::FxHashSet;
|
||||
use thiserror::Error;
|
||||
use tracing::debug;
|
||||
|
||||
use ruff_db::panic::{PanicError, catch_unwind};
|
||||
use ruff_diagnostics::{Edit, Fix, SourceMap};
|
||||
use ruff_diagnostics::SourceMap;
|
||||
use ruff_linter::fs;
|
||||
use ruff_linter::logging::{DisplayParseError, LogLevel};
|
||||
use ruff_linter::package::PackageRoot;
|
||||
@@ -33,15 +27,14 @@ use ruff_linter::source_kind::{SourceError, SourceKind};
|
||||
use ruff_linter::warn_user_once;
|
||||
use ruff_python_ast::{PySourceType, SourceType};
|
||||
use ruff_python_formatter::{FormatModuleError, QuoteStyle, format_module_source, format_range};
|
||||
use ruff_source_file::{LineIndex, LineRanges, OneIndexed, SourceFileBuilder};
|
||||
use ruff_source_file::LineIndex;
|
||||
use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||
use ruff_workspace::FormatterSettings;
|
||||
use ruff_workspace::resolver::{
|
||||
PyprojectConfig, ResolvedFile, Resolver, match_exclusion, python_files_in_path,
|
||||
};
|
||||
use ruff_workspace::resolver::{ResolvedFile, Resolver, match_exclusion, python_files_in_path};
|
||||
|
||||
use crate::args::{ConfigArguments, FormatArguments, FormatRange};
|
||||
use crate::cache::{Cache, FileCacheKey, PackageCacheMap, PackageCaches};
|
||||
use crate::resolve::resolve;
|
||||
use crate::{ExitStatus, resolve_default_files};
|
||||
|
||||
#[derive(Debug, Copy, Clone, is_macro::Is)]
|
||||
@@ -70,14 +63,11 @@ impl FormatMode {
|
||||
pub(crate) fn format(
|
||||
cli: FormatArguments,
|
||||
config_arguments: &ConfigArguments,
|
||||
pyproject_config: &PyprojectConfig,
|
||||
) -> Result<ExitStatus> {
|
||||
let pyproject_config = resolve(config_arguments, cli.stdin_filename.as_deref())?;
|
||||
let mode = FormatMode::from_cli(&cli);
|
||||
let files = resolve_default_files(cli.files, false);
|
||||
let (paths, resolver) = python_files_in_path(&files, pyproject_config, config_arguments)?;
|
||||
|
||||
let output_format = pyproject_config.settings.output_format;
|
||||
let preview = pyproject_config.settings.formatter.preview;
|
||||
let (paths, resolver) = python_files_in_path(&files, &pyproject_config, config_arguments)?;
|
||||
|
||||
if paths.is_empty() {
|
||||
warn_user_once!("No Python files found under the given path(s)");
|
||||
@@ -194,26 +184,17 @@ pub(crate) fn format(
|
||||
caches.persist()?;
|
||||
|
||||
// Report on any errors.
|
||||
//
|
||||
// We only convert errors to `Diagnostic`s in `Check` mode with preview enabled, otherwise we
|
||||
// fall back on printing simple messages.
|
||||
if !(preview.is_enabled() && mode.is_check()) {
|
||||
errors.sort_unstable_by(|a, b| a.path().cmp(&b.path()));
|
||||
errors.sort_unstable_by(|a, b| a.path().cmp(&b.path()));
|
||||
|
||||
for error in &errors {
|
||||
error!("{error}");
|
||||
}
|
||||
for error in &errors {
|
||||
error!("{error}");
|
||||
}
|
||||
|
||||
let results = FormatResults::new(results.as_slice(), mode);
|
||||
match mode {
|
||||
FormatMode::Write => {}
|
||||
FormatMode::Check => {
|
||||
if preview.is_enabled() {
|
||||
results.write_changed_preview(&mut stdout().lock(), output_format, &errors)?;
|
||||
} else {
|
||||
results.write_changed(&mut stdout().lock())?;
|
||||
}
|
||||
results.write_changed(&mut stdout().lock())?;
|
||||
}
|
||||
FormatMode::Diff => {
|
||||
results.write_diff(&mut stdout().lock())?;
|
||||
@@ -225,7 +206,7 @@ pub(crate) fn format(
|
||||
if mode.is_diff() {
|
||||
// Allow piping the diff to e.g. a file by writing the summary to stderr
|
||||
results.write_summary(&mut stderr().lock())?;
|
||||
} else if !preview.is_enabled() || output_format.is_human_readable() {
|
||||
} else {
|
||||
results.write_summary(&mut stdout().lock())?;
|
||||
}
|
||||
}
|
||||
@@ -314,7 +295,8 @@ pub(crate) fn format_path(
|
||||
|
||||
FormatResult::Formatted
|
||||
}
|
||||
FormatMode::Check | FormatMode::Diff => FormatResult::Diff {
|
||||
FormatMode::Check => FormatResult::Formatted,
|
||||
FormatMode::Diff => FormatResult::Diff {
|
||||
unformatted,
|
||||
formatted,
|
||||
},
|
||||
@@ -347,7 +329,7 @@ pub(crate) enum FormattedSource {
|
||||
impl From<FormattedSource> for FormatResult {
|
||||
fn from(value: FormattedSource) -> Self {
|
||||
match value {
|
||||
FormattedSource::Formatted { .. } => FormatResult::Formatted,
|
||||
FormattedSource::Formatted(_) => FormatResult::Formatted,
|
||||
FormattedSource::Unchanged => FormatResult::Unchanged,
|
||||
}
|
||||
}
|
||||
@@ -495,10 +477,10 @@ pub(crate) fn format_source(
|
||||
/// The result of an individual formatting operation.
|
||||
#[derive(Debug, Clone, is_macro::Is)]
|
||||
pub(crate) enum FormatResult {
|
||||
/// The file was formatted and written back to disk.
|
||||
/// The file was formatted.
|
||||
Formatted,
|
||||
|
||||
/// The file needs to be formatted, as the `formatted` and `unformatted` contents differ.
|
||||
/// The file was formatted, [`SourceKind`] contains the formatted code
|
||||
Diff {
|
||||
unformatted: SourceKind,
|
||||
formatted: SourceKind,
|
||||
@@ -570,7 +552,7 @@ impl<'a> FormatResults<'a> {
|
||||
.results
|
||||
.iter()
|
||||
.filter_map(|result| {
|
||||
if result.result.is_diff() {
|
||||
if result.result.is_formatted() {
|
||||
Some(result.path.as_path())
|
||||
} else {
|
||||
None
|
||||
@@ -584,30 +566,6 @@ impl<'a> FormatResults<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Write a list of the files that would be changed and any errors to the given writer.
|
||||
fn write_changed_preview(
|
||||
&self,
|
||||
f: &mut impl Write,
|
||||
output_format: OutputFormat,
|
||||
errors: &[FormatCommandError],
|
||||
) -> io::Result<()> {
|
||||
let mut notebook_index = FxHashMap::default();
|
||||
let diagnostics: Vec<_> = errors
|
||||
.iter()
|
||||
.map(Diagnostic::from)
|
||||
.chain(self.to_diagnostics(&mut notebook_index))
|
||||
.sorted_unstable_by(Diagnostic::ruff_start_ordering)
|
||||
.collect();
|
||||
|
||||
let context = EmitterContext::new(¬ebook_index);
|
||||
let config = DisplayDiagnosticConfig::default()
|
||||
.hide_severity(true)
|
||||
.show_fix_diff(true)
|
||||
.color(!cfg!(test) && colored::control::SHOULD_COLORIZE.should_colorize());
|
||||
|
||||
render_diagnostics(f, output_format, config, &context, &diagnostics)
|
||||
}
|
||||
|
||||
/// Write a summary of the formatting results to the given writer.
|
||||
fn write_summary(&self, f: &mut impl Write) -> io::Result<()> {
|
||||
// Compute the number of changed and unchanged files.
|
||||
@@ -670,155 +628,6 @@ impl<'a> FormatResults<'a> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert formatted files into [`Diagnostic`]s.
|
||||
fn to_diagnostics(
|
||||
&self,
|
||||
notebook_index: &mut FxHashMap<String, NotebookIndex>,
|
||||
) -> impl Iterator<Item = Diagnostic> {
|
||||
/// The number of unmodified context lines rendered in diffs.
|
||||
///
|
||||
/// Note that this should be kept in sync with the argument to `TextDiff::grouped_ops` in
|
||||
/// the diff rendering in `ruff_db` (currently 3). The `similar` crate uses two times that
|
||||
/// argument as a cutoff for rendering unmodified lines.
|
||||
const CONTEXT_LINES: u32 = 6;
|
||||
|
||||
self.results.iter().filter_map(|result| {
|
||||
let (unformatted, formatted) = match &result.result {
|
||||
FormatResult::Skipped | FormatResult::Unchanged => return None,
|
||||
FormatResult::Diff {
|
||||
unformatted,
|
||||
formatted,
|
||||
} => (unformatted, formatted),
|
||||
FormatResult::Formatted => {
|
||||
debug_assert!(
|
||||
false,
|
||||
"Expected `FormatResult::Diff` for changed files in check mode"
|
||||
);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
DiagnosticId::Unformatted,
|
||||
Severity::Error,
|
||||
"File would be reformatted",
|
||||
);
|
||||
|
||||
// Locate the first and last characters that differ to use as the diagnostic
|
||||
// range and to narrow the `Edit` range.
|
||||
let modified_range = ModifiedRange::new(unformatted, formatted);
|
||||
|
||||
let path = result.path.to_string_lossy();
|
||||
// For scripts, this is a single `Edit` using the `ModifiedRange` above, but notebook
|
||||
// edits must be split by cell in order to render them as diffs.
|
||||
//
|
||||
// We also attempt to estimate the line number width for aligning the
|
||||
// annotate-snippets header. This is only an estimate because we don't actually know
|
||||
// if the maximum line number present in the document will be rendered as part of
|
||||
// the diff, either as a changed line or as an unchanged context line. For
|
||||
// notebooks, we refine our estimate by checking the number of lines in each cell
|
||||
// individually, otherwise we could use `formatted.source_code().count_lines(...)`
|
||||
// in both cases.
|
||||
let (fix, line_count) = if let SourceKind::IpyNotebook(formatted) = formatted
|
||||
&& let SourceKind::IpyNotebook(unformatted) = unformatted
|
||||
{
|
||||
notebook_index.insert(path.to_string(), unformatted.index().clone());
|
||||
|
||||
let mut edits = formatted
|
||||
.cell_offsets()
|
||||
.ranges()
|
||||
.zip(unformatted.cell_offsets().ranges())
|
||||
.filter_map(|(formatted_range, unformatted_range)| {
|
||||
// Filter out cells that weren't modified. We use `intersect` instead of
|
||||
// `contains_range` because the full modified range might start or end in
|
||||
// the middle of a cell:
|
||||
//
|
||||
// ```
|
||||
// | cell 1 | cell 2 | cell 3 |
|
||||
// |----------------| modified range
|
||||
// ```
|
||||
//
|
||||
// The intersection will be `Some` for all three cells in this case.
|
||||
if modified_range
|
||||
.unformatted
|
||||
.intersect(unformatted_range)
|
||||
.is_some()
|
||||
{
|
||||
let formatted = &formatted.source_code()[formatted_range];
|
||||
let edit = if formatted.is_empty() {
|
||||
Edit::range_deletion(unformatted_range)
|
||||
} else {
|
||||
Edit::range_replacement(formatted.to_string(), unformatted_range)
|
||||
};
|
||||
Some(edit)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
let fix = Fix::safe_edits(
|
||||
edits
|
||||
.next()
|
||||
.expect("Formatted files must have at least one edit"),
|
||||
edits,
|
||||
);
|
||||
let source = formatted.source_code();
|
||||
let line_count = formatted
|
||||
.cell_offsets()
|
||||
.ranges()
|
||||
.filter_map(|range| {
|
||||
if modified_range.formatted.contains_range(range) {
|
||||
Some(source.count_lines(range))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.max()
|
||||
.unwrap_or_default();
|
||||
(fix, line_count)
|
||||
} else {
|
||||
let formatted_code = &formatted.source_code()[modified_range.formatted];
|
||||
let edit = if formatted_code.is_empty() {
|
||||
Edit::range_deletion(modified_range.unformatted)
|
||||
} else {
|
||||
Edit::range_replacement(formatted_code.to_string(), modified_range.unformatted)
|
||||
};
|
||||
let fix = Fix::safe_edit(edit);
|
||||
let line_count = formatted
|
||||
.source_code()
|
||||
.count_lines(TextRange::up_to(modified_range.formatted.end()));
|
||||
(fix, line_count)
|
||||
};
|
||||
|
||||
let source_file = SourceFileBuilder::new(path, unformatted.source_code()).finish();
|
||||
let span = Span::from(source_file).with_range(modified_range.unformatted);
|
||||
let mut annotation = Annotation::primary(span);
|
||||
annotation.hide_snippet(true);
|
||||
diagnostic.annotate(annotation);
|
||||
diagnostic.set_fix(fix);
|
||||
|
||||
// TODO(brent) this offset is a hack to get the header of the diagnostic message, which
|
||||
// is rendered by our fork of `annotate-snippets`, to align with our manually-rendered
|
||||
// diff. `annotate-snippets` computes the alignment of the arrow in the header based on
|
||||
// the maximum line number width in its rendered snippet. However, we don't have a
|
||||
// reasonable range to underline in an annotation, so we don't send `annotate-snippets`
|
||||
// a snippet to measure. If we commit to staying on our fork, a more robust way of
|
||||
// handling this would be to move the diff rendering in
|
||||
// `ruff_db::diagnostic::render::full` into `annotate-snippets`, likely as another
|
||||
// `DisplayLine` variant and update the `lineno_width` calculation in
|
||||
// `DisplayList::fmt`. That would handle this offset "automatically."
|
||||
let line_count = (line_count + CONTEXT_LINES).min(
|
||||
formatted
|
||||
.source_code()
|
||||
.count_lines(TextRange::up_to(formatted.source_code().text_len())),
|
||||
);
|
||||
let lines = OneIndexed::new(line_count as usize).unwrap_or_default();
|
||||
diagnostic.set_header_offset(lines.digits().get());
|
||||
|
||||
Some(diagnostic)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// An error that can occur while formatting a set of files.
|
||||
@@ -830,6 +639,7 @@ pub(crate) enum FormatCommandError {
|
||||
Read(Option<PathBuf>, SourceError),
|
||||
Format(Option<PathBuf>, FormatModuleError),
|
||||
Write(Option<PathBuf>, SourceError),
|
||||
Diff(Option<PathBuf>, io::Error),
|
||||
RangeFormatNotebook(Option<PathBuf>),
|
||||
}
|
||||
|
||||
@@ -848,65 +658,12 @@ impl FormatCommandError {
|
||||
| Self::Read(path, _)
|
||||
| Self::Format(path, _)
|
||||
| Self::Write(path, _)
|
||||
| Self::Diff(path, _)
|
||||
| Self::RangeFormatNotebook(path) => path.as_deref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&FormatCommandError> for Diagnostic {
|
||||
fn from(error: &FormatCommandError) -> Self {
|
||||
let annotation = error.path().map(|path| {
|
||||
let file = SourceFileBuilder::new(path.to_string_lossy(), "").finish();
|
||||
let span = Span::from(file);
|
||||
let mut annotation = Annotation::primary(span);
|
||||
annotation.hide_snippet(true);
|
||||
annotation
|
||||
});
|
||||
|
||||
let mut diagnostic = match error {
|
||||
FormatCommandError::Ignore(error) => {
|
||||
Diagnostic::new(DiagnosticId::Io, Severity::Error, error)
|
||||
}
|
||||
FormatCommandError::Parse(display_parse_error) => Diagnostic::new(
|
||||
DiagnosticId::InvalidSyntax,
|
||||
Severity::Error,
|
||||
&display_parse_error.error().error,
|
||||
),
|
||||
FormatCommandError::Panic(path, panic_error) => {
|
||||
return create_panic_diagnostic(panic_error, path.as_deref());
|
||||
}
|
||||
FormatCommandError::Read(_, source_error)
|
||||
| FormatCommandError::Write(_, source_error) => {
|
||||
Diagnostic::new(DiagnosticId::Io, Severity::Error, source_error)
|
||||
}
|
||||
FormatCommandError::Format(_, format_module_error) => match format_module_error {
|
||||
FormatModuleError::ParseError(parse_error) => Diagnostic::new(
|
||||
DiagnosticId::InternalError,
|
||||
Severity::Error,
|
||||
&parse_error.error,
|
||||
),
|
||||
FormatModuleError::FormatError(format_error) => {
|
||||
Diagnostic::new(DiagnosticId::InternalError, Severity::Error, format_error)
|
||||
}
|
||||
FormatModuleError::PrintError(print_error) => {
|
||||
Diagnostic::new(DiagnosticId::InternalError, Severity::Error, print_error)
|
||||
}
|
||||
},
|
||||
FormatCommandError::RangeFormatNotebook(_) => Diagnostic::new(
|
||||
DiagnosticId::InvalidCliOption,
|
||||
Severity::Error,
|
||||
"Range formatting isn't supported for notebooks.",
|
||||
),
|
||||
};
|
||||
|
||||
if let Some(annotation) = annotation {
|
||||
diagnostic.annotate(annotation);
|
||||
}
|
||||
|
||||
diagnostic
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FormatCommandError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
@@ -974,6 +731,23 @@ impl Display for FormatCommandError {
|
||||
write!(f, "{header} {err}", header = "Failed to format:".bold())
|
||||
}
|
||||
}
|
||||
Self::Diff(path, err) => {
|
||||
if let Some(path) = path {
|
||||
write!(
|
||||
f,
|
||||
"{}{}{} {err}",
|
||||
"Failed to generate diff for ".bold(),
|
||||
fs::relativize_path(path).bold(),
|
||||
":".bold()
|
||||
)
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"{header} {err}",
|
||||
header = "Failed to generate diff:".bold(),
|
||||
)
|
||||
}
|
||||
}
|
||||
Self::RangeFormatNotebook(path) => {
|
||||
if let Some(path) = path {
|
||||
write!(
|
||||
@@ -1018,54 +792,6 @@ impl Display for FormatCommandError {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ModifiedRange {
|
||||
unformatted: TextRange,
|
||||
formatted: TextRange,
|
||||
}
|
||||
|
||||
impl ModifiedRange {
|
||||
/// Determine the range that differs between `unformatted` and `formatted`.
|
||||
///
|
||||
/// If the two inputs are equal, the returned ranges will be empty.
|
||||
fn new(unformatted: &SourceKind, formatted: &SourceKind) -> Self {
|
||||
let unformatted = unformatted.source_code();
|
||||
let formatted = formatted.source_code();
|
||||
|
||||
let mut prefix_length = TextSize::ZERO;
|
||||
for (unformatted, formatted) in unformatted.chars().zip(formatted.chars()) {
|
||||
if unformatted != formatted {
|
||||
break;
|
||||
}
|
||||
prefix_length += unformatted.text_len();
|
||||
}
|
||||
|
||||
// For the ends of the ranges, track the length of the common suffix and then subtract that
|
||||
// from each total text length. Unlike for `start`, the character offsets are very unlikely
|
||||
// to be equal, so they need to be treated separately.
|
||||
let mut suffix_length = TextSize::ZERO;
|
||||
for (old, new) in unformatted[prefix_length.to_usize()..]
|
||||
.chars()
|
||||
.rev()
|
||||
.zip(formatted[prefix_length.to_usize()..].chars().rev())
|
||||
{
|
||||
if old != new {
|
||||
break;
|
||||
}
|
||||
suffix_length += old.text_len();
|
||||
}
|
||||
|
||||
let unformatted_range =
|
||||
TextRange::new(prefix_length, unformatted.text_len() - suffix_length);
|
||||
let formatted_range = TextRange::new(prefix_length, formatted.text_len() - suffix_length);
|
||||
|
||||
Self {
|
||||
unformatted: unformatted_range,
|
||||
formatted: formatted_range,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn warn_incompatible_formatter_settings(resolver: &Resolver) {
|
||||
// First, collect all rules that are incompatible regardless of the linter-specific settings.
|
||||
let mut incompatible_rules = FxHashSet::default();
|
||||
@@ -1237,144 +963,3 @@ pub(super) fn warn_incompatible_formatter_settings(resolver: &Resolver) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::io;
|
||||
use std::ops::Range;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use ignore::Error;
|
||||
use insta::assert_snapshot;
|
||||
|
||||
use ruff_db::panic::catch_unwind;
|
||||
use ruff_linter::logging::DisplayParseError;
|
||||
use ruff_linter::source_kind::{SourceError, SourceKind};
|
||||
use ruff_python_formatter::FormatModuleError;
|
||||
use ruff_python_parser::{ParseError, ParseErrorType};
|
||||
use ruff_text_size::{TextRange, TextSize};
|
||||
use test_case::test_case;
|
||||
|
||||
use crate::commands::format::{FormatCommandError, FormatMode, FormatResults, ModifiedRange};
|
||||
|
||||
#[test]
|
||||
fn error_diagnostics() -> anyhow::Result<()> {
|
||||
let path = PathBuf::from("test.py");
|
||||
let source_kind = SourceKind::Python("1".to_string());
|
||||
|
||||
let panic_error = catch_unwind(|| {
|
||||
panic!("Test panic for FormatCommandError");
|
||||
})
|
||||
.unwrap_err();
|
||||
|
||||
let errors = [
|
||||
FormatCommandError::Ignore(Error::WithPath {
|
||||
path: path.clone(),
|
||||
err: Box::new(Error::Io(io::Error::new(
|
||||
io::ErrorKind::PermissionDenied,
|
||||
"Permission denied",
|
||||
))),
|
||||
}),
|
||||
FormatCommandError::Parse(DisplayParseError::from_source_kind(
|
||||
ParseError {
|
||||
error: ParseErrorType::UnexpectedIndentation,
|
||||
location: TextRange::default(),
|
||||
},
|
||||
Some(path.clone()),
|
||||
&source_kind,
|
||||
)),
|
||||
FormatCommandError::Panic(Some(path.clone()), Box::new(panic_error)),
|
||||
FormatCommandError::Read(
|
||||
Some(path.clone()),
|
||||
SourceError::Io(io::Error::new(io::ErrorKind::NotFound, "File not found")),
|
||||
),
|
||||
FormatCommandError::Format(
|
||||
Some(path.clone()),
|
||||
FormatModuleError::ParseError(ParseError {
|
||||
error: ParseErrorType::EmptySlice,
|
||||
location: TextRange::default(),
|
||||
}),
|
||||
),
|
||||
FormatCommandError::Write(
|
||||
Some(path.clone()),
|
||||
SourceError::Io(io::Error::new(
|
||||
io::ErrorKind::PermissionDenied,
|
||||
"Cannot write to file",
|
||||
)),
|
||||
),
|
||||
FormatCommandError::RangeFormatNotebook(Some(path)),
|
||||
];
|
||||
|
||||
let results = FormatResults::new(&[], FormatMode::Check);
|
||||
let mut buf = Vec::new();
|
||||
results.write_changed_preview(
|
||||
&mut buf,
|
||||
ruff_linter::settings::types::OutputFormat::Full,
|
||||
&errors,
|
||||
)?;
|
||||
|
||||
let mut settings = insta::Settings::clone_current();
|
||||
settings.add_filter(r"(Panicked at) [^:]+:\d+:\d+", "$1 <location>");
|
||||
let _s = settings.bind_to_scope();
|
||||
|
||||
assert_snapshot!(str::from_utf8(&buf)?, @r"
|
||||
io: test.py: Permission denied
|
||||
--> test.py:1:1
|
||||
|
||||
invalid-syntax: Unexpected indentation
|
||||
--> test.py:1:1
|
||||
|
||||
io: File not found
|
||||
--> test.py:1:1
|
||||
|
||||
internal-error: Expected index or slice expression
|
||||
--> test.py:1:1
|
||||
|
||||
io: Cannot write to file
|
||||
--> test.py:1:1
|
||||
|
||||
invalid-cli-option: Range formatting isn't supported for notebooks.
|
||||
--> test.py:1:1
|
||||
|
||||
panic: Panicked at <location> when checking `test.py`: `Test panic for FormatCommandError`
|
||||
--> test.py:1:1
|
||||
info: This indicates a bug in Ruff.
|
||||
info: If you could open an issue at https://github.com/astral-sh/ruff/issues/new?title=%5Bpanic%5D, we'd be very appreciative!
|
||||
info: run with `RUST_BACKTRACE=1` environment variable to show the full backtrace information
|
||||
");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case("abcdef", "abcXYdef", 3..3, 3..5; "insertion")]
|
||||
#[test_case("abcXYdef", "abcdef", 3..5, 3..3; "deletion")]
|
||||
#[test_case("abcXdef", "abcYdef", 3..4, 3..4; "modification")]
|
||||
#[test_case("abc", "abcX", 3..3, 3..4; "strict_prefix")]
|
||||
#[test_case("", "", 0..0, 0..0; "empty")]
|
||||
#[test_case("abc", "abc", 3..3, 3..3; "equal")]
|
||||
fn modified_range(
|
||||
unformatted: &str,
|
||||
formatted: &str,
|
||||
expect_unformatted: Range<u32>,
|
||||
expect_formatted: Range<u32>,
|
||||
) {
|
||||
let mr = ModifiedRange::new(
|
||||
&SourceKind::Python(unformatted.to_string()),
|
||||
&SourceKind::Python(formatted.to_string()),
|
||||
);
|
||||
assert_eq!(
|
||||
mr.unformatted,
|
||||
TextRange::new(
|
||||
TextSize::new(expect_unformatted.start),
|
||||
TextSize::new(expect_unformatted.end)
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
mr.formatted,
|
||||
TextRange::new(
|
||||
TextSize::new(expect_formatted.start),
|
||||
TextSize::new(expect_formatted.end)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@ use std::path::Path;
|
||||
use anyhow::Result;
|
||||
use log::error;
|
||||
|
||||
use ruff_linter::source_kind::{SourceError, SourceKind};
|
||||
use ruff_linter::source_kind::SourceKind;
|
||||
use ruff_python_ast::{PySourceType, SourceType};
|
||||
use ruff_workspace::FormatterSettings;
|
||||
use ruff_workspace::resolver::{PyprojectConfig, Resolver, match_exclusion, python_file_at_path};
|
||||
use ruff_workspace::resolver::{Resolver, match_exclusion, python_file_at_path};
|
||||
|
||||
use crate::ExitStatus;
|
||||
use crate::args::{ConfigArguments, FormatArguments, FormatRange};
|
||||
@@ -15,15 +15,17 @@ use crate::commands::format::{
|
||||
FormatCommandError, FormatMode, FormatResult, FormattedSource, format_source,
|
||||
warn_incompatible_formatter_settings,
|
||||
};
|
||||
use crate::resolve::resolve;
|
||||
use crate::stdin::{parrot_stdin, read_from_stdin};
|
||||
|
||||
/// Run the formatter over a single file, read from `stdin`.
|
||||
pub(crate) fn format_stdin(
|
||||
cli: &FormatArguments,
|
||||
config_arguments: &ConfigArguments,
|
||||
pyproject_config: &PyprojectConfig,
|
||||
) -> Result<ExitStatus> {
|
||||
let mut resolver = Resolver::new(pyproject_config);
|
||||
let pyproject_config = resolve(config_arguments, cli.stdin_filename.as_deref())?;
|
||||
|
||||
let mut resolver = Resolver::new(&pyproject_config);
|
||||
warn_incompatible_formatter_settings(&resolver);
|
||||
|
||||
let mode = FormatMode::from_cli(cli);
|
||||
@@ -122,9 +124,7 @@ fn format_source_code(
|
||||
"{}",
|
||||
source_kind.diff(formatted, path).unwrap()
|
||||
)
|
||||
.map_err(|err| {
|
||||
FormatCommandError::Write(path.map(Path::to_path_buf), SourceError::Io(err))
|
||||
})?;
|
||||
.map_err(|err| FormatCommandError::Diff(path.map(Path::to_path_buf), err))?;
|
||||
}
|
||||
},
|
||||
FormattedSource::Unchanged => {
|
||||
|
||||
@@ -205,18 +205,12 @@ pub fn run(
|
||||
}
|
||||
|
||||
fn format(args: FormatCommand, global_options: GlobalConfigArgs) -> Result<ExitStatus> {
|
||||
let cli_output_format_set = args.output_format.is_some();
|
||||
let (cli, config_arguments) = args.partition(global_options)?;
|
||||
let pyproject_config = resolve::resolve(&config_arguments, cli.stdin_filename.as_deref())?;
|
||||
if cli_output_format_set && !pyproject_config.settings.formatter.preview.is_enabled() {
|
||||
warn_user_once!(
|
||||
"The --output-format flag for the formatter is unstable and requires preview mode to use."
|
||||
);
|
||||
}
|
||||
|
||||
if is_stdin(&cli.files, cli.stdin_filename.as_deref()) {
|
||||
commands::format_stdin::format_stdin(&cli, &config_arguments, &pyproject_config)
|
||||
commands::format_stdin::format_stdin(&cli, &config_arguments)
|
||||
} else {
|
||||
commands::format::format(cli, &config_arguments, &pyproject_config)
|
||||
commands::format::format(cli, &config_arguments)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::io::Write;
|
||||
use std::process::ExitCode;
|
||||
|
||||
use anyhow::Context;
|
||||
use clap::Parser;
|
||||
use colored::Colorize;
|
||||
|
||||
@@ -40,46 +39,39 @@ pub fn main() -> ExitCode {
|
||||
}
|
||||
|
||||
let args = wild::args_os();
|
||||
let args = match argfile::expand_args_from(args, argfile::parse_fromfile, argfile::PREFIX)
|
||||
.context("Failed to read CLI arguments from files")
|
||||
{
|
||||
Ok(args) => args,
|
||||
Err(err) => return report_error(&err),
|
||||
};
|
||||
let args = argfile::expand_args_from(args, argfile::parse_fromfile, argfile::PREFIX).unwrap();
|
||||
|
||||
let args = Args::parse_from(args);
|
||||
|
||||
match run(args) {
|
||||
Ok(code) => code.into(),
|
||||
Err(err) => report_error(&err),
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
{
|
||||
// Exit "gracefully" on broken pipe errors.
|
||||
//
|
||||
// See: https://github.com/BurntSushi/ripgrep/blob/bf63fe8f258afc09bae6caa48f0ae35eaf115005/crates/core/main.rs#L47C1-L61C14
|
||||
for cause in err.chain() {
|
||||
if let Some(ioerr) = cause.downcast_ref::<std::io::Error>() {
|
||||
if ioerr.kind() == std::io::ErrorKind::BrokenPipe {
|
||||
return ExitCode::from(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn report_error(err: &anyhow::Error) -> ExitCode {
|
||||
{
|
||||
// Exit "gracefully" on broken pipe errors.
|
||||
//
|
||||
// See: https://github.com/BurntSushi/ripgrep/blob/bf63fe8f258afc09bae6caa48f0ae35eaf115005/crates/core/main.rs#L47C1-L61C14
|
||||
for cause in err.chain() {
|
||||
if let Some(ioerr) = cause.downcast_ref::<std::io::Error>() {
|
||||
if ioerr.kind() == std::io::ErrorKind::BrokenPipe {
|
||||
return ExitCode::from(0);
|
||||
// Use `writeln` instead of `eprintln` to avoid panicking when the stderr pipe is broken.
|
||||
let mut stderr = std::io::stderr().lock();
|
||||
|
||||
// This communicates that this isn't a linter error but ruff itself hard-errored for
|
||||
// some reason (e.g. failed to resolve the configuration)
|
||||
writeln!(stderr, "{}", "ruff failed".red().bold()).ok();
|
||||
// Currently we generally only see one error, but e.g. with io errors when resolving
|
||||
// the configuration it is help to chain errors ("resolving configuration failed" ->
|
||||
// "failed to read file: subdir/pyproject.toml")
|
||||
for cause in err.chain() {
|
||||
writeln!(stderr, " {} {cause}", "Cause:".bold()).ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use `writeln` instead of `eprintln` to avoid panicking when the stderr pipe is broken.
|
||||
let mut stderr = std::io::stderr().lock();
|
||||
|
||||
// This communicates that this isn't a linter error but ruff itself hard-errored for
|
||||
// some reason (e.g. failed to resolve the configuration)
|
||||
writeln!(stderr, "{}", "ruff failed".red().bold()).ok();
|
||||
// Currently we generally only see one error, but e.g. with io errors when resolving
|
||||
// the configuration it is help to chain errors ("resolving configuration failed" ->
|
||||
// "failed to read file: subdir/pyproject.toml")
|
||||
for cause in err.chain() {
|
||||
writeln!(stderr, " {} {cause}", "Cause:".bold()).ok();
|
||||
ExitStatus::Error.into()
|
||||
}
|
||||
}
|
||||
ExitStatus::Error.into()
|
||||
}
|
||||
|
||||
@@ -10,11 +10,12 @@ use ruff_linter::linter::FixTable;
|
||||
use serde::Serialize;
|
||||
|
||||
use ruff_db::diagnostic::{
|
||||
Diagnostic, DiagnosticFormat, DisplayDiagnosticConfig, DisplayDiagnostics, SecondaryCode,
|
||||
Diagnostic, DiagnosticFormat, DisplayDiagnosticConfig, DisplayDiagnostics,
|
||||
DisplayGithubDiagnostics, GithubRenderer, SecondaryCode,
|
||||
};
|
||||
use ruff_linter::fs::relativize_path;
|
||||
use ruff_linter::logging::LogLevel;
|
||||
use ruff_linter::message::{EmitterContext, render_diagnostics};
|
||||
use ruff_linter::message::{Emitter, EmitterContext, GroupedEmitter, SarifEmitter, TextEmitter};
|
||||
use ruff_linter::notify_user;
|
||||
use ruff_linter::settings::flags::{self};
|
||||
use ruff_linter::settings::types::{OutputFormat, UnsafeFixes};
|
||||
@@ -224,28 +225,86 @@ impl Printer {
|
||||
let context = EmitterContext::new(&diagnostics.notebook_indexes);
|
||||
let fixables = FixableStatistics::try_from(diagnostics, self.unsafe_fixes);
|
||||
|
||||
let config = DisplayDiagnosticConfig::default()
|
||||
.preview(preview)
|
||||
.hide_severity(true)
|
||||
.color(!cfg!(test) && colored::control::SHOULD_COLORIZE.should_colorize())
|
||||
.with_show_fix_status(show_fix_status(self.fix_mode, fixables.as_ref()))
|
||||
.with_fix_applicability(self.unsafe_fixes.required_applicability())
|
||||
.show_fix_diff(preview);
|
||||
let config = DisplayDiagnosticConfig::default().preview(preview);
|
||||
|
||||
render_diagnostics(writer, self.format, config, &context, &diagnostics.inner)?;
|
||||
|
||||
if matches!(
|
||||
self.format,
|
||||
OutputFormat::Full | OutputFormat::Concise | OutputFormat::Grouped
|
||||
) {
|
||||
if self.flags.intersects(Flags::SHOW_FIX_SUMMARY) {
|
||||
if !diagnostics.fixed.is_empty() {
|
||||
writeln!(writer)?;
|
||||
print_fix_summary(writer, &diagnostics.fixed)?;
|
||||
writeln!(writer)?;
|
||||
}
|
||||
match self.format {
|
||||
OutputFormat::Json => {
|
||||
let config = config.format(DiagnosticFormat::Json);
|
||||
let value = DisplayDiagnostics::new(&context, &config, &diagnostics.inner);
|
||||
write!(writer, "{value}")?;
|
||||
}
|
||||
OutputFormat::Rdjson => {
|
||||
let config = config.format(DiagnosticFormat::Rdjson);
|
||||
let value = DisplayDiagnostics::new(&context, &config, &diagnostics.inner);
|
||||
write!(writer, "{value}")?;
|
||||
}
|
||||
OutputFormat::JsonLines => {
|
||||
let config = config.format(DiagnosticFormat::JsonLines);
|
||||
let value = DisplayDiagnostics::new(&context, &config, &diagnostics.inner);
|
||||
write!(writer, "{value}")?;
|
||||
}
|
||||
OutputFormat::Junit => {
|
||||
let config = config.format(DiagnosticFormat::Junit);
|
||||
let value = DisplayDiagnostics::new(&context, &config, &diagnostics.inner);
|
||||
write!(writer, "{value}")?;
|
||||
}
|
||||
OutputFormat::Concise | OutputFormat::Full => {
|
||||
TextEmitter::default()
|
||||
.with_show_fix_status(show_fix_status(self.fix_mode, fixables.as_ref()))
|
||||
.with_show_fix_diff(self.format == OutputFormat::Full && preview)
|
||||
.with_show_source(self.format == OutputFormat::Full)
|
||||
.with_fix_applicability(self.unsafe_fixes.required_applicability())
|
||||
.with_preview(preview)
|
||||
.emit(writer, &diagnostics.inner, &context)?;
|
||||
|
||||
if self.flags.intersects(Flags::SHOW_FIX_SUMMARY) {
|
||||
if !diagnostics.fixed.is_empty() {
|
||||
writeln!(writer)?;
|
||||
print_fix_summary(writer, &diagnostics.fixed)?;
|
||||
writeln!(writer)?;
|
||||
}
|
||||
}
|
||||
|
||||
self.write_summary_text(writer, diagnostics)?;
|
||||
}
|
||||
OutputFormat::Grouped => {
|
||||
GroupedEmitter::default()
|
||||
.with_show_fix_status(show_fix_status(self.fix_mode, fixables.as_ref()))
|
||||
.with_unsafe_fixes(self.unsafe_fixes)
|
||||
.emit(writer, &diagnostics.inner, &context)?;
|
||||
|
||||
if self.flags.intersects(Flags::SHOW_FIX_SUMMARY) {
|
||||
if !diagnostics.fixed.is_empty() {
|
||||
writeln!(writer)?;
|
||||
print_fix_summary(writer, &diagnostics.fixed)?;
|
||||
writeln!(writer)?;
|
||||
}
|
||||
}
|
||||
self.write_summary_text(writer, diagnostics)?;
|
||||
}
|
||||
OutputFormat::Github => {
|
||||
let renderer = GithubRenderer::new(&context, "Ruff");
|
||||
let value = DisplayGithubDiagnostics::new(&renderer, &diagnostics.inner);
|
||||
write!(writer, "{value}")?;
|
||||
}
|
||||
OutputFormat::Gitlab => {
|
||||
let config = config.format(DiagnosticFormat::Gitlab);
|
||||
let value = DisplayDiagnostics::new(&context, &config, &diagnostics.inner);
|
||||
write!(writer, "{value}")?;
|
||||
}
|
||||
OutputFormat::Pylint => {
|
||||
let config = config.format(DiagnosticFormat::Pylint);
|
||||
let value = DisplayDiagnostics::new(&context, &config, &diagnostics.inner);
|
||||
write!(writer, "{value}")?;
|
||||
}
|
||||
OutputFormat::Azure => {
|
||||
let config = config.format(DiagnosticFormat::Azure);
|
||||
let value = DisplayDiagnostics::new(&context, &config, &diagnostics.inner);
|
||||
write!(writer, "{value}")?;
|
||||
}
|
||||
OutputFormat::Sarif => {
|
||||
SarifEmitter.emit(writer, &diagnostics.inner, &context)?;
|
||||
}
|
||||
self.write_summary_text(writer, diagnostics)?;
|
||||
}
|
||||
|
||||
writer.flush()?;
|
||||
@@ -389,22 +448,11 @@ impl Printer {
|
||||
}
|
||||
|
||||
let context = EmitterContext::new(&diagnostics.notebook_indexes);
|
||||
let format = if preview {
|
||||
DiagnosticFormat::Full
|
||||
} else {
|
||||
DiagnosticFormat::Concise
|
||||
};
|
||||
let config = DisplayDiagnosticConfig::default()
|
||||
.hide_severity(true)
|
||||
.color(!cfg!(test) && colored::control::SHOULD_COLORIZE.should_colorize())
|
||||
TextEmitter::default()
|
||||
.with_show_fix_status(show_fix_status(self.fix_mode, fixables.as_ref()))
|
||||
.format(format)
|
||||
.with_fix_applicability(self.unsafe_fixes.required_applicability());
|
||||
write!(
|
||||
writer,
|
||||
"{}",
|
||||
DisplayDiagnostics::new(&context, &config, &diagnostics.inner)
|
||||
)?;
|
||||
.with_show_source(preview)
|
||||
.with_fix_applicability(self.unsafe_fixes.required_applicability())
|
||||
.emit(writer, &diagnostics.inner, &context)?;
|
||||
}
|
||||
writer.flush()?;
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ use tempfile::TempDir;
|
||||
|
||||
const BIN_NAME: &str = "ruff";
|
||||
|
||||
fn tempdir_filter(path: impl AsRef<Path>) -> String {
|
||||
format!(r"{}\\?/?", escape(path.as_ref().to_str().unwrap()))
|
||||
fn tempdir_filter(tempdir: &TempDir) -> String {
|
||||
format!(r"{}\\?/?", escape(tempdir.path().to_str().unwrap()))
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -500,35 +500,6 @@ OTHER = "OTHER"
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Regression test for <https://github.com/astral-sh/ruff/issues/20035>
|
||||
#[test]
|
||||
fn deduplicate_directory_and_explicit_file() -> Result<()> {
|
||||
let tempdir = TempDir::new()?;
|
||||
let root = tempdir.path();
|
||||
|
||||
let main = root.join("main.py");
|
||||
fs::write(&main, "x = 1\n")?;
|
||||
|
||||
assert_cmd_snapshot!(
|
||||
Command::new(get_cargo_bin(BIN_NAME))
|
||||
.current_dir(root)
|
||||
.args(["format", "--no-cache", "--check"])
|
||||
.arg(".")
|
||||
.arg("main.py"),
|
||||
@r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
Would reformat: main.py
|
||||
1 file would be reformatted
|
||||
|
||||
----- stderr -----
|
||||
"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn syntax_error() -> Result<()> {
|
||||
let tempdir = TempDir::new()?;
|
||||
@@ -609,112 +580,6 @@ if __name__ == "__main__":
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case::test_case("concise")]
|
||||
#[test_case::test_case("full")]
|
||||
#[test_case::test_case("json")]
|
||||
#[test_case::test_case("json-lines")]
|
||||
#[test_case::test_case("junit")]
|
||||
#[test_case::test_case("grouped")]
|
||||
#[test_case::test_case("github")]
|
||||
#[test_case::test_case("gitlab")]
|
||||
#[test_case::test_case("pylint")]
|
||||
#[test_case::test_case("rdjson")]
|
||||
#[test_case::test_case("azure")]
|
||||
#[test_case::test_case("sarif")]
|
||||
fn output_format(output_format: &str) -> Result<()> {
|
||||
const CONTENT: &str = r#"
|
||||
from test import say_hy
|
||||
|
||||
if __name__ == "__main__":
|
||||
say_hy("dear Ruff contributor")
|
||||
"#;
|
||||
|
||||
let tempdir = TempDir::new()?;
|
||||
let input = tempdir.path().join("input.py");
|
||||
fs::write(&input, CONTENT)?;
|
||||
|
||||
let snapshot = format!("output_format_{output_format}");
|
||||
|
||||
let project_dir = dunce::canonicalize(tempdir.path())?;
|
||||
|
||||
insta::with_settings!({
|
||||
filters => vec![
|
||||
(tempdir_filter(&project_dir).as_str(), "[TMP]/"),
|
||||
(tempdir_filter(&tempdir).as_str(), "[TMP]/"),
|
||||
(r#""[^"]+\\?/?input.py"#, r#""[TMP]/input.py"#),
|
||||
(ruff_linter::VERSION, "[VERSION]"),
|
||||
]
|
||||
}, {
|
||||
assert_cmd_snapshot!(
|
||||
snapshot,
|
||||
Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args([
|
||||
"format",
|
||||
"--no-cache",
|
||||
"--output-format",
|
||||
output_format,
|
||||
"--preview",
|
||||
"--check",
|
||||
"input.py",
|
||||
])
|
||||
.current_dir(&tempdir),
|
||||
);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn output_format_notebook() {
|
||||
let args = ["format", "--no-cache", "--isolated", "--preview", "--check"];
|
||||
let fixtures = Path::new("resources").join("test").join("fixtures");
|
||||
let path = fixtures.join("unformatted.ipynb");
|
||||
insta::with_settings!({filters => vec![
|
||||
// Replace windows paths
|
||||
(r"\\", "/"),
|
||||
]}, {
|
||||
assert_cmd_snapshot!(
|
||||
Command::new(get_cargo_bin(BIN_NAME)).args(args).arg(path),
|
||||
@r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
unformatted: File would be reformatted
|
||||
--> resources/test/fixtures/unformatted.ipynb:cell 1:1:1
|
||||
::: cell 1
|
||||
1 | import numpy
|
||||
- maths = (numpy.arange(100)**2).sum()
|
||||
- stats= numpy.asarray([1,2,3,4]).median()
|
||||
2 +
|
||||
3 + maths = (numpy.arange(100) ** 2).sum()
|
||||
4 + stats = numpy.asarray([1, 2, 3, 4]).median()
|
||||
::: cell 3
|
||||
1 | # A cell with IPython escape command
|
||||
2 | def some_function(foo, bar):
|
||||
3 | pass
|
||||
4 +
|
||||
5 +
|
||||
6 | %matplotlib inline
|
||||
::: cell 4
|
||||
1 | foo = %pwd
|
||||
- def some_function(foo,bar,):
|
||||
2 +
|
||||
3 +
|
||||
4 + def some_function(
|
||||
5 + foo,
|
||||
6 + bar,
|
||||
7 + ):
|
||||
8 | # Another cell with IPython escape command
|
||||
9 | foo = %pwd
|
||||
10 | print(foo)
|
||||
|
||||
1 file would be reformatted
|
||||
|
||||
----- stderr -----
|
||||
");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exit_non_zero_on_format() -> Result<()> {
|
||||
let tempdir = TempDir::new()?;
|
||||
@@ -2461,21 +2326,3 @@ fn cookiecutter_globbing() -> Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn stable_output_format_warning() {
|
||||
assert_cmd_snapshot!(
|
||||
Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(["format", "--output-format=full", "-"])
|
||||
.pass_stdin("1"),
|
||||
@r"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
1
|
||||
|
||||
----- stderr -----
|
||||
warning: The --output-format flag for the formatter is unstable and requires preview mode to use.
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1688,27 +1688,6 @@ fn check_input_from_argfile() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Regression test for https://github.com/astral-sh/ruff/issues/20655
|
||||
fn missing_argfile_reports_error() {
|
||||
let mut cmd = RuffCheck::default().filename("@!.txt").build();
|
||||
insta::with_settings!({filters => vec![
|
||||
("The system cannot find the file specified.", "No such file or directory")
|
||||
]}, {
|
||||
assert_cmd_snapshot!(cmd, @r"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
ruff failed
|
||||
Cause: Failed to read CLI arguments from files
|
||||
Cause: failed to open file `!.txt`
|
||||
Cause: No such file or directory (os error 2)
|
||||
");
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_hints_hidden_unsafe_fixes() {
|
||||
let mut cmd = RuffCheck::default()
|
||||
|
||||
@@ -271,50 +271,6 @@ OTHER = "OTHER"
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Regression test for <https://github.com/astral-sh/ruff/issues/20035>
|
||||
#[test]
|
||||
fn deduplicate_directory_and_explicit_file() -> Result<()> {
|
||||
let tempdir = TempDir::new()?;
|
||||
let root = tempdir.path();
|
||||
let ruff_toml = tempdir.path().join("ruff.toml");
|
||||
fs::write(
|
||||
&ruff_toml,
|
||||
r#"
|
||||
[lint]
|
||||
exclude = ["main.py"]
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let main = root.join("main.py");
|
||||
fs::write(&main, "import os\n")?;
|
||||
|
||||
insta::with_settings!({
|
||||
filters => vec![(tempdir_filter(&tempdir).as_str(), "[TMP]/")]
|
||||
}, {
|
||||
assert_cmd_snapshot!(
|
||||
Command::new(get_cargo_bin(BIN_NAME))
|
||||
.current_dir(root)
|
||||
.args(STDIN_BASE_OPTIONS)
|
||||
.args(["--config", &ruff_toml.file_name().unwrap().to_string_lossy()])
|
||||
.arg(".")
|
||||
// Explicitly pass main.py, should be linted regardless of it being excluded by lint.exclude
|
||||
.arg("main.py"),
|
||||
@r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
main.py:1:8: F401 [*] `os` imported but unused
|
||||
Found 1 error.
|
||||
[*] 1 fixable with the `--fix` option.
|
||||
|
||||
----- stderr -----
|
||||
"
|
||||
);
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exclude_stdin() -> Result<()> {
|
||||
let tempdir = TempDir::new()?;
|
||||
@@ -2445,7 +2401,6 @@ requires-python = ">= 3.11"
|
||||
linter.pylint.max_statements = 50
|
||||
linter.pylint.max_public_methods = 20
|
||||
linter.pylint.max_locals = 15
|
||||
linter.pylint.max_nested_blocks = 5
|
||||
linter.pyupgrade.keep_runtime_typing = false
|
||||
linter.ruff.parenthesize_tuple_in_subscript = false
|
||||
|
||||
@@ -2477,320 +2432,6 @@ requires-python = ">= 3.11"
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// ```
|
||||
/// tmp
|
||||
/// ├── pyproject.toml #<--- no `[tool.ruff]`
|
||||
/// └── test.py
|
||||
/// ```
|
||||
#[test]
|
||||
fn requires_python_no_tool_preview_enabled() -> Result<()> {
|
||||
let tempdir = TempDir::new()?;
|
||||
let project_dir = dunce::canonicalize(tempdir.path())?;
|
||||
let ruff_toml = tempdir.path().join("pyproject.toml");
|
||||
fs::write(
|
||||
&ruff_toml,
|
||||
r#"[project]
|
||||
requires-python = ">= 3.11"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let testpy = tempdir.path().join("test.py");
|
||||
fs::write(
|
||||
&testpy,
|
||||
r#"from typing import Union;foo: Union[int, str] = 1"#,
|
||||
)?;
|
||||
insta::with_settings!({
|
||||
filters => vec![(tempdir_filter(&project_dir).as_str(), "[TMP]/")]
|
||||
}, {
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(STDIN_BASE_OPTIONS)
|
||||
.arg("--preview")
|
||||
.arg("--show-settings")
|
||||
.args(["--select","UP007"])
|
||||
.arg("test.py")
|
||||
.arg("-")
|
||||
.current_dir(project_dir)
|
||||
, @r#"
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
Resolved settings for: "[TMP]/test.py"
|
||||
|
||||
# General Settings
|
||||
cache_dir = "[TMP]/.ruff_cache"
|
||||
fix = false
|
||||
fix_only = false
|
||||
output_format = concise
|
||||
show_fixes = 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",
|
||||
"dist",
|
||||
"node_modules",
|
||||
"site-packages",
|
||||
"venv",
|
||||
]
|
||||
file_resolver.extend_exclude = []
|
||||
file_resolver.force_exclude = false
|
||||
file_resolver.include = [
|
||||
"*.py",
|
||||
"*.pyi",
|
||||
"*.pyw",
|
||||
"*.ipynb",
|
||||
"**/pyproject.toml",
|
||||
]
|
||||
file_resolver.extend_include = []
|
||||
file_resolver.respect_gitignore = true
|
||||
file_resolver.project_root = "[TMP]/"
|
||||
|
||||
# Linter Settings
|
||||
linter.exclude = []
|
||||
linter.project_root = "[TMP]/"
|
||||
linter.rules.enabled = [
|
||||
non-pep604-annotation-union (UP007),
|
||||
]
|
||||
linter.rules.should_fix = [
|
||||
non-pep604-annotation-union (UP007),
|
||||
]
|
||||
linter.per_file_ignores = {}
|
||||
linter.safety_table.forced_safe = []
|
||||
linter.safety_table.forced_unsafe = []
|
||||
linter.unresolved_target_version = 3.11
|
||||
linter.per_file_target_version = {}
|
||||
linter.preview = enabled
|
||||
linter.explicit_preview_rules = false
|
||||
linter.extension = ExtensionMapping({})
|
||||
linter.allowed_confusables = []
|
||||
linter.builtins = []
|
||||
linter.dummy_variable_rgx = ^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$
|
||||
linter.external = []
|
||||
linter.ignore_init_module_imports = true
|
||||
linter.logger_objects = []
|
||||
linter.namespace_packages = []
|
||||
linter.src = [
|
||||
"[TMP]/",
|
||||
"[TMP]/src",
|
||||
]
|
||||
linter.tab_size = 4
|
||||
linter.line_length = 88
|
||||
linter.task_tags = [
|
||||
TODO,
|
||||
FIXME,
|
||||
XXX,
|
||||
]
|
||||
linter.typing_modules = []
|
||||
linter.typing_extensions = true
|
||||
|
||||
# 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_bandit.extend_markup_names = []
|
||||
linter.flake8_bandit.allowed_markup_calls = []
|
||||
linter.flake8_bugbear.extend_immutable_calls = []
|
||||
linter.flake8_builtins.allowed_modules = []
|
||||
linter.flake8_builtins.ignorelist = []
|
||||
linter.flake8_builtins.strict_checking = false
|
||||
linter.flake8_comprehensions.allow_dict_calls_with_keyword_arguments = false
|
||||
linter.flake8_copyright.notice_rgx = (?i)Copyright\s+((?:\(C\)|©)\s+)?\d{4}((-|,\s)\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 = {
|
||||
altair = alt,
|
||||
holoviews = hv,
|
||||
matplotlib = mpl,
|
||||
matplotlib.pyplot = plt,
|
||||
networkx = nx,
|
||||
numpy = np,
|
||||
numpy.typing = npt,
|
||||
pandas = pd,
|
||||
panel = pn,
|
||||
plotly.express = px,
|
||||
polars = pl,
|
||||
pyarrow = pa,
|
||||
seaborn = sns,
|
||||
tensorflow = tf,
|
||||
tkinter = tk,
|
||||
xml.etree.ElementTree = ET,
|
||||
}
|
||||
linter.flake8_import_conventions.banned_aliases = {}
|
||||
linter.flake8_import_conventions.banned_from = []
|
||||
linter.flake8_pytest_style.fixture_parentheses = false
|
||||
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 = false
|
||||
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.default_section = known { type = third_party }
|
||||
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.pyflakes.allowed_unused_imports = []
|
||||
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.pylint.max_nested_blocks = 5
|
||||
linter.pyupgrade.keep_runtime_typing = false
|
||||
linter.ruff.parenthesize_tuple_in_subscript = false
|
||||
|
||||
# Formatter Settings
|
||||
formatter.exclude = []
|
||||
formatter.unresolved_target_version = 3.11
|
||||
formatter.per_file_target_version = {}
|
||||
formatter.preview = enabled
|
||||
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
|
||||
|
||||
# Analyze Settings
|
||||
analyze.exclude = []
|
||||
analyze.preview = enabled
|
||||
analyze.target_version = 3.11
|
||||
analyze.string_imports = disabled
|
||||
analyze.extension = ExtensionMapping({})
|
||||
analyze.include_dependencies = {}
|
||||
|
||||
----- stderr -----
|
||||
"#);
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// ```
|
||||
/// tmp
|
||||
/// ├── pyproject.toml #<--- no `[tool.ruff]`
|
||||
@@ -3072,7 +2713,6 @@ requires-python = ">= 3.11"
|
||||
linter.pylint.max_statements = 50
|
||||
linter.pylint.max_public_methods = 20
|
||||
linter.pylint.max_locals = 15
|
||||
linter.pylint.max_nested_blocks = 5
|
||||
linter.pyupgrade.keep_runtime_typing = false
|
||||
linter.ruff.parenthesize_tuple_in_subscript = false
|
||||
|
||||
@@ -3437,7 +3077,6 @@ from typing import Union;foo: Union[int, str] = 1
|
||||
linter.pylint.max_statements = 50
|
||||
linter.pylint.max_public_methods = 20
|
||||
linter.pylint.max_locals = 15
|
||||
linter.pylint.max_nested_blocks = 5
|
||||
linter.pyupgrade.keep_runtime_typing = false
|
||||
linter.ruff.parenthesize_tuple_in_subscript = false
|
||||
|
||||
@@ -3818,7 +3457,6 @@ from typing import Union;foo: Union[int, str] = 1
|
||||
linter.pylint.max_statements = 50
|
||||
linter.pylint.max_public_methods = 20
|
||||
linter.pylint.max_locals = 15
|
||||
linter.pylint.max_nested_blocks = 5
|
||||
linter.pyupgrade.keep_runtime_typing = false
|
||||
linter.ruff.parenthesize_tuple_in_subscript = false
|
||||
|
||||
@@ -4147,7 +3785,6 @@ from typing import Union;foo: Union[int, str] = 1
|
||||
linter.pylint.max_statements = 50
|
||||
linter.pylint.max_public_methods = 20
|
||||
linter.pylint.max_locals = 15
|
||||
linter.pylint.max_nested_blocks = 5
|
||||
linter.pyupgrade.keep_runtime_typing = false
|
||||
linter.ruff.parenthesize_tuple_in_subscript = false
|
||||
|
||||
@@ -4476,7 +4113,6 @@ from typing import Union;foo: Union[int, str] = 1
|
||||
linter.pylint.max_statements = 50
|
||||
linter.pylint.max_public_methods = 20
|
||||
linter.pylint.max_locals = 15
|
||||
linter.pylint.max_nested_blocks = 5
|
||||
linter.pyupgrade.keep_runtime_typing = false
|
||||
linter.ruff.parenthesize_tuple_in_subscript = false
|
||||
|
||||
@@ -4762,7 +4398,6 @@ from typing import Union;foo: Union[int, str] = 1
|
||||
linter.pylint.max_statements = 50
|
||||
linter.pylint.max_public_methods = 20
|
||||
linter.pylint.max_locals = 15
|
||||
linter.pylint.max_nested_blocks = 5
|
||||
linter.pyupgrade.keep_runtime_typing = false
|
||||
linter.ruff.parenthesize_tuple_in_subscript = false
|
||||
|
||||
@@ -5101,7 +4736,6 @@ from typing import Union;foo: Union[int, str] = 1
|
||||
linter.pylint.max_statements = 50
|
||||
linter.pylint.max_public_methods = 20
|
||||
linter.pylint.max_locals = 15
|
||||
linter.pylint.max_nested_blocks = 5
|
||||
linter.pyupgrade.keep_runtime_typing = false
|
||||
linter.ruff.parenthesize_tuple_in_subscript = false
|
||||
|
||||
@@ -6199,36 +5833,6 @@ match 42: # invalid-syntax
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test_case::test_case("concise"; "concise_show_fixes")]
|
||||
#[test_case::test_case("full"; "full_show_fixes")]
|
||||
#[test_case::test_case("grouped"; "grouped_show_fixes")]
|
||||
fn output_format_show_fixes(output_format: &str) -> Result<()> {
|
||||
let tempdir = TempDir::new()?;
|
||||
let input = tempdir.path().join("input.py");
|
||||
fs::write(&input, "import os # F401")?;
|
||||
|
||||
let snapshot = format!("output_format_show_fixes_{output_format}");
|
||||
|
||||
assert_cmd_snapshot!(
|
||||
snapshot,
|
||||
Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args([
|
||||
"check",
|
||||
"--no-cache",
|
||||
"--output-format",
|
||||
output_format,
|
||||
"--select",
|
||||
"F401",
|
||||
"--fix",
|
||||
"--show-fixes",
|
||||
"input.py",
|
||||
])
|
||||
.current_dir(&tempdir),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn up045_nested_optional_flatten_all() {
|
||||
let contents = "\
|
||||
@@ -6302,7 +5906,6 @@ fn rule_panic_mixed_results_concise() -> Result<()> {
|
||||
filters => vec![
|
||||
(tempdir_filter(&tempdir).as_str(), "[TMP]/"),
|
||||
(r"\\", r"/"),
|
||||
(r"(Panicked at) [^:]+:\d+:\d+", "$1 <location>")
|
||||
]
|
||||
}, {
|
||||
assert_cmd_snapshot!(
|
||||
@@ -6319,7 +5922,7 @@ fn rule_panic_mixed_results_concise() -> Result<()> {
|
||||
[TMP]/normal.py:1:1: RUF903 Hey this is a stable test rule with a display only fix.
|
||||
[TMP]/normal.py:1:1: RUF911 Hey this is a preview test rule.
|
||||
[TMP]/normal.py:1:1: RUF950 Hey this is a test rule that was redirected from another.
|
||||
[TMP]/panic.py: panic: Panicked at <location> when checking `[TMP]/panic.py`: `This is a fake panic for testing.`
|
||||
[TMP]/panic.py: panic: Fatal error while linting: This is a fake panic for testing.
|
||||
Found 7 errors.
|
||||
[*] 1 fixable with the `--fix` option (1 hidden fix can be enabled with the `--unsafe-fixes` option).
|
||||
|
||||
@@ -6348,7 +5951,6 @@ fn rule_panic_mixed_results_full() -> Result<()> {
|
||||
filters => vec![
|
||||
(tempdir_filter(&tempdir).as_str(), "[TMP]/"),
|
||||
(r"\\", r"/"),
|
||||
(r"(Panicked at) [^:]+:\d+:\d+", "$1 <location>"),
|
||||
]
|
||||
}, {
|
||||
assert_cmd_snapshot!(
|
||||
@@ -6379,11 +5981,12 @@ fn rule_panic_mixed_results_full() -> Result<()> {
|
||||
RUF950 Hey this is a test rule that was redirected from another.
|
||||
--> [TMP]/normal.py:1:1
|
||||
|
||||
panic: Panicked at <location> when checking `[TMP]/panic.py`: `This is a fake panic for testing.`
|
||||
panic: Fatal error while linting: This is a fake panic for testing.
|
||||
--> [TMP]/panic.py:1:1
|
||||
info: This indicates a bug in Ruff.
|
||||
info: If you could open an issue at https://github.com/astral-sh/ruff/issues/new?title=%5Bpanic%5D, we'd be very appreciative!
|
||||
info: run with `RUST_BACKTRACE=1` environment variable to show the full backtrace information
|
||||
info: panicked at crates/ruff_linter/src/rules/ruff/rules/test_rules.rs:511:9:
|
||||
This is a fake panic for testing.
|
||||
run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||
|
||||
|
||||
Found 7 errors.
|
||||
[*] 1 fixable with the `--fix` option (1 hidden fix can be enabled with the `--unsafe-fixes` option).
|
||||
@@ -6398,200 +6001,3 @@ fn rule_panic_mixed_results_full() -> Result<()> {
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Test that the same rule fires across all supported extensions, but not on unsupported files
|
||||
#[test]
|
||||
fn supported_file_extensions() -> Result<()> {
|
||||
let tempdir = TempDir::new()?;
|
||||
let inner_dir = tempdir.path().join("src");
|
||||
fs::create_dir(&inner_dir)?;
|
||||
|
||||
// Create files of various types
|
||||
// text file
|
||||
fs::write(inner_dir.join("thing.txt"), b"hello world\n")?;
|
||||
// regular python
|
||||
fs::write(
|
||||
inner_dir.join("thing.py"),
|
||||
b"import os\nprint('hello world')\n",
|
||||
)?;
|
||||
// python typestub
|
||||
fs::write(
|
||||
inner_dir.join("thing.pyi"),
|
||||
b"import os\nclass foo:\n ...\n",
|
||||
)?;
|
||||
// windows gui
|
||||
fs::write(
|
||||
inner_dir.join("thing.pyw"),
|
||||
b"import os\nprint('hello world')\n",
|
||||
)?;
|
||||
// cython
|
||||
fs::write(
|
||||
inner_dir.join("thing.pyx"),
|
||||
b"import os\ncdef int add(int a, int b):\n return a + b\n",
|
||||
)?;
|
||||
// notebook
|
||||
fs::write(
|
||||
inner_dir.join("thing.ipynb"),
|
||||
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
|
||||
}
|
||||
"#,
|
||||
)?;
|
||||
|
||||
insta::with_settings!({
|
||||
filters => vec![
|
||||
(tempdir_filter(&tempdir).as_str(), "[TMP]/"),
|
||||
(r"\\", r"/"),
|
||||
]
|
||||
}, {
|
||||
assert_cmd_snapshot!(
|
||||
Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(["check", "--select", "F401", "--output-format=concise", "--no-cache"])
|
||||
.args([inner_dir]),
|
||||
@r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
[TMP]/src/thing.ipynb:cell 1:1:8: F401 [*] `os` imported but unused
|
||||
[TMP]/src/thing.py:1:8: F401 [*] `os` imported but unused
|
||||
[TMP]/src/thing.pyi:1:8: F401 [*] `os` imported but unused
|
||||
Found 3 errors.
|
||||
[*] 3 fixable with the `--fix` option.
|
||||
|
||||
----- stderr -----
|
||||
");
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Test that the same rule fires across all supported extensions, but not on unsupported files
|
||||
#[test]
|
||||
fn supported_file_extensions_preview_enabled() -> Result<()> {
|
||||
let tempdir = TempDir::new()?;
|
||||
let inner_dir = tempdir.path().join("src");
|
||||
fs::create_dir(&inner_dir)?;
|
||||
|
||||
// Create files of various types
|
||||
// text file
|
||||
fs::write(inner_dir.join("thing.txt"), b"hello world\n")?;
|
||||
// regular python
|
||||
fs::write(
|
||||
inner_dir.join("thing.py"),
|
||||
b"import os\nprint('hello world')\n",
|
||||
)?;
|
||||
// python typestub
|
||||
fs::write(
|
||||
inner_dir.join("thing.pyi"),
|
||||
b"import os\nclass foo:\n ...\n",
|
||||
)?;
|
||||
// windows gui
|
||||
fs::write(
|
||||
inner_dir.join("thing.pyw"),
|
||||
b"import os\nprint('hello world')\n",
|
||||
)?;
|
||||
// cython
|
||||
fs::write(
|
||||
inner_dir.join("thing.pyx"),
|
||||
b"import os\ncdef int add(int a, int b):\n return a + b\n",
|
||||
)?;
|
||||
// notebook
|
||||
fs::write(
|
||||
inner_dir.join("thing.ipynb"),
|
||||
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
|
||||
}
|
||||
"#,
|
||||
)?;
|
||||
|
||||
insta::with_settings!({
|
||||
filters => vec![
|
||||
(tempdir_filter(&tempdir).as_str(), "[TMP]/"),
|
||||
(r"\\", r"/"),
|
||||
]
|
||||
}, {
|
||||
assert_cmd_snapshot!(
|
||||
Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(["check", "--select", "F401", "--preview", "--output-format=concise", "--no-cache"])
|
||||
.args([inner_dir]),
|
||||
@r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
[TMP]/src/thing.ipynb:cell 1:1:8: F401 [*] `os` imported but unused
|
||||
[TMP]/src/thing.py:1:8: F401 [*] `os` imported but unused
|
||||
[TMP]/src/thing.pyi:1:8: F401 [*] `os` imported but unused
|
||||
[TMP]/src/thing.pyw:1:8: F401 [*] `os` imported but unused
|
||||
Found 4 errors.
|
||||
[*] 4 fixable with the `--fix` option.
|
||||
|
||||
----- stderr -----
|
||||
");
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/tests/format.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
- format
|
||||
- "--no-cache"
|
||||
- "--output-format"
|
||||
- azure
|
||||
- "--preview"
|
||||
- "--check"
|
||||
- input.py
|
||||
---
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
##vso[task.logissue type=error;sourcepath=[TMP]/input.py;linenumber=1;columnnumber=1;code=unformatted;]File would be reformatted
|
||||
|
||||
----- stderr -----
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/tests/format.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
- format
|
||||
- "--no-cache"
|
||||
- "--output-format"
|
||||
- concise
|
||||
- "--preview"
|
||||
- "--check"
|
||||
- input.py
|
||||
---
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
input.py:1:1: unformatted: File would be reformatted
|
||||
1 file would be reformatted
|
||||
|
||||
----- stderr -----
|
||||
@@ -1,26 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/tests/format.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
- format
|
||||
- "--no-cache"
|
||||
- "--output-format"
|
||||
- full
|
||||
- "--preview"
|
||||
- "--check"
|
||||
- input.py
|
||||
---
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
unformatted: File would be reformatted
|
||||
--> input.py:1:1
|
||||
-
|
||||
1 | from test import say_hy
|
||||
2 |
|
||||
3 | if __name__ == "__main__":
|
||||
|
||||
1 file would be reformatted
|
||||
|
||||
----- stderr -----
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/tests/format.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
- format
|
||||
- "--no-cache"
|
||||
- "--output-format"
|
||||
- github
|
||||
- "--preview"
|
||||
- "--check"
|
||||
- input.py
|
||||
---
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
::error title=Ruff (unformatted),file=[TMP]/input.py,line=1,col=1,endLine=2,endColumn=1::input.py:1:1: unformatted: File would be reformatted
|
||||
|
||||
----- stderr -----
|
||||
@@ -1,38 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/tests/format.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
- format
|
||||
- "--no-cache"
|
||||
- "--output-format"
|
||||
- gitlab
|
||||
- "--preview"
|
||||
- "--check"
|
||||
- input.py
|
||||
---
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
[
|
||||
{
|
||||
"check_name": "unformatted",
|
||||
"description": "unformatted: File would be reformatted",
|
||||
"severity": "major",
|
||||
"fingerprint": "d868d7da11a65fcf",
|
||||
"location": {
|
||||
"path": "input.py",
|
||||
"positions": {
|
||||
"begin": {
|
||||
"line": 1,
|
||||
"column": 1
|
||||
},
|
||||
"end": {
|
||||
"line": 2,
|
||||
"column": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
----- stderr -----
|
||||
@@ -1,21 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/tests/format.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
- format
|
||||
- "--no-cache"
|
||||
- "--output-format"
|
||||
- grouped
|
||||
- "--check"
|
||||
- input.py
|
||||
---
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
input.py:
|
||||
1:1 unformatted: File would be reformatted
|
||||
|
||||
1 file would be reformatted
|
||||
|
||||
----- stderr -----
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/tests/format.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
- format
|
||||
- "--no-cache"
|
||||
- "--output-format"
|
||||
- json-lines
|
||||
- "--preview"
|
||||
- "--check"
|
||||
- input.py
|
||||
---
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
{"cell":null,"code":"unformatted","end_location":{"column":1,"row":2},"filename":"[TMP]/input.py","fix":{"applicability":"safe","edits":[{"content":"","end_location":{"column":1,"row":2},"location":{"column":1,"row":1}}],"message":null},"location":{"column":1,"row":1},"message":"File would be reformatted","noqa_row":null,"url":null}
|
||||
|
||||
----- stderr -----
|
||||
@@ -1,52 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/tests/format.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
- format
|
||||
- "--no-cache"
|
||||
- "--output-format"
|
||||
- json
|
||||
- "--preview"
|
||||
- "--check"
|
||||
- input.py
|
||||
---
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
[
|
||||
{
|
||||
"cell": null,
|
||||
"code": "unformatted",
|
||||
"end_location": {
|
||||
"column": 1,
|
||||
"row": 2
|
||||
},
|
||||
"filename": "[TMP]/input.py",
|
||||
"fix": {
|
||||
"applicability": "safe",
|
||||
"edits": [
|
||||
{
|
||||
"content": "",
|
||||
"end_location": {
|
||||
"column": 1,
|
||||
"row": 2
|
||||
},
|
||||
"location": {
|
||||
"column": 1,
|
||||
"row": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"message": null
|
||||
},
|
||||
"location": {
|
||||
"column": 1,
|
||||
"row": 1
|
||||
},
|
||||
"message": "File would be reformatted",
|
||||
"noqa_row": null,
|
||||
"url": null
|
||||
}
|
||||
]
|
||||
----- stderr -----
|
||||
@@ -1,26 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/tests/format.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
- format
|
||||
- "--no-cache"
|
||||
- "--output-format"
|
||||
- junit
|
||||
- "--preview"
|
||||
- "--check"
|
||||
- input.py
|
||||
---
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuites name="ruff" tests="1" failures="1" errors="0">
|
||||
<testsuite name="[TMP]/input.py" tests="1" disabled="0" errors="0" failures="1" package="org.ruff">
|
||||
<testcase name="org.ruff.unformatted" classname="[TMP]/input" line="1" column="1">
|
||||
<failure message="File would be reformatted">line 1, col 1, File would be reformatted</failure>
|
||||
</testcase>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
----- stderr -----
|
||||
@@ -1,18 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/tests/format.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
- format
|
||||
- "--no-cache"
|
||||
- "--output-format"
|
||||
- pylint
|
||||
- "--check"
|
||||
- input.py
|
||||
---
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
input.py:1: [unformatted] File would be reformatted
|
||||
|
||||
----- stderr -----
|
||||
@@ -1,60 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/tests/format.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
- format
|
||||
- "--no-cache"
|
||||
- "--output-format"
|
||||
- rdjson
|
||||
- "--preview"
|
||||
- "--check"
|
||||
- input.py
|
||||
---
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
{
|
||||
"diagnostics": [
|
||||
{
|
||||
"code": {
|
||||
"value": "unformatted"
|
||||
},
|
||||
"location": {
|
||||
"path": "[TMP]/input.py",
|
||||
"range": {
|
||||
"end": {
|
||||
"column": 1,
|
||||
"line": 2
|
||||
},
|
||||
"start": {
|
||||
"column": 1,
|
||||
"line": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"message": "File would be reformatted",
|
||||
"suggestions": [
|
||||
{
|
||||
"range": {
|
||||
"end": {
|
||||
"column": 1,
|
||||
"line": 2
|
||||
},
|
||||
"start": {
|
||||
"column": 1,
|
||||
"line": 1
|
||||
}
|
||||
},
|
||||
"text": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"severity": "WARNING",
|
||||
"source": {
|
||||
"name": "ruff",
|
||||
"url": "https://docs.astral.sh/ruff"
|
||||
}
|
||||
}
|
||||
----- stderr -----
|
||||
@@ -1,81 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/tests/format.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
- format
|
||||
- "--no-cache"
|
||||
- "--output-format"
|
||||
- sarif
|
||||
- "--preview"
|
||||
- "--check"
|
||||
- input.py
|
||||
---
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
|
||||
"runs": [
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"fixes": [
|
||||
{
|
||||
"artifactChanges": [
|
||||
{
|
||||
"artifactLocation": {
|
||||
"uri": "[TMP]/input.py"
|
||||
},
|
||||
"replacements": [
|
||||
{
|
||||
"deletedRegion": {
|
||||
"endColumn": 1,
|
||||
"endLine": 2,
|
||||
"startColumn": 1,
|
||||
"startLine": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": {
|
||||
"text": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"level": "error",
|
||||
"locations": [
|
||||
{
|
||||
"physicalLocation": {
|
||||
"artifactLocation": {
|
||||
"uri": "[TMP]/input.py"
|
||||
},
|
||||
"region": {
|
||||
"endColumn": 1,
|
||||
"endLine": 2,
|
||||
"startColumn": 1,
|
||||
"startLine": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"message": {
|
||||
"text": "File would be reformatted"
|
||||
},
|
||||
"ruleId": "unformatted"
|
||||
}
|
||||
],
|
||||
"tool": {
|
||||
"driver": {
|
||||
"informationUri": "https://github.com/astral-sh/ruff",
|
||||
"name": "ruff",
|
||||
"rules": [],
|
||||
"version": "[VERSION]"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"version": "2.1.0"
|
||||
}
|
||||
----- stderr -----
|
||||
@@ -44,43 +44,6 @@ import some_module
|
||||
__all__ = ["some_module"]
|
||||
```
|
||||
|
||||
## Preview
|
||||
When [preview] is enabled (and certain simplifying assumptions
|
||||
are met), we analyze all import statements for a given module
|
||||
when determining whether an import is used, rather than simply
|
||||
the last of these statements. This can result in both different and
|
||||
more import statements being marked as unused.
|
||||
|
||||
For example, if a module consists of
|
||||
|
||||
```python
|
||||
import a
|
||||
import a.b
|
||||
```
|
||||
|
||||
then both statements are marked as unused under [preview], whereas
|
||||
only the second is marked as unused under stable behavior.
|
||||
|
||||
As another example, if a module consists of
|
||||
|
||||
```python
|
||||
import a.b
|
||||
import a
|
||||
|
||||
a.b.foo()
|
||||
```
|
||||
|
||||
then a diagnostic will only be emitted for the first line under [preview],
|
||||
whereas a diagnostic would only be emitted for the second line under
|
||||
stable behavior.
|
||||
|
||||
Note that this behavior is somewhat subjective and is designed
|
||||
to conform to the developer's intuition rather than Python's actual
|
||||
execution. To wit, the statement `import a.b` automatically executes
|
||||
`import a`, so in some sense `import a` is _always_ redundant
|
||||
in the presence of `import a.b`.
|
||||
|
||||
|
||||
## Fix safety
|
||||
|
||||
Fixes to remove unused imports are safe, except in `__init__.py` files.
|
||||
@@ -133,6 +96,4 @@ else:
|
||||
- [Python documentation: `importlib.util.find_spec`](https://docs.python.org/3/library/importlib.html#importlib.util.find_spec)
|
||||
- [Typing documentation: interface conventions](https://typing.python.org/en/latest/spec/distributing.html#library-interface-public-and-private-symbols)
|
||||
|
||||
[preview]: https://docs.astral.sh/ruff/preview/
|
||||
|
||||
----- stderr -----
|
||||
|
||||
@@ -22,30 +22,6 @@ exit_code: 1
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"fixes": [
|
||||
{
|
||||
"artifactChanges": [
|
||||
{
|
||||
"artifactLocation": {
|
||||
"uri": "[TMP]/input.py"
|
||||
},
|
||||
"replacements": [
|
||||
{
|
||||
"deletedRegion": {
|
||||
"endColumn": 1,
|
||||
"endLine": 2,
|
||||
"startColumn": 1,
|
||||
"startLine": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": {
|
||||
"text": "Remove unused import: `os`"
|
||||
}
|
||||
}
|
||||
],
|
||||
"level": "error",
|
||||
"locations": [
|
||||
{
|
||||
@@ -119,7 +95,7 @@ exit_code: 1
|
||||
"rules": [
|
||||
{
|
||||
"fullDescription": {
|
||||
"text": "## What it does\nChecks for unused imports.\n\n## Why is this bad?\nUnused imports add a performance overhead at runtime, and risk creating\nimport cycles. They also increase the cognitive load of reading the code.\n\nIf an import statement is used to check for the availability or existence\nof a module, consider using `importlib.util.find_spec` instead.\n\nIf an import statement is used to re-export a symbol as part of a module's\npublic interface, consider using a \"redundant\" import alias, which\ninstructs Ruff (and other tools) to respect the re-export, and avoid\nmarking it as unused, as in:\n\n```python\nfrom module import member as member\n```\n\nAlternatively, you can use `__all__` to declare a symbol as part of the module's\ninterface, as in:\n\n```python\n# __init__.py\nimport some_module\n\n__all__ = [\"some_module\"]\n```\n\n## Preview\nWhen [preview] is enabled (and certain simplifying assumptions\nare met), we analyze all import statements for a given module\nwhen determining whether an import is used, rather than simply\nthe last of these statements. This can result in both different and\nmore import statements being marked as unused.\n\nFor example, if a module consists of\n\n```python\nimport a\nimport a.b\n```\n\nthen both statements are marked as unused under [preview], whereas\nonly the second is marked as unused under stable behavior.\n\nAs another example, if a module consists of\n\n```python\nimport a.b\nimport a\n\na.b.foo()\n```\n\nthen a diagnostic will only be emitted for the first line under [preview],\nwhereas a diagnostic would only be emitted for the second line under\nstable behavior.\n\nNote that this behavior is somewhat subjective and is designed\nto conform to the developer's intuition rather than Python's actual\nexecution. To wit, the statement `import a.b` automatically executes\n`import a`, so in some sense `import a` is _always_ redundant\nin the presence of `import a.b`.\n\n\n## Fix safety\n\nFixes to remove unused imports are safe, except in `__init__.py` files.\n\nApplying fixes to `__init__.py` files is currently in preview. The fix offered depends on the\ntype of the unused import. Ruff will suggest a safe fix to export first-party imports with\neither a redundant alias or, if already present in the file, an `__all__` entry. If multiple\n`__all__` declarations are present, Ruff will not offer a fix. Ruff will suggest an unsafe fix\nto remove third-party and standard library imports -- the fix is unsafe because the module's\ninterface changes.\n\nSee [this FAQ section](https://docs.astral.sh/ruff/faq/#how-does-ruff-determine-which-of-my-imports-are-first-party-third-party-etc)\nfor more details on how Ruff\ndetermines whether an import is first or third-party.\n\n## Example\n\n```python\nimport numpy as np # unused import\n\n\ndef area(radius):\n return 3.14 * radius**2\n```\n\nUse instead:\n\n```python\ndef area(radius):\n return 3.14 * radius**2\n```\n\nTo check the availability of a module, use `importlib.util.find_spec`:\n\n```python\nfrom importlib.util import find_spec\n\nif find_spec(\"numpy\") is not None:\n print(\"numpy is installed\")\nelse:\n print(\"numpy is not installed\")\n```\n\n## Options\n- `lint.ignore-init-module-imports`\n- `lint.pyflakes.allowed-unused-imports`\n\n## References\n- [Python documentation: `import`](https://docs.python.org/3/reference/simple_stmts.html#the-import-statement)\n- [Python documentation: `importlib.util.find_spec`](https://docs.python.org/3/library/importlib.html#importlib.util.find_spec)\n- [Typing documentation: interface conventions](https://typing.python.org/en/latest/spec/distributing.html#library-interface-public-and-private-symbols)\n\n[preview]: https://docs.astral.sh/ruff/preview/\n"
|
||||
"text": "## What it does\nChecks for unused imports.\n\n## Why is this bad?\nUnused imports add a performance overhead at runtime, and risk creating\nimport cycles. They also increase the cognitive load of reading the code.\n\nIf an import statement is used to check for the availability or existence\nof a module, consider using `importlib.util.find_spec` instead.\n\nIf an import statement is used to re-export a symbol as part of a module's\npublic interface, consider using a \"redundant\" import alias, which\ninstructs Ruff (and other tools) to respect the re-export, and avoid\nmarking it as unused, as in:\n\n```python\nfrom module import member as member\n```\n\nAlternatively, you can use `__all__` to declare a symbol as part of the module's\ninterface, as in:\n\n```python\n# __init__.py\nimport some_module\n\n__all__ = [\"some_module\"]\n```\n\n## Fix safety\n\nFixes to remove unused imports are safe, except in `__init__.py` files.\n\nApplying fixes to `__init__.py` files is currently in preview. The fix offered depends on the\ntype of the unused import. Ruff will suggest a safe fix to export first-party imports with\neither a redundant alias or, if already present in the file, an `__all__` entry. If multiple\n`__all__` declarations are present, Ruff will not offer a fix. Ruff will suggest an unsafe fix\nto remove third-party and standard library imports -- the fix is unsafe because the module's\ninterface changes.\n\nSee [this FAQ section](https://docs.astral.sh/ruff/faq/#how-does-ruff-determine-which-of-my-imports-are-first-party-third-party-etc)\nfor more details on how Ruff\ndetermines whether an import is first or third-party.\n\n## Example\n\n```python\nimport numpy as np # unused import\n\n\ndef area(radius):\n return 3.14 * radius**2\n```\n\nUse instead:\n\n```python\ndef area(radius):\n return 3.14 * radius**2\n```\n\nTo check the availability of a module, use `importlib.util.find_spec`:\n\n```python\nfrom importlib.util import find_spec\n\nif find_spec(\"numpy\") is not None:\n print(\"numpy is installed\")\nelse:\n print(\"numpy is not installed\")\n```\n\n## Options\n- `lint.ignore-init-module-imports`\n- `lint.pyflakes.allowed-unused-imports`\n\n## References\n- [Python documentation: `import`](https://docs.python.org/3/reference/simple_stmts.html#the-import-statement)\n- [Python documentation: `importlib.util.find_spec`](https://docs.python.org/3/library/importlib.html#importlib.util.find_spec)\n- [Typing documentation: interface conventions](https://typing.python.org/en/latest/spec/distributing.html#library-interface-public-and-private-symbols)\n"
|
||||
},
|
||||
"help": {
|
||||
"text": "`{name}` imported but unused; consider using `importlib.util.find_spec` to test for availability"
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
- check
|
||||
- "--no-cache"
|
||||
- "--output-format"
|
||||
- concise
|
||||
- "--select"
|
||||
- F401
|
||||
- "--fix"
|
||||
- "--show-fixes"
|
||||
- input.py
|
||||
---
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
Fixed 1 error:
|
||||
- input.py:
|
||||
1 × F401 (unused-import)
|
||||
|
||||
Found 1 error (1 fixed, 0 remaining).
|
||||
|
||||
----- stderr -----
|
||||
@@ -1,26 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
- check
|
||||
- "--no-cache"
|
||||
- "--output-format"
|
||||
- full
|
||||
- "--select"
|
||||
- F401
|
||||
- "--fix"
|
||||
- "--show-fixes"
|
||||
- input.py
|
||||
---
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
Fixed 1 error:
|
||||
- input.py:
|
||||
1 × F401 (unused-import)
|
||||
|
||||
Found 1 error (1 fixed, 0 remaining).
|
||||
|
||||
----- stderr -----
|
||||
@@ -1,26 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/tests/lint.rs
|
||||
info:
|
||||
program: ruff
|
||||
args:
|
||||
- check
|
||||
- "--no-cache"
|
||||
- "--output-format"
|
||||
- grouped
|
||||
- "--select"
|
||||
- F401
|
||||
- "--fix"
|
||||
- "--show-fixes"
|
||||
- input.py
|
||||
---
|
||||
success: true
|
||||
exit_code: 0
|
||||
----- stdout -----
|
||||
|
||||
Fixed 1 error:
|
||||
- input.py:
|
||||
1 × F401 (unused-import)
|
||||
|
||||
Found 1 error (1 fixed, 0 remaining).
|
||||
|
||||
----- stderr -----
|
||||
@@ -371,7 +371,6 @@ linter.pylint.max_branches = 12
|
||||
linter.pylint.max_statements = 50
|
||||
linter.pylint.max_public_methods = 20
|
||||
linter.pylint.max_locals = 15
|
||||
linter.pylint.max_nested_blocks = 5
|
||||
linter.pyupgrade.keep_runtime_typing = false
|
||||
linter.ruff.parenthesize_tuple_in_subscript = false
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ pub(crate) struct DisplayList<'a> {
|
||||
pub(crate) stylesheet: &'a Stylesheet,
|
||||
pub(crate) anonymized_line_numbers: bool,
|
||||
pub(crate) cut_indicator: &'static str,
|
||||
pub(crate) lineno_offset: usize,
|
||||
}
|
||||
|
||||
impl PartialEq for DisplayList<'_> {
|
||||
@@ -82,14 +81,13 @@ impl Display for DisplayList<'_> {
|
||||
_ => max,
|
||||
})
|
||||
});
|
||||
let lineno_width = self.lineno_offset
|
||||
+ if lineno_width == 0 {
|
||||
lineno_width
|
||||
} else if self.anonymized_line_numbers {
|
||||
ANONYMIZED_LINE_NUM.len()
|
||||
} else {
|
||||
((lineno_width as f64).log10().floor() as usize) + 1
|
||||
};
|
||||
let lineno_width = if lineno_width == 0 {
|
||||
lineno_width
|
||||
} else if self.anonymized_line_numbers {
|
||||
ANONYMIZED_LINE_NUM.len()
|
||||
} else {
|
||||
((lineno_width as f64).log10().floor() as usize) + 1
|
||||
};
|
||||
|
||||
let multiline_depth = self.body.iter().fold(0, |max, set| {
|
||||
set.display_lines.iter().fold(max, |max2, line| match line {
|
||||
@@ -126,7 +124,6 @@ impl<'a> DisplayList<'a> {
|
||||
term_width: usize,
|
||||
cut_indicator: &'static str,
|
||||
) -> DisplayList<'a> {
|
||||
let lineno_offset = message.lineno_offset;
|
||||
let body = format_message(
|
||||
message,
|
||||
term_width,
|
||||
@@ -140,7 +137,6 @@ impl<'a> DisplayList<'a> {
|
||||
stylesheet,
|
||||
anonymized_line_numbers,
|
||||
cut_indicator,
|
||||
lineno_offset,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1092,7 +1088,6 @@ fn format_message<'m>(
|
||||
footer,
|
||||
snippets,
|
||||
is_fixable,
|
||||
lineno_offset: _,
|
||||
} = message;
|
||||
|
||||
let mut sets = vec![];
|
||||
|
||||
@@ -23,7 +23,6 @@ pub struct Message<'a> {
|
||||
pub(crate) snippets: Vec<Snippet<'a>>,
|
||||
pub(crate) footer: Vec<Message<'a>>,
|
||||
pub(crate) is_fixable: bool,
|
||||
pub(crate) lineno_offset: usize,
|
||||
}
|
||||
|
||||
impl<'a> Message<'a> {
|
||||
@@ -60,16 +59,6 @@ impl<'a> Message<'a> {
|
||||
self.is_fixable = yes;
|
||||
self
|
||||
}
|
||||
|
||||
/// Add an offset used for aligning the header sigil (`-->`) with the line number separators.
|
||||
///
|
||||
/// For normal diagnostics this is computed automatically based on the lines to be rendered.
|
||||
/// This is intended only for use in the formatter, where we don't render a snippet directly but
|
||||
/// still want the header to align with the diff.
|
||||
pub fn lineno_offset(mut self, offset: usize) -> Self {
|
||||
self.lineno_offset = offset;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Structure containing the slice of text to be annotated and
|
||||
@@ -155,7 +144,7 @@ impl<'a> Annotation<'a> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn hide_snippet(mut self, yes: bool) -> Self {
|
||||
pub fn is_file_level(mut self, yes: bool) -> Self {
|
||||
self.is_file_level = yes;
|
||||
self
|
||||
}
|
||||
@@ -184,7 +173,6 @@ impl Level {
|
||||
snippets: vec![],
|
||||
footer: vec![],
|
||||
is_fixable: false,
|
||||
lineno_offset: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<svg width="740px" height="128px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
.bg { background: #000000 }
|
||||
.fg-bright-blue { fill: #5555FF }
|
||||
.fg-bright-red { fill: #FF5555 }
|
||||
.container {
|
||||
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@@ -1,7 +1,7 @@
|
||||
<svg width="740px" height="128px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
.bg { background: #000000 }
|
||||
.fg-bright-blue { fill: #5555FF }
|
||||
.fg-bright-red { fill: #FF5555 }
|
||||
.container {
|
||||
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
@@ -1,7 +1,7 @@
|
||||
<svg width="740px" height="182px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
.bg { background: #000000 }
|
||||
.fg-bright-blue { fill: #5555FF }
|
||||
.fg-bright-red { fill: #FF5555 }
|
||||
.container {
|
||||
|
||||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
@@ -1,7 +1,7 @@
|
||||
<svg width="740px" height="164px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
.bg { background: #000000 }
|
||||
.fg-bright-blue { fill: #5555FF }
|
||||
.fg-bright-red { fill: #FF5555 }
|
||||
.container {
|
||||
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
@@ -1,7 +1,7 @@
|
||||
<svg width="740px" height="128px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
.bg { background: #000000 }
|
||||
.fg-bright-blue { fill: #5555FF }
|
||||
.fg-bright-red { fill: #FF5555 }
|
||||
.container {
|
||||
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@@ -1,7 +1,7 @@
|
||||
<svg width="1356px" height="128px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
.bg { background: #000000 }
|
||||
.fg-bright-blue { fill: #5555FF }
|
||||
.fg-bright-red { fill: #FF5555 }
|
||||
.container {
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -1,7 +1,7 @@
|
||||
<svg width="869px" height="236px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
.bg { background: #000000 }
|
||||
.fg-bright-blue { fill: #5555FF }
|
||||
.fg-bright-red { fill: #FF5555 }
|
||||
.fg-yellow { fill: #AA5500 }
|
||||
|
||||
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
@@ -1,7 +1,7 @@
|
||||
<svg width="740px" height="128px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
.bg { background: #000000 }
|
||||
.fg-bright-blue { fill: #5555FF }
|
||||
.fg-bright-red { fill: #FF5555 }
|
||||
.fg-yellow { fill: #AA5500 }
|
||||
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
@@ -1,7 +1,7 @@
|
||||
<svg width="740px" height="128px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
.bg { background: #000000 }
|
||||
.fg-bright-blue { fill: #5555FF }
|
||||
.fg-bright-red { fill: #FF5555 }
|
||||
.container {
|
||||
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
@@ -1,7 +1,7 @@
|
||||
<svg width="740px" height="128px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
.bg { background: #000000 }
|
||||
.fg-bright-blue { fill: #5555FF }
|
||||
.fg-bright-red { fill: #FF5555 }
|
||||
.container {
|
||||
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
@@ -1,7 +1,7 @@
|
||||
<svg width="911px" height="236px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
.bg { background: #000000 }
|
||||
.fg-bright-blue { fill: #5555FF }
|
||||
.fg-bright-red { fill: #FF5555 }
|
||||
.fg-yellow { fill: #AA5500 }
|
||||
|
||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
@@ -1,7 +1,7 @@
|
||||
<svg width="768px" height="290px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
.bg { background: #000000 }
|
||||
.fg-bright-blue { fill: #5555FF }
|
||||
.fg-bright-red { fill: #FF5555 }
|
||||
.container {
|
||||
|
||||
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.9 KiB |
@@ -1,7 +1,7 @@
|
||||
<svg width="740px" height="146px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
.bg { background: #000000 }
|
||||
.fg-bright-blue { fill: #5555FF }
|
||||
.fg-bright-red { fill: #FF5555 }
|
||||
.container {
|
||||
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,7 +1,7 @@
|
||||
<svg width="1196px" height="128px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
.bg { background: #000000 }
|
||||
.fg-bright-blue { fill: #5555FF }
|
||||
.fg-bright-red { fill: #FF5555 }
|
||||
.container {
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -1,7 +1,7 @@
|
||||
<svg width="740px" height="182px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
.bg { background: #000000 }
|
||||
.fg-bright-blue { fill: #5555FF }
|
||||
.fg-bright-red { fill: #FF5555 }
|
||||
.fg-yellow { fill: #AA5500 }
|
||||
|
||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -1,7 +1,7 @@
|
||||
<svg width="740px" height="128px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
.bg { background: #000000 }
|
||||
.fg-bright-blue { fill: #5555FF }
|
||||
.fg-bright-red { fill: #FF5555 }
|
||||
.container {
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -1,7 +1,7 @@
|
||||
<svg width="740px" height="128px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
.bg { background: #000000 }
|
||||
.fg-bright-blue { fill: #5555FF }
|
||||
.fg-bright-red { fill: #FF5555 }
|
||||
.container {
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -1,7 +1,7 @@
|
||||
<svg width="1196px" height="164px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
.bg { background: #000000 }
|
||||
.fg-bright-blue { fill: #5555FF }
|
||||
.fg-bright-red { fill: #FF5555 }
|
||||
.container {
|
||||
|
||||
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
@@ -444,7 +444,7 @@ fn benchmark_complex_constrained_attributes_2(criterion: &mut Criterion) {
|
||||
criterion.bench_function("ty_micro[complex_constrained_attributes_2]", |b| {
|
||||
b.iter_batched_ref(
|
||||
|| {
|
||||
// This is similar to the case above, but now the attributes are actually defined.
|
||||
// This is is similar to the case above, but now the attributes are actually defined.
|
||||
// https://github.com/astral-sh/ty/issues/711
|
||||
setup_micro_case(
|
||||
r#"
|
||||
|
||||
@@ -117,7 +117,7 @@ static COLOUR_SCIENCE: std::sync::LazyLock<Benchmark<'static>> = std::sync::Lazy
|
||||
max_dep_date: "2025-06-17",
|
||||
python_version: PythonVersion::PY310,
|
||||
},
|
||||
500,
|
||||
477,
|
||||
)
|
||||
});
|
||||
|
||||
@@ -232,7 +232,7 @@ static STATIC_FRAME: std::sync::LazyLock<Benchmark<'static>> = std::sync::LazyLo
|
||||
max_dep_date: "2025-08-09",
|
||||
python_version: PythonVersion::PY311,
|
||||
},
|
||||
600,
|
||||
500,
|
||||
)
|
||||
});
|
||||
|
||||
|
||||
@@ -69,7 +69,6 @@ impl Diagnostic {
|
||||
parent: None,
|
||||
noqa_offset: None,
|
||||
secondary_code: None,
|
||||
header_offset: 0,
|
||||
});
|
||||
Diagnostic { inner }
|
||||
}
|
||||
@@ -433,23 +432,14 @@ impl Diagnostic {
|
||||
|
||||
/// Returns the URL for the rule documentation, if it exists.
|
||||
pub fn to_ruff_url(&self) -> Option<String> {
|
||||
match self.id() {
|
||||
DiagnosticId::Panic
|
||||
| DiagnosticId::Io
|
||||
| DiagnosticId::InvalidSyntax
|
||||
| DiagnosticId::RevealedType
|
||||
| DiagnosticId::UnknownRule
|
||||
| DiagnosticId::InvalidGlob
|
||||
| DiagnosticId::EmptyInclude
|
||||
| DiagnosticId::UnnecessaryOverridesSection
|
||||
| DiagnosticId::UselessOverridesSection
|
||||
| DiagnosticId::DeprecatedSetting
|
||||
| DiagnosticId::Unformatted
|
||||
| DiagnosticId::InvalidCliOption
|
||||
| DiagnosticId::InternalError => None,
|
||||
DiagnosticId::Lint(lint_name) => {
|
||||
Some(format!("{}/rules/{lint_name}", env!("CARGO_PKG_HOMEPAGE")))
|
||||
}
|
||||
if self.is_invalid_syntax() {
|
||||
None
|
||||
} else {
|
||||
Some(format!(
|
||||
"{}/rules/{}",
|
||||
env!("CARGO_PKG_HOMEPAGE"),
|
||||
self.name()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -522,11 +512,6 @@ impl Diagnostic {
|
||||
|
||||
a.cmp(&b)
|
||||
}
|
||||
|
||||
/// Add an offset for aligning the header sigil with the line number separators in a diff.
|
||||
pub fn set_header_offset(&mut self, offset: usize) {
|
||||
Arc::make_mut(&mut self.inner).header_offset = offset;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash, get_size2::GetSize)]
|
||||
@@ -540,7 +525,6 @@ struct DiagnosticInner {
|
||||
parent: Option<TextSize>,
|
||||
noqa_offset: Option<TextSize>,
|
||||
secondary_code: Option<SecondaryCode>,
|
||||
header_offset: usize,
|
||||
}
|
||||
|
||||
struct RenderingSortKey<'a> {
|
||||
@@ -758,11 +742,11 @@ pub struct Annotation {
|
||||
is_primary: bool,
|
||||
/// The diagnostic tags associated with this annotation.
|
||||
tags: Vec<DiagnosticTag>,
|
||||
/// Whether the snippet for this annotation should be hidden.
|
||||
/// Whether this annotation is a file-level or full-file annotation.
|
||||
///
|
||||
/// When set, rendering will only include the file's name and (optional) range. Everything else
|
||||
/// is omitted, including any file snippet or message.
|
||||
hide_snippet: bool,
|
||||
is_file_level: bool,
|
||||
}
|
||||
|
||||
impl Annotation {
|
||||
@@ -781,7 +765,7 @@ impl Annotation {
|
||||
message: None,
|
||||
is_primary: true,
|
||||
tags: Vec::new(),
|
||||
hide_snippet: false,
|
||||
is_file_level: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -798,7 +782,7 @@ impl Annotation {
|
||||
message: None,
|
||||
is_primary: false,
|
||||
tags: Vec::new(),
|
||||
hide_snippet: false,
|
||||
is_file_level: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -865,20 +849,19 @@ impl Annotation {
|
||||
self.tags.push(tag);
|
||||
}
|
||||
|
||||
/// Set whether or not the snippet on this annotation should be suppressed when rendering.
|
||||
/// Set whether or not this annotation is file-level.
|
||||
///
|
||||
/// Such annotations are only rendered with their file name and range, if available. This is
|
||||
/// intended for backwards compatibility with Ruff diagnostics, which historically used
|
||||
/// File-level annotations are only rendered with their file name and range, if available. This
|
||||
/// is intended for backwards compatibility with Ruff diagnostics, which historically used
|
||||
/// `TextRange::default` to indicate a file-level diagnostic. In the new diagnostic model, a
|
||||
/// [`Span`] with a range of `None` should be used instead, as mentioned in the `Span`
|
||||
/// documentation.
|
||||
///
|
||||
/// TODO(brent) update this usage in Ruff and remove `is_file_level` entirely. See
|
||||
/// <https://github.com/astral-sh/ruff/issues/19688>, especially my first comment, for more
|
||||
/// details. As of 2025-09-26 we also use this to suppress snippet rendering for formatter
|
||||
/// diagnostics, which also need to have a range, so we probably can't eliminate this entirely.
|
||||
pub fn hide_snippet(&mut self, yes: bool) {
|
||||
self.hide_snippet = yes;
|
||||
/// details.
|
||||
pub fn set_file_level(&mut self, yes: bool) {
|
||||
self.is_file_level = yes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1033,17 +1016,6 @@ pub enum DiagnosticId {
|
||||
|
||||
/// Use of a deprecated setting.
|
||||
DeprecatedSetting,
|
||||
|
||||
/// The code needs to be formatted.
|
||||
Unformatted,
|
||||
|
||||
/// Use of an invalid command-line option.
|
||||
InvalidCliOption,
|
||||
|
||||
/// An internal assumption was violated.
|
||||
///
|
||||
/// This indicates a bug in the program rather than a user error.
|
||||
InternalError,
|
||||
}
|
||||
|
||||
impl DiagnosticId {
|
||||
@@ -1083,9 +1055,6 @@ impl DiagnosticId {
|
||||
DiagnosticId::UnnecessaryOverridesSection => "unnecessary-overrides-section",
|
||||
DiagnosticId::UselessOverridesSection => "useless-overrides-section",
|
||||
DiagnosticId::DeprecatedSetting => "deprecated-setting",
|
||||
DiagnosticId::Unformatted => "unformatted",
|
||||
DiagnosticId::InvalidCliOption => "invalid-cli-option",
|
||||
DiagnosticId::InternalError => "internal-error",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1384,7 +1353,7 @@ impl DisplayDiagnosticConfig {
|
||||
}
|
||||
|
||||
/// Whether to show a fix's availability or not.
|
||||
pub fn with_show_fix_status(self, yes: bool) -> DisplayDiagnosticConfig {
|
||||
pub fn show_fix_status(self, yes: bool) -> DisplayDiagnosticConfig {
|
||||
DisplayDiagnosticConfig {
|
||||
show_fix_status: yes,
|
||||
..self
|
||||
@@ -1405,20 +1374,12 @@ impl DisplayDiagnosticConfig {
|
||||
/// availability for unsafe or display-only fixes.
|
||||
///
|
||||
/// Note that this option is currently ignored when `hide_severity` is false.
|
||||
pub fn with_fix_applicability(self, applicability: Applicability) -> DisplayDiagnosticConfig {
|
||||
pub fn fix_applicability(self, applicability: Applicability) -> DisplayDiagnosticConfig {
|
||||
DisplayDiagnosticConfig {
|
||||
fix_applicability: applicability,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
pub fn show_fix_status(&self) -> bool {
|
||||
self.show_fix_status
|
||||
}
|
||||
|
||||
pub fn fix_applicability(&self) -> Applicability {
|
||||
self.fix_applicability
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for DisplayDiagnosticConfig {
|
||||
|
||||
@@ -15,6 +15,7 @@ use crate::{
|
||||
Db,
|
||||
files::File,
|
||||
source::{SourceText, line_index, source_text},
|
||||
system::SystemPath,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -208,7 +209,6 @@ struct ResolvedDiagnostic<'a> {
|
||||
message: String,
|
||||
annotations: Vec<ResolvedAnnotation<'a>>,
|
||||
is_fixable: bool,
|
||||
header_offset: usize,
|
||||
}
|
||||
|
||||
impl<'a> ResolvedDiagnostic<'a> {
|
||||
@@ -259,8 +259,7 @@ impl<'a> ResolvedDiagnostic<'a> {
|
||||
id,
|
||||
message: diag.inner.message.as_str().to_string(),
|
||||
annotations,
|
||||
is_fixable: config.show_fix_status && diag.has_applicable_fix(config),
|
||||
header_offset: diag.inner.header_offset,
|
||||
is_fixable: diag.has_applicable_fix(config),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,7 +289,6 @@ impl<'a> ResolvedDiagnostic<'a> {
|
||||
message: diag.inner.message.as_str().to_string(),
|
||||
annotations,
|
||||
is_fixable: false,
|
||||
header_offset: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,7 +386,6 @@ impl<'a> ResolvedDiagnostic<'a> {
|
||||
message: &self.message,
|
||||
snippets_by_input,
|
||||
is_fixable: self.is_fixable,
|
||||
header_offset: self.header_offset,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -408,7 +405,7 @@ struct ResolvedAnnotation<'a> {
|
||||
line_end: OneIndexed,
|
||||
message: Option<&'a str>,
|
||||
is_primary: bool,
|
||||
hide_snippet: bool,
|
||||
is_file_level: bool,
|
||||
notebook_index: Option<NotebookIndex>,
|
||||
}
|
||||
|
||||
@@ -456,7 +453,7 @@ impl<'a> ResolvedAnnotation<'a> {
|
||||
line_end,
|
||||
message: ann.get_message(),
|
||||
is_primary: ann.is_primary,
|
||||
hide_snippet: ann.hide_snippet,
|
||||
is_file_level: ann.is_file_level,
|
||||
notebook_index: resolver.notebook_index(&ann.span.file),
|
||||
})
|
||||
}
|
||||
@@ -496,11 +493,6 @@ struct RenderableDiagnostic<'r> {
|
||||
///
|
||||
/// This is rendered as a `[*]` indicator after the diagnostic ID.
|
||||
is_fixable: bool,
|
||||
/// Offset to align the header sigil (`-->`) with the subsequent line number separators.
|
||||
///
|
||||
/// This is only needed for formatter diagnostics where we don't render a snippet via
|
||||
/// `annotate-snippets` and thus the alignment isn't computed automatically.
|
||||
header_offset: usize,
|
||||
}
|
||||
|
||||
impl RenderableDiagnostic<'_> {
|
||||
@@ -513,11 +505,7 @@ impl RenderableDiagnostic<'_> {
|
||||
.iter()
|
||||
.map(|snippet| snippet.to_annotate(path))
|
||||
});
|
||||
let mut message = self
|
||||
.level
|
||||
.title(self.message)
|
||||
.is_fixable(self.is_fixable)
|
||||
.lineno_offset(self.header_offset);
|
||||
let mut message = self.level.title(self.message).is_fixable(self.is_fixable);
|
||||
if let Some(id) = self.id {
|
||||
message = message.id(id);
|
||||
}
|
||||
@@ -722,8 +710,8 @@ struct RenderableAnnotation<'r> {
|
||||
message: Option<&'r str>,
|
||||
/// Whether this annotation is considered "primary" or not.
|
||||
is_primary: bool,
|
||||
/// Whether the snippet for this annotation should be hidden instead of rendered.
|
||||
hide_snippet: bool,
|
||||
/// Whether this annotation applies to an entire file, rather than a snippet within it.
|
||||
is_file_level: bool,
|
||||
}
|
||||
|
||||
impl<'r> RenderableAnnotation<'r> {
|
||||
@@ -745,7 +733,7 @@ impl<'r> RenderableAnnotation<'r> {
|
||||
range,
|
||||
message: ann.message,
|
||||
is_primary: ann.is_primary,
|
||||
hide_snippet: ann.hide_snippet,
|
||||
is_file_level: ann.is_file_level,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -771,7 +759,7 @@ impl<'r> RenderableAnnotation<'r> {
|
||||
if let Some(message) = self.message {
|
||||
ann = ann.label(message);
|
||||
}
|
||||
ann.hide_snippet(self.hide_snippet)
|
||||
ann.is_file_level(self.is_file_level)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -812,7 +800,7 @@ where
|
||||
T: Db,
|
||||
{
|
||||
fn path(&self, file: File) -> &str {
|
||||
file.path(self).as_str()
|
||||
relativize_path(self.system().current_directory(), file.path(self).as_str())
|
||||
}
|
||||
|
||||
fn input(&self, file: File) -> Input {
|
||||
@@ -848,7 +836,7 @@ where
|
||||
|
||||
impl FileResolver for &dyn Db {
|
||||
fn path(&self, file: File) -> &str {
|
||||
file.path(*self).as_str()
|
||||
relativize_path(self.system().current_directory(), file.path(*self).as_str())
|
||||
}
|
||||
|
||||
fn input(&self, file: File) -> Input {
|
||||
@@ -967,6 +955,14 @@ fn context_after(
|
||||
line
|
||||
}
|
||||
|
||||
/// Convert an absolute path to be relative to the current working directory.
|
||||
fn relativize_path<'p>(cwd: &SystemPath, path: &'p str) -> &'p str {
|
||||
if let Ok(path) = SystemPath::new(path).strip_prefix(cwd) {
|
||||
return path.as_str();
|
||||
}
|
||||
path
|
||||
}
|
||||
|
||||
/// Given some source code and annotation ranges, this routine replaces
|
||||
/// unprintable characters with printable representations of them.
|
||||
///
|
||||
@@ -2631,7 +2627,7 @@ watermelon
|
||||
/// Show fix availability when rendering.
|
||||
pub(super) fn show_fix_status(&mut self, yes: bool) {
|
||||
let mut config = std::mem::take(&mut self.config);
|
||||
config = config.with_show_fix_status(yes);
|
||||
config = config.show_fix_status(yes);
|
||||
self.config = config;
|
||||
}
|
||||
|
||||
@@ -2645,7 +2641,7 @@ watermelon
|
||||
/// The lowest fix applicability to show when rendering.
|
||||
pub(super) fn fix_applicability(&mut self, applicability: Applicability) {
|
||||
let mut config = std::mem::take(&mut self.config);
|
||||
config = config.with_fix_applicability(applicability);
|
||||
config = config.fix_applicability(applicability);
|
||||
self.config = config;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,11 +58,10 @@ impl<'a> FullRenderer<'a> {
|
||||
writeln!(f, "{}", renderer.render(diag.to_annotate()))?;
|
||||
}
|
||||
|
||||
if self.config.show_fix_diff
|
||||
&& diag.has_applicable_fix(self.config)
|
||||
&& let Some(diff) = Diff::from_diagnostic(diag, &stylesheet, self.resolver)
|
||||
{
|
||||
write!(f, "{diff}")?;
|
||||
if self.config.show_fix_diff && diag.has_applicable_fix(self.config) {
|
||||
if let Some(diff) = Diff::from_diagnostic(diag, &stylesheet, self.resolver) {
|
||||
write!(f, "{diff}")?;
|
||||
}
|
||||
}
|
||||
|
||||
writeln!(f)?;
|
||||
@@ -366,7 +365,6 @@ mod tests {
|
||||
fn hide_severity_output() {
|
||||
let (mut env, diagnostics) = create_diagnostics(DiagnosticFormat::Full);
|
||||
env.hide_severity(true);
|
||||
env.show_fix_status(true);
|
||||
env.fix_applicability(Applicability::DisplayOnly);
|
||||
|
||||
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @r#"
|
||||
@@ -573,7 +571,7 @@ print()
|
||||
let mut diagnostic = env.err().build();
|
||||
let span = env.path("example.py").with_range(TextRange::default());
|
||||
let mut annotation = Annotation::primary(span);
|
||||
annotation.hide_snippet(true);
|
||||
annotation.set_file_level(true);
|
||||
diagnostic.annotate(annotation);
|
||||
|
||||
insta::assert_snapshot!(env.render(&diagnostic), @r"
|
||||
@@ -585,8 +583,7 @@ print()
|
||||
/// Check that ranges in notebooks are remapped relative to the cells.
|
||||
#[test]
|
||||
fn notebook_output() {
|
||||
let (mut env, diagnostics) = create_notebook_diagnostics(DiagnosticFormat::Full);
|
||||
env.show_fix_status(true);
|
||||
let (env, diagnostics) = create_notebook_diagnostics(DiagnosticFormat::Full);
|
||||
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @r"
|
||||
error[unused-import][*]: `os` imported but unused
|
||||
--> notebook.ipynb:cell 1:2:8
|
||||
@@ -700,7 +697,6 @@ print()
|
||||
fn notebook_output_with_diff() {
|
||||
let (mut env, diagnostics) = create_notebook_diagnostics(DiagnosticFormat::Full);
|
||||
env.show_fix_diff(true);
|
||||
env.show_fix_status(true);
|
||||
env.fix_applicability(Applicability::DisplayOnly);
|
||||
|
||||
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @r"
|
||||
@@ -755,7 +751,6 @@ print()
|
||||
fn notebook_output_with_diff_spanning_cells() {
|
||||
let (mut env, mut diagnostics) = create_notebook_diagnostics(DiagnosticFormat::Full);
|
||||
env.show_fix_diff(true);
|
||||
env.show_fix_status(true);
|
||||
env.fix_applicability(Applicability::DisplayOnly);
|
||||
|
||||
// Move all of the edits from the later diagnostics to the first diagnostic to simulate a
|
||||
@@ -932,7 +927,6 @@ line 10
|
||||
env.add("example.py", contents);
|
||||
env.format(DiagnosticFormat::Full);
|
||||
env.show_fix_diff(true);
|
||||
env.show_fix_status(true);
|
||||
env.fix_applicability(Applicability::DisplayOnly);
|
||||
|
||||
let mut diagnostic = env.err().primary("example.py", "3", "3", "label").build();
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
source: crates/ruff_db/src/diagnostic/render/azure.rs
|
||||
expression: env.render_diagnostics(&diagnostics)
|
||||
---
|
||||
##vso[task.logissue type=error;sourcepath=/fib.py;linenumber=1;columnnumber=8;code=F401;]`os` imported but unused
|
||||
##vso[task.logissue type=error;sourcepath=/fib.py;linenumber=6;columnnumber=5;code=F841;]Local variable `x` is assigned to but never used
|
||||
##vso[task.logissue type=error;sourcepath=/undef.py;linenumber=1;columnnumber=4;code=F821;]Undefined name `a`
|
||||
##vso[task.logissue type=error;sourcepath=fib.py;linenumber=1;columnnumber=8;code=F401;]`os` imported but unused
|
||||
##vso[task.logissue type=error;sourcepath=fib.py;linenumber=6;columnnumber=5;code=F841;]Local variable `x` is assigned to but never used
|
||||
##vso[task.logissue type=error;sourcepath=undef.py;linenumber=1;columnnumber=4;code=F821;]Undefined name `a`
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
source: crates/ruff_db/src/diagnostic/render/azure.rs
|
||||
expression: env.render_diagnostics(&diagnostics)
|
||||
---
|
||||
##vso[task.logissue type=error;sourcepath=/syntax_errors.py;linenumber=1;columnnumber=15;code=invalid-syntax;]Expected one or more symbol names after import
|
||||
##vso[task.logissue type=error;sourcepath=/syntax_errors.py;linenumber=3;columnnumber=12;code=invalid-syntax;]Expected ')', found newline
|
||||
##vso[task.logissue type=error;sourcepath=syntax_errors.py;linenumber=1;columnnumber=15;code=invalid-syntax;]Expected one or more symbol names after import
|
||||
##vso[task.logissue type=error;sourcepath=syntax_errors.py;linenumber=3;columnnumber=12;code=invalid-syntax;]Expected ')', found newline
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
source: crates/ruff_db/src/diagnostic/render/github.rs
|
||||
expression: env.render_diagnostics(&diagnostics)
|
||||
---
|
||||
::error title=ty (F401),file=/fib.py,line=1,col=8,endLine=1,endColumn=10::fib.py:1:8: F401 `os` imported but unused
|
||||
::error title=ty (F841),file=/fib.py,line=6,col=5,endLine=6,endColumn=6::fib.py:6:5: F841 Local variable `x` is assigned to but never used
|
||||
::error title=ty (F821),file=/undef.py,line=1,col=4,endLine=1,endColumn=5::undef.py:1:4: F821 Undefined name `a`
|
||||
::error title=ty (F401),file=fib.py,line=1,col=8,endLine=1,endColumn=10::fib.py:1:8: F401 `os` imported but unused
|
||||
::error title=ty (F841),file=fib.py,line=6,col=5,endLine=6,endColumn=6::fib.py:6:5: F841 Local variable `x` is assigned to but never used
|
||||
::error title=ty (F821),file=undef.py,line=1,col=4,endLine=1,endColumn=5::undef.py:1:4: F821 Undefined name `a`
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
source: crates/ruff_db/src/diagnostic/render/github.rs
|
||||
expression: env.render_diagnostics(&diagnostics)
|
||||
---
|
||||
::error title=ty (invalid-syntax),file=/syntax_errors.py,line=1,col=15,endLine=2,endColumn=1::syntax_errors.py:1:15: invalid-syntax: Expected one or more symbol names after import
|
||||
::error title=ty (invalid-syntax),file=/syntax_errors.py,line=3,col=12,endLine=4,endColumn=1::syntax_errors.py:3:12: invalid-syntax: Expected ')', found newline
|
||||
::error title=ty (invalid-syntax),file=syntax_errors.py,line=1,col=15,endLine=2,endColumn=1::syntax_errors.py:1:15: invalid-syntax: Expected one or more symbol names after import
|
||||
::error title=ty (invalid-syntax),file=syntax_errors.py,line=3,col=12,endLine=4,endColumn=1::syntax_errors.py:3:12: invalid-syntax: Expected ')', found newline
|
||||
|
||||
@@ -10,7 +10,7 @@ expression: env.render_diagnostics(&diagnostics)
|
||||
"column": 10,
|
||||
"row": 2
|
||||
},
|
||||
"filename": "/notebook.ipynb",
|
||||
"filename": "notebook.ipynb",
|
||||
"fix": {
|
||||
"applicability": "safe",
|
||||
"edits": [
|
||||
@@ -43,7 +43,7 @@ expression: env.render_diagnostics(&diagnostics)
|
||||
"column": 12,
|
||||
"row": 2
|
||||
},
|
||||
"filename": "/notebook.ipynb",
|
||||
"filename": "notebook.ipynb",
|
||||
"fix": {
|
||||
"applicability": "safe",
|
||||
"edits": [
|
||||
@@ -76,7 +76,7 @@ expression: env.render_diagnostics(&diagnostics)
|
||||
"column": 6,
|
||||
"row": 4
|
||||
},
|
||||
"filename": "/notebook.ipynb",
|
||||
"filename": "notebook.ipynb",
|
||||
"fix": {
|
||||
"applicability": "unsafe",
|
||||
"edits": [
|
||||
|
||||
@@ -10,7 +10,7 @@ expression: env.render_diagnostics(&diagnostics)
|
||||
"column": 10,
|
||||
"row": 1
|
||||
},
|
||||
"filename": "/fib.py",
|
||||
"filename": "fib.py",
|
||||
"fix": {
|
||||
"applicability": "unsafe",
|
||||
"edits": [
|
||||
@@ -43,7 +43,7 @@ expression: env.render_diagnostics(&diagnostics)
|
||||
"column": 6,
|
||||
"row": 6
|
||||
},
|
||||
"filename": "/fib.py",
|
||||
"filename": "fib.py",
|
||||
"fix": {
|
||||
"applicability": "unsafe",
|
||||
"edits": [
|
||||
@@ -76,7 +76,7 @@ expression: env.render_diagnostics(&diagnostics)
|
||||
"column": 5,
|
||||
"row": 1
|
||||
},
|
||||
"filename": "/undef.py",
|
||||
"filename": "undef.py",
|
||||
"fix": null,
|
||||
"location": {
|
||||
"column": 4,
|
||||
|
||||
@@ -10,7 +10,7 @@ expression: env.render_diagnostics(&diagnostics)
|
||||
"column": 1,
|
||||
"row": 2
|
||||
},
|
||||
"filename": "/syntax_errors.py",
|
||||
"filename": "syntax_errors.py",
|
||||
"fix": null,
|
||||
"location": {
|
||||
"column": 15,
|
||||
@@ -27,7 +27,7 @@ expression: env.render_diagnostics(&diagnostics)
|
||||
"column": 1,
|
||||
"row": 4
|
||||
},
|
||||
"filename": "/syntax_errors.py",
|
||||
"filename": "syntax_errors.py",
|
||||
"fix": null,
|
||||
"location": {
|
||||
"column": 12,
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
source: crates/ruff_db/src/diagnostic/render/json_lines.rs
|
||||
expression: env.render_diagnostics(&diagnostics)
|
||||
---
|
||||
{"cell":1,"code":"F401","end_location":{"column":10,"row":2},"filename":"/notebook.ipynb","fix":{"applicability":"safe","edits":[{"content":"","end_location":{"column":10,"row":2},"location":{"column":1,"row":2}}],"message":"Remove unused import: `os`"},"location":{"column":8,"row":2},"message":"`os` imported but unused","noqa_row":2,"url":"https://docs.astral.sh/ruff/rules/unused-import"}
|
||||
{"cell":2,"code":"F401","end_location":{"column":12,"row":2},"filename":"/notebook.ipynb","fix":{"applicability":"safe","edits":[{"content":"","end_location":{"column":1,"row":3},"location":{"column":1,"row":2}}],"message":"Remove unused import: `math`"},"location":{"column":8,"row":2},"message":"`math` imported but unused","noqa_row":2,"url":"https://docs.astral.sh/ruff/rules/unused-import"}
|
||||
{"cell":3,"code":"F841","end_location":{"column":6,"row":4},"filename":"/notebook.ipynb","fix":{"applicability":"unsafe","edits":[{"content":"","end_location":{"column":1,"row":5},"location":{"column":1,"row":4}}],"message":"Remove assignment to unused variable `x`"},"location":{"column":5,"row":4},"message":"Local variable `x` is assigned to but never used","noqa_row":4,"url":"https://docs.astral.sh/ruff/rules/unused-variable"}
|
||||
{"cell":1,"code":"F401","end_location":{"column":10,"row":2},"filename":"notebook.ipynb","fix":{"applicability":"safe","edits":[{"content":"","end_location":{"column":10,"row":2},"location":{"column":1,"row":2}}],"message":"Remove unused import: `os`"},"location":{"column":8,"row":2},"message":"`os` imported but unused","noqa_row":2,"url":"https://docs.astral.sh/ruff/rules/unused-import"}
|
||||
{"cell":2,"code":"F401","end_location":{"column":12,"row":2},"filename":"notebook.ipynb","fix":{"applicability":"safe","edits":[{"content":"","end_location":{"column":1,"row":3},"location":{"column":1,"row":2}}],"message":"Remove unused import: `math`"},"location":{"column":8,"row":2},"message":"`math` imported but unused","noqa_row":2,"url":"https://docs.astral.sh/ruff/rules/unused-import"}
|
||||
{"cell":3,"code":"F841","end_location":{"column":6,"row":4},"filename":"notebook.ipynb","fix":{"applicability":"unsafe","edits":[{"content":"","end_location":{"column":1,"row":5},"location":{"column":1,"row":4}}],"message":"Remove assignment to unused variable `x`"},"location":{"column":5,"row":4},"message":"Local variable `x` is assigned to but never used","noqa_row":4,"url":"https://docs.astral.sh/ruff/rules/unused-variable"}
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
source: crates/ruff_db/src/diagnostic/render/json_lines.rs
|
||||
expression: env.render_diagnostics(&diagnostics)
|
||||
---
|
||||
{"cell":null,"code":"F401","end_location":{"column":10,"row":1},"filename":"/fib.py","fix":{"applicability":"unsafe","edits":[{"content":"","end_location":{"column":1,"row":2},"location":{"column":1,"row":1}}],"message":"Remove unused import: `os`"},"location":{"column":8,"row":1},"message":"`os` imported but unused","noqa_row":1,"url":"https://docs.astral.sh/ruff/rules/unused-import"}
|
||||
{"cell":null,"code":"F841","end_location":{"column":6,"row":6},"filename":"/fib.py","fix":{"applicability":"unsafe","edits":[{"content":"","end_location":{"column":10,"row":6},"location":{"column":5,"row":6}}],"message":"Remove assignment to unused variable `x`"},"location":{"column":5,"row":6},"message":"Local variable `x` is assigned to but never used","noqa_row":6,"url":"https://docs.astral.sh/ruff/rules/unused-variable"}
|
||||
{"cell":null,"code":"F821","end_location":{"column":5,"row":1},"filename":"/undef.py","fix":null,"location":{"column":4,"row":1},"message":"Undefined name `a`","noqa_row":1,"url":"https://docs.astral.sh/ruff/rules/undefined-name"}
|
||||
{"cell":null,"code":"F401","end_location":{"column":10,"row":1},"filename":"fib.py","fix":{"applicability":"unsafe","edits":[{"content":"","end_location":{"column":1,"row":2},"location":{"column":1,"row":1}}],"message":"Remove unused import: `os`"},"location":{"column":8,"row":1},"message":"`os` imported but unused","noqa_row":1,"url":"https://docs.astral.sh/ruff/rules/unused-import"}
|
||||
{"cell":null,"code":"F841","end_location":{"column":6,"row":6},"filename":"fib.py","fix":{"applicability":"unsafe","edits":[{"content":"","end_location":{"column":10,"row":6},"location":{"column":5,"row":6}}],"message":"Remove assignment to unused variable `x`"},"location":{"column":5,"row":6},"message":"Local variable `x` is assigned to but never used","noqa_row":6,"url":"https://docs.astral.sh/ruff/rules/unused-variable"}
|
||||
{"cell":null,"code":"F821","end_location":{"column":5,"row":1},"filename":"undef.py","fix":null,"location":{"column":4,"row":1},"message":"Undefined name `a`","noqa_row":1,"url":"https://docs.astral.sh/ruff/rules/undefined-name"}
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
source: crates/ruff_db/src/diagnostic/render/json_lines.rs
|
||||
expression: env.render_diagnostics(&diagnostics)
|
||||
---
|
||||
{"cell":null,"code":"invalid-syntax","end_location":{"column":1,"row":2},"filename":"/syntax_errors.py","fix":null,"location":{"column":15,"row":1},"message":"Expected one or more symbol names after import","noqa_row":null,"url":null}
|
||||
{"cell":null,"code":"invalid-syntax","end_location":{"column":1,"row":4},"filename":"/syntax_errors.py","fix":null,"location":{"column":12,"row":3},"message":"Expected ')', found newline","noqa_row":null,"url":null}
|
||||
{"cell":null,"code":"invalid-syntax","end_location":{"column":1,"row":2},"filename":"syntax_errors.py","fix":null,"location":{"column":15,"row":1},"message":"Expected one or more symbol names after import","noqa_row":null,"url":null}
|
||||
{"cell":null,"code":"invalid-syntax","end_location":{"column":1,"row":4},"filename":"syntax_errors.py","fix":null,"location":{"column":12,"row":3},"message":"Expected ')', found newline","noqa_row":null,"url":null}
|
||||
|
||||
@@ -4,16 +4,16 @@ expression: env.render_diagnostics(&diagnostics)
|
||||
---
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuites name="ruff" tests="3" failures="3" errors="0">
|
||||
<testsuite name="/fib.py" tests="2" disabled="0" errors="0" failures="2" package="org.ruff">
|
||||
<testcase name="org.ruff.F401" classname="/fib" line="1" column="8">
|
||||
<testsuite name="fib.py" tests="2" disabled="0" errors="0" failures="2" package="org.ruff">
|
||||
<testcase name="org.ruff.F401" classname="fib" line="1" column="8">
|
||||
<failure message="`os` imported but unused">line 1, col 8, `os` imported but unused</failure>
|
||||
</testcase>
|
||||
<testcase name="org.ruff.F841" classname="/fib" line="6" column="5">
|
||||
<testcase name="org.ruff.F841" classname="fib" line="6" column="5">
|
||||
<failure message="Local variable `x` is assigned to but never used">line 6, col 5, Local variable `x` is assigned to but never used</failure>
|
||||
</testcase>
|
||||
</testsuite>
|
||||
<testsuite name="/undef.py" tests="1" disabled="0" errors="0" failures="1" package="org.ruff">
|
||||
<testcase name="org.ruff.F821" classname="/undef" line="1" column="4">
|
||||
<testsuite name="undef.py" tests="1" disabled="0" errors="0" failures="1" package="org.ruff">
|
||||
<testcase name="org.ruff.F821" classname="undef" line="1" column="4">
|
||||
<failure message="Undefined name `a`">line 1, col 4, Undefined name `a`</failure>
|
||||
</testcase>
|
||||
</testsuite>
|
||||
|
||||
@@ -4,11 +4,11 @@ expression: env.render_diagnostics(&diagnostics)
|
||||
---
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuites name="ruff" tests="2" failures="2" errors="0">
|
||||
<testsuite name="/syntax_errors.py" tests="2" disabled="0" errors="0" failures="2" package="org.ruff">
|
||||
<testcase name="org.ruff.invalid-syntax" classname="/syntax_errors" line="1" column="15">
|
||||
<testsuite name="syntax_errors.py" tests="2" disabled="0" errors="0" failures="2" package="org.ruff">
|
||||
<testcase name="org.ruff.invalid-syntax" classname="syntax_errors" line="1" column="15">
|
||||
<failure message="Expected one or more symbol names after import">line 1, col 15, Expected one or more symbol names after import</failure>
|
||||
</testcase>
|
||||
<testcase name="org.ruff.invalid-syntax" classname="/syntax_errors" line="3" column="12">
|
||||
<testcase name="org.ruff.invalid-syntax" classname="syntax_errors" line="3" column="12">
|
||||
<failure message="Expected ')', found newline">line 3, col 12, Expected ')', found newline</failure>
|
||||
</testcase>
|
||||
</testsuite>
|
||||
|
||||
@@ -10,7 +10,7 @@ expression: env.render_diagnostics(&diagnostics)
|
||||
"value": "F401"
|
||||
},
|
||||
"location": {
|
||||
"path": "/fib.py",
|
||||
"path": "fib.py",
|
||||
"range": {
|
||||
"end": {
|
||||
"column": 10,
|
||||
@@ -45,7 +45,7 @@ expression: env.render_diagnostics(&diagnostics)
|
||||
"value": "F841"
|
||||
},
|
||||
"location": {
|
||||
"path": "/fib.py",
|
||||
"path": "fib.py",
|
||||
"range": {
|
||||
"end": {
|
||||
"column": 6,
|
||||
@@ -80,7 +80,7 @@ expression: env.render_diagnostics(&diagnostics)
|
||||
"value": "F821"
|
||||
},
|
||||
"location": {
|
||||
"path": "/undef.py",
|
||||
"path": "undef.py",
|
||||
"range": {
|
||||
"end": {
|
||||
"column": 5,
|
||||
|
||||
@@ -9,7 +9,7 @@ expression: env.render_diagnostics(&diagnostics)
|
||||
"value": "invalid-syntax"
|
||||
},
|
||||
"location": {
|
||||
"path": "/syntax_errors.py",
|
||||
"path": "syntax_errors.py",
|
||||
"range": {
|
||||
"end": {
|
||||
"column": 1,
|
||||
@@ -28,7 +28,7 @@ expression: env.render_diagnostics(&diagnostics)
|
||||
"value": "invalid-syntax"
|
||||
},
|
||||
"location": {
|
||||
"path": "/syntax_errors.py",
|
||||
"path": "syntax_errors.py",
|
||||
"range": {
|
||||
"end": {
|
||||
"column": 1,
|
||||
|
||||
@@ -95,10 +95,7 @@ impl FileRoots {
|
||||
self.by_path.insert(route.clone(), root).unwrap();
|
||||
|
||||
// Insert a path that matches all subdirectories and files
|
||||
if !route.ends_with("/") {
|
||||
route.push('/');
|
||||
}
|
||||
route.push_str("{*filepath}");
|
||||
route.push_str("/{*filepath}");
|
||||
|
||||
self.by_path.insert(route, root).unwrap();
|
||||
self.roots.push(root);
|
||||
|
||||
@@ -31,29 +31,6 @@ impl Payload {
|
||||
}
|
||||
}
|
||||
|
||||
impl PanicError {
|
||||
pub fn to_diagnostic_message(&self, path: Option<impl std::fmt::Display>) -> String {
|
||||
use std::fmt::Write;
|
||||
|
||||
let mut message = String::new();
|
||||
message.push_str("Panicked");
|
||||
|
||||
if let Some(location) = &self.location {
|
||||
let _ = write!(&mut message, " at {location}");
|
||||
}
|
||||
|
||||
if let Some(path) = path {
|
||||
let _ = write!(&mut message, " when checking `{path}`");
|
||||
}
|
||||
|
||||
if let Some(payload) = self.payload.as_str() {
|
||||
let _ = write!(&mut message, ": `{payload}`");
|
||||
}
|
||||
|
||||
message
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for PanicError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "panicked at")?;
|
||||
|
||||
@@ -504,8 +504,8 @@ impl ToOwned for SystemPath {
|
||||
pub struct SystemPathBuf(#[cfg_attr(feature = "schemars", schemars(with = "String"))] Utf8PathBuf);
|
||||
|
||||
impl get_size2::GetSize for SystemPathBuf {
|
||||
fn get_heap_size_with_tracker<T: get_size2::GetSizeTracker>(&self, tracker: T) -> (usize, T) {
|
||||
(self.0.capacity(), tracker)
|
||||
fn get_heap_size(&self) -> usize {
|
||||
self.0.capacity()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -92,8 +92,8 @@ impl ToOwned for VendoredPath {
|
||||
pub struct VendoredPathBuf(Utf8PathBuf);
|
||||
|
||||
impl get_size2::GetSize for VendoredPathBuf {
|
||||
fn get_heap_size_with_tracker<T: get_size2::GetSizeTracker>(&self, tracker: T) -> (usize, T) {
|
||||
(self.0.capacity(), tracker)
|
||||
fn get_heap_size(&self) -> usize {
|
||||
self.0.capacity()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,12 +38,12 @@ impl std::fmt::Display for FormatError {
|
||||
),
|
||||
FormatError::InvalidDocument(error) => std::write!(
|
||||
fmt,
|
||||
"Invalid document: {error}\n\n This is an internal Ruff error. Please report if necessary."
|
||||
"Invalid document: {error}\n\n This is an internal Rome error. Please report if necessary."
|
||||
),
|
||||
FormatError::PoorLayout => {
|
||||
std::write!(
|
||||
fmt,
|
||||
"Poor layout: The formatter wasn't able to pick a good layout for your document. This is an internal Ruff error. Please report if necessary."
|
||||
"Poor layout: The formatter wasn't able to pick a good layout for your document. This is an internal Rome error. Please report if necessary."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_linter"
|
||||
version = "0.13.3"
|
||||
version = "0.13.0"
|
||||
publish = false
|
||||
authors = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
from collections import UserString as str
|
||||
from typing import override
|
||||
|
||||
def foo():
|
||||
return "!"
|
||||
|
||||
def _foo():
|
||||
return "!"
|
||||
|
||||
class C:
|
||||
@override
|
||||
def __str__(self):
|
||||
return "!"
|
||||
|
||||
@staticmethod
|
||||
def foo():
|
||||
return "!"
|
||||
|
||||
@classmethod
|
||||
def bar(cls):
|
||||
return "!"
|
||||
@@ -1,104 +0,0 @@
|
||||
import os
|
||||
from typing import Optional
|
||||
from pathlib import Path
|
||||
|
||||
## Valid cases:
|
||||
|
||||
def os_path_in_foo():
|
||||
file = "file.txt"
|
||||
|
||||
os.path.abspath(file) # OK
|
||||
os.path.exists(file) # OK
|
||||
os.path.split() # OK
|
||||
|
||||
async def non_io_os_path_methods():
|
||||
os.path.split() # OK
|
||||
os.path.dirname() # OK
|
||||
os.path.basename() # OK
|
||||
os.path.join() # OK
|
||||
|
||||
def pathlib_path_in_foo():
|
||||
path = Path("src/my_text.txt") # OK
|
||||
path.exists() # OK
|
||||
with path.open() as f: # OK
|
||||
...
|
||||
path = Path("src/my_text.txt").open() # OK
|
||||
|
||||
async def non_io_pathlib_path_methods():
|
||||
path = Path("src/my_text.txt")
|
||||
path.is_absolute() # OK
|
||||
path.is_relative_to() # OK
|
||||
path.as_posix() # OK
|
||||
path.relative_to() # OK
|
||||
|
||||
def inline_path_method_call():
|
||||
Path("src/my_text.txt").open() # OK
|
||||
Path("src/my_text.txt").open().flush() # OK
|
||||
with Path("src/my_text.txt").open() as f: # OK
|
||||
...
|
||||
|
||||
async def trio_path_in_foo():
|
||||
from trio import Path
|
||||
|
||||
path = Path("src/my_text.txt") # OK
|
||||
await path.absolute() # OK
|
||||
await path.exists() # OK
|
||||
with Path("src/my_text.txt").open() as f: # OK
|
||||
...
|
||||
|
||||
async def anyio_path_in_foo():
|
||||
from anyio import Path
|
||||
|
||||
path = Path("src/my_text.txt") # OK
|
||||
await path.absolute() # OK
|
||||
await path.exists() # OK
|
||||
with Path("src/my_text.txt").open() as f: # OK
|
||||
...
|
||||
|
||||
async def path_open_in_foo():
|
||||
path = Path("src/my_text.txt") # OK
|
||||
path.open() # OK, covered by ASYNC230
|
||||
|
||||
## Invalid cases:
|
||||
|
||||
async def os_path_in_foo():
|
||||
file = "file.txt"
|
||||
|
||||
os.path.abspath(file) # ASYNC240
|
||||
os.path.exists(file) # ASYNC240
|
||||
|
||||
async def pathlib_path_in_foo():
|
||||
path = Path("src/my_text.txt")
|
||||
path.exists() # ASYNC240
|
||||
|
||||
async def pathlib_path_in_foo():
|
||||
import pathlib
|
||||
|
||||
path = pathlib.Path("src/my_text.txt")
|
||||
path.exists() # ASYNC240
|
||||
|
||||
async def inline_path_method_call():
|
||||
Path("src/my_text.txt").exists() # ASYNC240
|
||||
Path("src/my_text.txt").absolute().exists() # ASYNC240
|
||||
|
||||
async def aliased_path_in_foo():
|
||||
from pathlib import Path as PathAlias
|
||||
|
||||
path = PathAlias("src/my_text.txt")
|
||||
path.exists() # ASYNC240
|
||||
|
||||
global_path = Path("src/my_text.txt")
|
||||
|
||||
async def global_path_in_foo():
|
||||
global_path.exists() # ASYNC240
|
||||
|
||||
async def path_as_simple_parameter_type(path: Path):
|
||||
path.exists() # ASYNC240
|
||||
|
||||
async def path_as_union_parameter_type(path: Path | None):
|
||||
path.exists() # ASYNC240
|
||||
|
||||
async def path_as_optional_parameter_type(path: Optional[Path]):
|
||||
path.exists() # ASYNC240
|
||||
|
||||
|
||||
@@ -52,21 +52,3 @@ class A:
|
||||
|
||||
assert hasattr(A(), "__call__")
|
||||
assert callable(A()) is False
|
||||
|
||||
# https://github.com/astral-sh/ruff/issues/20440
|
||||
def test_invalid_hasattr_calls():
|
||||
hasattr(0, "__call__", 0) # 3 args - invalid
|
||||
hasattr(0, "__call__", x=0) # keyword arg - invalid
|
||||
hasattr(0, "__call__", 0, x=0) # 3 args + keyword - invalid
|
||||
hasattr() # no args - invalid
|
||||
hasattr(0) # 1 arg - invalid
|
||||
hasattr(*(), "__call__", "extra") # unpacking - invalid
|
||||
hasattr(*()) # unpacking - invalid
|
||||
|
||||
def test_invalid_getattr_calls():
|
||||
getattr(0, "__call__", None, "extra") # 4 args - invalid
|
||||
getattr(0, "__call__", default=None) # keyword arg - invalid
|
||||
getattr() # no args - invalid
|
||||
getattr(0) # 1 arg - invalid
|
||||
getattr(*(), "__call__", None, "extra") # unpacking - invalid
|
||||
getattr(*()) # unpacking - invalid
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
from itertools import count, cycle, repeat
|
||||
|
||||
# Errors
|
||||
map(lambda x: x, [1, 2, 3])
|
||||
map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6])
|
||||
map(lambda x, y, z: x + y + z, [1, 2, 3], [4, 5, 6], [7, 8, 9])
|
||||
map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]))
|
||||
map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]), strict=False)
|
||||
map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9], strict=True))
|
||||
|
||||
# Errors (limited iterators).
|
||||
map(lambda x, y: x + y, [1, 2, 3], repeat(1, 1))
|
||||
map(lambda x, y: x + y, [1, 2, 3], repeat(1, times=4))
|
||||
|
||||
import builtins
|
||||
# Still an error even though it uses the qualified name
|
||||
builtins.map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6])
|
||||
|
||||
# OK
|
||||
map(lambda x: x, [1, 2, 3], strict=True)
|
||||
map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], strict=True)
|
||||
map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], strict=False)
|
||||
map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]), strict=True)
|
||||
map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9], strict=True), strict=True)
|
||||
|
||||
# OK (single iterable - no strict required)
|
||||
map(lambda x: x, [1, 2, 3])
|
||||
|
||||
# OK (infinite iterators)
|
||||
map(lambda x, y: x + y, [1, 2, 3], cycle([1, 2, 3]))
|
||||
map(lambda x, y: x + y, [1, 2, 3], repeat(1))
|
||||
map(lambda x, y: x + y, [1, 2, 3], repeat(1, times=None))
|
||||
map(lambda x, y: x + y, [1, 2, 3], count())
|
||||
@@ -19,18 +19,3 @@ class MyClass:
|
||||
|
||||
def attribute_usage(self) -> id:
|
||||
pass
|
||||
|
||||
|
||||
class C:
|
||||
@staticmethod
|
||||
def property(f):
|
||||
return f
|
||||
|
||||
id = 1
|
||||
|
||||
@[property][0]
|
||||
def f(self, x=[id]):
|
||||
return x
|
||||
|
||||
bin = 2
|
||||
foo = [bin]
|
||||
|
||||
@@ -42,6 +42,3 @@ tuple(
|
||||
x for x in [1,2,3]
|
||||
}
|
||||
)
|
||||
|
||||
t9 = tuple([1],)
|
||||
t10 = tuple([1, 2],)
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
import asyncio
|
||||
import collections
|
||||
import contextlib
|
||||
import dataclasses
|
||||
import functools
|
||||
import os
|
||||
import queue
|
||||
import re
|
||||
import shelve
|
||||
import types
|
||||
import weakref
|
||||
from collections.abc import (
|
||||
AsyncGenerator,
|
||||
AsyncIterable,
|
||||
AsyncIterator,
|
||||
Awaitable,
|
||||
ByteString,
|
||||
Callable,
|
||||
Collection,
|
||||
Container,
|
||||
Coroutine,
|
||||
Generator,
|
||||
Iterable,
|
||||
Iterator,
|
||||
ItemsView,
|
||||
KeysView,
|
||||
Mapping,
|
||||
MappingView,
|
||||
MutableMapping,
|
||||
MutableSequence,
|
||||
MutableSet,
|
||||
Reversible,
|
||||
Sequence,
|
||||
Set,
|
||||
ValuesView,
|
||||
)
|
||||
|
||||
|
||||
def takes_preview_generics(
|
||||
future: asyncio.Future[int],
|
||||
task: asyncio.Task[str],
|
||||
deque_object: collections.deque[int],
|
||||
defaultdict_object: collections.defaultdict[str, int],
|
||||
ordered_dict: collections.OrderedDict[str, int],
|
||||
counter_obj: collections.Counter[str],
|
||||
chain_map: collections.ChainMap[str, int],
|
||||
context_manager: contextlib.AbstractContextManager[str],
|
||||
async_context_manager: contextlib.AbstractAsyncContextManager[int],
|
||||
dataclass_field: dataclasses.Field[int],
|
||||
cached_prop: functools.cached_property[int],
|
||||
partial_method: functools.partialmethod[int],
|
||||
path_like: os.PathLike[str],
|
||||
lifo_queue: queue.LifoQueue[int],
|
||||
regular_queue: queue.Queue[int],
|
||||
priority_queue: queue.PriorityQueue[int],
|
||||
simple_queue: queue.SimpleQueue[int],
|
||||
regex_pattern: re.Pattern[str],
|
||||
regex_match: re.Match[str],
|
||||
bsd_db_shelf: shelve.BsdDbShelf[str, int],
|
||||
db_filename_shelf: shelve.DbfilenameShelf[str, int],
|
||||
shelf_obj: shelve.Shelf[str, int],
|
||||
mapping_proxy: types.MappingProxyType[str, int],
|
||||
weak_key_dict: weakref.WeakKeyDictionary[object, int],
|
||||
weak_method: weakref.WeakMethod[int],
|
||||
weak_set: weakref.WeakSet[int],
|
||||
weak_value_dict: weakref.WeakValueDictionary[object, int],
|
||||
awaitable: Awaitable[int],
|
||||
coroutine: Coroutine[int, None, str],
|
||||
async_iterable: AsyncIterable[int],
|
||||
async_iterator: AsyncIterator[int],
|
||||
async_generator: AsyncGenerator[int, None],
|
||||
iterable: Iterable[int],
|
||||
iterator: Iterator[int],
|
||||
generator: Generator[int, None, None],
|
||||
reversible: Reversible[int],
|
||||
container: Container[int],
|
||||
collection: Collection[int],
|
||||
callable_obj: Callable[[int], str],
|
||||
set_obj: Set[int],
|
||||
mutable_set: MutableSet[int],
|
||||
mapping: Mapping[str, int],
|
||||
mutable_mapping: MutableMapping[str, int],
|
||||
sequence: Sequence[int],
|
||||
mutable_sequence: MutableSequence[int],
|
||||
byte_string: ByteString[int],
|
||||
mapping_view: MappingView[str, int],
|
||||
keys_view: KeysView[str],
|
||||
items_view: ItemsView[str, int],
|
||||
values_view: ValuesView[int],
|
||||
) -> None:
|
||||
...
|
||||
@@ -1,18 +0,0 @@
|
||||
from contextlib import nullcontext
|
||||
|
||||
|
||||
def check_isolation_level(mode: int) -> None:
|
||||
"""Will report both, but only fix the first.""" # ERROR PYI021
|
||||
... # ERROR PIE790
|
||||
|
||||
|
||||
with nullcontext():
|
||||
"""Should not report."""
|
||||
# add something thats not a pass here
|
||||
# to not get a remove unnecessary pass err
|
||||
x = 0
|
||||
|
||||
if True:
|
||||
"""Should not report."""
|
||||
# same as above
|
||||
y = 1
|
||||
@@ -170,4 +170,3 @@ print("<\x1c\x1d\x1e\x1f".rsplit(maxsplit=0))
|
||||
# leading/trailing whitespace should not count towards maxsplit
|
||||
" a b c d ".split(maxsplit=2) # ["a", "b", "c d "]
|
||||
" a b c d ".rsplit(maxsplit=2) # [" a b", "c", "d"]
|
||||
"a b".split(maxsplit=1) # ["a", "b"]
|
||||
|
||||
@@ -125,15 +125,3 @@ os.makedirs("name", 0o777, False)
|
||||
os.makedirs(name="name", mode=0o777, exist_ok=False)
|
||||
|
||||
os.makedirs("name", unknown_kwarg=True)
|
||||
|
||||
# https://github.com/astral-sh/ruff/issues/20134
|
||||
os.chmod("pth1_link", mode=0o600, follow_symlinks= False )
|
||||
os.chmod("pth1_link", mode=0o600, follow_symlinks=True)
|
||||
|
||||
# Only diagnostic
|
||||
os.chmod("pth1_file", 0o700, None, True, 1, *[1], **{"x": 1}, foo=1)
|
||||
|
||||
os.rename("pth1_file", "pth1_file1", None, None, 1, *[1], **{"x": 1}, foo=1)
|
||||
os.replace("pth1_file1", "pth1_file", None, None, 1, *[1], **{"x": 1}, foo=1)
|
||||
|
||||
os.path.samefile("pth1_file", "pth1_link", 1, *[1], **{"x": 1}, foo=1)
|
||||
@@ -16,16 +16,8 @@ nok4 = "a".join([a, a, *a]) # Not OK (not a static length)
|
||||
nok5 = "a".join([choice("flarp")]) # Not OK (not a simple call)
|
||||
nok6 = "a".join(x for x in "feefoofum") # Not OK (generator)
|
||||
nok7 = "a".join([f"foo{8}", "bar"]) # Not OK (contains an f-string)
|
||||
# https://github.com/astral-sh/ruff/issues/19887
|
||||
nok8 = '\n'.join([r'line1','line2'])
|
||||
nok9 = '\n'.join([r"raw string", '<""">', "<'''>"]) # Not OK (both triple-quote delimiters appear; should bail)
|
||||
|
||||
|
||||
# Regression test for: https://github.com/astral-sh/ruff/issues/7197
|
||||
def create_file_public_url(url, filename):
|
||||
return''.join([url, filename])
|
||||
|
||||
# Regression test for: https://github.com/astral-sh/ruff/issues/19837
|
||||
nok10 = "".join((foo, '"'))
|
||||
nok11 = ''.join((foo, "'"))
|
||||
nok12 = ''.join([foo, "'", '"'])
|
||||
nok13 = "".join([foo, "'", '"'])
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import concurrent.futures as futures
|
||||
|
||||
1
|
||||
@@ -1,3 +0,0 @@
|
||||
import concurrent.futures as futures
|
||||
|
||||
1
|
||||
@@ -271,35 +271,3 @@ class ChildI9(ParentI):
|
||||
if False: super
|
||||
if False: __class__
|
||||
builtins.super(ChildI9, self).f()
|
||||
|
||||
|
||||
# See: https://github.com/astral-sh/ruff/issues/20422
|
||||
# UP008 should not apply when the class variable is shadowed
|
||||
class A:
|
||||
def f(self):
|
||||
return 1
|
||||
|
||||
class B(A):
|
||||
def f(self):
|
||||
return 2
|
||||
|
||||
class C(B):
|
||||
def f(self):
|
||||
C = B # Local variable C shadows the class name
|
||||
return super(C, self).f() # Should NOT trigger UP008
|
||||
|
||||
|
||||
# See: https://github.com/astral-sh/ruff/issues/20491
|
||||
# UP008 should not apply when __class__ is a local variable
|
||||
class A:
|
||||
def f(self):
|
||||
return 1
|
||||
|
||||
class B(A):
|
||||
def f(self):
|
||||
return 2
|
||||
|
||||
class C(B):
|
||||
def f(self):
|
||||
__class__ = B # Local variable __class__ shadows the implicit __class__
|
||||
return super(__class__, self).f() # Should NOT trigger UP008
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
from builtins import str, int
|
||||