Compare commits

..

2 Commits

Author SHA1 Message Date
konstin
63ef7652ed Fix test 2023-10-13 17:14:17 +02:00
konstin
1743ef8398 Remove empty line before raw dostrings
**Summary** This fixes a deviation with black where black would remove
empty lines before raw docstrings for some reason.
2023-10-13 16:04:01 +02:00
52 changed files with 796 additions and 523 deletions

View File

@@ -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 }}

View File

@@ -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 }}

View File

@@ -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

View File

@@ -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
View File

@@ -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",

View File

@@ -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" }

View File

@@ -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
```

View File

@@ -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.
"""

View File

@@ -1,6 +1,6 @@
[package]
name = "ruff_cli"
version = "0.1.0"
version = "0.0.292"
publish = false
authors = { workspace = true }
edition = { workspace = true }

View File

@@ -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),
},
)

View File

@@ -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`

View File

@@ -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
)?;
}

View File

@@ -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(())
}

View File

@@ -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 -----
"###);

View File

@@ -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 }

View File

@@ -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:
...

View File

@@ -22,10 +22,3 @@ class C:
class D(C):
x: UUID
import collections
class E(BaseModel[int]):
x: collections.Awaitable

View File

@@ -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
...

View File

@@ -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():
...

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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)
})
})
}

View File

@@ -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"))]

View File

@@ -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_"
)
}

View File

@@ -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 {

View File

@@ -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")
|

View File

@@ -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()
}

View File

@@ -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,
};

View File

@@ -1,7 +0,0 @@
.1
1.
1E+1
1E-1
1.E+1
1.0E+1
1.1E+1

View File

@@ -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

View File

@@ -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(

View File

@@ -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');

View File

@@ -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)
}
}

View File

@@ -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),

View File

@@ -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

View File

@@ -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
```

View File

@@ -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

View File

@@ -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)

View File

@@ -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()
},
})
}

View File

@@ -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))]

View File

@@ -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)?;

View File

@@ -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.

View File

@@ -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?

View File

@@ -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
```

View File

@@ -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]

View File

@@ -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
View File

@@ -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": [
{

View File

@@ -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