mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-23 13:05:06 +00:00
Re-integrate RustPython parser repository (#4359)
Co-authored-by: Micha Reiser <micha@reiser.io>
This commit is contained in:
parent
865205d992
commit
be6e00ef6e
270 changed files with 3061 additions and 3361 deletions
271
Cargo.lock
generated
271
Cargo.lock
generated
|
@ -144,15 +144,6 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
|
checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ascii-canvas"
|
|
||||||
version = "3.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6"
|
|
||||||
dependencies = [
|
|
||||||
"term",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "assert_cmd"
|
name = "assert_cmd"
|
||||||
version = "2.0.11"
|
version = "2.0.11"
|
||||||
|
@ -200,21 +191,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bit-set"
|
|
||||||
version = "0.5.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
|
|
||||||
dependencies = [
|
|
||||||
"bit-vec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bit-vec"
|
|
||||||
version = "0.6.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
|
@ -223,9 +199,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.1.0"
|
version = "2.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c70beb79cbb5ce9c4f8e20849978f34225931f665bb49efa6982875a4d5facb3"
|
checksum = "24a6904aef64d73cf10ab17ebace7befb918b82164785cb89907993be7f83813"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bstr"
|
name = "bstr"
|
||||||
|
@ -700,16 +676,6 @@ dependencies = [
|
||||||
"dirs-sys 0.4.0",
|
"dirs-sys 0.4.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "dirs-next"
|
|
||||||
version = "2.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"dirs-sys-next",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-sys"
|
name = "dirs-sys"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
|
@ -732,17 +698,6 @@ dependencies = [
|
||||||
"windows-sys 0.45.0",
|
"windows-sys 0.45.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "dirs-sys-next"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"redox_users",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "doc-comment"
|
name = "doc-comment"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
@ -767,15 +722,6 @@ version = "1.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ena"
|
|
||||||
version = "0.14.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1"
|
|
||||||
dependencies = [
|
|
||||||
"log",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encode_unicode"
|
name = "encode_unicode"
|
||||||
version = "0.3.6"
|
version = "0.3.6"
|
||||||
|
@ -833,12 +779,6 @@ dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fixedbitset"
|
|
||||||
version = "0.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flake8-to-ruff"
|
name = "flake8-to-ruff"
|
||||||
version = "0.0.265"
|
version = "0.0.265"
|
||||||
|
@ -1168,37 +1108,11 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lalrpop"
|
|
||||||
version = "0.19.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f34313ec00c2eb5c3c87ca6732ea02dcf3af99c3ff7a8fb622ffb99c9d860a87"
|
|
||||||
dependencies = [
|
|
||||||
"ascii-canvas",
|
|
||||||
"bit-set",
|
|
||||||
"diff",
|
|
||||||
"ena",
|
|
||||||
"is-terminal",
|
|
||||||
"itertools",
|
|
||||||
"lalrpop-util",
|
|
||||||
"petgraph",
|
|
||||||
"pico-args",
|
|
||||||
"regex",
|
|
||||||
"regex-syntax 0.6.29",
|
|
||||||
"string_cache",
|
|
||||||
"term",
|
|
||||||
"tiny-keccak",
|
|
||||||
"unicode-xid",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lalrpop-util"
|
name = "lalrpop-util"
|
||||||
version = "0.19.9"
|
version = "0.20.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5c1f7869c94d214466c5fd432dfed12c379fd87786768d36455892d46b18edd"
|
checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d"
|
||||||
dependencies = [
|
|
||||||
"regex",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
|
@ -1388,12 +1302,6 @@ version = "1.0.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "308d96db8debc727c3fd9744aac51751243420e46edf401010908da7f8d5e57c"
|
checksum = "308d96db8debc727c3fd9744aac51751243420e46edf401010908da7f8d5e57c"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "new_debug_unreachable"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nextest-workspace-hack"
|
name = "nextest-workspace-hack"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -1525,29 +1433,6 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking_lot"
|
|
||||||
version = "0.12.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
|
||||||
dependencies = [
|
|
||||||
"lock_api",
|
|
||||||
"parking_lot_core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking_lot_core"
|
|
||||||
version = "0.9.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"redox_syscall 0.2.16",
|
|
||||||
"smallvec",
|
|
||||||
"windows-sys 0.45.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "paste"
|
name = "paste"
|
||||||
version = "1.0.12"
|
version = "1.0.12"
|
||||||
|
@ -1624,23 +1509,13 @@ version = "2.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "petgraph"
|
|
||||||
version = "0.6.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
|
|
||||||
dependencies = [
|
|
||||||
"fixedbitset",
|
|
||||||
"indexmap",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phf"
|
name = "phf"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c"
|
checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"phf_shared 0.11.1",
|
"phf_shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1650,7 +1525,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770"
|
checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"phf_generator",
|
"phf_generator",
|
||||||
"phf_shared 0.11.1",
|
"phf_shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1659,19 +1534,10 @@ version = "0.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf"
|
checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"phf_shared 0.11.1",
|
"phf_shared",
|
||||||
"rand",
|
"rand",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "phf_shared"
|
|
||||||
version = "0.10.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
|
|
||||||
dependencies = [
|
|
||||||
"siphasher",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phf_shared"
|
name = "phf_shared"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
|
@ -1681,12 +1547,6 @@ dependencies = [
|
||||||
"siphasher",
|
"siphasher",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pico-args"
|
|
||||||
version = "0.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.9"
|
version = "0.2.9"
|
||||||
|
@ -1738,12 +1598,6 @@ version = "0.2.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "precomputed-hash"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "predicates"
|
name = "predicates"
|
||||||
version = "3.0.3"
|
version = "3.0.3"
|
||||||
|
@ -1944,7 +1798,7 @@ checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick 1.0.1",
|
"aho-corasick 1.0.1",
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-syntax 0.7.1",
|
"regex-syntax",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1953,12 +1807,6 @@ version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "regex-syntax"
|
|
||||||
version = "0.6.29"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
|
@ -2008,7 +1856,7 @@ version = "0.0.265"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"annotate-snippets 0.9.1",
|
"annotate-snippets 0.9.1",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bitflags 2.1.0",
|
"bitflags 2.2.1",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap 4.2.4",
|
"clap 4.2.4",
|
||||||
"colored",
|
"colored",
|
||||||
|
@ -2101,7 +1949,7 @@ dependencies = [
|
||||||
"assert_cmd",
|
"assert_cmd",
|
||||||
"atty",
|
"atty",
|
||||||
"bincode",
|
"bincode",
|
||||||
"bitflags 2.1.0",
|
"bitflags 2.2.1",
|
||||||
"cachedir",
|
"cachedir",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap 4.2.4",
|
"clap 4.2.4",
|
||||||
|
@ -2200,7 +2048,7 @@ name = "ruff_python_ast"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bitflags 2.1.0",
|
"bitflags 2.2.1",
|
||||||
"is-macro",
|
"is-macro",
|
||||||
"itertools",
|
"itertools",
|
||||||
"log",
|
"log",
|
||||||
|
@ -2209,10 +2057,9 @@ dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"regex",
|
"regex",
|
||||||
"ruff_rustpython",
|
|
||||||
"ruff_text_size",
|
"ruff_text_size",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"rustpython-common",
|
"rustpython-literal 0.2.0 (git+https://github.com/RustPython/Parser.git?rev=2af98056629fbe75ccc0d90c4ee05dfeb403d666)",
|
||||||
"rustpython-parser",
|
"rustpython-parser",
|
||||||
"serde",
|
"serde",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
|
@ -2234,7 +2081,6 @@ dependencies = [
|
||||||
"ruff_testing_macros",
|
"ruff_testing_macros",
|
||||||
"ruff_text_size",
|
"ruff_text_size",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"rustpython-common",
|
|
||||||
"rustpython-parser",
|
"rustpython-parser",
|
||||||
"similar",
|
"similar",
|
||||||
"test-case",
|
"test-case",
|
||||||
|
@ -2244,7 +2090,7 @@ dependencies = [
|
||||||
name = "ruff_python_semantic"
|
name = "ruff_python_semantic"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.1.0",
|
"bitflags 2.2.1",
|
||||||
"is-macro",
|
"is-macro",
|
||||||
"nohash-hasher",
|
"nohash-hasher",
|
||||||
"ruff_python_ast",
|
"ruff_python_ast",
|
||||||
|
@ -2268,8 +2114,6 @@ name = "ruff_rustpython"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"once_cell",
|
|
||||||
"rustpython-common",
|
|
||||||
"rustpython-parser",
|
"rustpython-parser",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2286,7 +2130,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruff_text_size"
|
name = "ruff_text_size"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
source = "git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a#c3147d2c1524ebd0e90cf1c2938d770314fd5a5a"
|
source = "git+https://github.com/RustPython/Parser.git?rev=2af98056629fbe75ccc0d90c4ee05dfeb403d666#2af98056629fbe75ccc0d90c4ee05dfeb403d666"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"schemars",
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -2357,75 +2201,92 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustpython-ast"
|
name = "rustpython-ast"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a#c3147d2c1524ebd0e90cf1c2938d770314fd5a5a"
|
source = "git+https://github.com/RustPython/Parser.git?rev=2af98056629fbe75ccc0d90c4ee05dfeb403d666#2af98056629fbe75ccc0d90c4ee05dfeb403d666"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"ruff_text_size",
|
"rustpython-parser-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustpython-common"
|
name = "rustpython-common"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a#c3147d2c1524ebd0e90cf1c2938d770314fd5a5a"
|
source = "git+https://github.com/RustPython/RustPython.git?rev=f3e4d3409253660bd4fa7f3d24d3db747e7dca61#f3e4d3409253660bd4fa7f3d24d3db747e7dca61"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ascii",
|
"ascii",
|
||||||
"bitflags 1.3.2",
|
"bitflags 2.2.1",
|
||||||
"bstr 0.2.17",
|
"bstr 0.2.17",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"getrandom",
|
|
||||||
"hexf-parse",
|
|
||||||
"itertools",
|
"itertools",
|
||||||
"lexical-parse-float",
|
|
||||||
"libc",
|
"libc",
|
||||||
"lock_api",
|
"lock_api",
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
|
"num-complex",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"radium",
|
"radium",
|
||||||
"rand",
|
"rand",
|
||||||
|
"rustpython-literal 0.2.0 (git+https://github.com/youknowone/RustPython-parser.git?rev=5b2af304a2baa53598e594097824165d4ac7a119)",
|
||||||
"siphasher",
|
"siphasher",
|
||||||
"unic-ucd-category",
|
|
||||||
"volatile",
|
"volatile",
|
||||||
"widestring",
|
"widestring",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustpython-compiler-core"
|
name = "rustpython-literal"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a#c3147d2c1524ebd0e90cf1c2938d770314fd5a5a"
|
source = "git+https://github.com/RustPython/Parser.git?rev=2af98056629fbe75ccc0d90c4ee05dfeb403d666#2af98056629fbe75ccc0d90c4ee05dfeb403d666"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"hexf-parse",
|
||||||
"itertools",
|
"lexical-parse-float",
|
||||||
"lz4_flex",
|
"num-traits",
|
||||||
"num-bigint",
|
"unic-ucd-category",
|
||||||
"num-complex",
|
]
|
||||||
"ruff_text_size",
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustpython-literal"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "git+https://github.com/youknowone/RustPython-parser.git?rev=5b2af304a2baa53598e594097824165d4ac7a119#5b2af304a2baa53598e594097824165d4ac7a119"
|
||||||
|
dependencies = [
|
||||||
|
"hexf-parse",
|
||||||
|
"lexical-parse-float",
|
||||||
|
"num-traits",
|
||||||
|
"unic-ucd-category",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustpython-parser"
|
name = "rustpython-parser"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/charliermarsh/RustPython.git?rev=c3147d2c1524ebd0e90cf1c2938d770314fd5a5a#c3147d2c1524ebd0e90cf1c2938d770314fd5a5a"
|
source = "git+https://github.com/RustPython/Parser.git?rev=2af98056629fbe75ccc0d90c4ee05dfeb403d666#2af98056629fbe75ccc0d90c4ee05dfeb403d666"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"itertools",
|
"itertools",
|
||||||
"lalrpop",
|
|
||||||
"lalrpop-util",
|
"lalrpop-util",
|
||||||
"log",
|
"log",
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"phf",
|
"phf",
|
||||||
"phf_codegen",
|
"phf_codegen",
|
||||||
"ruff_text_size",
|
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"rustpython-ast",
|
"rustpython-ast",
|
||||||
"rustpython-compiler-core",
|
"rustpython-parser-core",
|
||||||
"tiny-keccak",
|
"tiny-keccak",
|
||||||
"unic-emoji-char",
|
"unic-emoji-char",
|
||||||
"unic-ucd-ident",
|
"unic-ucd-ident",
|
||||||
"unicode_names2",
|
"unicode_names2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustpython-parser-core"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "git+https://github.com/RustPython/Parser.git?rev=2af98056629fbe75ccc0d90c4ee05dfeb403d666#2af98056629fbe75ccc0d90c4ee05dfeb403d666"
|
||||||
|
dependencies = [
|
||||||
|
"itertools",
|
||||||
|
"lz4_flex",
|
||||||
|
"num-bigint",
|
||||||
|
"num-complex",
|
||||||
|
"ruff_text_size",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.12"
|
version = "1.0.12"
|
||||||
|
@ -2613,19 +2474,6 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "string_cache"
|
|
||||||
version = "0.8.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b"
|
|
||||||
dependencies = [
|
|
||||||
"new_debug_unreachable",
|
|
||||||
"once_cell",
|
|
||||||
"parking_lot",
|
|
||||||
"phf_shared 0.10.0",
|
|
||||||
"precomputed-hash",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
|
@ -2698,17 +2546,6 @@ dependencies = [
|
||||||
"windows-sys 0.45.0",
|
"windows-sys 0.45.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "term"
|
|
||||||
version = "0.7.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
|
|
||||||
dependencies = [
|
|
||||||
"dirs-next",
|
|
||||||
"rustversion",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
@ -3061,12 +2898,6 @@ version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-xid"
|
|
||||||
version = "0.2.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode_names2"
|
name = "unicode_names2"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
|
|
|
@ -11,7 +11,7 @@ authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
anyhow = { version = "1.0.69" }
|
anyhow = { version = "1.0.69" }
|
||||||
bitflags = { version = "2.1.0" }
|
bitflags = { version = "2.2.1" }
|
||||||
chrono = { version = "0.4.23", default-features = false, features = ["clock"] }
|
chrono = { version = "0.4.23", default-features = false, features = ["clock"] }
|
||||||
clap = { version = "4.1.8", features = ["derive"] }
|
clap = { version = "4.1.8", features = ["derive"] }
|
||||||
colored = { version = "2.0.0" }
|
colored = { version = "2.0.0" }
|
||||||
|
@ -30,10 +30,11 @@ path-absolutize = { version = "3.0.14" }
|
||||||
proc-macro2 = { version = "1.0.51" }
|
proc-macro2 = { version = "1.0.51" }
|
||||||
quote = { version = "1.0.23" }
|
quote = { version = "1.0.23" }
|
||||||
regex = { version = "1.7.1" }
|
regex = { version = "1.7.1" }
|
||||||
ruff_text_size = { git = "https://github.com/charliermarsh/RustPython.git", rev = "c3147d2c1524ebd0e90cf1c2938d770314fd5a5a" }
|
ruff_text_size = { git = "https://github.com/RustPython/Parser.git", rev = "2af98056629fbe75ccc0d90c4ee05dfeb403d666" }
|
||||||
rustc-hash = { version = "1.1.0" }
|
rustc-hash = { version = "1.1.0" }
|
||||||
rustpython-common = { git = "https://github.com/charliermarsh/RustPython.git", rev = "c3147d2c1524ebd0e90cf1c2938d770314fd5a5a" }
|
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "f3e4d3409253660bd4fa7f3d24d3db747e7dca61" }
|
||||||
rustpython-parser = { git = "https://github.com/charliermarsh/RustPython.git", rev = "c3147d2c1524ebd0e90cf1c2938d770314fd5a5a" }
|
rustpython-literal = { git = "https://github.com/RustPython/Parser.git", rev = "2af98056629fbe75ccc0d90c4ee05dfeb403d666" }
|
||||||
|
rustpython-parser = { git = "https://github.com/RustPython/Parser.git", rev = "2af98056629fbe75ccc0d90c4ee05dfeb403d666" , default-features = false}
|
||||||
schemars = { version = "0.8.12" }
|
schemars = { version = "0.8.12" }
|
||||||
serde = { version = "1.0.152", features = ["derive"] }
|
serde = { version = "1.0.152", features = ["derive"] }
|
||||||
serde_json = { version = "1.0.93", features = ["preserve_order"] }
|
serde_json = { version = "1.0.93", features = ["preserve_order"] }
|
||||||
|
|
|
@ -5,7 +5,7 @@ use libcst_native::{
|
||||||
Codegen, CodegenState, ImportNames, ParenthesizableWhitespace, SmallStatement, Statement,
|
Codegen, CodegenState, ImportNames, ParenthesizableWhitespace, SmallStatement, Statement,
|
||||||
};
|
};
|
||||||
use ruff_text_size::{TextLen, TextRange, TextSize};
|
use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||||
use rustpython_parser::ast::{ExcepthandlerKind, Expr, Keyword, Stmt, StmtKind};
|
use rustpython_parser::ast::{self, ExcepthandlerKind, Expr, Keyword, Stmt, StmtKind};
|
||||||
use rustpython_parser::{lexer, Mode, Tok};
|
use rustpython_parser::{lexer, Mode, Tok};
|
||||||
|
|
||||||
use ruff_diagnostics::Edit;
|
use ruff_diagnostics::Edit;
|
||||||
|
@ -28,21 +28,21 @@ fn has_single_child(body: &[Stmt], deleted: &[&Stmt]) -> bool {
|
||||||
/// Determine if a child is the only statement in its body.
|
/// Determine if a child is the only statement in its body.
|
||||||
fn is_lone_child(child: &Stmt, parent: &Stmt, deleted: &[&Stmt]) -> Result<bool> {
|
fn is_lone_child(child: &Stmt, parent: &Stmt, deleted: &[&Stmt]) -> Result<bool> {
|
||||||
match &parent.node {
|
match &parent.node {
|
||||||
StmtKind::FunctionDef { body, .. }
|
StmtKind::FunctionDef(ast::StmtFunctionDef { body, .. })
|
||||||
| StmtKind::AsyncFunctionDef { body, .. }
|
| StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { body, .. })
|
||||||
| StmtKind::ClassDef { body, .. }
|
| StmtKind::ClassDef(ast::StmtClassDef { body, .. })
|
||||||
| StmtKind::With { body, .. }
|
| StmtKind::With(ast::StmtWith { body, .. })
|
||||||
| StmtKind::AsyncWith { body, .. } => {
|
| StmtKind::AsyncWith(ast::StmtAsyncWith { body, .. }) => {
|
||||||
if body.iter().contains(child) {
|
if body.iter().contains(child) {
|
||||||
Ok(has_single_child(body, deleted))
|
Ok(has_single_child(body, deleted))
|
||||||
} else {
|
} else {
|
||||||
bail!("Unable to find child in parent body")
|
bail!("Unable to find child in parent body")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::For { body, orelse, .. }
|
StmtKind::For(ast::StmtFor { body, orelse, .. })
|
||||||
| StmtKind::AsyncFor { body, orelse, .. }
|
| StmtKind::AsyncFor(ast::StmtAsyncFor { body, orelse, .. })
|
||||||
| StmtKind::While { body, orelse, .. }
|
| StmtKind::While(ast::StmtWhile { body, orelse, .. })
|
||||||
| StmtKind::If { body, orelse, .. } => {
|
| StmtKind::If(ast::StmtIf { body, orelse, .. }) => {
|
||||||
if body.iter().contains(child) {
|
if body.iter().contains(child) {
|
||||||
Ok(has_single_child(body, deleted))
|
Ok(has_single_child(body, deleted))
|
||||||
} else if orelse.iter().contains(child) {
|
} else if orelse.iter().contains(child) {
|
||||||
|
@ -51,18 +51,18 @@ fn is_lone_child(child: &Stmt, parent: &Stmt, deleted: &[&Stmt]) -> Result<bool>
|
||||||
bail!("Unable to find child in parent body")
|
bail!("Unable to find child in parent body")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::Try {
|
StmtKind::Try(ast::StmtTry {
|
||||||
body,
|
body,
|
||||||
handlers,
|
handlers,
|
||||||
orelse,
|
orelse,
|
||||||
finalbody,
|
finalbody,
|
||||||
}
|
})
|
||||||
| StmtKind::TryStar {
|
| StmtKind::TryStar(ast::StmtTryStar {
|
||||||
body,
|
body,
|
||||||
handlers,
|
handlers,
|
||||||
orelse,
|
orelse,
|
||||||
finalbody,
|
finalbody,
|
||||||
} => {
|
}) => {
|
||||||
if body.iter().contains(child) {
|
if body.iter().contains(child) {
|
||||||
Ok(has_single_child(body, deleted))
|
Ok(has_single_child(body, deleted))
|
||||||
} else if orelse.iter().contains(child) {
|
} else if orelse.iter().contains(child) {
|
||||||
|
@ -70,7 +70,9 @@ fn is_lone_child(child: &Stmt, parent: &Stmt, deleted: &[&Stmt]) -> Result<bool>
|
||||||
} else if finalbody.iter().contains(child) {
|
} else if finalbody.iter().contains(child) {
|
||||||
Ok(has_single_child(finalbody, deleted))
|
Ok(has_single_child(finalbody, deleted))
|
||||||
} else if let Some(body) = handlers.iter().find_map(|handler| match &handler.node {
|
} else if let Some(body) = handlers.iter().find_map(|handler| match &handler.node {
|
||||||
ExcepthandlerKind::ExceptHandler { body, .. } => {
|
ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler {
|
||||||
|
body, ..
|
||||||
|
}) => {
|
||||||
if body.iter().contains(child) {
|
if body.iter().contains(child) {
|
||||||
Some(body)
|
Some(body)
|
||||||
} else {
|
} else {
|
||||||
|
@ -83,7 +85,7 @@ fn is_lone_child(child: &Stmt, parent: &Stmt, deleted: &[&Stmt]) -> Result<bool>
|
||||||
bail!("Unable to find child in parent body")
|
bail!("Unable to find child in parent body")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::Match { cases, .. } => {
|
StmtKind::Match(ast::StmtMatch { cases, .. }) => {
|
||||||
if let Some(body) = cases.iter().find_map(|case| {
|
if let Some(body) = cases.iter().find_map(|case| {
|
||||||
if case.body.iter().contains(child) {
|
if case.body.iter().contains(child) {
|
||||||
Some(&case.body)
|
Some(&case.body)
|
||||||
|
@ -350,7 +352,7 @@ pub fn remove_argument(
|
||||||
if n_arguments == 1 {
|
if n_arguments == 1 {
|
||||||
// Case 1: there is only one argument.
|
// Case 1: there is only one argument.
|
||||||
let mut count: usize = 0;
|
let mut count: usize = 0;
|
||||||
for (tok, range) in lexer::lex_located(contents, Mode::Module, call_at).flatten() {
|
for (tok, range) in lexer::lex_starts_at(contents, Mode::Module, call_at).flatten() {
|
||||||
if matches!(tok, Tok::Lpar) {
|
if matches!(tok, Tok::Lpar) {
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
fix_start = Some(if remove_parentheses {
|
fix_start = Some(if remove_parentheses {
|
||||||
|
@ -382,7 +384,7 @@ pub fn remove_argument(
|
||||||
{
|
{
|
||||||
// Case 2: argument or keyword is _not_ the last node.
|
// Case 2: argument or keyword is _not_ the last node.
|
||||||
let mut seen_comma = false;
|
let mut seen_comma = false;
|
||||||
for (tok, range) in lexer::lex_located(contents, Mode::Module, call_at).flatten() {
|
for (tok, range) in lexer::lex_starts_at(contents, Mode::Module, call_at).flatten() {
|
||||||
if seen_comma {
|
if seen_comma {
|
||||||
if matches!(tok, Tok::NonLogicalNewline) {
|
if matches!(tok, Tok::NonLogicalNewline) {
|
||||||
// Also delete any non-logical newlines after the comma.
|
// Also delete any non-logical newlines after the comma.
|
||||||
|
@ -405,7 +407,7 @@ pub fn remove_argument(
|
||||||
} else {
|
} else {
|
||||||
// Case 3: argument or keyword is the last node, so we have to find the last
|
// Case 3: argument or keyword is the last node, so we have to find the last
|
||||||
// comma in the stmt.
|
// comma in the stmt.
|
||||||
for (tok, range) in lexer::lex_located(contents, Mode::Module, call_at).flatten() {
|
for (tok, range) in lexer::lex_starts_at(contents, Mode::Module, call_at).flatten() {
|
||||||
if range.start() == expr_range.start() {
|
if range.start() == expr_range.start() {
|
||||||
fix_end = Some(expr_range.end());
|
fix_end = Some(expr_range.end());
|
||||||
break;
|
break;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,7 +2,7 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use rustpython_parser::ast::{StmtKind, Suite};
|
use rustpython_parser::ast::{self, StmtKind, Suite};
|
||||||
|
|
||||||
use ruff_diagnostics::Diagnostic;
|
use ruff_diagnostics::Diagnostic;
|
||||||
use ruff_python_ast::helpers::to_module_path;
|
use ruff_python_ast::helpers::to_module_path;
|
||||||
|
@ -29,20 +29,21 @@ fn extract_import_map(path: &Path, package: Option<&Path>, blocks: &[&Block]) ->
|
||||||
let mut module_imports = Vec::with_capacity(num_imports);
|
let mut module_imports = Vec::with_capacity(num_imports);
|
||||||
for stmt in blocks.iter().flat_map(|block| &block.imports) {
|
for stmt in blocks.iter().flat_map(|block| &block.imports) {
|
||||||
match &stmt.node {
|
match &stmt.node {
|
||||||
StmtKind::Import { names } => {
|
StmtKind::Import(ast::StmtImport { names }) => {
|
||||||
module_imports.extend(
|
module_imports.extend(
|
||||||
names
|
names
|
||||||
.iter()
|
.iter()
|
||||||
.map(|name| ModuleImport::new(name.node.name.clone(), stmt.range())),
|
.map(|name| ModuleImport::new(name.node.name.to_string(), stmt.range())),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
StmtKind::ImportFrom {
|
StmtKind::ImportFrom(ast::StmtImportFrom {
|
||||||
module,
|
module,
|
||||||
names,
|
names,
|
||||||
level,
|
level,
|
||||||
} => {
|
}) => {
|
||||||
let level = level.unwrap_or(0);
|
let level = level.map_or(0, |level| level.to_usize());
|
||||||
let module = if let Some(module) = module {
|
let module = if let Some(module) = module {
|
||||||
|
let module: &String = module.as_ref();
|
||||||
if level == 0 {
|
if level == 0 {
|
||||||
Cow::Borrowed(module)
|
Cow::Borrowed(module)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
use std::iter::FusedIterator;
|
use std::iter::FusedIterator;
|
||||||
|
|
||||||
use ruff_text_size::{TextRange, TextSize};
|
use ruff_text_size::{TextRange, TextSize};
|
||||||
use rustpython_parser::ast::{Constant, ExprKind, Stmt, StmtKind, Suite};
|
use rustpython_parser::ast::{self, Constant, ExprKind, Stmt, StmtKind, Suite};
|
||||||
use rustpython_parser::lexer::LexResult;
|
use rustpython_parser::lexer::LexResult;
|
||||||
use rustpython_parser::Tok;
|
use rustpython_parser::Tok;
|
||||||
|
|
||||||
|
@ -76,11 +76,11 @@ struct StringLinesVisitor<'a> {
|
||||||
|
|
||||||
impl StatementVisitor<'_> for StringLinesVisitor<'_> {
|
impl StatementVisitor<'_> for StringLinesVisitor<'_> {
|
||||||
fn visit_stmt(&mut self, stmt: &Stmt) {
|
fn visit_stmt(&mut self, stmt: &Stmt) {
|
||||||
if let StmtKind::Expr { value } = &stmt.node {
|
if let StmtKind::Expr(ast::StmtExpr { value }) = &stmt.node {
|
||||||
if let ExprKind::Constant {
|
if let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(..),
|
value: Constant::Str(..),
|
||||||
..
|
..
|
||||||
} = &value.node
|
}) = &value.node
|
||||||
{
|
{
|
||||||
for line in UniversalNewlineIterator::with_offset(
|
for line in UniversalNewlineIterator::with_offset(
|
||||||
self.locator.slice(value.range()),
|
self.locator.slice(value.range()),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Extract docstrings from an AST.
|
//! Extract docstrings from an AST.
|
||||||
|
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Stmt, StmtKind};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_python_semantic::analyze::visibility;
|
use ruff_python_semantic::analyze::visibility;
|
||||||
|
|
||||||
|
@ -10,16 +10,16 @@ use crate::docstrings::definition::{Definition, DefinitionKind, Documentable};
|
||||||
pub fn docstring_from(suite: &[Stmt]) -> Option<&Expr> {
|
pub fn docstring_from(suite: &[Stmt]) -> Option<&Expr> {
|
||||||
let stmt = suite.first()?;
|
let stmt = suite.first()?;
|
||||||
// Require the docstring to be a standalone expression.
|
// Require the docstring to be a standalone expression.
|
||||||
let StmtKind::Expr { value } = &stmt.node else {
|
let StmtKind::Expr(ast::StmtExpr { value }) = &stmt.node else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
// Only match strings.
|
// Only match strings.
|
||||||
if !matches!(
|
if !matches!(
|
||||||
&value.node,
|
&value.node,
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(_),
|
value: Constant::Str(_),
|
||||||
..
|
..
|
||||||
}
|
})
|
||||||
) {
|
) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use libcst_native::{Codegen, CodegenState, ImportAlias, Name, NameOrAttribute};
|
use libcst_native::{Codegen, CodegenState, ImportAlias, Name, NameOrAttribute};
|
||||||
use ruff_text_size::TextSize;
|
use ruff_text_size::TextSize;
|
||||||
use rustpython_parser::ast::{Stmt, StmtKind, Suite};
|
use rustpython_parser::ast::{self, Stmt, StmtKind, Suite};
|
||||||
use rustpython_parser::{lexer, Mode, Tok};
|
use rustpython_parser::{lexer, Mode, Tok};
|
||||||
|
|
||||||
use ruff_diagnostics::Edit;
|
use ruff_diagnostics::Edit;
|
||||||
|
@ -79,13 +79,13 @@ impl<'a> Importer<'a> {
|
||||||
if stmt.start() >= at {
|
if stmt.start() >= at {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if let StmtKind::ImportFrom {
|
if let StmtKind::ImportFrom(ast::StmtImportFrom {
|
||||||
module: name,
|
module: name,
|
||||||
level,
|
level,
|
||||||
..
|
..
|
||||||
} = &stmt.node
|
}) = &stmt.node
|
||||||
{
|
{
|
||||||
if level.map_or(true, |level| level == 0)
|
if level.map_or(true, |level| level.to_u32() == 0)
|
||||||
&& name.as_ref().map_or(false, |name| name == module)
|
&& name.as_ref().map_or(false, |name| name == module)
|
||||||
{
|
{
|
||||||
import_from = Some(*stmt);
|
import_from = Some(*stmt);
|
||||||
|
@ -178,7 +178,8 @@ fn match_docstring_end(body: &[Stmt]) -> Option<TextSize> {
|
||||||
/// along with a trailing newline suffix.
|
/// along with a trailing newline suffix.
|
||||||
fn end_of_statement_insertion(stmt: &Stmt, locator: &Locator, stylist: &Stylist) -> Insertion {
|
fn end_of_statement_insertion(stmt: &Stmt, locator: &Locator, stylist: &Stylist) -> Insertion {
|
||||||
let location = stmt.end();
|
let location = stmt.end();
|
||||||
let mut tokens = lexer::lex_located(locator.after(location), Mode::Module, location).flatten();
|
let mut tokens =
|
||||||
|
lexer::lex_starts_at(locator.after(location), Mode::Module, location).flatten();
|
||||||
if let Some((Tok::Semi, range)) = tokens.next() {
|
if let Some((Tok::Semi, range)) = tokens.next() {
|
||||||
// If the first token after the docstring is a semicolon, insert after the semicolon as an
|
// If the first token after the docstring is a semicolon, insert after the semicolon as an
|
||||||
// inline statement;
|
// inline statement;
|
||||||
|
@ -211,7 +212,7 @@ fn top_of_file_insertion(body: &[Stmt], locator: &Locator, stylist: &Stylist) ->
|
||||||
let mut location = if let Some(location) = match_docstring_end(body) {
|
let mut location = if let Some(location) = match_docstring_end(body) {
|
||||||
// If the first token after the docstring is a semicolon, insert after the semicolon as an
|
// If the first token after the docstring is a semicolon, insert after the semicolon as an
|
||||||
// inline statement;
|
// inline statement;
|
||||||
let first_token = lexer::lex_located(locator.after(location), Mode::Module, location)
|
let first_token = lexer::lex_starts_at(locator.after(location), Mode::Module, location)
|
||||||
.flatten()
|
.flatten()
|
||||||
.next();
|
.next();
|
||||||
if let Some((Tok::Semi, range)) = first_token {
|
if let Some((Tok::Semi, range)) = first_token {
|
||||||
|
@ -226,7 +227,7 @@ fn top_of_file_insertion(body: &[Stmt], locator: &Locator, stylist: &Stylist) ->
|
||||||
|
|
||||||
// Skip over any comments and empty lines.
|
// Skip over any comments and empty lines.
|
||||||
for (tok, range) in
|
for (tok, range) in
|
||||||
lexer::lex_located(locator.after(location), Mode::Module, location).flatten()
|
lexer::lex_starts_at(locator.after(location), Mode::Module, location).flatten()
|
||||||
{
|
{
|
||||||
if matches!(tok, Tok::Comment(..) | Tok::Newline) {
|
if matches!(tok, Tok::Comment(..) | Tok::Newline) {
|
||||||
location = locator.full_line_end(range.end());
|
location = locator.full_line_end(range.end());
|
||||||
|
|
|
@ -145,7 +145,7 @@ impl<'a> DisplayParseError<'a> {
|
||||||
|
|
||||||
impl Display for DisplayParseError<'_> {
|
impl Display for DisplayParseError<'_> {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
let source_location = self.source_code.source_location(self.error.location);
|
let source_location = self.source_code.source_location(self.error.offset);
|
||||||
|
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
use rustpython_parser::ast::{Cmpop, Constant, Expr, ExprKind, Located};
|
use rustpython_parser::ast::{self, Attributed, Cmpop, Constant, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -124,16 +124,15 @@ fn is_sys(checker: &Checker, expr: &Expr, target: &str) -> bool {
|
||||||
pub fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) {
|
pub fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) {
|
||||||
if is_sys(checker, value, "version") {
|
if is_sys(checker, value, "version") {
|
||||||
match &slice.node {
|
match &slice.node {
|
||||||
ExprKind::Slice {
|
ExprKind::Slice(ast::ExprSlice {
|
||||||
lower: None,
|
lower: None,
|
||||||
upper: Some(upper),
|
upper: Some(upper),
|
||||||
step: None,
|
step: None,
|
||||||
..
|
}) => {
|
||||||
} => {
|
if let ExprKind::Constant(ast::ExprConstant {
|
||||||
if let ExprKind::Constant {
|
|
||||||
value: Constant::Int(i),
|
value: Constant::Int(i),
|
||||||
..
|
..
|
||||||
} = &upper.node
|
}) = &upper.node
|
||||||
{
|
{
|
||||||
if *i == BigInt::from(1)
|
if *i == BigInt::from(1)
|
||||||
&& checker.settings.rules.enabled(Rule::SysVersionSlice1)
|
&& checker.settings.rules.enabled(Rule::SysVersionSlice1)
|
||||||
|
@ -151,10 +150,10 @@ pub fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Int(i),
|
value: Constant::Int(i),
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
if *i == BigInt::from(2) && checker.settings.rules.enabled(Rule::SysVersion2) {
|
if *i == BigInt::from(2) && checker.settings.rules.enabled(Rule::SysVersion2) {
|
||||||
checker
|
checker
|
||||||
.diagnostics
|
.diagnostics
|
||||||
|
@ -175,21 +174,23 @@ pub fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) {
|
||||||
/// YTT103, YTT201, YTT203, YTT204, YTT302
|
/// YTT103, YTT201, YTT203, YTT204, YTT302
|
||||||
pub fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], comparators: &[Expr]) {
|
pub fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], comparators: &[Expr]) {
|
||||||
match &left.node {
|
match &left.node {
|
||||||
ExprKind::Subscript { value, slice, .. } if is_sys(checker, value, "version_info") => {
|
ExprKind::Subscript(ast::ExprSubscript { value, slice, .. })
|
||||||
if let ExprKind::Constant {
|
if is_sys(checker, value, "version_info") =>
|
||||||
|
{
|
||||||
|
if let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Int(i),
|
value: Constant::Int(i),
|
||||||
..
|
..
|
||||||
} = &slice.node
|
}) = &slice.node
|
||||||
{
|
{
|
||||||
if *i == BigInt::from(0) {
|
if *i == BigInt::from(0) {
|
||||||
if let (
|
if let (
|
||||||
[Cmpop::Eq | Cmpop::NotEq],
|
[Cmpop::Eq | Cmpop::NotEq],
|
||||||
[Located {
|
[Attributed {
|
||||||
node:
|
node:
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Int(n),
|
value: Constant::Int(n),
|
||||||
..
|
..
|
||||||
},
|
}),
|
||||||
..
|
..
|
||||||
}],
|
}],
|
||||||
) = (ops, comparators)
|
) = (ops, comparators)
|
||||||
|
@ -205,12 +206,12 @@ pub fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], comparators: &
|
||||||
} else if *i == BigInt::from(1) {
|
} else if *i == BigInt::from(1) {
|
||||||
if let (
|
if let (
|
||||||
[Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE],
|
[Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE],
|
||||||
[Located {
|
[Attributed {
|
||||||
node:
|
node:
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Int(_),
|
value: Constant::Int(_),
|
||||||
..
|
..
|
||||||
},
|
}),
|
||||||
..
|
..
|
||||||
}],
|
}],
|
||||||
) = (ops, comparators)
|
) = (ops, comparators)
|
||||||
|
@ -225,17 +226,17 @@ pub fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], comparators: &
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprKind::Attribute { value, attr, .. }
|
ExprKind::Attribute(ast::ExprAttribute { value, attr, .. })
|
||||||
if is_sys(checker, value, "version_info") && attr == "minor" =>
|
if is_sys(checker, value, "version_info") && attr == "minor" =>
|
||||||
{
|
{
|
||||||
if let (
|
if let (
|
||||||
[Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE],
|
[Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE],
|
||||||
[Located {
|
[Attributed {
|
||||||
node:
|
node:
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Int(_),
|
value: Constant::Int(_),
|
||||||
..
|
..
|
||||||
},
|
}),
|
||||||
..
|
..
|
||||||
}],
|
}],
|
||||||
) = (ops, comparators)
|
) = (ops, comparators)
|
||||||
|
@ -258,12 +259,12 @@ pub fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], comparators: &
|
||||||
if is_sys(checker, left, "version") {
|
if is_sys(checker, left, "version") {
|
||||||
if let (
|
if let (
|
||||||
[Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE],
|
[Cmpop::Lt | Cmpop::LtE | Cmpop::Gt | Cmpop::GtE],
|
||||||
[Located {
|
[Attributed {
|
||||||
node:
|
node:
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(s),
|
value: Constant::Str(s),
|
||||||
..
|
..
|
||||||
},
|
}),
|
||||||
..
|
..
|
||||||
}],
|
}],
|
||||||
) = (ops, comparators)
|
) = (ops, comparators)
|
||||||
|
|
|
@ -13,7 +13,7 @@ pub fn add_return_annotation(locator: &Locator, stmt: &Stmt, annotation: &str) -
|
||||||
let mut seen_lpar = false;
|
let mut seen_lpar = false;
|
||||||
let mut seen_rpar = false;
|
let mut seen_rpar = false;
|
||||||
let mut count: usize = 0;
|
let mut count: usize = 0;
|
||||||
for (tok, range) in lexer::lex_located(contents, Mode::Module, stmt.start()).flatten() {
|
for (tok, range) in lexer::lex_starts_at(contents, Mode::Module, stmt.start()).flatten() {
|
||||||
if seen_lpar && seen_rpar {
|
if seen_lpar && seen_rpar {
|
||||||
if matches!(tok, Tok::Colon) {
|
if matches!(tok, Tok::Colon) {
|
||||||
return Ok(Edit::insertion(format!(" -> {annotation}"), range.start()));
|
return Ok(Edit::insertion(format!(" -> {annotation}"), range.start()));
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Arguments, Expr, Stmt, StmtKind};
|
use rustpython_parser::ast::{self, Arguments, Expr, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_python_ast::cast;
|
use ruff_python_ast::cast;
|
||||||
use ruff_python_semantic::analyze::visibility;
|
use ruff_python_semantic::analyze::visibility;
|
||||||
|
@ -8,20 +8,20 @@ use crate::docstrings::definition::{Definition, DefinitionKind};
|
||||||
|
|
||||||
pub(super) fn match_function_def(stmt: &Stmt) -> (&str, &Arguments, Option<&Expr>, &Vec<Stmt>) {
|
pub(super) fn match_function_def(stmt: &Stmt) -> (&str, &Arguments, Option<&Expr>, &Vec<Stmt>) {
|
||||||
match &stmt.node {
|
match &stmt.node {
|
||||||
StmtKind::FunctionDef {
|
StmtKind::FunctionDef(ast::StmtFunctionDef {
|
||||||
name,
|
name,
|
||||||
args,
|
args,
|
||||||
returns,
|
returns,
|
||||||
body,
|
body,
|
||||||
..
|
..
|
||||||
}
|
})
|
||||||
| StmtKind::AsyncFunctionDef {
|
| StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef {
|
||||||
name,
|
name,
|
||||||
args,
|
args,
|
||||||
returns,
|
returns,
|
||||||
body,
|
body,
|
||||||
..
|
..
|
||||||
} => (name, args, returns.as_ref().map(|expr| &**expr), body),
|
}) => (name, args, returns.as_ref().map(|expr| &**expr), body),
|
||||||
_ => panic!("Found non-FunctionDef in match_name"),
|
_ => panic!("Found non-FunctionDef in match_name"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Stmt};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Stmt};
|
||||||
|
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Violation};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -420,10 +420,10 @@ fn is_none_returning(body: &[Stmt]) -> bool {
|
||||||
for expr in visitor.returns.into_iter().flatten() {
|
for expr in visitor.returns.into_iter().flatten() {
|
||||||
if !matches!(
|
if !matches!(
|
||||||
expr.node,
|
expr.node,
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::None,
|
value: Constant::None,
|
||||||
..
|
..
|
||||||
}
|
})
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind};
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
|
|
||||||
|
@ -10,10 +10,10 @@ static PASSWORD_CANDIDATE_REGEX: Lazy<Regex> = Lazy::new(|| {
|
||||||
|
|
||||||
pub fn string_literal(expr: &Expr) -> Option<&str> {
|
pub fn string_literal(expr: &Expr) -> Option<&str> {
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(string),
|
value: Constant::Str(string),
|
||||||
..
|
..
|
||||||
} => Some(string),
|
}) => Some(string),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ pub fn matches_password_name(string: &str) -> bool {
|
||||||
|
|
||||||
pub fn is_untyped_exception(type_: Option<&Expr>, checker: &Checker) -> bool {
|
pub fn is_untyped_exception(type_: Option<&Expr>, checker: &Checker) -> bool {
|
||||||
type_.map_or(true, |type_| {
|
type_.map_or(true, |type_| {
|
||||||
if let ExprKind::Tuple { elts, .. } = &type_.node {
|
if let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &type_.node {
|
||||||
elts.iter().any(|type_| {
|
elts.iter().any(|type_| {
|
||||||
checker
|
checker
|
||||||
.ctx
|
.ctx
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use num_traits::ToPrimitive;
|
use num_traits::ToPrimitive;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword, Operator};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword, Operator};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -70,14 +70,14 @@ static PYSTAT_MAPPING: Lazy<FxHashMap<&'static str, u16>> = Lazy::new(|| {
|
||||||
|
|
||||||
fn get_int_value(expr: &Expr) -> Option<u16> {
|
fn get_int_value(expr: &Expr) -> Option<u16> {
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Int(value),
|
value: Constant::Int(value),
|
||||||
..
|
..
|
||||||
} => value.to_u16(),
|
}) => value.to_u16(),
|
||||||
ExprKind::Attribute { .. } => {
|
ExprKind::Attribute(_) => {
|
||||||
compose_call_path(expr).and_then(|path| PYSTAT_MAPPING.get(path.as_str()).copied())
|
compose_call_path(expr).and_then(|path| PYSTAT_MAPPING.get(path.as_str()).copied())
|
||||||
}
|
}
|
||||||
ExprKind::BinOp { left, op, right } => {
|
ExprKind::BinOp(ast::ExprBinOp { left, op, right }) => {
|
||||||
if let (Some(left_value), Some(right_value)) =
|
if let (Some(left_value), Some(right_value)) =
|
||||||
(get_int_value(left), get_int_value(right))
|
(get_int_value(left), get_int_value(right))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind};
|
use rustpython_parser::ast::{self, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -15,7 +15,7 @@ impl Violation for ExecBuiltin {
|
||||||
|
|
||||||
/// S102
|
/// S102
|
||||||
pub fn exec_used(expr: &Expr, func: &Expr) -> Option<Diagnostic> {
|
pub fn exec_used(expr: &Expr, func: &Expr) -> Option<Diagnostic> {
|
||||||
let ExprKind::Name { id, .. } = &func.node else {
|
let ExprKind::Name(ast::ExprName { id, .. }) = &func.node else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
if id != "exec" {
|
if id != "exec" {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -24,17 +24,17 @@ impl Violation for HardcodedPasswordString {
|
||||||
fn password_target(target: &Expr) -> Option<&str> {
|
fn password_target(target: &Expr) -> Option<&str> {
|
||||||
let target_name = match &target.node {
|
let target_name = match &target.node {
|
||||||
// variable = "s3cr3t"
|
// variable = "s3cr3t"
|
||||||
ExprKind::Name { id, .. } => id,
|
ExprKind::Name(ast::ExprName { id, .. }) => id.as_str(),
|
||||||
// d["password"] = "s3cr3t"
|
// d["password"] = "s3cr3t"
|
||||||
ExprKind::Subscript { slice, .. } => match &slice.node {
|
ExprKind::Subscript(ast::ExprSubscript { slice, .. }) => match &slice.node {
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(string),
|
value: Constant::Str(string),
|
||||||
..
|
..
|
||||||
} => string,
|
}) => string,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
},
|
},
|
||||||
// obj.password = "s3cr3t"
|
// obj.password = "s3cr3t"
|
||||||
ExprKind::Attribute { attr, .. } => attr,
|
ExprKind::Attribute(ast::ExprAttribute { attr, .. }) => attr,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use rustpython_parser::ast::{Expr, ExprKind, Operator};
|
use rustpython_parser::ast::{self, Expr, ExprKind, Operator};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -56,10 +56,10 @@ fn unparse_string_format_expression(checker: &mut Checker, expr: &Expr) -> Optio
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
// "select * from table where val = " + "str" + ...
|
// "select * from table where val = " + "str" + ...
|
||||||
// "select * from table where val = %s" % ...
|
// "select * from table where val = %s" % ...
|
||||||
ExprKind::BinOp {
|
ExprKind::BinOp(ast::ExprBinOp {
|
||||||
op: Operator::Add | Operator::Mod,
|
op: Operator::Add | Operator::Mod,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
let Some(parent) = checker.ctx.expr_parent() else {
|
let Some(parent) = checker.ctx.expr_parent() else {
|
||||||
if any_over_expr(expr, &has_string_literal) {
|
if any_over_expr(expr, &has_string_literal) {
|
||||||
return Some(unparse_expr(expr, checker.stylist));
|
return Some(unparse_expr(expr, checker.stylist));
|
||||||
|
@ -67,7 +67,7 @@ fn unparse_string_format_expression(checker: &mut Checker, expr: &Expr) -> Optio
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
// Only evaluate the full BinOp, not the nested components.
|
// Only evaluate the full BinOp, not the nested components.
|
||||||
let ExprKind::BinOp { .. } = &parent.node else {
|
let ExprKind::BinOp(_ )= &parent.node else {
|
||||||
if any_over_expr(expr, &has_string_literal) {
|
if any_over_expr(expr, &has_string_literal) {
|
||||||
return Some(unparse_expr(expr, checker.stylist));
|
return Some(unparse_expr(expr, checker.stylist));
|
||||||
}
|
}
|
||||||
|
@ -75,8 +75,8 @@ fn unparse_string_format_expression(checker: &mut Checker, expr: &Expr) -> Optio
|
||||||
};
|
};
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
ExprKind::Call { func, .. } => {
|
ExprKind::Call(ast::ExprCall { func, .. }) => {
|
||||||
let ExprKind::Attribute{ attr, value, .. } = &func.node else {
|
let ExprKind::Attribute(ast::ExprAttribute { attr, value, .. }) = &func.node else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
// "select * from table where val = {}".format(...)
|
// "select * from table where val = {}".format(...)
|
||||||
|
@ -86,7 +86,7 @@ fn unparse_string_format_expression(checker: &mut Checker, expr: &Expr) -> Optio
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
// f"select * from table where val = {val}"
|
// f"select * from table where val = {val}"
|
||||||
ExprKind::JoinedStr { .. } => Some(unparse_expr(expr, checker.stylist)),
|
ExprKind::JoinedStr(_) => Some(unparse_expr(expr, checker.stylist)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -27,10 +27,10 @@ fn is_used_for_security(call_args: &SimpleCallArgs) -> bool {
|
||||||
match call_args.keyword_argument("usedforsecurity") {
|
match call_args.keyword_argument("usedforsecurity") {
|
||||||
Some(expr) => !matches!(
|
Some(expr) => !matches!(
|
||||||
&expr.node,
|
&expr.node,
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Bool(false),
|
value: Constant::Bool(false),
|
||||||
..
|
..
|
||||||
}
|
})
|
||||||
),
|
),
|
||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -47,13 +47,13 @@ pub fn jinja2_autoescape_false(
|
||||||
|
|
||||||
if let Some(autoescape_arg) = call_args.keyword_argument("autoescape") {
|
if let Some(autoescape_arg) = call_args.keyword_argument("autoescape") {
|
||||||
match &autoescape_arg.node {
|
match &autoescape_arg.node {
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Bool(true),
|
value: Constant::Bool(true),
|
||||||
..
|
..
|
||||||
} => (),
|
}) => (),
|
||||||
ExprKind::Call { func, .. } => {
|
ExprKind::Call(ast::ExprCall { func, .. }) => {
|
||||||
if let ExprKind::Name { id, .. } = &func.node {
|
if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node {
|
||||||
if id.as_str() != "select_autoescape" {
|
if id != "select_autoescape" {
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
Jinja2AutoescapeFalse { value: true },
|
Jinja2AutoescapeFalse { value: true },
|
||||||
autoescape_arg.range(),
|
autoescape_arg.range(),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -56,10 +56,10 @@ pub fn request_with_no_cert_validation(
|
||||||
}) {
|
}) {
|
||||||
let call_args = SimpleCallArgs::new(args, keywords);
|
let call_args = SimpleCallArgs::new(args, keywords);
|
||||||
if let Some(verify_arg) = call_args.keyword_argument("verify") {
|
if let Some(verify_arg) = call_args.keyword_argument("verify") {
|
||||||
if let ExprKind::Constant {
|
if let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Bool(false),
|
value: Constant::Bool(false),
|
||||||
..
|
..
|
||||||
} = &verify_arg.node
|
}) = &verify_arg.node
|
||||||
{
|
{
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
RequestWithNoCertValidation {
|
RequestWithNoCertValidation {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -45,10 +45,10 @@ pub fn request_without_timeout(
|
||||||
let call_args = SimpleCallArgs::new(args, keywords);
|
let call_args = SimpleCallArgs::new(args, keywords);
|
||||||
if let Some(timeout_arg) = call_args.keyword_argument("timeout") {
|
if let Some(timeout_arg) = call_args.keyword_argument("timeout") {
|
||||||
if let Some(timeout) = match &timeout_arg.node {
|
if let Some(timeout) = match &timeout_arg.node {
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: value @ Constant::None,
|
value: value @ Constant::None,
|
||||||
..
|
..
|
||||||
} => Some(unparse_constant(value, checker.stylist)),
|
}) => Some(unparse_constant(value, checker.stylist)),
|
||||||
_ => None,
|
_ => None,
|
||||||
} {
|
} {
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -159,17 +159,17 @@ fn find_shell_keyword<'a>(ctx: &Context, keywords: &'a [Keyword]) -> Option<Shel
|
||||||
fn shell_call_seems_safe(arg: &Expr) -> bool {
|
fn shell_call_seems_safe(arg: &Expr) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
arg.node,
|
arg.node,
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(_),
|
value: Constant::Str(_),
|
||||||
..
|
..
|
||||||
}
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the [`Expr`] as a string literal, if it's a string or a list of strings.
|
/// Return the [`Expr`] as a string literal, if it's a string or a list of strings.
|
||||||
fn try_string_literal(expr: &Expr) -> Option<&str> {
|
fn try_string_literal(expr: &Expr) -> Option<&str> {
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
ExprKind::List { elts, .. } => {
|
ExprKind::List(ast::ExprList { elts, .. }) => {
|
||||||
if elts.is_empty() {
|
if elts.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use num_traits::{One, Zero};
|
use num_traits::{One, Zero};
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -33,10 +33,10 @@ pub fn snmp_insecure_version(
|
||||||
{
|
{
|
||||||
let call_args = SimpleCallArgs::new(args, keywords);
|
let call_args = SimpleCallArgs::new(args, keywords);
|
||||||
if let Some(mp_model_arg) = call_args.keyword_argument("mpModel") {
|
if let Some(mp_model_arg) = call_args.keyword_argument("mpModel") {
|
||||||
if let ExprKind::Constant {
|
if let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Int(value),
|
value: Constant::Int(value),
|
||||||
..
|
..
|
||||||
} = &mp_model_arg.node
|
}) = &mp_model_arg.node
|
||||||
{
|
{
|
||||||
if value.is_zero() || value.is_one() {
|
if value.is_zero() || value.is_one() {
|
||||||
checker
|
checker
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! Check for calls to suspicious functions, or calls into suspicious modules.
|
//! Check for calls to suspicious functions, or calls into suspicious modules.
|
||||||
//!
|
//!
|
||||||
//! See: <https://bandit.readthedocs.io/en/latest/blacklists/blacklist_calls.html>
|
//! See: <https://bandit.readthedocs.io/en/latest/blacklists/blacklist_calls.html>
|
||||||
use rustpython_parser::ast::{Expr, ExprKind};
|
use rustpython_parser::ast::{self, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, DiagnosticKind, Violation};
|
use ruff_diagnostics::{Diagnostic, DiagnosticKind, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -466,7 +466,7 @@ const SUSPICIOUS_MODULES: &[SuspiciousModule] = &[
|
||||||
|
|
||||||
/// S001
|
/// S001
|
||||||
pub fn suspicious_function_call(checker: &mut Checker, expr: &Expr) {
|
pub fn suspicious_function_call(checker: &mut Checker, expr: &Expr) {
|
||||||
let ExprKind::Call { func, .. } = &expr.node else {
|
let ExprKind::Call(ast::ExprCall { func, .. }) = &expr.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
|
use rustpython_parser::ast::{self, Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -48,8 +48,8 @@ pub fn unsafe_yaml_load(checker: &mut Checker, func: &Expr, args: &[Expr], keywo
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
let loader = match &loader_arg.node {
|
let loader = match &loader_arg.node {
|
||||||
ExprKind::Attribute { attr, .. } => Some(attr.to_string()),
|
ExprKind::Attribute(ast::ExprAttribute { attr, .. }) => Some(attr.to_string()),
|
||||||
ExprKind::Name { id, .. } => Some(id.to_string()),
|
ExprKind::Name(ast::ExprName { id, .. }) => Some(id.to_string()),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind, Stmt, StmtKind};
|
use rustpython_parser::ast::{self, Expr, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -30,17 +30,17 @@ pub fn blind_except(
|
||||||
let Some(type_) = type_ else {
|
let Some(type_) = type_ else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let ExprKind::Name { id, .. } = &type_.node else {
|
let ExprKind::Name(ast::ExprName { id, .. }) = &type_.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
for exception in ["BaseException", "Exception"] {
|
for exception in ["BaseException", "Exception"] {
|
||||||
if id == exception && checker.ctx.is_builtin(exception) {
|
if id == exception && checker.ctx.is_builtin(exception) {
|
||||||
// If the exception is re-raised, don't flag an error.
|
// If the exception is re-raised, don't flag an error.
|
||||||
if body.iter().any(|stmt| {
|
if body.iter().any(|stmt| {
|
||||||
if let StmtKind::Raise { exc, .. } = &stmt.node {
|
if let StmtKind::Raise(ast::StmtRaise { exc, .. }) = &stmt.node {
|
||||||
if let Some(exc) = exc {
|
if let Some(exc) = exc {
|
||||||
if let ExprKind::Name { id, .. } = &exc.node {
|
if let ExprKind::Name(ast::ExprName { id, .. }) = &exc.node {
|
||||||
name.map_or(false, |name| name == id)
|
name.map_or(false, |name| id == name)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -56,10 +56,12 @@ pub fn blind_except(
|
||||||
|
|
||||||
// If the exception is logged, don't flag an error.
|
// If the exception is logged, don't flag an error.
|
||||||
if body.iter().any(|stmt| {
|
if body.iter().any(|stmt| {
|
||||||
if let StmtKind::Expr { value } = &stmt.node {
|
if let StmtKind::Expr(ast::StmtExpr { value }) = &stmt.node {
|
||||||
if let ExprKind::Call { func, keywords, .. } = &value.node {
|
if let ExprKind::Call(ast::ExprCall { func, keywords, .. }) = &value.node {
|
||||||
if logging::is_logger_candidate(&checker.ctx, func) {
|
if logging::is_logger_candidate(&checker.ctx, func) {
|
||||||
if let ExprKind::Attribute { attr, .. } = &func.node {
|
if let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &func.node
|
||||||
|
{
|
||||||
|
let attr = attr.as_str();
|
||||||
if attr == "exception" {
|
if attr == "exception" {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Arguments, Constant, Expr, ExprKind};
|
use rustpython_parser::ast::{self, Arguments, Constant, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::Violation;
|
use ruff_diagnostics::Violation;
|
||||||
use ruff_diagnostics::{Diagnostic, DiagnosticKind};
|
use ruff_diagnostics::{Diagnostic, DiagnosticKind};
|
||||||
|
@ -67,11 +67,11 @@ const FUNC_DEF_NAME_ALLOWLIST: &[&str] = &["__setitem__"];
|
||||||
/// `true`, the function name must be explicitly allowed, and the argument must
|
/// `true`, the function name must be explicitly allowed, and the argument must
|
||||||
/// be either the first or second argument in the call.
|
/// be either the first or second argument in the call.
|
||||||
fn allow_boolean_trap(func: &Expr) -> bool {
|
fn allow_boolean_trap(func: &Expr) -> bool {
|
||||||
if let ExprKind::Attribute { attr, .. } = &func.node {
|
if let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &func.node {
|
||||||
return FUNC_CALL_NAME_ALLOWLIST.contains(&attr.as_ref());
|
return FUNC_CALL_NAME_ALLOWLIST.contains(&attr.as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ExprKind::Name { id, .. } = &func.node {
|
if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node {
|
||||||
return FUNC_CALL_NAME_ALLOWLIST.contains(&id.as_ref());
|
return FUNC_CALL_NAME_ALLOWLIST.contains(&id.as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,10 +81,10 @@ fn allow_boolean_trap(func: &Expr) -> bool {
|
||||||
const fn is_boolean_arg(arg: &Expr) -> bool {
|
const fn is_boolean_arg(arg: &Expr) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
&arg.node,
|
&arg.node,
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Bool(_),
|
value: Constant::Bool(_),
|
||||||
..
|
..
|
||||||
}
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,11 +120,11 @@ pub fn check_positional_boolean_in_def(
|
||||||
|
|
||||||
// check for both bool (python class) and 'bool' (string annotation)
|
// check for both bool (python class) and 'bool' (string annotation)
|
||||||
let hint = match &expr.node {
|
let hint = match &expr.node {
|
||||||
ExprKind::Name { id, .. } => id == "bool",
|
ExprKind::Name(ast::ExprName { id, .. }) => id == "bool",
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(value),
|
value: Constant::Str(value),
|
||||||
..
|
..
|
||||||
} => value == "bool",
|
}) => value == "bool",
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
if !hint {
|
if !hint {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword, Stmt, StmtKind};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -57,8 +57,8 @@ fn is_abc_class(context: &Context, bases: &[Expr], keywords: &[Keyword]) -> bool
|
||||||
fn is_empty_body(body: &[Stmt]) -> bool {
|
fn is_empty_body(body: &[Stmt]) -> bool {
|
||||||
body.iter().all(|stmt| match &stmt.node {
|
body.iter().all(|stmt| match &stmt.node {
|
||||||
StmtKind::Pass => true,
|
StmtKind::Pass => true,
|
||||||
StmtKind::Expr { value } => match &value.node {
|
StmtKind::Expr(ast::StmtExpr { value }) => match &value.node {
|
||||||
ExprKind::Constant { value, .. } => {
|
ExprKind::Constant(ast::ExprConstant { value, .. }) => {
|
||||||
matches!(value, Constant::Str(..) | Constant::Ellipsis)
|
matches!(value, Constant::Str(..) | Constant::Ellipsis)
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -88,23 +88,23 @@ pub fn abstract_base_class(
|
||||||
for stmt in body {
|
for stmt in body {
|
||||||
// https://github.com/PyCQA/flake8-bugbear/issues/293
|
// https://github.com/PyCQA/flake8-bugbear/issues/293
|
||||||
// Ignore abc's that declares a class attribute that must be set
|
// Ignore abc's that declares a class attribute that must be set
|
||||||
if let StmtKind::AnnAssign { .. } | StmtKind::Assign { .. } = &stmt.node {
|
if let StmtKind::AnnAssign(_) | StmtKind::Assign(_) = &stmt.node {
|
||||||
has_abstract_method = true;
|
has_abstract_method = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (
|
let (
|
||||||
StmtKind::FunctionDef {
|
StmtKind::FunctionDef(ast::StmtFunctionDef {
|
||||||
decorator_list,
|
decorator_list,
|
||||||
body,
|
body,
|
||||||
name: method_name,
|
name: method_name,
|
||||||
..
|
..
|
||||||
} | StmtKind::AsyncFunctionDef {
|
}) | StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef {
|
||||||
decorator_list,
|
decorator_list,
|
||||||
body,
|
body,
|
||||||
name: method_name,
|
name: method_name,
|
||||||
..
|
..
|
||||||
}
|
})
|
||||||
) = &stmt.node else {
|
) = &stmt.node else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use ruff_text_size::TextSize;
|
use ruff_text_size::TextRange;
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -24,20 +24,17 @@ impl AlwaysAutofixableViolation for AssertFalse {
|
||||||
|
|
||||||
fn assertion_error(msg: Option<&Expr>) -> Stmt {
|
fn assertion_error(msg: Option<&Expr>) -> Stmt {
|
||||||
Stmt::new(
|
Stmt::new(
|
||||||
TextSize::default(),
|
TextRange::default(),
|
||||||
TextSize::default(),
|
StmtKind::Raise(ast::StmtRaise {
|
||||||
StmtKind::Raise {
|
|
||||||
exc: Some(Box::new(Expr::new(
|
exc: Some(Box::new(Expr::new(
|
||||||
TextSize::default(),
|
TextRange::default(),
|
||||||
TextSize::default(),
|
ExprKind::Call(ast::ExprCall {
|
||||||
ExprKind::Call {
|
|
||||||
func: Box::new(Expr::new(
|
func: Box::new(Expr::new(
|
||||||
TextSize::default(),
|
TextRange::default(),
|
||||||
TextSize::default(),
|
ExprKind::Name(ast::ExprName {
|
||||||
ExprKind::Name {
|
id: "AssertionError".into(),
|
||||||
id: "AssertionError".to_string(),
|
|
||||||
ctx: ExprContext::Load,
|
ctx: ExprContext::Load,
|
||||||
},
|
}),
|
||||||
)),
|
)),
|
||||||
args: if let Some(msg) = msg {
|
args: if let Some(msg) = msg {
|
||||||
vec![msg.clone()]
|
vec![msg.clone()]
|
||||||
|
@ -45,19 +42,19 @@ fn assertion_error(msg: Option<&Expr>) -> Stmt {
|
||||||
vec![]
|
vec![]
|
||||||
},
|
},
|
||||||
keywords: vec![],
|
keywords: vec![],
|
||||||
},
|
}),
|
||||||
))),
|
))),
|
||||||
cause: None,
|
cause: None,
|
||||||
},
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// B011
|
/// B011
|
||||||
pub fn assert_false(checker: &mut Checker, stmt: &Stmt, test: &Expr, msg: Option<&Expr>) {
|
pub fn assert_false(checker: &mut Checker, stmt: &Stmt, test: &Expr, msg: Option<&Expr>) {
|
||||||
let ExprKind::Constant {
|
let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Bool(false),
|
value: Constant::Bool(false),
|
||||||
..
|
..
|
||||||
} = &test.node else {
|
} )= &test.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{ExprKind, Stmt, Withitem};
|
use rustpython_parser::ast::{self, ExprKind, Stmt, Withitem};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -55,7 +55,7 @@ pub fn assert_raises_exception(checker: &mut Checker, stmt: &Stmt, items: &[With
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let item_context = &item.context_expr;
|
let item_context = &item.context_expr;
|
||||||
let ExprKind::Call { func, args, keywords } = &item_context.node else {
|
let ExprKind::Call(ast::ExprCall { func, args, keywords }) = &item_context.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if args.len() != 1 {
|
if args.len() != 1 {
|
||||||
|
@ -74,7 +74,8 @@ pub fn assert_raises_exception(checker: &mut Checker, stmt: &Stmt, items: &[With
|
||||||
}
|
}
|
||||||
|
|
||||||
let kind = {
|
let kind = {
|
||||||
if matches!(&func.node, ExprKind::Attribute { attr, .. } if attr == "assertRaises") {
|
if matches!(&func.node, ExprKind::Attribute(ast::ExprAttribute { attr, .. }) if attr == "assertRaises")
|
||||||
|
{
|
||||||
AssertionKind::AssertRaises
|
AssertionKind::AssertRaises
|
||||||
} else if checker
|
} else if checker
|
||||||
.ctx
|
.ctx
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind};
|
use rustpython_parser::ast::{self, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -20,13 +20,13 @@ pub fn assignment_to_os_environ(checker: &mut Checker, targets: &[Expr]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let target = &targets[0];
|
let target = &targets[0];
|
||||||
let ExprKind::Attribute { value, attr, .. } = &target.node else {
|
let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) = &target.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if attr != "environ" {
|
if attr != "environ" {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let ExprKind::Name { id, .. } = &value.node else {
|
let ExprKind::Name(ast::ExprName { id, .. } )= &value.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if id != "os" {
|
if id != "os" {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind};
|
use rustpython_parser::ast::{self, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -36,7 +36,7 @@ pub fn cached_instance_method(checker: &mut Checker, decorator_list: &[Expr]) {
|
||||||
for decorator in decorator_list {
|
for decorator in decorator_list {
|
||||||
// TODO(charlie): This should take into account `classmethod-decorators` and
|
// TODO(charlie): This should take into account `classmethod-decorators` and
|
||||||
// `staticmethod-decorators`.
|
// `staticmethod-decorators`.
|
||||||
if let ExprKind::Name { id, .. } = &decorator.node {
|
if let ExprKind::Name(ast::ExprName { id, .. }) = &decorator.node {
|
||||||
if id == "classmethod" || id == "staticmethod" {
|
if id == "classmethod" || id == "staticmethod" {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ pub fn cached_instance_method(checker: &mut Checker, decorator_list: &[Expr]) {
|
||||||
if is_cache_func(
|
if is_cache_func(
|
||||||
checker,
|
checker,
|
||||||
match &decorator.node {
|
match &decorator.node {
|
||||||
ExprKind::Call { func, .. } => func,
|
ExprKind::Call(ast::ExprCall { func, .. }) => func,
|
||||||
_ => decorator,
|
_ => decorator,
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -17,7 +17,7 @@ impl Violation for CannotRaiseLiteral {
|
||||||
|
|
||||||
/// B016
|
/// B016
|
||||||
pub fn cannot_raise_literal(checker: &mut Checker, expr: &Expr) {
|
pub fn cannot_raise_literal(checker: &mut Checker, expr: &Expr) {
|
||||||
let ExprKind::Constant { .. } = &expr.node else {
|
let ExprKind::Constant ( _) = &expr.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
checker
|
checker
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use ruff_text_size::TextSize;
|
use ruff_text_size::TextRange;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use rustpython_parser::ast::{Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind};
|
use rustpython_parser::ast::{self, Excepthandler, ExcepthandlerKind, Expr, ExprContext, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Violation};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Violation};
|
||||||
use ruff_diagnostics::{Diagnostic, Edit, Fix};
|
use ruff_diagnostics::{Diagnostic, Edit, Fix};
|
||||||
|
@ -50,9 +50,8 @@ impl AlwaysAutofixableViolation for DuplicateHandlerException {
|
||||||
|
|
||||||
fn type_pattern(elts: Vec<&Expr>) -> Expr {
|
fn type_pattern(elts: Vec<&Expr>) -> Expr {
|
||||||
Expr::new(
|
Expr::new(
|
||||||
TextSize::default(),
|
TextRange::default(),
|
||||||
TextSize::default(),
|
ast::ExprTuple {
|
||||||
ExprKind::Tuple {
|
|
||||||
elts: elts.into_iter().cloned().collect(),
|
elts: elts.into_iter().cloned().collect(),
|
||||||
ctx: ExprContext::Load,
|
ctx: ExprContext::Load,
|
||||||
},
|
},
|
||||||
|
@ -117,11 +116,11 @@ pub fn duplicate_exceptions(checker: &mut Checker, handlers: &[Excepthandler]) {
|
||||||
let mut seen: FxHashSet<CallPath> = FxHashSet::default();
|
let mut seen: FxHashSet<CallPath> = FxHashSet::default();
|
||||||
let mut duplicates: FxHashMap<CallPath, Vec<&Expr>> = FxHashMap::default();
|
let mut duplicates: FxHashMap<CallPath, Vec<&Expr>> = FxHashMap::default();
|
||||||
for handler in handlers {
|
for handler in handlers {
|
||||||
let ExcepthandlerKind::ExceptHandler { type_: Some(type_), .. } = &handler.node else {
|
let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { type_: Some(type_), .. }) = &handler.node else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
match &type_.node {
|
match &type_.node {
|
||||||
ExprKind::Attribute { .. } | ExprKind::Name { .. } => {
|
ExprKind::Attribute(_) | ExprKind::Name(_) => {
|
||||||
if let Some(call_path) = call_path::collect_call_path(type_) {
|
if let Some(call_path) = call_path::collect_call_path(type_) {
|
||||||
if seen.contains(&call_path) {
|
if seen.contains(&call_path) {
|
||||||
duplicates.entry(call_path).or_default().push(type_);
|
duplicates.entry(call_path).or_default().push(type_);
|
||||||
|
@ -130,7 +129,7 @@ pub fn duplicate_exceptions(checker: &mut Checker, handlers: &[Excepthandler]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Tuple { elts, .. } => {
|
ExprKind::Tuple(ast::ExprTuple { elts, .. }) => {
|
||||||
for (name, expr) in duplicate_handler_exceptions(checker, type_, elts) {
|
for (name, expr) in duplicate_handler_exceptions(checker, type_, elts) {
|
||||||
if seen.contains(&name) {
|
if seen.contains(&name) {
|
||||||
duplicates.entry(name).or_default().push(expr);
|
duplicates.entry(name).or_default().push(expr);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use rustpython_parser::ast::Excepthandler;
|
use rustpython_parser::ast::Excepthandler;
|
||||||
use rustpython_parser::ast::{ExcepthandlerKind, ExprKind};
|
use rustpython_parser::ast::{self, ExcepthandlerKind, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -18,11 +18,12 @@ impl Violation for ExceptWithEmptyTuple {
|
||||||
|
|
||||||
/// B029
|
/// B029
|
||||||
pub fn except_with_empty_tuple(checker: &mut Checker, excepthandler: &Excepthandler) {
|
pub fn except_with_empty_tuple(checker: &mut Checker, excepthandler: &Excepthandler) {
|
||||||
let ExcepthandlerKind::ExceptHandler { type_, .. } = &excepthandler.node;
|
let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) =
|
||||||
|
&excepthandler.node;
|
||||||
let Some(type_) = type_ else {
|
let Some(type_) = type_ else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let ExprKind::Tuple { elts, .. } = &type_.node else {
|
let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &type_.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if elts.is_empty() {
|
if elts.is_empty() {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use rustpython_parser::ast::{Excepthandler, ExcepthandlerKind, Expr, ExprKind};
|
use rustpython_parser::ast::{self, Excepthandler, ExcepthandlerKind, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -21,15 +21,16 @@ impl Violation for ExceptWithNonExceptionClasses {
|
||||||
/// This should leave any unstarred iterables alone (subsequently raising a
|
/// This should leave any unstarred iterables alone (subsequently raising a
|
||||||
/// warning for B029).
|
/// warning for B029).
|
||||||
fn flatten_starred_iterables(expr: &Expr) -> Vec<&Expr> {
|
fn flatten_starred_iterables(expr: &Expr) -> Vec<&Expr> {
|
||||||
let ExprKind::Tuple { elts, .. } = &expr.node else {
|
let ExprKind::Tuple(ast::ExprTuple { elts, .. } )= &expr.node else {
|
||||||
return vec![expr];
|
return vec![expr];
|
||||||
};
|
};
|
||||||
let mut flattened_exprs: Vec<&Expr> = Vec::with_capacity(elts.len());
|
let mut flattened_exprs: Vec<&Expr> = Vec::with_capacity(elts.len());
|
||||||
let mut exprs_to_process: VecDeque<&Expr> = elts.iter().collect();
|
let mut exprs_to_process: VecDeque<&Expr> = elts.iter().collect();
|
||||||
while let Some(expr) = exprs_to_process.pop_front() {
|
while let Some(expr) = exprs_to_process.pop_front() {
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
ExprKind::Starred { value, .. } => match &value.node {
|
ExprKind::Starred(ast::ExprStarred { value, .. }) => match &value.node {
|
||||||
ExprKind::Tuple { elts, .. } | ExprKind::List { elts, .. } => {
|
ExprKind::Tuple(ast::ExprTuple { elts, .. })
|
||||||
|
| ExprKind::List(ast::ExprList { elts, .. }) => {
|
||||||
exprs_to_process.append(&mut elts.iter().collect());
|
exprs_to_process.append(&mut elts.iter().collect());
|
||||||
}
|
}
|
||||||
_ => flattened_exprs.push(value),
|
_ => flattened_exprs.push(value),
|
||||||
|
@ -42,17 +43,15 @@ fn flatten_starred_iterables(expr: &Expr) -> Vec<&Expr> {
|
||||||
|
|
||||||
/// B030
|
/// B030
|
||||||
pub fn except_with_non_exception_classes(checker: &mut Checker, excepthandler: &Excepthandler) {
|
pub fn except_with_non_exception_classes(checker: &mut Checker, excepthandler: &Excepthandler) {
|
||||||
let ExcepthandlerKind::ExceptHandler { type_, .. } = &excepthandler.node;
|
let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { type_, .. }) =
|
||||||
|
&excepthandler.node;
|
||||||
let Some(type_) = type_ else {
|
let Some(type_) = type_ else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
for expr in flatten_starred_iterables(type_) {
|
for expr in flatten_starred_iterables(type_) {
|
||||||
if !matches!(
|
if !matches!(
|
||||||
&expr.node,
|
&expr.node,
|
||||||
ExprKind::Subscript { .. }
|
ExprKind::Subscript(_) | ExprKind::Attribute(_) | ExprKind::Name(_) | ExprKind::Call(_),
|
||||||
| ExprKind::Attribute { .. }
|
|
||||||
| ExprKind::Name { .. }
|
|
||||||
| ExprKind::Call { .. },
|
|
||||||
) {
|
) {
|
||||||
checker
|
checker
|
||||||
.diagnostics
|
.diagnostics
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{ExprKind, Stmt, StmtKind};
|
use rustpython_parser::ast::{self, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -23,10 +23,10 @@ pub fn f_string_docstring(checker: &mut Checker, body: &[Stmt]) {
|
||||||
let Some(stmt) = body.first() else {
|
let Some(stmt) = body.first() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let StmtKind::Expr { value } = &stmt.node else {
|
let StmtKind::Expr(ast::StmtExpr { value }) = &stmt.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let ExprKind::JoinedStr { .. } = value.node else {
|
let ExprKind::JoinedStr ( _) = value.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use ruff_text_size::TextRange;
|
use ruff_text_size::TextRange;
|
||||||
use rustpython_parser::ast::{Arguments, Constant, Expr, ExprKind};
|
use rustpython_parser::ast::{self, Arguments, Constant, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::Violation;
|
use ruff_diagnostics::Violation;
|
||||||
use ruff_diagnostics::{Diagnostic, DiagnosticKind};
|
use ruff_diagnostics::{Diagnostic, DiagnosticKind};
|
||||||
|
@ -84,7 +84,7 @@ where
|
||||||
{
|
{
|
||||||
fn visit_expr(&mut self, expr: &'b Expr) {
|
fn visit_expr(&mut self, expr: &'b Expr) {
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
ExprKind::Call { func, args, .. } => {
|
ExprKind::Call(ast::ExprCall { func, args, .. }) => {
|
||||||
if !is_mutable_func(self.checker, func)
|
if !is_mutable_func(self.checker, func)
|
||||||
&& !is_immutable_func(&self.checker.ctx, func, &self.extend_immutable_calls)
|
&& !is_immutable_func(&self.checker.ctx, func, &self.extend_immutable_calls)
|
||||||
&& !is_nan_or_infinity(func, args)
|
&& !is_nan_or_infinity(func, args)
|
||||||
|
@ -99,14 +99,14 @@ where
|
||||||
}
|
}
|
||||||
visitor::walk_expr(self, expr);
|
visitor::walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
ExprKind::Lambda { .. } => {}
|
ExprKind::Lambda(_) => {}
|
||||||
_ => visitor::walk_expr(self, expr),
|
_ => visitor::walk_expr(self, expr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_nan_or_infinity(expr: &Expr, args: &[Expr]) -> bool {
|
fn is_nan_or_infinity(expr: &Expr, args: &[Expr]) -> bool {
|
||||||
let ExprKind::Name { id, .. } = &expr.node else {
|
let ExprKind::Name(ast::ExprName { id, .. }) = &expr.node else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
if id != "float" {
|
if id != "float" {
|
||||||
|
@ -115,10 +115,10 @@ fn is_nan_or_infinity(expr: &Expr, args: &[Expr]) -> bool {
|
||||||
let Some(arg) = args.first() else {
|
let Some(arg) = args.first() else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
let ExprKind::Constant {
|
let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(value),
|
value: Constant::Str(value),
|
||||||
..
|
..
|
||||||
} = &arg.node else {
|
} )= &arg.node else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
let lowercased = value.to_lowercase();
|
let lowercased = value.to_lowercase();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use ruff_text_size::TextRange;
|
use ruff_text_size::TextRange;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use rustpython_parser::ast::{Comprehension, Expr, ExprContext, ExprKind, Stmt, StmtKind};
|
use rustpython_parser::ast::{self, Comprehension, Expr, ExprContext, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -36,7 +36,7 @@ struct LoadedNamesVisitor<'a> {
|
||||||
impl<'a> Visitor<'a> for LoadedNamesVisitor<'a> {
|
impl<'a> Visitor<'a> for LoadedNamesVisitor<'a> {
|
||||||
fn visit_expr(&mut self, expr: &'a Expr) {
|
fn visit_expr(&mut self, expr: &'a Expr) {
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
ExprKind::Name { id, ctx } => match ctx {
|
ExprKind::Name(ast::ExprName { id, ctx }) => match ctx {
|
||||||
ExprContext::Load => self.loaded.push((id, expr, expr.range())),
|
ExprContext::Load => self.loaded.push((id, expr, expr.range())),
|
||||||
ExprContext::Store => self.stored.push((id, expr, expr.range())),
|
ExprContext::Store => self.stored.push((id, expr, expr.range())),
|
||||||
ExprContext::Del => {}
|
ExprContext::Del => {}
|
||||||
|
@ -57,8 +57,8 @@ struct SuspiciousVariablesVisitor<'a> {
|
||||||
impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> {
|
impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> {
|
||||||
fn visit_stmt(&mut self, stmt: &'a Stmt) {
|
fn visit_stmt(&mut self, stmt: &'a Stmt) {
|
||||||
match &stmt.node {
|
match &stmt.node {
|
||||||
StmtKind::FunctionDef { args, body, .. }
|
StmtKind::FunctionDef(ast::StmtFunctionDef { args, body, .. })
|
||||||
| StmtKind::AsyncFunctionDef { args, body, .. } => {
|
| StmtKind::AsyncFunctionDef(ast::StmtAsyncFunctionDef { args, body, .. }) => {
|
||||||
// Collect all loaded variable names.
|
// Collect all loaded variable names.
|
||||||
let mut visitor = LoadedNamesVisitor::default();
|
let mut visitor = LoadedNamesVisitor::default();
|
||||||
visitor.visit_body(body);
|
visitor.visit_body(body);
|
||||||
|
@ -76,9 +76,9 @@ impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> {
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
StmtKind::Return { value: Some(value) } => {
|
StmtKind::Return(ast::StmtReturn { value: Some(value) }) => {
|
||||||
// Mark `return lambda: x` as safe.
|
// Mark `return lambda: x` as safe.
|
||||||
if matches!(value.node, ExprKind::Lambda { .. }) {
|
if matches!(value.node, ExprKind::Lambda(_)) {
|
||||||
self.safe_functions.push(value);
|
self.safe_functions.push(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,26 +89,27 @@ impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> {
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &'a Expr) {
|
fn visit_expr(&mut self, expr: &'a Expr) {
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
ExprKind::Call {
|
ExprKind::Call(ast::ExprCall {
|
||||||
func,
|
func,
|
||||||
args,
|
args,
|
||||||
keywords,
|
keywords,
|
||||||
} => {
|
}) => {
|
||||||
if let ExprKind::Name { id, .. } = &func.node {
|
if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node {
|
||||||
|
let id = id.as_str();
|
||||||
if id == "filter" || id == "reduce" || id == "map" {
|
if id == "filter" || id == "reduce" || id == "map" {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
if matches!(arg.node, ExprKind::Lambda { .. }) {
|
if matches!(arg.node, ExprKind::Lambda(_)) {
|
||||||
self.safe_functions.push(arg);
|
self.safe_functions.push(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let ExprKind::Attribute { value, attr, .. } = &func.node {
|
if let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) = &func.node {
|
||||||
if attr == "reduce" {
|
if attr == "reduce" {
|
||||||
if let ExprKind::Name { id, .. } = &value.node {
|
if let ExprKind::Name(ast::ExprName { id, .. }) = &value.node {
|
||||||
if id == "functools" {
|
if id == "functools" {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
if matches!(arg.node, ExprKind::Lambda { .. }) {
|
if matches!(arg.node, ExprKind::Lambda(_)) {
|
||||||
self.safe_functions.push(arg);
|
self.safe_functions.push(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,13 +119,13 @@ impl<'a> Visitor<'a> for SuspiciousVariablesVisitor<'a> {
|
||||||
}
|
}
|
||||||
for keyword in keywords {
|
for keyword in keywords {
|
||||||
if keyword.node.arg.as_ref().map_or(false, |arg| arg == "key")
|
if keyword.node.arg.as_ref().map_or(false, |arg| arg == "key")
|
||||||
&& matches!(keyword.node.value.node, ExprKind::Lambda { .. })
|
&& matches!(keyword.node.value.node, ExprKind::Lambda(_))
|
||||||
{
|
{
|
||||||
self.safe_functions.push(&keyword.node.value);
|
self.safe_functions.push(&keyword.node.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Lambda { args, body } => {
|
ExprKind::Lambda(ast::ExprLambda { args, body }) => {
|
||||||
if !self.safe_functions.contains(&expr) {
|
if !self.safe_functions.contains(&expr) {
|
||||||
// Collect all loaded variable names.
|
// Collect all loaded variable names.
|
||||||
let mut visitor = LoadedNamesVisitor::default();
|
let mut visitor = LoadedNamesVisitor::default();
|
||||||
|
@ -160,13 +161,14 @@ struct NamesFromAssignmentsVisitor<'a> {
|
||||||
impl<'a> Visitor<'a> for NamesFromAssignmentsVisitor<'a> {
|
impl<'a> Visitor<'a> for NamesFromAssignmentsVisitor<'a> {
|
||||||
fn visit_expr(&mut self, expr: &'a Expr) {
|
fn visit_expr(&mut self, expr: &'a Expr) {
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
ExprKind::Name { id, .. } => {
|
ExprKind::Name(ast::ExprName { id, .. }) => {
|
||||||
self.names.insert(id.as_str());
|
self.names.insert(id.as_str());
|
||||||
}
|
}
|
||||||
ExprKind::Starred { value, .. } => {
|
ExprKind::Starred(ast::ExprStarred { value, .. }) => {
|
||||||
self.visit_expr(value);
|
self.visit_expr(value);
|
||||||
}
|
}
|
||||||
ExprKind::List { elts, .. } | ExprKind::Tuple { elts, .. } => {
|
ExprKind::List(ast::ExprList { elts, .. })
|
||||||
|
| ExprKind::Tuple(ast::ExprTuple { elts, .. }) => {
|
||||||
for expr in elts {
|
for expr in elts {
|
||||||
self.visit_expr(expr);
|
self.visit_expr(expr);
|
||||||
}
|
}
|
||||||
|
@ -186,24 +188,24 @@ impl<'a> Visitor<'a> for AssignedNamesVisitor<'a> {
|
||||||
fn visit_stmt(&mut self, stmt: &'a Stmt) {
|
fn visit_stmt(&mut self, stmt: &'a Stmt) {
|
||||||
if matches!(
|
if matches!(
|
||||||
&stmt.node,
|
&stmt.node,
|
||||||
StmtKind::FunctionDef { .. } | StmtKind::AsyncFunctionDef { .. }
|
StmtKind::FunctionDef(_) | StmtKind::AsyncFunctionDef(_)
|
||||||
) {
|
) {
|
||||||
// Don't recurse.
|
// Don't recurse.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match &stmt.node {
|
match &stmt.node {
|
||||||
StmtKind::Assign { targets, .. } => {
|
StmtKind::Assign(ast::StmtAssign { targets, .. }) => {
|
||||||
let mut visitor = NamesFromAssignmentsVisitor::default();
|
let mut visitor = NamesFromAssignmentsVisitor::default();
|
||||||
for expr in targets {
|
for expr in targets {
|
||||||
visitor.visit_expr(expr);
|
visitor.visit_expr(expr);
|
||||||
}
|
}
|
||||||
self.names.extend(visitor.names);
|
self.names.extend(visitor.names);
|
||||||
}
|
}
|
||||||
StmtKind::AugAssign { target, .. }
|
StmtKind::AugAssign(ast::StmtAugAssign { target, .. })
|
||||||
| StmtKind::AnnAssign { target, .. }
|
| StmtKind::AnnAssign(ast::StmtAnnAssign { target, .. })
|
||||||
| StmtKind::For { target, .. }
|
| StmtKind::For(ast::StmtFor { target, .. })
|
||||||
| StmtKind::AsyncFor { target, .. } => {
|
| StmtKind::AsyncFor(ast::StmtAsyncFor { target, .. }) => {
|
||||||
let mut visitor = NamesFromAssignmentsVisitor::default();
|
let mut visitor = NamesFromAssignmentsVisitor::default();
|
||||||
visitor.visit_expr(target);
|
visitor.visit_expr(target);
|
||||||
self.names.extend(visitor.names);
|
self.names.extend(visitor.names);
|
||||||
|
@ -215,7 +217,7 @@ impl<'a> Visitor<'a> for AssignedNamesVisitor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &'a Expr) {
|
fn visit_expr(&mut self, expr: &'a Expr) {
|
||||||
if matches!(&expr.node, ExprKind::Lambda { .. }) {
|
if matches!(&expr.node, ExprKind::Lambda(_)) {
|
||||||
// Don't recurse.
|
// Don't recurse.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use ruff_text_size::TextSize;
|
use ruff_text_size::TextRange;
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprContext, ExprKind};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprContext, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -27,11 +27,10 @@ impl AlwaysAutofixableViolation for GetAttrWithConstant {
|
||||||
}
|
}
|
||||||
fn attribute(value: &Expr, attr: &str) -> Expr {
|
fn attribute(value: &Expr, attr: &str) -> Expr {
|
||||||
Expr::new(
|
Expr::new(
|
||||||
TextSize::default(),
|
TextRange::default(),
|
||||||
TextSize::default(),
|
ast::ExprAttribute {
|
||||||
ExprKind::Attribute {
|
|
||||||
value: Box::new(value.clone()),
|
value: Box::new(value.clone()),
|
||||||
attr: attr.to_string(),
|
attr: attr.into(),
|
||||||
ctx: ExprContext::Load,
|
ctx: ExprContext::Load,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -39,7 +38,7 @@ fn attribute(value: &Expr, attr: &str) -> Expr {
|
||||||
|
|
||||||
/// B009
|
/// B009
|
||||||
pub fn getattr_with_constant(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
|
pub fn getattr_with_constant(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
|
||||||
let ExprKind::Name { id, .. } = &func.node else {
|
let ExprKind::Name(ast::ExprName { id, .. } )= &func.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if id != "getattr" {
|
if id != "getattr" {
|
||||||
|
@ -48,10 +47,10 @@ pub fn getattr_with_constant(checker: &mut Checker, expr: &Expr, func: &Expr, ar
|
||||||
let [obj, arg] = args else {
|
let [obj, arg] = args else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let ExprKind::Constant {
|
let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(value),
|
value: Constant::Str(value),
|
||||||
..
|
..
|
||||||
} = &arg.node else {
|
} )= &arg.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if !is_identifier(value) {
|
if !is_identifier(value) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Stmt, StmtKind};
|
use rustpython_parser::ast::{self, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -24,33 +24,34 @@ fn walk_stmt(checker: &mut Checker, body: &[Stmt], f: fn(&Stmt) -> bool) {
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
JumpStatementInFinally {
|
JumpStatementInFinally {
|
||||||
name: match &stmt.node {
|
name: match &stmt.node {
|
||||||
StmtKind::Break { .. } => "break".to_string(),
|
StmtKind::Break => "break",
|
||||||
StmtKind::Continue { .. } => "continue".to_string(),
|
StmtKind::Continue => "continue",
|
||||||
StmtKind::Return { .. } => "return".to_string(),
|
StmtKind::Return(_) => "return",
|
||||||
_ => unreachable!(
|
_ => unreachable!(
|
||||||
"Expected StmtKind::Break | StmtKind::Continue | StmtKind::Return"
|
"Expected StmtKind::Break | StmtKind::Continue | StmtKind::Return"
|
||||||
),
|
),
|
||||||
},
|
}
|
||||||
|
.to_owned(),
|
||||||
},
|
},
|
||||||
stmt.range(),
|
stmt.range(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
match &stmt.node {
|
match &stmt.node {
|
||||||
StmtKind::While { body, .. }
|
StmtKind::While(ast::StmtWhile { body, .. })
|
||||||
| StmtKind::For { body, .. }
|
| StmtKind::For(ast::StmtFor { body, .. })
|
||||||
| StmtKind::AsyncFor { body, .. } => {
|
| StmtKind::AsyncFor(ast::StmtAsyncFor { body, .. }) => {
|
||||||
walk_stmt(checker, body, |stmt| {
|
walk_stmt(checker, body, |stmt| {
|
||||||
matches!(stmt.node, StmtKind::Return { .. })
|
matches!(stmt.node, StmtKind::Return(_))
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
StmtKind::If { body, .. }
|
StmtKind::If(ast::StmtIf { body, .. })
|
||||||
| StmtKind::Try { body, .. }
|
| StmtKind::Try(ast::StmtTry { body, .. })
|
||||||
| StmtKind::TryStar { body, .. }
|
| StmtKind::TryStar(ast::StmtTryStar { body, .. })
|
||||||
| StmtKind::With { body, .. }
|
| StmtKind::With(ast::StmtWith { body, .. })
|
||||||
| StmtKind::AsyncWith { body, .. } => {
|
| StmtKind::AsyncWith(ast::StmtAsyncWith { body, .. }) => {
|
||||||
walk_stmt(checker, body, f);
|
walk_stmt(checker, body, f);
|
||||||
}
|
}
|
||||||
StmtKind::Match { cases, .. } => {
|
StmtKind::Match(ast::StmtMatch { cases, .. }) => {
|
||||||
for case in cases {
|
for case in cases {
|
||||||
walk_stmt(checker, &case.body, f);
|
walk_stmt(checker, &case.body, f);
|
||||||
}
|
}
|
||||||
|
@ -65,7 +66,7 @@ pub fn jump_statement_in_finally(checker: &mut Checker, finalbody: &[Stmt]) {
|
||||||
walk_stmt(checker, finalbody, |stmt| {
|
walk_stmt(checker, finalbody, |stmt| {
|
||||||
matches!(
|
matches!(
|
||||||
stmt.node,
|
stmt.node,
|
||||||
StmtKind::Break | StmtKind::Continue | StmtKind::Return { .. }
|
StmtKind::Break | StmtKind::Continue | StmtKind::Return(_)
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use rustpython_parser::ast::{Expr, ExprKind};
|
use rustpython_parser::ast::{self, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -32,18 +32,18 @@ where
|
||||||
{
|
{
|
||||||
fn visit_expr(&mut self, expr: &'b Expr) {
|
fn visit_expr(&mut self, expr: &'b Expr) {
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
ExprKind::Name { id, .. } => {
|
ExprKind::Name(ast::ExprName { id, .. }) => {
|
||||||
self.names.insert(id, expr);
|
self.names.insert(id, expr);
|
||||||
}
|
}
|
||||||
ExprKind::ListComp { generators, .. }
|
ExprKind::ListComp(ast::ExprListComp { generators, .. })
|
||||||
| ExprKind::DictComp { generators, .. }
|
| ExprKind::DictComp(ast::ExprDictComp { generators, .. })
|
||||||
| ExprKind::SetComp { generators, .. }
|
| ExprKind::SetComp(ast::ExprSetComp { generators, .. })
|
||||||
| ExprKind::GeneratorExp { generators, .. } => {
|
| ExprKind::GeneratorExp(ast::ExprGeneratorExp { generators, .. }) => {
|
||||||
for comp in generators {
|
for comp in generators {
|
||||||
self.visit_expr(&comp.iter);
|
self.visit_expr(&comp.iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Lambda { args, body } => {
|
ExprKind::Lambda(ast::ExprLambda { args, body }) => {
|
||||||
visitor::walk_expr(self, body);
|
visitor::walk_expr(self, body);
|
||||||
for arg in &args.args {
|
for arg in &args.args {
|
||||||
self.names.remove(arg.node.arg.as_str());
|
self.names.remove(arg.node.arg.as_str());
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Arguments, Expr, ExprKind};
|
use rustpython_parser::ast::{self, Arguments, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -38,13 +38,13 @@ pub fn is_mutable_func(checker: &Checker, func: &Expr) -> bool {
|
||||||
|
|
||||||
fn is_mutable_expr(checker: &Checker, expr: &Expr) -> bool {
|
fn is_mutable_expr(checker: &Checker, expr: &Expr) -> bool {
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
ExprKind::List { .. }
|
ExprKind::List(_)
|
||||||
| ExprKind::Dict { .. }
|
| ExprKind::Dict(_)
|
||||||
| ExprKind::Set { .. }
|
| ExprKind::Set(_)
|
||||||
| ExprKind::ListComp { .. }
|
| ExprKind::ListComp(_)
|
||||||
| ExprKind::DictComp { .. }
|
| ExprKind::DictComp(_)
|
||||||
| ExprKind::SetComp { .. } => true,
|
| ExprKind::SetComp(_) => true,
|
||||||
ExprKind::Call { func, .. } => is_mutable_func(checker, func),
|
ExprKind::Call(ast::ExprCall { func, .. }) => is_mutable_func(checker, func),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{ExprKind, Stmt};
|
use rustpython_parser::ast::{self, ExprKind, Stmt};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -33,7 +33,7 @@ pub fn raise_without_from_inside_except(checker: &mut Checker, body: &[Stmt]) {
|
||||||
if cause.is_none() {
|
if cause.is_none() {
|
||||||
if let Some(exc) = exc {
|
if let Some(exc) = exc {
|
||||||
match &exc.node {
|
match &exc.node {
|
||||||
ExprKind::Name { id, .. } if is_lower(id) => {}
|
ExprKind::Name(ast::ExprName { id, .. }) if is_lower(id) => {}
|
||||||
_ => {
|
_ => {
|
||||||
checker
|
checker
|
||||||
.diagnostics
|
.diagnostics
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Excepthandler, ExcepthandlerKind, ExprKind};
|
use rustpython_parser::ast::{self, Excepthandler, ExcepthandlerKind, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -31,10 +31,10 @@ impl AlwaysAutofixableViolation for RedundantTupleInExceptionHandler {
|
||||||
/// B013
|
/// B013
|
||||||
pub fn redundant_tuple_in_exception_handler(checker: &mut Checker, handlers: &[Excepthandler]) {
|
pub fn redundant_tuple_in_exception_handler(checker: &mut Checker, handlers: &[Excepthandler]) {
|
||||||
for handler in handlers {
|
for handler in handlers {
|
||||||
let ExcepthandlerKind::ExceptHandler { type_: Some(type_), .. } = &handler.node else {
|
let ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler { type_: Some(type_), .. }) = &handler.node else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let ExprKind::Tuple { elts, .. } = &type_.node else {
|
let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &type_.node else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let [elt] = &elts[..] else {
|
let [elt] = &elts[..] else {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Comprehension, Expr, ExprKind, Stmt, StmtKind};
|
use rustpython_parser::ast::{self, Comprehension, Expr, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -84,7 +84,7 @@ impl<'a> GroupNameFinder<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name_matches(&self, expr: &Expr) -> bool {
|
fn name_matches(&self, expr: &Expr) -> bool {
|
||||||
if let ExprKind::Name { id, .. } = &expr.node {
|
if let ExprKind::Name(ast::ExprName { id, .. }) = &expr.node {
|
||||||
id == self.group_name
|
id == self.group_name
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -113,9 +113,9 @@ where
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
match &stmt.node {
|
match &stmt.node {
|
||||||
StmtKind::For {
|
StmtKind::For(ast::StmtFor {
|
||||||
target, iter, body, ..
|
target, iter, body, ..
|
||||||
} => {
|
}) => {
|
||||||
if self.name_matches(target) {
|
if self.name_matches(target) {
|
||||||
self.overridden = true;
|
self.overridden = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -138,15 +138,15 @@ where
|
||||||
self.nested = false;
|
self.nested = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::While { body, .. } => {
|
StmtKind::While(ast::StmtWhile { body, .. }) => {
|
||||||
self.nested = true;
|
self.nested = true;
|
||||||
visitor::walk_body(self, body);
|
visitor::walk_body(self, body);
|
||||||
self.nested = false;
|
self.nested = false;
|
||||||
}
|
}
|
||||||
StmtKind::If { test, body, orelse } => {
|
StmtKind::If(ast::StmtIf { test, body, orelse }) => {
|
||||||
// Determine whether we're on an `if` arm (as opposed to an `elif`).
|
// Determine whether we're on an `if` arm (as opposed to an `elif`).
|
||||||
let is_if_arm = !self.parent_ifs.iter().any(|parent| {
|
let is_if_arm = !self.parent_ifs.iter().any(|parent| {
|
||||||
if let StmtKind::If { orelse, .. } = &parent.node {
|
if let StmtKind::If(ast::StmtIf { orelse, .. }) = &parent.node {
|
||||||
orelse.len() == 1 && &orelse[0] == stmt
|
orelse.len() == 1 && &orelse[0] == stmt
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -166,7 +166,7 @@ where
|
||||||
|
|
||||||
let has_else = orelse
|
let has_else = orelse
|
||||||
.first()
|
.first()
|
||||||
.map_or(false, |expr| !matches!(expr.node, StmtKind::If { .. }));
|
.map_or(false, |expr| !matches!(expr.node, StmtKind::If(_)));
|
||||||
|
|
||||||
self.parent_ifs.push(stmt);
|
self.parent_ifs.push(stmt);
|
||||||
if has_else {
|
if has_else {
|
||||||
|
@ -193,7 +193,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::Match { subject, cases } => {
|
StmtKind::Match(ast::StmtMatch { subject, cases }) => {
|
||||||
self.counter_stack.push(Vec::with_capacity(cases.len()));
|
self.counter_stack.push(Vec::with_capacity(cases.len()));
|
||||||
self.visit_expr(subject);
|
self.visit_expr(subject);
|
||||||
for match_case in cases {
|
for match_case in cases {
|
||||||
|
@ -207,14 +207,14 @@ where
|
||||||
self.increment_usage_count(max_count);
|
self.increment_usage_count(max_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::Assign { targets, value, .. } => {
|
StmtKind::Assign(ast::StmtAssign { targets, value, .. }) => {
|
||||||
if targets.iter().any(|target| self.name_matches(target)) {
|
if targets.iter().any(|target| self.name_matches(target)) {
|
||||||
self.overridden = true;
|
self.overridden = true;
|
||||||
} else {
|
} else {
|
||||||
self.visit_expr(value);
|
self.visit_expr(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::AnnAssign { target, value, .. } => {
|
StmtKind::AnnAssign(ast::StmtAnnAssign { target, value, .. }) => {
|
||||||
if self.name_matches(target) {
|
if self.name_matches(target) {
|
||||||
self.overridden = true;
|
self.overridden = true;
|
||||||
} else if let Some(expr) = value {
|
} else if let Some(expr) = value {
|
||||||
|
@ -241,7 +241,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &'a Expr) {
|
fn visit_expr(&mut self, expr: &'a Expr) {
|
||||||
if let ExprKind::NamedExpr { target, .. } = &expr.node {
|
if let ExprKind::NamedExpr(ast::ExprNamedExpr { target, .. }) = &expr.node {
|
||||||
if self.name_matches(target) {
|
if self.name_matches(target) {
|
||||||
self.overridden = true;
|
self.overridden = true;
|
||||||
}
|
}
|
||||||
|
@ -251,7 +251,8 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
ExprKind::ListComp { elt, generators } | ExprKind::SetComp { elt, generators } => {
|
ExprKind::ListComp(ast::ExprListComp { elt, generators })
|
||||||
|
| ExprKind::SetComp(ast::ExprSetComp { elt, generators }) => {
|
||||||
for comprehension in generators {
|
for comprehension in generators {
|
||||||
self.visit_comprehension(comprehension);
|
self.visit_comprehension(comprehension);
|
||||||
}
|
}
|
||||||
|
@ -261,11 +262,11 @@ where
|
||||||
self.nested = false;
|
self.nested = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::DictComp {
|
ExprKind::DictComp(ast::ExprDictComp {
|
||||||
key,
|
key,
|
||||||
value,
|
value,
|
||||||
generators,
|
generators,
|
||||||
} => {
|
}) => {
|
||||||
for comprehension in generators {
|
for comprehension in generators {
|
||||||
self.visit_comprehension(comprehension);
|
self.visit_comprehension(comprehension);
|
||||||
}
|
}
|
||||||
|
@ -307,10 +308,10 @@ pub fn reuse_of_groupby_generator(
|
||||||
body: &[Stmt],
|
body: &[Stmt],
|
||||||
iter: &Expr,
|
iter: &Expr,
|
||||||
) {
|
) {
|
||||||
let ExprKind::Call { func, .. } = &iter.node else {
|
let ExprKind::Call(ast::ExprCall { func, .. }) = &iter.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let ExprKind::Tuple { elts, .. } = &target.node else {
|
let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &target.node else {
|
||||||
// Ignore any `groupby()` invocation that isn't unpacked
|
// Ignore any `groupby()` invocation that isn't unpacked
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -318,7 +319,7 @@ pub fn reuse_of_groupby_generator(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// We have an invocation of groupby which is a simple unpacking
|
// We have an invocation of groupby which is a simple unpacking
|
||||||
let ExprKind::Name { id: group_name, .. } = &elts[1].node else {
|
let ExprKind::Name(ast::ExprName { id: group_name, .. }) = &elts[1].node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
// Check if the function call is `itertools.groupby`
|
// Check if the function call is `itertools.groupby`
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use ruff_text_size::TextSize;
|
use ruff_text_size::TextRange;
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -29,28 +29,26 @@ impl AlwaysAutofixableViolation for SetAttrWithConstant {
|
||||||
|
|
||||||
fn assignment(obj: &Expr, name: &str, value: &Expr, stylist: &Stylist) -> String {
|
fn assignment(obj: &Expr, name: &str, value: &Expr, stylist: &Stylist) -> String {
|
||||||
let stmt = Stmt::new(
|
let stmt = Stmt::new(
|
||||||
TextSize::default(),
|
TextRange::default(),
|
||||||
TextSize::default(),
|
StmtKind::Assign(ast::StmtAssign {
|
||||||
StmtKind::Assign {
|
|
||||||
targets: vec![Expr::new(
|
targets: vec![Expr::new(
|
||||||
TextSize::default(),
|
TextRange::default(),
|
||||||
TextSize::default(),
|
ExprKind::Attribute(ast::ExprAttribute {
|
||||||
ExprKind::Attribute {
|
|
||||||
value: Box::new(obj.clone()),
|
value: Box::new(obj.clone()),
|
||||||
attr: name.to_string(),
|
attr: name.into(),
|
||||||
ctx: ExprContext::Store,
|
ctx: ExprContext::Store,
|
||||||
},
|
}),
|
||||||
)],
|
)],
|
||||||
value: Box::new(value.clone()),
|
value: Box::new(value.clone()),
|
||||||
type_comment: None,
|
type_comment: None,
|
||||||
},
|
}),
|
||||||
);
|
);
|
||||||
unparse_stmt(&stmt, stylist)
|
unparse_stmt(&stmt, stylist)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// B010
|
/// B010
|
||||||
pub fn setattr_with_constant(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
|
pub fn setattr_with_constant(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
|
||||||
let ExprKind::Name { id, .. } = &func.node else {
|
let ExprKind::Name(ast::ExprName { id, .. }) = &func.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if id != "setattr" {
|
if id != "setattr" {
|
||||||
|
@ -59,10 +57,10 @@ pub fn setattr_with_constant(checker: &mut Checker, expr: &Expr, func: &Expr, ar
|
||||||
let [obj, name, value] = args else {
|
let [obj, name, value] = args else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let ExprKind::Constant {
|
let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(name),
|
value: Constant::Str(name),
|
||||||
..
|
..
|
||||||
} = &name.node else {
|
} )= &name.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if !is_identifier(name) {
|
if !is_identifier(name) {
|
||||||
|
@ -74,7 +72,7 @@ pub fn setattr_with_constant(checker: &mut Checker, expr: &Expr, func: &Expr, ar
|
||||||
// We can only replace a `setattr` call (which is an `Expr`) with an assignment
|
// We can only replace a `setattr` call (which is an `Expr`) with an assignment
|
||||||
// (which is a `Stmt`) if the `Expr` is already being used as a `Stmt`
|
// (which is a `Stmt`) if the `Expr` is already being used as a `Stmt`
|
||||||
// (i.e., it's directly within an `StmtKind::Expr`).
|
// (i.e., it's directly within an `StmtKind::Expr`).
|
||||||
if let StmtKind::Expr { value: child } = &checker.ctx.stmt().node {
|
if let StmtKind::Expr(ast::StmtExpr { value: child }) = &checker.ctx.stmt().node {
|
||||||
if expr == child.as_ref() {
|
if expr == child.as_ref() {
|
||||||
let mut diagnostic = Diagnostic::new(SetAttrWithConstant, expr.range());
|
let mut diagnostic = Diagnostic::new(SetAttrWithConstant, expr.range());
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ pub fn star_arg_unpacking_after_keyword_arg(
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
for arg in args {
|
for arg in args {
|
||||||
let ExprKind::Starred { .. } = arg.node else {
|
let ExprKind::Starred (_) = arg.node else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if arg.start() <= keyword.start() {
|
if arg.start() <= keyword.start() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -18,7 +18,7 @@ impl Violation for StripWithMultiCharacters {
|
||||||
|
|
||||||
/// B005
|
/// B005
|
||||||
pub fn strip_with_multi_characters(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
|
pub fn strip_with_multi_characters(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
|
||||||
let ExprKind::Attribute { attr, .. } = &func.node else {
|
let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &func.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if !matches!(attr.as_str(), "strip" | "lstrip" | "rstrip") {
|
if !matches!(attr.as_str(), "strip" | "lstrip" | "rstrip") {
|
||||||
|
@ -28,10 +28,10 @@ pub fn strip_with_multi_characters(checker: &mut Checker, expr: &Expr, func: &Ex
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ExprKind::Constant {
|
let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(value),
|
value: Constant::Str(value),
|
||||||
..
|
..
|
||||||
} = &args[0].node else {
|
} )= &args[0].node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
//! n += 1
|
//! n += 1
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use rustpython_parser::ast::{Expr, ExprKind, Unaryop};
|
use rustpython_parser::ast::{self, Expr, ExprKind, Unaryop};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -39,7 +39,7 @@ pub fn unary_prefix_increment(checker: &mut Checker, expr: &Expr, op: &Unaryop,
|
||||||
if !matches!(op, Unaryop::UAdd) {
|
if !matches!(op, Unaryop::UAdd) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let ExprKind::UnaryOp { op, .. } = &operand.node else {
|
let ExprKind::UnaryOp(ast::ExprUnaryOp { op, .. })= &operand.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if !matches!(op, Unaryop::UAdd) {
|
if !matches!(op, Unaryop::UAdd) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind, Stmt};
|
use rustpython_parser::ast::{self, Expr, ExprKind, Stmt};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -44,15 +44,15 @@ pub fn unintentional_type_annotation(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
match &target.node {
|
match &target.node {
|
||||||
ExprKind::Subscript { value, .. } => {
|
ExprKind::Subscript(ast::ExprSubscript { value, .. }) => {
|
||||||
if matches!(&value.node, ExprKind::Name { .. }) {
|
if matches!(&value.node, ExprKind::Name(_)) {
|
||||||
checker
|
checker
|
||||||
.diagnostics
|
.diagnostics
|
||||||
.push(Diagnostic::new(UnintentionalTypeAnnotation, stmt.range()));
|
.push(Diagnostic::new(UnintentionalTypeAnnotation, stmt.range()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Attribute { value, .. } => {
|
ExprKind::Attribute(ast::ExprAttribute { value, .. }) => {
|
||||||
if let ExprKind::Name { id, .. } = &value.node {
|
if let ExprKind::Name(ast::ExprName { id, .. }) = &value.node {
|
||||||
if id != "self" {
|
if id != "self" {
|
||||||
checker
|
checker
|
||||||
.diagnostics
|
.diagnostics
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -20,7 +20,7 @@ impl Violation for UnreliableCallableCheck {
|
||||||
|
|
||||||
/// B004
|
/// B004
|
||||||
pub fn unreliable_callable_check(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
|
pub fn unreliable_callable_check(checker: &mut Checker, expr: &Expr, func: &Expr, args: &[Expr]) {
|
||||||
let ExprKind::Name { id, .. } = &func.node else {
|
let ExprKind::Name(ast::ExprName { id, .. }) = &func.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if id != "getattr" && id != "hasattr" {
|
if id != "getattr" && id != "hasattr" {
|
||||||
|
@ -29,10 +29,10 @@ pub fn unreliable_callable_check(checker: &mut Checker, expr: &Expr, func: &Expr
|
||||||
if args.len() < 2 {
|
if args.len() < 2 {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let ExprKind::Constant {
|
let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(s),
|
value: Constant::Str(s),
|
||||||
..
|
..
|
||||||
} = &args[1].node else
|
}) = &args[1].node else
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use rustpython_parser::ast::{Expr, ExprKind, Stmt};
|
use rustpython_parser::ast::{self, Expr, ExprKind, Stmt};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
|
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
|
||||||
|
@ -93,7 +93,7 @@ where
|
||||||
'b: 'a,
|
'b: 'a,
|
||||||
{
|
{
|
||||||
fn visit_expr(&mut self, expr: &'a Expr) {
|
fn visit_expr(&mut self, expr: &'a Expr) {
|
||||||
if let ExprKind::Name { id, .. } = &expr.node {
|
if let ExprKind::Name(ast::ExprName { id, .. }) = &expr.node {
|
||||||
self.names.insert(id, expr);
|
self.names.insert(id, expr);
|
||||||
}
|
}
|
||||||
visitor::walk_expr(self, expr);
|
visitor::walk_expr(self, expr);
|
||||||
|
|
|
@ -20,7 +20,7 @@ impl Violation for UselessComparison {
|
||||||
|
|
||||||
/// B015
|
/// B015
|
||||||
pub fn useless_comparison(checker: &mut Checker, expr: &Expr) {
|
pub fn useless_comparison(checker: &mut Checker, expr: &Expr) {
|
||||||
if matches!(expr.node, ExprKind::Compare { .. }) {
|
if matches!(expr.node, ExprKind::Compare(_)) {
|
||||||
checker
|
checker
|
||||||
.diagnostics
|
.diagnostics
|
||||||
.push(Diagnostic::new(UselessComparison, expr.range()));
|
.push(Diagnostic::new(UselessComparison, expr.range()));
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -36,18 +36,18 @@ impl Violation for UselessExpression {
|
||||||
/// B018
|
/// B018
|
||||||
pub fn useless_expression(checker: &mut Checker, value: &Expr) {
|
pub fn useless_expression(checker: &mut Checker, value: &Expr) {
|
||||||
// Ignore comparisons, as they're handled by `useless_comparison`.
|
// Ignore comparisons, as they're handled by `useless_comparison`.
|
||||||
if matches!(value.node, ExprKind::Compare { .. }) {
|
if matches!(value.node, ExprKind::Compare(_)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore strings, to avoid false positives with docstrings.
|
// Ignore strings, to avoid false positives with docstrings.
|
||||||
if matches!(
|
if matches!(
|
||||||
value.node,
|
value.node,
|
||||||
ExprKind::JoinedStr { .. }
|
ExprKind::JoinedStr(_)
|
||||||
| ExprKind::Constant {
|
| ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(..) | Constant::Ellipsis,
|
value: Constant::Str(..) | Constant::Ellipsis,
|
||||||
..
|
..
|
||||||
}
|
})
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ pub fn useless_expression(checker: &mut Checker, value: &Expr) {
|
||||||
if contains_effect(value, |id| checker.ctx.is_builtin(id)) {
|
if contains_effect(value, |id| checker.ctx.is_builtin(id)) {
|
||||||
// Flag attributes as useless expressions, even if they're attached to calls or other
|
// Flag attributes as useless expressions, even if they're attached to calls or other
|
||||||
// expressions.
|
// expressions.
|
||||||
if matches!(value.node, ExprKind::Attribute { .. }) {
|
if matches!(value.node, ExprKind::Attribute(_)) {
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
UselessExpression {
|
UselessExpression {
|
||||||
kind: Kind::Attribute,
|
kind: Kind::Attribute,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
|
use rustpython_parser::ast::{self, Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
|
@ -21,7 +21,7 @@ pub fn zip_without_explicit_strict(
|
||||||
func: &Expr,
|
func: &Expr,
|
||||||
kwargs: &[Keyword],
|
kwargs: &[Keyword],
|
||||||
) {
|
) {
|
||||||
if let ExprKind::Name { id, .. } = &func.node {
|
if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node {
|
||||||
if id == "zip"
|
if id == "zip"
|
||||||
&& checker.ctx.is_builtin("zip")
|
&& checker.ctx.is_builtin("zip")
|
||||||
&& !kwargs.iter().any(|keyword| {
|
&& !kwargs.iter().any(|keyword| {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::Located;
|
use rustpython_parser::ast::Attributed;
|
||||||
|
|
||||||
use ruff_diagnostics::Violation;
|
use ruff_diagnostics::Violation;
|
||||||
use ruff_diagnostics::{Diagnostic, DiagnosticKind};
|
use ruff_diagnostics::{Diagnostic, DiagnosticKind};
|
||||||
|
@ -170,7 +170,7 @@ impl Violation for BuiltinAttributeShadowing {
|
||||||
/// Check builtin name shadowing.
|
/// Check builtin name shadowing.
|
||||||
pub fn builtin_shadowing<T>(
|
pub fn builtin_shadowing<T>(
|
||||||
name: &str,
|
name: &str,
|
||||||
located: &Located<T>,
|
located: &Attributed<T>,
|
||||||
node_type: ShadowingType,
|
node_type: ShadowingType,
|
||||||
ignorelist: &[String],
|
ignorelist: &[String],
|
||||||
) -> Option<Diagnostic> {
|
) -> Option<Diagnostic> {
|
||||||
|
|
|
@ -116,7 +116,7 @@ pub fn fix_unnecessary_generator_set(
|
||||||
// If the expression is embedded in an f-string, surround it with spaces to avoid
|
// If the expression is embedded in an f-string, surround it with spaces to avoid
|
||||||
// syntax errors.
|
// syntax errors.
|
||||||
if let Some(parent_element) = parent {
|
if let Some(parent_element) = parent {
|
||||||
if let &rustpython_parser::ast::ExprKind::FormattedValue { .. } = &parent_element.node {
|
if let &rustpython_parser::ast::ExprKind::FormattedValue(_) = &parent_element.node {
|
||||||
content = format!(" {content} ");
|
content = format!(" {content} ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,7 @@ pub fn fix_unnecessary_generator_dict(
|
||||||
// If the expression is embedded in an f-string, surround it with spaces to avoid
|
// If the expression is embedded in an f-string, surround it with spaces to avoid
|
||||||
// syntax errors.
|
// syntax errors.
|
||||||
if let Some(parent_element) = parent {
|
if let Some(parent_element) = parent {
|
||||||
if let &rustpython_parser::ast::ExprKind::FormattedValue { .. } = &parent_element.node {
|
if let &rustpython_parser::ast::ExprKind::FormattedValue(_) = &parent_element.node {
|
||||||
content = format!(" {content} ");
|
content = format!(" {content} ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1101,9 +1101,7 @@ pub fn fix_unnecessary_map(
|
||||||
// syntax errors.
|
// syntax errors.
|
||||||
if kind == "set" || kind == "dict" {
|
if kind == "set" || kind == "dict" {
|
||||||
if let Some(parent_element) = parent {
|
if let Some(parent_element) = parent {
|
||||||
if let &rustpython_parser::ast::ExprKind::FormattedValue { .. } =
|
if let &rustpython_parser::ast::ExprKind::FormattedValue(_) = &parent_element.node {
|
||||||
&parent_element.node
|
|
||||||
{
|
|
||||||
content = format!(" {content} ");
|
content = format!(" {content} ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
|
use rustpython_parser::ast::{self, Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
pub fn expr_name(func: &Expr) -> Option<&str> {
|
pub fn expr_name(func: &Expr) -> Option<&str> {
|
||||||
if let ExprKind::Name { id, .. } = &func.node {
|
if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node {
|
||||||
Some(id)
|
Some(id)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind};
|
use rustpython_parser::ast::{self, Expr, ExprKind};
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::AsRule;
|
use crate::registry::AsRule;
|
||||||
|
@ -65,7 +65,7 @@ pub fn unnecessary_call_around_sorted(
|
||||||
let Some(arg) = args.first() else {
|
let Some(arg) = args.first() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let ExprKind::Call { func, .. } = &arg.node else {
|
let ExprKind::Call(ast::ExprCall { func, .. }) = &arg.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(inner) = helpers::expr_name(func) else {
|
let Some(inner) = helpers::expr_name(func) else {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Comprehension, Expr, ExprKind};
|
use rustpython_parser::ast::{self, Comprehension, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -51,9 +51,9 @@ impl AlwaysAutofixableViolation for UnnecessaryComprehension {
|
||||||
/// Add diagnostic for C416 based on the expression node id.
|
/// Add diagnostic for C416 based on the expression node id.
|
||||||
fn add_diagnostic(checker: &mut Checker, expr: &Expr) {
|
fn add_diagnostic(checker: &mut Checker, expr: &Expr) {
|
||||||
let id = match &expr.node {
|
let id = match &expr.node {
|
||||||
ExprKind::ListComp { .. } => "list",
|
ExprKind::ListComp(_) => "list",
|
||||||
ExprKind::SetComp { .. } => "set",
|
ExprKind::SetComp(_) => "set",
|
||||||
ExprKind::DictComp { .. } => "dict",
|
ExprKind::DictComp(_) => "dict",
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
if !checker.ctx.is_builtin(id) {
|
if !checker.ctx.is_builtin(id) {
|
||||||
|
@ -86,7 +86,7 @@ pub fn unnecessary_dict_comprehension(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let generator = &generators[0];
|
let generator = &generators[0];
|
||||||
if !(generator.ifs.is_empty() && generator.is_async == 0) {
|
if !generator.ifs.is_empty() || generator.is_async {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let Some(key_id) = helpers::expr_name(key) else {
|
let Some(key_id) = helpers::expr_name(key) else {
|
||||||
|
@ -95,7 +95,7 @@ pub fn unnecessary_dict_comprehension(
|
||||||
let Some(value_id) = helpers::expr_name(value) else {
|
let Some(value_id) = helpers::expr_name(value) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let ExprKind::Tuple { elts, .. } = &generator.target.node else {
|
let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &generator.target.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if elts.len() != 2 {
|
if elts.len() != 2 {
|
||||||
|
@ -127,7 +127,7 @@ pub fn unnecessary_list_set_comprehension(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let generator = &generators[0];
|
let generator = &generators[0];
|
||||||
if !(generator.ifs.is_empty() && generator.is_async == 0) {
|
if !generator.ifs.is_empty() || generator.is_async {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let Some(elt_id) = helpers::expr_name(elt) else {
|
let Some(elt_id) = helpers::expr_name(elt) else {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
|
use rustpython_parser::ast::{self, Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
use ruff_diagnostics::Violation;
|
use ruff_diagnostics::Violation;
|
||||||
use ruff_diagnostics::{AutofixKind, Diagnostic};
|
use ruff_diagnostics::{AutofixKind, Diagnostic};
|
||||||
|
@ -66,11 +66,11 @@ pub fn unnecessary_comprehension_any_all(
|
||||||
if !keywords.is_empty() {
|
if !keywords.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let ExprKind::Name { id, .. } = &func.node else {
|
let ExprKind::Name(ast::ExprName { id, .. } )= &func.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if (matches!(id.as_str(), "all" | "any")) && args.len() == 1 {
|
if (matches!(id.as_str(), "all" | "any")) && args.len() == 1 {
|
||||||
let (ExprKind::ListComp { elt, .. } | ExprKind::SetComp { elt, .. }) = &args[0].node else {
|
let (ExprKind::ListComp(ast::ExprListComp { elt, .. } )| ExprKind::SetComp(ast::ExprSetComp { elt, .. })) = &args[0].node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if is_async_generator(elt) {
|
if is_async_generator(elt) {
|
||||||
|
@ -92,5 +92,5 @@ pub fn unnecessary_comprehension_any_all(
|
||||||
|
|
||||||
/// Return `true` if the `Expr` contains an `await` expression.
|
/// Return `true` if the `Expr` contains an `await` expression.
|
||||||
fn is_async_generator(expr: &Expr) -> bool {
|
fn is_async_generator(expr: &Expr) -> bool {
|
||||||
any_over_expr(expr, &|expr| matches!(expr.node, ExprKind::Await { .. }))
|
any_over_expr(expr, &|expr| matches!(expr.node, ExprKind::Await(_)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind};
|
use rustpython_parser::ast::{self, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -84,7 +84,7 @@ pub fn unnecessary_double_cast_or_process(
|
||||||
let Some(arg) = args.first() else {
|
let Some(arg) = args.first() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let ExprKind::Call { func, ..} = &arg.node else {
|
let ExprKind::Call(ast::ExprCall { func, ..} )= &arg.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let Some(inner) = helpers::expr_name(func) else {
|
let Some(inner) = helpers::expr_name(func) else {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
|
use rustpython_parser::ast::{self, Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -53,9 +53,9 @@ pub fn unnecessary_generator_dict(
|
||||||
let Some(argument) = helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords) else {
|
let Some(argument) = helpers::exactly_one_argument_with_matching_function("dict", func, args, keywords) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if let ExprKind::GeneratorExp { elt, .. } = argument {
|
if let ExprKind::GeneratorExp(ast::ExprGeneratorExp { elt, .. }) = argument {
|
||||||
match &elt.node {
|
match &elt.node {
|
||||||
ExprKind::Tuple { elts, .. } if elts.len() == 2 => {
|
ExprKind::Tuple(ast::ExprTuple { elts, .. }) if elts.len() == 2 => {
|
||||||
let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorDict, expr.range());
|
let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorDict, expr.range());
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
|
|
|
@ -55,7 +55,7 @@ pub fn unnecessary_generator_list(
|
||||||
if !checker.ctx.is_builtin("list") {
|
if !checker.ctx.is_builtin("list") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let ExprKind::GeneratorExp { .. } = argument {
|
if let ExprKind::GeneratorExp(_) = argument {
|
||||||
let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorList, expr.range());
|
let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorList, expr.range());
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
|
|
|
@ -56,7 +56,7 @@ pub fn unnecessary_generator_set(
|
||||||
if !checker.ctx.is_builtin("set") {
|
if !checker.ctx.is_builtin("set") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let ExprKind::GeneratorExp { .. } = argument {
|
if let ExprKind::GeneratorExp(_) = argument {
|
||||||
let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorSet, expr.range());
|
let mut diagnostic = Diagnostic::new(UnnecessaryGeneratorSet, expr.range());
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
|
|
|
@ -45,7 +45,7 @@ pub fn unnecessary_list_call(checker: &mut Checker, expr: &Expr, func: &Expr, ar
|
||||||
if !checker.ctx.is_builtin("list") {
|
if !checker.ctx.is_builtin("list") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if !matches!(argument, ExprKind::ListComp { .. }) {
|
if !matches!(argument, ExprKind::ListComp(_)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mut diagnostic = Diagnostic::new(UnnecessaryListCall, expr.range());
|
let mut diagnostic = Diagnostic::new(UnnecessaryListCall, expr.range());
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
|
use rustpython_parser::ast::{self, Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::AsRule;
|
use crate::registry::AsRule;
|
||||||
|
@ -52,10 +52,10 @@ pub fn unnecessary_list_comprehension_dict(
|
||||||
if !checker.ctx.is_builtin("dict") {
|
if !checker.ctx.is_builtin("dict") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let ExprKind::ListComp { elt, .. } = &argument else {
|
let ExprKind::ListComp(ast::ExprListComp { elt, .. }) = &argument else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let ExprKind::Tuple { elts, .. } = &elt.node else {
|
let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &elt.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if elts.len() != 2 {
|
if elts.len() != 2 {
|
||||||
|
|
|
@ -53,7 +53,7 @@ pub fn unnecessary_list_comprehension_set(
|
||||||
if !checker.ctx.is_builtin("set") {
|
if !checker.ctx.is_builtin("set") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let ExprKind::ListComp { .. } = &argument {
|
if let ExprKind::ListComp(_) = &argument {
|
||||||
let mut diagnostic = Diagnostic::new(UnnecessaryListComprehensionSet, expr.range());
|
let mut diagnostic = Diagnostic::new(UnnecessaryListComprehensionSet, expr.range());
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
|
use rustpython_parser::ast::{self, Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::AsRule;
|
use crate::registry::AsRule;
|
||||||
|
@ -60,15 +60,14 @@ pub fn unnecessary_literal_dict(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let (kind, elts) = match argument {
|
let (kind, elts) = match argument {
|
||||||
ExprKind::Tuple { elts, .. } => ("tuple", elts),
|
ExprKind::Tuple(ast::ExprTuple { elts, .. }) => ("tuple", elts),
|
||||||
ExprKind::List { elts, .. } => ("list", elts),
|
ExprKind::List(ast::ExprList { elts, .. }) => ("list", elts),
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
// Accept `dict((1, 2), ...))` `dict([(1, 2), ...])`.
|
// Accept `dict((1, 2), ...))` `dict([(1, 2), ...])`.
|
||||||
if !elts
|
if !elts.iter().all(
|
||||||
.iter()
|
|elt| matches!(&elt.node, ExprKind::Tuple(ast::ExprTuple { elts, .. } )if elts.len() == 2),
|
||||||
.all(|elt| matches!(&elt.node, ExprKind::Tuple { elts, .. } if elts.len() == 2))
|
) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mut diagnostic = Diagnostic::new(
|
let mut diagnostic = Diagnostic::new(
|
||||||
|
|
|
@ -61,8 +61,8 @@ pub fn unnecessary_literal_set(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let kind = match argument {
|
let kind = match argument {
|
||||||
ExprKind::List { .. } => "list",
|
ExprKind::List(_) => "list",
|
||||||
ExprKind::Tuple { .. } => "tuple",
|
ExprKind::Tuple(_) => "tuple",
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
let mut diagnostic = Diagnostic::new(
|
let mut diagnostic = Diagnostic::new(
|
||||||
|
|
|
@ -79,8 +79,8 @@ pub fn unnecessary_literal_within_dict_call(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let argument_kind = match argument {
|
let argument_kind = match argument {
|
||||||
ExprKind::DictComp { .. } => DictKind::Comprehension,
|
ExprKind::DictComp(_) => DictKind::Comprehension,
|
||||||
ExprKind::Dict { .. } => DictKind::Literal,
|
ExprKind::Dict(_) => DictKind::Literal,
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
let mut diagnostic = Diagnostic::new(
|
let mut diagnostic = Diagnostic::new(
|
||||||
|
|
|
@ -82,8 +82,8 @@ pub fn unnecessary_literal_within_list_call(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let argument_kind = match argument {
|
let argument_kind = match argument {
|
||||||
ExprKind::Tuple { .. } => "tuple",
|
ExprKind::Tuple(_) => "tuple",
|
||||||
ExprKind::List { .. } => "list",
|
ExprKind::List(_) => "list",
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
let mut diagnostic = Diagnostic::new(
|
let mut diagnostic = Diagnostic::new(
|
||||||
|
|
|
@ -83,8 +83,8 @@ pub fn unnecessary_literal_within_tuple_call(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let argument_kind = match argument {
|
let argument_kind = match argument {
|
||||||
ExprKind::Tuple { .. } => "tuple",
|
ExprKind::Tuple(_) => "tuple",
|
||||||
ExprKind::List { .. } => "list",
|
ExprKind::List(_) => "list",
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
let mut diagnostic = Diagnostic::new(
|
let mut diagnostic = Diagnostic::new(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use ruff_text_size::TextRange;
|
use ruff_text_size::TextRange;
|
||||||
use rustpython_parser::ast::{Expr, ExprKind};
|
use rustpython_parser::ast::{self, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::Diagnostic;
|
use ruff_diagnostics::Diagnostic;
|
||||||
use ruff_diagnostics::{AutofixKind, Violation};
|
use ruff_diagnostics::{AutofixKind, Violation};
|
||||||
|
@ -94,7 +94,7 @@ pub fn unnecessary_map(
|
||||||
|
|
||||||
// Exclude the parent if already matched by other arms
|
// Exclude the parent if already matched by other arms
|
||||||
if let Some(parent) = parent {
|
if let Some(parent) = parent {
|
||||||
if let ExprKind::Call { func: f, .. } = &parent.node {
|
if let ExprKind::Call(ast::ExprCall { func: f, .. }) = &parent.node {
|
||||||
if let Some(id_parent) = helpers::expr_name(f) {
|
if let Some(id_parent) = helpers::expr_name(f) {
|
||||||
if id_parent == "dict" || id_parent == "set" || id_parent == "list" {
|
if id_parent == "dict" || id_parent == "set" || id_parent == "list" {
|
||||||
return;
|
return;
|
||||||
|
@ -103,7 +103,7 @@ pub fn unnecessary_map(
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
if args.len() == 2 && matches!(&args[0].node, ExprKind::Lambda { .. }) {
|
if args.len() == 2 && matches!(&args[0].node, ExprKind::Lambda(_)) {
|
||||||
let mut diagnostic = create_diagnostic("generator", expr.range());
|
let mut diagnostic = create_diagnostic("generator", expr.range());
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
|
@ -126,14 +126,14 @@ pub fn unnecessary_map(
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(arg) = args.first() {
|
if let Some(arg) = args.first() {
|
||||||
if let ExprKind::Call { func, args, .. } = &arg.node {
|
if let ExprKind::Call(ast::ExprCall { func, args, .. }) = &arg.node {
|
||||||
if args.len() != 2 {
|
if args.len() != 2 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let Some(argument) = helpers::first_argument_with_matching_function("map", func, args) else {
|
let Some(argument) = helpers::first_argument_with_matching_function("map", func, args) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if let ExprKind::Lambda { .. } = argument {
|
if let ExprKind::Lambda(_) = argument {
|
||||||
let mut diagnostic = create_diagnostic(id, expr.range());
|
let mut diagnostic = create_diagnostic(id, expr.range());
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
|
@ -158,12 +158,12 @@ pub fn unnecessary_map(
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.len() == 1 {
|
if args.len() == 1 {
|
||||||
if let ExprKind::Call { func, args, .. } = &args[0].node {
|
if let ExprKind::Call(ast::ExprCall { func, args, .. }) = &args[0].node {
|
||||||
let Some(argument) = helpers::first_argument_with_matching_function("map", func, args) else {
|
let Some(argument) = helpers::first_argument_with_matching_function("map", func, args) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if let ExprKind::Lambda { body, .. } = &argument {
|
if let ExprKind::Lambda(ast::ExprLambda { body, .. }) = &argument {
|
||||||
if matches!(&body.node, ExprKind::Tuple { elts, .. } | ExprKind::List { elts, .. } if elts.len() == 2)
|
if matches!(&body.node, ExprKind::Tuple(ast::ExprTuple { elts, .. }) | ExprKind::List(ast::ExprList { elts, .. } )if elts.len() == 2)
|
||||||
{
|
{
|
||||||
let mut diagnostic = create_diagnostic(id, expr.range());
|
let mut diagnostic = create_diagnostic(id, expr.range());
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Unaryop};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Unaryop};
|
||||||
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
|
@ -60,10 +60,10 @@ pub fn unnecessary_subscript_reversal(
|
||||||
if !checker.ctx.is_builtin(id) {
|
if !checker.ctx.is_builtin(id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let ExprKind::Subscript { slice, .. } = &first_arg.node else {
|
let ExprKind::Subscript(ast::ExprSubscript { slice, .. }) = &first_arg.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let ExprKind::Slice { lower, upper, step } = &slice.node else {
|
let ExprKind::Slice(ast::ExprSlice { lower, upper, step }) = &slice.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if lower.is_some() || upper.is_some() {
|
if lower.is_some() || upper.is_some() {
|
||||||
|
@ -72,16 +72,16 @@ pub fn unnecessary_subscript_reversal(
|
||||||
let Some(step) = step.as_ref() else {
|
let Some(step) = step.as_ref() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let ExprKind::UnaryOp {
|
let ExprKind::UnaryOp(ast::ExprUnaryOp {
|
||||||
op: Unaryop::USub,
|
op: Unaryop::USub,
|
||||||
operand,
|
operand,
|
||||||
} = &step.node else {
|
}) = &step.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let ExprKind::Constant {
|
let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Int(val),
|
value: Constant::Int(val),
|
||||||
..
|
..
|
||||||
} = &operand.node else {
|
}) = &operand.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if *val != BigInt::from(1) {
|
if *val != BigInt::from(1) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use ruff_text_size::TextRange;
|
use ruff_text_size::TextRange;
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -317,10 +317,10 @@ pub fn call_datetime_strptime_without_zone(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does the `strptime` call contain a format string with a timezone specifier?
|
// Does the `strptime` call contain a format string with a timezone specifier?
|
||||||
if let Some(ExprKind::Constant {
|
if let Some(ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(format),
|
value: Constant::Str(format),
|
||||||
kind: None,
|
kind: None,
|
||||||
}) = args.get(1).as_ref().map(|arg| &arg.node)
|
})) = args.get(1).as_ref().map(|arg| &arg.node)
|
||||||
{
|
{
|
||||||
if format.contains("%z") {
|
if format.contains("%z") {
|
||||||
return;
|
return;
|
||||||
|
@ -335,8 +335,9 @@ pub fn call_datetime_strptime_without_zone(
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let ExprKind::Call { keywords, .. } = &grandparent.node {
|
if let ExprKind::Call(ast::ExprCall { keywords, .. }) = &grandparent.node {
|
||||||
if let ExprKind::Attribute { attr, .. } = &parent.node {
|
if let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &parent.node {
|
||||||
|
let attr = attr.as_str();
|
||||||
// Ex) `datetime.strptime(...).astimezone()`
|
// Ex) `datetime.strptime(...).astimezone()`
|
||||||
if attr == "astimezone" {
|
if attr == "astimezone" {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Stmt, StmtKind};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -52,24 +52,24 @@ pub fn all_with_model_form(checker: &Checker, bases: &[Expr], body: &[Stmt]) ->
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
for element in body.iter() {
|
for element in body.iter() {
|
||||||
let StmtKind::ClassDef { name, body, .. } = &element.node else {
|
let StmtKind::ClassDef(ast::StmtClassDef { name, body, .. }) = &element.node else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if name != "Meta" {
|
if name != "Meta" {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for element in body.iter() {
|
for element in body.iter() {
|
||||||
let StmtKind::Assign { targets, value, .. } = &element.node else {
|
let StmtKind::Assign(ast::StmtAssign { targets, value, .. }) = &element.node else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
for target in targets.iter() {
|
for target in targets.iter() {
|
||||||
let ExprKind::Name { id, .. } = &target.node else {
|
let ExprKind::Name(ast::ExprName { id, .. }) = &target.node else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if id != "fields" {
|
if id != "fields" {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let ExprKind::Constant { value, .. } = &value.node else {
|
let ExprKind::Constant(ast::ExprConstant { value, .. }) = &value.node else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
match &value {
|
match &value {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind, Stmt, StmtKind};
|
use rustpython_parser::ast::{self, Expr, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -54,18 +54,18 @@ pub fn exclude_with_model_form(
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
for element in body.iter() {
|
for element in body.iter() {
|
||||||
let StmtKind::ClassDef { name, body, .. } = &element.node else {
|
let StmtKind::ClassDef(ast::StmtClassDef { name, body, .. }) = &element.node else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if name != "Meta" {
|
if name != "Meta" {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for element in body.iter() {
|
for element in body.iter() {
|
||||||
let StmtKind::Assign { targets, .. } = &element.node else {
|
let StmtKind::Assign(ast::StmtAssign { targets, .. }) = &element.node else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
for target in targets.iter() {
|
for target in targets.iter() {
|
||||||
let ExprKind::Name { id, .. } = &target.node else {
|
let ExprKind::Name(ast::ExprName { id, .. }) = &target.node else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if id == "exclude" {
|
if id == "exclude" {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind, Keyword};
|
use rustpython_parser::ast::{self, Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -86,7 +86,7 @@ pub fn locals_in_render_function(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_locals_call(checker: &Checker, expr: &Expr) -> bool {
|
fn is_locals_call(checker: &Checker, expr: &Expr) -> bool {
|
||||||
let ExprKind::Call { func, .. } = &expr.node else {
|
let ExprKind::Call(ast::ExprCall { func, .. }) = &expr.node else {
|
||||||
return false
|
return false
|
||||||
};
|
};
|
||||||
checker
|
checker
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use rustpython_parser::ast::{Constant, Expr, StmtKind};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Stmt, StmtKind};
|
||||||
use rustpython_parser::ast::{ExprKind, Stmt};
|
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -70,7 +69,7 @@ pub fn model_without_dunder_str(
|
||||||
|
|
||||||
fn has_dunder_method(body: &[Stmt]) -> bool {
|
fn has_dunder_method(body: &[Stmt]) -> bool {
|
||||||
body.iter().any(|val| match &val.node {
|
body.iter().any(|val| match &val.node {
|
||||||
StmtKind::FunctionDef { name, .. } => {
|
StmtKind::FunctionDef(ast::StmtFunctionDef { name, .. }) => {
|
||||||
if name == "__str__" {
|
if name == "__str__" {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -95,24 +94,24 @@ fn checker_applies(checker: &Checker, bases: &[Expr], body: &[Stmt]) -> bool {
|
||||||
/// Check if class is abstract, in terms of Django model inheritance.
|
/// Check if class is abstract, in terms of Django model inheritance.
|
||||||
fn is_model_abstract(body: &[Stmt]) -> bool {
|
fn is_model_abstract(body: &[Stmt]) -> bool {
|
||||||
for element in body.iter() {
|
for element in body.iter() {
|
||||||
let StmtKind::ClassDef {name, body, ..} = &element.node else {
|
let StmtKind::ClassDef(ast::StmtClassDef {name, body, ..}) = &element.node else {
|
||||||
continue
|
continue
|
||||||
};
|
};
|
||||||
if name != "Meta" {
|
if name != "Meta" {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for element in body.iter() {
|
for element in body.iter() {
|
||||||
let StmtKind::Assign {targets, value, ..} = &element.node else {
|
let StmtKind::Assign(ast::StmtAssign {targets, value, ..}) = &element.node else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
for target in targets.iter() {
|
for target in targets.iter() {
|
||||||
let ExprKind::Name {id , ..} = &target.node else {
|
let ExprKind::Name(ast::ExprName {id , ..}) = &target.node else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if id != "abstract" {
|
if id != "abstract" {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let ExprKind::Constant{value: Constant::Bool(true), ..} = &value.node else {
|
let ExprKind::Constant(ast::ExprConstant{value: Constant::Bool(true), ..}) = &value.node else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind};
|
use rustpython_parser::ast::{self, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -59,9 +59,10 @@ where
|
||||||
let mut seen_receiver = false;
|
let mut seen_receiver = false;
|
||||||
for (i, decorator) in decorator_list.iter().enumerate() {
|
for (i, decorator) in decorator_list.iter().enumerate() {
|
||||||
let is_receiver = match &decorator.node {
|
let is_receiver = match &decorator.node {
|
||||||
ExprKind::Call { func, .. } => resolve_call_path(func).map_or(false, |call_path| {
|
ExprKind::Call(ast::ExprCall { func, .. }) => resolve_call_path(func)
|
||||||
call_path.as_slice() == ["django", "dispatch", "receiver"]
|
.map_or(false, |call_path| {
|
||||||
}),
|
call_path.as_slice() == ["django", "dispatch", "receiver"]
|
||||||
|
}),
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
if i > 0 && is_receiver && !seen_receiver {
|
if i > 0 && is_receiver && !seen_receiver {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use rustpython_parser::ast::Constant::Bool;
|
use rustpython_parser::ast::Constant::Bool;
|
||||||
use rustpython_parser::ast::{Expr, ExprKind, Stmt, StmtKind};
|
use rustpython_parser::ast::{self, Expr, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -64,7 +64,7 @@ const NOT_NULL_TRUE_FIELDS: [&str; 6] = [
|
||||||
pub fn nullable_model_string_field(checker: &Checker, body: &[Stmt]) -> Vec<Diagnostic> {
|
pub fn nullable_model_string_field(checker: &Checker, body: &[Stmt]) -> Vec<Diagnostic> {
|
||||||
let mut errors = Vec::new();
|
let mut errors = Vec::new();
|
||||||
for statement in body.iter() {
|
for statement in body.iter() {
|
||||||
let StmtKind::Assign {value, ..} = &statement.node else {
|
let StmtKind::Assign(ast::StmtAssign {value, ..}) = &statement.node else {
|
||||||
continue
|
continue
|
||||||
};
|
};
|
||||||
if let Some(field_name) = is_nullable_field(checker, value) {
|
if let Some(field_name) = is_nullable_field(checker, value) {
|
||||||
|
@ -80,7 +80,7 @@ pub fn nullable_model_string_field(checker: &Checker, body: &[Stmt]) -> Vec<Diag
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_nullable_field<'a>(checker: &'a Checker, value: &'a Expr) -> Option<&'a str> {
|
fn is_nullable_field<'a>(checker: &'a Checker, value: &'a Expr) -> Option<&'a str> {
|
||||||
let ExprKind::Call {func, keywords, ..} = &value.node else {
|
let ExprKind::Call(ast::ExprCall {func, keywords, ..}) = &value.node else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ fn is_nullable_field<'a>(checker: &'a Checker, value: &'a Expr) -> Option<&'a st
|
||||||
let mut blank_key = false;
|
let mut blank_key = false;
|
||||||
let mut unique_key = false;
|
let mut unique_key = false;
|
||||||
for keyword in keywords.iter() {
|
for keyword in keywords.iter() {
|
||||||
let ExprKind::Constant {value: Bool(true), ..} = &keyword.node.value.node else {
|
let ExprKind::Constant(ast::ExprConstant {value: Bool(true), ..}) = &keyword.node.value.node else {
|
||||||
continue
|
continue
|
||||||
};
|
};
|
||||||
let Some(argument) = &keyword.node.arg else {
|
let Some(argument) = &keyword.node.arg else {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use rustpython_parser::ast::{Expr, ExprKind, Stmt, StmtKind};
|
use rustpython_parser::ast::{self, Expr, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -101,8 +101,8 @@ impl fmt::Display for ContentType {
|
||||||
|
|
||||||
fn get_element_type(checker: &Checker, element: &StmtKind) -> Option<ContentType> {
|
fn get_element_type(checker: &Checker, element: &StmtKind) -> Option<ContentType> {
|
||||||
match element {
|
match element {
|
||||||
StmtKind::Assign { targets, value, .. } => {
|
StmtKind::Assign(ast::StmtAssign { targets, value, .. }) => {
|
||||||
if let ExprKind::Call { func, .. } = &value.node {
|
if let ExprKind::Call(ast::ExprCall { func, .. }) = &value.node {
|
||||||
if helpers::is_model_field(&checker.ctx, func) {
|
if helpers::is_model_field(&checker.ctx, func) {
|
||||||
return Some(ContentType::FieldDeclaration);
|
return Some(ContentType::FieldDeclaration);
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ fn get_element_type(checker: &Checker, element: &StmtKind) -> Option<ContentType
|
||||||
let Some(expr) = targets.first() else {
|
let Some(expr) = targets.first() else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let ExprKind::Name { id, .. } = &expr.node else {
|
let ExprKind::Name(ast::ExprName { id, .. }) = &expr.node else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
if id == "objects" {
|
if id == "objects" {
|
||||||
|
@ -119,14 +119,14 @@ fn get_element_type(checker: &Checker, element: &StmtKind) -> Option<ContentType
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::ClassDef { name, .. } => {
|
StmtKind::ClassDef(ast::StmtClassDef { name, .. }) => {
|
||||||
if name == "Meta" {
|
if name == "Meta" {
|
||||||
Some(ContentType::MetaClass)
|
Some(ContentType::MetaClass)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::FunctionDef { name, .. } => match name.as_str() {
|
StmtKind::FunctionDef(ast::StmtFunctionDef { name, .. }) => match name.as_str() {
|
||||||
"__str__" => Some(ContentType::StrMethod),
|
"__str__" => Some(ContentType::StrMethod),
|
||||||
"save" => Some(ContentType::SaveMethod),
|
"save" => Some(ContentType::SaveMethod),
|
||||||
"get_absolute_url" => Some(ContentType::GetAbsoluteUrlMethod),
|
"get_absolute_url" => Some(ContentType::GetAbsoluteUrlMethod),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprContext, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
|
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -184,14 +184,14 @@ impl Violation for DotFormatInException {
|
||||||
/// 2. Replace the exception argument with the variable name.
|
/// 2. Replace the exception argument with the variable name.
|
||||||
fn generate_fix(stylist: &Stylist, stmt: &Stmt, exc_arg: &Expr, indentation: &str) -> Fix {
|
fn generate_fix(stylist: &Stylist, stmt: &Stmt, exc_arg: &Expr, indentation: &str) -> Fix {
|
||||||
let assignment = unparse_stmt(
|
let assignment = unparse_stmt(
|
||||||
&create_stmt(StmtKind::Assign {
|
&create_stmt(StmtKind::Assign(ast::StmtAssign {
|
||||||
targets: vec![create_expr(ExprKind::Name {
|
targets: vec![create_expr(ExprKind::Name(ast::ExprName {
|
||||||
id: String::from("msg"),
|
id: "msg".into(),
|
||||||
ctx: ExprContext::Store,
|
ctx: ExprContext::Store,
|
||||||
})],
|
}))],
|
||||||
value: Box::new(exc_arg.clone()),
|
value: Box::new(exc_arg.clone()),
|
||||||
type_comment: None,
|
type_comment: None,
|
||||||
}),
|
})),
|
||||||
stylist,
|
stylist,
|
||||||
);
|
);
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
|
@ -214,14 +214,14 @@ fn generate_fix(stylist: &Stylist, stmt: &Stmt, exc_arg: &Expr, indentation: &st
|
||||||
|
|
||||||
/// EM101, EM102, EM103
|
/// EM101, EM102, EM103
|
||||||
pub fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr) {
|
pub fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr) {
|
||||||
if let ExprKind::Call { args, .. } = &exc.node {
|
if let ExprKind::Call(ast::ExprCall { args, .. }) = &exc.node {
|
||||||
if let Some(first) = args.first() {
|
if let Some(first) = args.first() {
|
||||||
match &first.node {
|
match &first.node {
|
||||||
// Check for string literals
|
// Check for string literals
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(string),
|
value: Constant::Str(string),
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
if checker.settings.rules.enabled(Rule::RawStringInException) {
|
if checker.settings.rules.enabled(Rule::RawStringInException) {
|
||||||
if string.len() > checker.settings.flake8_errmsg.max_string_length {
|
if string.len() > checker.settings.flake8_errmsg.max_string_length {
|
||||||
let indentation = whitespace::indentation(checker.locator, stmt)
|
let indentation = whitespace::indentation(checker.locator, stmt)
|
||||||
|
@ -249,7 +249,7 @@ pub fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check for f-strings
|
// Check for f-strings
|
||||||
ExprKind::JoinedStr { .. } => {
|
ExprKind::JoinedStr(_) => {
|
||||||
if checker.settings.rules.enabled(Rule::FStringInException) {
|
if checker.settings.rules.enabled(Rule::FStringInException) {
|
||||||
let indentation = whitespace::indentation(checker.locator, stmt).and_then(
|
let indentation = whitespace::indentation(checker.locator, stmt).and_then(
|
||||||
|indentation| {
|
|indentation| {
|
||||||
|
@ -275,10 +275,12 @@ pub fn string_in_exception(checker: &mut Checker, stmt: &Stmt, exc: &Expr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check for .format() calls
|
// Check for .format() calls
|
||||||
ExprKind::Call { func, .. } => {
|
ExprKind::Call(ast::ExprCall { func, .. }) => {
|
||||||
if checker.settings.rules.enabled(Rule::DotFormatInException) {
|
if checker.settings.rules.enabled(Rule::DotFormatInException) {
|
||||||
if let ExprKind::Attribute { value, attr, .. } = &func.node {
|
if let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) =
|
||||||
if attr == "format" && matches!(value.node, ExprKind::Constant { .. }) {
|
&func.node
|
||||||
|
{
|
||||||
|
if attr == "format" && matches!(value.node, ExprKind::Constant(_)) {
|
||||||
let indentation = whitespace::indentation(checker.locator, stmt)
|
let indentation = whitespace::indentation(checker.locator, stmt)
|
||||||
.and_then(|indentation| {
|
.and_then(|indentation| {
|
||||||
if checker.ctx.find_binding("msg").is_none() {
|
if checker.ctx.find_binding("msg").is_none() {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Operator};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Operator};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -34,8 +34,8 @@ impl Violation for PrintfInGetTextFuncCall {
|
||||||
|
|
||||||
/// Returns true if the [`Expr`] is an internationalization function call.
|
/// Returns true if the [`Expr`] is an internationalization function call.
|
||||||
pub fn is_gettext_func_call(func: &Expr, functions_names: &[String]) -> bool {
|
pub fn is_gettext_func_call(func: &Expr, functions_names: &[String]) -> bool {
|
||||||
if let ExprKind::Name { id, .. } = &func.node {
|
if let ExprKind::Name(ast::ExprName { id, .. }) = &func.node {
|
||||||
functions_names.contains(id)
|
functions_names.contains(id.as_ref())
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ pub fn is_gettext_func_call(func: &Expr, functions_names: &[String]) -> bool {
|
||||||
/// INT001
|
/// INT001
|
||||||
pub fn f_string_in_gettext_func_call(args: &[Expr]) -> Option<Diagnostic> {
|
pub fn f_string_in_gettext_func_call(args: &[Expr]) -> Option<Diagnostic> {
|
||||||
if let Some(first) = args.first() {
|
if let Some(first) = args.first() {
|
||||||
if matches!(first.node, ExprKind::JoinedStr { .. }) {
|
if matches!(first.node, ExprKind::JoinedStr(_)) {
|
||||||
return Some(Diagnostic::new(FStringInGetTextFuncCall {}, first.range()));
|
return Some(Diagnostic::new(FStringInGetTextFuncCall {}, first.range()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,8 +54,8 @@ pub fn f_string_in_gettext_func_call(args: &[Expr]) -> Option<Diagnostic> {
|
||||||
/// INT002
|
/// INT002
|
||||||
pub fn format_in_gettext_func_call(args: &[Expr]) -> Option<Diagnostic> {
|
pub fn format_in_gettext_func_call(args: &[Expr]) -> Option<Diagnostic> {
|
||||||
if let Some(first) = args.first() {
|
if let Some(first) = args.first() {
|
||||||
if let ExprKind::Call { func, .. } = &first.node {
|
if let ExprKind::Call(ast::ExprCall { func, .. }) = &first.node {
|
||||||
if let ExprKind::Attribute { attr, .. } = &func.node {
|
if let ExprKind::Attribute(ast::ExprAttribute { attr, .. }) = &func.node {
|
||||||
if attr == "format" {
|
if attr == "format" {
|
||||||
return Some(Diagnostic::new(FormatInGetTextFuncCall {}, first.range()));
|
return Some(Diagnostic::new(FormatInGetTextFuncCall {}, first.range()));
|
||||||
}
|
}
|
||||||
|
@ -68,16 +68,16 @@ pub fn format_in_gettext_func_call(args: &[Expr]) -> Option<Diagnostic> {
|
||||||
/// INT003
|
/// INT003
|
||||||
pub fn printf_in_gettext_func_call(args: &[Expr]) -> Option<Diagnostic> {
|
pub fn printf_in_gettext_func_call(args: &[Expr]) -> Option<Diagnostic> {
|
||||||
if let Some(first) = args.first() {
|
if let Some(first) = args.first() {
|
||||||
if let ExprKind::BinOp {
|
if let ExprKind::BinOp(ast::ExprBinOp {
|
||||||
op: Operator::Mod { .. },
|
op: Operator::Mod { .. },
|
||||||
left,
|
left,
|
||||||
..
|
..
|
||||||
} = &first.node
|
}) = &first.node
|
||||||
{
|
{
|
||||||
if let ExprKind::Constant {
|
if let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(_),
|
value: Constant::Str(_),
|
||||||
..
|
..
|
||||||
} = left.node
|
}) = left.node
|
||||||
{
|
{
|
||||||
return Some(Diagnostic::new(PrintfInGetTextFuncCall {}, first.range()));
|
return Some(Diagnostic::new(PrintfInGetTextFuncCall {}, first.range()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use ruff_text_size::TextRange;
|
use ruff_text_size::TextRange;
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Operator};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Operator};
|
||||||
use rustpython_parser::lexer::LexResult;
|
use rustpython_parser::lexer::LexResult;
|
||||||
use rustpython_parser::Tok;
|
use rustpython_parser::Tok;
|
||||||
|
|
||||||
|
@ -149,22 +149,22 @@ pub fn implicit(tokens: &[LexResult], settings: &Settings, locator: &Locator) ->
|
||||||
|
|
||||||
/// ISC003
|
/// ISC003
|
||||||
pub fn explicit(expr: &Expr) -> Option<Diagnostic> {
|
pub fn explicit(expr: &Expr) -> Option<Diagnostic> {
|
||||||
if let ExprKind::BinOp { left, op, right } = &expr.node {
|
if let ExprKind::BinOp(ast::ExprBinOp { left, op, right }) = &expr.node {
|
||||||
if matches!(op, Operator::Add) {
|
if matches!(op, Operator::Add) {
|
||||||
if matches!(
|
if matches!(
|
||||||
left.node,
|
left.node,
|
||||||
ExprKind::JoinedStr { .. }
|
ExprKind::JoinedStr(_)
|
||||||
| ExprKind::Constant {
|
| ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(..) | Constant::Bytes(..),
|
value: Constant::Str(..) | Constant::Bytes(..),
|
||||||
..
|
..
|
||||||
}
|
})
|
||||||
) && matches!(
|
) && matches!(
|
||||||
right.node,
|
right.node,
|
||||||
ExprKind::JoinedStr { .. }
|
ExprKind::JoinedStr(_)
|
||||||
| ExprKind::Constant {
|
| ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(..) | Constant::Bytes(..),
|
value: Constant::Str(..) | Constant::Bytes(..),
|
||||||
..
|
..
|
||||||
}
|
})
|
||||||
) {
|
) {
|
||||||
return Some(Diagnostic::new(ExplicitStringConcatenation, expr.range()));
|
return Some(Diagnostic::new(ExplicitStringConcatenation, expr.range()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use ruff_text_size::{TextRange, TextSize};
|
use ruff_text_size::{TextRange, TextSize};
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword, Operator};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword, Operator};
|
||||||
use std::ops::Add;
|
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Edit, Fix};
|
use ruff_diagnostics::{Diagnostic, Edit, Fix};
|
||||||
use ruff_python_ast::helpers::{find_keyword, SimpleCallArgs};
|
use ruff_python_ast::helpers::{find_keyword, SimpleCallArgs};
|
||||||
|
@ -43,7 +42,7 @@ const RESERVED_ATTRS: &[&str; 22] = &[
|
||||||
fn check_msg(checker: &mut Checker, msg: &Expr) {
|
fn check_msg(checker: &mut Checker, msg: &Expr) {
|
||||||
match &msg.node {
|
match &msg.node {
|
||||||
// Check for string concatenation and percent format.
|
// Check for string concatenation and percent format.
|
||||||
ExprKind::BinOp { op, .. } => match op {
|
ExprKind::BinOp(ast::ExprBinOp { op, .. }) => match op {
|
||||||
Operator::Add => {
|
Operator::Add => {
|
||||||
if checker.settings.rules.enabled(Rule::LoggingStringConcat) {
|
if checker.settings.rules.enabled(Rule::LoggingStringConcat) {
|
||||||
checker
|
checker
|
||||||
|
@ -61,7 +60,7 @@ fn check_msg(checker: &mut Checker, msg: &Expr) {
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
// Check for f-strings.
|
// Check for f-strings.
|
||||||
ExprKind::JoinedStr { .. } => {
|
ExprKind::JoinedStr(_) => {
|
||||||
if checker.settings.rules.enabled(Rule::LoggingFString) {
|
if checker.settings.rules.enabled(Rule::LoggingFString) {
|
||||||
checker
|
checker
|
||||||
.diagnostics
|
.diagnostics
|
||||||
|
@ -69,10 +68,10 @@ fn check_msg(checker: &mut Checker, msg: &Expr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check for .format() calls.
|
// Check for .format() calls.
|
||||||
ExprKind::Call { func, .. } => {
|
ExprKind::Call(ast::ExprCall { func, .. }) => {
|
||||||
if checker.settings.rules.enabled(Rule::LoggingStringFormat) {
|
if checker.settings.rules.enabled(Rule::LoggingStringFormat) {
|
||||||
if let ExprKind::Attribute { value, attr, .. } = &func.node {
|
if let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) = &func.node {
|
||||||
if attr == "format" && matches!(value.node, ExprKind::Constant { .. }) {
|
if attr == "format" && matches!(value.node, ExprKind::Constant(_)) {
|
||||||
checker
|
checker
|
||||||
.diagnostics
|
.diagnostics
|
||||||
.push(Diagnostic::new(LoggingStringFormat, msg.range()));
|
.push(Diagnostic::new(LoggingStringFormat, msg.range()));
|
||||||
|
@ -87,13 +86,13 @@ fn check_msg(checker: &mut Checker, msg: &Expr) {
|
||||||
/// Check contents of the `extra` argument to logging calls.
|
/// Check contents of the `extra` argument to logging calls.
|
||||||
fn check_log_record_attr_clash(checker: &mut Checker, extra: &Keyword) {
|
fn check_log_record_attr_clash(checker: &mut Checker, extra: &Keyword) {
|
||||||
match &extra.node.value.node {
|
match &extra.node.value.node {
|
||||||
ExprKind::Dict { keys, .. } => {
|
ExprKind::Dict(ast::ExprDict { keys, .. }) => {
|
||||||
for key in keys {
|
for key in keys {
|
||||||
if let Some(key) = &key {
|
if let Some(key) = &key {
|
||||||
if let ExprKind::Constant {
|
if let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(string),
|
value: Constant::Str(string),
|
||||||
..
|
..
|
||||||
} = &key.node
|
}) = &key.node
|
||||||
{
|
{
|
||||||
if RESERVED_ATTRS.contains(&string.as_str()) {
|
if RESERVED_ATTRS.contains(&string.as_str()) {
|
||||||
checker.diagnostics.push(Diagnostic::new(
|
checker.diagnostics.push(Diagnostic::new(
|
||||||
|
@ -105,7 +104,7 @@ fn check_log_record_attr_clash(checker: &mut Checker, extra: &Keyword) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Call { func, keywords, .. } => {
|
ExprKind::Call(ast::ExprCall { func, keywords, .. }) => {
|
||||||
if checker
|
if checker
|
||||||
.ctx
|
.ctx
|
||||||
.resolve_call_path(func)
|
.resolve_call_path(func)
|
||||||
|
@ -151,10 +150,10 @@ pub fn logging_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ExprKind::Attribute { value, attr, .. } = &func.node {
|
if let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. }) = &func.node {
|
||||||
if let Some(logging_call_type) = LoggingCallType::from_attribute(attr.as_str()) {
|
if let Some(logging_call_type) = LoggingCallType::from_attribute(attr.as_str()) {
|
||||||
let call_args = SimpleCallArgs::new(args, keywords);
|
let call_args = SimpleCallArgs::new(args, keywords);
|
||||||
let level_call_range = TextRange::new(value.end().add(TextSize::from(1)), func.end());
|
let level_call_range = TextRange::new(value.end() + TextSize::from(1), func.end());
|
||||||
|
|
||||||
// G001 - G004
|
// G001 - G004
|
||||||
let msg_pos = usize::from(matches!(logging_call_type, LoggingCallType::LogCall));
|
let msg_pos = usize::from(matches!(logging_call_type, LoggingCallType::LogCall));
|
||||||
|
@ -202,11 +201,13 @@ pub fn logging_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords:
|
||||||
// return.
|
// return.
|
||||||
if !(matches!(
|
if !(matches!(
|
||||||
exc_info.node.value.node,
|
exc_info.node.value.node,
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Bool(true),
|
value: Constant::Bool(true),
|
||||||
..
|
..
|
||||||
}
|
})
|
||||||
) || if let ExprKind::Call { func, .. } = &exc_info.node.value.node {
|
) || if let ExprKind::Call(ast::ExprCall { func, .. }) =
|
||||||
|
&exc_info.node.value.node
|
||||||
|
{
|
||||||
checker
|
checker
|
||||||
.ctx
|
.ctx
|
||||||
.resolve_call_path(func)
|
.resolve_call_path(func)
|
||||||
|
|
|
@ -5,7 +5,7 @@ use itertools::Either::{Left, Right};
|
||||||
use log::error;
|
use log::error;
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use rustpython_parser::ast::{
|
use rustpython_parser::ast::{
|
||||||
Boolop, Constant, Expr, ExprContext, ExprKind, Keyword, Stmt, StmtKind,
|
self, Boolop, Constant, Expr, ExprContext, ExprKind, Keyword, Stmt, StmtKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Violation};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Violation};
|
||||||
|
@ -301,15 +301,15 @@ pub fn no_unnecessary_pass(checker: &mut Checker, body: &[Stmt]) {
|
||||||
// redundant. Consider removing all `pass` statements instead.
|
// redundant. Consider removing all `pass` statements instead.
|
||||||
let docstring_stmt = &body[0];
|
let docstring_stmt = &body[0];
|
||||||
let pass_stmt = &body[1];
|
let pass_stmt = &body[1];
|
||||||
let StmtKind::Expr { value } = &docstring_stmt.node else {
|
let StmtKind::Expr(ast::StmtExpr { value } )= &docstring_stmt.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if matches!(
|
if matches!(
|
||||||
value.node,
|
value.node,
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(..),
|
value: Constant::Str(..),
|
||||||
..
|
..
|
||||||
}
|
})
|
||||||
) {
|
) {
|
||||||
if matches!(pass_stmt.node, StmtKind::Pass) {
|
if matches!(pass_stmt.node, StmtKind::Pass) {
|
||||||
let mut diagnostic = Diagnostic::new(UnnecessaryPass, pass_stmt.range());
|
let mut diagnostic = Diagnostic::new(UnnecessaryPass, pass_stmt.range());
|
||||||
|
@ -351,18 +351,18 @@ pub fn duplicate_class_field_definition<'a, 'b>(
|
||||||
for stmt in body {
|
for stmt in body {
|
||||||
// Extract the property name from the assignment statement.
|
// Extract the property name from the assignment statement.
|
||||||
let target = match &stmt.node {
|
let target = match &stmt.node {
|
||||||
StmtKind::Assign { targets, .. } => {
|
StmtKind::Assign(ast::StmtAssign { targets, .. }) => {
|
||||||
if targets.len() != 1 {
|
if targets.len() != 1 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let ExprKind::Name { id, .. } = &targets[0].node {
|
if let ExprKind::Name(ast::ExprName { id, .. }) = &targets[0].node {
|
||||||
id
|
id
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::AnnAssign { target, .. } => {
|
StmtKind::AnnAssign(ast::StmtAnnAssign { target, .. }) => {
|
||||||
if let ExprKind::Name { id, .. } = &target.node {
|
if let ExprKind::Name(ast::ExprName { id, .. }) = &target.node {
|
||||||
id
|
id
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
|
@ -407,7 +407,7 @@ pub fn non_unique_enums<'a, 'b>(checker: &mut Checker<'a>, parent: &'b Stmt, bod
|
||||||
where
|
where
|
||||||
'b: 'a,
|
'b: 'a,
|
||||||
{
|
{
|
||||||
let StmtKind::ClassDef { bases, .. } = &parent.node else {
|
let StmtKind::ClassDef(ast::StmtClassDef { bases, .. }) = &parent.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -422,11 +422,11 @@ where
|
||||||
|
|
||||||
let mut seen_targets: FxHashSet<ComparableExpr> = FxHashSet::default();
|
let mut seen_targets: FxHashSet<ComparableExpr> = FxHashSet::default();
|
||||||
for stmt in body {
|
for stmt in body {
|
||||||
let StmtKind::Assign { value, .. } = &stmt.node else {
|
let StmtKind::Assign(ast::StmtAssign { value, .. }) = &stmt.node else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let ExprKind::Call { func, .. } = &value.node {
|
if let ExprKind::Call(ast::ExprCall { func, .. }) = &value.node {
|
||||||
if checker
|
if checker
|
||||||
.ctx
|
.ctx
|
||||||
.resolve_call_path(func)
|
.resolve_call_path(func)
|
||||||
|
@ -454,7 +454,7 @@ pub fn unnecessary_spread(checker: &mut Checker, keys: &[Option<Expr>], values:
|
||||||
if let (None, value) = item {
|
if let (None, value) = item {
|
||||||
// We only care about when the key is None which indicates a spread `**`
|
// We only care about when the key is None which indicates a spread `**`
|
||||||
// inside a dict.
|
// inside a dict.
|
||||||
if let ExprKind::Dict { .. } = value.node {
|
if let ExprKind::Dict(_) = value.node {
|
||||||
let diagnostic = Diagnostic::new(UnnecessarySpread, value.range());
|
let diagnostic = Diagnostic::new(UnnecessarySpread, value.range());
|
||||||
checker.diagnostics.push(diagnostic);
|
checker.diagnostics.push(diagnostic);
|
||||||
}
|
}
|
||||||
|
@ -464,10 +464,10 @@ pub fn unnecessary_spread(checker: &mut Checker, keys: &[Option<Expr>], values:
|
||||||
|
|
||||||
/// Return `true` if a key is a valid keyword argument name.
|
/// Return `true` if a key is a valid keyword argument name.
|
||||||
fn is_valid_kwarg_name(key: &Expr) -> bool {
|
fn is_valid_kwarg_name(key: &Expr) -> bool {
|
||||||
if let ExprKind::Constant {
|
if let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(value),
|
value: Constant::Str(value),
|
||||||
..
|
..
|
||||||
} = &key.node
|
}) = &key.node
|
||||||
{
|
{
|
||||||
is_identifier(value)
|
is_identifier(value)
|
||||||
} else {
|
} else {
|
||||||
|
@ -480,7 +480,7 @@ pub fn unnecessary_dict_kwargs(checker: &mut Checker, expr: &Expr, kwargs: &[Key
|
||||||
for kw in kwargs {
|
for kw in kwargs {
|
||||||
// keyword is a spread operator (indicated by None)
|
// keyword is a spread operator (indicated by None)
|
||||||
if kw.node.arg.is_none() {
|
if kw.node.arg.is_none() {
|
||||||
if let ExprKind::Dict { keys, .. } = &kw.node.value.node {
|
if let ExprKind::Dict(ast::ExprDict { keys, .. }) = &kw.node.value.node {
|
||||||
// ensure foo(**{"bar-bar": 1}) doesn't error
|
// ensure foo(**{"bar-bar": 1}) doesn't error
|
||||||
if keys.iter().all(|expr| expr.as_ref().map_or(false, is_valid_kwarg_name)) ||
|
if keys.iter().all(|expr| expr.as_ref().map_or(false, is_valid_kwarg_name)) ||
|
||||||
// handle case of foo(**{**bar})
|
// handle case of foo(**{**bar})
|
||||||
|
@ -496,18 +496,17 @@ pub fn unnecessary_dict_kwargs(checker: &mut Checker, expr: &Expr, kwargs: &[Key
|
||||||
|
|
||||||
/// PIE810
|
/// PIE810
|
||||||
pub fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
|
pub fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
|
||||||
let ExprKind::BoolOp { op: Boolop::Or, values } = &expr.node else {
|
let ExprKind::BoolOp(ast::ExprBoolOp { op: Boolop::Or, values }) = &expr.node else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut duplicates = BTreeMap::new();
|
let mut duplicates = BTreeMap::new();
|
||||||
for (index, call) in values.iter().enumerate() {
|
for (index, call) in values.iter().enumerate() {
|
||||||
let ExprKind::Call {
|
let ExprKind::Call(ast::ExprCall {
|
||||||
func,
|
func,
|
||||||
args,
|
args,
|
||||||
keywords,
|
keywords,
|
||||||
..
|
}) = &call.node else {
|
||||||
} = &call.node else {
|
|
||||||
continue
|
continue
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -515,15 +514,14 @@ pub fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ExprKind::Attribute { value, attr, .. } = &func.node else {
|
let ExprKind::Attribute(ast::ExprAttribute { value, attr, .. } )= &func.node else {
|
||||||
continue
|
continue
|
||||||
};
|
};
|
||||||
|
|
||||||
if attr != "startswith" && attr != "endswith" {
|
if attr != "startswith" && attr != "endswith" {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ExprKind::Name { id: arg_name, .. } = &value.node else {
|
let ExprKind::Name(ast::ExprName { id: arg_name, .. } )= &value.node else {
|
||||||
continue
|
continue
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -547,7 +545,7 @@ pub fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|index| &values[*index])
|
.map(|index| &values[*index])
|
||||||
.map(|expr| {
|
.map(|expr| {
|
||||||
let ExprKind::Call { func: _, args, keywords: _} = &expr.node else {
|
let ExprKind::Call(ast::ExprCall { func: _, args, keywords: _}) = &expr.node else {
|
||||||
unreachable!("{}", format!("Indices should only contain `{attr_name}` calls"))
|
unreachable!("{}", format!("Indices should only contain `{attr_name}` calls"))
|
||||||
};
|
};
|
||||||
args.get(0)
|
args.get(0)
|
||||||
|
@ -555,20 +553,20 @@ pub fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let call = create_expr(ExprKind::Call {
|
let call = create_expr(ExprKind::Call(ast::ExprCall {
|
||||||
func: Box::new(create_expr(ExprKind::Attribute {
|
func: Box::new(create_expr(ExprKind::Attribute(ast::ExprAttribute {
|
||||||
value: Box::new(create_expr(ExprKind::Name {
|
value: Box::new(create_expr(ExprKind::Name(ast::ExprName {
|
||||||
id: arg_name.to_string(),
|
id: arg_name.into(),
|
||||||
ctx: ExprContext::Load,
|
ctx: ExprContext::Load,
|
||||||
})),
|
}))),
|
||||||
attr: attr_name.to_string(),
|
attr: attr_name.into(),
|
||||||
ctx: ExprContext::Load,
|
ctx: ExprContext::Load,
|
||||||
})),
|
}))),
|
||||||
args: vec![create_expr(ExprKind::Tuple {
|
args: vec![create_expr(ExprKind::Tuple(ast::ExprTuple {
|
||||||
elts: words
|
elts: words
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|value| {
|
.flat_map(|value| {
|
||||||
if let ExprKind::Tuple { elts, .. } = &value.node {
|
if let ExprKind::Tuple(ast::ExprTuple { elts, .. }) = &value.node {
|
||||||
Left(elts.iter())
|
Left(elts.iter())
|
||||||
} else {
|
} else {
|
||||||
Right(iter::once(*value))
|
Right(iter::once(*value))
|
||||||
|
@ -577,13 +575,13 @@ pub fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
|
||||||
.map(Clone::clone)
|
.map(Clone::clone)
|
||||||
.collect(),
|
.collect(),
|
||||||
ctx: ExprContext::Load,
|
ctx: ExprContext::Load,
|
||||||
})],
|
}))],
|
||||||
keywords: vec![],
|
keywords: vec![],
|
||||||
});
|
}));
|
||||||
|
|
||||||
// Generate the combined `BoolOp`.
|
// Generate the combined `BoolOp`.
|
||||||
let mut call = Some(call);
|
let mut call = Some(call);
|
||||||
let bool_op = create_expr(ExprKind::BoolOp {
|
let bool_op = create_expr(ExprKind::BoolOp(ast::ExprBoolOp {
|
||||||
op: Boolop::Or,
|
op: Boolop::Or,
|
||||||
values: values
|
values: values
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -596,7 +594,7 @@ pub fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
});
|
}));
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
diagnostic.set_fix(Fix::unspecified(Edit::range_replacement(
|
diagnostic.set_fix(Fix::unspecified(Edit::range_replacement(
|
||||||
unparse_expr(&bool_op, checker.stylist),
|
unparse_expr(&bool_op, checker.stylist),
|
||||||
|
@ -610,7 +608,7 @@ pub fn multiple_starts_ends_with(checker: &mut Checker, expr: &Expr) {
|
||||||
|
|
||||||
/// PIE807
|
/// PIE807
|
||||||
pub fn reimplemented_list_builtin(checker: &mut Checker, expr: &Expr) {
|
pub fn reimplemented_list_builtin(checker: &mut Checker, expr: &Expr) {
|
||||||
let ExprKind::Lambda { args, body } = &expr.node else {
|
let ExprKind::Lambda(ast::ExprLambda { args, body }) = &expr.node else {
|
||||||
panic!("Expected ExprKind::Lambda");
|
panic!("Expected ExprKind::Lambda");
|
||||||
};
|
};
|
||||||
if args.args.is_empty()
|
if args.args.is_empty()
|
||||||
|
@ -619,7 +617,7 @@ pub fn reimplemented_list_builtin(checker: &mut Checker, expr: &Expr) {
|
||||||
&& args.vararg.is_none()
|
&& args.vararg.is_none()
|
||||||
&& args.kwarg.is_none()
|
&& args.kwarg.is_none()
|
||||||
{
|
{
|
||||||
if let ExprKind::List { elts, .. } = &body.node {
|
if let ExprKind::List(ast::ExprList { elts, .. }) = &body.node {
|
||||||
if elts.is_empty() {
|
if elts.is_empty() {
|
||||||
let mut diagnostic = Diagnostic::new(ReimplementedListBuiltin, expr.range());
|
let mut diagnostic = Diagnostic::new(ReimplementedListBuiltin, expr.range());
|
||||||
if checker.patch(diagnostic.kind.rule()) {
|
if checker.patch(diagnostic.kind.rule()) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashSet;
|
||||||
use rustpython_parser::ast::{Expr, ExprKind, Operator};
|
use rustpython_parser::ast::{self, Expr, ExprKind, Operator};
|
||||||
|
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -45,11 +45,11 @@ fn traverse_union<'a>(
|
||||||
//
|
//
|
||||||
// So we have to traverse both branches in order (left, then right), to report duplicates
|
// So we have to traverse both branches in order (left, then right), to report duplicates
|
||||||
// in the order they appear in the source code.
|
// in the order they appear in the source code.
|
||||||
if let ExprKind::BinOp {
|
if let ExprKind::BinOp(ast::ExprBinOp {
|
||||||
op: Operator::BitOr,
|
op: Operator::BitOr,
|
||||||
left,
|
left,
|
||||||
right,
|
right,
|
||||||
} = &expr.node
|
}) = &expr.node
|
||||||
{
|
{
|
||||||
// Traverse left subtree, then the right subtree, propagating the previous node.
|
// Traverse left subtree, then the right subtree, propagating the previous node.
|
||||||
traverse_union(seen_nodes, checker, left, Some(expr));
|
traverse_union(seen_nodes, checker, left, Some(expr));
|
||||||
|
@ -72,7 +72,7 @@ fn traverse_union<'a>(
|
||||||
let parent = parent.expect("Parent node must exist");
|
let parent = parent.expect("Parent node must exist");
|
||||||
|
|
||||||
// SAFETY: Parent node must have been a `BinOp` in order for us to have traversed it.
|
// SAFETY: Parent node must have been a `BinOp` in order for us to have traversed it.
|
||||||
let ExprKind::BinOp { left, right, .. } = &parent.node else {
|
let ExprKind::BinOp(ast::ExprBinOp { left, right, .. }) = &parent.node else {
|
||||||
panic!("Parent node must be a BinOp");
|
panic!("Parent node must be a BinOp");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Constant, ExprKind, Stmt, StmtKind};
|
use rustpython_parser::ast::{self, Constant, ExprKind, Stmt, StmtKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -20,8 +20,8 @@ pub fn non_empty_stub_body(checker: &mut Checker, body: &[Stmt]) {
|
||||||
if body.len() != 1 {
|
if body.len() != 1 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let StmtKind::Expr { value } = &body[0].node {
|
if let StmtKind::Expr(ast::StmtExpr { value }) = &body[0].node {
|
||||||
if let ExprKind::Constant { value, .. } = &value.node {
|
if let ExprKind::Constant(ast::ExprConstant { value, .. }) = &value.node {
|
||||||
if matches!(value, Constant::Ellipsis | Constant::Str(_)) {
|
if matches!(value, Constant::Ellipsis | Constant::Str(_)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use rustpython_parser::ast::{Expr, ExprKind};
|
use rustpython_parser::ast::{self, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -63,13 +63,13 @@ pub fn prefix_type_params(checker: &mut Checker, value: &Expr, targets: &[Expr])
|
||||||
if targets.len() != 1 {
|
if targets.len() != 1 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let ExprKind::Name { id, .. } = &targets[0].node {
|
if let ExprKind::Name(ast::ExprName { id, .. }) = &targets[0].node {
|
||||||
if id.starts_with('_') {
|
if id.starts_with('_') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let ExprKind::Call { func, .. } = &value.node {
|
if let ExprKind::Call(ast::ExprCall { func, .. }) = &value.node {
|
||||||
let Some(kind) = checker.ctx.resolve_call_path(func).and_then(|call_path| {
|
let Some(kind) = checker.ctx.resolve_call_path(func).and_then(|call_path| {
|
||||||
if checker.ctx.match_typing_call_path(&call_path, "ParamSpec") {
|
if checker.ctx.match_typing_call_path(&call_path, "ParamSpec") {
|
||||||
Some(VarKind::ParamSpec)
|
Some(VarKind::ParamSpec)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Arguments, Constant, Expr, ExprKind, Operator, Unaryop};
|
use rustpython_parser::ast::{self, Arguments, Constant, Expr, ExprKind, Operator, Unaryop};
|
||||||
|
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -80,14 +80,16 @@ fn is_valid_default_value_with_annotation(
|
||||||
allow_container: bool,
|
allow_container: bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
match &default.node {
|
match &default.node {
|
||||||
ExprKind::List { elts, .. } | ExprKind::Tuple { elts, .. } | ExprKind::Set { elts, .. } => {
|
ExprKind::List(ast::ExprList { elts, .. })
|
||||||
|
| ExprKind::Tuple(ast::ExprTuple { elts, .. })
|
||||||
|
| ExprKind::Set(ast::ExprSet { elts }) => {
|
||||||
return allow_container
|
return allow_container
|
||||||
&& elts.len() <= 10
|
&& elts.len() <= 10
|
||||||
&& elts
|
&& elts
|
||||||
.iter()
|
.iter()
|
||||||
.all(|e| is_valid_default_value_with_annotation(e, checker, false));
|
.all(|e| is_valid_default_value_with_annotation(e, checker, false));
|
||||||
}
|
}
|
||||||
ExprKind::Dict { keys, values, .. } => {
|
ExprKind::Dict(ast::ExprDict { keys, values }) => {
|
||||||
return allow_container
|
return allow_container
|
||||||
&& keys.len() <= 10
|
&& keys.len() <= 10
|
||||||
&& keys.iter().zip(values).all(|(k, v)| {
|
&& keys.iter().zip(values).all(|(k, v)| {
|
||||||
|
@ -96,60 +98,60 @@ fn is_valid_default_value_with_annotation(
|
||||||
}) && is_valid_default_value_with_annotation(v, checker, false)
|
}) && is_valid_default_value_with_annotation(v, checker, false)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Ellipsis | Constant::None,
|
value: Constant::Ellipsis | Constant::None,
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(..),
|
value: Constant::Str(..),
|
||||||
..
|
..
|
||||||
} => return checker.locator.slice(default.range()).len() <= 50,
|
}) => return checker.locator.slice(default.range()).len() <= 50,
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Bytes(..),
|
value: Constant::Bytes(..),
|
||||||
..
|
..
|
||||||
} => return checker.locator.slice(default.range()).len() <= 50,
|
}) => return checker.locator.slice(default.range()).len() <= 50,
|
||||||
// Ex) `123`, `True`, `False`, `3.14`
|
// Ex) `123`, `True`, `False`, `3.14`
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Int(..) | Constant::Bool(..) | Constant::Float(..),
|
value: Constant::Int(..) | Constant::Bool(..) | Constant::Float(..),
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
return checker.locator.slice(default.range()).len() <= 10;
|
return checker.locator.slice(default.range()).len() <= 10;
|
||||||
}
|
}
|
||||||
// Ex) `2j`
|
// Ex) `2j`
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Complex { real, .. },
|
value: Constant::Complex { real, .. },
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
if *real == 0.0 {
|
if *real == 0.0 {
|
||||||
return checker.locator.slice(default.range()).len() <= 10;
|
return checker.locator.slice(default.range()).len() <= 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::UnaryOp {
|
ExprKind::UnaryOp(ast::ExprUnaryOp {
|
||||||
op: Unaryop::USub,
|
op: Unaryop::USub,
|
||||||
operand,
|
operand,
|
||||||
} => {
|
}) => {
|
||||||
// Ex) `-1`, `-3.14`
|
// Ex) `-1`, `-3.14`
|
||||||
if let ExprKind::Constant {
|
if let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Int(..) | Constant::Float(..),
|
value: Constant::Int(..) | Constant::Float(..),
|
||||||
..
|
..
|
||||||
} = &operand.node
|
}) = &operand.node
|
||||||
{
|
{
|
||||||
return checker.locator.slice(operand.range()).len() <= 10;
|
return checker.locator.slice(operand.range()).len() <= 10;
|
||||||
}
|
}
|
||||||
// Ex) `-2j`
|
// Ex) `-2j`
|
||||||
if let ExprKind::Constant {
|
if let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Complex { real, .. },
|
value: Constant::Complex { real, .. },
|
||||||
..
|
..
|
||||||
} = &operand.node
|
}) = &operand.node
|
||||||
{
|
{
|
||||||
if *real == 0.0 {
|
if *real == 0.0 {
|
||||||
return checker.locator.slice(operand.range()).len() <= 10;
|
return checker.locator.slice(operand.range()).len() <= 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Ex) `-math.inf`, `-math.pi`, etc.
|
// Ex) `-math.inf`, `-math.pi`, etc.
|
||||||
if let ExprKind::Attribute { .. } = &operand.node {
|
if let ExprKind::Attribute(_) = &operand.node {
|
||||||
if checker
|
if checker
|
||||||
.ctx
|
.ctx
|
||||||
.resolve_call_path(operand)
|
.resolve_call_path(operand)
|
||||||
|
@ -164,34 +166,34 @@ fn is_valid_default_value_with_annotation(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::BinOp {
|
ExprKind::BinOp(ast::ExprBinOp {
|
||||||
left,
|
left,
|
||||||
op: Operator::Add | Operator::Sub,
|
op: Operator::Add | Operator::Sub,
|
||||||
right,
|
right,
|
||||||
} => {
|
}) => {
|
||||||
// Ex) `1 + 2j`, `1 - 2j`, `-1 - 2j`, `-1 + 2j`
|
// Ex) `1 + 2j`, `1 - 2j`, `-1 - 2j`, `-1 + 2j`
|
||||||
if let ExprKind::Constant {
|
if let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Complex { .. },
|
value: Constant::Complex { .. },
|
||||||
..
|
..
|
||||||
} = right.node
|
}) = right.node
|
||||||
{
|
{
|
||||||
// Ex) `1 + 2j`, `1 - 2j`
|
// Ex) `1 + 2j`, `1 - 2j`
|
||||||
if let ExprKind::Constant {
|
if let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Int(..) | Constant::Float(..),
|
value: Constant::Int(..) | Constant::Float(..),
|
||||||
..
|
..
|
||||||
} = &left.node
|
}) = &left.node
|
||||||
{
|
{
|
||||||
return checker.locator.slice(left.range()).len() <= 10;
|
return checker.locator.slice(left.range()).len() <= 10;
|
||||||
} else if let ExprKind::UnaryOp {
|
} else if let ExprKind::UnaryOp(ast::ExprUnaryOp {
|
||||||
op: Unaryop::USub,
|
op: Unaryop::USub,
|
||||||
operand,
|
operand,
|
||||||
} = &left.node
|
}) = &left.node
|
||||||
{
|
{
|
||||||
// Ex) `-1 + 2j`, `-1 - 2j`
|
// Ex) `-1 + 2j`, `-1 - 2j`
|
||||||
if let ExprKind::Constant {
|
if let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Int(..) | Constant::Float(..),
|
value: Constant::Int(..) | Constant::Float(..),
|
||||||
..
|
..
|
||||||
} = &operand.node
|
}) = &operand.node
|
||||||
{
|
{
|
||||||
return checker.locator.slice(operand.range()).len() <= 10;
|
return checker.locator.slice(operand.range()).len() <= 10;
|
||||||
}
|
}
|
||||||
|
@ -199,7 +201,7 @@ fn is_valid_default_value_with_annotation(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Ex) `math.inf`, `sys.stdin`, etc.
|
// Ex) `math.inf`, `sys.stdin`, etc.
|
||||||
ExprKind::Attribute { .. } => {
|
ExprKind::Attribute(_) => {
|
||||||
if checker
|
if checker
|
||||||
.ctx
|
.ctx
|
||||||
.resolve_call_path(default)
|
.resolve_call_path(default)
|
||||||
|
@ -221,18 +223,18 @@ fn is_valid_default_value_with_annotation(
|
||||||
/// Returns `true` if an [`Expr`] appears to be a valid PEP 604 union. (e.g. `int | None`)
|
/// Returns `true` if an [`Expr`] appears to be a valid PEP 604 union. (e.g. `int | None`)
|
||||||
fn is_valid_pep_604_union(annotation: &Expr) -> bool {
|
fn is_valid_pep_604_union(annotation: &Expr) -> bool {
|
||||||
match &annotation.node {
|
match &annotation.node {
|
||||||
ExprKind::BinOp {
|
ExprKind::BinOp(ast::ExprBinOp {
|
||||||
left,
|
left,
|
||||||
op: Operator::BitOr,
|
op: Operator::BitOr,
|
||||||
right,
|
right,
|
||||||
} => is_valid_pep_604_union(left) && is_valid_pep_604_union(right),
|
}) => is_valid_pep_604_union(left) && is_valid_pep_604_union(right),
|
||||||
ExprKind::Name { .. }
|
ExprKind::Name(_)
|
||||||
| ExprKind::Subscript { .. }
|
| ExprKind::Subscript(_)
|
||||||
| ExprKind::Attribute { .. }
|
| ExprKind::Attribute(_)
|
||||||
| ExprKind::Constant {
|
| ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::None,
|
value: Constant::None,
|
||||||
..
|
..
|
||||||
} => true,
|
}) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,21 +243,21 @@ fn is_valid_pep_604_union(annotation: &Expr) -> bool {
|
||||||
fn is_valid_default_value_without_annotation(default: &Expr) -> bool {
|
fn is_valid_default_value_without_annotation(default: &Expr) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
&default.node,
|
&default.node,
|
||||||
ExprKind::Call { .. }
|
ExprKind::Call(_)
|
||||||
| ExprKind::Name { .. }
|
| ExprKind::Name(_)
|
||||||
| ExprKind::Attribute { .. }
|
| ExprKind::Attribute(_)
|
||||||
| ExprKind::Subscript { .. }
|
| ExprKind::Subscript(_)
|
||||||
| ExprKind::Constant {
|
| ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Ellipsis | Constant::None,
|
value: Constant::Ellipsis | Constant::None,
|
||||||
..
|
..
|
||||||
}
|
})
|
||||||
) || is_valid_pep_604_union(default)
|
) || is_valid_pep_604_union(default)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if an [`Expr`] appears to be `TypeVar`, `TypeVarTuple`, `NewType`, or `ParamSpec`
|
/// Returns `true` if an [`Expr`] appears to be `TypeVar`, `TypeVarTuple`, `NewType`, or `ParamSpec`
|
||||||
/// call.
|
/// call.
|
||||||
fn is_type_var_like_call(context: &Context, expr: &Expr) -> bool {
|
fn is_type_var_like_call(context: &Context, expr: &Expr) -> bool {
|
||||||
let ExprKind::Call { func, .. } = &expr.node else {
|
let ExprKind::Call(ast::ExprCall { func, .. } )= &expr.node else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
context.resolve_call_path(func).map_or(false, |call_path| {
|
context.resolve_call_path(func).map_or(false, |call_path| {
|
||||||
|
@ -272,7 +274,7 @@ fn is_type_var_like_call(context: &Context, expr: &Expr) -> bool {
|
||||||
/// Returns `true` if this is a "special" assignment which must have a value (e.g., an assignment to
|
/// Returns `true` if this is a "special" assignment which must have a value (e.g., an assignment to
|
||||||
/// `__all__`).
|
/// `__all__`).
|
||||||
fn is_special_assignment(context: &Context, target: &Expr) -> bool {
|
fn is_special_assignment(context: &Context, target: &Expr) -> bool {
|
||||||
if let ExprKind::Name { id, .. } = &target.node {
|
if let ExprKind::Name(ast::ExprName { id, .. }) = &target.node {
|
||||||
match id.as_str() {
|
match id.as_str() {
|
||||||
"__all__" => context.scope().kind.is_module(),
|
"__all__" => context.scope().kind.is_module(),
|
||||||
"__match_args__" | "__slots__" => context.scope().kind.is_class(),
|
"__match_args__" | "__slots__" => context.scope().kind.is_class(),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Expr, ExprKind};
|
use rustpython_parser::ast::{self, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -60,7 +60,7 @@ fn is_t_suffixed_type_alias(name: &str) -> bool {
|
||||||
|
|
||||||
/// PYI042
|
/// PYI042
|
||||||
pub fn snake_case_type_alias(checker: &mut Checker, target: &Expr) {
|
pub fn snake_case_type_alias(checker: &mut Checker, target: &Expr) {
|
||||||
if let ExprKind::Name { id, .. } = target.node() {
|
if let ExprKind::Name(ast::ExprName { id, .. }) = target.node() {
|
||||||
if !is_snake_case_type_alias(id) {
|
if !is_snake_case_type_alias(id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ pub fn snake_case_type_alias(checker: &mut Checker, target: &Expr) {
|
||||||
|
|
||||||
/// PYI043
|
/// PYI043
|
||||||
pub fn t_suffixed_type_alias(checker: &mut Checker, target: &Expr) {
|
pub fn t_suffixed_type_alias(checker: &mut Checker, target: &Expr) {
|
||||||
if let ExprKind::Name { id, .. } = target.node() {
|
if let ExprKind::Name(ast::ExprName { id, .. }) = target.node() {
|
||||||
if !is_t_suffixed_type_alias(id) {
|
if !is_t_suffixed_type_alias(id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Cmpop, Constant, Expr, ExprKind};
|
use rustpython_parser::ast::{self, Cmpop, Constant, Expr, ExprKind};
|
||||||
|
|
||||||
use ruff_diagnostics::{Diagnostic, Violation};
|
use ruff_diagnostics::{Diagnostic, Violation};
|
||||||
use ruff_macros::{derive_message_formats, violation};
|
use ruff_macros::{derive_message_formats, violation};
|
||||||
|
@ -126,10 +126,10 @@ pub fn unrecognized_platform(
|
||||||
}
|
}
|
||||||
|
|
||||||
match &right.node {
|
match &right.node {
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(value),
|
value: Constant::Str(value),
|
||||||
..
|
..
|
||||||
} => {
|
}) => {
|
||||||
// Other values are possible but we don't need them right now.
|
// Other values are possible but we don't need them right now.
|
||||||
// This protects against typos.
|
// This protects against typos.
|
||||||
if !["linux", "win32", "cygwin", "darwin"].contains(&value.as_str())
|
if !["linux", "win32", "cygwin", "darwin"].contains(&value.as_str())
|
||||||
|
|
|
@ -6,7 +6,8 @@ use libcst_native::{
|
||||||
SmallStatement, Statement, Suite, TrailingWhitespace, UnaryOp, UnaryOperation,
|
SmallStatement, Statement, Suite, TrailingWhitespace, UnaryOp, UnaryOperation,
|
||||||
};
|
};
|
||||||
use rustpython_parser::ast::{
|
use rustpython_parser::ast::{
|
||||||
Boolop, Excepthandler, ExcepthandlerKind, Expr, ExprKind, Keyword, Stmt, StmtKind, Unaryop,
|
self, Boolop, Excepthandler, ExcepthandlerKind, Expr, ExprKind, Keyword, Stmt, StmtKind,
|
||||||
|
Unaryop,
|
||||||
};
|
};
|
||||||
|
|
||||||
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
|
use ruff_diagnostics::{AutofixKind, Diagnostic, Edit, Fix, Violation};
|
||||||
|
@ -135,7 +136,7 @@ where
|
||||||
{
|
{
|
||||||
fn visit_stmt(&mut self, stmt: &'a Stmt) {
|
fn visit_stmt(&mut self, stmt: &'a Stmt) {
|
||||||
match &stmt.node {
|
match &stmt.node {
|
||||||
StmtKind::Assert { .. } => {
|
StmtKind::Assert(_) => {
|
||||||
self.current_assert = Some(stmt);
|
self.current_assert = Some(stmt);
|
||||||
visitor::walk_stmt(self, stmt);
|
visitor::walk_stmt(self, stmt);
|
||||||
self.current_assert = None;
|
self.current_assert = None;
|
||||||
|
@ -146,9 +147,9 @@ where
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &'a Expr) {
|
fn visit_expr(&mut self, expr: &'a Expr) {
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
ExprKind::Name { id, .. } => {
|
ExprKind::Name(ast::ExprName { id, .. }) => {
|
||||||
if let Some(current_assert) = self.current_assert {
|
if let Some(current_assert) = self.current_assert {
|
||||||
if id.as_str() == self.exception_name {
|
if id == self.exception_name {
|
||||||
self.errors.push(Diagnostic::new(
|
self.errors.push(Diagnostic::new(
|
||||||
PytestAssertInExcept {
|
PytestAssertInExcept {
|
||||||
name: id.to_string(),
|
name: id.to_string(),
|
||||||
|
@ -181,11 +182,11 @@ pub fn unittest_assertion(
|
||||||
keywords: &[Keyword],
|
keywords: &[Keyword],
|
||||||
) -> Option<Diagnostic> {
|
) -> Option<Diagnostic> {
|
||||||
match &func.node {
|
match &func.node {
|
||||||
ExprKind::Attribute { attr, .. } => {
|
ExprKind::Attribute(ast::ExprAttribute { attr, .. }) => {
|
||||||
if let Ok(unittest_assert) = UnittestAssert::try_from(attr.as_str()) {
|
if let Ok(unittest_assert) = UnittestAssert::try_from(attr.as_str()) {
|
||||||
// We're converting an expression to a statement, so avoid applying the fix if
|
// We're converting an expression to a statement, so avoid applying the fix if
|
||||||
// the assertion is part of a larger expression.
|
// the assertion is part of a larger expression.
|
||||||
let fixable = matches!(checker.ctx.stmt().node, StmtKind::Expr { .. })
|
let fixable = matches!(checker.ctx.stmt().node, StmtKind::Expr(_))
|
||||||
&& checker.ctx.expr_parent().is_none()
|
&& checker.ctx.expr_parent().is_none()
|
||||||
&& !checker.ctx.scope().kind.is_lambda()
|
&& !checker.ctx.scope().kind.is_lambda()
|
||||||
&& !has_comments_in(expr.range(), checker.locator);
|
&& !has_comments_in(expr.range(), checker.locator);
|
||||||
|
@ -227,7 +228,11 @@ pub fn assert_in_exception_handler(handlers: &[Excepthandler]) -> Vec<Diagnostic
|
||||||
handlers
|
handlers
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|handler| match &handler.node {
|
.flat_map(|handler| match &handler.node {
|
||||||
ExcepthandlerKind::ExceptHandler { name, body, .. } => {
|
ExcepthandlerKind::ExceptHandler(ast::ExcepthandlerExceptHandler {
|
||||||
|
name,
|
||||||
|
body,
|
||||||
|
..
|
||||||
|
}) => {
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
check_assert_in_except(name, body)
|
check_assert_in_except(name, body)
|
||||||
} else {
|
} else {
|
||||||
|
@ -255,28 +260,28 @@ enum CompositionKind {
|
||||||
/// `not a and not b` by De Morgan's laws.
|
/// `not a and not b` by De Morgan's laws.
|
||||||
fn is_composite_condition(test: &Expr) -> CompositionKind {
|
fn is_composite_condition(test: &Expr) -> CompositionKind {
|
||||||
match &test.node {
|
match &test.node {
|
||||||
ExprKind::BoolOp {
|
ExprKind::BoolOp(ast::ExprBoolOp {
|
||||||
op: Boolop::And, ..
|
op: Boolop::And, ..
|
||||||
} => {
|
}) => {
|
||||||
return CompositionKind::Simple;
|
return CompositionKind::Simple;
|
||||||
}
|
}
|
||||||
ExprKind::UnaryOp {
|
ExprKind::UnaryOp(ast::ExprUnaryOp {
|
||||||
op: Unaryop::Not,
|
op: Unaryop::Not,
|
||||||
operand,
|
operand,
|
||||||
} => {
|
}) => {
|
||||||
if let ExprKind::BoolOp {
|
if let ExprKind::BoolOp(ast::ExprBoolOp {
|
||||||
op: Boolop::Or,
|
op: Boolop::Or,
|
||||||
values,
|
values,
|
||||||
} = &operand.node
|
}) = &operand.node
|
||||||
{
|
{
|
||||||
// Only split cases without mixed `and` and `or`.
|
// Only split cases without mixed `and` and `or`.
|
||||||
return if values.iter().all(|expr| {
|
return if values.iter().all(|expr| {
|
||||||
!matches!(
|
!matches!(
|
||||||
expr.node,
|
expr.node,
|
||||||
ExprKind::BoolOp {
|
ExprKind::BoolOp(ast::ExprBoolOp {
|
||||||
op: Boolop::And,
|
op: Boolop::And,
|
||||||
..
|
..
|
||||||
}
|
})
|
||||||
)
|
)
|
||||||
}) {
|
}) {
|
||||||
CompositionKind::Simple
|
CompositionKind::Simple
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use ruff_text_size::{TextLen, TextRange, TextSize};
|
use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||||
use rustpython_parser::ast::{Arguments, Expr, ExprKind, Keyword, Stmt, StmtKind};
|
use rustpython_parser::ast::{self, Arguments, Expr, ExprKind, Keyword, Stmt, StmtKind};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use ruff_diagnostics::{AlwaysAutofixableViolation, Violation};
|
use ruff_diagnostics::{AlwaysAutofixableViolation, Violation};
|
||||||
|
@ -208,28 +208,28 @@ where
|
||||||
{
|
{
|
||||||
fn visit_stmt(&mut self, stmt: &'b Stmt) {
|
fn visit_stmt(&mut self, stmt: &'b Stmt) {
|
||||||
match &stmt.node {
|
match &stmt.node {
|
||||||
StmtKind::Return { value, .. } => {
|
StmtKind::Return(ast::StmtReturn { value }) => {
|
||||||
if value.is_some() {
|
if value.is_some() {
|
||||||
self.has_return_with_value = true;
|
self.has_return_with_value = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::FunctionDef { .. } | StmtKind::AsyncFunctionDef { .. } => {}
|
StmtKind::FunctionDef(_) | StmtKind::AsyncFunctionDef(_) => {}
|
||||||
_ => visitor::walk_stmt(self, stmt),
|
_ => visitor::walk_stmt(self, stmt),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &'b Expr) {
|
fn visit_expr(&mut self, expr: &'b Expr) {
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
ExprKind::YieldFrom { .. } => {
|
ExprKind::YieldFrom(_) => {
|
||||||
self.has_yield_from = true;
|
self.has_yield_from = true;
|
||||||
}
|
}
|
||||||
ExprKind::Yield { value, .. } => {
|
ExprKind::Yield(ast::ExprYield { value }) => {
|
||||||
self.yield_statements.push(expr);
|
self.yield_statements.push(expr);
|
||||||
if value.is_some() {
|
if value.is_some() {
|
||||||
self.has_return_with_value = true;
|
self.has_return_with_value = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Call { func, .. } => {
|
ExprKind::Call(ast::ExprCall { func, .. }) => {
|
||||||
if collect_call_path(func).map_or(false, |call_path| {
|
if collect_call_path(func).map_or(false, |call_path| {
|
||||||
call_path.as_slice() == ["request", "addfinalizer"]
|
call_path.as_slice() == ["request", "addfinalizer"]
|
||||||
}) {
|
}) {
|
||||||
|
@ -278,12 +278,11 @@ pub fn fix_extraneous_scope_function(
|
||||||
/// PT001, PT002, PT003
|
/// PT001, PT002, PT003
|
||||||
fn check_fixture_decorator(checker: &mut Checker, func_name: &str, decorator: &Expr) {
|
fn check_fixture_decorator(checker: &mut Checker, func_name: &str, decorator: &Expr) {
|
||||||
match &decorator.node {
|
match &decorator.node {
|
||||||
ExprKind::Call {
|
ExprKind::Call(ast::ExprCall {
|
||||||
func,
|
func,
|
||||||
args,
|
args,
|
||||||
keywords,
|
keywords,
|
||||||
..
|
}) => {
|
||||||
} => {
|
|
||||||
if checker
|
if checker
|
||||||
.settings
|
.settings
|
||||||
.rules
|
.rules
|
||||||
|
@ -415,8 +414,8 @@ fn check_fixture_returns(checker: &mut Checker, stmt: &Stmt, name: &str, body: &
|
||||||
.enabled(Rule::PytestUselessYieldFixture)
|
.enabled(Rule::PytestUselessYieldFixture)
|
||||||
{
|
{
|
||||||
if let Some(stmt) = body.last() {
|
if let Some(stmt) = body.last() {
|
||||||
if let StmtKind::Expr { value, .. } = &stmt.node {
|
if let StmtKind::Expr(ast::StmtExpr { value }) = &stmt.node {
|
||||||
if let ExprKind::Yield { .. } = value.node {
|
if let ExprKind::Yield(_) = value.node {
|
||||||
if visitor.yield_statements.len() == 1 {
|
if visitor.yield_statements.len() == 1 {
|
||||||
let mut diagnostic = Diagnostic::new(
|
let mut diagnostic = Diagnostic::new(
|
||||||
PytestUselessYieldFixture {
|
PytestUselessYieldFixture {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use rustpython_parser::ast::{Constant, Expr, ExprKind, Keyword};
|
use rustpython_parser::ast::{self, Constant, Expr, ExprKind, Keyword};
|
||||||
|
|
||||||
use ruff_python_ast::call_path::{collect_call_path, CallPath};
|
use ruff_python_ast::call_path::{collect_call_path, CallPath};
|
||||||
use ruff_python_ast::helpers::map_callable;
|
use ruff_python_ast::helpers::map_callable;
|
||||||
|
@ -48,10 +48,10 @@ pub(super) fn is_pytest_parametrize(context: &Context, decorator: &Expr) -> bool
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn keyword_is_literal(kw: &Keyword, literal: &str) -> bool {
|
pub(super) fn keyword_is_literal(kw: &Keyword, literal: &str) -> bool {
|
||||||
if let ExprKind::Constant {
|
if let ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(string),
|
value: Constant::Str(string),
|
||||||
..
|
..
|
||||||
} = &kw.node.value.node
|
}) = &kw.node.value.node
|
||||||
{
|
{
|
||||||
string == literal
|
string == literal
|
||||||
} else {
|
} else {
|
||||||
|
@ -61,15 +61,17 @@ pub(super) fn keyword_is_literal(kw: &Keyword, literal: &str) -> bool {
|
||||||
|
|
||||||
pub(super) fn is_empty_or_null_string(expr: &Expr) -> bool {
|
pub(super) fn is_empty_or_null_string(expr: &Expr) -> bool {
|
||||||
match &expr.node {
|
match &expr.node {
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::Str(string),
|
value: Constant::Str(string),
|
||||||
..
|
..
|
||||||
} => string.is_empty(),
|
}) => string.is_empty(),
|
||||||
ExprKind::Constant {
|
ExprKind::Constant(ast::ExprConstant {
|
||||||
value: Constant::None,
|
value: Constant::None,
|
||||||
..
|
..
|
||||||
} => true,
|
}) => true,
|
||||||
ExprKind::JoinedStr { values } => values.iter().all(is_empty_or_null_string),
|
ExprKind::JoinedStr(ast::ExprJoinedStr { values }) => {
|
||||||
|
values.iter().all(is_empty_or_null_string)
|
||||||
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ pub fn import(import_from: &Stmt, name: &str, asname: Option<&str>) -> Option<Di
|
||||||
pub fn import_from(
|
pub fn import_from(
|
||||||
import_from: &Stmt,
|
import_from: &Stmt,
|
||||||
module: Option<&str>,
|
module: Option<&str>,
|
||||||
level: Option<usize>,
|
level: Option<u32>,
|
||||||
) -> Option<Diagnostic> {
|
) -> Option<Diagnostic> {
|
||||||
// If level is not zero or module is none, return
|
// If level is not zero or module is none, return
|
||||||
if let Some(level) = level {
|
if let Some(level) = level {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue