Compare commits

..

1 Commits

Author SHA1 Message Date
David Peter
618fa922c7 [ty] Do not infer types for unannotated implicit instance attribtues 2025-10-06 16:59:49 +02:00
270 changed files with 8711 additions and 12536 deletions

View File

@@ -707,24 +707,6 @@ jobs:
- run: cargo binstall --no-confirm cargo-shear
- run: cargo shear
ty-completion-evaluation:
name: "ty completion evaluation"
runs-on: depot-ubuntu-22.04-16
needs: determine_changes
if: ${{ needs.determine_changes.outputs.ty == 'true' || github.ref == 'refs/heads/main' }}
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- uses: astral-sh/setup-uv@d0cc045d04ccac9d8b7881df0226f9e82c39688e # v6.8.0
- uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2.8.1
- name: "Install Rust toolchain"
run: rustup show
- name: "Run ty completion evaluation"
run: cargo run --release --package ty_completion_eval -- all --threshold 0.1 --tasks /tmp/completion-evaluation-tasks.csv
- name: "Ensure there are no changes"
run: diff ./crates/ty_completion_eval/completion-evaluation-tasks.csv /tmp/completion-evaluation-tasks.csv
python-package:
name: "python package"
runs-on: ubuntu-latest
@@ -767,7 +749,7 @@ jobs:
with:
node-version: 22
- name: "Cache pre-commit"
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
with:
path: ~/.cache/pre-commit
key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
@@ -929,7 +911,7 @@ jobs:
runs-on: ubuntu-24.04
needs: determine_changes
if: |
github.ref == 'refs/heads/main' ||
github.ref == 'refs/heads/main' ||
(needs.determine_changes.outputs.formatter == 'true' || needs.determine_changes.outputs.linter == 'true')
timeout-minutes: 20
steps:
@@ -964,7 +946,7 @@ jobs:
runs-on: ubuntu-24.04
needs: determine_changes
if: |
github.ref == 'refs/heads/main' ||
github.ref == 'refs/heads/main' ||
needs.determine_changes.outputs.ty == 'true'
timeout-minutes: 20
steps:

View File

@@ -16,8 +16,7 @@ exclude: |
crates/ruff_python_formatter/resources/.*|
crates/ruff_python_formatter/tests/snapshots/.*|
crates/ruff_python_resolver/resources/.*|
crates/ruff_python_resolver/tests/snapshots/.*|
crates/ty_completion_eval/truth/.*
crates/ruff_python_resolver/tests/snapshots/.*
)$
repos:

View File

@@ -1,21 +1,5 @@
# Breaking Changes
## 0.14.0
- **Default to Python 3.10**
Ruff now defaults to Python 3.10 instead of 3.9 if no explicit Python
version is configured using [`ruff.target-version`](https://docs.astral.sh/ruff/settings/#target-version)
or [`project.requires-python`](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#python-requires)
([#20725](https://github.com/astral-sh/ruff/pull/20725))
- **Default to Python 3.14 for syntax errors**
Ruff will default to the _latest_ supported Python version (3.14) when
checking for syntax errors without a Python version configured. The default
in all other cases, like applying lint rules, remains at the minimum
supported Python version (3.10).
## 0.13.0
- **Several rules can now add `from __future__ import annotations` automatically**

View File

@@ -1,46 +1,266 @@
# Changelog
## 0.14.0
## 0.13.3
Released on 2025-10-07.
### Breaking changes
- Update default and latest Python versions for 3.14 ([#20725](https://github.com/astral-sh/ruff/pull/20725))
Released on 2025-10-02.
### Preview features
- \[`flake8-bugbear`\] Include certain guaranteed-mutable expressions: tuples, generators, and assignment expressions (`B006`) ([#20024](https://github.com/astral-sh/ruff/pull/20024))
- \[`refurb`\] Add fixes for `FURB101` and `FURB103` ([#20520](https://github.com/astral-sh/ruff/pull/20520))
- \[`ruff`\] Extend `FA102` with listed PEP585-compatible APIs ([#20659](https://github.com/astral-sh/ruff/pull/20659))
- 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
- \[`flake8-annotations`\] Fix return type annotations to handle shadowed builtin symbols (`ANN201`, `ANN202`, `ANN204`, `ANN205`, `ANN206`) ([#20612](https://github.com/astral-sh/ruff/pull/20612))
- \[`flynt`\] Fix f-string quoting for mixed quote joiners (`FLY002`) ([#20662](https://github.com/astral-sh/ruff/pull/20662))
- \[`isort`\] Fix inserting required imports before future imports (`I002`) ([#20676](https://github.com/astral-sh/ruff/pull/20676))
- \[`ruff`\] Handle argfile expansion errors gracefully ([#20691](https://github.com/astral-sh/ruff/pull/20691))
- \[`ruff`\] Skip `RUF051` if `else`/`elif` block is present ([#20705](https://github.com/astral-sh/ruff/pull/20705))
- \[`ruff`\] Improve handling of intermixed comments inside from-imports ([#20561](https://github.com/astral-sh/ruff/pull/20561))
- \[`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
- \[`flake8-comprehensions`\] Clarify fix safety documentation (`C413`) ([#20640](https://github.com/astral-sh/ruff/pull/20640))
- 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
- [@danparizher](https://github.com/danparizher)
- [@terror](https://github.com/terror)
- [@TaKO8Ki](https://github.com/TaKO8Ki)
- [@ntBre](https://github.com/ntBre)
- [@njhearp](https://github.com/njhearp)
- [@amyreese](https://github.com/amyreese)
- [@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 nonBMP 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.x
## 0.13.0
See [changelogs/0.13.x](./changelogs/0.13.x.md)
Check out the [blog post](https://astral.sh/blog/ruff-v0.13.0) for a migration
guide and overview of the changes!
### Breaking changes
- **Several rules can now add `from __future__ import annotations` automatically**
`TC001`, `TC002`, `TC003`, `RUF013`, and `UP037` now add `from __future__ import annotations` as part of their fixes when the
`lint.future-annotations` setting is enabled. This allows the rules to move
more imports into `TYPE_CHECKING` blocks (`TC001`, `TC002`, and `TC003`),
use PEP 604 union syntax on Python versions before 3.10 (`RUF013`), and
unquote more annotations (`UP037`).
- **Full module paths are now used to verify first-party modules**
Ruff now checks that the full path to a module exists on disk before
categorizing it as a first-party import. This change makes first-party
import detection more accurate, helping to avoid false positives on local
directories with the same name as a third-party dependency, for example. See
the [FAQ
section](https://docs.astral.sh/ruff/faq/#how-does-ruff-determine-which-of-my-imports-are-first-party-third-party-etc) on import categorization for more details.
- **Deprecated rules must now be selected by exact rule code**
Ruff will no longer activate deprecated rules selected by their group name
or prefix. As noted below, the two remaining deprecated rules were also
removed in this release, so this won't affect any current rules, but it will
still affect any deprecations in the future.
- **The deprecated macOS configuration directory fallback has been removed**
Ruff will no longer look for a user-level configuration file at
`~/Library/Application Support/ruff/ruff.toml` on macOS. This feature was
deprecated in v0.5 in favor of using the [XDG
specification](https://specifications.freedesktop.org/basedir-spec/latest/)
(usually resolving to `~/.config/ruff/ruff.toml`), like on Linux. The
fallback and accompanying deprecation warning have now been removed.
### Removed Rules
The following rules have been removed:
- [`pandas-df-variable-name`](https://docs.astral.sh/ruff/rules/pandas-df-variable-name) (`PD901`)
- [`non-pep604-isinstance`](https://docs.astral.sh/ruff/rules/non-pep604-isinstance) (`UP038`)
### Stabilization
The following rules have been stabilized and are no longer in preview:
- [`airflow-dag-no-schedule-argument`](https://docs.astral.sh/ruff/rules/airflow-dag-no-schedule-argument)
(`AIR002`)
- [`airflow3-removal`](https://docs.astral.sh/ruff/rules/airflow3-removal) (`AIR301`)
- [`airflow3-moved-to-provider`](https://docs.astral.sh/ruff/rules/airflow3-moved-to-provider)
(`AIR302`)
- [`airflow3-suggested-update`](https://docs.astral.sh/ruff/rules/airflow3-suggested-update)
(`AIR311`)
- [`airflow3-suggested-to-move-to-provider`](https://docs.astral.sh/ruff/rules/airflow3-suggested-to-move-to-provider)
(`AIR312`)
- [`long-sleep-not-forever`](https://docs.astral.sh/ruff/rules/long-sleep-not-forever) (`ASYNC116`)
- [`f-string-number-format`](https://docs.astral.sh/ruff/rules/f-string-number-format) (`FURB116`)
- [`os-symlink`](https://docs.astral.sh/ruff/rules/os-symlink) (`PTH211`)
- [`generic-not-last-base-class`](https://docs.astral.sh/ruff/rules/generic-not-last-base-class)
(`PYI059`)
- [`redundant-none-literal`](https://docs.astral.sh/ruff/rules/redundant-none-literal) (`PYI061`)
- [`pytest-raises-ambiguous-pattern`](https://docs.astral.sh/ruff/rules/pytest-raises-ambiguous-pattern)
(`RUF043`)
- [`unused-unpacked-variable`](https://docs.astral.sh/ruff/rules/unused-unpacked-variable)
(`RUF059`)
- [`useless-class-metaclass-type`](https://docs.astral.sh/ruff/rules/useless-class-metaclass-type)
(`UP050`)
The following behaviors have been stabilized:
- [`assert-raises-exception`](https://docs.astral.sh/ruff/rules/assert-raises-exception) (`B017`)
now checks for direct calls to `unittest.TestCase.assert_raises` and `pytest.raises` instead of
only the context manager forms.
- [`missing-trailing-comma`](https://docs.astral.sh/ruff/rules/missing-trailing-comma) (`COM812`)
and [`prohibited-trailing-comma`](https://docs.astral.sh/ruff/rules/prohibited-trailing-comma)
(`COM819`) now check for trailing commas in PEP 695 type parameter lists.
- [`raw-string-in-exception`](https://docs.astral.sh/ruff/rules/raw-string-in-exception) (`EM101`)
now also checks for byte strings in exception messages.
- [`invalid-mock-access`](https://docs.astral.sh/ruff/rules/invalid-mock-access) (`PGH005`) now
checks for `AsyncMock` methods like `not_awaited` in addition to the synchronous variants.
- [`useless-import-alias`](https://docs.astral.sh/ruff/rules/useless-import-alias) (`PLC0414`) no
longer applies to `__init__.py` files, where it conflicted with one of the suggested fixes for
[`unused-import`](https://docs.astral.sh/ruff/rules/unused-import) (`F401`).
- [`bidirectional-unicode`](https://docs.astral.sh/ruff/rules/bidirectional-unicode) (`PLE2502`) now
also checks for U+061C (Arabic Letter Mark).
- The fix for
[`multiple-with-statements`](https://docs.astral.sh/ruff/rules/multiple-with-statements)
(`SIM117`) is now marked as always safe.
### Preview features
- \[`pyupgrade`\] Enable `UP043` in stub files ([#20027](https://github.com/astral-sh/ruff/pull/20027))
### Bug fixes
- \[`pyupgrade`\] Apply `UP008` only when the `__class__` cell exists ([#19424](https://github.com/astral-sh/ruff/pull/19424))
- \[`ruff`\] Fix empty f-string detection in `in-empty-collection` (`RUF060`) ([#20249](https://github.com/astral-sh/ruff/pull/20249))
### Server
- Add support for using uv as an alternative formatter backend ([#19665](https://github.com/astral-sh/ruff/pull/19665))
### Documentation
- \[`pep8-naming`\] Fix formatting of `__all__` (`N816`) ([#20301](https://github.com/astral-sh/ruff/pull/20301))
## 0.12.x

View File

@@ -321,15 +321,9 @@ them to [PyPI](https://pypi.org/project/ruff/).
Ruff follows the [semver](https://semver.org/) versioning standard. However, as pre-1.0 software,
even patch releases may contain [non-backwards-compatible changes](https://semver.org/#spec-item-4).
### Installing tools
1. Install `uv`: `curl -LsSf https://astral.sh/uv/install.sh | sh`
1. Install `npm`: `brew install npm` or similar
### Creating a new release
Commit each step of this process separately for easier review.
1. Install `uv`: `curl -LsSf https://astral.sh/uv/install.sh | sh`
1. Run `./scripts/release.sh`; this command will:
@@ -343,7 +337,6 @@ Commit each step of this process separately for easier review.
- Often labels will be missing from pull requests they will need to be manually organized into the proper section
- Changes should be edited to be user-facing descriptions, avoiding internal details
- Square brackets (eg, `[ruff]` project name) will be automatically escaped by `pre-commit`
Additionally, for minor releases:
@@ -383,13 +376,13 @@ Commit each step of this process separately for easier review.
1. Verify the GitHub release:
1. The changelog should match the content of `CHANGELOG.md`
1. The Changelog should match the content of `CHANGELOG.md`
1. Append the contributors from the `scripts/release.sh` script
1. If needed, [update the schemastore](https://github.com/astral-sh/ruff/blob/main/scripts/update_schemastore.py).
1. One can determine if an update is needed when
`git diff old-version-tag new-version-tag -- ruff.schema.json` returns a non-empty diff.
1. Run `uv run --only-dev --no-sync scripts/update_schemastore.py --proto <https|ssh>`
1. Once run successfully, you should follow the link in the output to create a PR.
1. If needed, update the [`ruff-lsp`](https://github.com/astral-sh/ruff-lsp) and

49
Cargo.lock generated
View File

@@ -818,27 +818,6 @@ dependencies = [
"typenum",
]
[[package]]
name = "csv"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf"
dependencies = [
"csv-core",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "csv-core"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d"
dependencies = [
"memchr",
]
[[package]]
name = "ctrlc"
version = "3.5.0"
@@ -2759,7 +2738,7 @@ dependencies = [
[[package]]
name = "ruff"
version = "0.14.0"
version = "0.13.3"
dependencies = [
"anyhow",
"argfile",
@@ -2798,7 +2777,6 @@ dependencies = [
"ruff_python_ast",
"ruff_python_formatter",
"ruff_python_parser",
"ruff_python_trivia",
"ruff_server",
"ruff_source_file",
"ruff_text_size",
@@ -3016,7 +2994,7 @@ dependencies = [
[[package]]
name = "ruff_linter"
version = "0.14.0"
version = "0.13.3"
dependencies = [
"aho-corasick",
"anyhow",
@@ -3370,7 +3348,7 @@ dependencies = [
[[package]]
name = "ruff_wasm"
version = "0.14.0"
version = "0.13.3"
dependencies = [
"console_error_panic_hook",
"console_log",
@@ -4249,26 +4227,6 @@ dependencies = [
"ty_python_semantic",
]
[[package]]
name = "ty_completion_eval"
version = "0.0.0"
dependencies = [
"anyhow",
"bstr",
"clap",
"csv",
"regex",
"ruff_db",
"ruff_text_size",
"serde",
"tempfile",
"toml",
"ty_ide",
"ty_project",
"ty_python_semantic",
"walkdir",
]
[[package]]
name = "ty_ide"
version = "0.0.0"
@@ -4460,7 +4418,6 @@ dependencies = [
"thiserror 2.0.16",
"toml",
"tracing",
"ty_ide",
"ty_python_semantic",
"ty_static",
"ty_vendored",

View File

@@ -43,7 +43,6 @@ ruff_workspace = { path = "crates/ruff_workspace" }
ty = { path = "crates/ty" }
ty_combine = { path = "crates/ty_combine" }
ty_completion_eval = { path = "crates/ty_completion_eval" }
ty_ide = { path = "crates/ty_ide" }
ty_project = { path = "crates/ty_project", default-features = false }
ty_python_semantic = { path = "crates/ty_python_semantic" }
@@ -70,7 +69,6 @@ camino = { version = "1.1.7" }
clap = { version = "4.5.3", features = ["derive"] }
clap_complete_command = { version = "0.6.0" }
clearscreen = { version = "4.0.0" }
csv = { version = "1.3.1" }
divan = { package = "codspeed-divan-compat", version = "3.0.2" }
codspeed-criterion-compat = { version = "3.0.2", default-features = false }
colored = { version = "3.0.0" }
@@ -205,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", "ty_completion_eval"]
ignored = ["getrandom", "ruff_options_metadata", "uuid", "get-size2"]
[workspace.lints.rust]

View File

@@ -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.14.0/install.sh | sh
powershell -c "irm https://astral.sh/ruff/0.14.0/install.ps1 | iex"
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"
```
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.14.0
rev: v0.13.3
hooks:
# Run the linter.
- id: ruff-check

View File

@@ -1,263 +0,0 @@
# Changelog 0.13.x
## 0.13.0
Check out the [blog post](https://astral.sh/blog/ruff-v0.13.0) for a migration
guide and overview of the changes!
### Breaking changes
- **Several rules can now add `from __future__ import annotations` automatically**
`TC001`, `TC002`, `TC003`, `RUF013`, and `UP037` now add `from __future__ import annotations` as part of their fixes when the
`lint.future-annotations` setting is enabled. This allows the rules to move
more imports into `TYPE_CHECKING` blocks (`TC001`, `TC002`, and `TC003`),
use PEP 604 union syntax on Python versions before 3.10 (`RUF013`), and
unquote more annotations (`UP037`).
- **Full module paths are now used to verify first-party modules**
Ruff now checks that the full path to a module exists on disk before
categorizing it as a first-party import. This change makes first-party
import detection more accurate, helping to avoid false positives on local
directories with the same name as a third-party dependency, for example. See
the [FAQ
section](https://docs.astral.sh/ruff/faq/#how-does-ruff-determine-which-of-my-imports-are-first-party-third-party-etc) on import categorization for more details.
- **Deprecated rules must now be selected by exact rule code**
Ruff will no longer activate deprecated rules selected by their group name
or prefix. As noted below, the two remaining deprecated rules were also
removed in this release, so this won't affect any current rules, but it will
still affect any deprecations in the future.
- **The deprecated macOS configuration directory fallback has been removed**
Ruff will no longer look for a user-level configuration file at
`~/Library/Application Support/ruff/ruff.toml` on macOS. This feature was
deprecated in v0.5 in favor of using the [XDG
specification](https://specifications.freedesktop.org/basedir-spec/latest/)
(usually resolving to `~/.config/ruff/ruff.toml`), like on Linux. The
fallback and accompanying deprecation warning have now been removed.
### Removed Rules
The following rules have been removed:
- [`pandas-df-variable-name`](https://docs.astral.sh/ruff/rules/pandas-df-variable-name) (`PD901`)
- [`non-pep604-isinstance`](https://docs.astral.sh/ruff/rules/non-pep604-isinstance) (`UP038`)
### Stabilization
The following rules have been stabilized and are no longer in preview:
- [`airflow-dag-no-schedule-argument`](https://docs.astral.sh/ruff/rules/airflow-dag-no-schedule-argument)
(`AIR002`)
- [`airflow3-removal`](https://docs.astral.sh/ruff/rules/airflow3-removal) (`AIR301`)
- [`airflow3-moved-to-provider`](https://docs.astral.sh/ruff/rules/airflow3-moved-to-provider)
(`AIR302`)
- [`airflow3-suggested-update`](https://docs.astral.sh/ruff/rules/airflow3-suggested-update)
(`AIR311`)
- [`airflow3-suggested-to-move-to-provider`](https://docs.astral.sh/ruff/rules/airflow3-suggested-to-move-to-provider)
(`AIR312`)
- [`long-sleep-not-forever`](https://docs.astral.sh/ruff/rules/long-sleep-not-forever) (`ASYNC116`)
- [`f-string-number-format`](https://docs.astral.sh/ruff/rules/f-string-number-format) (`FURB116`)
- [`os-symlink`](https://docs.astral.sh/ruff/rules/os-symlink) (`PTH211`)
- [`generic-not-last-base-class`](https://docs.astral.sh/ruff/rules/generic-not-last-base-class)
(`PYI059`)
- [`redundant-none-literal`](https://docs.astral.sh/ruff/rules/redundant-none-literal) (`PYI061`)
- [`pytest-raises-ambiguous-pattern`](https://docs.astral.sh/ruff/rules/pytest-raises-ambiguous-pattern)
(`RUF043`)
- [`unused-unpacked-variable`](https://docs.astral.sh/ruff/rules/unused-unpacked-variable)
(`RUF059`)
- [`useless-class-metaclass-type`](https://docs.astral.sh/ruff/rules/useless-class-metaclass-type)
(`UP050`)
The following behaviors have been stabilized:
- [`assert-raises-exception`](https://docs.astral.sh/ruff/rules/assert-raises-exception) (`B017`)
now checks for direct calls to `unittest.TestCase.assert_raises` and `pytest.raises` instead of
only the context manager forms.
- [`missing-trailing-comma`](https://docs.astral.sh/ruff/rules/missing-trailing-comma) (`COM812`)
and [`prohibited-trailing-comma`](https://docs.astral.sh/ruff/rules/prohibited-trailing-comma)
(`COM819`) now check for trailing commas in PEP 695 type parameter lists.
- [`raw-string-in-exception`](https://docs.astral.sh/ruff/rules/raw-string-in-exception) (`EM101`)
now also checks for byte strings in exception messages.
- [`invalid-mock-access`](https://docs.astral.sh/ruff/rules/invalid-mock-access) (`PGH005`) now
checks for `AsyncMock` methods like `not_awaited` in addition to the synchronous variants.
- [`useless-import-alias`](https://docs.astral.sh/ruff/rules/useless-import-alias) (`PLC0414`) no
longer applies to `__init__.py` files, where it conflicted with one of the suggested fixes for
[`unused-import`](https://docs.astral.sh/ruff/rules/unused-import) (`F401`).
- [`bidirectional-unicode`](https://docs.astral.sh/ruff/rules/bidirectional-unicode) (`PLE2502`) now
also checks for U+061C (Arabic Letter Mark).
- The fix for
[`multiple-with-statements`](https://docs.astral.sh/ruff/rules/multiple-with-statements)
(`SIM117`) is now marked as always safe.
### Preview features
- \[`pyupgrade`\] Enable `UP043` in stub files ([#20027](https://github.com/astral-sh/ruff/pull/20027))
### Bug fixes
- \[`pyupgrade`\] Apply `UP008` only when the `__class__` cell exists ([#19424](https://github.com/astral-sh/ruff/pull/19424))
- \[`ruff`\] Fix empty f-string detection in `in-empty-collection` (`RUF060`) ([#20249](https://github.com/astral-sh/ruff/pull/20249))
### Server
- Add support for using uv as an alternative formatter backend ([#19665](https://github.com/astral-sh/ruff/pull/19665))
### Documentation
- \[`pep8-naming`\] Fix formatting of `__all__` (`N816`) ([#20301](https://github.com/astral-sh/ruff/pull/20301))
## 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.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 nonBMP 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.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)

View File

@@ -1,6 +1,6 @@
[package]
name = "ruff"
version = "0.14.0"
version = "0.13.3"
publish = true
authors = { workspace = true }
edition = { workspace = true }
@@ -72,7 +72,6 @@ dunce = { workspace = true }
indoc = { workspace = true }
insta = { workspace = true, features = ["filters", "json"] }
insta-cmd = { workspace = true }
ruff_python_trivia = { workspace = true }
tempfile = { workspace = true }
test-case = { workspace = true }

File diff suppressed because it is too large Load Diff

View File

@@ -1,177 +0,0 @@
//! Test fixture utilities for ruff CLI tests
//!
//! The core concept is borrowed from ty/tests/cli/main.rs and can be extended
//! with more functionality from there in the future if needed.
#![cfg(not(target_family = "wasm"))]
use anyhow::{Context as _, Result};
use insta::internals::SettingsBindDropGuard;
use insta_cmd::get_cargo_bin;
use std::{
fs,
path::{Path, PathBuf},
process::Command,
};
use tempfile::TempDir;
mod lint;
const BIN_NAME: &str = "ruff";
/// Creates a regex filter for replacing temporary directory paths in snapshots
pub(crate) fn tempdir_filter(path: impl AsRef<str>) -> String {
format!(r"{}[\\/]?", regex::escape(path.as_ref()))
}
/// A test fixture for running ruff CLI tests with temporary directories and files.
///
/// This fixture provides:
/// - Temporary directory management
/// - File creation utilities
/// - Proper snapshot filtering for cross-platform compatibility
/// - Pre-configured ruff command creation
///
/// # Example
///
/// ```rust,no_run
/// use crate::common::RuffTestFixture;
///
/// let fixture = RuffTestFixture::with_file("ruff.toml", "select = ['E']")?;
/// let output = fixture.command().args(["check", "."]).output()?;
/// ```
pub(crate) struct CliTest {
_temp_dir: TempDir,
_settings_scope: SettingsBindDropGuard,
project_dir: PathBuf,
}
impl CliTest {
/// Creates a new test fixture with an empty temporary directory.
///
/// This sets up:
/// - A temporary directory that's automatically cleaned up
/// - Insta snapshot filters for cross-platform path compatibility
/// - Environment isolation for consistent test behavior
pub(crate) fn new() -> Result<Self> {
Self::with_settings(|_, settings| settings)
}
pub(crate) fn with_settings(
setup_settings: impl FnOnce(&Path, insta::Settings) -> insta::Settings,
) -> Result<Self> {
let temp_dir = TempDir::new()?;
// Canonicalize the tempdir path because macOS uses symlinks for tempdirs
// and that doesn't play well with our snapshot filtering.
// Simplify with dunce because otherwise we get UNC paths on Windows.
let project_dir = dunce::simplified(
&temp_dir
.path()
.canonicalize()
.context("Failed to canonicalize project path")?,
)
.to_path_buf();
let mut settings = setup_settings(&project_dir, insta::Settings::clone_current());
settings.add_filter(&tempdir_filter(project_dir.to_str().unwrap()), "[TMP]/");
settings.add_filter(r#"\\([\w&&[^nr"]]\w|\s|\.)"#, "/$1");
settings.add_filter(r"(Panicked at) [^:]+:\d+:\d+", "$1 <location>");
settings.add_filter(ruff_linter::VERSION, "[VERSION]");
settings.add_filter(
r#"The system cannot find the file specified."#,
"No such file or directory",
);
let settings_scope = settings.bind_to_scope();
Ok(Self {
project_dir,
_temp_dir: temp_dir,
_settings_scope: settings_scope,
})
}
/// Creates a test fixture with a single file.
///
/// # Arguments
///
/// * `path` - The relative path for the file
/// * `content` - The content to write to the file
///
/// # Example
///
/// ```rust,no_run
/// let fixture = RuffTestFixture::with_file("ruff.toml", "select = ['E']")?;
/// ```
pub(crate) fn with_file(path: impl AsRef<Path>, content: &str) -> Result<Self> {
let fixture = Self::new()?;
fixture.write_file(path, content)?;
Ok(fixture)
}
/// Ensures that the parent directory of a path exists.
fn ensure_parent_directory(path: &Path) -> Result<()> {
if let Some(parent) = path.parent() {
fs::create_dir_all(parent)
.with_context(|| format!("Failed to create directory `{}`", parent.display()))?;
}
Ok(())
}
/// Writes a file to the test directory.
///
/// Parent directories are created automatically if they don't exist.
/// Content is dedented to remove common leading whitespace for cleaner test code.
///
/// # Arguments
///
/// * `path` - The relative path for the file
/// * `content` - The content to write to the file
pub(crate) fn write_file(&self, path: impl AsRef<Path>, content: &str) -> Result<()> {
let path = path.as_ref();
let file_path = self.project_dir.join(path);
Self::ensure_parent_directory(&file_path)?;
let content = ruff_python_trivia::textwrap::dedent(content);
fs::write(&file_path, content.as_ref())
.with_context(|| format!("Failed to write file `{}`", file_path.display()))?;
Ok(())
}
/// Returns the path to the test directory root.
pub(crate) fn root(&self) -> &Path {
&self.project_dir
}
/// Creates a pre-configured ruff command for testing.
///
/// The command is set up with:
/// - The correct ruff binary path
/// - Working directory set to the test directory
/// - Clean environment variables for consistent behavior
///
/// You can chain additional arguments and options as needed.
///
/// # Example
///
/// ```rust,no_run
/// let output = fixture
/// .command()
/// .args(["check", "--select", "E"])
/// .arg(".")
/// .output()?;
/// ```
pub(crate) fn command(&self) -> Command {
let mut command = Command::new(get_cargo_bin(BIN_NAME));
command.current_dir(&self.project_dir);
// Unset all environment variables because they can affect test behavior.
command.env_clear();
command
}
}

View File

@@ -1,288 +0,0 @@
---
source: crates/ruff/tests/cli/lint.rs
info:
program: ruff
args:
- check
- "--no-cache"
- "--output-format"
- concise
- "--show-settings"
- test.py
snapshot_kind: text
---
success: true
exit_code: 0
----- stdout -----
Resolved settings for: "[TMP]/test.py"
Settings path: "[TMP]/ruff.toml"
# 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",
"*.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.10
linter.per_file_target_version = {}
linter.preview = disabled
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.10
formatter.per_file_target_version = {}
formatter.preview = disabled
formatter.line_width = 88
formatter.line_ending = auto
formatter.indent_style = space
formatter.indent_width = 4
formatter.quote_style = double
formatter.magic_trailing_comma = respect
formatter.docstring_code_format = disabled
formatter.docstring_code_line_width = dynamic
# Analyze Settings
analyze.exclude = []
analyze.preview = disabled
analyze.target_version = 3.10
analyze.string_imports = disabled
analyze.extension = ExtensionMapping({})
analyze.include_dependencies = {}
----- stderr -----

View File

@@ -1,290 +0,0 @@
---
source: crates/ruff/tests/cli/lint.rs
info:
program: ruff
args:
- check
- "--no-cache"
- "--output-format"
- concise
- "--show-settings"
- "--select"
- UP007
- test.py
- "-"
snapshot_kind: text
---
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",
"*.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 = disabled
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 = disabled
formatter.line_width = 88
formatter.line_ending = auto
formatter.indent_style = space
formatter.indent_width = 4
formatter.quote_style = double
formatter.magic_trailing_comma = respect
formatter.docstring_code_format = disabled
formatter.docstring_code_line_width = dynamic
# Analyze Settings
analyze.exclude = []
analyze.preview = disabled
analyze.target_version = 3.11
analyze.string_imports = disabled
analyze.extension = ExtensionMapping({})
analyze.include_dependencies = {}
----- stderr -----

View File

@@ -1,292 +0,0 @@
---
source: crates/ruff/tests/cli/lint.rs
info:
program: ruff
args:
- check
- "--no-cache"
- "--output-format"
- concise
- "--preview"
- "--show-settings"
- "--select"
- UP007
- test.py
- "-"
snapshot_kind: text
---
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 -----

View File

@@ -1,292 +0,0 @@
---
source: crates/ruff/tests/cli/lint.rs
info:
program: ruff
args:
- check
- "--no-cache"
- "--output-format"
- concise
- "--show-settings"
- "--select"
- UP007
- "--target-version"
- py310
- test.py
- "-"
snapshot_kind: text
---
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",
"*.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.10
linter.per_file_target_version = {}
linter.preview = disabled
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.10
formatter.per_file_target_version = {}
formatter.preview = disabled
formatter.line_width = 88
formatter.line_ending = auto
formatter.indent_style = space
formatter.indent_width = 4
formatter.quote_style = double
formatter.magic_trailing_comma = respect
formatter.docstring_code_format = disabled
formatter.docstring_code_line_width = dynamic
# Analyze Settings
analyze.exclude = []
analyze.preview = disabled
analyze.target_version = 3.10
analyze.string_imports = disabled
analyze.extension = ExtensionMapping({})
analyze.include_dependencies = {}
----- stderr -----

View File

@@ -1,289 +0,0 @@
---
source: crates/ruff/tests/cli/lint.rs
info:
program: ruff
args:
- check
- "--no-cache"
- "--output-format"
- concise
- "--show-settings"
- "--select"
- UP007
- foo/test.py
snapshot_kind: text
---
success: true
exit_code: 0
----- stdout -----
Resolved settings for: "[TMP]/foo/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",
"*.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 = disabled
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 = disabled
formatter.line_width = 88
formatter.line_ending = auto
formatter.indent_style = space
formatter.indent_width = 4
formatter.quote_style = double
formatter.magic_trailing_comma = respect
formatter.docstring_code_format = disabled
formatter.docstring_code_line_width = dynamic
# Analyze Settings
analyze.exclude = []
analyze.preview = disabled
analyze.target_version = 3.11
analyze.string_imports = disabled
analyze.extension = ExtensionMapping({})
analyze.include_dependencies = {}
----- stderr -----

View File

@@ -1,289 +0,0 @@
---
source: crates/ruff/tests/cli/lint.rs
info:
program: ruff
args:
- check
- "--no-cache"
- "--output-format"
- concise
- "--show-settings"
- "--select"
- UP007
- foo/test.py
snapshot_kind: text
---
success: true
exit_code: 0
----- stdout -----
Resolved settings for: "[TMP]/foo/test.py"
# General Settings
cache_dir = "[TMP]/foo/.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",
"*.ipynb",
"**/pyproject.toml",
]
file_resolver.extend_include = []
file_resolver.respect_gitignore = true
file_resolver.project_root = "[TMP]/foo"
# Linter Settings
linter.exclude = []
linter.project_root = "[TMP]/foo"
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.10
linter.per_file_target_version = {}
linter.preview = disabled
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]/foo",
"[TMP]/foo/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.10
formatter.per_file_target_version = {}
formatter.preview = disabled
formatter.line_width = 88
formatter.line_ending = auto
formatter.indent_style = space
formatter.indent_width = 4
formatter.quote_style = double
formatter.magic_trailing_comma = respect
formatter.docstring_code_format = disabled
formatter.docstring_code_line_width = dynamic
# Analyze Settings
analyze.exclude = []
analyze.preview = disabled
analyze.target_version = 3.10
analyze.string_imports = disabled
analyze.extension = ExtensionMapping({})
analyze.include_dependencies = {}
----- stderr -----

View File

@@ -1,287 +0,0 @@
---
source: crates/ruff/tests/cli/lint.rs
info:
program: ruff
args:
- check
- "--no-cache"
- "--output-format"
- concise
- "--show-settings"
- test.py
---
success: true
exit_code: 0
----- stdout -----
Resolved settings for: "[TMP]/foo/test.py"
Settings path: "[TMP]/ruff.toml"
# 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",
"*.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 = none
linter.per_file_target_version = {}
linter.preview = disabled
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.10
formatter.per_file_target_version = {}
formatter.preview = disabled
formatter.line_width = 88
formatter.line_ending = auto
formatter.indent_style = space
formatter.indent_width = 4
formatter.quote_style = double
formatter.magic_trailing_comma = respect
formatter.docstring_code_format = disabled
formatter.docstring_code_line_width = dynamic
# Analyze Settings
analyze.exclude = []
analyze.preview = disabled
analyze.target_version = 3.10
analyze.string_imports = disabled
analyze.extension = ExtensionMapping({})
analyze.include_dependencies = {}
----- stderr -----

View File

@@ -1,287 +0,0 @@
---
source: crates/ruff/tests/cli/lint.rs
info:
program: ruff
args:
- check
- "--no-cache"
- "--output-format"
- concise
- "--show-settings"
- foo/test.py
---
success: true
exit_code: 0
----- stdout -----
Resolved settings for: "[TMP]/foo/test.py"
Settings path: "[TMP]/ruff.toml"
# 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",
"*.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 = none
linter.per_file_target_version = {}
linter.preview = disabled
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.10
formatter.per_file_target_version = {}
formatter.preview = disabled
formatter.line_width = 88
formatter.line_ending = auto
formatter.indent_style = space
formatter.indent_width = 4
formatter.quote_style = double
formatter.magic_trailing_comma = respect
formatter.docstring_code_format = disabled
formatter.docstring_code_line_width = dynamic
# Analyze Settings
analyze.exclude = []
analyze.preview = disabled
analyze.target_version = 3.10
analyze.string_imports = disabled
analyze.extension = ExtensionMapping({})
analyze.include_dependencies = {}
----- stderr -----

View File

@@ -1,288 +0,0 @@
---
source: crates/ruff/tests/cli/lint.rs
info:
program: ruff
args:
- check
- "--no-cache"
- "--output-format"
- concise
- test.py
- "--show-settings"
snapshot_kind: text
---
success: true
exit_code: 0
----- stdout -----
Resolved settings for: "[TMP]/test.py"
Settings path: "[TMP]/ruff.toml"
# 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",
"*.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 = disabled
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 = disabled
formatter.line_width = 88
formatter.line_ending = auto
formatter.indent_style = space
formatter.indent_width = 4
formatter.quote_style = double
formatter.magic_trailing_comma = respect
formatter.docstring_code_format = disabled
formatter.docstring_code_line_width = dynamic
# Analyze Settings
analyze.exclude = []
analyze.preview = disabled
analyze.target_version = 3.11
analyze.string_imports = disabled
analyze.extension = ExtensionMapping({})
analyze.include_dependencies = {}
----- stderr -----

6597
crates/ruff/tests/lint.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
---
source: crates/ruff/tests/cli/lint.rs
source: crates/ruff/tests/lint.rs
info:
program: ruff
args:
@@ -12,7 +12,6 @@ info:
- "--target-version"
- py39
- input.py
snapshot_kind: text
---
success: false
exit_code: 1

View File

@@ -1,6 +1,6 @@
[package]
name = "ruff_linter"
version = "0.14.0"
version = "0.13.3"
publish = false
authors = { workspace = true }
edition = { workspace = true }

View File

@@ -1,3 +0,0 @@
"a docstring"
from __future__ import annotations
# EOF

View File

@@ -1,2 +0,0 @@
from __future__ import annotations
# EOF

View File

@@ -14,6 +14,6 @@ class Bar:
]
# This is no longer allowed on Python 3.14+
# OK: Allow named expressions in annotations.
x: (y := 1)
print(y)

View File

@@ -13,16 +13,16 @@ CStr2: TypeAlias = Union["C", str] # always okay
# References to a class from inside the class:
class C:
other: C = ... # valid in a `.pyi` stub file, and in a `.py` runtime file with deferred annotations
other: C = ... # valid in a `.pyi` stub file, not in a `.py` runtime file
other2: "C" = ... # always okay
def from_str(self, s: str) -> C: ... # valid in a `.pyi` stub file, and in a `.py` runtime file with deferred annotations
def from_str(self, s: str) -> C: ... # valid in a `.pyi` stub file, not in a `.py` runtime file
def from_str2(self, s: str) -> "C": ... # always okay
# Circular references:
class A:
foo: B # valid in a `.pyi` stub file, and in a `.py` runtime file with deferred annotations
foo: B # valid in a `.pyi` stub file, not in a `.py` runtime file
foo2: "B" # always okay
bar: dict[str, B] # valid in a `.pyi` stub file, and in a `.py` runtime file with deferred annotations
bar: dict[str, B] # valid in a `.pyi` stub file, not in a `.py` runtime file
bar2: dict[str, "A"] # always okay
class B:

View File

@@ -56,11 +56,3 @@ f"{str(object=3)}"
f"{str(x for x in [])}"
f"{str((x for x in []))}"
# Debug text cases - should not trigger RUF010
f"{str(1)=}"
f"{ascii(1)=}"
f"{repr(1)=}"
f"{str('hello')=}"
f"{ascii('hello')=}"
f"{repr('hello')=}"

View File

@@ -128,15 +128,3 @@ if f"0" in d: # f-string
if k in a.d: # Attribute dict
del a.d[k]
if k in d: # else statement
del d[k]
else:
pass
if k in d: # elif and else statements
del d[k]
elif 0 in d:
del d[0]
else:
pass

View File

@@ -67,25 +67,17 @@ impl<'a> Importer<'a> {
/// Add an import statement to import the given module.
///
/// If there are no existing imports, the new import will be added at the top
/// of the file. If there are future imports, the new import will be added
/// after the last future import. Otherwise, it will be added after the most
/// recent top-level import statement.
/// of the file. Otherwise, it will be added after the most recent top-level
/// import statement.
pub(crate) fn add_import(&self, import: &NameImport, at: TextSize) -> Edit {
let required_import = import.to_string();
if let Some(stmt) = self.preceding_import(at) {
// Insert after the last top-level import.
Insertion::end_of_statement(stmt, self.source, self.stylist).into_edit(&required_import)
} else {
// Check if there are any future imports that we need to respect
if let Some(last_future_import) = self.find_last_future_import() {
// Insert after the last future import
Insertion::end_of_statement(last_future_import, self.source, self.stylist)
.into_edit(&required_import)
} else {
// Insert at the start of the file.
Insertion::start_of_file(self.python_ast, self.source, self.stylist)
.into_edit(&required_import)
}
// Insert at the start of the file.
Insertion::start_of_file(self.python_ast, self.source, self.stylist)
.into_edit(&required_import)
}
}
@@ -532,18 +524,6 @@ impl<'a> Importer<'a> {
}
}
/// Find the last `from __future__` import statement in the AST.
fn find_last_future_import(&self) -> Option<&'a Stmt> {
let mut body = self.python_ast.iter().peekable();
let _docstring = body.next_if(|stmt| ast::helpers::is_docstring_stmt(stmt));
body.take_while(|stmt| {
stmt.as_import_from_stmt()
.is_some_and(|import_from| import_from.module.as_deref() == Some("__future__"))
})
.last()
}
/// Add a `from __future__ import annotations` import.
pub(crate) fn add_future_import(&self) -> Edit {
let import = &NameImport::ImportFrom(MemberNameImport::member(

View File

@@ -27,13 +27,14 @@ use crate::fix::{FixResult, fix_file};
use crate::message::create_syntax_error_diagnostic;
use crate::noqa::add_noqa;
use crate::package::PackageRoot;
use crate::preview::is_py314_support_enabled;
use crate::registry::Rule;
#[cfg(any(feature = "test-rules", test))]
use crate::rules::ruff::rules::test_rules::{self, TEST_RULES, TestRule};
use crate::settings::types::UnsafeFixes;
use crate::settings::{LinterSettings, TargetVersion, flags};
use crate::source_kind::SourceKind;
use crate::{Locator, directives, fs};
use crate::{Locator, directives, fs, warn_user_once};
pub(crate) mod float;
@@ -441,6 +442,14 @@ pub fn lint_only(
) -> LinterResult {
let target_version = settings.resolve_target_version(path);
if matches!(target_version, TargetVersion(Some(PythonVersion::PY314)))
&& !is_py314_support_enabled(settings)
{
warn_user_once!(
"Support for Python 3.14 is in preview and may undergo breaking changes. Enable `preview` to remove this warning."
);
}
let parsed = source.into_parsed(source_kind, source_type, target_version.parser_version());
// Map row and column locations to byte slices (lazily).
@@ -542,6 +551,14 @@ pub fn lint_fix<'a>(
let target_version = settings.resolve_target_version(path);
if matches!(target_version, TargetVersion(Some(PythonVersion::PY314)))
&& !is_py314_support_enabled(settings)
{
warn_user_once!(
"Support for Python 3.14 is in preview and may undergo breaking changes. Enable `preview` to remove this warning."
);
}
// Continuously fix until the source code stabilizes.
loop {
// Parse once.

View File

@@ -7,6 +7,10 @@
use crate::settings::LinterSettings;
pub(crate) const fn is_py314_support_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}
// Rule-specific behavior
// https://github.com/astral-sh/ruff/pull/15541
@@ -255,13 +259,3 @@ pub(crate) const fn is_b006_unsafe_fix_preserve_assignment_expr_enabled(
) -> bool {
settings.preview.is_enabled()
}
// https://github.com/astral-sh/ruff/pull/20520
pub(crate) const fn is_fix_read_whole_file_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}
// https://github.com/astral-sh/ruff/pull/20520
pub(crate) const fn is_fix_write_whole_file_enabled(settings: &LinterSettings) -> bool {
settings.preview.is_enabled()
}

View File

@@ -8,12 +8,9 @@ mod tests {
use anyhow::Result;
use test_case::test_case;
use ruff_python_ast::PythonVersion;
use crate::registry::Rule;
use crate::settings::LinterSettings;
use crate::test::test_path;
use crate::{assert_diagnostics, assert_diagnostics_diff};
use crate::{assert_diagnostics, settings};
#[test_case(Rule::FastApiRedundantResponseModel, Path::new("FAST001.py"))]
#[test_case(Rule::FastApiNonAnnotatedDependency, Path::new("FAST002_0.py"))]
@@ -23,35 +20,12 @@ mod tests {
let snapshot = format!("{}_{}", rule_code.name(), path.to_string_lossy());
let diagnostics = test_path(
Path::new("fastapi").join(path).as_path(),
&LinterSettings::for_rule(rule_code),
&settings::LinterSettings::for_rule(rule_code),
)?;
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
#[test_case(Rule::FastApiRedundantResponseModel, Path::new("FAST001.py"))]
#[test_case(Rule::FastApiUnusedPathParameter, Path::new("FAST003.py"))]
fn deferred_annotations_diff(rule_code: Rule, path: &Path) -> Result<()> {
let snapshot = format!(
"deferred_annotations_diff_{}_{}",
rule_code.name(),
path.to_string_lossy()
);
assert_diagnostics_diff!(
snapshot,
Path::new("fastapi").join(path).as_path(),
&LinterSettings {
unresolved_target_version: PythonVersion::PY313.into(),
..LinterSettings::for_rule(rule_code)
},
&LinterSettings {
unresolved_target_version: PythonVersion::PY314.into(),
..LinterSettings::for_rule(rule_code)
},
);
Ok(())
}
// FAST002 autofixes use `typing_extensions` on Python 3.8,
// since `typing.Annotated` was added in Python 3.9
#[test_case(Rule::FastApiNonAnnotatedDependency, Path::new("FAST002_0.py"))]
@@ -60,9 +34,9 @@ mod tests {
let snapshot = format!("{}_{}_py38", rule_code.name(), path.to_string_lossy());
let diagnostics = test_path(
Path::new("fastapi").join(path).as_path(),
&LinterSettings {
unresolved_target_version: PythonVersion::PY38.into(),
..LinterSettings::for_rule(rule_code)
&settings::LinterSettings {
unresolved_target_version: ruff_python_ast::PythonVersion::PY38.into(),
..settings::LinterSettings::for_rule(rule_code)
},
)?;
assert_diagnostics!(snapshot, diagnostics);

View File

@@ -1,213 +0,0 @@
---
source: crates/ruff_linter/src/rules/fastapi/mod.rs
---
--- Linter settings ---
-linter.unresolved_target_version = 3.13
+linter.unresolved_target_version = 3.14
--- Summary ---
Removed: 10
Added: 0
--- Removed ---
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:17:22
|
17 | @app.post("/items/", response_model=Item)
| ^^^^^^^^^^^^^^^^^^^
18 | async def create_item(item: Item) -> Item:
19 | return item
|
help: Remove argument
14 | # Errors
15 |
16 |
- @app.post("/items/", response_model=Item)
17 + @app.post("/items/")
18 | async def create_item(item: Item) -> Item:
19 | return item
20 |
note: This is an unsafe fix and may change runtime behavior
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:22:22
|
22 | @app.post("/items/", response_model=list[Item])
| ^^^^^^^^^^^^^^^^^^^^^^^^^
23 | async def create_item(item: Item) -> list[Item]:
24 | return item
|
help: Remove argument
19 | return item
20 |
21 |
- @app.post("/items/", response_model=list[Item])
22 + @app.post("/items/")
23 | async def create_item(item: Item) -> list[Item]:
24 | return item
25 |
note: This is an unsafe fix and may change runtime behavior
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:27:22
|
27 | @app.post("/items/", response_model=List[Item])
| ^^^^^^^^^^^^^^^^^^^^^^^^^
28 | async def create_item(item: Item) -> List[Item]:
29 | return item
|
help: Remove argument
24 | return item
25 |
26 |
- @app.post("/items/", response_model=List[Item])
27 + @app.post("/items/")
28 | async def create_item(item: Item) -> List[Item]:
29 | return item
30 |
note: This is an unsafe fix and may change runtime behavior
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:32:22
|
32 | @app.post("/items/", response_model=Dict[str, Item])
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
33 | async def create_item(item: Item) -> Dict[str, Item]:
34 | return item
|
help: Remove argument
29 | return item
30 |
31 |
- @app.post("/items/", response_model=Dict[str, Item])
32 + @app.post("/items/")
33 | async def create_item(item: Item) -> Dict[str, Item]:
34 | return item
35 |
note: This is an unsafe fix and may change runtime behavior
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:37:22
|
37 | @app.post("/items/", response_model=str)
| ^^^^^^^^^^^^^^^^^^
38 | async def create_item(item: Item) -> str:
39 | return item
|
help: Remove argument
34 | return item
35 |
36 |
- @app.post("/items/", response_model=str)
37 + @app.post("/items/")
38 | async def create_item(item: Item) -> str:
39 | return item
40 |
note: This is an unsafe fix and may change runtime behavior
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:42:21
|
42 | @app.get("/items/", response_model=Item)
| ^^^^^^^^^^^^^^^^^^^
43 | async def create_item(item: Item) -> Item:
44 | return item
|
help: Remove argument
39 | return item
40 |
41 |
- @app.get("/items/", response_model=Item)
42 + @app.get("/items/")
43 | async def create_item(item: Item) -> Item:
44 | return item
45 |
note: This is an unsafe fix and may change runtime behavior
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:47:21
|
47 | @app.get("/items/", response_model=Item)
| ^^^^^^^^^^^^^^^^^^^
48 | @app.post("/items/", response_model=Item)
49 | async def create_item(item: Item) -> Item:
|
help: Remove argument
44 | return item
45 |
46 |
- @app.get("/items/", response_model=Item)
47 + @app.get("/items/")
48 | @app.post("/items/", response_model=Item)
49 | async def create_item(item: Item) -> Item:
50 | return item
note: This is an unsafe fix and may change runtime behavior
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:48:22
|
47 | @app.get("/items/", response_model=Item)
48 | @app.post("/items/", response_model=Item)
| ^^^^^^^^^^^^^^^^^^^
49 | async def create_item(item: Item) -> Item:
50 | return item
|
help: Remove argument
45 |
46 |
47 | @app.get("/items/", response_model=Item)
- @app.post("/items/", response_model=Item)
48 + @app.post("/items/")
49 | async def create_item(item: Item) -> Item:
50 | return item
51 |
note: This is an unsafe fix and may change runtime behavior
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:53:24
|
53 | @router.get("/items/", response_model=Item)
| ^^^^^^^^^^^^^^^^^^^
54 | async def create_item(item: Item) -> Item:
55 | return item
|
help: Remove argument
50 | return item
51 |
52 |
- @router.get("/items/", response_model=Item)
53 + @router.get("/items/")
54 | async def create_item(item: Item) -> Item:
55 | return item
56 |
note: This is an unsafe fix and may change runtime behavior
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:118:23
|
116 | def setup_app(app_arg: FastAPI, non_app: str) -> None:
117 | # Error
118 | @app_arg.get("/", response_model=str)
| ^^^^^^^^^^^^^^^^^^
119 | async def get_root() -> str:
120 | return "Hello World!"
|
help: Remove argument
115 |
116 | def setup_app(app_arg: FastAPI, non_app: str) -> None:
117 | # Error
- @app_arg.get("/", response_model=str)
118 + @app_arg.get("/")
119 | async def get_root() -> str:
120 | return "Hello World!"
121 |
note: This is an unsafe fix and may change runtime behavior

View File

@@ -1,74 +0,0 @@
---
source: crates/ruff_linter/src/rules/fastapi/mod.rs
---
--- Linter settings ---
-linter.unresolved_target_version = 3.13
+linter.unresolved_target_version = 3.14
--- Summary ---
Removed: 3
Added: 0
--- Removed ---
FAST003 [*] Parameter `thing_id` appears in route path, but not in `single` signature
--> FAST003.py:158:19
|
157 | ### Errors
158 | @app.get("/things/{thing_id}")
| ^^^^^^^^^^
159 | async def single(other: Annotated[str, Depends(something_else)]): ...
160 | @app.get("/things/{thing_id}")
|
help: Add `thing_id` to function signature
156 |
157 | ### Errors
158 | @app.get("/things/{thing_id}")
- async def single(other: Annotated[str, Depends(something_else)]): ...
159 + async def single(other: Annotated[str, Depends(something_else)], thing_id): ...
160 | @app.get("/things/{thing_id}")
161 | async def default(other: str = Depends(something_else)): ...
162 |
note: This is an unsafe fix and may change runtime behavior
FAST003 [*] Parameter `id` appears in route path, but not in `get_id_pydantic_full` signature
--> FAST003.py:197:12
|
196 | # Errors
197 | @app.get("/{id}")
| ^^^^
198 | async def get_id_pydantic_full(
199 | params: Annotated[PydanticParams, Depends(PydanticParams)],
|
help: Add `id` to function signature
196 | # Errors
197 | @app.get("/{id}")
198 | async def get_id_pydantic_full(
- params: Annotated[PydanticParams, Depends(PydanticParams)],
199 + params: Annotated[PydanticParams, Depends(PydanticParams)], id,
200 | ): ...
201 | @app.get("/{id}")
202 | async def get_id_pydantic_short(params: Annotated[PydanticParams, Depends()]): ...
note: This is an unsafe fix and may change runtime behavior
FAST003 [*] Parameter `id` appears in route path, but not in `get_id_pydantic_short` signature
--> FAST003.py:201:12
|
199 | params: Annotated[PydanticParams, Depends(PydanticParams)],
200 | ): ...
201 | @app.get("/{id}")
| ^^^^
202 | async def get_id_pydantic_short(params: Annotated[PydanticParams, Depends()]): ...
203 | @app.get("/{id}")
|
help: Add `id` to function signature
199 | params: Annotated[PydanticParams, Depends(PydanticParams)],
200 | ): ...
201 | @app.get("/{id}")
- async def get_id_pydantic_short(params: Annotated[PydanticParams, Depends()]): ...
202 + async def get_id_pydantic_short(params: Annotated[PydanticParams, Depends()], id): ...
203 | @app.get("/{id}")
204 | async def get_id_init_not_annotated(params = Depends(InitParams)): ...
205 |
note: This is an unsafe fix and may change runtime behavior

View File

@@ -1,4 +1,195 @@
---
source: crates/ruff_linter/src/rules/fastapi/mod.rs
---
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:17:22
|
17 | @app.post("/items/", response_model=Item)
| ^^^^^^^^^^^^^^^^^^^
18 | async def create_item(item: Item) -> Item:
19 | return item
|
help: Remove argument
14 | # Errors
15 |
16 |
- @app.post("/items/", response_model=Item)
17 + @app.post("/items/")
18 | async def create_item(item: Item) -> Item:
19 | return item
20 |
note: This is an unsafe fix and may change runtime behavior
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:22:22
|
22 | @app.post("/items/", response_model=list[Item])
| ^^^^^^^^^^^^^^^^^^^^^^^^^
23 | async def create_item(item: Item) -> list[Item]:
24 | return item
|
help: Remove argument
19 | return item
20 |
21 |
- @app.post("/items/", response_model=list[Item])
22 + @app.post("/items/")
23 | async def create_item(item: Item) -> list[Item]:
24 | return item
25 |
note: This is an unsafe fix and may change runtime behavior
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:27:22
|
27 | @app.post("/items/", response_model=List[Item])
| ^^^^^^^^^^^^^^^^^^^^^^^^^
28 | async def create_item(item: Item) -> List[Item]:
29 | return item
|
help: Remove argument
24 | return item
25 |
26 |
- @app.post("/items/", response_model=List[Item])
27 + @app.post("/items/")
28 | async def create_item(item: Item) -> List[Item]:
29 | return item
30 |
note: This is an unsafe fix and may change runtime behavior
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:32:22
|
32 | @app.post("/items/", response_model=Dict[str, Item])
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
33 | async def create_item(item: Item) -> Dict[str, Item]:
34 | return item
|
help: Remove argument
29 | return item
30 |
31 |
- @app.post("/items/", response_model=Dict[str, Item])
32 + @app.post("/items/")
33 | async def create_item(item: Item) -> Dict[str, Item]:
34 | return item
35 |
note: This is an unsafe fix and may change runtime behavior
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:37:22
|
37 | @app.post("/items/", response_model=str)
| ^^^^^^^^^^^^^^^^^^
38 | async def create_item(item: Item) -> str:
39 | return item
|
help: Remove argument
34 | return item
35 |
36 |
- @app.post("/items/", response_model=str)
37 + @app.post("/items/")
38 | async def create_item(item: Item) -> str:
39 | return item
40 |
note: This is an unsafe fix and may change runtime behavior
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:42:21
|
42 | @app.get("/items/", response_model=Item)
| ^^^^^^^^^^^^^^^^^^^
43 | async def create_item(item: Item) -> Item:
44 | return item
|
help: Remove argument
39 | return item
40 |
41 |
- @app.get("/items/", response_model=Item)
42 + @app.get("/items/")
43 | async def create_item(item: Item) -> Item:
44 | return item
45 |
note: This is an unsafe fix and may change runtime behavior
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:47:21
|
47 | @app.get("/items/", response_model=Item)
| ^^^^^^^^^^^^^^^^^^^
48 | @app.post("/items/", response_model=Item)
49 | async def create_item(item: Item) -> Item:
|
help: Remove argument
44 | return item
45 |
46 |
- @app.get("/items/", response_model=Item)
47 + @app.get("/items/")
48 | @app.post("/items/", response_model=Item)
49 | async def create_item(item: Item) -> Item:
50 | return item
note: This is an unsafe fix and may change runtime behavior
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:48:22
|
47 | @app.get("/items/", response_model=Item)
48 | @app.post("/items/", response_model=Item)
| ^^^^^^^^^^^^^^^^^^^
49 | async def create_item(item: Item) -> Item:
50 | return item
|
help: Remove argument
45 |
46 |
47 | @app.get("/items/", response_model=Item)
- @app.post("/items/", response_model=Item)
48 + @app.post("/items/")
49 | async def create_item(item: Item) -> Item:
50 | return item
51 |
note: This is an unsafe fix and may change runtime behavior
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:53:24
|
53 | @router.get("/items/", response_model=Item)
| ^^^^^^^^^^^^^^^^^^^
54 | async def create_item(item: Item) -> Item:
55 | return item
|
help: Remove argument
50 | return item
51 |
52 |
- @router.get("/items/", response_model=Item)
53 + @router.get("/items/")
54 | async def create_item(item: Item) -> Item:
55 | return item
56 |
note: This is an unsafe fix and may change runtime behavior
FAST001 [*] FastAPI route with redundant `response_model` argument
--> FAST001.py:118:23
|
116 | def setup_app(app_arg: FastAPI, non_app: str) -> None:
117 | # Error
118 | @app_arg.get("/", response_model=str)
| ^^^^^^^^^^^^^^^^^^
119 | async def get_root() -> str:
120 | return "Hello World!"
|
help: Remove argument
115 |
116 | def setup_app(app_arg: FastAPI, non_app: str) -> None:
117 | # Error
- @app_arg.get("/", response_model=str)
118 + @app_arg.get("/")
119 | async def get_root() -> str:
120 | return "Hello World!"
121 |
note: This is an unsafe fix and may change runtime behavior

View File

@@ -324,6 +324,26 @@ help: Add `name` to function signature
91 |
note: This is an unsafe fix and may change runtime behavior
FAST003 [*] Parameter `thing_id` appears in route path, but not in `single` signature
--> FAST003.py:158:19
|
157 | ### Errors
158 | @app.get("/things/{thing_id}")
| ^^^^^^^^^^
159 | async def single(other: Annotated[str, Depends(something_else)]): ...
160 | @app.get("/things/{thing_id}")
|
help: Add `thing_id` to function signature
156 |
157 | ### Errors
158 | @app.get("/things/{thing_id}")
- async def single(other: Annotated[str, Depends(something_else)]): ...
159 + async def single(other: Annotated[str, Depends(something_else)], thing_id): ...
160 | @app.get("/things/{thing_id}")
161 | async def default(other: str = Depends(something_else)): ...
162 |
note: This is an unsafe fix and may change runtime behavior
FAST003 [*] Parameter `thing_id` appears in route path, but not in `default` signature
--> FAST003.py:160:19
|
@@ -344,6 +364,47 @@ help: Add `thing_id` to function signature
164 | ### No errors
note: This is an unsafe fix and may change runtime behavior
FAST003 [*] Parameter `id` appears in route path, but not in `get_id_pydantic_full` signature
--> FAST003.py:197:12
|
196 | # Errors
197 | @app.get("/{id}")
| ^^^^
198 | async def get_id_pydantic_full(
199 | params: Annotated[PydanticParams, Depends(PydanticParams)],
|
help: Add `id` to function signature
196 | # Errors
197 | @app.get("/{id}")
198 | async def get_id_pydantic_full(
- params: Annotated[PydanticParams, Depends(PydanticParams)],
199 + params: Annotated[PydanticParams, Depends(PydanticParams)], id,
200 | ): ...
201 | @app.get("/{id}")
202 | async def get_id_pydantic_short(params: Annotated[PydanticParams, Depends()]): ...
note: This is an unsafe fix and may change runtime behavior
FAST003 [*] Parameter `id` appears in route path, but not in `get_id_pydantic_short` signature
--> FAST003.py:201:12
|
199 | params: Annotated[PydanticParams, Depends(PydanticParams)],
200 | ): ...
201 | @app.get("/{id}")
| ^^^^
202 | async def get_id_pydantic_short(params: Annotated[PydanticParams, Depends()]): ...
203 | @app.get("/{id}")
|
help: Add `id` to function signature
199 | params: Annotated[PydanticParams, Depends(PydanticParams)],
200 | ): ...
201 | @app.get("/{id}")
- async def get_id_pydantic_short(params: Annotated[PydanticParams, Depends()]): ...
202 + async def get_id_pydantic_short(params: Annotated[PydanticParams, Depends()], id): ...
203 | @app.get("/{id}")
204 | async def get_id_init_not_annotated(params = Depends(InitParams)): ...
205 |
note: This is an unsafe fix and may change runtime behavior
FAST003 [*] Parameter `id` appears in route path, but not in `get_id_init_not_annotated` signature
--> FAST003.py:203:12
|

View File

@@ -34,10 +34,9 @@ use crate::{AlwaysFixableViolation, Applicability, Fix};
/// ```
///
/// ## Fix safety
/// This rule's fix is marked as unsafe. While adding `strict=False` preserves
/// the runtime behavior, it can obscure situations where the iterables are of
/// unequal length. Ruff prefers to alert users so they can choose the intended
/// behavior themselves.
/// This rule's fix is marked as unsafe for `map` calls that contain
/// `**kwargs`, as adding a `strict` keyword argument to such a call may lead
/// to a duplicate keyword argument error.
///
/// ## References
/// - [Python documentation: `map`](https://docs.python.org/3/library/functions.html#map)
@@ -74,7 +73,17 @@ pub(crate) fn map_without_explicit_strict(checker: &Checker, call: &ast::ExprCal
checker.comment_ranges(),
checker.locator().contents(),
),
Applicability::Unsafe,
// If the function call contains `**kwargs`, mark the fix as unsafe.
if call
.arguments
.keywords
.iter()
.any(|keyword| keyword.arg.is_none())
{
Applicability::Unsafe
} else {
Applicability::Safe
},
));
}
}

View File

@@ -31,10 +31,9 @@ use crate::{AlwaysFixableViolation, Applicability, Fix};
/// ```
///
/// ## Fix safety
/// This rule's fix is marked as unsafe. While adding `strict=False` preserves
/// the runtime behavior, it can obscure situations where the iterables are of
/// unequal length. Ruff prefers to alert users so they can choose the intended
/// behavior themselves.
/// This rule's fix is marked as unsafe for `zip` calls that contain
/// `**kwargs`, as adding a `strict` keyword argument to such a call may lead
/// to a duplicate keyword argument error.
///
/// ## References
/// - [Python documentation: `zip`](https://docs.python.org/3/library/functions.html#zip)
@@ -69,7 +68,17 @@ pub(crate) fn zip_without_explicit_strict(checker: &Checker, call: &ast::ExprCal
checker.comment_ranges(),
checker.locator().contents(),
),
Applicability::Unsafe,
// If the function call contains `**kwargs`, mark the fix as unsafe.
if call
.arguments
.keywords
.iter()
.any(|keyword| keyword.arg.is_none())
{
Applicability::Unsafe
} else {
Applicability::Safe
},
));
}
}

View File

@@ -1,6 +1,5 @@
---
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
assertion_line: 156
---
B905 [*] `zip()` without an explicit `strict=` parameter
--> B905.py:4:1
@@ -20,7 +19,6 @@ help: Add explicit value for parameter `strict=`
5 | zip(range(3))
6 | zip("a", "b")
7 | zip("a", "b", *zip("c"))
note: This is an unsafe fix and may change runtime behavior
B905 [*] `zip()` without an explicit `strict=` parameter
--> B905.py:5:1
@@ -41,7 +39,6 @@ help: Add explicit value for parameter `strict=`
6 | zip("a", "b")
7 | zip("a", "b", *zip("c"))
8 | zip(zip("a"), strict=False)
note: This is an unsafe fix and may change runtime behavior
B905 [*] `zip()` without an explicit `strict=` parameter
--> B905.py:6:1
@@ -62,7 +59,6 @@ help: Add explicit value for parameter `strict=`
7 | zip("a", "b", *zip("c"))
8 | zip(zip("a"), strict=False)
9 | zip(zip("a", strict=True))
note: This is an unsafe fix and may change runtime behavior
B905 [*] `zip()` without an explicit `strict=` parameter
--> B905.py:7:1
@@ -83,7 +79,6 @@ help: Add explicit value for parameter `strict=`
8 | zip(zip("a"), strict=False)
9 | zip(zip("a", strict=True))
10 |
note: This is an unsafe fix and may change runtime behavior
B905 [*] `zip()` without an explicit `strict=` parameter
--> B905.py:7:16
@@ -104,7 +99,6 @@ help: Add explicit value for parameter `strict=`
8 | zip(zip("a"), strict=False)
9 | zip(zip("a", strict=True))
10 |
note: This is an unsafe fix and may change runtime behavior
B905 [*] `zip()` without an explicit `strict=` parameter
--> B905.py:8:5
@@ -124,7 +118,6 @@ help: Add explicit value for parameter `strict=`
9 | zip(zip("a", strict=True))
10 |
11 | # OK
note: This is an unsafe fix and may change runtime behavior
B905 [*] `zip()` without an explicit `strict=` parameter
--> B905.py:9:1
@@ -145,7 +138,6 @@ help: Add explicit value for parameter `strict=`
10 |
11 | # OK
12 | zip(range(3), strict=True)
note: This is an unsafe fix and may change runtime behavior
B905 [*] `zip()` without an explicit `strict=` parameter
--> B905.py:24:1
@@ -164,7 +156,6 @@ help: Add explicit value for parameter `strict=`
25 | zip([1, 2, 3], repeat(1, times=4))
26 |
27 | import builtins
note: This is an unsafe fix and may change runtime behavior
B905 [*] `zip()` without an explicit `strict=` parameter
--> B905.py:25:1
@@ -185,7 +176,6 @@ help: Add explicit value for parameter `strict=`
26 |
27 | import builtins
28 | # Still an error even though it uses the qualified name
note: This is an unsafe fix and may change runtime behavior
B905 [*] `zip()` without an explicit `strict=` parameter
--> B905.py:29:1
@@ -201,4 +191,3 @@ help: Add explicit value for parameter `strict=`
28 | # Still an error even though it uses the qualified name
- builtins.zip([1, 2, 3])
29 + builtins.zip([1, 2, 3], strict=False)
note: This is an unsafe fix and may change runtime behavior

View File

@@ -1,6 +1,5 @@
---
source: crates/ruff_linter/src/rules/flake8_bugbear/mod.rs
assertion_line: 112
---
B912 [*] `map()` without an explicit `strict=` parameter
--> B912.py:5:1
@@ -21,7 +20,6 @@ help: Add explicit value for parameter `strict=`
6 | map(lambda x, y, z: x + y + z, [1, 2, 3], [4, 5, 6], [7, 8, 9])
7 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]))
8 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]), strict=False)
note: This is an unsafe fix and may change runtime behavior
B912 [*] `map()` without an explicit `strict=` parameter
--> B912.py:6:1
@@ -42,7 +40,6 @@ help: Add explicit value for parameter `strict=`
7 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]))
8 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9]), strict=False)
9 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9], strict=True))
note: This is an unsafe fix and may change runtime behavior
B912 [*] `map()` without an explicit `strict=` parameter
--> B912.py:7:1
@@ -64,7 +61,6 @@ help: Add explicit value for parameter `strict=`
9 | map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6], *map(lambda x: x, [7, 8, 9], strict=True))
10 |
11 | # Errors (limited iterators).
note: This is an unsafe fix and may change runtime behavior
B912 [*] `map()` without an explicit `strict=` parameter
--> B912.py:9:1
@@ -85,7 +81,6 @@ help: Add explicit value for parameter `strict=`
10 |
11 | # Errors (limited iterators).
12 | map(lambda x, y: x + y, [1, 2, 3], repeat(1, 1))
note: This is an unsafe fix and may change runtime behavior
B912 [*] `map()` without an explicit `strict=` parameter
--> B912.py:12:1
@@ -104,7 +99,6 @@ help: Add explicit value for parameter `strict=`
13 | map(lambda x, y: x + y, [1, 2, 3], repeat(1, times=4))
14 |
15 | import builtins
note: This is an unsafe fix and may change runtime behavior
B912 [*] `map()` without an explicit `strict=` parameter
--> B912.py:13:1
@@ -125,7 +119,6 @@ help: Add explicit value for parameter `strict=`
14 |
15 | import builtins
16 | # Still an error even though it uses the qualified name
note: This is an unsafe fix and may change runtime behavior
B912 [*] `map()` without an explicit `strict=` parameter
--> B912.py:17:1
@@ -146,4 +139,3 @@ help: Add explicit value for parameter `strict=`
18 |
19 | # OK
20 | map(lambda x: x, [1, 2, 3], strict=True)
note: This is an unsafe fix and may change runtime behavior

View File

@@ -10,12 +10,12 @@ mod tests {
use anyhow::Result;
use test_case::test_case;
use crate::assert_diagnostics;
use crate::registry::Rule;
use crate::rules::flake8_builtins;
use crate::settings::LinterSettings;
use crate::settings::types::PreviewMode;
use crate::test::{test_path, test_resource_path};
use crate::{assert_diagnostics, assert_diagnostics_diff};
use ruff_python_ast::PythonVersion;
#[test_case(Rule::BuiltinVariableShadowing, Path::new("A001.py"))]
@@ -64,28 +64,6 @@ mod tests {
Ok(())
}
#[test_case(Rule::BuiltinAttributeShadowing, Path::new("A003.py"))]
fn deferred_annotations_diff(rule_code: Rule, path: &Path) -> Result<()> {
let snapshot = format!(
"deferred_annotations_diff_{}_{}",
rule_code.name(),
path.to_string_lossy()
);
assert_diagnostics_diff!(
snapshot,
Path::new("flake8_builtins").join(path).as_path(),
&LinterSettings {
unresolved_target_version: PythonVersion::PY313.into(),
..LinterSettings::for_rule(rule_code)
},
&LinterSettings {
unresolved_target_version: PythonVersion::PY314.into(),
..LinterSettings::for_rule(rule_code)
},
);
Ok(())
}
#[test_case(Rule::BuiltinAttributeShadowing, Path::new("A003.py"))]
fn preview_rules(rule_code: Rule, path: &Path) -> Result<()> {
let snapshot = format!(

View File

@@ -1,4 +1,22 @@
---
source: crates/ruff_linter/src/rules/flake8_builtins/mod.rs
---
A003 Python builtin is shadowed by method `str` from line 14
--> A003.py:17:31
|
15 | pass
16 |
17 | def method_usage(self) -> str:
| ^^^
18 | pass
|
A003 Python builtin is shadowed by class attribute `id` from line 3
--> A003.py:20:34
|
18 | pass
19 |
20 | def attribute_usage(self) -> id:
| ^^
21 | pass
|

View File

@@ -1,4 +1,12 @@
---
source: crates/ruff_linter/src/rules/flake8_builtins/mod.rs
---
A003 Python builtin is shadowed by method `str` from line 14
--> A003.py:17:31
|
15 | pass
16 |
17 | def method_usage(self) -> str:
| ^^^
18 | pass
|

View File

@@ -1,32 +0,0 @@
---
source: crates/ruff_linter/src/rules/flake8_builtins/mod.rs
---
--- Linter settings ---
-linter.unresolved_target_version = 3.13
+linter.unresolved_target_version = 3.14
--- Summary ---
Removed: 2
Added: 0
--- Removed ---
A003 Python builtin is shadowed by method `str` from line 14
--> A003.py:17:31
|
15 | pass
16 |
17 | def method_usage(self) -> str:
| ^^^
18 | pass
|
A003 Python builtin is shadowed by class attribute `id` from line 3
--> A003.py:20:34
|
18 | pass
19 |
20 | def attribute_usage(self) -> id:
| ^^
21 | pass
|

View File

@@ -1,6 +1,26 @@
---
source: crates/ruff_linter/src/rules/flake8_builtins/mod.rs
---
A003 Python builtin is shadowed by method `str` from line 14
--> A003.py:17:31
|
15 | pass
16 |
17 | def method_usage(self) -> str:
| ^^^
18 | pass
|
A003 Python builtin is shadowed by class attribute `id` from line 3
--> A003.py:20:34
|
18 | pass
19 |
20 | def attribute_usage(self) -> id:
| ^^
21 | pass
|
A003 Python builtin is shadowed by method `property` from line 26
--> A003.py:31:7
|

View File

@@ -1,196 +1,6 @@
---
source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs
---
PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[int | str | complex]`.
--> PYI055.py:4:4
|
2 | from typing import Union
3 |
4 | s: builtins.type[int] | builtins.type[str] | builtins.type[complex]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5 | t: type[int] | type[str] | type[float]
6 | u: builtins.type[int] | type[str] | builtins.type[complex]
|
help: Combine multiple `type` members
1 | import builtins
2 | from typing import Union
3 |
- s: builtins.type[int] | builtins.type[str] | builtins.type[complex]
4 + s: type[int | str | complex]
5 | t: type[int] | type[str] | type[float]
6 | u: builtins.type[int] | type[str] | builtins.type[complex]
7 | v: Union[type[float], type[complex]]
PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[int | str | float]`.
--> PYI055.py:5:4
|
4 | s: builtins.type[int] | builtins.type[str] | builtins.type[complex]
5 | t: type[int] | type[str] | type[float]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6 | u: builtins.type[int] | type[str] | builtins.type[complex]
7 | v: Union[type[float], type[complex]]
|
help: Combine multiple `type` members
2 | from typing import Union
3 |
4 | s: builtins.type[int] | builtins.type[str] | builtins.type[complex]
- t: type[int] | type[str] | type[float]
5 + t: type[int | str | float]
6 | u: builtins.type[int] | type[str] | builtins.type[complex]
7 | v: Union[type[float], type[complex]]
8 | w: Union[type[float | int], type[complex]]
PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[int | str | complex]`.
--> PYI055.py:6:4
|
4 | s: builtins.type[int] | builtins.type[str] | builtins.type[complex]
5 | t: type[int] | type[str] | type[float]
6 | u: builtins.type[int] | type[str] | builtins.type[complex]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7 | v: Union[type[float], type[complex]]
8 | w: Union[type[float | int], type[complex]]
|
help: Combine multiple `type` members
3 |
4 | s: builtins.type[int] | builtins.type[str] | builtins.type[complex]
5 | t: type[int] | type[str] | type[float]
- u: builtins.type[int] | type[str] | builtins.type[complex]
6 + u: type[int | str | complex]
7 | v: Union[type[float], type[complex]]
8 | w: Union[type[float | int], type[complex]]
9 | x: Union[Union[type[Union[float, int]], type[complex]]]
PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[Union[float, complex]]`.
--> PYI055.py:7:4
|
5 | t: type[int] | type[str] | type[float]
6 | u: builtins.type[int] | type[str] | builtins.type[complex]
7 | v: Union[type[float], type[complex]]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8 | w: Union[type[float | int], type[complex]]
9 | x: Union[Union[type[Union[float, int]], type[complex]]]
|
help: Combine multiple `type` members
4 | s: builtins.type[int] | builtins.type[str] | builtins.type[complex]
5 | t: type[int] | type[str] | type[float]
6 | u: builtins.type[int] | type[str] | builtins.type[complex]
- v: Union[type[float], type[complex]]
7 + v: type[Union[float, complex]]
8 | w: Union[type[float | int], type[complex]]
9 | x: Union[Union[type[Union[float, int]], type[complex]]]
10 | y: Union[Union[Union[type[float | int], type[complex]]]]
PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[Union[float | int, complex]]`.
--> PYI055.py:8:4
|
6 | u: builtins.type[int] | type[str] | builtins.type[complex]
7 | v: Union[type[float], type[complex]]
8 | w: Union[type[float | int], type[complex]]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9 | x: Union[Union[type[Union[float, int]], type[complex]]]
10 | y: Union[Union[Union[type[float | int], type[complex]]]]
|
help: Combine multiple `type` members
5 | t: type[int] | type[str] | type[float]
6 | u: builtins.type[int] | type[str] | builtins.type[complex]
7 | v: Union[type[float], type[complex]]
- w: Union[type[float | int], type[complex]]
8 + w: type[Union[float | int, complex]]
9 | x: Union[Union[type[Union[float, int]], type[complex]]]
10 | y: Union[Union[Union[type[float | int], type[complex]]]]
11 | z: Union[type[complex], Union[Union[type[Union[float, int]]]]]
PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[Union[Union[float, int], complex]]`.
--> PYI055.py:9:4
|
7 | v: Union[type[float], type[complex]]
8 | w: Union[type[float | int], type[complex]]
9 | x: Union[Union[type[Union[float, int]], type[complex]]]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
10 | y: Union[Union[Union[type[float | int], type[complex]]]]
11 | z: Union[type[complex], Union[Union[type[Union[float, int]]]]]
|
help: Combine multiple `type` members
6 | u: builtins.type[int] | type[str] | builtins.type[complex]
7 | v: Union[type[float], type[complex]]
8 | w: Union[type[float | int], type[complex]]
- x: Union[Union[type[Union[float, int]], type[complex]]]
9 + x: type[Union[Union[float, int], complex]]
10 | y: Union[Union[Union[type[float | int], type[complex]]]]
11 | z: Union[type[complex], Union[Union[type[Union[float, int]]]]]
12 |
PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[Union[float | int, complex]]`.
--> PYI055.py:10:4
|
8 | w: Union[type[float | int], type[complex]]
9 | x: Union[Union[type[Union[float, int]], type[complex]]]
10 | y: Union[Union[Union[type[float | int], type[complex]]]]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
11 | z: Union[type[complex], Union[Union[type[Union[float, int]]]]]
|
help: Combine multiple `type` members
7 | v: Union[type[float], type[complex]]
8 | w: Union[type[float | int], type[complex]]
9 | x: Union[Union[type[Union[float, int]], type[complex]]]
- y: Union[Union[Union[type[float | int], type[complex]]]]
10 + y: type[Union[float | int, complex]]
11 | z: Union[type[complex], Union[Union[type[Union[float, int]]]]]
12 |
13 |
PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[Union[complex, Union[float, int]]]`.
--> PYI055.py:11:4
|
9 | x: Union[Union[type[Union[float, int]], type[complex]]]
10 | y: Union[Union[Union[type[float | int], type[complex]]]]
11 | z: Union[type[complex], Union[Union[type[Union[float, int]]]]]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: Combine multiple `type` members
8 | w: Union[type[float | int], type[complex]]
9 | x: Union[Union[type[Union[float, int]], type[complex]]]
10 | y: Union[Union[Union[type[float | int], type[complex]]]]
- z: Union[type[complex], Union[Union[type[Union[float, int]]]]]
11 + z: type[Union[complex, Union[float, int]]]
12 |
13 |
14 | def func(arg: type[int] | str | type[float]) -> None:
PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[int | float]`.
--> PYI055.py:14:15
|
14 | def func(arg: type[int] | str | type[float]) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15 | ...
|
help: Combine multiple `type` members
11 | z: Union[type[complex], Union[Union[type[Union[float, int]]]]]
12 |
13 |
- def func(arg: type[int] | str | type[float]) -> None:
14 + def func(arg: type[int | float] | str) -> None:
15 | ...
16 |
17 |
PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[requests_mock.Mocker | httpretty]`.
--> PYI055.py:29:7
|
28 | # OK
29 | item: type[requests_mock.Mocker] | type[httpretty] = requests_mock.Mocker
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: Combine multiple `type` members
26 |
27 |
28 | # OK
- item: type[requests_mock.Mocker] | type[httpretty] = requests_mock.Mocker
29 + item: type[requests_mock.Mocker | httpretty] = requests_mock.Mocker
30 |
31 |
32 | def func():
PYI055 [*] Multiple `type` members in a union. Combine them into one, e.g., `type[requests_mock.Mocker | httpretty | str]`.
--> PYI055.py:34:8
|

View File

@@ -11,17 +11,18 @@ TC003 [*] Move standard library import `collections.Counter` into a type-checkin
|
help: Move into type-checking block
- from collections import Counter
1 |
2 | from elsewhere import third_party
3 |
4 | from . import first_party
5 + from typing import TYPE_CHECKING
6 +
7 + if TYPE_CHECKING:
8 + from collections import Counter
9 |
1 + from __future__ import annotations
2 |
3 | from elsewhere import third_party
4 |
5 | from . import first_party
6 + from typing import TYPE_CHECKING
7 +
8 + if TYPE_CHECKING:
9 + from collections import Counter
10 |
11 | def f(x: first_party.foo): ...
11 |
12 | def f(x: first_party.foo): ...
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `elsewhere.third_party` into a type-checking block
@@ -35,18 +36,19 @@ TC002 [*] Move third-party import `elsewhere.third_party` into a type-checking b
5 | from . import first_party
|
help: Move into type-checking block
1 | from collections import Counter
2 |
- from elsewhere import third_party
1 + from __future__ import annotations
2 | from collections import Counter
3 |
4 | from . import first_party
5 + from typing import TYPE_CHECKING
6 +
7 + if TYPE_CHECKING:
8 + from elsewhere import third_party
9 |
- from elsewhere import third_party
4 |
5 | from . import first_party
6 + from typing import TYPE_CHECKING
7 +
8 + if TYPE_CHECKING:
9 + from elsewhere import third_party
10 |
11 | def f(x: first_party.foo): ...
11 |
12 | def f(x: first_party.foo): ...
note: This is an unsafe fix and may change runtime behavior
TC001 [*] Move application import `.first_party` into a type-checking block
@@ -58,15 +60,17 @@ TC001 [*] Move application import `.first_party` into a type-checking block
| ^^^^^^^^^^^
|
help: Move into type-checking block
2 |
3 | from elsewhere import third_party
4 |
1 + from __future__ import annotations
2 | from collections import Counter
3 |
4 | from elsewhere import third_party
5 |
- from . import first_party
5 + from typing import TYPE_CHECKING
6 +
7 + if TYPE_CHECKING:
8 + from . import first_party
9 |
6 + from typing import TYPE_CHECKING
7 +
8 + if TYPE_CHECKING:
9 + from . import first_party
10 |
11 | def f(x: first_party.foo): ...
11 |
12 | def f(x: first_party.foo): ...
note: This is an unsafe fix and may change runtime behavior

View File

@@ -12,14 +12,15 @@ TC001 [*] Move application import `.first_party` into a type-checking block
|
help: Move into type-checking block
- def f():
1 + from typing import TYPE_CHECKING
2 +
3 + if TYPE_CHECKING:
4 | from . import first_party
5 + def f():
6 |
7 | def f(x: first_party.foo): ...
8 |
1 + from __future__ import annotations
2 + from typing import TYPE_CHECKING
3 +
4 + if TYPE_CHECKING:
5 | from . import first_party
6 + def f():
7 |
8 | def f(x: first_party.foo): ...
9 |
note: This is an unsafe fix and may change runtime behavior
TC001 [*] Move application import `.foo` into a type-checking block
@@ -32,19 +33,24 @@ TC001 [*] Move application import `.foo` into a type-checking block
59 | def f(x: Union[foo.Ty, int]): ...
|
help: Move into type-checking block
50 |
1 + from __future__ import annotations
2 | def f():
3 | from . import first_party
4 |
--------------------------------------------------------------------------------
51 |
52 | # unions
52 |
53 | # unions
- from typing import Union
53 + from typing import Union, TYPE_CHECKING
54 +
55 + if TYPE_CHECKING:
56 + from . import foo
57 |
58 |
59 | def n():
54 + from typing import Union, TYPE_CHECKING
55 |
56 + if TYPE_CHECKING:
57 + from . import foo
58 +
59 |
60 | def n():
- from . import foo
60 |
61 | def f(x: Union[foo.Ty, int]): ...
62 | def g(x: foo.Ty | int): ...
61 |
62 | def f(x: Union[foo.Ty, int]): ...
63 | def g(x: foo.Ty | int): ...
note: This is an unsafe fix and may change runtime behavior

View File

@@ -220,3 +220,32 @@ help: Move into type-checking block
52 | x = dict["pd.DataFrame", "pd.DataFrame"]
53 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `module.Member` into a type-checking block
--> TC002.py:172:24
|
170 | global Member
171 |
172 | from module import Member
| ^^^^^^
173 |
174 | x: Member = 1
|
help: Move into type-checking block
1 | """Tests to determine accurate detection of typing-only imports."""
2 + from typing import TYPE_CHECKING
3 +
4 + if TYPE_CHECKING:
5 + from module import Member
6 |
7 |
8 | def f():
--------------------------------------------------------------------------------
173 | def f():
174 | global Member
175 |
- from module import Member
176 |
177 | x: Member = 1
178 |
note: This is an unsafe fix and may change runtime behavior

View File

@@ -1,6 +1,26 @@
---
source: crates/ruff_linter/src/rules/flake8_type_checking/mod.rs
---
TC004 [*] Quote references to `pandas.DataFrame`. Import is in a type-checking block.
--> quote.py:57:28
|
56 | if TYPE_CHECKING:
57 | from pandas import DataFrame
| ^^^^^^^^^
58 |
59 | def func(value: DataFrame):
|
help: Quote references
56 | if TYPE_CHECKING:
57 | from pandas import DataFrame
58 |
- def func(value: DataFrame):
59 + def func(value: "DataFrame"):
60 | ...
61 |
62 |
note: This is an unsafe fix and may change runtime behavior
TC004 [*] Move import `pandas.DataFrame` out of type-checking block. Import is used for more than type hinting.
--> quote.py:110:28
|

View File

@@ -11,15 +11,18 @@ TC002 [*] Move third-party import `pandas.DataFrame` into a type-checking block
4 | def baz() -> DataFrame:
|
help: Move into type-checking block
- def f():
1 + from typing import TYPE_CHECKING
2 +
3 + if TYPE_CHECKING:
4 | from pandas import DataFrame
5 + def f():
6 |
7 | def baz() -> DataFrame:
8 | ...
- def f():
1 + from typing import TYPE_CHECKING
2 +
3 + if TYPE_CHECKING:
4 | from pandas import DataFrame
5 + def f():
6 |
- def baz() -> DataFrame:
7 + def baz() -> "DataFrame":
8 | ...
9 |
10 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas.DataFrame` into a type-checking block
@@ -45,8 +48,11 @@ help: Move into type-checking block
12 | def f():
- from pandas import DataFrame
13 |
14 | def baz() -> DataFrame[int]:
- def baz() -> DataFrame[int]:
14 + def baz() -> "DataFrame[int]":
15 | ...
16 |
17 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas` into a type-checking block
@@ -72,8 +78,11 @@ help: Move into type-checking block
19 | def f():
- import pandas as pd
20 |
21 | def baz() -> pd.DataFrame:
- def baz() -> pd.DataFrame:
21 + def baz() -> "pd.DataFrame":
22 | ...
23 |
24 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas` into a type-checking block
@@ -99,8 +108,11 @@ help: Move into type-checking block
26 | def f():
- import pandas as pd
27 |
28 | def baz() -> pd.DataFrame.Extra:
- def baz() -> pd.DataFrame.Extra:
28 + def baz() -> "pd.DataFrame.Extra":
29 | ...
30 |
31 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas` into a type-checking block
@@ -126,8 +138,11 @@ help: Move into type-checking block
33 | def f():
- import pandas as pd
34 |
35 | def baz() -> pd.DataFrame | int:
- def baz() -> pd.DataFrame | int:
35 + def baz() -> "pd.DataFrame | int":
36 | ...
37 |
38 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas.DataFrame` into a type-checking block
@@ -153,8 +168,11 @@ help: Move into type-checking block
41 | def f():
- from pandas import DataFrame
42 |
43 | def baz() -> DataFrame():
- def baz() -> DataFrame():
43 + def baz() -> "DataFrame()":
44 | ...
45 |
46 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas.DataFrame` into a type-checking block
@@ -181,8 +199,11 @@ help: Move into type-checking block
50 |
- from pandas import DataFrame
51 |
52 | def baz() -> DataFrame[Literal["int"]]:
- def baz() -> DataFrame[Literal["int"]]:
52 + def baz() -> "DataFrame[Literal['int']]":
53 | ...
54 |
55 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas.DataFrame` into a type-checking block
@@ -208,8 +229,11 @@ help: Move into type-checking block
67 | def f():
- from pandas import DataFrame, Series
68 |
69 | def baz() -> DataFrame | Series:
- def baz() -> DataFrame | Series:
69 + def baz() -> "DataFrame | Series":
70 | ...
71 |
72 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas.Series` into a type-checking block
@@ -235,8 +259,11 @@ help: Move into type-checking block
67 | def f():
- from pandas import DataFrame, Series
68 |
69 | def baz() -> DataFrame | Series:
- def baz() -> DataFrame | Series:
69 + def baz() -> "DataFrame | Series":
70 | ...
71 |
72 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas.DataFrame` into a type-checking block
@@ -263,7 +290,23 @@ help: Move into type-checking block
- from pandas import DataFrame, Series
75 |
76 | def baz() -> (
77 | DataFrame |
- DataFrame |
- Series
77 + "DataFrame | Series"
78 | ):
79 | ...
80 |
81 | class C:
- x: DataFrame[
- int
- ] = 1
82 + x: "DataFrame[int]" = 1
83 |
- def func() -> DataFrame[[DataFrame[_P, _R]], DataFrame[_P, _R]]:
84 + def func() -> "DataFrame[[DataFrame[_P, _R]], DataFrame[_P, _R]]":
85 | ...
86 |
87 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas.Series` into a type-checking block
@@ -290,7 +333,23 @@ help: Move into type-checking block
- from pandas import DataFrame, Series
75 |
76 | def baz() -> (
77 | DataFrame |
- DataFrame |
- Series
77 + "DataFrame | Series"
78 | ):
79 | ...
80 |
81 | class C:
- x: DataFrame[
- int
- ] = 1
82 + x: "DataFrame[int]" = 1
83 |
- def func() -> DataFrame[[DataFrame[_P, _R]], DataFrame[_P, _R]]:
84 + def func() -> "DataFrame[[DataFrame[_P, _R]], DataFrame[_P, _R]]":
85 | ...
86 |
87 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas.DataFrame` into a type-checking block
@@ -316,8 +375,11 @@ help: Move into type-checking block
92 | def f():
- from pandas import DataFrame, Series
93 |
94 | def func(self) -> DataFrame | list[Series]:
- def func(self) -> DataFrame | list[Series]:
94 + def func(self) -> "DataFrame | list[Series]":
95 | pass
96 |
97 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas.Series` into a type-checking block
@@ -343,6 +405,9 @@ help: Move into type-checking block
92 | def f():
- from pandas import DataFrame, Series
93 |
94 | def func(self) -> DataFrame | list[Series]:
- def func(self) -> DataFrame | list[Series]:
94 + def func(self) -> "DataFrame | list[Series]":
95 | pass
96 |
97 |
note: This is an unsafe fix and may change runtime behavior

View File

@@ -11,15 +11,18 @@ TC002 [*] Move third-party import `django.contrib.auth.models.AbstractBaseUser`
4 | def test_remove_inner_quotes_double(self, user: AbstractBaseUser["int"]):
|
help: Move into type-checking block
- def f():
1 + from typing import TYPE_CHECKING
2 +
3 + if TYPE_CHECKING:
4 | from django.contrib.auth.models import AbstractBaseUser
5 + def f():
6 |
7 | def test_remove_inner_quotes_double(self, user: AbstractBaseUser["int"]):
8 | pass
- def f():
1 + from typing import TYPE_CHECKING
2 +
3 + if TYPE_CHECKING:
4 | from django.contrib.auth.models import AbstractBaseUser
5 + def f():
6 |
- def test_remove_inner_quotes_double(self, user: AbstractBaseUser["int"]):
7 + def test_remove_inner_quotes_double(self, user: "AbstractBaseUser[int]"):
8 | pass
9 |
10 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `django.contrib.auth.models.AbstractBaseUser` into a type-checking block
@@ -45,8 +48,11 @@ help: Move into type-checking block
12 | def f():
- from django.contrib.auth.models import AbstractBaseUser
13 |
14 | def test_remove_inner_quotes_single(self, user: AbstractBaseUser['int']):
- def test_remove_inner_quotes_single(self, user: AbstractBaseUser['int']):
14 + def test_remove_inner_quotes_single(self, user: "AbstractBaseUser[int]"):
15 | pass
16 |
17 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `django.contrib.auth.models.AbstractBaseUser` into a type-checking block
@@ -72,8 +78,11 @@ help: Move into type-checking block
19 | def f():
- from django.contrib.auth.models import AbstractBaseUser
20 |
21 | def test_remove_inner_quotes_mixed(self, user: AbstractBaseUser['int', "str"]):
- def test_remove_inner_quotes_mixed(self, user: AbstractBaseUser['int', "str"]):
21 + def test_remove_inner_quotes_mixed(self, user: "AbstractBaseUser[int, str]"):
22 | pass
23 |
24 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `django.contrib.auth.models.AbstractBaseUser` into a type-checking block
@@ -100,8 +109,11 @@ help: Move into type-checking block
28 |
- from django.contrib.auth.models import AbstractBaseUser
29 |
30 | def test_literal_annotation_args_contain_quotes(self, type1: AbstractBaseUser[Literal["user", "admin"], Annotated["int", "1", 2]]):
- def test_literal_annotation_args_contain_quotes(self, type1: AbstractBaseUser[Literal["user", "admin"], Annotated["int", "1", 2]]):
30 + def test_literal_annotation_args_contain_quotes(self, type1: "AbstractBaseUser[Literal['user', 'admin'], Annotated[int, '1', 2]]"):
31 | pass
32 |
33 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `django.contrib.auth.models.AbstractBaseUser` into a type-checking block
@@ -128,8 +140,11 @@ help: Move into type-checking block
37 |
- from django.contrib.auth.models import AbstractBaseUser
38 |
39 | def test_union_contain_inner_quotes(self, type1: AbstractBaseUser["int" | Literal["int"]]):
- def test_union_contain_inner_quotes(self, type1: AbstractBaseUser["int" | Literal["int"]]):
39 + def test_union_contain_inner_quotes(self, type1: "AbstractBaseUser[int | Literal['int']]"):
40 | pass
41 |
42 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `django.contrib.auth.models.AbstractBaseUser` into a type-checking block
@@ -156,8 +171,11 @@ help: Move into type-checking block
46 |
- from django.contrib.auth.models import AbstractBaseUser
47 |
48 | def test_inner_literal_mixed_quotes(user: AbstractBaseUser[Literal['user', "admin"]]):
- def test_inner_literal_mixed_quotes(user: AbstractBaseUser[Literal['user', "admin"]]):
48 + def test_inner_literal_mixed_quotes(user: "AbstractBaseUser[Literal['user', 'admin']]"):
49 | pass
50 |
51 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `django.contrib.auth.models.AbstractBaseUser` into a type-checking block
@@ -184,8 +202,11 @@ help: Move into type-checking block
55 |
- from django.contrib.auth.models import AbstractBaseUser
56 |
57 | def test_inner_literal_single_quote(user: AbstractBaseUser[Literal['int'], str]):
- def test_inner_literal_single_quote(user: AbstractBaseUser[Literal['int'], str]):
57 + def test_inner_literal_single_quote(user: "AbstractBaseUser[Literal['int'], str]"):
58 | pass
59 |
60 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `django.contrib.auth.models.AbstractBaseUser` into a type-checking block
@@ -212,8 +233,11 @@ help: Move into type-checking block
64 |
- from django.contrib.auth.models import AbstractBaseUser
65 |
66 | def test_mixed_quotes_literal(user: AbstractBaseUser[Literal['user'], "int"]):
- def test_mixed_quotes_literal(user: AbstractBaseUser[Literal['user'], "int"]):
66 + def test_mixed_quotes_literal(user: "AbstractBaseUser[Literal['user'], int]"):
67 | pass
68 |
69 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `django.contrib.auth.models.AbstractBaseUser` into a type-checking block
@@ -240,6 +264,9 @@ help: Move into type-checking block
73 |
- from django.contrib.auth.models import AbstractBaseUser
74 |
75 | def test_annotated_literal_mixed_quotes(user: AbstractBaseUser[Annotated[str, "max_length=20", Literal['user', "admin"]]]):
- def test_annotated_literal_mixed_quotes(user: AbstractBaseUser[Annotated[str, "max_length=20", Literal['user', "admin"]]]):
75 + def test_annotated_literal_mixed_quotes(user: "AbstractBaseUser[Annotated[str, 'max_length=20', Literal['user', 'admin']]]"):
76 | pass
77 |
78 |
note: This is an unsafe fix and may change runtime behavior

View File

@@ -21,8 +21,11 @@ help: Move into type-checking block
7 |
- from django.contrib.auth.models import AbstractBaseUser
8 |
9 | def test_union_literal_mixed_quotes(user: AbstractBaseUser[Union[Literal['active', "inactive"], str]]):
- def test_union_literal_mixed_quotes(user: AbstractBaseUser[Union[Literal['active', "inactive"], str]]):
9 + def test_union_literal_mixed_quotes(user: 'AbstractBaseUser[Union[Literal["active", "inactive"], str]]'):
10 | pass
11 |
12 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `django.contrib.auth.models.AbstractBaseUser` into a type-checking block
@@ -49,8 +52,11 @@ help: Move into type-checking block
16 |
- from django.contrib.auth.models import AbstractBaseUser
17 |
18 | def test_callable_literal_mixed_quotes(callable_fn: AbstractBaseUser[Callable[["int", Literal['admin', "user"]], 'bool']]):
- def test_callable_literal_mixed_quotes(callable_fn: AbstractBaseUser[Callable[["int", Literal['admin', "user"]], 'bool']]):
18 + def test_callable_literal_mixed_quotes(callable_fn: 'AbstractBaseUser[Callable[[int, Literal["admin", "user"]], bool]]'):
19 | pass
20 |
21 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `django.contrib.auth.models.AbstractBaseUser` into a type-checking block
@@ -77,8 +83,11 @@ help: Move into type-checking block
25 |
- from django.contrib.auth.models import AbstractBaseUser
26 |
27 | def test_callable_annotated_literal(callable_fn: AbstractBaseUser[Callable[[int, Annotated[str, Literal['active', "inactive"]]], bool]]):
- def test_callable_annotated_literal(callable_fn: AbstractBaseUser[Callable[[int, Annotated[str, Literal['active', "inactive"]]], bool]]):
27 + def test_callable_annotated_literal(callable_fn: 'AbstractBaseUser[Callable[[int, Annotated[str, Literal["active", "inactive"]]], bool]]'):
28 | pass
29 |
30 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `django.contrib.auth.models` into a type-checking block
@@ -105,8 +114,11 @@ help: Move into type-checking block
34 |
- from django.contrib.auth import models
35 |
36 | def test_attribute(arg: models.AbstractBaseUser["int"]):
- def test_attribute(arg: models.AbstractBaseUser["int"]):
36 + def test_attribute(arg: 'models.AbstractBaseUser[int]'):
37 | pass
38 |
39 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `django.contrib.auth.models` into a type-checking block
@@ -133,8 +145,11 @@ help: Move into type-checking block
43 |
- from django.contrib.auth import models
44 |
45 | def test_attribute_typing_literal(arg: models.AbstractBaseUser[Literal["admin"]]):
- def test_attribute_typing_literal(arg: models.AbstractBaseUser[Literal["admin"]]):
45 + def test_attribute_typing_literal(arg: 'models.AbstractBaseUser[Literal["admin"]]'):
46 | pass
47 |
48 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `third_party.Type` into a type-checking block
@@ -161,8 +176,11 @@ help: Move into type-checking block
62 | from typing import Literal
- from third_party import Type
63 |
64 | def test_string_contains_opposite_quote(self, type1: Type[Literal["'"]], type2: Type[Literal["\'"]]):
- def test_string_contains_opposite_quote(self, type1: Type[Literal["'"]], type2: Type[Literal["\'"]]):
64 + def test_string_contains_opposite_quote(self, type1: 'Type[Literal["\'"]]', type2: 'Type[Literal["\'"]]'):
65 | pass
66 |
67 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `third_party.Type` into a type-checking block
@@ -189,6 +207,7 @@ help: Move into type-checking block
70 | from typing import Literal
- from third_party import Type
71 |
72 | def test_quote_contains_backslash(self, type1: Type[Literal["\n"]], type2: Type[Literal["\""]]):
- def test_quote_contains_backslash(self, type1: Type[Literal["\n"]], type2: Type[Literal["\""]]):
72 + def test_quote_contains_backslash(self, type1: 'Type[Literal["\\n"]]', type2: 'Type[Literal[\'"\']]'):
73 | pass
note: This is an unsafe fix and may change runtime behavior

View File

@@ -1,4 +1,21 @@
---
source: crates/ruff_linter/src/rules/flake8_type_checking/mod.rs
---
TC004 [*] Move import `typing.Any` out of type-checking block. Import is used for more than type hinting.
--> TC004_4.py:4:24
|
3 | if TYPE_CHECKING:
4 | from typing import Any
| ^^^
|
help: Move out of type-checking block
1 | from typing import TYPE_CHECKING, Type
2 + from typing import Any
3 |
4 | if TYPE_CHECKING:
- from typing import Any
5 + pass
6 |
7 |
8 | def example(*args: Any, **kwargs: Any):
note: This is an unsafe fix and may change runtime behavior

View File

@@ -1,4 +1,59 @@
---
source: crates/ruff_linter/src/rules/flake8_type_checking/mod.rs
---
TC004 [*] Move import `typing.List` out of type-checking block. Import is used for more than type hinting.
--> TC004_5.py:4:24
|
3 | if TYPE_CHECKING:
4 | from typing import List, Sequence, Set
| ^^^^
|
help: Move out of type-checking block
1 | from typing import TYPE_CHECKING
2 + from typing import List, Sequence, Set
3 |
4 | if TYPE_CHECKING:
- from typing import List, Sequence, Set
5 + pass
6 |
7 |
8 | def example(a: List[int], /, b: Sequence[int], *, c: Set[int]):
note: This is an unsafe fix and may change runtime behavior
TC004 [*] Move import `typing.Sequence` out of type-checking block. Import is used for more than type hinting.
--> TC004_5.py:4:30
|
3 | if TYPE_CHECKING:
4 | from typing import List, Sequence, Set
| ^^^^^^^^
|
help: Move out of type-checking block
1 | from typing import TYPE_CHECKING
2 + from typing import List, Sequence, Set
3 |
4 | if TYPE_CHECKING:
- from typing import List, Sequence, Set
5 + pass
6 |
7 |
8 | def example(a: List[int], /, b: Sequence[int], *, c: Set[int]):
note: This is an unsafe fix and may change runtime behavior
TC004 [*] Move import `typing.Set` out of type-checking block. Import is used for more than type hinting.
--> TC004_5.py:4:40
|
3 | if TYPE_CHECKING:
4 | from typing import List, Sequence, Set
| ^^^
|
help: Move out of type-checking block
1 | from typing import TYPE_CHECKING
2 + from typing import List, Sequence, Set
3 |
4 | if TYPE_CHECKING:
- from typing import List, Sequence, Set
5 + pass
6 |
7 |
8 | def example(a: List[int], /, b: Sequence[int], *, c: Set[int]):
note: This is an unsafe fix and may change runtime behavior

View File

@@ -1,4 +1,44 @@
---
source: crates/ruff_linter/src/rules/flake8_type_checking/mod.rs
---
TC004 [*] Move import `typing.Tuple` out of type-checking block. Import is used for more than type hinting.
--> TC004_9.py:4:24
|
3 | if TYPE_CHECKING:
4 | from typing import Tuple, List, Dict
| ^^^^^
5 |
6 | x: Tuple
|
help: Move out of type-checking block
1 | from typing import TYPE_CHECKING
2 + from typing import Tuple, List
3 |
4 | if TYPE_CHECKING:
- from typing import Tuple, List, Dict
5 + from typing import Dict
6 |
7 | x: Tuple
8 |
note: This is an unsafe fix and may change runtime behavior
TC004 [*] Move import `typing.List` out of type-checking block. Import is used for more than type hinting.
--> TC004_9.py:4:31
|
3 | if TYPE_CHECKING:
4 | from typing import Tuple, List, Dict
| ^^^^
5 |
6 | x: Tuple
|
help: Move out of type-checking block
1 | from typing import TYPE_CHECKING
2 + from typing import Tuple, List
3 |
4 | if TYPE_CHECKING:
- from typing import Tuple, List, Dict
5 + from typing import Dict
6 |
7 | x: Tuple
8 |
note: This is an unsafe fix and may change runtime behavior

View File

@@ -1,6 +1,31 @@
---
source: crates/ruff_linter/src/rules/flake8_type_checking/mod.rs
---
TC004 [*] Move import `pandas.DataFrame` out of type-checking block. Import is used for more than type hinting.
--> quote.py:57:28
|
56 | if TYPE_CHECKING:
57 | from pandas import DataFrame
| ^^^^^^^^^
58 |
59 | def func(value: DataFrame):
|
help: Move out of type-checking block
1 + from pandas import DataFrame
2 | def f():
3 | from pandas import DataFrame
4 |
--------------------------------------------------------------------------------
55 | from typing import TYPE_CHECKING
56 |
57 | if TYPE_CHECKING:
- from pandas import DataFrame
58 + pass
59 |
60 | def func(value: DataFrame):
61 | ...
note: This is an unsafe fix and may change runtime behavior
TC004 [*] Move import `pandas.DataFrame` out of type-checking block. Import is used for more than type hinting.
--> quote.py:110:28
|

View File

@@ -1,6 +1,39 @@
---
source: crates/ruff_linter/src/rules/flake8_type_checking/mod.rs
---
TC010 Invalid string member in `X | Y`-style union type
--> TC010_2.py:4:4
|
4 | x: "int" | str # TC010
| ^^^^^
5 | x: ("int" | str) | "bool" # TC010
|
TC010 Invalid string member in `X | Y`-style union type
--> TC010_2.py:5:5
|
4 | x: "int" | str # TC010
5 | x: ("int" | str) | "bool" # TC010
| ^^^^^
|
TC010 Invalid string member in `X | Y`-style union type
--> TC010_2.py:5:20
|
4 | x: "int" | str # TC010
5 | x: ("int" | str) | "bool" # TC010
| ^^^^^^
|
TC010 Invalid string member in `X | Y`-style union type
--> TC010_2.py:12:20
|
12 | z: list[str, str | "int"] = [] # TC010
| ^^^^^
13 |
14 | type A = Value["int" | str] # OK
|
TC010 Invalid string member in `X | Y`-style union type
--> TC010_2.py:16:30
|

View File

@@ -220,3 +220,32 @@ help: Move into type-checking block
52 | x = dict["pd.DataFrame", "pd.DataFrame"]
53 |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `module.Member` into a type-checking block
--> TC002.py:172:24
|
170 | global Member
171 |
172 | from module import Member
| ^^^^^^
173 |
174 | x: Member = 1
|
help: Move into type-checking block
1 | """Tests to determine accurate detection of typing-only imports."""
2 + from typing import TYPE_CHECKING
3 +
4 + if TYPE_CHECKING:
5 + from module import Member
6 |
7 |
8 | def f():
--------------------------------------------------------------------------------
173 | def f():
174 | global Member
175 |
- from module import Member
176 |
177 | x: Member = 1
178 |
note: This is an unsafe fix and may change runtime behavior

View File

@@ -1,348 +1,5 @@
---
source: crates/ruff_linter/src/rules/flake8_type_checking/mod.rs
snapshot_kind: text
---
TC002 [*] Move third-party import `pandas.DataFrame` into a type-checking block
--> quote.py:2:24
|
1 | def f():
2 | from pandas import DataFrame
| ^^^^^^^^^
3 |
4 | def baz() -> DataFrame:
|
help: Move into type-checking block
- def f():
1 + from typing import TYPE_CHECKING
2 +
3 + if TYPE_CHECKING:
4 | from pandas import DataFrame
5 + def f():
6 |
7 | def baz() -> DataFrame:
8 | ...
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas.DataFrame` into a type-checking block
--> quote.py:9:24
|
8 | def f():
9 | from pandas import DataFrame
| ^^^^^^^^^
10 |
11 | def baz() -> DataFrame[int]:
|
help: Move into type-checking block
1 + from typing import TYPE_CHECKING
2 +
3 + if TYPE_CHECKING:
4 + from pandas import DataFrame
5 | def f():
6 | from pandas import DataFrame
7 |
--------------------------------------------------------------------------------
10 |
11 |
12 | def f():
- from pandas import DataFrame
13 |
14 | def baz() -> DataFrame[int]:
15 | ...
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas` into a type-checking block
--> quote.py:16:22
|
15 | def f():
16 | import pandas as pd
| ^^
17 |
18 | def baz() -> pd.DataFrame:
|
help: Move into type-checking block
1 + from typing import TYPE_CHECKING
2 +
3 + if TYPE_CHECKING:
4 + import pandas as pd
5 | def f():
6 | from pandas import DataFrame
7 |
--------------------------------------------------------------------------------
17 |
18 |
19 | def f():
- import pandas as pd
20 |
21 | def baz() -> pd.DataFrame:
22 | ...
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas` into a type-checking block
--> quote.py:23:22
|
22 | def f():
23 | import pandas as pd
| ^^
24 |
25 | def baz() -> pd.DataFrame.Extra:
|
help: Move into type-checking block
1 + from typing import TYPE_CHECKING
2 +
3 + if TYPE_CHECKING:
4 + import pandas as pd
5 | def f():
6 | from pandas import DataFrame
7 |
--------------------------------------------------------------------------------
24 |
25 |
26 | def f():
- import pandas as pd
27 |
28 | def baz() -> pd.DataFrame.Extra:
29 | ...
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas` into a type-checking block
--> quote.py:30:22
|
29 | def f():
30 | import pandas as pd
| ^^
31 |
32 | def baz() -> pd.DataFrame | int:
|
help: Move into type-checking block
1 + from typing import TYPE_CHECKING
2 +
3 + if TYPE_CHECKING:
4 + import pandas as pd
5 | def f():
6 | from pandas import DataFrame
7 |
--------------------------------------------------------------------------------
31 |
32 |
33 | def f():
- import pandas as pd
34 |
35 | def baz() -> pd.DataFrame | int:
36 | ...
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas.DataFrame` into a type-checking block
--> quote.py:38:24
|
37 | def f():
38 | from pandas import DataFrame
| ^^^^^^^^^
39 |
40 | def baz() -> DataFrame():
|
help: Move into type-checking block
1 + from typing import TYPE_CHECKING
2 +
3 + if TYPE_CHECKING:
4 + from pandas import DataFrame
5 | def f():
6 | from pandas import DataFrame
7 |
--------------------------------------------------------------------------------
39 |
40 |
41 | def f():
- from pandas import DataFrame
42 |
43 | def baz() -> DataFrame():
44 | ...
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas.DataFrame` into a type-checking block
--> quote.py:47:24
|
45 | from typing import Literal
46 |
47 | from pandas import DataFrame
| ^^^^^^^^^
48 |
49 | def baz() -> DataFrame[Literal["int"]]:
|
help: Move into type-checking block
1 + from typing import TYPE_CHECKING
2 +
3 + if TYPE_CHECKING:
4 + from pandas import DataFrame
5 | def f():
6 | from pandas import DataFrame
7 |
--------------------------------------------------------------------------------
48 | def f():
49 | from typing import Literal
50 |
- from pandas import DataFrame
51 |
52 | def baz() -> DataFrame[Literal["int"]]:
53 | ...
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas.DataFrame` into a type-checking block
--> quote.py:64:24
|
63 | def f():
64 | from pandas import DataFrame, Series
| ^^^^^^^^^
65 |
66 | def baz() -> DataFrame | Series:
|
help: Move into type-checking block
1 + from typing import TYPE_CHECKING
2 +
3 + if TYPE_CHECKING:
4 + from pandas import DataFrame, Series
5 | def f():
6 | from pandas import DataFrame
7 |
--------------------------------------------------------------------------------
65 |
66 |
67 | def f():
- from pandas import DataFrame, Series
68 |
69 | def baz() -> DataFrame | Series:
70 | ...
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas.Series` into a type-checking block
--> quote.py:64:35
|
63 | def f():
64 | from pandas import DataFrame, Series
| ^^^^^^
65 |
66 | def baz() -> DataFrame | Series:
|
help: Move into type-checking block
1 + from typing import TYPE_CHECKING
2 +
3 + if TYPE_CHECKING:
4 + from pandas import DataFrame, Series
5 | def f():
6 | from pandas import DataFrame
7 |
--------------------------------------------------------------------------------
65 |
66 |
67 | def f():
- from pandas import DataFrame, Series
68 |
69 | def baz() -> DataFrame | Series:
70 | ...
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas.DataFrame` into a type-checking block
--> quote.py:71:24
|
70 | def f():
71 | from pandas import DataFrame, Series
| ^^^^^^^^^
72 |
73 | def baz() -> (
|
help: Move into type-checking block
1 + from typing import TYPE_CHECKING
2 +
3 + if TYPE_CHECKING:
4 + from pandas import DataFrame, Series
5 | def f():
6 | from pandas import DataFrame
7 |
--------------------------------------------------------------------------------
72 |
73 |
74 | def f():
- from pandas import DataFrame, Series
75 |
76 | def baz() -> (
77 | DataFrame |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas.Series` into a type-checking block
--> quote.py:71:35
|
70 | def f():
71 | from pandas import DataFrame, Series
| ^^^^^^
72 |
73 | def baz() -> (
|
help: Move into type-checking block
1 + from typing import TYPE_CHECKING
2 +
3 + if TYPE_CHECKING:
4 + from pandas import DataFrame, Series
5 | def f():
6 | from pandas import DataFrame
7 |
--------------------------------------------------------------------------------
72 |
73 |
74 | def f():
- from pandas import DataFrame, Series
75 |
76 | def baz() -> (
77 | DataFrame |
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas.DataFrame` into a type-checking block
--> quote.py:89:24
|
88 | def f():
89 | from pandas import DataFrame, Series
| ^^^^^^^^^
90 |
91 | def func(self) -> DataFrame | list[Series]:
|
help: Move into type-checking block
1 + from typing import TYPE_CHECKING
2 +
3 + if TYPE_CHECKING:
4 + from pandas import DataFrame, Series
5 | def f():
6 | from pandas import DataFrame
7 |
--------------------------------------------------------------------------------
90 |
91 |
92 | def f():
- from pandas import DataFrame, Series
93 |
94 | def func(self) -> DataFrame | list[Series]:
95 | pass
note: This is an unsafe fix and may change runtime behavior
TC002 [*] Move third-party import `pandas.Series` into a type-checking block
--> quote.py:89:35
|
88 | def f():
89 | from pandas import DataFrame, Series
| ^^^^^^
90 |
91 | def func(self) -> DataFrame | list[Series]:
|
help: Move into type-checking block
1 + from typing import TYPE_CHECKING
2 +
3 + if TYPE_CHECKING:
4 + from pandas import DataFrame, Series
5 | def f():
6 | from pandas import DataFrame
7 |
--------------------------------------------------------------------------------
90 |
91 |
92 | def f():
- from pandas import DataFrame, Series
93 |
94 | def func(self) -> DataFrame | list[Series]:
95 | pass
note: This is an unsafe fix and may change runtime behavior

View File

@@ -11,11 +11,11 @@ mod tests {
use ruff_python_ast::PythonVersion;
use test_case::test_case;
use crate::assert_diagnostics;
use crate::registry::Rule;
use crate::settings;
use crate::settings::types::PreviewMode;
use crate::test::test_path;
use crate::{assert_diagnostics, assert_diagnostics_diff};
#[test_case(Path::new("full_name.py"))]
#[test_case(Path::new("import_as.py"))]
@@ -82,29 +82,6 @@ mod tests {
Ok(())
}
#[test_case(Rule::InvalidPathlibWithSuffix, Path::new("PTH210.py"))]
#[test_case(Rule::InvalidPathlibWithSuffix, Path::new("PTH210_1.py"))]
fn deferred_annotations_diff(rule_code: Rule, path: &Path) -> Result<()> {
let snapshot = format!(
"deferred_annotations_diff_{}_{}",
rule_code.name(),
path.to_string_lossy()
);
assert_diagnostics_diff!(
snapshot,
Path::new("flake8_use_pathlib").join(path).as_path(),
&settings::LinterSettings {
unresolved_target_version: PythonVersion::PY313.into(),
..settings::LinterSettings::for_rule(rule_code)
},
&settings::LinterSettings {
unresolved_target_version: PythonVersion::PY314.into(),
..settings::LinterSettings::for_rule(rule_code)
},
);
Ok(())
}
#[test_case(Path::new("full_name.py"))]
#[test_case(Path::new("import_as.py"))]
#[test_case(Path::new("import_from_as.py"))]

View File

@@ -1,6 +1,17 @@
---
source: crates/ruff_linter/src/rules/flake8_use_pathlib/mod.rs
---
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210.py:21:1
|
20 | ### Errors
21 | path.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^^^^
22 | path.with_suffix("py")
23 | path.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 [*] Dotless suffix passed to `.with_suffix()`
--> PTH210.py:22:1
|
@@ -84,6 +95,18 @@ help: Add a leading dot
28 | posix_path.with_suffix("py")
note: This is an unsafe fix and may change runtime behavior
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210.py:27:1
|
25 | path.with_suffix(suffix="js")
26 |
27 | posix_path.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
28 | posix_path.with_suffix("py")
29 | posix_path.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 [*] Dotless suffix passed to `.with_suffix()`
--> PTH210.py:28:1
|
@@ -166,6 +189,18 @@ help: Add a leading dot
34 | pure_path.with_suffix("py")
note: This is an unsafe fix and may change runtime behavior
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210.py:33:1
|
31 | posix_path.with_suffix(suffix="js")
32 |
33 | pure_path.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
34 | pure_path.with_suffix("py")
35 | pure_path.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 [*] Dotless suffix passed to `.with_suffix()`
--> PTH210.py:34:1
|
@@ -248,6 +283,18 @@ help: Add a leading dot
40 | pure_posix_path.with_suffix("py")
note: This is an unsafe fix and may change runtime behavior
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210.py:39:1
|
37 | pure_path.with_suffix(suffix="js")
38 |
39 | pure_posix_path.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
40 | pure_posix_path.with_suffix("py")
41 | pure_posix_path.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 [*] Dotless suffix passed to `.with_suffix()`
--> PTH210.py:40:1
|
@@ -330,6 +377,18 @@ help: Add a leading dot
46 | pure_windows_path.with_suffix("py")
note: This is an unsafe fix and may change runtime behavior
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210.py:45:1
|
43 | pure_posix_path.with_suffix(suffix="js")
44 |
45 | pure_windows_path.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46 | pure_windows_path.with_suffix("py")
47 | pure_windows_path.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 [*] Dotless suffix passed to `.with_suffix()`
--> PTH210.py:46:1
|
@@ -412,6 +471,18 @@ help: Add a leading dot
52 | windows_path.with_suffix("py")
note: This is an unsafe fix and may change runtime behavior
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210.py:51:1
|
49 | pure_windows_path.with_suffix(suffix="js")
50 |
51 | windows_path.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
52 | windows_path.with_suffix("py")
53 | windows_path.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 [*] Dotless suffix passed to `.with_suffix()`
--> PTH210.py:52:1
|
@@ -494,6 +565,18 @@ help: Add a leading dot
58 | Path().with_suffix("py")
note: This is an unsafe fix and may change runtime behavior
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210.py:57:1
|
55 | windows_path.with_suffix(suffix="js")
56 |
57 | Path().with_suffix(".")
| ^^^^^^^^^^^^^^^^^^^^^^^
58 | Path().with_suffix("py")
59 | PosixPath().with_suffix("py")
|
help: Remove "." or extend to valid suffix
PTH210 [*] Dotless suffix passed to `.with_suffix()`
--> PTH210.py:58:1
|

View File

@@ -1,6 +1,18 @@
---
source: crates/ruff_linter/src/rules/flake8_use_pathlib/mod.rs
---
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210_1.py:13:5
|
11 | def test_path(p: Path) -> None:
12 | ## Errors
13 | p.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^
14 | p.with_suffix("py")
15 | p.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 [*] Dotless suffix passed to `.with_suffix()`
--> PTH210_1.py:14:5
|
@@ -84,6 +96,18 @@ help: Add a leading dot
20 | p.with_suffix()
note: This is an unsafe fix and may change runtime behavior
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210_1.py:31:5
|
29 | def test_posix_path(p: PosixPath) -> None:
30 | ## Errors
31 | p.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^
32 | p.with_suffix("py")
33 | p.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 [*] Dotless suffix passed to `.with_suffix()`
--> PTH210_1.py:32:5
|
@@ -167,6 +191,18 @@ help: Add a leading dot
38 | p.with_suffix()
note: This is an unsafe fix and may change runtime behavior
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210_1.py:49:5
|
47 | def test_pure_path(p: PurePath) -> None:
48 | ## Errors
49 | p.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^
50 | p.with_suffix("py")
51 | p.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 [*] Dotless suffix passed to `.with_suffix()`
--> PTH210_1.py:50:5
|
@@ -250,6 +286,18 @@ help: Add a leading dot
56 | p.with_suffix()
note: This is an unsafe fix and may change runtime behavior
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210_1.py:67:5
|
65 | def test_pure_posix_path(p: PurePosixPath) -> None:
66 | ## Errors
67 | p.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^
68 | p.with_suffix("py")
69 | p.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 [*] Dotless suffix passed to `.with_suffix()`
--> PTH210_1.py:68:5
|
@@ -333,6 +381,18 @@ help: Add a leading dot
74 | p.with_suffix()
note: This is an unsafe fix and may change runtime behavior
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210_1.py:85:5
|
83 | def test_pure_windows_path(p: PureWindowsPath) -> None:
84 | ## Errors
85 | p.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^
86 | p.with_suffix("py")
87 | p.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 [*] Dotless suffix passed to `.with_suffix()`
--> PTH210_1.py:86:5
|
@@ -416,6 +476,18 @@ help: Add a leading dot
92 | p.with_suffix()
note: This is an unsafe fix and may change runtime behavior
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210_1.py:103:5
|
101 | def test_windows_path(p: WindowsPath) -> None:
102 | ## Errors
103 | p.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^
104 | p.with_suffix("py")
105 | p.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 [*] Dotless suffix passed to `.with_suffix()`
--> PTH210_1.py:104:5
|

View File

@@ -1,100 +0,0 @@
---
source: crates/ruff_linter/src/rules/flake8_use_pathlib/mod.rs
---
--- Linter settings ---
-linter.unresolved_target_version = 3.13
+linter.unresolved_target_version = 3.14
--- Summary ---
Removed: 7
Added: 0
--- Removed ---
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210.py:21:1
|
20 | ### Errors
21 | path.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^^^^
22 | path.with_suffix("py")
23 | path.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210.py:27:1
|
25 | path.with_suffix(suffix="js")
26 |
27 | posix_path.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
28 | posix_path.with_suffix("py")
29 | posix_path.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210.py:33:1
|
31 | posix_path.with_suffix(suffix="js")
32 |
33 | pure_path.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
34 | pure_path.with_suffix("py")
35 | pure_path.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210.py:39:1
|
37 | pure_path.with_suffix(suffix="js")
38 |
39 | pure_posix_path.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
40 | pure_posix_path.with_suffix("py")
41 | pure_posix_path.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210.py:45:1
|
43 | pure_posix_path.with_suffix(suffix="js")
44 |
45 | pure_windows_path.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46 | pure_windows_path.with_suffix("py")
47 | pure_windows_path.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210.py:51:1
|
49 | pure_windows_path.with_suffix(suffix="js")
50 |
51 | windows_path.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
52 | windows_path.with_suffix("py")
53 | windows_path.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210.py:57:1
|
55 | windows_path.with_suffix(suffix="js")
56 |
57 | Path().with_suffix(".")
| ^^^^^^^^^^^^^^^^^^^^^^^
58 | Path().with_suffix("py")
59 | PosixPath().with_suffix("py")
|
help: Remove "." or extend to valid suffix

View File

@@ -1,88 +0,0 @@
---
source: crates/ruff_linter/src/rules/flake8_use_pathlib/mod.rs
---
--- Linter settings ---
-linter.unresolved_target_version = 3.13
+linter.unresolved_target_version = 3.14
--- Summary ---
Removed: 6
Added: 0
--- Removed ---
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210_1.py:13:5
|
11 | def test_path(p: Path) -> None:
12 | ## Errors
13 | p.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^
14 | p.with_suffix("py")
15 | p.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210_1.py:31:5
|
29 | def test_posix_path(p: PosixPath) -> None:
30 | ## Errors
31 | p.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^
32 | p.with_suffix("py")
33 | p.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210_1.py:49:5
|
47 | def test_pure_path(p: PurePath) -> None:
48 | ## Errors
49 | p.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^
50 | p.with_suffix("py")
51 | p.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210_1.py:67:5
|
65 | def test_pure_posix_path(p: PurePosixPath) -> None:
66 | ## Errors
67 | p.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^
68 | p.with_suffix("py")
69 | p.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210_1.py:85:5
|
83 | def test_pure_windows_path(p: PureWindowsPath) -> None:
84 | ## Errors
85 | p.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^
86 | p.with_suffix("py")
87 | p.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix
PTH210 Invalid suffix passed to `.with_suffix()`
--> PTH210_1.py:103:5
|
101 | def test_windows_path(p: WindowsPath) -> None:
102 | ## Errors
103 | p.with_suffix(".")
| ^^^^^^^^^^^^^^^^^^
104 | p.with_suffix("py")
105 | p.with_suffix(r"s")
|
help: Remove "." or extend to valid suffix

View File

@@ -1014,30 +1014,6 @@ mod tests {
Ok(())
}
#[test_case(Path::new("future_import.py"))]
#[test_case(Path::new("docstring_future_import.py"))]
fn required_import_with_future_import(path: &Path) -> Result<()> {
let snapshot = format!(
"required_import_with_future_import_{}",
path.to_string_lossy()
);
let diagnostics = test_path(
Path::new("isort/required_imports").join(path).as_path(),
&LinterSettings {
src: vec![test_resource_path("fixtures/isort")],
isort: super::settings::Settings {
required_imports: BTreeSet::from_iter([NameImport::Import(
ModuleNameImport::module("this".to_string()),
)]),
..super::settings::Settings::default()
},
..LinterSettings::for_rule(Rule::MissingRequiredImport)
},
)?;
assert_diagnostics!(snapshot, diagnostics);
Ok(())
}
#[test_case(Path::new("from_first.py"))]
fn from_first(path: &Path) -> Result<()> {
let snapshot = format!("from_first_{}", path.to_string_lossy());

View File

@@ -4,6 +4,6 @@ source: crates/ruff_linter/src/rules/isort/mod.rs
I002 [*] Missing required import: `from __future__ import annotations`
--> existing_import.py:1:1
help: Insert required import: `from __future__ import annotations`
1 | from __future__ import generator_stop
2 + from __future__ import annotations
1 + from __future__ import annotations
2 | from __future__ import generator_stop
3 | import os

View File

@@ -4,6 +4,6 @@ source: crates/ruff_linter/src/rules/isort/mod.rs
I002 [*] Missing required import: `from __future__ import annotations as _annotations`
--> existing_import.py:1:1
help: Insert required import: `from __future__ import annotations as _annotations`
1 | from __future__ import generator_stop
2 + from __future__ import annotations as _annotations
1 + from __future__ import annotations as _annotations
2 | from __future__ import generator_stop
3 | import os

View File

@@ -1,10 +0,0 @@
---
source: crates/ruff_linter/src/rules/isort/mod.rs
---
I002 [*] Missing required import: `import this`
--> docstring_future_import.py:1:1
help: Insert required import: `import this`
1 | "a docstring"
2 | from __future__ import annotations
3 + import this
4 | # EOF

View File

@@ -1,9 +0,0 @@
---
source: crates/ruff_linter/src/rules/isort/mod.rs
---
I002 [*] Missing required import: `import this`
--> future_import.py:1:1
help: Insert required import: `import this`
1 | from __future__ import annotations
2 + import this
3 | # EOF

View File

@@ -3769,7 +3769,7 @@ lambda: fu
def f(a: A) -> A: pass
class A: pass
",
&[],
&[Rule::UndefinedName, Rule::UndefinedName],
);
flakes(
r"
@@ -3783,7 +3783,7 @@ lambda: fu
a: A
class A: pass
",
&[],
&[Rule::UndefinedName],
);
flakes(
r"

View File

@@ -1,11 +1,5 @@
---
source: crates/ruff_linter/src/rules/pyflakes/mod.rs
snapshot_kind: text
---
F821 Undefined name `y`
--> F821_18.py:19:7
|
17 | # This is no longer allowed on Python 3.14+
18 | x: (y := 1)
19 | print(y)
| ^
|

View File

@@ -1,4 +1,12 @@
---
source: crates/ruff_linter/src/rules/pyflakes/mod.rs
---
F821 Undefined name `Model`
--> F821_2.py:5:13
|
4 | # F821 Undefined name `Model`
5 | x: Literal["Model"]
| ^^^^^
6 |
7 | from typing_extensions import Literal
|

View File

@@ -21,6 +21,48 @@ F821 Undefined name `C`
12 | CStr2: TypeAlias = Union["C", str] # always okay
|
F821 Undefined name `C`
--> F821_26.py:16:12
|
14 | # References to a class from inside the class:
15 | class C:
16 | other: C = ... # valid in a `.pyi` stub file, not in a `.py` runtime file
| ^
17 | other2: "C" = ... # always okay
18 | def from_str(self, s: str) -> C: ... # valid in a `.pyi` stub file, not in a `.py` runtime file
|
F821 Undefined name `C`
--> F821_26.py:18:35
|
16 | other: C = ... # valid in a `.pyi` stub file, not in a `.py` runtime file
17 | other2: "C" = ... # always okay
18 | def from_str(self, s: str) -> C: ... # valid in a `.pyi` stub file, not in a `.py` runtime file
| ^
19 | def from_str2(self, s: str) -> "C": ... # always okay
|
F821 Undefined name `B`
--> F821_26.py:23:10
|
21 | # Circular references:
22 | class A:
23 | foo: B # valid in a `.pyi` stub file, not in a `.py` runtime file
| ^
24 | foo2: "B" # always okay
25 | bar: dict[str, B] # valid in a `.pyi` stub file, not in a `.py` runtime file
|
F821 Undefined name `B`
--> F821_26.py:25:20
|
23 | foo: B # valid in a `.pyi` stub file, not in a `.py` runtime file
24 | foo2: "B" # always okay
25 | bar: dict[str, B] # valid in a `.pyi` stub file, not in a `.py` runtime file
| ^
26 | bar2: dict[str, "A"] # always okay
|
F821 Undefined name `Tree`
--> F821_26.py:33:17
|

View File

@@ -43,7 +43,6 @@ where
T: Ranged,
{
let mut diagnostic = checker.report_diagnostic(DeprecatedCElementTree, node.range());
diagnostic.add_primary_tag(ruff_db::diagnostic::DiagnosticTag::Deprecated);
let contents = checker.locator().slice(node);
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
contents.replacen("cElementTree", "ElementTree", 1),

View File

@@ -265,7 +265,6 @@ pub(crate) fn deprecated_mock_attribute(checker: &Checker, attribute: &ast::Expr
},
attribute.value.range(),
);
diagnostic.add_primary_tag(ruff_db::diagnostic::DiagnosticTag::Deprecated);
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
"mock".to_string(),
attribute.value.range(),
@@ -314,7 +313,6 @@ pub(crate) fn deprecated_mock_import(checker: &Checker, stmt: &Stmt) {
},
name.range(),
);
diagnostic.add_primary_tag(ruff_db::diagnostic::DiagnosticTag::Deprecated);
if let Some(content) = content.as_ref() {
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
content.clone(),
@@ -353,7 +351,6 @@ pub(crate) fn deprecated_mock_import(checker: &Checker, stmt: &Stmt) {
},
stmt.range(),
);
diagnostic.add_primary_tag(ruff_db::diagnostic::DiagnosticTag::Deprecated);
if let Some(indent) = indentation(checker.source(), stmt) {
diagnostic.try_set_fix(|| {
format_import_from(stmt, indent, checker.locator(), checker.stylist())

View File

@@ -98,7 +98,6 @@ pub(crate) fn deprecated_unittest_alias(checker: &Checker, expr: &Expr) {
},
expr.range(),
);
diagnostic.add_primary_tag(ruff_db::diagnostic::DiagnosticTag::Deprecated);
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
format!("self.{target}"),
expr.range(),

View File

@@ -68,7 +68,6 @@ pub(crate) fn replace_universal_newlines(checker: &Checker, call: &ast::ExprCall
};
let mut diagnostic = checker.report_diagnostic(ReplaceUniversalNewlines, arg.range());
diagnostic.add_primary_tag(ruff_db::diagnostic::DiagnosticTag::Deprecated);
if call.arguments.find_keyword("text").is_some() {
diagnostic.try_set_fix(|| {

View File

@@ -57,7 +57,6 @@ pub(crate) fn typing_text_str_alias(checker: &Checker, expr: &Expr) {
.is_some_and(|qualified_name| matches!(qualified_name.segments(), ["typing", "Text"]))
{
let mut diagnostic = checker.report_diagnostic(TypingTextStrAlias, expr.range());
diagnostic.add_primary_tag(ruff_db::diagnostic::DiagnosticTag::Deprecated);
diagnostic.try_set_fix(|| {
let (import_edit, binding) = checker.importer().get_or_import_builtin_symbol(
"str",

View File

@@ -1,7 +1,7 @@
---
source: crates/ruff_linter/src/rules/pyupgrade/mod.rs
---
UP006 [*] Use `collections.defaultdict` instead of `typing.DefaultDict` for type annotation
UP006 Use `collections.defaultdict` instead of `typing.DefaultDict` for type annotation
--> UP006_2.py:7:10
|
7 | def f(x: typing.DefaultDict[str, str]) -> None:
@@ -9,9 +9,3 @@ UP006 [*] Use `collections.defaultdict` instead of `typing.DefaultDict` for type
8 | ...
|
help: Replace with `collections.defaultdict`
4 | from collections import defaultdict
5 |
6 |
- def f(x: typing.DefaultDict[str, str]) -> None:
7 + def f(x: defaultdict[str, str]) -> None:
8 | ...

View File

@@ -171,40 +171,6 @@ help: Convert to `X | Y`
35 |
36 |
UP007 [*] Use `X | Y` for type annotations
--> UP007.py:37:10
|
37 | def f(x: Union["str", int]) -> None:
| ^^^^^^^^^^^^^^^^^
38 | ...
|
help: Convert to `X | Y`
34 | ...
35 |
36 |
- def f(x: Union["str", int]) -> None:
37 + def f(x: "str" | int) -> None:
38 | ...
39 |
40 |
UP007 [*] Use `X | Y` for type annotations
--> UP007.py:41:10
|
41 | def f(x: Union[("str", "int"), float]) -> None:
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42 | ...
|
help: Convert to `X | Y`
38 | ...
39 |
40 |
- def f(x: Union[("str", "int"), float]) -> None:
41 + def f(x: "str" | "int" | float) -> None:
42 | ...
43 |
44 |
UP007 Use `X | Y` for type annotations
--> UP007.py:46:9
|

Some files were not shown because too many files have changed in this diff Show More