Compare commits
2 Commits
v0.1.0
...
Remove_emp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63ef7652ed | ||
|
|
1743ef8398 |
2
.github/workflows/docs.yaml
vendored
2
.github/workflows/docs.yaml
vendored
@@ -47,7 +47,7 @@ jobs:
|
||||
run: mkdocs build --strict -f mkdocs.generated.yml
|
||||
- name: "Deploy to Cloudflare Pages"
|
||||
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
|
||||
uses: cloudflare/wrangler-action@v3.3.1
|
||||
uses: cloudflare/wrangler-action@v3.2.0
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
accountId: ${{ secrets.CF_ACCOUNT_ID }}
|
||||
|
||||
2
.github/workflows/playground.yaml
vendored
2
.github/workflows/playground.yaml
vendored
@@ -40,7 +40,7 @@ jobs:
|
||||
working-directory: playground
|
||||
- name: "Deploy to Cloudflare Pages"
|
||||
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
|
||||
uses: cloudflare/wrangler-action@v3.3.1
|
||||
uses: cloudflare/wrangler-action@v3.2.0
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
accountId: ${{ secrets.CF_ACCOUNT_ID }}
|
||||
|
||||
@@ -2,16 +2,6 @@
|
||||
|
||||
## 0.1.0
|
||||
|
||||
### The deprecated `format` setting has been removed
|
||||
|
||||
Ruff previously used the `format` setting, `--format` CLI option, and `RUFF_FORMAT` environment variable to
|
||||
configure the output format of the CLI. This usage was deprecated in `v0.0.291` — the `format` setting is now used
|
||||
to control Ruff's code formatting. As of this release:
|
||||
|
||||
- The `format` setting cannot be used to configure the output format, use `output-format` instead
|
||||
- The `RUFF_FORMAT` environment variable is ignored, use `RUFF_OUTPUT_FORMAT` instead
|
||||
- The `--format` option has been removed from `ruff check`, use `--output-format` instead
|
||||
|
||||
### Unsafe fixes are not applied by default ([#7769](https://github.com/astral-sh/ruff/pull/7769))
|
||||
|
||||
Ruff labels fixes as "safe" and "unsafe". The meaning and intent of your code will be retained when applying safe
|
||||
|
||||
115
CHANGELOG.md
115
CHANGELOG.md
@@ -1,115 +0,0 @@
|
||||
# Changelog
|
||||
|
||||
This is the first release which uses the `CHANGELOG` file. See [GitHub Releases](https://github.com/astral-sh/ruff/releases) for prior changelog entries.
|
||||
|
||||
Read Ruff's new [versioning policy](https://docs.astral.sh/ruff/versioning/).
|
||||
|
||||
## 0.1.0
|
||||
|
||||
### Breaking changes
|
||||
|
||||
- Unsafe fixes are no longer displayed or applied without opt-in ([#7769](https://github.com/astral-sh/ruff/pull/7769))
|
||||
- Drop formatting specific rules from the default set ([#7900](https://github.com/astral-sh/ruff/pull/7900))
|
||||
- The deprecated `format` setting has been removed ([#7984](https://github.com/astral-sh/ruff/pull/7984))
|
||||
- The `format` setting cannot be used to configure the output format, use `output-format` instead
|
||||
- The `RUFF_FORMAT` environment variable is ignored, use `RUFF_OUTPUT_FORMAT` instead
|
||||
- The `--format` option has been removed from `ruff check`, use `--output-format` instead
|
||||
|
||||
### Rule changes
|
||||
|
||||
- Extend `reimplemented-starmap` (`FURB140`) to catch calls with a single and starred argument ([#7768](https://github.com/astral-sh/ruff/pull/7768))
|
||||
- Improve cases covered by `RUF015` ([#7848](https://github.com/astral-sh/ruff/pull/7848))
|
||||
- Update `SIM15` to allow `open` followed by `close` ([#7916](https://github.com/astral-sh/ruff/pull/7916))
|
||||
- Respect `msgspec.Struct` default-copy semantics in `RUF012` ([#7786](https://github.com/astral-sh/ruff/pull/7786))
|
||||
- Add `sqlalchemy` methods to \`flake8-boolean-trap\`\` exclusion list ([#7874](https://github.com/astral-sh/ruff/pull/7874))
|
||||
- Add fix for `PLR1714` ([#7910](https://github.com/astral-sh/ruff/pull/7910))
|
||||
- Add fix for `PIE804` ([#7884](https://github.com/astral-sh/ruff/pull/7884))
|
||||
- Add fix for `PLC0208` ([#7887](https://github.com/astral-sh/ruff/pull/7887))
|
||||
- Add fix for `PYI055` ([#7886](https://github.com/astral-sh/ruff/pull/7886))
|
||||
- Update `non-pep695-type-alias` to require `--unsafe-fixes` outside of stub files ([#7836](https://github.com/astral-sh/ruff/pull/7836))
|
||||
- Improve fix message for `UP018` ([#7913](https://github.com/astral-sh/ruff/pull/7913))
|
||||
- Update `PLW3201` to support `Enum` [sunder names](https://docs.python.org/3/library/enum.html#supported-sunder-names) ([#7987](https://github.com/astral-sh/ruff/pull/7987))
|
||||
|
||||
### Preview features
|
||||
|
||||
- Only show warnings for empty preview selectors when enabling rules ([#7842](https://github.com/astral-sh/ruff/pull/7842))
|
||||
- Add `unnecessary-key-check` to simplify `key in dct and dct[key]` to `dct.get(key)` ([#7895](https://github.com/astral-sh/ruff/pull/7895))
|
||||
- Add `assignment-in-assert` to prevent walrus expressions in assert statements ([#7856](https://github.com/astral-sh/ruff/pull/7856))
|
||||
- \[`refurb`\] Add `single-item-membership-test` (`FURB171`) ([#7815](https://github.com/astral-sh/ruff/pull/7815))
|
||||
- \[`pylint`\] Add `and-or-ternary` (`R1706`) ([#7811](https://github.com/astral-sh/ruff/pull/7811))
|
||||
|
||||
_New rules are added in [preview](https://docs.astral.sh/ruff/preview/)._
|
||||
|
||||
### Configuration
|
||||
|
||||
- Add `unsafe-fixes` setting ([#7769](https://github.com/astral-sh/ruff/pull/7769))
|
||||
- Add `extend-safe-fixes` and `extend-unsafe-fixes` for promoting and demoting fixes ([#7841](https://github.com/astral-sh/ruff/pull/7841))
|
||||
|
||||
### CLI
|
||||
|
||||
- Added `--unsafe-fixes` option for opt-in to display and apply unsafe fixes ([#7769](https://github.com/astral-sh/ruff/pull/7769))
|
||||
- Fix use of deprecated `--format` option in warning ([#7837](https://github.com/astral-sh/ruff/pull/7837))
|
||||
- Show changed files when running under `--check` ([#7788](https://github.com/astral-sh/ruff/pull/7788))
|
||||
- Write summary messages to stderr when fixing via stdin instead of omitting them ([#7838](https://github.com/astral-sh/ruff/pull/7838))
|
||||
- Update fix summary message in `check --diff` to include unsafe fix hints ([#7790](https://github.com/astral-sh/ruff/pull/7790))
|
||||
- Add notebook `cell` field to JSON output format ([#7664](https://github.com/astral-sh/ruff/pull/7664))
|
||||
- Rename applicability levels to `Safe`, `Unsafe`, and `Display` ([#7843](https://github.com/astral-sh/ruff/pull/7843))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- Fix bug where f-strings were allowed in match pattern literal ([#7857](https://github.com/astral-sh/ruff/pull/7857))
|
||||
- Fix `SIM110` with a yield in the condition ([#7801](https://github.com/astral-sh/ruff/pull/7801))
|
||||
- Preserve trailing comments in `C414` fixes ([#7775](https://github.com/astral-sh/ruff/pull/7775))
|
||||
- Check sequence type before triggering `unnecessary-enumerate` `len` suggestion ([#7781](https://github.com/astral-sh/ruff/pull/7781))
|
||||
- Use correct start location for class/function clause header ([#7802](https://github.com/astral-sh/ruff/pull/7802))
|
||||
- Fix incorrect fixes for `SIM101` ([#7798](https://github.com/astral-sh/ruff/pull/7798))
|
||||
- Format comment before parameter default correctly ([#7870](https://github.com/astral-sh/ruff/pull/7870))
|
||||
- Fix `E251` false positive inside f-strings ([#7894](https://github.com/astral-sh/ruff/pull/7894))
|
||||
- Allow bindings to be created and referenced within annotations ([#7885](https://github.com/astral-sh/ruff/pull/7885))
|
||||
- Show per-cell diffs when analyzing notebooks over `stdin` ([#7789](https://github.com/astral-sh/ruff/pull/7789))
|
||||
- Avoid curly brace escape in f-string format spec ([#7780](https://github.com/astral-sh/ruff/pull/7780))
|
||||
- Fix lexing single-quoted f-string with multi-line format spec ([#7787](https://github.com/astral-sh/ruff/pull/7787))
|
||||
- Consider nursery rules to be in-preview for `ruff rule` ([#7812](https://github.com/astral-sh/ruff/pull/7812))
|
||||
- Report precise location for invalid conversion flag ([#7809](https://github.com/astral-sh/ruff/pull/7809))
|
||||
- Visit pattern match guard as a boolean test ([#7911](https://github.com/astral-sh/ruff/pull/7911))
|
||||
- Respect `--unfixable` in `ISC` rules ([#7917](https://github.com/astral-sh/ruff/pull/7917))
|
||||
- Fix edge case with `PIE804` ([#7922](https://github.com/astral-sh/ruff/pull/7922))
|
||||
- Show custom message in `PTH118` for `Path.joinpath` with starred arguments ([#7852](https://github.com/astral-sh/ruff/pull/7852))
|
||||
- Fix false negative in `outdated-version-block` when using greater than comparisons ([#7920](https://github.com/astral-sh/ruff/pull/7920))
|
||||
- Avoid converting f-strings within Django `gettext` calls ([#7898](https://github.com/astral-sh/ruff/pull/7898))
|
||||
- Fix false positive in `PLR6301` ([#7933](https://github.com/astral-sh/ruff/pull/7933))
|
||||
- Treat type aliases as typing-only expressions e.g. resolves false positive in `TCH004` ([#7968](https://github.com/astral-sh/ruff/pull/7968))
|
||||
- Resolve `cache-dir` relative to project root ([#7962](https://github.com/astral-sh/ruff/pull/7962))
|
||||
- Respect subscripted base classes in type-checking rules e.g. resolves false positive in `TCH003` ([#7954](https://github.com/astral-sh/ruff/pull/7954))
|
||||
- Fix JSON schema limit for `line-length` ([#7883](https://github.com/astral-sh/ruff/pull/7883))
|
||||
- Fix commented-out `coalesce` keyword ([#7876](https://github.com/astral-sh/ruff/pull/7876))
|
||||
|
||||
### Documentation
|
||||
|
||||
- Document `reimplemented-starmap` performance effects ([#7846](https://github.com/astral-sh/ruff/pull/7846))
|
||||
- Default to following the system dark/light mode ([#7888](https://github.com/astral-sh/ruff/pull/7888))
|
||||
- Add documentation for fixes ([#7901](https://github.com/astral-sh/ruff/pull/7901))
|
||||
- Fix typo in docs of `PLR6301` ([#7831](https://github.com/astral-sh/ruff/pull/7831))
|
||||
- Update `UP038` docs to note that it results in slower code ([#7872](https://github.com/astral-sh/ruff/pull/7872))
|
||||
- crlf -> cr-lf ([#7766](https://github.com/astral-sh/ruff/pull/7766))
|
||||
- Add an example of an unsafe fix ([#7924](https://github.com/astral-sh/ruff/pull/7924))
|
||||
- Fix documented examples for `unnecessary-subscript-reversal` ([#7774](https://github.com/astral-sh/ruff/pull/7774))
|
||||
- Correct error in tuple example in ruff formatter docs ([#7822](https://github.com/astral-sh/ruff/pull/7822))
|
||||
- Add versioning policy to documentation ([#7923](https://github.com/astral-sh/ruff/pull/7923))
|
||||
- Fix invalid code in `FURB177` example ([#7832](https://github.com/astral-sh/ruff/pull/7832))
|
||||
|
||||
### Formatter
|
||||
|
||||
- Less scary `ruff format` message ([#7867](https://github.com/astral-sh/ruff/pull/7867))
|
||||
- Remove spaces from import statements ([#7859](https://github.com/astral-sh/ruff/pull/7859))
|
||||
- Formatter quoting for f-strings with triple quotes ([#7826](https://github.com/astral-sh/ruff/pull/7826))
|
||||
- Update `ruff_python_formatter` generate.py comment ([#7850](https://github.com/astral-sh/ruff/pull/7850))
|
||||
- Document one-call chaining deviation ([#7767](https://github.com/astral-sh/ruff/pull/7767))
|
||||
- Allow f-string modifications in line-shrinking cases ([#7818](https://github.com/astral-sh/ruff/pull/7818))
|
||||
- Add trailing comment deviation to README ([#7827](https://github.com/astral-sh/ruff/pull/7827))
|
||||
- Add trailing zero between dot and exponential ([#7956](https://github.com/astral-sh/ruff/pull/7956))
|
||||
- Force parentheses for power operations in unary expressions ([#7955](https://github.com/astral-sh/ruff/pull/7955))
|
||||
|
||||
### Playground
|
||||
|
||||
- Fix playground `Quick Fix` action ([#7824](https://github.com/astral-sh/ruff/pull/7824))
|
||||
50
Cargo.lock
generated
50
Cargo.lock
generated
@@ -28,9 +28,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.2"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
||||
checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@@ -810,7 +810,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.1.0"
|
||||
version = "0.0.292"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -1084,9 +1084,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "insta"
|
||||
version = "1.34.0"
|
||||
version = "1.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d64600be34b2fcfc267740a243fa7744441bb4947a619ac4e5bb6507f35fbfc"
|
||||
checksum = "1aa511b2e298cd49b1856746f6bb73e17036bcd66b25f5e92cdcdbec9bd75686"
|
||||
dependencies = [
|
||||
"console",
|
||||
"globset",
|
||||
@@ -1925,14 +1925,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.2"
|
||||
version = "1.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
||||
checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata 0.4.3",
|
||||
"regex-syntax 0.8.2",
|
||||
"regex-automata 0.3.9",
|
||||
"regex-syntax 0.7.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1949,16 +1949,10 @@ name = "regex-automata"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9"
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax 0.8.2",
|
||||
"regex-syntax 0.7.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1973,12 +1967,6 @@ version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
|
||||
[[package]]
|
||||
name = "result-like"
|
||||
version = "0.4.6"
|
||||
@@ -2051,7 +2039,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_cli"
|
||||
version = "0.1.0"
|
||||
version = "0.0.292"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.9.1",
|
||||
"anyhow",
|
||||
@@ -2188,7 +2176,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_linter"
|
||||
version = "0.1.0"
|
||||
version = "0.0.292"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"annotate-snippets 0.9.1",
|
||||
@@ -2658,9 +2646,9 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.20"
|
||||
version = "1.0.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
|
||||
checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
@@ -3260,9 +3248,8 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode_names2"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d5506ae2c3c1ccbdf468e52fc5ef536c2ccd981f01273a4cb81aa61021f3a5f"
|
||||
version = "1.1.0"
|
||||
source = "git+https://github.com/konstin/unicode_names2?rev=e2ee8155795a13afbea5caa4dbce8d1f93bc26eb#e2ee8155795a13afbea5caa4dbce8d1f93bc26eb"
|
||||
dependencies = [
|
||||
"phf",
|
||||
"unicode_names2_generator",
|
||||
@@ -3270,9 +3257,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "unicode_names2_generator"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6dfc680313e95bc6637fa278cd7a22390c3c2cd7b8b2bd28755bc6c0fc811e7"
|
||||
version = "1.1.0"
|
||||
source = "git+https://github.com/konstin/unicode_names2?rev=e2ee8155795a13afbea5caa4dbce8d1f93bc26eb#e2ee8155795a13afbea5caa4dbce8d1f93bc26eb"
|
||||
dependencies = [
|
||||
"getopts",
|
||||
"log",
|
||||
|
||||
@@ -21,7 +21,7 @@ filetime = { version = "0.2.20" }
|
||||
glob = { version = "0.3.1" }
|
||||
globset = { version = "0.4.10" }
|
||||
ignore = { version = "0.4.20" }
|
||||
insta = { version = "1.34.0", feature = ["filters", "glob"] }
|
||||
insta = { version = "1.33.0", feature = ["filters", "glob"] }
|
||||
is-macro = { version = "0.3.0" }
|
||||
itertools = { version = "0.11.0" }
|
||||
libcst = { version = "1.1.0", default-features = false }
|
||||
@@ -31,7 +31,7 @@ once_cell = { version = "1.17.1" }
|
||||
path-absolutize = { version = "3.1.1" }
|
||||
proc-macro2 = { version = "1.0.69" }
|
||||
quote = { version = "1.0.23" }
|
||||
regex = { version = "1.10.2" }
|
||||
regex = { version = "1.9.6" }
|
||||
rustc-hash = { version = "1.1.0" }
|
||||
schemars = { version = "0.8.15" }
|
||||
serde = { version = "1.0.152", features = ["derive"] }
|
||||
@@ -50,7 +50,7 @@ tracing = { version = "0.1.37" }
|
||||
tracing-indicatif = { version = "0.3.4" }
|
||||
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
||||
unicode-ident = { version = "1.0.12" }
|
||||
unicode_names2 = { version = "1.2.0" }
|
||||
unicode_names2 = { git = "https://github.com/konstin/unicode_names2", rev = "e2ee8155795a13afbea5caa4dbce8d1f93bc26eb" }
|
||||
unicode-width = { version = "0.1.11" }
|
||||
uuid = { version = "1.4.1", features = ["v4", "fast-rng", "macro-diagnostics", "js"] }
|
||||
wsl = { version = "0.1.0" }
|
||||
|
||||
@@ -140,7 +140,7 @@ Ruff can also be used as a [pre-commit](https://pre-commit.com) hook:
|
||||
```yaml
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.1.0
|
||||
rev: v0.0.292
|
||||
hooks:
|
||||
- id: ruff
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.1.0"
|
||||
version = "0.0.292"
|
||||
description = """
|
||||
Convert Flake8 configuration files to Ruff configuration files.
|
||||
"""
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_cli"
|
||||
version = "0.1.0"
|
||||
version = "0.0.292"
|
||||
publish = false
|
||||
authors = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
|
||||
@@ -117,6 +117,16 @@ pub struct CheckCommand {
|
||||
#[arg(long)]
|
||||
ignore_noqa: bool,
|
||||
|
||||
/// Output serialization format for violations. (Deprecated: Use `--output-format` instead).
|
||||
#[arg(
|
||||
long,
|
||||
value_enum,
|
||||
env = "RUFF_FORMAT",
|
||||
conflicts_with = "output_format",
|
||||
hide = true
|
||||
)]
|
||||
pub format: Option<SerializationFormat>,
|
||||
|
||||
/// Output serialization format for violations.
|
||||
#[arg(long, value_enum, env = "RUFF_OUTPUT_FORMAT")]
|
||||
pub output_format: Option<SerializationFormat>,
|
||||
@@ -497,7 +507,7 @@ impl CheckCommand {
|
||||
unsafe_fixes: resolve_bool_arg(self.unsafe_fixes, self.no_unsafe_fixes)
|
||||
.map(UnsafeFixes::from),
|
||||
force_exclude: resolve_bool_arg(self.force_exclude, self.no_force_exclude),
|
||||
output_format: self.output_format,
|
||||
output_format: self.output_format.or(self.format),
|
||||
show_fixes: resolve_bool_arg(self.show_fixes, self.no_show_fixes),
|
||||
},
|
||||
)
|
||||
|
||||
@@ -177,6 +177,14 @@ fn format(args: FormatCommand, log_level: LogLevel) -> Result<ExitStatus> {
|
||||
}
|
||||
|
||||
pub fn check(args: CheckCommand, log_level: LogLevel) -> Result<ExitStatus> {
|
||||
if args.format.is_some() {
|
||||
if std::env::var("RUFF_FORMAT").is_ok() {
|
||||
warn_user!("The environment variable `RUFF_FORMAT` is deprecated. Use `RUFF_OUTPUT_FORMAT` instead.");
|
||||
} else {
|
||||
warn_user!("The argument `--format=<FORMAT>` is deprecated. Use `--output-format=<FORMAT>` instead.");
|
||||
}
|
||||
}
|
||||
|
||||
let (cli, overrides) = args.partition();
|
||||
|
||||
// Construct the "default" settings. These are used when no `pyproject.toml`
|
||||
|
||||
@@ -161,7 +161,7 @@ impl Printer {
|
||||
"es"
|
||||
};
|
||||
writeln!(writer,
|
||||
"No fixes available ({} hidden fix{es} can be enabled with the `--unsafe-fixes` option).",
|
||||
"{} hidden fix{es} can be enabled with the `--unsafe-fixes` option.",
|
||||
fixables.unapplicable_unsafe
|
||||
)?;
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ if condition:
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Since 0.1.0 the legacy format option is no longer supported
|
||||
/// Tests that the legacy `format` option continues to work but emits a warning.
|
||||
#[test]
|
||||
fn legacy_format_option() -> Result<()> {
|
||||
let tempdir = TempDir::new()?;
|
||||
@@ -156,29 +156,53 @@ format = "json"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
insta::with_settings!({filters => vec![
|
||||
(&*regex::escape(ruff_toml.to_str().unwrap()), "[RUFF-TOML-PATH]"),
|
||||
]}, {
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(["check", "--select", "F401", "--no-cache", "--config"])
|
||||
.arg(&ruff_toml)
|
||||
.arg("-")
|
||||
.pass_stdin(r#"
|
||||
import os
|
||||
"#), @r###"
|
||||
success: false
|
||||
exit_code: 2
|
||||
----- stdout -----
|
||||
|
||||
----- stderr -----
|
||||
ruff failed
|
||||
Cause: Failed to parse `[RUFF-TOML-PATH]`: TOML parse error at line 2, column 10
|
||||
|
|
||||
2 | format = "json"
|
||||
| ^^^^^^
|
||||
invalid type: string "json", expected struct FormatOptions
|
||||
|
||||
"###);
|
||||
});
|
||||
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(["check", "--select", "F401", "--no-cache", "--config"])
|
||||
.arg(&ruff_toml)
|
||||
.arg("-")
|
||||
.pass_stdin(r#"
|
||||
import os
|
||||
"#), @r###"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
[
|
||||
{
|
||||
"cell": null,
|
||||
"code": "F401",
|
||||
"end_location": {
|
||||
"column": 10,
|
||||
"row": 2
|
||||
},
|
||||
"filename": "-",
|
||||
"fix": {
|
||||
"applicability": "safe",
|
||||
"edits": [
|
||||
{
|
||||
"content": "",
|
||||
"end_location": {
|
||||
"column": 1,
|
||||
"row": 3
|
||||
},
|
||||
"location": {
|
||||
"column": 1,
|
||||
"row": 2
|
||||
}
|
||||
}
|
||||
],
|
||||
"message": "Remove unused import: `os`"
|
||||
},
|
||||
"location": {
|
||||
"column": 8,
|
||||
"row": 2
|
||||
},
|
||||
"message": "`os` imported but unused",
|
||||
"noqa_row": 2,
|
||||
"url": "https://docs.astral.sh/ruff/rules/unused-import"
|
||||
}
|
||||
]
|
||||
----- stderr -----
|
||||
warning: The option `format` has been deprecated to avoid ambiguity with Ruff's upcoming formatter. Use `output-format` instead.
|
||||
"###);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -945,7 +945,7 @@ fn check_hints_hidden_unsafe_fixes_with_no_safe_fixes() {
|
||||
----- stdout -----
|
||||
-:1:14: F601 Dictionary key literal `'a'` repeated
|
||||
Found 1 error.
|
||||
No fixes available (1 hidden fix can be enabled with the `--unsafe-fixes` option).
|
||||
1 hidden fix can be enabled with the `--unsafe-fixes` option.
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
@@ -1002,7 +1002,7 @@ fn fix_applies_safe_fixes_by_default() {
|
||||
----- stderr -----
|
||||
-:1:14: F601 Dictionary key literal `'a'` repeated
|
||||
Found 2 errors (1 fixed, 1 remaining).
|
||||
No fixes available (1 hidden fix can be enabled with the `--unsafe-fixes` option).
|
||||
1 hidden fix can be enabled with the `--unsafe-fixes` option.
|
||||
"###);
|
||||
}
|
||||
|
||||
@@ -1112,7 +1112,7 @@ fn fix_only_unsafe_fixes_available() {
|
||||
----- stderr -----
|
||||
-:1:14: F601 Dictionary key literal `'a'` repeated
|
||||
Found 1 error.
|
||||
No fixes available (1 hidden fix can be enabled with the `--unsafe-fixes` option).
|
||||
1 hidden fix can be enabled with the `--unsafe-fixes` option.
|
||||
"###);
|
||||
}
|
||||
|
||||
@@ -1317,7 +1317,7 @@ extend-unsafe-fixes = ["UP034"]
|
||||
-:1:14: F601 Dictionary key literal `'a'` repeated
|
||||
-:2:7: UP034 Avoid extraneous parentheses
|
||||
Found 2 errors.
|
||||
No fixes available (2 hidden fixes can be enabled with the `--unsafe-fixes` option).
|
||||
2 hidden fixes can be enabled with the `--unsafe-fixes` option.
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
@@ -1397,7 +1397,7 @@ extend-safe-fixes = ["UP034"]
|
||||
-:1:14: F601 Dictionary key literal `'a'` repeated
|
||||
-:2:7: UP034 Avoid extraneous parentheses
|
||||
Found 2 errors.
|
||||
No fixes available (2 hidden fixes can be enabled with the `--unsafe-fixes` option).
|
||||
2 hidden fixes can be enabled with the `--unsafe-fixes` option.
|
||||
|
||||
----- stderr -----
|
||||
"###);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_linter"
|
||||
version = "0.1.0"
|
||||
version = "0.0.292"
|
||||
publish = false
|
||||
authors = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
@@ -29,7 +29,7 @@ ruff_python_parser = { path = "../ruff_python_parser" }
|
||||
ruff_source_file = { path = "../ruff_source_file", features = ["serde"] }
|
||||
ruff_text_size = { path = "../ruff_text_size" }
|
||||
|
||||
aho-corasick = { version = "1.1.2" }
|
||||
aho-corasick = { version = "1.1.1" }
|
||||
annotate-snippets = { version = "0.9.1", features = ["color"] }
|
||||
anyhow = { workspace = true }
|
||||
bitflags = { workspace = true }
|
||||
@@ -59,7 +59,7 @@ regex = { workspace = true }
|
||||
result-like = { version = "0.4.6" }
|
||||
rustc-hash = { workspace = true }
|
||||
schemars = { workspace = true, optional = true }
|
||||
semver = { version = "1.0.20" }
|
||||
semver = { version = "1.0.19" }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
similar = { workspace = true }
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .foo import Record
|
||||
|
||||
type RecordOrThings = Record | int | str
|
||||
type RecordCallback[R: Record] = Callable[[R], None]
|
||||
|
||||
|
||||
def process_record[R: Record](record: R) -> None:
|
||||
...
|
||||
|
||||
|
||||
class RecordContainer[R: Record]:
|
||||
def add_record(self, record: R) -> None:
|
||||
...
|
||||
@@ -22,10 +22,3 @@ class C:
|
||||
|
||||
class D(C):
|
||||
x: UUID
|
||||
|
||||
|
||||
import collections
|
||||
|
||||
|
||||
class E(BaseModel[int]):
|
||||
x: collections.Awaitable
|
||||
|
||||
@@ -63,11 +63,6 @@ class Apples:
|
||||
def __html__(self):
|
||||
pass
|
||||
|
||||
# Allow _missing_, used by enum.Enum.
|
||||
@classmethod
|
||||
def _missing_(cls, value):
|
||||
pass
|
||||
|
||||
|
||||
def __foo_bar__(): # this is not checked by the [bad-dunder-name] rule
|
||||
...
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import abc
|
||||
|
||||
from typing_extensions import override
|
||||
|
||||
|
||||
class Person:
|
||||
def developer_greeting(self, name): # [no-self-use]
|
||||
@@ -62,24 +60,3 @@ class Prop:
|
||||
@property
|
||||
def count(self):
|
||||
return 24
|
||||
|
||||
|
||||
class A:
|
||||
def foo(self):
|
||||
...
|
||||
|
||||
|
||||
class B(A):
|
||||
@override
|
||||
def foo(self):
|
||||
...
|
||||
|
||||
def foobar(self):
|
||||
super()
|
||||
|
||||
def bar(self):
|
||||
super().foo()
|
||||
|
||||
def baz(self):
|
||||
if super().foo():
|
||||
...
|
||||
|
||||
@@ -306,7 +306,7 @@ pub(crate) fn deferred_scopes(checker: &mut Checker) {
|
||||
|
||||
if scope.kind.is_function() {
|
||||
if checker.enabled(Rule::NoSelfUse) {
|
||||
pylint::rules::no_self_use(checker, scope_id, scope, &mut diagnostics);
|
||||
pylint::rules::no_self_use(checker, scope, &mut diagnostics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,9 +580,7 @@ where
|
||||
if let Some(type_params) = type_params {
|
||||
self.visit_type_params(type_params);
|
||||
}
|
||||
// The value in a `type` alias has annotation semantics, in that it's never
|
||||
// evaluated at runtime.
|
||||
self.visit_annotation(value);
|
||||
self.visit_expr(value);
|
||||
self.semantic.pop_scope();
|
||||
self.visit_expr(name);
|
||||
}
|
||||
@@ -1768,7 +1766,7 @@ impl<'a> Checker<'a> {
|
||||
bound: Some(bound), ..
|
||||
}) = type_param
|
||||
{
|
||||
self.visit_annotation(bound);
|
||||
self.visit_expr(bound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use ruff_diagnostics::{Diagnostic, Violation};
|
||||
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
|
||||
use ruff_macros::{derive_message_formats, violation};
|
||||
use ruff_python_ast::{self as ast, Expr};
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
|
||||
use crate::rules::flake8_pyi::helpers::traverse_union;
|
||||
|
||||
/// ## What it does
|
||||
@@ -31,7 +32,7 @@ pub struct UnnecessaryLiteralUnion {
|
||||
members: Vec<String>,
|
||||
}
|
||||
|
||||
impl Violation for UnnecessaryLiteralUnion {
|
||||
impl AlwaysFixableViolation for UnnecessaryLiteralUnion {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
format!(
|
||||
@@ -39,13 +40,17 @@ impl Violation for UnnecessaryLiteralUnion {
|
||||
self.members.join(", ")
|
||||
)
|
||||
}
|
||||
|
||||
fn fix_title(&self) -> String {
|
||||
format!("Replace with a single `Literal`")
|
||||
}
|
||||
}
|
||||
|
||||
/// PYI030
|
||||
pub(crate) fn unnecessary_literal_union<'a>(checker: &mut Checker, expr: &'a Expr) {
|
||||
let mut literal_exprs = Vec::new();
|
||||
|
||||
// Adds a member to `literal_exprs` if it is a `Literal` annotation
|
||||
// Adds a member to `literal_exprs` if it is a `Literal` annotation.
|
||||
let mut collect_literal_expr = |expr: &'a Expr, _| {
|
||||
if let Expr::Subscript(ast::ExprSubscript { value, slice, .. }) = expr {
|
||||
if checker.semantic().match_typing_expr(value, "Literal") {
|
||||
@@ -54,21 +59,28 @@ pub(crate) fn unnecessary_literal_union<'a>(checker: &mut Checker, expr: &'a Exp
|
||||
}
|
||||
};
|
||||
|
||||
// Traverse the union, collect all literal members
|
||||
// Traverse the union, collect all literal members.
|
||||
traverse_union(&mut collect_literal_expr, checker.semantic(), expr, None);
|
||||
|
||||
// Raise a violation if more than one
|
||||
// Raise a violation if more than one.
|
||||
if literal_exprs.len() > 1 {
|
||||
let diagnostic = Diagnostic::new(
|
||||
let literal_members: Vec<String> = literal_exprs
|
||||
.into_iter()
|
||||
.map(|expr| checker.locator().slice(expr.as_ref()).to_string())
|
||||
.collect();
|
||||
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
UnnecessaryLiteralUnion {
|
||||
members: literal_exprs
|
||||
.into_iter()
|
||||
.map(|expr| checker.locator().slice(expr.as_ref()).to_string())
|
||||
.collect(),
|
||||
members: literal_members.clone(),
|
||||
},
|
||||
expr.range(),
|
||||
);
|
||||
|
||||
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
|
||||
format!("Literal[{}]", literal_members.join(", ")),
|
||||
expr.range(),
|
||||
)));
|
||||
|
||||
checker.diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI030.py:9:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
PYI030.py:9:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
8 | # Should emit for duplicate field types.
|
||||
9 | field2: Literal[1] | Literal[2] # Error
|
||||
@@ -9,24 +9,57 @@ PYI030.py:9:9: PYI030 Multiple literal members in a union. Use a single literal,
|
||||
10 |
|
||||
11 | # Should emit for union types in arguments.
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.py:12:17: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
6 6 | field1: Literal[1] # OK
|
||||
7 7 |
|
||||
8 8 | # Should emit for duplicate field types.
|
||||
9 |-field2: Literal[1] | Literal[2] # Error
|
||||
9 |+field2: Literal[1, 2] # Error
|
||||
10 10 |
|
||||
11 11 | # Should emit for union types in arguments.
|
||||
12 12 | def func1(arg1: Literal[1] | Literal[2]): # Error
|
||||
|
||||
PYI030.py:12:17: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
11 | # Should emit for union types in arguments.
|
||||
12 | def func1(arg1: Literal[1] | Literal[2]): # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
13 | print(arg1)
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.py:17:16: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
9 9 | field2: Literal[1] | Literal[2] # Error
|
||||
10 10 |
|
||||
11 11 | # Should emit for union types in arguments.
|
||||
12 |-def func1(arg1: Literal[1] | Literal[2]): # Error
|
||||
12 |+def func1(arg1: Literal[1, 2]): # Error
|
||||
13 13 | print(arg1)
|
||||
14 14 |
|
||||
15 15 |
|
||||
|
||||
PYI030.py:17:16: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
16 | # Should emit for unions in return types.
|
||||
17 | def func2() -> Literal[1] | Literal[2]: # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
18 | return "my Literal[1]ing"
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.py:22:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
14 14 |
|
||||
15 15 |
|
||||
16 16 | # Should emit for unions in return types.
|
||||
17 |-def func2() -> Literal[1] | Literal[2]: # Error
|
||||
17 |+def func2() -> Literal[1, 2]: # Error
|
||||
18 18 | return "my Literal[1]ing"
|
||||
19 19 |
|
||||
20 20 |
|
||||
|
||||
PYI030.py:22:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
21 | # Should emit in longer unions, even if not directly adjacent.
|
||||
22 | field3: Literal[1] | Literal[2] | str # Error
|
||||
@@ -34,8 +67,19 @@ PYI030.py:22:9: PYI030 Multiple literal members in a union. Use a single literal
|
||||
23 | field4: str | Literal[1] | Literal[2] # Error
|
||||
24 | field5: Literal[1] | str | Literal[2] # Error
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.py:23:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
19 19 |
|
||||
20 20 |
|
||||
21 21 | # Should emit in longer unions, even if not directly adjacent.
|
||||
22 |-field3: Literal[1] | Literal[2] | str # Error
|
||||
22 |+field3: Literal[1, 2] # Error
|
||||
23 23 | field4: str | Literal[1] | Literal[2] # Error
|
||||
24 24 | field5: Literal[1] | str | Literal[2] # Error
|
||||
25 25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
||||
|
||||
PYI030.py:23:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
21 | # Should emit in longer unions, even if not directly adjacent.
|
||||
22 | field3: Literal[1] | Literal[2] | str # Error
|
||||
@@ -44,8 +88,19 @@ PYI030.py:23:9: PYI030 Multiple literal members in a union. Use a single literal
|
||||
24 | field5: Literal[1] | str | Literal[2] # Error
|
||||
25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.py:24:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
20 20 |
|
||||
21 21 | # Should emit in longer unions, even if not directly adjacent.
|
||||
22 22 | field3: Literal[1] | Literal[2] | str # Error
|
||||
23 |-field4: str | Literal[1] | Literal[2] # Error
|
||||
23 |+field4: Literal[1, 2] # Error
|
||||
24 24 | field5: Literal[1] | str | Literal[2] # Error
|
||||
25 25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
||||
26 26 |
|
||||
|
||||
PYI030.py:24:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
22 | field3: Literal[1] | Literal[2] | str # Error
|
||||
23 | field4: str | Literal[1] | Literal[2] # Error
|
||||
@@ -53,8 +108,19 @@ PYI030.py:24:9: PYI030 Multiple literal members in a union. Use a single literal
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.py:25:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
21 21 | # Should emit in longer unions, even if not directly adjacent.
|
||||
22 22 | field3: Literal[1] | Literal[2] | str # Error
|
||||
23 23 | field4: str | Literal[1] | Literal[2] # Error
|
||||
24 |-field5: Literal[1] | str | Literal[2] # Error
|
||||
24 |+field5: Literal[1, 2] # Error
|
||||
25 25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
||||
26 26 |
|
||||
27 27 | # Should emit for non-type unions.
|
||||
|
||||
PYI030.py:25:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
23 | field4: str | Literal[1] | Literal[2] # Error
|
||||
24 | field5: Literal[1] | str | Literal[2] # Error
|
||||
@@ -63,8 +129,19 @@ PYI030.py:25:9: PYI030 Multiple literal members in a union. Use a single literal
|
||||
26 |
|
||||
27 | # Should emit for non-type unions.
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.py:28:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
22 22 | field3: Literal[1] | Literal[2] | str # Error
|
||||
23 23 | field4: str | Literal[1] | Literal[2] # Error
|
||||
24 24 | field5: Literal[1] | str | Literal[2] # Error
|
||||
25 |-field6: Literal[1] | bool | Literal[2] | str # Error
|
||||
25 |+field6: Literal[1, 2] # Error
|
||||
26 26 |
|
||||
27 27 | # Should emit for non-type unions.
|
||||
28 28 | field7 = Literal[1] | Literal[2] # Error
|
||||
|
||||
PYI030.py:28:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
27 | # Should emit for non-type unions.
|
||||
28 | field7 = Literal[1] | Literal[2] # Error
|
||||
@@ -72,8 +149,19 @@ PYI030.py:28:10: PYI030 Multiple literal members in a union. Use a single litera
|
||||
29 |
|
||||
30 | # Should emit for parenthesized unions.
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.py:31:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
25 25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
||||
26 26 |
|
||||
27 27 | # Should emit for non-type unions.
|
||||
28 |-field7 = Literal[1] | Literal[2] # Error
|
||||
28 |+field7 = Literal[1, 2] # Error
|
||||
29 29 |
|
||||
30 30 | # Should emit for parenthesized unions.
|
||||
31 31 | field8: Literal[1] | (Literal[2] | str) # Error
|
||||
|
||||
PYI030.py:31:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
30 | # Should emit for parenthesized unions.
|
||||
31 | field8: Literal[1] | (Literal[2] | str) # Error
|
||||
@@ -81,16 +169,38 @@ PYI030.py:31:9: PYI030 Multiple literal members in a union. Use a single literal
|
||||
32 |
|
||||
33 | # Should handle user parentheses when fixing.
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.py:34:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
28 28 | field7 = Literal[1] | Literal[2] # Error
|
||||
29 29 |
|
||||
30 30 | # Should emit for parenthesized unions.
|
||||
31 |-field8: Literal[1] | (Literal[2] | str) # Error
|
||||
31 |+field8: Literal[1, 2] # Error
|
||||
32 32 |
|
||||
33 33 | # Should handle user parentheses when fixing.
|
||||
34 34 | field9: Literal[1] | (Literal[2] | str) # Error
|
||||
|
||||
PYI030.py:34:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
33 | # Should handle user parentheses when fixing.
|
||||
34 | field9: Literal[1] | (Literal[2] | str) # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
35 | field10: (Literal[1] | str) | Literal[2] # Error
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.py:35:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
31 31 | field8: Literal[1] | (Literal[2] | str) # Error
|
||||
32 32 |
|
||||
33 33 | # Should handle user parentheses when fixing.
|
||||
34 |-field9: Literal[1] | (Literal[2] | str) # Error
|
||||
34 |+field9: Literal[1, 2] # Error
|
||||
35 35 | field10: (Literal[1] | str) | Literal[2] # Error
|
||||
36 36 |
|
||||
37 37 | # Should emit for union in generic parent type.
|
||||
|
||||
PYI030.py:35:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
33 | # Should handle user parentheses when fixing.
|
||||
34 | field9: Literal[1] | (Literal[2] | str) # Error
|
||||
@@ -99,12 +209,31 @@ PYI030.py:35:10: PYI030 Multiple literal members in a union. Use a single litera
|
||||
36 |
|
||||
37 | # Should emit for union in generic parent type.
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.py:38:15: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
32 32 |
|
||||
33 33 | # Should handle user parentheses when fixing.
|
||||
34 34 | field9: Literal[1] | (Literal[2] | str) # Error
|
||||
35 |-field10: (Literal[1] | str) | Literal[2] # Error
|
||||
35 |+field10: Literal[1, 2] # Error
|
||||
36 36 |
|
||||
37 37 | # Should emit for union in generic parent type.
|
||||
38 38 | field11: dict[Literal[1] | Literal[2], str] # Error
|
||||
|
||||
PYI030.py:38:15: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
37 | # Should emit for union in generic parent type.
|
||||
38 | field11: dict[Literal[1] | Literal[2], str] # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
ℹ Fix
|
||||
35 35 | field10: (Literal[1] | str) | Literal[2] # Error
|
||||
36 36 |
|
||||
37 37 | # Should emit for union in generic parent type.
|
||||
38 |-field11: dict[Literal[1] | Literal[2], str] # Error
|
||||
38 |+field11: dict[Literal[1, 2], str] # Error
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_pyi/mod.rs
|
||||
---
|
||||
PYI030.pyi:9:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
PYI030.pyi:9:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
8 | # Should emit for duplicate field types.
|
||||
9 | field2: Literal[1] | Literal[2] # Error
|
||||
@@ -9,24 +9,57 @@ PYI030.pyi:9:9: PYI030 Multiple literal members in a union. Use a single literal
|
||||
10 |
|
||||
11 | # Should emit for union types in arguments.
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:12:17: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
6 6 | field1: Literal[1] # OK
|
||||
7 7 |
|
||||
8 8 | # Should emit for duplicate field types.
|
||||
9 |-field2: Literal[1] | Literal[2] # Error
|
||||
9 |+field2: Literal[1, 2] # Error
|
||||
10 10 |
|
||||
11 11 | # Should emit for union types in arguments.
|
||||
12 12 | def func1(arg1: Literal[1] | Literal[2]): # Error
|
||||
|
||||
PYI030.pyi:12:17: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
11 | # Should emit for union types in arguments.
|
||||
12 | def func1(arg1: Literal[1] | Literal[2]): # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
13 | print(arg1)
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:17:16: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
9 9 | field2: Literal[1] | Literal[2] # Error
|
||||
10 10 |
|
||||
11 11 | # Should emit for union types in arguments.
|
||||
12 |-def func1(arg1: Literal[1] | Literal[2]): # Error
|
||||
12 |+def func1(arg1: Literal[1, 2]): # Error
|
||||
13 13 | print(arg1)
|
||||
14 14 |
|
||||
15 15 |
|
||||
|
||||
PYI030.pyi:17:16: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
16 | # Should emit for unions in return types.
|
||||
17 | def func2() -> Literal[1] | Literal[2]: # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
18 | return "my Literal[1]ing"
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:22:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
14 14 |
|
||||
15 15 |
|
||||
16 16 | # Should emit for unions in return types.
|
||||
17 |-def func2() -> Literal[1] | Literal[2]: # Error
|
||||
17 |+def func2() -> Literal[1, 2]: # Error
|
||||
18 18 | return "my Literal[1]ing"
|
||||
19 19 |
|
||||
20 20 |
|
||||
|
||||
PYI030.pyi:22:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
21 | # Should emit in longer unions, even if not directly adjacent.
|
||||
22 | field3: Literal[1] | Literal[2] | str # Error
|
||||
@@ -34,8 +67,19 @@ PYI030.pyi:22:9: PYI030 Multiple literal members in a union. Use a single litera
|
||||
23 | field4: str | Literal[1] | Literal[2] # Error
|
||||
24 | field5: Literal[1] | str | Literal[2] # Error
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:23:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
19 19 |
|
||||
20 20 |
|
||||
21 21 | # Should emit in longer unions, even if not directly adjacent.
|
||||
22 |-field3: Literal[1] | Literal[2] | str # Error
|
||||
22 |+field3: Literal[1, 2] # Error
|
||||
23 23 | field4: str | Literal[1] | Literal[2] # Error
|
||||
24 24 | field5: Literal[1] | str | Literal[2] # Error
|
||||
25 25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
||||
|
||||
PYI030.pyi:23:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
21 | # Should emit in longer unions, even if not directly adjacent.
|
||||
22 | field3: Literal[1] | Literal[2] | str # Error
|
||||
@@ -44,8 +88,19 @@ PYI030.pyi:23:9: PYI030 Multiple literal members in a union. Use a single litera
|
||||
24 | field5: Literal[1] | str | Literal[2] # Error
|
||||
25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:24:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
20 20 |
|
||||
21 21 | # Should emit in longer unions, even if not directly adjacent.
|
||||
22 22 | field3: Literal[1] | Literal[2] | str # Error
|
||||
23 |-field4: str | Literal[1] | Literal[2] # Error
|
||||
23 |+field4: Literal[1, 2] # Error
|
||||
24 24 | field5: Literal[1] | str | Literal[2] # Error
|
||||
25 25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
||||
26 26 |
|
||||
|
||||
PYI030.pyi:24:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
22 | field3: Literal[1] | Literal[2] | str # Error
|
||||
23 | field4: str | Literal[1] | Literal[2] # Error
|
||||
@@ -53,8 +108,19 @@ PYI030.pyi:24:9: PYI030 Multiple literal members in a union. Use a single litera
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:25:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
21 21 | # Should emit in longer unions, even if not directly adjacent.
|
||||
22 22 | field3: Literal[1] | Literal[2] | str # Error
|
||||
23 23 | field4: str | Literal[1] | Literal[2] # Error
|
||||
24 |-field5: Literal[1] | str | Literal[2] # Error
|
||||
24 |+field5: Literal[1, 2] # Error
|
||||
25 25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
||||
26 26 |
|
||||
27 27 | # Should emit for non-type unions.
|
||||
|
||||
PYI030.pyi:25:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
23 | field4: str | Literal[1] | Literal[2] # Error
|
||||
24 | field5: Literal[1] | str | Literal[2] # Error
|
||||
@@ -63,8 +129,19 @@ PYI030.pyi:25:9: PYI030 Multiple literal members in a union. Use a single litera
|
||||
26 |
|
||||
27 | # Should emit for non-type unions.
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:28:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
22 22 | field3: Literal[1] | Literal[2] | str # Error
|
||||
23 23 | field4: str | Literal[1] | Literal[2] # Error
|
||||
24 24 | field5: Literal[1] | str | Literal[2] # Error
|
||||
25 |-field6: Literal[1] | bool | Literal[2] | str # Error
|
||||
25 |+field6: Literal[1, 2] # Error
|
||||
26 26 |
|
||||
27 27 | # Should emit for non-type unions.
|
||||
28 28 | field7 = Literal[1] | Literal[2] # Error
|
||||
|
||||
PYI030.pyi:28:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
27 | # Should emit for non-type unions.
|
||||
28 | field7 = Literal[1] | Literal[2] # Error
|
||||
@@ -72,8 +149,19 @@ PYI030.pyi:28:10: PYI030 Multiple literal members in a union. Use a single liter
|
||||
29 |
|
||||
30 | # Should emit for parenthesized unions.
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:31:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
25 25 | field6: Literal[1] | bool | Literal[2] | str # Error
|
||||
26 26 |
|
||||
27 27 | # Should emit for non-type unions.
|
||||
28 |-field7 = Literal[1] | Literal[2] # Error
|
||||
28 |+field7 = Literal[1, 2] # Error
|
||||
29 29 |
|
||||
30 30 | # Should emit for parenthesized unions.
|
||||
31 31 | field8: Literal[1] | (Literal[2] | str) # Error
|
||||
|
||||
PYI030.pyi:31:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
30 | # Should emit for parenthesized unions.
|
||||
31 | field8: Literal[1] | (Literal[2] | str) # Error
|
||||
@@ -81,16 +169,38 @@ PYI030.pyi:31:9: PYI030 Multiple literal members in a union. Use a single litera
|
||||
32 |
|
||||
33 | # Should handle user parentheses when fixing.
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:34:9: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
28 28 | field7 = Literal[1] | Literal[2] # Error
|
||||
29 29 |
|
||||
30 30 | # Should emit for parenthesized unions.
|
||||
31 |-field8: Literal[1] | (Literal[2] | str) # Error
|
||||
31 |+field8: Literal[1, 2] # Error
|
||||
32 32 |
|
||||
33 33 | # Should handle user parentheses when fixing.
|
||||
34 34 | field9: Literal[1] | (Literal[2] | str) # Error
|
||||
|
||||
PYI030.pyi:34:9: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
33 | # Should handle user parentheses when fixing.
|
||||
34 | field9: Literal[1] | (Literal[2] | str) # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
35 | field10: (Literal[1] | str) | Literal[2] # Error
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:35:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
31 31 | field8: Literal[1] | (Literal[2] | str) # Error
|
||||
32 32 |
|
||||
33 33 | # Should handle user parentheses when fixing.
|
||||
34 |-field9: Literal[1] | (Literal[2] | str) # Error
|
||||
34 |+field9: Literal[1, 2] # Error
|
||||
35 35 | field10: (Literal[1] | str) | Literal[2] # Error
|
||||
36 36 |
|
||||
37 37 | # Should emit for union in generic parent type.
|
||||
|
||||
PYI030.pyi:35:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
33 | # Should handle user parentheses when fixing.
|
||||
34 | field9: Literal[1] | (Literal[2] | str) # Error
|
||||
@@ -99,8 +209,19 @@ PYI030.pyi:35:10: PYI030 Multiple literal members in a union. Use a single liter
|
||||
36 |
|
||||
37 | # Should emit for union in generic parent type.
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:38:15: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
32 32 |
|
||||
33 33 | # Should handle user parentheses when fixing.
|
||||
34 34 | field9: Literal[1] | (Literal[2] | str) # Error
|
||||
35 |-field10: (Literal[1] | str) | Literal[2] # Error
|
||||
35 |+field10: Literal[1, 2] # Error
|
||||
36 36 |
|
||||
37 37 | # Should emit for union in generic parent type.
|
||||
38 38 | field11: dict[Literal[1] | Literal[2], str] # Error
|
||||
|
||||
PYI030.pyi:38:15: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
37 | # Should emit for union in generic parent type.
|
||||
38 | field11: dict[Literal[1] | Literal[2], str] # Error
|
||||
@@ -108,16 +229,38 @@ PYI030.pyi:38:15: PYI030 Multiple literal members in a union. Use a single liter
|
||||
39 |
|
||||
40 | # Should emit for unions with more than two cases
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:41:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3]`
|
||||
ℹ Fix
|
||||
35 35 | field10: (Literal[1] | str) | Literal[2] # Error
|
||||
36 36 |
|
||||
37 37 | # Should emit for union in generic parent type.
|
||||
38 |-field11: dict[Literal[1] | Literal[2], str] # Error
|
||||
38 |+field11: dict[Literal[1, 2], str] # Error
|
||||
39 39 |
|
||||
40 40 | # Should emit for unions with more than two cases
|
||||
41 41 | field12: Literal[1] | Literal[2] | Literal[3] # Error
|
||||
|
||||
PYI030.pyi:41:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3]`
|
||||
|
|
||||
40 | # Should emit for unions with more than two cases
|
||||
41 | field12: Literal[1] | Literal[2] | Literal[3] # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
42 | field13: Literal[1] | Literal[2] | Literal[3] | Literal[4] # Error
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:42:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3, 4]`
|
||||
ℹ Fix
|
||||
38 38 | field11: dict[Literal[1] | Literal[2], str] # Error
|
||||
39 39 |
|
||||
40 40 | # Should emit for unions with more than two cases
|
||||
41 |-field12: Literal[1] | Literal[2] | Literal[3] # Error
|
||||
41 |+field12: Literal[1, 2, 3] # Error
|
||||
42 42 | field13: Literal[1] | Literal[2] | Literal[3] | Literal[4] # Error
|
||||
43 43 |
|
||||
44 44 | # Should emit for unions with more than two cases, even if not directly adjacent
|
||||
|
||||
PYI030.pyi:42:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3, 4]`
|
||||
|
|
||||
40 | # Should emit for unions with more than two cases
|
||||
41 | field12: Literal[1] | Literal[2] | Literal[3] # Error
|
||||
@@ -126,8 +269,19 @@ PYI030.pyi:42:10: PYI030 Multiple literal members in a union. Use a single liter
|
||||
43 |
|
||||
44 | # Should emit for unions with more than two cases, even if not directly adjacent
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:45:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3]`
|
||||
ℹ Fix
|
||||
39 39 |
|
||||
40 40 | # Should emit for unions with more than two cases
|
||||
41 41 | field12: Literal[1] | Literal[2] | Literal[3] # Error
|
||||
42 |-field13: Literal[1] | Literal[2] | Literal[3] | Literal[4] # Error
|
||||
42 |+field13: Literal[1, 2, 3, 4] # Error
|
||||
43 43 |
|
||||
44 44 | # Should emit for unions with more than two cases, even if not directly adjacent
|
||||
45 45 | field14: Literal[1] | Literal[2] | str | Literal[3] # Error
|
||||
|
||||
PYI030.pyi:45:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3]`
|
||||
|
|
||||
44 | # Should emit for unions with more than two cases, even if not directly adjacent
|
||||
45 | field14: Literal[1] | Literal[2] | str | Literal[3] # Error
|
||||
@@ -135,8 +289,19 @@ PYI030.pyi:45:10: PYI030 Multiple literal members in a union. Use a single liter
|
||||
46 |
|
||||
47 | # Should emit for unions with mixed literal internal types
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:48:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, "foo", True]`
|
||||
ℹ Fix
|
||||
42 42 | field13: Literal[1] | Literal[2] | Literal[3] | Literal[4] # Error
|
||||
43 43 |
|
||||
44 44 | # Should emit for unions with more than two cases, even if not directly adjacent
|
||||
45 |-field14: Literal[1] | Literal[2] | str | Literal[3] # Error
|
||||
45 |+field14: Literal[1, 2, 3] # Error
|
||||
46 46 |
|
||||
47 47 | # Should emit for unions with mixed literal internal types
|
||||
48 48 | field15: Literal[1] | Literal["foo"] | Literal[True] # Error
|
||||
|
||||
PYI030.pyi:48:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, "foo", True]`
|
||||
|
|
||||
47 | # Should emit for unions with mixed literal internal types
|
||||
48 | field15: Literal[1] | Literal["foo"] | Literal[True] # Error
|
||||
@@ -144,8 +309,19 @@ PYI030.pyi:48:10: PYI030 Multiple literal members in a union. Use a single liter
|
||||
49 |
|
||||
50 | # Shouldn't emit for duplicate field types with same value; covered by Y016
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:51:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 1]`
|
||||
ℹ Fix
|
||||
45 45 | field14: Literal[1] | Literal[2] | str | Literal[3] # Error
|
||||
46 46 |
|
||||
47 47 | # Should emit for unions with mixed literal internal types
|
||||
48 |-field15: Literal[1] | Literal["foo"] | Literal[True] # Error
|
||||
48 |+field15: Literal[1, "foo", True] # Error
|
||||
49 49 |
|
||||
50 50 | # Shouldn't emit for duplicate field types with same value; covered by Y016
|
||||
51 51 | field16: Literal[1] | Literal[1] # OK
|
||||
|
||||
PYI030.pyi:51:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 1]`
|
||||
|
|
||||
50 | # Shouldn't emit for duplicate field types with same value; covered by Y016
|
||||
51 | field16: Literal[1] | Literal[1] # OK
|
||||
@@ -153,8 +329,19 @@ PYI030.pyi:51:10: PYI030 Multiple literal members in a union. Use a single liter
|
||||
52 |
|
||||
53 | # Shouldn't emit if in new parent type
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:60:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
48 48 | field15: Literal[1] | Literal["foo"] | Literal[True] # Error
|
||||
49 49 |
|
||||
50 50 | # Shouldn't emit for duplicate field types with same value; covered by Y016
|
||||
51 |-field16: Literal[1] | Literal[1] # OK
|
||||
51 |+field16: Literal[1, 1] # OK
|
||||
52 52 |
|
||||
53 53 | # Shouldn't emit if in new parent type
|
||||
54 54 | field17: Literal[1] | dict[Literal[2], str] # OK
|
||||
|
||||
PYI030.pyi:60:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
59 | # Should respect name of literal type used
|
||||
60 | field19: typing.Literal[1] | typing.Literal[2] # Error
|
||||
@@ -162,8 +349,19 @@ PYI030.pyi:60:10: PYI030 Multiple literal members in a union. Use a single liter
|
||||
61 |
|
||||
62 | # Should emit in cases with newlines
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:63:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
57 57 | field18: dict[Literal[1], Literal[2]] # OK
|
||||
58 58 |
|
||||
59 59 | # Should respect name of literal type used
|
||||
60 |-field19: typing.Literal[1] | typing.Literal[2] # Error
|
||||
60 |+field19: Literal[1, 2] # Error
|
||||
61 61 |
|
||||
62 62 | # Should emit in cases with newlines
|
||||
63 63 | field20: typing.Union[
|
||||
|
||||
PYI030.pyi:63:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
62 | # Should emit in cases with newlines
|
||||
63 | field20: typing.Union[
|
||||
@@ -177,8 +375,24 @@ PYI030.pyi:63:10: PYI030 Multiple literal members in a union. Use a single liter
|
||||
69 |
|
||||
70 | # Should handle multiple unions with multiple members
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:71:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3, 4]`
|
||||
ℹ Fix
|
||||
60 60 | field19: typing.Literal[1] | typing.Literal[2] # Error
|
||||
61 61 |
|
||||
62 62 | # Should emit in cases with newlines
|
||||
63 |-field20: typing.Union[
|
||||
64 |- Literal[
|
||||
65 |- 1 # test
|
||||
66 |- ],
|
||||
67 |- Literal[2],
|
||||
68 |-] # Error, newline and comment will not be emitted in message
|
||||
63 |+field20: Literal[1, 2] # Error, newline and comment will not be emitted in message
|
||||
69 64 |
|
||||
70 65 | # Should handle multiple unions with multiple members
|
||||
71 66 | field21: Literal[1, 2] | Literal[3, 4] # Error
|
||||
|
||||
PYI030.pyi:71:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3, 4]`
|
||||
|
|
||||
70 | # Should handle multiple unions with multiple members
|
||||
71 | field21: Literal[1, 2] | Literal[3, 4] # Error
|
||||
@@ -186,8 +400,19 @@ PYI030.pyi:71:10: PYI030 Multiple literal members in a union. Use a single liter
|
||||
72 |
|
||||
73 | # Should emit in cases with `typing.Union` instead of `|`
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:74:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
68 68 | ] # Error, newline and comment will not be emitted in message
|
||||
69 69 |
|
||||
70 70 | # Should handle multiple unions with multiple members
|
||||
71 |-field21: Literal[1, 2] | Literal[3, 4] # Error
|
||||
71 |+field21: Literal[1, 2, 3, 4] # Error
|
||||
72 72 |
|
||||
73 73 | # Should emit in cases with `typing.Union` instead of `|`
|
||||
74 74 | field22: typing.Union[Literal[1], Literal[2]] # Error
|
||||
|
||||
PYI030.pyi:74:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
73 | # Should emit in cases with `typing.Union` instead of `|`
|
||||
74 | field22: typing.Union[Literal[1], Literal[2]] # Error
|
||||
@@ -195,8 +420,19 @@ PYI030.pyi:74:10: PYI030 Multiple literal members in a union. Use a single liter
|
||||
75 |
|
||||
76 | # Should emit in cases with `typing_extensions.Literal`
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:77:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
71 71 | field21: Literal[1, 2] | Literal[3, 4] # Error
|
||||
72 72 |
|
||||
73 73 | # Should emit in cases with `typing.Union` instead of `|`
|
||||
74 |-field22: typing.Union[Literal[1], Literal[2]] # Error
|
||||
74 |+field22: Literal[1, 2] # Error
|
||||
75 75 |
|
||||
76 76 | # Should emit in cases with `typing_extensions.Literal`
|
||||
77 77 | field23: typing_extensions.Literal[1] | typing_extensions.Literal[2] # Error
|
||||
|
||||
PYI030.pyi:77:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
76 | # Should emit in cases with `typing_extensions.Literal`
|
||||
77 | field23: typing_extensions.Literal[1] | typing_extensions.Literal[2] # Error
|
||||
@@ -204,8 +440,19 @@ PYI030.pyi:77:10: PYI030 Multiple literal members in a union. Use a single liter
|
||||
78 |
|
||||
79 | # Should emit in cases with nested `typing.Union`
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:80:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
74 74 | field22: typing.Union[Literal[1], Literal[2]] # Error
|
||||
75 75 |
|
||||
76 76 | # Should emit in cases with `typing_extensions.Literal`
|
||||
77 |-field23: typing_extensions.Literal[1] | typing_extensions.Literal[2] # Error
|
||||
77 |+field23: Literal[1, 2] # Error
|
||||
78 78 |
|
||||
79 79 | # Should emit in cases with nested `typing.Union`
|
||||
80 80 | field24: typing.Union[Literal[1], typing.Union[Literal[2], str]] # Error
|
||||
|
||||
PYI030.pyi:80:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
79 | # Should emit in cases with nested `typing.Union`
|
||||
80 | field24: typing.Union[Literal[1], typing.Union[Literal[2], str]] # Error
|
||||
@@ -213,8 +460,19 @@ PYI030.pyi:80:10: PYI030 Multiple literal members in a union. Use a single liter
|
||||
81 |
|
||||
82 | # Should emit in cases with mixed `typing.Union` and `|`
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:83:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
ℹ Fix
|
||||
77 77 | field23: typing_extensions.Literal[1] | typing_extensions.Literal[2] # Error
|
||||
78 78 |
|
||||
79 79 | # Should emit in cases with nested `typing.Union`
|
||||
80 |-field24: typing.Union[Literal[1], typing.Union[Literal[2], str]] # Error
|
||||
80 |+field24: Literal[1, 2] # Error
|
||||
81 81 |
|
||||
82 82 | # Should emit in cases with mixed `typing.Union` and `|`
|
||||
83 83 | field25: typing.Union[Literal[1], Literal[2] | str] # Error
|
||||
|
||||
PYI030.pyi:83:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2]`
|
||||
|
|
||||
82 | # Should emit in cases with mixed `typing.Union` and `|`
|
||||
83 | field25: typing.Union[Literal[1], Literal[2] | str] # Error
|
||||
@@ -222,12 +480,31 @@ PYI030.pyi:83:10: PYI030 Multiple literal members in a union. Use a single liter
|
||||
84 |
|
||||
85 | # Should emit only once in cases with multiple nested `typing.Union`
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
PYI030.pyi:86:10: PYI030 Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3, 4]`
|
||||
ℹ Fix
|
||||
80 80 | field24: typing.Union[Literal[1], typing.Union[Literal[2], str]] # Error
|
||||
81 81 |
|
||||
82 82 | # Should emit in cases with mixed `typing.Union` and `|`
|
||||
83 |-field25: typing.Union[Literal[1], Literal[2] | str] # Error
|
||||
83 |+field25: Literal[1, 2] # Error
|
||||
84 84 |
|
||||
85 85 | # Should emit only once in cases with multiple nested `typing.Union`
|
||||
86 86 | field24: typing.Union[Literal[1], typing.Union[Literal[2], typing.Union[Literal[3], Literal[4]]]] # Error
|
||||
|
||||
PYI030.pyi:86:10: PYI030 [*] Multiple literal members in a union. Use a single literal, e.g. `Literal[1, 2, 3, 4]`
|
||||
|
|
||||
85 | # Should emit only once in cases with multiple nested `typing.Union`
|
||||
86 | field24: typing.Union[Literal[1], typing.Union[Literal[2], typing.Union[Literal[3], Literal[4]]]] # Error
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ PYI030
|
||||
|
|
||||
= help: Replace with a single `Literal`
|
||||
|
||||
ℹ Fix
|
||||
83 83 | field25: typing.Union[Literal[1], Literal[2] | str] # Error
|
||||
84 84 |
|
||||
85 85 | # Should emit only once in cases with multiple nested `typing.Union`
|
||||
86 |-field24: typing.Union[Literal[1], typing.Union[Literal[2], typing.Union[Literal[3], Literal[4]]]] # Error
|
||||
86 |+field24: Literal[1, 2, 3, 4] # Error
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use ruff_python_ast::call_path::from_qualified_name;
|
||||
use ruff_python_ast::helpers::{map_callable, map_subscript};
|
||||
use ruff_python_ast::helpers::map_callable;
|
||||
use ruff_python_semantic::{Binding, BindingKind, ScopeKind, SemanticModel};
|
||||
|
||||
pub(crate) fn is_valid_runtime_import(binding: &Binding, semantic: &SemanticModel) -> bool {
|
||||
@@ -40,13 +40,11 @@ fn runtime_evaluated_base_class(base_classes: &[String], semantic: &SemanticMode
|
||||
};
|
||||
|
||||
class_def.bases().iter().any(|base| {
|
||||
semantic
|
||||
.resolve_call_path(map_subscript(base))
|
||||
.is_some_and(|call_path| {
|
||||
base_classes
|
||||
.iter()
|
||||
.any(|base_class| from_qualified_name(base_class) == call_path)
|
||||
})
|
||||
semantic.resolve_call_path(base).is_some_and(|call_path| {
|
||||
base_classes
|
||||
.iter()
|
||||
.any(|base_class| from_qualified_name(base_class) == call_path)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ mod tests {
|
||||
#[test_case(Rule::RuntimeImportInTypeCheckingBlock, Path::new("TCH004_12.py"))]
|
||||
#[test_case(Rule::RuntimeImportInTypeCheckingBlock, Path::new("TCH004_13.py"))]
|
||||
#[test_case(Rule::RuntimeImportInTypeCheckingBlock, Path::new("TCH004_14.pyi"))]
|
||||
#[test_case(Rule::RuntimeImportInTypeCheckingBlock, Path::new("TCH004_15.py"))]
|
||||
#[test_case(Rule::RuntimeImportInTypeCheckingBlock, Path::new("TCH004_2.py"))]
|
||||
#[test_case(Rule::RuntimeImportInTypeCheckingBlock, Path::new("TCH004_3.py"))]
|
||||
#[test_case(Rule::RuntimeImportInTypeCheckingBlock, Path::new("TCH004_4.py"))]
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_type_checking/mod.rs
|
||||
---
|
||||
|
||||
@@ -196,13 +196,5 @@ fn is_known_dunder_method(method: &str) -> bool {
|
||||
| "__trunc__"
|
||||
| "__weakref__"
|
||||
| "__xor__"
|
||||
// Overridable sunder names from the `Enum` class.
|
||||
// See: https://docs.python.org/3/library/enum.html#supported-sunder-names
|
||||
| "_name_"
|
||||
| "_value_"
|
||||
| "_missing_"
|
||||
| "_ignore_"
|
||||
| "_order_"
|
||||
| "_generate_next_value_"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use ruff_python_ast::call_path::{from_qualified_name, CallPath};
|
||||
use ruff_python_ast::{self as ast, ParameterWithDefault};
|
||||
use ruff_python_semantic::{
|
||||
analyze::{function_type, visibility},
|
||||
Scope, ScopeId, ScopeKind,
|
||||
Scope, ScopeKind,
|
||||
};
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
@@ -45,12 +45,7 @@ impl Violation for NoSelfUse {
|
||||
}
|
||||
|
||||
/// PLR6301
|
||||
pub(crate) fn no_self_use(
|
||||
checker: &Checker,
|
||||
scope_id: ScopeId,
|
||||
scope: &Scope,
|
||||
diagnostics: &mut Vec<Diagnostic>,
|
||||
) {
|
||||
pub(crate) fn no_self_use(checker: &Checker, scope: &Scope, diagnostics: &mut Vec<Diagnostic>) {
|
||||
let Some(parent) = &checker.semantic().first_non_type_parent_scope(scope) else {
|
||||
return;
|
||||
};
|
||||
@@ -110,28 +105,11 @@ pub(crate) fn no_self_use(
|
||||
return;
|
||||
};
|
||||
|
||||
if parameter.name.as_str() != "self" {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the method contains a `super` reference, then it should be considered to use self
|
||||
// implicitly.
|
||||
if let Some(binding_id) = checker.semantic().global_scope().get("super") {
|
||||
let binding = checker.semantic().binding(binding_id);
|
||||
if binding.kind.is_builtin() {
|
||||
if binding
|
||||
.references()
|
||||
.any(|id| checker.semantic().reference(id).scope_id() == scope_id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if scope
|
||||
.get("self")
|
||||
.map(|binding_id| checker.semantic().binding(binding_id))
|
||||
.is_some_and(|binding| binding.kind.is_argument() && !binding.is_used())
|
||||
if parameter.name.as_str() == "self"
|
||||
&& scope
|
||||
.get("self")
|
||||
.map(|binding_id| checker.semantic().binding(binding_id))
|
||||
.is_some_and(|binding| binding.kind.is_argument() && !binding.is_used())
|
||||
{
|
||||
diagnostics.push(Diagnostic::new(
|
||||
NoSelfUse {
|
||||
|
||||
@@ -1,30 +1,39 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/pylint/mod.rs
|
||||
---
|
||||
no_self_use.py:7:28: PLR6301 Method `developer_greeting` could be a function or static method
|
||||
no_self_use.py:5:28: PLR6301 Method `developer_greeting` could be a function or static method
|
||||
|
|
||||
6 | class Person:
|
||||
7 | def developer_greeting(self, name): # [no-self-use]
|
||||
4 | class Person:
|
||||
5 | def developer_greeting(self, name): # [no-self-use]
|
||||
| ^^^^ PLR6301
|
||||
8 | print(f"Greetings {name}!")
|
||||
6 | print(f"Greetings {name}!")
|
||||
|
|
||||
|
||||
no_self_use.py:10:20: PLR6301 Method `greeting_1` could be a function or static method
|
||||
no_self_use.py:8:20: PLR6301 Method `greeting_1` could be a function or static method
|
||||
|
|
||||
6 | print(f"Greetings {name}!")
|
||||
7 |
|
||||
8 | def greeting_1(self): # [no-self-use]
|
||||
| ^^^^ PLR6301
|
||||
9 | print("Hello!")
|
||||
|
|
||||
|
||||
no_self_use.py:11:20: PLR6301 Method `greeting_2` could be a function or static method
|
||||
|
|
||||
8 | print(f"Greetings {name}!")
|
||||
9 |
|
||||
10 | def greeting_1(self): # [no-self-use]
|
||||
9 | print("Hello!")
|
||||
10 |
|
||||
11 | def greeting_2(self): # [no-self-use]
|
||||
| ^^^^ PLR6301
|
||||
11 | print("Hello!")
|
||||
12 | print("Hi!")
|
||||
|
|
||||
|
||||
no_self_use.py:13:20: PLR6301 Method `greeting_2` could be a function or static method
|
||||
no_self_use.py:55:25: PLR6301 Method `abstract_method` could be a function or static method
|
||||
|
|
||||
11 | print("Hello!")
|
||||
12 |
|
||||
13 | def greeting_2(self): # [no-self-use]
|
||||
| ^^^^ PLR6301
|
||||
14 | print("Hi!")
|
||||
53 | class Sub(Base):
|
||||
54 | @override
|
||||
55 | def abstract_method(self):
|
||||
| ^^^^ PLR6301
|
||||
56 | print("concrete method")
|
||||
|
|
||||
|
||||
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::{Captures, Regex};
|
||||
use std::borrow::Cow;
|
||||
|
||||
static CURLY_BRACES: Lazy<Regex> = Lazy::new(|| Regex::new(r"(\\N\{[^}]+})|([{}])").unwrap());
|
||||
|
||||
pub(super) fn curly_escape(text: &str) -> Cow<'_, str> {
|
||||
pub(super) fn curly_escape(text: &str) -> String {
|
||||
// Match all curly braces. This will include named unicode escapes (like
|
||||
// \N{SNOWMAN}), which we _don't_ want to escape, so take care to preserve them.
|
||||
CURLY_BRACES.replace_all(text, |caps: &Captures| {
|
||||
if let Some(match_) = caps.get(1) {
|
||||
match_.as_str().to_string()
|
||||
} else {
|
||||
if &caps[2] == "{" {
|
||||
"{{".to_string()
|
||||
CURLY_BRACES
|
||||
.replace_all(text, |caps: &Captures| {
|
||||
if let Some(match_) = caps.get(1) {
|
||||
match_.as_str().to_string()
|
||||
} else {
|
||||
"}}".to_string()
|
||||
if &caps[2] == "{" {
|
||||
"{{".to_string()
|
||||
} else {
|
||||
"}}".to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
.to_string()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use std::borrow::Cow;
|
||||
use std::str::FromStr;
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
|
||||
@@ -106,7 +105,7 @@ fn simplify_conversion_flag(flags: CConversionFlags) -> String {
|
||||
}
|
||||
|
||||
/// Convert a [`PercentFormat`] struct into a `String`.
|
||||
fn handle_part(part: &CFormatPart<String>) -> Cow<'_, str> {
|
||||
fn handle_part(part: &CFormatPart<String>) -> String {
|
||||
match part {
|
||||
CFormatPart::Literal(item) => curly_escape(item),
|
||||
CFormatPart::Spec(spec) => {
|
||||
@@ -115,7 +114,7 @@ fn handle_part(part: &CFormatPart<String>) -> Cow<'_, str> {
|
||||
// TODO(charlie): What case is this?
|
||||
if spec.format_char == '%' {
|
||||
format_string.push('%');
|
||||
return Cow::Owned(format_string);
|
||||
return format_string;
|
||||
}
|
||||
|
||||
format_string.push('{');
|
||||
@@ -172,25 +171,26 @@ fn handle_part(part: &CFormatPart<String>) -> Cow<'_, str> {
|
||||
format_string.push(spec.format_char);
|
||||
}
|
||||
format_string.push('}');
|
||||
Cow::Owned(format_string)
|
||||
format_string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a [`CFormatString`] into a `String`.
|
||||
fn percent_to_format(format_string: &CFormatString) -> String {
|
||||
format_string
|
||||
.iter()
|
||||
.map(|(_, part)| handle_part(part))
|
||||
.collect()
|
||||
let mut contents = String::new();
|
||||
for (.., format_part) in format_string.iter() {
|
||||
contents.push_str(&handle_part(format_part));
|
||||
}
|
||||
contents
|
||||
}
|
||||
|
||||
/// If a tuple has one argument, remove the comma; otherwise, return it as-is.
|
||||
fn clean_params_tuple<'a>(right: &Expr, locator: &Locator<'a>) -> Cow<'a, str> {
|
||||
fn clean_params_tuple(right: &Expr, locator: &Locator) -> String {
|
||||
let mut contents = locator.slice(right).to_string();
|
||||
if let Expr::Tuple(ast::ExprTuple { elts, .. }) = &right {
|
||||
if elts.len() == 1 {
|
||||
if !locator.contains_line_break(right.range()) {
|
||||
let mut contents = locator.slice(right).to_string();
|
||||
for (i, character) in contents.chars().rev().enumerate() {
|
||||
if character == ',' {
|
||||
let correct_index = contents.len() - i - 1;
|
||||
@@ -198,12 +198,10 @@ fn clean_params_tuple<'a>(right: &Expr, locator: &Locator<'a>) -> Cow<'a, str> {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Cow::Owned(contents);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Cow::Borrowed(locator.slice(right))
|
||||
contents
|
||||
}
|
||||
|
||||
/// Converts a dictionary to a function call while preserving as much styling as
|
||||
@@ -421,16 +419,16 @@ pub(crate) fn printf_string_formatting(checker: &mut Checker, expr: &Expr, right
|
||||
// Parse the parameters.
|
||||
let params_string = match right {
|
||||
Expr::Constant(_) | Expr::FString(_) => {
|
||||
Cow::Owned(format!("({})", checker.locator().slice(right)))
|
||||
format!("({})", checker.locator().slice(right))
|
||||
}
|
||||
Expr::Name(_) | Expr::Attribute(_) | Expr::Subscript(_) | Expr::Call(_) => {
|
||||
if num_keyword_arguments > 0 {
|
||||
// If we have _any_ named fields, assume the right-hand side is a mapping.
|
||||
Cow::Owned(format!("(**{})", checker.locator().slice(right)))
|
||||
format!("(**{})", checker.locator().slice(right))
|
||||
} else if num_positional_arguments > 1 {
|
||||
// If we have multiple fields, but no named fields, assume the right-hand side is a
|
||||
// tuple.
|
||||
Cow::Owned(format!("(*{})", checker.locator().slice(right)))
|
||||
format!("(*{})", checker.locator().slice(right))
|
||||
} else {
|
||||
// Otherwise, if we have a single field, we can't make any assumptions about the
|
||||
// right-hand side. It _could_ be a tuple, but it could also be a single value,
|
||||
@@ -446,12 +444,13 @@ pub(crate) fn printf_string_formatting(checker: &mut Checker, expr: &Expr, right
|
||||
}
|
||||
Expr::Tuple(_) => clean_params_tuple(right, checker.locator()),
|
||||
Expr::Dict(_) => {
|
||||
let Some(params_string) =
|
||||
if let Some(params_string) =
|
||||
clean_params_dictionary(right, checker.locator(), checker.stylist())
|
||||
else {
|
||||
{
|
||||
params_string
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
Cow::Owned(params_string)
|
||||
}
|
||||
}
|
||||
_ => return,
|
||||
};
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
.1
|
||||
1.
|
||||
1E+1
|
||||
1E-1
|
||||
1.E+1
|
||||
1.0E+1
|
||||
1.1E+1
|
||||
@@ -102,6 +102,11 @@ class Test:
|
||||
x = 1
|
||||
|
||||
|
||||
class EmptyLineBeforeRawDocstring:
|
||||
|
||||
r"""Character and line based layer over a BufferedIOBase object, buffer."""
|
||||
|
||||
|
||||
class C(): # comment
|
||||
pass
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ use ruff_python_ast::UnaryOp;
|
||||
|
||||
use crate::comments::{trailing_comments, SourceComment};
|
||||
use crate::expression::parentheses::{
|
||||
is_expression_parenthesized, NeedsParentheses, OptionalParentheses, Parentheses,
|
||||
is_expression_parenthesized, NeedsParentheses, OptionalParentheses,
|
||||
};
|
||||
use crate::prelude::*;
|
||||
|
||||
@@ -57,14 +57,7 @@ impl FormatNodeRule<ExprUnaryOp> for FormatExprUnaryOp {
|
||||
space().fmt(f)?;
|
||||
}
|
||||
|
||||
if operand
|
||||
.as_bin_op_expr()
|
||||
.is_some_and(|bin_op| bin_op.op.is_pow())
|
||||
{
|
||||
operand.format().with_options(Parentheses::Always).fmt(f)
|
||||
} else {
|
||||
operand.format().fmt(f)
|
||||
}
|
||||
operand.format().fmt(f)
|
||||
}
|
||||
|
||||
fn fmt_dangling_comments(
|
||||
|
||||
@@ -142,7 +142,7 @@ fn normalize_floating_number(input: &str) -> Cow<str> {
|
||||
|
||||
let mut chars = input.char_indices();
|
||||
|
||||
let mut prev_char_is_dot = if let Some((index, '.')) = chars.next() {
|
||||
let fraction_ends_with_dot = if let Some((index, '.')) = chars.next() {
|
||||
// Add a leading `0` if `input` starts with `.`.
|
||||
output.push('0');
|
||||
output.push('.');
|
||||
@@ -155,8 +155,8 @@ fn normalize_floating_number(input: &str) -> Cow<str> {
|
||||
loop {
|
||||
match chars.next() {
|
||||
Some((index, c @ ('e' | 'E'))) => {
|
||||
if prev_char_is_dot {
|
||||
// Add `0` if the `e` immediately follows a `.` (e.g., `1.e1`).
|
||||
if fraction_ends_with_dot {
|
||||
// Add `0` if fraction part ends with `.`.
|
||||
output.push_str(&input[last_index..index]);
|
||||
output.push('0');
|
||||
last_index = index;
|
||||
@@ -177,12 +177,9 @@ fn normalize_floating_number(input: &str) -> Cow<str> {
|
||||
|
||||
break;
|
||||
}
|
||||
Some((_index, c)) => {
|
||||
prev_char_is_dot = c == '.';
|
||||
continue;
|
||||
}
|
||||
Some(_) => continue,
|
||||
None => {
|
||||
if prev_char_is_dot {
|
||||
if input.ends_with('.') {
|
||||
// Add `0` if fraction part ends with `.`.
|
||||
output.push_str(&input[last_index..]);
|
||||
output.push('0');
|
||||
|
||||
@@ -496,7 +496,7 @@ impl Format<PyFormatContext<'_>> for NormalizedString<'_> {
|
||||
|
||||
bitflags! {
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub(super) struct StringPrefix: u8 {
|
||||
pub(crate) struct StringPrefix: u8 {
|
||||
const UNICODE = 0b0000_0001;
|
||||
/// `r"test"`
|
||||
const RAW = 0b0000_0010;
|
||||
@@ -508,7 +508,7 @@ bitflags! {
|
||||
}
|
||||
|
||||
impl StringPrefix {
|
||||
pub(super) fn parse(input: &str) -> StringPrefix {
|
||||
pub(crate) fn parse(input: &str) -> StringPrefix {
|
||||
let chars = input.chars();
|
||||
let mut prefix = StringPrefix::empty();
|
||||
|
||||
@@ -533,15 +533,15 @@ impl StringPrefix {
|
||||
prefix
|
||||
}
|
||||
|
||||
pub(super) const fn text_len(self) -> TextSize {
|
||||
pub(crate) const fn text_len(self) -> TextSize {
|
||||
TextSize::new(self.bits().count_ones())
|
||||
}
|
||||
|
||||
pub(super) const fn is_raw_string(self) -> bool {
|
||||
pub(crate) const fn is_raw_string(self) -> bool {
|
||||
self.contains(StringPrefix::RAW) || self.contains(StringPrefix::RAW_UPPER)
|
||||
}
|
||||
|
||||
pub(super) const fn is_fstring(self) -> bool {
|
||||
pub(crate) const fn is_fstring(self) -> bool {
|
||||
self.contains(StringPrefix::F_STRING)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::comments::{
|
||||
};
|
||||
use crate::context::{NodeLevel, WithNodeLevel};
|
||||
use crate::expression::expr_constant::ExprConstantLayout;
|
||||
use crate::expression::string::StringLayout;
|
||||
use crate::expression::string::{StringLayout, StringPrefix};
|
||||
use crate::prelude::*;
|
||||
use crate::statement::stmt_expr::FormatStmtExpr;
|
||||
use crate::verbatim::{
|
||||
@@ -99,9 +99,13 @@ impl FormatRule<Suite, PyFormatContext<'_>> for FormatSuite {
|
||||
|
||||
SuiteKind::Class => {
|
||||
if let Some(docstring) = DocstringStmt::try_from_statement(first) {
|
||||
let prefix =
|
||||
StringPrefix::parse(f.context().locator().slice(docstring.0.range()));
|
||||
if !comments.has_leading(first)
|
||||
&& lines_before(first.start(), source) > 1
|
||||
&& !source_type.is_stub()
|
||||
// For some reason black removes the empty line before raw docstrings
|
||||
&& !prefix.is_raw_string()
|
||||
{
|
||||
// Allow up to one empty line before a class docstring, e.g., this is
|
||||
// stable formatting:
|
||||
@@ -484,8 +488,10 @@ impl<'ast> IntoFormat<PyFormatContext<'ast>> for Suite {
|
||||
}
|
||||
|
||||
/// A statement representing a docstring.
|
||||
///
|
||||
/// We keep both the outer statement and the inner constant here for convenience.
|
||||
#[derive(Copy, Clone)]
|
||||
pub(crate) struct DocstringStmt<'a>(&'a Stmt);
|
||||
pub(crate) struct DocstringStmt<'a>(&'a Stmt, &'a ExprConstant);
|
||||
|
||||
impl<'a> DocstringStmt<'a> {
|
||||
/// Checks if the statement is a simple string that can be formatted as a docstring
|
||||
@@ -494,9 +500,9 @@ impl<'a> DocstringStmt<'a> {
|
||||
return None;
|
||||
};
|
||||
|
||||
if let Expr::Constant(ExprConstant { value, .. }) = value.as_ref() {
|
||||
if !value.is_implicit_concatenated() {
|
||||
return Some(DocstringStmt(stmt));
|
||||
if let Expr::Constant(expr_constant @ ExprConstant { value, .. }) = value.as_ref() {
|
||||
if (value.is_str() || value.is_unicode_string()) && !value.is_implicit_concatenated() {
|
||||
return Some(DocstringStmt(stmt, expr_constant));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -512,21 +518,12 @@ impl Format<PyFormatContext<'_>> for DocstringStmt<'_> {
|
||||
if FormatStmtExpr.is_suppressed(node_comments.trailing, f.context()) {
|
||||
suppressed_node(self.0).fmt(f)
|
||||
} else {
|
||||
// SAFETY: Safe because `DocStringStmt` guarantees that it only ever wraps a `ExprStmt` containing a `ConstantExpr`.
|
||||
let constant = self
|
||||
.0
|
||||
.as_expr_stmt()
|
||||
.unwrap()
|
||||
.value
|
||||
.as_constant_expr()
|
||||
.unwrap();
|
||||
|
||||
// We format the expression, but the statement carries the comments
|
||||
write!(
|
||||
f,
|
||||
[
|
||||
leading_comments(node_comments.leading),
|
||||
constant
|
||||
self.1
|
||||
.format()
|
||||
.with_options(ExprConstantLayout::String(StringLayout::DocString)),
|
||||
trailing_comments(node_comments.trailing),
|
||||
|
||||
@@ -266,6 +266,15 @@ last_call()
|
||||
```diff
|
||||
--- Black
|
||||
+++ Ruff
|
||||
@@ -31,7 +31,7 @@
|
||||
-1
|
||||
~int and not v1 ^ 123 + v2 | True
|
||||
(~int) and (not ((v1 ^ (123 + v2)) | True))
|
||||
-+(really ** -(confusing ** ~(operator**-precedence)))
|
||||
++really ** -confusing ** ~operator**-precedence
|
||||
flags & ~select.EPOLLIN and waiters.write_task is not None
|
||||
lambda arg: None
|
||||
lambda a=True: a
|
||||
@@ -115,7 +115,7 @@
|
||||
arg,
|
||||
another,
|
||||
@@ -313,7 +322,7 @@ not great
|
||||
-1
|
||||
~int and not v1 ^ 123 + v2 | True
|
||||
(~int) and (not ((v1 ^ (123 + v2)) | True))
|
||||
+(really ** -(confusing ** ~(operator**-precedence)))
|
||||
+really ** -confusing ** ~operator**-precedence
|
||||
flags & ~select.EPOLLIN and waiters.write_task is not None
|
||||
lambda arg: None
|
||||
lambda a=True: a
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
---
|
||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/number.py
|
||||
---
|
||||
## Input
|
||||
```py
|
||||
.1
|
||||
1.
|
||||
1E+1
|
||||
1E-1
|
||||
1.E+1
|
||||
1.0E+1
|
||||
1.1E+1
|
||||
```
|
||||
|
||||
## Output
|
||||
```py
|
||||
0.1
|
||||
1.0
|
||||
1e1
|
||||
1e-1
|
||||
1.0e1
|
||||
1.0e1
|
||||
1.1e1
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -108,6 +108,11 @@ class Test:
|
||||
x = 1
|
||||
|
||||
|
||||
class EmptyLineBeforeRawDocstring:
|
||||
|
||||
r"""Character and line based layer over a BufferedIOBase object, buffer."""
|
||||
|
||||
|
||||
class C(): # comment
|
||||
pass
|
||||
|
||||
@@ -356,6 +361,10 @@ class Test:
|
||||
x = 1
|
||||
|
||||
|
||||
class EmptyLineBeforeRawDocstring:
|
||||
r"""Character and line based layer over a BufferedIOBase object, buffer."""
|
||||
|
||||
|
||||
class C: # comment
|
||||
pass
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ use ruff_python_trivia::CommentRanges;
|
||||
use ruff_source_file::{Locator, SourceLocation};
|
||||
use ruff_text_size::Ranged;
|
||||
use ruff_workspace::configuration::Configuration;
|
||||
use ruff_workspace::options::{FormatOptions, LintOptions, Options};
|
||||
use ruff_workspace::options::{FormatOptions, FormatOrOutputFormat, LintOptions, Options};
|
||||
use ruff_workspace::Settings;
|
||||
|
||||
#[wasm_bindgen(typescript_custom_section)]
|
||||
@@ -140,11 +140,11 @@ impl Workspace {
|
||||
|
||||
..LintOptions::default()
|
||||
}),
|
||||
format: Some(FormatOptions {
|
||||
format: Some(FormatOrOutputFormat::Format(FormatOptions {
|
||||
indent_style: Some(IndentStyle::Space),
|
||||
quote_style: Some(QuoteStyle::Double),
|
||||
..FormatOptions::default()
|
||||
}),
|
||||
})),
|
||||
..Options::default()
|
||||
})
|
||||
.map_err(into_error)
|
||||
|
||||
@@ -39,9 +39,9 @@ use crate::options::{
|
||||
Flake8ComprehensionsOptions, Flake8CopyrightOptions, Flake8ErrMsgOptions, Flake8GetTextOptions,
|
||||
Flake8ImplicitStrConcatOptions, Flake8ImportConventionsOptions, Flake8PytestStyleOptions,
|
||||
Flake8QuotesOptions, Flake8SelfOptions, Flake8TidyImportsOptions, Flake8TypeCheckingOptions,
|
||||
Flake8UnusedArgumentsOptions, FormatOptions, IsortOptions, LintOptions, McCabeOptions, Options,
|
||||
Pep8NamingOptions, PyUpgradeOptions, PycodestyleOptions, PydocstyleOptions, PyflakesOptions,
|
||||
PylintOptions,
|
||||
Flake8UnusedArgumentsOptions, FormatOptions, FormatOrOutputFormat, IsortOptions, LintOptions,
|
||||
McCabeOptions, Options, Pep8NamingOptions, PyUpgradeOptions, PycodestyleOptions,
|
||||
PydocstyleOptions, PyflakesOptions, PylintOptions,
|
||||
};
|
||||
use crate::settings::{
|
||||
FileResolverSettings, FormatterSettings, LineEnding, Settings, EXCLUDE, INCLUDE,
|
||||
@@ -377,7 +377,7 @@ impl Configuration {
|
||||
.cache_dir
|
||||
.map(|dir| {
|
||||
let dir = shellexpand::full(&dir);
|
||||
dir.map(|dir| fs::normalize_path_to(dir.as_ref(), project_root))
|
||||
dir.map(|dir| PathBuf::from(dir.as_ref()))
|
||||
})
|
||||
.transpose()
|
||||
.map_err(|e| anyhow!("Invalid `cache-dir` value: {e}"))?,
|
||||
@@ -435,7 +435,12 @@ impl Configuration {
|
||||
fix: options.fix,
|
||||
fix_only: options.fix_only,
|
||||
unsafe_fixes: options.unsafe_fixes.map(UnsafeFixes::from),
|
||||
output_format: options.output_format,
|
||||
output_format: options.output_format.or_else(|| {
|
||||
options
|
||||
.format
|
||||
.as_ref()
|
||||
.and_then(FormatOrOutputFormat::as_output_format)
|
||||
}),
|
||||
force_exclude: options.force_exclude,
|
||||
line_length: options.line_length,
|
||||
tab_size: options.tab_size,
|
||||
@@ -455,7 +460,11 @@ impl Configuration {
|
||||
target_version: options.target_version,
|
||||
|
||||
lint: LintConfiguration::from_options(lint, project_root)?,
|
||||
format: FormatConfiguration::from_options(options.format.unwrap_or_default())?,
|
||||
format: if let Some(FormatOrOutputFormat::Format(format)) = options.format {
|
||||
FormatConfiguration::from_options(format)?
|
||||
} else {
|
||||
FormatConfiguration::default()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ use ruff_linter::{warn_user_once, RuleSelector};
|
||||
use ruff_macros::{CombineOptions, OptionsMetadata};
|
||||
use ruff_python_formatter::QuoteStyle;
|
||||
|
||||
use crate::options_base::{OptionsMetadata, Visit};
|
||||
use crate::settings::LineEnding;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Default, OptionsMetadata, Serialize, Deserialize)]
|
||||
@@ -379,9 +380,19 @@ pub struct Options {
|
||||
#[serde(flatten)]
|
||||
pub lint_top_level: LintOptions,
|
||||
|
||||
/// Options to configure code formatting.
|
||||
/// Options to configure the code formatting.
|
||||
///
|
||||
/// Previously:
|
||||
/// The style in which violation messages should be formatted: `"text"`
|
||||
/// (default), `"grouped"` (group messages by file), `"json"`
|
||||
/// (machine-readable), `"junit"` (machine-readable XML), `"github"` (GitHub
|
||||
/// Actions annotations), `"gitlab"` (GitLab CI code quality report),
|
||||
/// `"pylint"` (Pylint text format) or `"azure"` (Azure Pipeline logging commands).
|
||||
///
|
||||
/// This option has been **deprecated** in favor of `output-format`
|
||||
/// to avoid ambiguity with Ruff's upcoming formatter.
|
||||
#[option_group]
|
||||
pub format: Option<FormatOptions>,
|
||||
pub format: Option<FormatOrOutputFormat>,
|
||||
}
|
||||
|
||||
/// Experimental section to configure Ruff's linting. This new section will eventually
|
||||
@@ -2454,11 +2465,38 @@ impl PyUpgradeOptions {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub enum FormatOrOutputFormat {
|
||||
Format(FormatOptions),
|
||||
OutputFormat(SerializationFormat),
|
||||
}
|
||||
|
||||
impl FormatOrOutputFormat {
|
||||
pub const fn as_output_format(&self) -> Option<SerializationFormat> {
|
||||
match self {
|
||||
FormatOrOutputFormat::Format(_) => None,
|
||||
FormatOrOutputFormat::OutputFormat(format) => Some(*format),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OptionsMetadata for FormatOrOutputFormat {
|
||||
fn record(visit: &mut dyn Visit) {
|
||||
FormatOptions::record(visit);
|
||||
}
|
||||
|
||||
fn documentation() -> Option<&'static str> {
|
||||
FormatOptions::documentation()
|
||||
}
|
||||
}
|
||||
|
||||
/// Experimental: Configures how `ruff format` formats your code.
|
||||
///
|
||||
/// Please provide feedback in [this discussion](https://github.com/astral-sh/ruff/discussions/7310).
|
||||
#[derive(
|
||||
Debug, PartialEq, Eq, Default, Deserialize, Serialize, OptionsMetadata, CombineOptions,
|
||||
Debug, PartialEq, Eq, Default, Serialize, Deserialize, OptionsMetadata, CombineOptions,
|
||||
)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
|
||||
@@ -13,10 +13,11 @@ use log::debug;
|
||||
use path_absolutize::path_dedot;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
use ruff_linter::fs;
|
||||
use ruff_linter::packaging::is_package;
|
||||
use ruff_linter::{fs, warn_user_once};
|
||||
|
||||
use crate::configuration::Configuration;
|
||||
use crate::options::FormatOrOutputFormat;
|
||||
use crate::pyproject;
|
||||
use crate::pyproject::settings_toml;
|
||||
use crate::settings::Settings;
|
||||
@@ -220,6 +221,10 @@ fn resolve_configuration(
|
||||
let options = pyproject::load_options(&path)
|
||||
.map_err(|err| anyhow!("Failed to parse `{}`: {}", path.display(), err))?;
|
||||
|
||||
if matches!(options.format, Some(FormatOrOutputFormat::OutputFormat(_))) {
|
||||
warn_user_once!("The option `format` has been deprecated to avoid ambiguity with Ruff's upcoming formatter. Use `output-format` instead.");
|
||||
}
|
||||
|
||||
let project_root = relativity.resolve(&path);
|
||||
let configuration = Configuration::from_options(options, &project_root)?;
|
||||
|
||||
|
||||
@@ -109,6 +109,8 @@ If you're wondering how to configure Ruff, here are some **recommended guideline
|
||||
- Start with a small set of rules (`select = ["E", "F"]`) and add a category at-a-time. For example,
|
||||
you might consider expanding to `select = ["E", "F", "B"]` to enable the popular flake8-bugbear
|
||||
extension.
|
||||
- By default, Ruff's fixes are aggressive. If you find that it's too aggressive for your liking,
|
||||
consider turning off fixes for specific rules or categories (see [_FAQ_](faq.md#ruff-tried-to-fix-something--but-it-broke-my-code)).
|
||||
|
||||
## Using `ruff.toml`
|
||||
|
||||
@@ -428,7 +430,7 @@ Ruff only enables safe fixes by default. Unsafe fixes can be enabled by settings
|
||||
ruff check . --unsafe-fixes
|
||||
|
||||
# Apply unsafe fixes
|
||||
ruff check . --fix --unsafe-fixes
|
||||
ruff check . --fix --unsafe-fixes
|
||||
```
|
||||
|
||||
The safety of fixes can be adjusted per rule using the [`extend-safe-fixes`](settings.md#extend-safe-fixes) and [`extend-unsafe-fixes`](settings.md#extend-unsafe-fixes) settings.
|
||||
|
||||
21
docs/faq.md
21
docs/faq.md
@@ -436,13 +436,22 @@ For more, see the [`dirs`](https://docs.rs/dirs/4.0.0/dirs/fn.config_dir.html) c
|
||||
|
||||
## Ruff tried to fix something — but it broke my code?
|
||||
|
||||
Ruff labels fixes as "safe" and "unsafe". By default, Ruff will fix all violations for which safe
|
||||
fixes are available, while unsafe fixes can be enabled via the [`unsafe-fixes`](settings.md#unsafe-fixes)
|
||||
setting, or passing the `--unsafe-fixes` flag to `ruff check`. For more, see [the fix documentation](configuration.md#fixes).
|
||||
Ruff's fixes are a best-effort mechanism. Given the dynamic nature of Python, it's difficult to
|
||||
have _complete_ certainty when making changes to code, even for the seemingly trivial fixes.
|
||||
|
||||
Even still, given the dynamic nature of Python, it's difficult to have _complete_ certainty when
|
||||
making changes to code, even for seemingly trivial fixes. If a "safe" fix breaks your code, please
|
||||
[file an Issue](https://github.com/astral-sh/ruff/issues/new).
|
||||
In the future, Ruff will support enabling fix behavior based on the safety of the patch.
|
||||
|
||||
In the meantime, if you find that the fixes are too aggressive, you can disable it on a per-rule or
|
||||
per-category basis using the [`unfixable`](settings.md#unfixable) mechanic.
|
||||
For example, to disable the fix for some possibly-unsafe rules, you could add the following to your
|
||||
`pyproject.toml`:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
unfixable = ["B", "SIM", "TRY", "RUF"]
|
||||
```
|
||||
|
||||
If you find a case where Ruff's fix breaks your code, please file an Issue!
|
||||
|
||||
## How can I disable Ruff's color output?
|
||||
|
||||
|
||||
@@ -247,7 +247,7 @@ This tutorial has focused on Ruff's command-line interface, but Ruff can also be
|
||||
```yaml
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.1.0
|
||||
rev: v0.0.292
|
||||
hooks:
|
||||
- id: ruff
|
||||
```
|
||||
|
||||
@@ -23,7 +23,7 @@ Ruff can also be used as a [pre-commit](https://pre-commit.com) hook:
|
||||
```yaml
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.1.0
|
||||
rev: v0.0.292
|
||||
hooks:
|
||||
- id: ruff
|
||||
```
|
||||
@@ -33,7 +33,7 @@ Or, to enable fixes:
|
||||
```yaml
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.1.0
|
||||
rev: v0.0.292
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [ --fix, --exit-non-zero-on-fix ]
|
||||
@@ -44,7 +44,7 @@ Or, to run the hook on Jupyter Notebooks too:
|
||||
```yaml
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.1.0
|
||||
rev: v0.0.292
|
||||
hooks:
|
||||
- id: ruff
|
||||
types_or: [python, pyi, jupyter]
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "maturin"
|
||||
|
||||
[project]
|
||||
name = "ruff"
|
||||
version = "0.1.0"
|
||||
version = "0.0.292"
|
||||
description = "An extremely fast Python linter, written in Rust."
|
||||
authors = [{ name = "Astral Software Inc.", email = "hey@astral.sh" }]
|
||||
readme = "README.md"
|
||||
|
||||
14
ruff.schema.json
generated
14
ruff.schema.json
generated
@@ -355,10 +355,10 @@
|
||||
]
|
||||
},
|
||||
"format": {
|
||||
"description": "Options to configure code formatting.",
|
||||
"description": "Options to configure the code formatting.\n\nPreviously: The style in which violation messages should be formatted: `\"text\"` (default), `\"grouped\"` (group messages by file), `\"json\"` (machine-readable), `\"junit\"` (machine-readable XML), `\"github\"` (GitHub Actions annotations), `\"gitlab\"` (GitLab CI code quality report), `\"pylint\"` (Pylint text format) or `\"azure\"` (Azure Pipeline logging commands).\n\nThis option has been **deprecated** in favor of `output-format` to avoid ambiguity with Ruff's upcoming formatter.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/FormatOptions"
|
||||
"$ref": "#/definitions/FormatOrOutputFormat"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
@@ -1259,6 +1259,16 @@
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"FormatOrOutputFormat": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/FormatOptions"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/SerializationFormat"
|
||||
}
|
||||
]
|
||||
},
|
||||
"ImportSection": {
|
||||
"anyOf": [
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# The pinned revisions are the latest of this writing, update freely.
|
||||
|
||||
set -e
|
||||
set -ex
|
||||
|
||||
target=$(git rev-parse --show-toplevel)/target
|
||||
dir="$target/progress_projects"
|
||||
@@ -20,55 +20,43 @@ mkdir -p "$dir"
|
||||
if [ ! -d "$dir/twine/.git" ]; then
|
||||
git clone --filter=tree:0 https://github.com/pypa/twine "$dir/twine"
|
||||
fi
|
||||
git -C "$dir/twine" checkout -q afc37f8b26ed06ccd104f6724f293f657b9b7f15
|
||||
git -C "$dir/twine" checkout 0bb428c410b8df64c04dc881ac1db37d932f3066
|
||||
|
||||
# web framework that implements a lot of magic
|
||||
if [ ! -d "$dir/django/.git" ]; then
|
||||
git clone --filter=tree:0 https://github.com/django/django "$dir/django"
|
||||
fi
|
||||
git -C "$dir/django" checkout -q 20b7aac7ca60b0352d926340622e618bcbee54a8
|
||||
git -C "$dir/django" checkout 48a1929ca050f1333927860ff561f6371706968a
|
||||
|
||||
# an ML project
|
||||
if [ ! -d "$dir/transformers/.git" ]; then
|
||||
git clone --filter=tree:0 https://github.com/huggingface/transformers "$dir/transformers"
|
||||
fi
|
||||
git -C "$dir/transformers" checkout -q 5c081e29930466ecf9a478727039d980131076d9
|
||||
git -C "$dir/transformers" checkout 62396cff46854dc53023236cfeb785993fa70067
|
||||
|
||||
# type annotations
|
||||
if [ ! -d "$dir/typeshed/.git" ]; then
|
||||
git clone --filter=tree:0 https://github.com/python/typeshed "$dir/typeshed"
|
||||
fi
|
||||
git -C "$dir/typeshed" checkout -q cb688d2577520d98c09853acc20de099300b4e48
|
||||
git -C "$dir/typeshed" checkout 2c15a8e7906e19f49bb765e2807dd0079fe9c04b
|
||||
|
||||
# python 3.11, typing and 100% test coverage
|
||||
if [ ! -d "$dir/warehouse/.git" ]; then
|
||||
git clone --filter=tree:0 https://github.com/pypi/warehouse "$dir/warehouse"
|
||||
fi
|
||||
git -C "$dir/warehouse" checkout -q c6d9dd32b7c85d3a5f4240c95267874417e5b965
|
||||
git -C "$dir/warehouse" checkout 6be6bccf07dace18784ea8aeac7906903fdbcf3a
|
||||
|
||||
# zulip, a django user
|
||||
if [ ! -d "$dir/zulip/.git" ]; then
|
||||
git clone --filter=tree:0 https://github.com/zulip/zulip "$dir/zulip"
|
||||
fi
|
||||
git -C "$dir/zulip" checkout -q b605042312c763c9a1e458f0ca6a003799682546
|
||||
|
||||
# home-assistant, home automation with 1ok files
|
||||
if [ ! -d "$dir/home-assistant/.git" ]; then
|
||||
git clone --filter=tree:0 https://github.com/home-assistant/core "$dir/home-assistant"
|
||||
fi
|
||||
git -C "$dir/home-assistant" checkout -q 88296c1998fd1943576e0167ab190d25af175257
|
||||
|
||||
# poetry, a package manager that uses black preview style
|
||||
if [ ! -d "$dir/poetry/.git" ]; then
|
||||
git clone --filter=tree:0 https://github.com/python-poetry/poetry "$dir/poetry"
|
||||
fi
|
||||
git -C "$dir/poetry" checkout -q f5cb9f0fb19063cf280faf5e39c82d5691da9939
|
||||
git -C "$dir/zulip" checkout 328cdde24331b82baa4c9b1bf1cb7b2015799826
|
||||
|
||||
# cpython itself
|
||||
if [ ! -d "$dir/cpython/.git" ]; then
|
||||
git clone --filter=tree:0 https://github.com/python/cpython "$dir/cpython"
|
||||
fi
|
||||
git -C "$dir/cpython" checkout -q b75186f69edcf54615910a5cd707996144163ef7
|
||||
git -C "$dir/cpython" checkout 1a1bfc28912a39b500c578e9f10a8a222638d411
|
||||
|
||||
# Uncomment if you want to update the hashes
|
||||
#for i in "$dir"/*/; do git -C "$i" switch main && git -C "$i" pull; done
|
||||
@@ -76,7 +64,7 @@ git -C "$dir/cpython" checkout -q b75186f69edcf54615910a5cd707996144163ef7
|
||||
|
||||
time cargo run --bin ruff_dev -- format-dev --stability-check \
|
||||
--error-file "$target/progress_projects_errors.txt" --log-file "$target/progress_projects_log.txt" --stats-file "$target/progress_projects_stats.txt" \
|
||||
--files-with-errors 14 --multi-project "$dir" || (
|
||||
--files-with-errors 15 --multi-project "$dir" || (
|
||||
echo "Ecosystem check failed"
|
||||
cat "$target/progress_projects_log.txt"
|
||||
exit 1
|
||||
|
||||
Reference in New Issue
Block a user