Compare commits
17 Commits
brent/ty-c
...
jack/new_t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49942f656c | ||
|
|
e5ca03e1c7 | ||
|
|
2be369f299 | ||
|
|
5d9a8af775 | ||
|
|
5191691d01 | ||
|
|
a88517f13b | ||
|
|
83e3e67cd7 | ||
|
|
d7376bc9ef | ||
|
|
fe8bd215bf | ||
|
|
8368c28ba7 | ||
|
|
e7b093a371 | ||
|
|
5bbeb56feb | ||
|
|
fd181bf986 | ||
|
|
6b81418bdb | ||
|
|
1dbecd3634 | ||
|
|
e59f0b2211 | ||
|
|
790cce4628 |
16
.github/workflows/ci.yaml
vendored
16
.github/workflows/ci.yaml
vendored
@@ -441,7 +441,7 @@ jobs:
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- name: "Install cargo-binstall"
|
||||
uses: cargo-bins/cargo-binstall@0dca8cf8dfb40cb77a29cece06933ce674674523 # v1.15.1
|
||||
uses: cargo-bins/cargo-binstall@79e4beb1e02f733a26129a6bf26c37dab4ab3307 # v1.14.4
|
||||
with:
|
||||
tool: cargo-fuzz@0.11.2
|
||||
- name: "Install cargo-fuzz"
|
||||
@@ -463,7 +463,7 @@ jobs:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: astral-sh/setup-uv@4959332f0f014c5280e7eac8b70c90cb574c9f9b # v6.6.0
|
||||
- uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
|
||||
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||
name: Download Ruff binary to test
|
||||
id: download-cached-binary
|
||||
@@ -664,7 +664,7 @@ jobs:
|
||||
branch: ${{ github.event.pull_request.base.ref }}
|
||||
workflow: "ci.yaml"
|
||||
check_artifacts: true
|
||||
- uses: astral-sh/setup-uv@4959332f0f014c5280e7eac8b70c90cb574c9f9b # v6.6.0
|
||||
- uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
|
||||
- name: Fuzz
|
||||
env:
|
||||
FORCE_COLOR: 1
|
||||
@@ -694,7 +694,7 @@ jobs:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: cargo-bins/cargo-binstall@0dca8cf8dfb40cb77a29cece06933ce674674523 # v1.15.1
|
||||
- uses: cargo-bins/cargo-binstall@79e4beb1e02f733a26129a6bf26c37dab4ab3307 # v1.14.4
|
||||
- run: cargo binstall --no-confirm cargo-shear
|
||||
- run: cargo shear
|
||||
|
||||
@@ -734,7 +734,7 @@ jobs:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: astral-sh/setup-uv@4959332f0f014c5280e7eac8b70c90cb574c9f9b # v6.6.0
|
||||
- uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
|
||||
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
with:
|
||||
@@ -777,7 +777,7 @@ jobs:
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@4959332f0f014c5280e7eac8b70c90cb574c9f9b # v6.6.0
|
||||
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
|
||||
- name: "Install Insiders dependencies"
|
||||
if: ${{ env.MKDOCS_INSIDERS_SSH_KEY_EXISTS == 'true' }}
|
||||
run: uv pip install -r docs/requirements-insiders.txt --system
|
||||
@@ -909,7 +909,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||
- uses: astral-sh/setup-uv@4959332f0f014c5280e7eac8b70c90cb574c9f9b # v6.6.0
|
||||
- uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
|
||||
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
@@ -942,7 +942,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||
- uses: astral-sh/setup-uv@4959332f0f014c5280e7eac8b70c90cb574c9f9b # v6.6.0
|
||||
- uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
|
||||
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
|
||||
2
.github/workflows/daily_fuzz.yaml
vendored
2
.github/workflows/daily_fuzz.yaml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: astral-sh/setup-uv@4959332f0f014c5280e7eac8b70c90cb574c9f9b # v6.6.0
|
||||
- uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- name: "Install mold"
|
||||
|
||||
4
.github/workflows/mypy_primer.yaml
vendored
4
.github/workflows/mypy_primer.yaml
vendored
@@ -39,7 +39,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@4959332f0f014c5280e7eac8b70c90cb574c9f9b # v6.6.0
|
||||
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
|
||||
|
||||
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||
with:
|
||||
@@ -82,7 +82,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@4959332f0f014c5280e7eac8b70c90cb574c9f9b # v6.6.0
|
||||
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
|
||||
|
||||
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||
with:
|
||||
|
||||
2
.github/workflows/publish-pypi.yml
vendored
2
.github/workflows/publish-pypi.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
id-token: write
|
||||
steps:
|
||||
- name: "Install uv"
|
||||
uses: astral-sh/setup-uv@4959332f0f014c5280e7eac8b70c90cb574c9f9b # v6.6.0
|
||||
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
|
||||
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||
with:
|
||||
pattern: wheels-*
|
||||
|
||||
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@@ -61,7 +61,7 @@ jobs:
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -124,7 +124,7 @@ jobs:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json
|
||||
steps:
|
||||
- uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -175,7 +175,7 @@ jobs:
|
||||
outputs:
|
||||
val: ${{ steps.host.outputs.manifest }}
|
||||
steps:
|
||||
- uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
@@ -251,7 +251,7 @@ jobs:
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
|
||||
6
.github/workflows/sync_typeshed.yaml
vendored
6
.github/workflows/sync_typeshed.yaml
vendored
@@ -65,7 +65,7 @@ jobs:
|
||||
run: |
|
||||
git config --global user.name typeshedbot
|
||||
git config --global user.email '<>'
|
||||
- uses: astral-sh/setup-uv@4959332f0f014c5280e7eac8b70c90cb574c9f9b # v6.6.0
|
||||
- uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
|
||||
- name: Sync typeshed stubs
|
||||
run: |
|
||||
rm -rf "ruff/${VENDORED_TYPESHED}"
|
||||
@@ -117,7 +117,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: true
|
||||
ref: ${{ env.UPSTREAM_BRANCH}}
|
||||
- uses: astral-sh/setup-uv@4959332f0f014c5280e7eac8b70c90cb574c9f9b # v6.6.0
|
||||
- uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
|
||||
- name: Setup git
|
||||
run: |
|
||||
git config --global user.name typeshedbot
|
||||
@@ -155,7 +155,7 @@ jobs:
|
||||
with:
|
||||
persist-credentials: true
|
||||
ref: ${{ env.UPSTREAM_BRANCH}}
|
||||
- uses: astral-sh/setup-uv@4959332f0f014c5280e7eac8b70c90cb574c9f9b # v6.6.0
|
||||
- uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
|
||||
- name: Setup git
|
||||
run: |
|
||||
git config --global user.name typeshedbot
|
||||
|
||||
2
.github/workflows/ty-ecosystem-analyzer.yaml
vendored
2
.github/workflows/ty-ecosystem-analyzer.yaml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@4959332f0f014c5280e7eac8b70c90cb574c9f9b # v6.6.0
|
||||
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
|
||||
|
||||
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||
with:
|
||||
|
||||
2
.github/workflows/ty-ecosystem-report.yaml
vendored
2
.github/workflows/ty-ecosystem-report.yaml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@4959332f0f014c5280e7eac8b70c90cb574c9f9b # v6.6.0
|
||||
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
|
||||
|
||||
- uses: Swatinem/rust-cache@98c8021b550208e191a6a3145459bfc9fb29c4c0 # v2.8.0
|
||||
with:
|
||||
|
||||
24
CHANGELOG.md
24
CHANGELOG.md
@@ -1,29 +1,5 @@
|
||||
# Changelog
|
||||
|
||||
## 0.12.10
|
||||
|
||||
### Preview features
|
||||
|
||||
- \[`flake8-simplify`\] Implement fix for `maxsplit` without separator (`SIM905`) ([#19851](https://github.com/astral-sh/ruff/pull/19851))
|
||||
- \[`flake8-use-pathlib`\] Add fixes for `PTH102` and `PTH103` ([#19514](https://github.com/astral-sh/ruff/pull/19514))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- \[`isort`\] Handle multiple continuation lines after module docstring (`I002`) ([#19818](https://github.com/astral-sh/ruff/pull/19818))
|
||||
- \[`pyupgrade`\] Avoid reporting `__future__` features as unnecessary when they are used (`UP010`) ([#19769](https://github.com/astral-sh/ruff/pull/19769))
|
||||
- \[`pyupgrade`\] Handle nested `Optional`s (`UP045`) ([#19770](https://github.com/astral-sh/ruff/pull/19770))
|
||||
|
||||
### Rule changes
|
||||
|
||||
- \[`pycodestyle`\] Make `E731` fix unsafe instead of display-only for class assignments ([#19700](https://github.com/astral-sh/ruff/pull/19700))
|
||||
- \[`pyflakes`\] Add secondary annotation showing previous definition (`F811`) ([#19900](https://github.com/astral-sh/ruff/pull/19900))
|
||||
|
||||
### Documentation
|
||||
|
||||
- Fix description of global config file discovery strategy ([#19188](https://github.com/astral-sh/ruff/pull/19188))
|
||||
- Update outdated links to <https://typing.python.org/en/latest/source/stubs.html> ([#19992](https://github.com/astral-sh/ruff/pull/19992))
|
||||
- \[`flake8-annotations`\] Remove unused import in example (`ANN401`) ([#20000](https://github.com/astral-sh/ruff/pull/20000))
|
||||
|
||||
## 0.12.9
|
||||
|
||||
### Preview features
|
||||
|
||||
181
Cargo.lock
generated
181
Cargo.lock
generated
@@ -257,9 +257,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.3"
|
||||
version = "2.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d"
|
||||
checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29"
|
||||
|
||||
[[package]]
|
||||
name = "bitvec"
|
||||
@@ -295,7 +295,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"regex-automata 0.4.10",
|
||||
"regex-automata 0.4.9",
|
||||
"serde",
|
||||
]
|
||||
|
||||
@@ -485,7 +485,7 @@ checksum = "85a8ab73a1c02b0c15597b22e09c7dc36e63b2f601f9d1e83ac0c3decd38b1ae"
|
||||
dependencies = [
|
||||
"nix 0.29.0",
|
||||
"terminfo",
|
||||
"thiserror 2.0.16",
|
||||
"thiserror 2.0.12",
|
||||
"which",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
@@ -955,7 +955,7 @@ dependencies = [
|
||||
"libc",
|
||||
"option-ext",
|
||||
"redox_users",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1035,7 +1035,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1084,14 +1084,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.26"
|
||||
version = "0.2.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed"
|
||||
checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"libredox",
|
||||
"windows-sys 0.60.2",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1118,9 +1118,9 @@ checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.2.2"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
|
||||
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
|
||||
dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
@@ -1218,9 +1218,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.3"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
|
||||
checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
|
||||
|
||||
[[package]]
|
||||
name = "globset"
|
||||
@@ -1231,7 +1231,7 @@ dependencies = [
|
||||
"aho-corasick",
|
||||
"bstr",
|
||||
"log",
|
||||
"regex-automata 0.4.10",
|
||||
"regex-automata 0.4.9",
|
||||
"regex-syntax 0.8.5",
|
||||
]
|
||||
|
||||
@@ -1241,7 +1241,7 @@ version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bf760ebf69878d9fd8f110c89703d90ce35095324d1f1edcb595c63945ee757"
|
||||
dependencies = [
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
"ignore",
|
||||
"walkdir",
|
||||
]
|
||||
@@ -1430,9 +1430,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "1.1.0"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
|
||||
checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
|
||||
dependencies = [
|
||||
"idna_adapter",
|
||||
"smallvec",
|
||||
@@ -1459,7 +1459,7 @@ dependencies = [
|
||||
"globset",
|
||||
"log",
|
||||
"memchr",
|
||||
"regex-automata 0.4.10",
|
||||
"regex-automata 0.4.9",
|
||||
"same-file",
|
||||
"walkdir",
|
||||
"winapi-util",
|
||||
@@ -1486,9 +1486,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.11.0"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9"
|
||||
checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.15.5",
|
||||
@@ -1521,7 +1521,7 @@ version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3"
|
||||
dependencies = [
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
"inotify-sys",
|
||||
"libc",
|
||||
]
|
||||
@@ -1780,7 +1780,7 @@ dependencies = [
|
||||
"paste",
|
||||
"peg",
|
||||
"regex",
|
||||
"thiserror 2.0.16",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1809,7 +1809,7 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3"
|
||||
dependencies = [
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
]
|
||||
@@ -2014,7 +2014,7 @@ version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
|
||||
dependencies = [
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
@@ -2026,7 +2026,7 @@ version = "0.30.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
||||
dependencies = [
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
@@ -2054,7 +2054,7 @@ version = "8.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3"
|
||||
dependencies = [
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
"fsevent-sys",
|
||||
"inotify",
|
||||
"kqueue",
|
||||
@@ -2127,9 +2127,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||
|
||||
[[package]]
|
||||
name = "ordermap"
|
||||
version = "0.5.9"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fd6fedcd996c8c97932075cc3811d83f53280f48d5620e4e3cab7f6a12678c4"
|
||||
checksum = "6d6bff06e4a5dc6416bead102d3e63c480dd852ffbb278bf8cfeb4966b329609"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
@@ -2283,9 +2283,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.2"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
@@ -2294,7 +2294,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"thiserror 2.0.16",
|
||||
"thiserror 2.0.12",
|
||||
"ucd-trie",
|
||||
]
|
||||
|
||||
@@ -2473,9 +2473,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.101"
|
||||
version = "1.0.96"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
|
||||
checksum = "beef09f85ae72cea1ef96ba6870c51e6382ebfa4f0e85b643459331f3daa5be0"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -2490,7 +2490,7 @@ dependencies = [
|
||||
"pep440_rs",
|
||||
"pep508_rs",
|
||||
"serde",
|
||||
"thiserror 2.0.16",
|
||||
"thiserror 2.0.12",
|
||||
"toml 0.8.23",
|
||||
]
|
||||
|
||||
@@ -2505,7 +2505,7 @@ dependencies = [
|
||||
"newtype-uuid",
|
||||
"quick-xml",
|
||||
"strip-ansi-escapes",
|
||||
"thiserror 2.0.16",
|
||||
"thiserror 2.0.12",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
@@ -2666,7 +2666,7 @@ version = "0.5.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
|
||||
dependencies = [
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2677,18 +2677,18 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac"
|
||||
dependencies = [
|
||||
"getrandom 0.2.16",
|
||||
"libredox",
|
||||
"thiserror 2.0.16",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.11.2"
|
||||
version = "1.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912"
|
||||
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata 0.4.10",
|
||||
"regex-automata 0.4.9",
|
||||
"regex-syntax 0.8.5",
|
||||
]
|
||||
|
||||
@@ -2703,9 +2703,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.10"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6"
|
||||
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -2743,13 +2743,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.12.10"
|
||||
version = "0.12.9"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"argfile",
|
||||
"assert_fs",
|
||||
"bincode 2.0.1",
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
"cachedir",
|
||||
"clap",
|
||||
"clap_complete_command",
|
||||
@@ -2793,7 +2793,7 @@ dependencies = [
|
||||
"strum",
|
||||
"tempfile",
|
||||
"test-case",
|
||||
"thiserror 2.0.16",
|
||||
"thiserror 2.0.12",
|
||||
"tikv-jemallocator",
|
||||
"toml 0.9.5",
|
||||
"tracing",
|
||||
@@ -2886,9 +2886,8 @@ dependencies = [
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"similar",
|
||||
"tempfile",
|
||||
"thiserror 2.0.16",
|
||||
"thiserror 2.0.12",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"ty_static",
|
||||
@@ -2935,7 +2934,6 @@ dependencies = [
|
||||
"tracing-subscriber",
|
||||
"ty",
|
||||
"ty_project",
|
||||
"ty_python_semantic",
|
||||
"ty_static",
|
||||
"url",
|
||||
]
|
||||
@@ -2998,11 +2996,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_linter"
|
||||
version = "0.12.10"
|
||||
version = "0.12.9"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"anyhow",
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
"clap",
|
||||
"colored 3.0.0",
|
||||
"fern",
|
||||
@@ -3049,7 +3047,7 @@ dependencies = [
|
||||
"strum_macros",
|
||||
"tempfile",
|
||||
"test-case",
|
||||
"thiserror 2.0.16",
|
||||
"thiserror 2.0.12",
|
||||
"toml 0.9.5",
|
||||
"typed-arena",
|
||||
"unicode-normalization",
|
||||
@@ -3092,7 +3090,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"serde_with",
|
||||
"test-case",
|
||||
"thiserror 2.0.16",
|
||||
"thiserror 2.0.12",
|
||||
"uuid",
|
||||
]
|
||||
|
||||
@@ -3108,7 +3106,7 @@ name = "ruff_python_ast"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
"compact_str",
|
||||
"get-size2",
|
||||
"is-macro",
|
||||
@@ -3123,7 +3121,7 @@ dependencies = [
|
||||
"salsa",
|
||||
"schemars",
|
||||
"serde",
|
||||
"thiserror 2.0.16",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3177,7 +3175,7 @@ dependencies = [
|
||||
"similar",
|
||||
"smallvec",
|
||||
"static_assertions",
|
||||
"thiserror 2.0.16",
|
||||
"thiserror 2.0.12",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
@@ -3196,7 +3194,7 @@ dependencies = [
|
||||
name = "ruff_python_literal"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
"itertools 0.14.0",
|
||||
"ruff_python_ast",
|
||||
"unic-ucd-category",
|
||||
@@ -3207,7 +3205,7 @@ name = "ruff_python_parser"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
"bstr",
|
||||
"compact_str",
|
||||
"get-size2",
|
||||
@@ -3232,7 +3230,7 @@ dependencies = [
|
||||
name = "ruff_python_semantic"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
"insta",
|
||||
"is-macro",
|
||||
"ruff_cache",
|
||||
@@ -3253,7 +3251,7 @@ dependencies = [
|
||||
name = "ruff_python_stdlib"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
@@ -3307,7 +3305,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"shellexpand",
|
||||
"thiserror 2.0.16",
|
||||
"thiserror 2.0.12",
|
||||
"toml 0.9.5",
|
||||
"tracing",
|
||||
"tracing-log",
|
||||
@@ -3337,7 +3335,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff_wasm"
|
||||
version = "0.12.10"
|
||||
version = "0.12.9"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"console_log",
|
||||
@@ -3430,11 +3428,11 @@ version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
|
||||
dependencies = [
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3452,7 +3450,7 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
[[package]]
|
||||
name = "salsa"
|
||||
version = "0.23.0"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=a3ffa22cb26756473d56f867aedec3fd907c4dd9#a3ffa22cb26756473d56f867aedec3fd907c4dd9"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=918d35d873b2b73a0237536144ef4d22e8d57f27#918d35d873b2b73a0237536144ef4d22e8d57f27"
|
||||
dependencies = [
|
||||
"boxcar",
|
||||
"compact_str",
|
||||
@@ -3476,12 +3474,12 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "salsa-macro-rules"
|
||||
version = "0.23.0"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=a3ffa22cb26756473d56f867aedec3fd907c4dd9#a3ffa22cb26756473d56f867aedec3fd907c4dd9"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=918d35d873b2b73a0237536144ef4d22e8d57f27#918d35d873b2b73a0237536144ef4d22e8d57f27"
|
||||
|
||||
[[package]]
|
||||
name = "salsa-macros"
|
||||
version = "0.23.0"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=a3ffa22cb26756473d56f867aedec3fd907c4dd9#a3ffa22cb26756473d56f867aedec3fd907c4dd9"
|
||||
source = "git+https://github.com/salsa-rs/salsa.git?rev=918d35d873b2b73a0237536144ef4d22e8d57f27#918d35d873b2b73a0237536144ef4d22e8d57f27"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3578,9 +3576,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.143"
|
||||
version = "1.0.142"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a"
|
||||
checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
@@ -3791,9 +3789,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.106"
|
||||
version = "2.0.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
|
||||
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -3917,11 +3915,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.16"
|
||||
version = "2.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
|
||||
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
|
||||
dependencies = [
|
||||
"thiserror-impl 2.0.16",
|
||||
"thiserror-impl 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3937,9 +3935,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.16"
|
||||
version = "2.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
|
||||
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -4138,9 +4136,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-indicatif"
|
||||
version = "0.3.13"
|
||||
version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04d4e11e0e27acef25a47f27e9435355fecdc488867fa2bc90e75b0700d2823d"
|
||||
checksum = "e1983afead46ff13a3c93581e0cec31d20b29efdd22cbdaa8b9f850eccf2c352"
|
||||
dependencies = [
|
||||
"indicatif",
|
||||
"tracing",
|
||||
@@ -4240,22 +4238,17 @@ dependencies = [
|
||||
name = "ty_ide"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 2.9.3",
|
||||
"get-size2",
|
||||
"bitflags 2.9.2",
|
||||
"insta",
|
||||
"itertools 0.14.0",
|
||||
"rayon",
|
||||
"regex",
|
||||
"ruff_db",
|
||||
"ruff_index",
|
||||
"ruff_memory_usage",
|
||||
"ruff_python_ast",
|
||||
"ruff_python_parser",
|
||||
"ruff_python_trivia",
|
||||
"ruff_source_file",
|
||||
"ruff_text_size",
|
||||
"rustc-hash",
|
||||
"salsa",
|
||||
"smallvec",
|
||||
"tracing",
|
||||
"ty_project",
|
||||
@@ -4278,7 +4271,7 @@ dependencies = [
|
||||
"pep440_rs",
|
||||
"rayon",
|
||||
"regex",
|
||||
"regex-automata 0.4.10",
|
||||
"regex-automata 0.4.9",
|
||||
"ruff_cache",
|
||||
"ruff_db",
|
||||
"ruff_macros",
|
||||
@@ -4291,7 +4284,7 @@ dependencies = [
|
||||
"salsa",
|
||||
"schemars",
|
||||
"serde",
|
||||
"thiserror 2.0.16",
|
||||
"thiserror 2.0.12",
|
||||
"toml 0.9.5",
|
||||
"tracing",
|
||||
"ty_combine",
|
||||
@@ -4304,7 +4297,7 @@ name = "ty_python_semantic"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
"bitvec",
|
||||
"camino",
|
||||
"colored 3.0.0",
|
||||
@@ -4344,7 +4337,7 @@ dependencies = [
|
||||
"strum_macros",
|
||||
"tempfile",
|
||||
"test-case",
|
||||
"thiserror 2.0.16",
|
||||
"thiserror 2.0.12",
|
||||
"tracing",
|
||||
"ty_python_semantic",
|
||||
"ty_static",
|
||||
@@ -4357,7 +4350,7 @@ name = "ty_server"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
"crossbeam",
|
||||
"dunce",
|
||||
"insta",
|
||||
@@ -4378,7 +4371,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"shellexpand",
|
||||
"tempfile",
|
||||
"thiserror 2.0.16",
|
||||
"thiserror 2.0.12",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"ty_combine",
|
||||
@@ -4400,7 +4393,7 @@ name = "ty_test"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
"camino",
|
||||
"colored 3.0.0",
|
||||
"insta",
|
||||
@@ -4419,7 +4412,7 @@ dependencies = [
|
||||
"serde",
|
||||
"smallvec",
|
||||
"tempfile",
|
||||
"thiserror 2.0.16",
|
||||
"thiserror 2.0.12",
|
||||
"toml 0.9.5",
|
||||
"tracing",
|
||||
"ty_python_semantic",
|
||||
@@ -4596,9 +4589,9 @@ checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.7"
|
||||
version = "2.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b"
|
||||
checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
@@ -5150,7 +5143,7 @@ version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
||||
dependencies = [
|
||||
"bitflags 2.9.3",
|
||||
"bitflags 2.9.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -143,7 +143,7 @@ regex-automata = { version = "0.4.9" }
|
||||
rustc-hash = { version = "2.0.0" }
|
||||
rustc-stable-hash = { version = "0.1.2" }
|
||||
# When updating salsa, make sure to also update the revision in `fuzz/Cargo.toml`
|
||||
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "a3ffa22cb26756473d56f867aedec3fd907c4dd9", default-features = false, features = [
|
||||
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "918d35d873b2b73a0237536144ef4d22e8d57f27", default-features = false, features = [
|
||||
"compact_str",
|
||||
"macros",
|
||||
"salsa_unstable",
|
||||
@@ -215,8 +215,6 @@ unexpected_cfgs = { level = "warn", check-cfg = [
|
||||
|
||||
[workspace.lints.clippy]
|
||||
pedantic = { level = "warn", priority = -2 }
|
||||
# Enabled at the crate level
|
||||
disallowed_methods = "allow"
|
||||
# Allowed pedantic lints
|
||||
char_lit_as_u8 = "allow"
|
||||
collapsible_else_if = "allow"
|
||||
@@ -255,7 +253,6 @@ unused_peekable = "warn"
|
||||
# Diagnostics are not actionable: Enable once https://github.com/rust-lang/rust-clippy/issues/13774 is resolved.
|
||||
large_stack_arrays = "allow"
|
||||
|
||||
|
||||
[profile.release]
|
||||
# Note that we set these explicitly, and these values
|
||||
# were chosen based on a trade-off between compile times
|
||||
|
||||
@@ -148,8 +148,8 @@ curl -LsSf https://astral.sh/ruff/install.sh | sh
|
||||
powershell -c "irm https://astral.sh/ruff/install.ps1 | iex"
|
||||
|
||||
# For a specific version.
|
||||
curl -LsSf https://astral.sh/ruff/0.12.10/install.sh | sh
|
||||
powershell -c "irm https://astral.sh/ruff/0.12.10/install.ps1 | iex"
|
||||
curl -LsSf https://astral.sh/ruff/0.12.9/install.sh | sh
|
||||
powershell -c "irm https://astral.sh/ruff/0.12.9/install.ps1 | iex"
|
||||
```
|
||||
|
||||
You can also install Ruff via [Homebrew](https://formulae.brew.sh/formula/ruff), [Conda](https://anaconda.org/conda-forge/ruff),
|
||||
@@ -182,7 +182,7 @@ Ruff can also be used as a [pre-commit](https://pre-commit.com/) hook via [`ruff
|
||||
```yaml
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.12.10
|
||||
rev: v0.12.9
|
||||
hooks:
|
||||
# Run the linter.
|
||||
- id: ruff-check
|
||||
|
||||
17
clippy.toml
17
clippy.toml
@@ -24,20 +24,3 @@ ignore-interior-mutability = [
|
||||
# The expression is read-only.
|
||||
"ruff_python_ast::hashable::HashableExpr",
|
||||
]
|
||||
|
||||
disallowed-methods = [
|
||||
{ path = "std::env::var", reason = "Use System::env_var instead in ty crates" },
|
||||
{ path = "std::env::current_dir", reason = "Use System::current_directory instead in ty crates" },
|
||||
{ path = "std::fs::read_to_string", reason = "Use System::read_to_string instead in ty crates" },
|
||||
{ path = "std::fs::metadata", reason = "Use System::path_metadata instead in ty crates" },
|
||||
{ path = "std::fs::canonicalize", reason = "Use System::canonicalize_path instead in ty crates" },
|
||||
{ path = "dunce::canonicalize", reason = "Use System::canonicalize_path instead in ty crates" },
|
||||
{ path = "std::fs::read_dir", reason = "Use System::read_directory instead in ty crates" },
|
||||
{ path = "std::fs::write", reason = "Use WritableSystem::write_file instead in ty crates" },
|
||||
{ path = "std::fs::create_dir_all", reason = "Use WritableSystem::create_directory_all instead in ty crates" },
|
||||
{ path = "std::fs::File::create_new", reason = "Use WritableSystem::create_new_file instead in ty crates" },
|
||||
# Path methods that have System trait equivalents
|
||||
{ path = "std::path::Path::exists", reason = "Use System::path_exists instead in ty crates" },
|
||||
{ path = "std::path::Path::is_dir", reason = "Use System::is_directory instead in ty crates" },
|
||||
{ path = "std::path::Path::is_file", reason = "Use System::is_file instead in ty crates" },
|
||||
]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.12.10"
|
||||
version = "0.12.9"
|
||||
publish = true
|
||||
authors = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
|
||||
@@ -5801,32 +5801,3 @@ fn future_annotations_preview_warning() {
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn up045_nested_optional_flatten_all() {
|
||||
let contents = "\
|
||||
from typing import Optional
|
||||
nested_optional: Optional[Optional[Optional[str]]] = None
|
||||
";
|
||||
|
||||
assert_cmd_snapshot!(
|
||||
Command::new(get_cargo_bin(BIN_NAME))
|
||||
.args(STDIN_BASE_OPTIONS)
|
||||
.args(["--select", "UP045", "--diff", "--target-version", "py312"])
|
||||
.arg("-")
|
||||
.pass_stdin(contents),
|
||||
@r"
|
||||
success: false
|
||||
exit_code: 1
|
||||
----- stdout -----
|
||||
@@ -1,2 +1,2 @@
|
||||
from typing import Optional
|
||||
-nested_optional: Optional[Optional[Optional[str]]] = None
|
||||
+nested_optional: str | None = None
|
||||
|
||||
|
||||
----- stderr -----
|
||||
Would fix 1 error.
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ salsa = { workspace = true }
|
||||
schemars = { workspace = true, optional = true }
|
||||
serde = { workspace = true, optional = true }
|
||||
serde_json = { workspace = true, optional = true }
|
||||
similar = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
tracing-subscriber = { workspace = true, optional = true }
|
||||
|
||||
@@ -325,11 +325,6 @@ impl Diagnostic {
|
||||
self.inner.fix.as_ref()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) fn fix_mut(&mut self) -> Option<&mut Fix> {
|
||||
Arc::make_mut(&mut self.inner).fix.as_mut()
|
||||
}
|
||||
|
||||
/// Set the fix for this diagnostic.
|
||||
pub fn set_fix(&mut self, fix: Fix) {
|
||||
debug_assert!(
|
||||
@@ -1299,10 +1294,6 @@ pub struct DisplayDiagnosticConfig {
|
||||
hide_severity: bool,
|
||||
/// Whether to show the availability of a fix in a diagnostic.
|
||||
show_fix_status: bool,
|
||||
/// Whether to show the diff for an available fix after the main diagnostic.
|
||||
///
|
||||
/// This currently only applies to `DiagnosticFormat::Full`.
|
||||
show_fix_diff: bool,
|
||||
/// The lowest applicability that should be shown when reporting diagnostics.
|
||||
fix_applicability: Applicability,
|
||||
}
|
||||
@@ -1350,14 +1341,6 @@ impl DisplayDiagnosticConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether to show a diff for an available fix after the main diagnostic.
|
||||
pub fn show_fix_diff(self, yes: bool) -> DisplayDiagnosticConfig {
|
||||
DisplayDiagnosticConfig {
|
||||
show_fix_diff: yes,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the lowest fix applicability that should be shown.
|
||||
///
|
||||
/// In other words, an applicability of `Safe` (the default) would suppress showing fixes or fix
|
||||
@@ -1381,7 +1364,6 @@ impl Default for DisplayDiagnosticConfig {
|
||||
preview: false,
|
||||
hide_severity: false,
|
||||
show_fix_status: false,
|
||||
show_fix_diff: false,
|
||||
fix_applicability: Applicability::Safe,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2622,13 +2622,6 @@ watermelon
|
||||
self.config = config;
|
||||
}
|
||||
|
||||
/// Show a diff for the fix when rendering.
|
||||
pub(super) fn show_fix_diff(&mut self, yes: bool) {
|
||||
let mut config = std::mem::take(&mut self.config);
|
||||
config = config.show_fix_diff(yes);
|
||||
self.config = config;
|
||||
}
|
||||
|
||||
/// The lowest fix applicability to show when rendering.
|
||||
pub(super) fn fix_applicability(&mut self, applicability: Applicability) {
|
||||
let mut config = std::mem::take(&mut self.config);
|
||||
|
||||
@@ -1,18 +1,7 @@
|
||||
use std::borrow::Cow;
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
use anstyle::Style;
|
||||
use ruff_notebook::NotebookIndex;
|
||||
use similar::{ChangeTag, TextDiff};
|
||||
|
||||
use ruff_annotate_snippets::Renderer as AnnotateRenderer;
|
||||
use ruff_diagnostics::{Applicability, Fix};
|
||||
use ruff_source_file::OneIndexed;
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
|
||||
use crate::diagnostic::render::{FileResolver, Resolved};
|
||||
use crate::diagnostic::stylesheet::{DiagnosticStylesheet, fmt_styled};
|
||||
use crate::diagnostic::{Diagnostic, DiagnosticSource, DisplayDiagnosticConfig};
|
||||
use crate::diagnostic::{Diagnostic, DisplayDiagnosticConfig, stylesheet::DiagnosticStylesheet};
|
||||
|
||||
pub(super) struct FullRenderer<'a> {
|
||||
resolver: &'a dyn FileResolver,
|
||||
@@ -59,245 +48,15 @@ impl<'a> FullRenderer<'a> {
|
||||
writeln!(f, "{}", renderer.render(diag.to_annotate()))?;
|
||||
}
|
||||
writeln!(f)?;
|
||||
|
||||
if self.config.show_fix_diff {
|
||||
if let Some(diff) = Diff::from_diagnostic(diag, &stylesheet, self.resolver) {
|
||||
writeln!(f, "{diff}")?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Renders a diff that shows the code fixes.
|
||||
///
|
||||
/// The implementation isn't fully fledged out and only used by tests. Before using in production, try
|
||||
/// * Improve layout
|
||||
/// * Replace tabs with spaces for a consistent experience across terminals
|
||||
/// * Replace zero-width whitespaces
|
||||
/// * Print a simpler diff if only a single line has changed
|
||||
/// * Compute the diff from the `Edit` because diff calculation is expensive.
|
||||
struct Diff<'a> {
|
||||
fix: &'a Fix,
|
||||
diagnostic_source: DiagnosticSource,
|
||||
notebook_index: Option<NotebookIndex>,
|
||||
stylesheet: &'a DiagnosticStylesheet,
|
||||
}
|
||||
|
||||
impl<'a> Diff<'a> {
|
||||
fn from_diagnostic(
|
||||
diagnostic: &'a Diagnostic,
|
||||
stylesheet: &'a DiagnosticStylesheet,
|
||||
resolver: &'a dyn FileResolver,
|
||||
) -> Option<Diff<'a>> {
|
||||
let file = &diagnostic.primary_span_ref()?.file;
|
||||
Some(Diff {
|
||||
fix: diagnostic.fix()?,
|
||||
diagnostic_source: file.diagnostic_source(resolver),
|
||||
notebook_index: resolver.notebook_index(file),
|
||||
stylesheet,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Diff<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let source_code = self.diagnostic_source.as_source_code();
|
||||
let source_text = source_code.text();
|
||||
|
||||
// Partition the source code into end offsets for each cell. If `self.notebook_index` is
|
||||
// `None`, indicating a regular script file, all the lines will be in one "cell" under the
|
||||
// `None` key.
|
||||
let cells = if let Some(notebook_index) = &self.notebook_index {
|
||||
let mut last_cell = OneIndexed::MIN;
|
||||
let mut cells: Vec<(Option<OneIndexed>, TextSize)> = Vec::new();
|
||||
for (row, cell) in notebook_index.iter() {
|
||||
if cell != last_cell {
|
||||
let offset = source_code.line_start(row);
|
||||
cells.push((Some(last_cell), offset));
|
||||
last_cell = cell;
|
||||
}
|
||||
}
|
||||
cells.push((Some(last_cell), source_text.text_len()));
|
||||
cells
|
||||
} else {
|
||||
vec![(None, source_text.text_len())]
|
||||
};
|
||||
|
||||
let message = match self.fix.applicability() {
|
||||
// TODO(zanieb): Adjust this messaging once it's user-facing
|
||||
Applicability::Safe => "Safe fix",
|
||||
Applicability::Unsafe => "Unsafe fix",
|
||||
Applicability::DisplayOnly => "Display-only fix",
|
||||
};
|
||||
|
||||
// TODO(brent) `stylesheet.separator` is cyan rather than blue, as we had before. I think
|
||||
// we're getting rid of this soon anyway, so I didn't think it was worth adding another
|
||||
// style to the stylesheet temporarily. The color doesn't appear at all in the snapshot
|
||||
// tests, which is the only place these are currently used.
|
||||
writeln!(f, "ℹ {}", fmt_styled(message, self.stylesheet.separator))?;
|
||||
|
||||
let mut last_end = TextSize::ZERO;
|
||||
for (cell, offset) in cells {
|
||||
let range = TextRange::new(last_end, offset);
|
||||
last_end = offset;
|
||||
let input = source_code.slice(range);
|
||||
|
||||
let mut output = String::with_capacity(input.len());
|
||||
let mut last_end = range.start();
|
||||
|
||||
let mut applied = 0;
|
||||
for edit in self.fix.edits() {
|
||||
if range.contains_range(edit.range()) {
|
||||
output.push_str(source_code.slice(TextRange::new(last_end, edit.start())));
|
||||
output.push_str(edit.content().unwrap_or_default());
|
||||
last_end = edit.end();
|
||||
applied += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// No edits were applied, so there's no need to diff.
|
||||
if applied == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
output.push_str(&source_text[usize::from(last_end)..usize::from(range.end())]);
|
||||
|
||||
let diff = TextDiff::from_lines(input, &output);
|
||||
|
||||
let (largest_old, largest_new) = diff
|
||||
.ops()
|
||||
.last()
|
||||
.map(|op| (op.old_range().start, op.new_range().start))
|
||||
.unwrap_or_default();
|
||||
|
||||
let digit_with = OneIndexed::from_zero_indexed(largest_new.max(largest_old)).digits();
|
||||
|
||||
if let Some(cell) = cell {
|
||||
// Room for 2 digits, 2 x 1 space before each digit, 1 space, and 1 `|`. This
|
||||
// centers the three colons on the pipe.
|
||||
writeln!(f, "{:>1$} cell {cell}", ":::", 2 * digit_with.get() + 4)?;
|
||||
}
|
||||
|
||||
for (idx, group) in diff.grouped_ops(3).iter().enumerate() {
|
||||
if idx > 0 {
|
||||
writeln!(f, "{:-^1$}", "-", 80)?;
|
||||
}
|
||||
for op in group {
|
||||
for change in diff.iter_inline_changes(op) {
|
||||
let sign = match change.tag() {
|
||||
ChangeTag::Delete => "-",
|
||||
ChangeTag::Insert => "+",
|
||||
ChangeTag::Equal => " ",
|
||||
};
|
||||
|
||||
let line_style = LineStyle::from(change.tag(), self.stylesheet);
|
||||
|
||||
let old_index = change.old_index().map(OneIndexed::from_zero_indexed);
|
||||
let new_index = change.new_index().map(OneIndexed::from_zero_indexed);
|
||||
|
||||
write!(
|
||||
f,
|
||||
"{} {} |{}",
|
||||
Line {
|
||||
index: old_index,
|
||||
width: digit_with,
|
||||
},
|
||||
Line {
|
||||
index: new_index,
|
||||
width: digit_with,
|
||||
},
|
||||
fmt_styled(line_style.apply_to(sign), self.stylesheet.emphasis),
|
||||
)?;
|
||||
|
||||
for (emphasized, value) in change.iter_strings_lossy() {
|
||||
let value = show_nonprinting(&value);
|
||||
if emphasized {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
fmt_styled(
|
||||
line_style.apply_to(&value),
|
||||
self.stylesheet.underline
|
||||
)
|
||||
)?;
|
||||
} else {
|
||||
write!(f, "{}", line_style.apply_to(&value))?;
|
||||
}
|
||||
}
|
||||
if change.missing_newline() {
|
||||
writeln!(f)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct LineStyle {
|
||||
style: Style,
|
||||
}
|
||||
|
||||
impl LineStyle {
|
||||
fn apply_to(&self, input: &str) -> impl std::fmt::Display {
|
||||
fmt_styled(input, self.style)
|
||||
}
|
||||
|
||||
fn from(value: ChangeTag, stylesheet: &DiagnosticStylesheet) -> LineStyle {
|
||||
match value {
|
||||
ChangeTag::Equal => LineStyle {
|
||||
style: stylesheet.none,
|
||||
},
|
||||
ChangeTag::Delete => LineStyle {
|
||||
style: stylesheet.deletion,
|
||||
},
|
||||
ChangeTag::Insert => LineStyle {
|
||||
style: stylesheet.insertion,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Line {
|
||||
index: Option<OneIndexed>,
|
||||
width: NonZeroUsize,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Line {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self.index {
|
||||
None => {
|
||||
for _ in 0..self.width.get() {
|
||||
f.write_str(" ")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Some(idx) => write!(f, "{:<width$}", idx, width = self.width.get()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn show_nonprinting(s: &str) -> Cow<'_, str> {
|
||||
if s.find(['\x07', '\x08', '\x1b', '\x7f']).is_some() {
|
||||
Cow::Owned(
|
||||
s.replace('\x07', "␇")
|
||||
.replace('\x08', "␈")
|
||||
.replace('\x1b', "␛")
|
||||
.replace('\x7f', "␡"),
|
||||
)
|
||||
} else {
|
||||
Cow::Borrowed(s)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ruff_diagnostics::{Applicability, Fix};
|
||||
use ruff_diagnostics::Applicability;
|
||||
use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||
|
||||
use crate::diagnostic::{
|
||||
@@ -698,107 +457,6 @@ print()
|
||||
");
|
||||
}
|
||||
|
||||
/// Test that we remap notebook cell line numbers in the diff as well as the main diagnostic.
|
||||
#[test]
|
||||
fn notebook_output_with_diff() {
|
||||
let (mut env, diagnostics) = create_notebook_diagnostics(DiagnosticFormat::Full);
|
||||
env.show_fix_diff(true);
|
||||
insta::assert_snapshot!(env.render_diagnostics(&diagnostics), @r"
|
||||
error[unused-import][*]: `os` imported but unused
|
||||
--> notebook.ipynb:cell 1:2:8
|
||||
|
|
||||
1 | # cell 1
|
||||
2 | import os
|
||||
| ^^
|
||||
|
|
||||
help: Remove unused import: `os`
|
||||
|
||||
ℹ Safe fix
|
||||
::: cell 1
|
||||
1 1 | # cell 1
|
||||
2 |-import os
|
||||
|
||||
error[unused-import][*]: `math` imported but unused
|
||||
--> notebook.ipynb:cell 2:2:8
|
||||
|
|
||||
1 | # cell 2
|
||||
2 | import math
|
||||
| ^^^^
|
||||
3 |
|
||||
4 | print('hello world')
|
||||
|
|
||||
help: Remove unused import: `math`
|
||||
|
||||
ℹ Safe fix
|
||||
::: cell 2
|
||||
1 1 | # cell 2
|
||||
2 |-import math
|
||||
3 2 |
|
||||
4 3 | print('hello world')
|
||||
|
||||
error[unused-variable]: Local variable `x` is assigned to but never used
|
||||
--> notebook.ipynb:cell 3:4:5
|
||||
|
|
||||
2 | def foo():
|
||||
3 | print()
|
||||
4 | x = 1
|
||||
| ^
|
||||
|
|
||||
help: Remove assignment to unused variable `x`
|
||||
|
||||
ℹ Unsafe fix
|
||||
::: cell 3
|
||||
1 1 | # cell 3
|
||||
2 2 | def foo():
|
||||
3 3 | print()
|
||||
4 |- x = 1
|
||||
5 4 |
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn notebook_output_with_diff_spanning_cells() {
|
||||
let (mut env, mut diagnostics) = create_notebook_diagnostics(DiagnosticFormat::Full);
|
||||
env.show_fix_diff(true);
|
||||
|
||||
// Move all of the edits from the later diagnostics to the first diagnostic to simulate a
|
||||
// single diagnostic with edits in different cells.
|
||||
let mut diagnostic = diagnostics.swap_remove(0);
|
||||
let fix = diagnostic.fix_mut().unwrap();
|
||||
let mut edits = fix.edits().to_vec();
|
||||
for diag in diagnostics {
|
||||
edits.extend_from_slice(diag.fix().unwrap().edits());
|
||||
}
|
||||
*fix = Fix::unsafe_edits(edits.remove(0), edits);
|
||||
|
||||
insta::assert_snapshot!(env.render(&diagnostic), @r"
|
||||
error[unused-import]: `os` imported but unused
|
||||
--> notebook.ipynb:cell 1:2:8
|
||||
|
|
||||
1 | # cell 1
|
||||
2 | import os
|
||||
| ^^
|
||||
|
|
||||
help: Remove unused import: `os`
|
||||
|
||||
ℹ Unsafe fix
|
||||
::: cell 1
|
||||
1 1 | # cell 1
|
||||
2 |-import os
|
||||
::: cell 2
|
||||
1 1 | # cell 2
|
||||
2 |-import math
|
||||
3 2 |
|
||||
4 3 | print('hello world')
|
||||
::: cell 3
|
||||
1 1 | # cell 3
|
||||
2 2 | def foo():
|
||||
3 3 | print()
|
||||
4 |- x = 1
|
||||
5 4 |
|
||||
");
|
||||
}
|
||||
|
||||
/// Carriage return (`\r`) is a valid line-ending in Python, so we should normalize this to a
|
||||
/// line feed (`\n`) for rendering. Otherwise we report a single long line for this case.
|
||||
#[test]
|
||||
|
||||
@@ -40,12 +40,9 @@ pub struct DiagnosticStylesheet {
|
||||
pub(crate) help: Style,
|
||||
pub(crate) line_no: Style,
|
||||
pub(crate) emphasis: Style,
|
||||
pub(crate) underline: Style,
|
||||
pub(crate) none: Style,
|
||||
pub(crate) separator: Style,
|
||||
pub(crate) secondary_code: Style,
|
||||
pub(crate) insertion: Style,
|
||||
pub(crate) deletion: Style,
|
||||
}
|
||||
|
||||
impl Default for DiagnosticStylesheet {
|
||||
@@ -66,12 +63,9 @@ impl DiagnosticStylesheet {
|
||||
help: AnsiColor::BrightCyan.on_default().effects(Effects::BOLD),
|
||||
line_no: bright_blue.effects(Effects::BOLD),
|
||||
emphasis: Style::new().effects(Effects::BOLD),
|
||||
underline: Style::new().effects(Effects::UNDERLINE),
|
||||
none: Style::new(),
|
||||
separator: AnsiColor::Cyan.on_default(),
|
||||
secondary_code: AnsiColor::Red.on_default().effects(Effects::BOLD),
|
||||
insertion: AnsiColor::Green.on_default(),
|
||||
deletion: AnsiColor::Red.on_default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,12 +78,9 @@ impl DiagnosticStylesheet {
|
||||
help: Style::new(),
|
||||
line_no: Style::new(),
|
||||
emphasis: Style::new(),
|
||||
underline: Style::new(),
|
||||
none: Style::new(),
|
||||
separator: Style::new(),
|
||||
secondary_code: Style::new(),
|
||||
insertion: Style::new(),
|
||||
deletion: Style::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
#![warn(
|
||||
clippy::disallowed_methods,
|
||||
reason = "Prefer System trait methods over std methods"
|
||||
)]
|
||||
|
||||
use crate::files::Files;
|
||||
use crate::system::System;
|
||||
use crate::vendored::VendoredFileSystem;
|
||||
@@ -70,10 +65,6 @@ pub trait Db: salsa::Database {
|
||||
/// to process work in parallel. For example, to index a directory or checking the files of a project.
|
||||
/// ty can still spawn more threads for other tasks, e.g. to wait for a Ctrl+C signal or
|
||||
/// watching the files for changes.
|
||||
#[expect(
|
||||
clippy::disallowed_methods,
|
||||
reason = "We don't have access to System here, but this is also only used by the CLI and the server which always run on a real system."
|
||||
)]
|
||||
pub fn max_parallelism() -> NonZeroUsize {
|
||||
std::env::var(EnvVars::TY_MAX_PARALLELISM)
|
||||
.or_else(|_| std::env::var(EnvVars::RAYON_NUM_THREADS))
|
||||
|
||||
@@ -92,14 +92,14 @@ impl ParsedModule {
|
||||
self.inner.store(None);
|
||||
}
|
||||
|
||||
/// Returns the pointer address of this [`ParsedModule`].
|
||||
/// Returns a pointer for this [`ParsedModule`].
|
||||
///
|
||||
/// The pointer uniquely identifies the module within the current Salsa revision,
|
||||
/// regardless of whether particular [`ParsedModuleRef`] instances are garbage collected.
|
||||
pub fn addr(&self) -> usize {
|
||||
pub fn as_ptr(&self) -> *const () {
|
||||
// Note that the outer `Arc` in `inner` is stable across garbage collection, while the inner
|
||||
// `Arc` within the `ArcSwap` may change.
|
||||
Arc::as_ptr(&self.inner).addr()
|
||||
Arc::as_ptr(&self.inner).cast()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,13 +202,9 @@ mod indexed {
|
||||
|
||||
/// Returns the node at the given index.
|
||||
pub fn get_by_index<'ast>(&'ast self, index: NodeIndex) -> AnyRootNodeRef<'ast> {
|
||||
let index = index
|
||||
.as_u32()
|
||||
.expect("attempted to access uninitialized `NodeIndex`");
|
||||
|
||||
// Note that this method restores the correct lifetime: the nodes are valid for as
|
||||
// long as the reference to `IndexedModule` is alive.
|
||||
self.index[index as usize]
|
||||
self.index[index.as_usize()]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +220,7 @@ mod indexed {
|
||||
T: HasNodeIndex + std::fmt::Debug,
|
||||
AnyRootNodeRef<'a>: From<&'a T>,
|
||||
{
|
||||
node.node_index().set(NodeIndex::from(self.index));
|
||||
node.node_index().set(self.index);
|
||||
self.nodes.push(AnyRootNodeRef::from(node));
|
||||
self.index += 1;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ pub type Result<T> = std::io::Result<T>;
|
||||
/// * File watching isn't supported.
|
||||
///
|
||||
/// Abstracting the system also enables tests to use a more efficient in-memory file system.
|
||||
pub trait System: Debug + Sync + Send {
|
||||
pub trait System: Debug {
|
||||
/// Reads the metadata of the file or directory at `path`.
|
||||
///
|
||||
/// This function will traverse symbolic links to query information about the destination file.
|
||||
@@ -197,8 +197,6 @@ pub trait System: Debug + Sync + Send {
|
||||
fn as_any(&self) -> &dyn std::any::Any;
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
|
||||
|
||||
fn dyn_clone(&self) -> Box<dyn System>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#![allow(clippy::disallowed_methods)]
|
||||
|
||||
use super::walk_directory::{
|
||||
self, DirectoryWalker, WalkDirectoryBuilder, WalkDirectoryConfiguration,
|
||||
WalkDirectoryVisitorBuilder, WalkState,
|
||||
@@ -257,10 +255,6 @@ impl System for OsSystem {
|
||||
fn env_var(&self, name: &str) -> std::result::Result<String, std::env::VarError> {
|
||||
std::env::var(name)
|
||||
}
|
||||
|
||||
fn dyn_clone(&self) -> Box<dyn System> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl OsSystem {
|
||||
|
||||
@@ -146,10 +146,6 @@ impl System for TestSystem {
|
||||
fn case_sensitivity(&self) -> CaseSensitivity {
|
||||
self.system().case_sensitivity()
|
||||
}
|
||||
|
||||
fn dyn_clone(&self) -> Box<dyn System> {
|
||||
Box::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TestSystem {
|
||||
@@ -398,13 +394,6 @@ impl System for InMemorySystem {
|
||||
fn case_sensitivity(&self) -> CaseSensitivity {
|
||||
CaseSensitivity::CaseSensitive
|
||||
}
|
||||
|
||||
fn dyn_clone(&self) -> Box<dyn System> {
|
||||
Box::new(Self {
|
||||
user_config_directory: Mutex::new(self.user_config_directory.lock().unwrap().clone()),
|
||||
memory_fs: self.memory_fs.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl WritableSystem for InMemorySystem {
|
||||
|
||||
@@ -13,7 +13,6 @@ license = { workspace = true }
|
||||
[dependencies]
|
||||
ty = { workspace = true }
|
||||
ty_project = { workspace = true, features = ["schemars"] }
|
||||
ty_python_semantic = { workspace = true }
|
||||
ty_static = { workspace = true }
|
||||
ruff = { workspace = true }
|
||||
ruff_formatter = { workspace = true }
|
||||
|
||||
@@ -52,7 +52,7 @@ pub(crate) fn main(args: &Args) -> Result<()> {
|
||||
}
|
||||
|
||||
fn generate_markdown() -> String {
|
||||
let registry = ty_python_semantic::default_lint_registry();
|
||||
let registry = &*ty_project::DEFAULT_LINT_REGISTRY;
|
||||
|
||||
let mut output = String::new();
|
||||
|
||||
|
||||
@@ -14,11 +14,8 @@ license = { workspace = true }
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
ruff_text_size = { workspace = true, features = ["get-size"] }
|
||||
ruff_text_size = { workspace = true }
|
||||
|
||||
get-size2 = { workspace = true }
|
||||
is-macro = { workspace = true }
|
||||
serde = { workspace = true, optional = true, features = [] }
|
||||
|
||||
[features]
|
||||
serde = ["dep:serde", "ruff_text_size/serde"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ruff_linter"
|
||||
version = "0.12.10"
|
||||
version = "0.12.9"
|
||||
publish = false
|
||||
authors = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
|
||||
@@ -13,11 +13,3 @@ Path("tmp/python").symlink_to("usr/bin/python", target_is_directory=True) # Ok
|
||||
fd = os.open(".", os.O_RDONLY)
|
||||
os.symlink("source.txt", "link.txt", dir_fd=fd) # Ok: dir_fd is not supported by pathlib
|
||||
os.close(fd)
|
||||
|
||||
os.symlink(src="usr/bin/python", dst="tmp/python", unknown=True)
|
||||
os.symlink("usr/bin/python", dst="tmp/python", target_is_directory=False)
|
||||
|
||||
os.symlink(src="usr/bin/python", dst="tmp/python", dir_fd=None)
|
||||
|
||||
os.symlink("usr/bin/python", dst="tmp/python", target_is_directory= True )
|
||||
os.symlink("usr/bin/python", dst="tmp/python", target_is_directory="nonboolean")
|
||||
|
||||
@@ -106,22 +106,4 @@ os.replace("src", "dst", src_dir_fd=1)
|
||||
os.replace("src", "dst", dst_dir_fd=2)
|
||||
|
||||
os.getcwd()
|
||||
os.getcwdb()
|
||||
|
||||
os.mkdir(path="directory")
|
||||
|
||||
os.mkdir(
|
||||
# comment 1
|
||||
"directory",
|
||||
mode=0o777
|
||||
)
|
||||
|
||||
os.mkdir("directory", mode=0o777, dir_fd=1)
|
||||
|
||||
os.makedirs("name", 0o777, exist_ok=False)
|
||||
|
||||
os.makedirs("name", 0o777, False)
|
||||
|
||||
os.makedirs(name="name", mode=0o777, exist_ok=False)
|
||||
|
||||
os.makedirs("name", unknown_kwarg=True)
|
||||
os.getcwdb()
|
||||
@@ -1,18 +0,0 @@
|
||||
from __future__ import nested_scopes, generators
|
||||
from __future__ import with_statement, unicode_literals
|
||||
|
||||
from __future__ import absolute_import, division
|
||||
from __future__ import generator_stop
|
||||
from __future__ import print_function, nested_scopes, generator_stop
|
||||
|
||||
print(with_statement)
|
||||
generators = 1
|
||||
|
||||
|
||||
class Foo():
|
||||
|
||||
def boo(self):
|
||||
print(division)
|
||||
|
||||
|
||||
__all__ = ["print_function", "generator_stop"]
|
||||
@@ -69,10 +69,3 @@ a7: OptionalTE[typing.NamedTuple] = None
|
||||
a8: typing_extensions.Optional[typing.NamedTuple] = None
|
||||
a9: "Optional[NamedTuple]" = None
|
||||
a10: Optional[NamedTupleTE] = None
|
||||
|
||||
|
||||
# Test for: https://github.com/astral-sh/ruff/issues/19746
|
||||
# Nested Optional types should be flattened
|
||||
nested_optional: Optional[Optional[str]] = None
|
||||
nested_optional_typing: typing.Optional[Optional[int]] = None
|
||||
triple_nested_optional: Optional[Optional[Optional[str]]] = None
|
||||
|
||||
@@ -118,10 +118,3 @@ def func():
|
||||
return lambda: value
|
||||
|
||||
defaultdict(constant_factory("<missing>"))
|
||||
|
||||
def func():
|
||||
defaultdict(default_factory=t"") # OK
|
||||
|
||||
|
||||
def func():
|
||||
defaultdict(default_factory=t"hello") # OK
|
||||
|
||||
@@ -102,8 +102,3 @@ deque("abc") # OK
|
||||
deque(b"abc") # OK
|
||||
deque(f"" "a") # OK
|
||||
deque(f"{x}" "") # OK
|
||||
|
||||
# https://github.com/astral-sh/ruff/issues/19951
|
||||
deque(t"")
|
||||
deque(t"" t"")
|
||||
deque(t"{""}") # OK
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
use ruff_python_ast::PythonVersion;
|
||||
use ruff_python_semantic::{Binding, ScopeKind};
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::codes::Rule;
|
||||
use crate::rules::{
|
||||
flake8_builtins, flake8_pyi, flake8_type_checking, flake8_unused_arguments, pep8_naming,
|
||||
pyflakes, pylint, pyupgrade, ruff,
|
||||
pyflakes, pylint, ruff,
|
||||
};
|
||||
|
||||
/// Run lint rules over all deferred scopes in the [`SemanticModel`].
|
||||
@@ -46,7 +45,6 @@ pub(crate) fn deferred_scopes(checker: &Checker) {
|
||||
Rule::UnusedStaticMethodArgument,
|
||||
Rule::UnusedUnpackedVariable,
|
||||
Rule::UnusedVariable,
|
||||
Rule::UnnecessaryFutureImport,
|
||||
]) {
|
||||
return;
|
||||
}
|
||||
@@ -226,11 +224,6 @@ pub(crate) fn deferred_scopes(checker: &Checker) {
|
||||
if checker.is_rule_enabled(Rule::UnusedImport) {
|
||||
pyflakes::rules::unused_import(checker, scope);
|
||||
}
|
||||
if checker.is_rule_enabled(Rule::UnnecessaryFutureImport) {
|
||||
if checker.target_version() >= PythonVersion::PY37 {
|
||||
pyupgrade::rules::unnecessary_future_import(checker, scope);
|
||||
}
|
||||
}
|
||||
|
||||
if checker.is_rule_enabled(Rule::ImportPrivateName) {
|
||||
pylint::rules::import_private_name(checker, scope);
|
||||
|
||||
@@ -1039,6 +1039,8 @@ pub(crate) fn expression(expr: &Expr, checker: &Checker) {
|
||||
flake8_simplify::rules::zip_dict_keys_and_values(checker, call);
|
||||
}
|
||||
if checker.any_rule_enabled(&[
|
||||
Rule::OsMkdir,
|
||||
Rule::OsMakedirs,
|
||||
Rule::OsStat,
|
||||
Rule::OsPathJoin,
|
||||
Rule::OsPathSplitext,
|
||||
@@ -1118,15 +1120,6 @@ pub(crate) fn expression(expr: &Expr, checker: &Checker) {
|
||||
if checker.is_rule_enabled(Rule::OsPathSamefile) {
|
||||
flake8_use_pathlib::rules::os_path_samefile(checker, call, segments);
|
||||
}
|
||||
if checker.is_rule_enabled(Rule::OsMkdir) {
|
||||
flake8_use_pathlib::rules::os_mkdir(checker, call, segments);
|
||||
}
|
||||
if checker.is_rule_enabled(Rule::OsMakedirs) {
|
||||
flake8_use_pathlib::rules::os_makedirs(checker, call, segments);
|
||||
}
|
||||
if checker.is_rule_enabled(Rule::OsSymlink) {
|
||||
flake8_use_pathlib::rules::os_symlink(checker, call, segments);
|
||||
}
|
||||
if checker.is_rule_enabled(Rule::PathConstructorCurrentDirectory) {
|
||||
flake8_use_pathlib::rules::path_constructor_current_directory(
|
||||
checker, call, segments,
|
||||
|
||||
@@ -728,6 +728,13 @@ pub(crate) fn statement(stmt: &Stmt, checker: &mut Checker) {
|
||||
pylint::rules::non_ascii_module_import(checker, alias);
|
||||
}
|
||||
}
|
||||
if checker.is_rule_enabled(Rule::UnnecessaryFutureImport) {
|
||||
if checker.target_version() >= PythonVersion::PY37 {
|
||||
if let Some("__future__") = module {
|
||||
pyupgrade::rules::unnecessary_future_import(checker, stmt, names);
|
||||
}
|
||||
}
|
||||
}
|
||||
if checker.is_rule_enabled(Rule::DeprecatedMockImport) {
|
||||
pyupgrade::rules::deprecated_mock_import(checker, stmt);
|
||||
}
|
||||
|
||||
@@ -921,8 +921,8 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
||||
// flake8-use-pathlib
|
||||
(Flake8UsePathlib, "100") => (RuleGroup::Stable, rules::flake8_use_pathlib::rules::OsPathAbspath),
|
||||
(Flake8UsePathlib, "101") => (RuleGroup::Stable, rules::flake8_use_pathlib::rules::OsChmod),
|
||||
(Flake8UsePathlib, "102") => (RuleGroup::Stable, rules::flake8_use_pathlib::rules::OsMkdir),
|
||||
(Flake8UsePathlib, "103") => (RuleGroup::Stable, rules::flake8_use_pathlib::rules::OsMakedirs),
|
||||
(Flake8UsePathlib, "102") => (RuleGroup::Stable, rules::flake8_use_pathlib::violations::OsMkdir),
|
||||
(Flake8UsePathlib, "103") => (RuleGroup::Stable, rules::flake8_use_pathlib::violations::OsMakedirs),
|
||||
(Flake8UsePathlib, "104") => (RuleGroup::Stable, rules::flake8_use_pathlib::rules::OsRename),
|
||||
(Flake8UsePathlib, "105") => (RuleGroup::Stable, rules::flake8_use_pathlib::rules::OsReplace),
|
||||
(Flake8UsePathlib, "106") => (RuleGroup::Stable, rules::flake8_use_pathlib::rules::OsRmdir),
|
||||
@@ -954,7 +954,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
||||
(Flake8UsePathlib, "207") => (RuleGroup::Stable, rules::flake8_use_pathlib::rules::Glob),
|
||||
(Flake8UsePathlib, "208") => (RuleGroup::Stable, rules::flake8_use_pathlib::violations::OsListdir),
|
||||
(Flake8UsePathlib, "210") => (RuleGroup::Stable, rules::flake8_use_pathlib::rules::InvalidPathlibWithSuffix),
|
||||
(Flake8UsePathlib, "211") => (RuleGroup::Preview, rules::flake8_use_pathlib::rules::OsSymlink),
|
||||
(Flake8UsePathlib, "211") => (RuleGroup::Preview, rules::flake8_use_pathlib::violations::OsSymlink),
|
||||
|
||||
// flake8-logging-format
|
||||
(Flake8LoggingFormat, "001") => (RuleGroup::Stable, rules::flake8_logging_format::violations::LoggingStringFormat),
|
||||
|
||||
202
crates/ruff_linter/src/message/diff.rs
Normal file
202
crates/ruff_linter/src/message/diff.rs
Normal file
@@ -0,0 +1,202 @@
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
use colored::{Color, ColoredString, Colorize, Styles};
|
||||
use similar::{ChangeTag, TextDiff};
|
||||
|
||||
use ruff_db::diagnostic::Diagnostic;
|
||||
use ruff_source_file::{OneIndexed, SourceFile};
|
||||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||
|
||||
use crate::text_helpers::ShowNonprinting;
|
||||
use crate::{Applicability, Fix};
|
||||
|
||||
/// Renders a diff that shows the code fixes.
|
||||
///
|
||||
/// The implementation isn't fully fledged out and only used by tests. Before using in production, try
|
||||
/// * Improve layout
|
||||
/// * Replace tabs with spaces for a consistent experience across terminals
|
||||
/// * Replace zero-width whitespaces
|
||||
/// * Print a simpler diff if only a single line has changed
|
||||
/// * Compute the diff from the [`Edit`] because diff calculation is expensive.
|
||||
pub(super) struct Diff<'a> {
|
||||
fix: &'a Fix,
|
||||
source_code: &'a SourceFile,
|
||||
}
|
||||
|
||||
impl<'a> Diff<'a> {
|
||||
pub(crate) fn from_message(message: &'a Diagnostic) -> Option<Diff<'a>> {
|
||||
message.fix().map(|fix| Diff {
|
||||
source_code: message.expect_ruff_source_file(),
|
||||
fix,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Diff<'_> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
// TODO(dhruvmanila): Add support for Notebook cells once it's user-facing
|
||||
let mut output = String::with_capacity(self.source_code.source_text().len());
|
||||
let mut last_end = TextSize::default();
|
||||
|
||||
for edit in self.fix.edits() {
|
||||
output.push_str(
|
||||
self.source_code
|
||||
.slice(TextRange::new(last_end, edit.start())),
|
||||
);
|
||||
output.push_str(edit.content().unwrap_or_default());
|
||||
last_end = edit.end();
|
||||
}
|
||||
|
||||
output.push_str(&self.source_code.source_text()[usize::from(last_end)..]);
|
||||
|
||||
let diff = TextDiff::from_lines(self.source_code.source_text(), &output);
|
||||
|
||||
let message = match self.fix.applicability() {
|
||||
// TODO(zanieb): Adjust this messaging once it's user-facing
|
||||
Applicability::Safe => "Safe fix",
|
||||
Applicability::Unsafe => "Unsafe fix",
|
||||
Applicability::DisplayOnly => "Display-only fix",
|
||||
};
|
||||
writeln!(f, "ℹ {}", message.blue())?;
|
||||
|
||||
let (largest_old, largest_new) = diff
|
||||
.ops()
|
||||
.last()
|
||||
.map(|op| (op.old_range().start, op.new_range().start))
|
||||
.unwrap_or_default();
|
||||
|
||||
let digit_with =
|
||||
calculate_print_width(OneIndexed::from_zero_indexed(largest_new.max(largest_old)));
|
||||
|
||||
for (idx, group) in diff.grouped_ops(3).iter().enumerate() {
|
||||
if idx > 0 {
|
||||
writeln!(f, "{:-^1$}", "-", 80)?;
|
||||
}
|
||||
for op in group {
|
||||
for change in diff.iter_inline_changes(op) {
|
||||
let sign = match change.tag() {
|
||||
ChangeTag::Delete => "-",
|
||||
ChangeTag::Insert => "+",
|
||||
ChangeTag::Equal => " ",
|
||||
};
|
||||
|
||||
let line_style = LineStyle::from(change.tag());
|
||||
|
||||
let old_index = change.old_index().map(OneIndexed::from_zero_indexed);
|
||||
let new_index = change.new_index().map(OneIndexed::from_zero_indexed);
|
||||
|
||||
write!(
|
||||
f,
|
||||
"{} {} |{}",
|
||||
Line {
|
||||
index: old_index,
|
||||
width: digit_with
|
||||
},
|
||||
Line {
|
||||
index: new_index,
|
||||
width: digit_with
|
||||
},
|
||||
line_style.apply_to(sign).bold()
|
||||
)?;
|
||||
|
||||
for (emphasized, value) in change.iter_strings_lossy() {
|
||||
let value = value.show_nonprinting();
|
||||
if emphasized {
|
||||
write!(f, "{}", line_style.apply_to(&value).underline().on_black())?;
|
||||
} else {
|
||||
write!(f, "{}", line_style.apply_to(&value))?;
|
||||
}
|
||||
}
|
||||
if change.missing_newline() {
|
||||
writeln!(f)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct LineStyle {
|
||||
fgcolor: Option<Color>,
|
||||
style: Option<Styles>,
|
||||
}
|
||||
|
||||
impl LineStyle {
|
||||
fn apply_to(&self, input: &str) -> ColoredString {
|
||||
let mut colored = ColoredString::from(input);
|
||||
if let Some(color) = self.fgcolor {
|
||||
colored = colored.color(color);
|
||||
}
|
||||
|
||||
if let Some(style) = self.style {
|
||||
match style {
|
||||
Styles::Clear => colored.clear(),
|
||||
Styles::Bold => colored.bold(),
|
||||
Styles::Dimmed => colored.dimmed(),
|
||||
Styles::Underline => colored.underline(),
|
||||
Styles::Reversed => colored.reversed(),
|
||||
Styles::Italic => colored.italic(),
|
||||
Styles::Blink => colored.blink(),
|
||||
Styles::Hidden => colored.hidden(),
|
||||
Styles::Strikethrough => colored.strikethrough(),
|
||||
}
|
||||
} else {
|
||||
colored
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ChangeTag> for LineStyle {
|
||||
fn from(value: ChangeTag) -> Self {
|
||||
match value {
|
||||
ChangeTag::Equal => LineStyle {
|
||||
fgcolor: None,
|
||||
style: Some(Styles::Dimmed),
|
||||
},
|
||||
ChangeTag::Delete => LineStyle {
|
||||
fgcolor: Some(Color::Red),
|
||||
style: None,
|
||||
},
|
||||
ChangeTag::Insert => LineStyle {
|
||||
fgcolor: Some(Color::Green),
|
||||
style: None,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Line {
|
||||
index: Option<OneIndexed>,
|
||||
width: NonZeroUsize,
|
||||
}
|
||||
|
||||
impl Display for Line {
|
||||
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
||||
match self.index {
|
||||
None => {
|
||||
for _ in 0..self.width.get() {
|
||||
f.write_str(" ")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Some(idx) => write!(f, "{:<width$}", idx, width = self.width.get()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Calculate the length of the string representation of `value`
|
||||
pub(super) fn calculate_print_width(mut value: OneIndexed) -> NonZeroUsize {
|
||||
const TEN: OneIndexed = OneIndexed::from_zero_indexed(9);
|
||||
|
||||
let mut width = OneIndexed::ONE;
|
||||
|
||||
while value >= TEN {
|
||||
value = OneIndexed::new(value.get() / 10).unwrap_or(OneIndexed::MIN);
|
||||
width = width.checked_add(1).unwrap();
|
||||
}
|
||||
|
||||
width
|
||||
}
|
||||
@@ -10,6 +10,7 @@ use ruff_notebook::NotebookIndex;
|
||||
use ruff_source_file::{LineColumn, OneIndexed};
|
||||
|
||||
use crate::fs::relativize_path;
|
||||
use crate::message::diff::calculate_print_width;
|
||||
use crate::message::{Emitter, EmitterContext};
|
||||
use crate::settings::types::UnsafeFixes;
|
||||
|
||||
@@ -52,8 +53,8 @@ impl Emitter for GroupedEmitter {
|
||||
max_column_length = max_column_length.max(message.start_location.column);
|
||||
}
|
||||
|
||||
let row_length = max_row_length.digits();
|
||||
let column_length = max_column_length.digits();
|
||||
let row_length = calculate_print_width(max_row_length);
|
||||
let column_length = calculate_print_width(max_column_length);
|
||||
|
||||
// Print the filename.
|
||||
writeln!(writer, "{}:", relativize_path(&*filename).underline())?;
|
||||
@@ -130,7 +131,8 @@ impl Display for DisplayGroupedMessage<'_> {
|
||||
write!(
|
||||
f,
|
||||
" {row_padding}",
|
||||
row_padding = " ".repeat(self.row_length.get() - start_location.line.digits().get())
|
||||
row_padding = " "
|
||||
.repeat(self.row_length.get() - calculate_print_width(start_location.line).get())
|
||||
)?;
|
||||
|
||||
// Check if we're working on a jupyter notebook and translate positions with cell accordingly
|
||||
@@ -157,8 +159,9 @@ impl Display for DisplayGroupedMessage<'_> {
|
||||
f,
|
||||
"{row}{sep}{col}{col_padding} {code_and_body}",
|
||||
sep = ":".cyan(),
|
||||
col_padding =
|
||||
" ".repeat(self.column_length.get() - start_location.column.digits().get()),
|
||||
col_padding = " ".repeat(
|
||||
self.column_length.get() - calculate_print_width(start_location.column).get()
|
||||
),
|
||||
code_and_body = RuleCodeAndBody {
|
||||
message,
|
||||
show_fix_status: self.show_fix_status,
|
||||
|
||||
@@ -21,6 +21,7 @@ pub use text::TextEmitter;
|
||||
use crate::Fix;
|
||||
use crate::registry::Rule;
|
||||
|
||||
mod diff;
|
||||
mod github;
|
||||
mod gitlab;
|
||||
mod grouped;
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
use std::io::Write;
|
||||
|
||||
use ruff_db::diagnostic::{
|
||||
Diagnostic, DiagnosticFormat, DisplayDiagnosticConfig, DisplayDiagnostics,
|
||||
};
|
||||
use ruff_db::diagnostic::{Diagnostic, DiagnosticFormat, DisplayDiagnosticConfig};
|
||||
|
||||
use crate::message::diff::Diff;
|
||||
use crate::message::{Emitter, EmitterContext};
|
||||
use crate::settings::types::UnsafeFixes;
|
||||
|
||||
pub struct TextEmitter {
|
||||
/// Whether to show the diff of a fix, for diagnostics that have a fix.
|
||||
///
|
||||
/// Note that this is not currently exposed in the CLI (#7352) and is only used in tests.
|
||||
show_fix_diff: bool,
|
||||
config: DisplayDiagnosticConfig,
|
||||
}
|
||||
|
||||
impl Default for TextEmitter {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
show_fix_diff: false,
|
||||
config: DisplayDiagnosticConfig::default()
|
||||
.format(DiagnosticFormat::Concise)
|
||||
.hide_severity(true)
|
||||
@@ -31,7 +35,7 @@ impl TextEmitter {
|
||||
|
||||
#[must_use]
|
||||
pub fn with_show_fix_diff(mut self, show_fix_diff: bool) -> Self {
|
||||
self.config = self.config.show_fix_diff(show_fix_diff);
|
||||
self.show_fix_diff = show_fix_diff;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -73,11 +77,15 @@ impl Emitter for TextEmitter {
|
||||
diagnostics: &[Diagnostic],
|
||||
context: &EmitterContext,
|
||||
) -> anyhow::Result<()> {
|
||||
write!(
|
||||
writer,
|
||||
"{}",
|
||||
DisplayDiagnostics::new(context, &self.config, diagnostics)
|
||||
)?;
|
||||
for message in diagnostics {
|
||||
write!(writer, "{}", message.display(context, &self.config))?;
|
||||
|
||||
if self.show_fix_diff {
|
||||
if let Some(diff) = Diff::from_message(message) {
|
||||
writeln!(writer, "{diff}")?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -159,21 +159,6 @@ pub(crate) const fn is_fix_os_getcwd_enabled(settings: &LinterSettings) -> bool
|
||||
settings.preview.is_enabled()
|
||||
}
|
||||
|
||||
// https://github.com/astral-sh/ruff/pull/19514
|
||||
pub(crate) const fn is_fix_os_mkdir_enabled(settings: &LinterSettings) -> bool {
|
||||
settings.preview.is_enabled()
|
||||
}
|
||||
|
||||
// https://github.com/astral-sh/ruff/pull/19514
|
||||
pub(crate) const fn is_fix_os_makedirs_enabled(settings: &LinterSettings) -> bool {
|
||||
settings.preview.is_enabled()
|
||||
}
|
||||
|
||||
// https://github.com/astral-sh/ruff/pull/20009
|
||||
pub(crate) const fn is_fix_os_symlink_enabled(settings: &LinterSettings) -> bool {
|
||||
settings.preview.is_enabled()
|
||||
}
|
||||
|
||||
// https://github.com/astral-sh/ruff/pull/11436
|
||||
// https://github.com/astral-sh/ruff/pull/11168
|
||||
pub(crate) const fn is_dunder_init_fix_unused_import_enabled(settings: &LinterSettings) -> bool {
|
||||
|
||||
@@ -137,7 +137,7 @@ impl AutoPythonType {
|
||||
let expr = Expr::Name(ast::ExprName {
|
||||
id: Name::from(binding),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
ctx: ExprContext::Load,
|
||||
});
|
||||
Some((expr, vec![no_return_edit]))
|
||||
@@ -204,7 +204,7 @@ fn type_expr(python_type: PythonType) -> Option<Expr> {
|
||||
Expr::Name(ast::ExprName {
|
||||
id: name.into(),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
ctx: ExprContext::Load,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -485,6 +485,9 @@ impl Violation for MissingReturnTypeClassMethod {
|
||||
/// Use instead:
|
||||
///
|
||||
/// ```python
|
||||
/// from typing import Any
|
||||
///
|
||||
///
|
||||
/// def foo(x: int): ...
|
||||
/// ```
|
||||
///
|
||||
|
||||
@@ -52,13 +52,13 @@ impl AlwaysFixableViolation for AssertFalse {
|
||||
fn assertion_error(msg: Option<&Expr>) -> Stmt {
|
||||
Stmt::Raise(ast::StmtRaise {
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
exc: Some(Box::new(Expr::Call(ast::ExprCall {
|
||||
func: Box::new(Expr::Name(ast::ExprName {
|
||||
id: "AssertionError".into(),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
})),
|
||||
arguments: Arguments {
|
||||
args: if let Some(msg) = msg {
|
||||
@@ -68,10 +68,10 @@ fn assertion_error(msg: Option<&Expr>) -> Stmt {
|
||||
},
|
||||
keywords: Box::from([]),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
},
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
}))),
|
||||
cause: None,
|
||||
})
|
||||
|
||||
@@ -113,7 +113,7 @@ fn type_pattern(elts: Vec<&Expr>) -> Expr {
|
||||
elts: elts.into_iter().cloned().collect(),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
parenthesized: true,
|
||||
}
|
||||
.into()
|
||||
|
||||
@@ -53,11 +53,11 @@ fn assignment(obj: &Expr, name: &str, value: &Expr, generator: Generator) -> Str
|
||||
attr: Identifier::new(name.to_string(), TextRange::default()),
|
||||
ctx: ExprContext::Store,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
})],
|
||||
value: Box::new(value.clone()),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
});
|
||||
generator.stmt(&stmt)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ mod tests {
|
||||
|
||||
use crate::registry::Rule;
|
||||
use crate::test::test_path;
|
||||
use crate::{assert_diagnostics, assert_diagnostics_diff, settings};
|
||||
use crate::{assert_diagnostics, settings};
|
||||
|
||||
#[test_case(Path::new("COM81.py"))]
|
||||
#[test_case(Path::new("COM81_syntax_error.py"))]
|
||||
@@ -31,24 +31,19 @@ mod tests {
|
||||
#[test_case(Path::new("COM81.py"))]
|
||||
#[test_case(Path::new("COM81_syntax_error.py"))]
|
||||
fn preview_rules(path: &Path) -> Result<()> {
|
||||
let snapshot = format!("preview_diff__{}", path.to_string_lossy());
|
||||
let rules = vec![
|
||||
Rule::MissingTrailingComma,
|
||||
Rule::TrailingCommaOnBareTuple,
|
||||
Rule::ProhibitedTrailingComma,
|
||||
];
|
||||
let settings_before = settings::LinterSettings::for_rules(rules.clone());
|
||||
let settings_after = settings::LinterSettings {
|
||||
preview: crate::settings::types::PreviewMode::Enabled,
|
||||
..settings::LinterSettings::for_rules(rules)
|
||||
};
|
||||
|
||||
assert_diagnostics_diff!(
|
||||
snapshot,
|
||||
let snapshot = format!("preview__{}", path.to_string_lossy());
|
||||
let diagnostics = test_path(
|
||||
Path::new("flake8_commas").join(path).as_path(),
|
||||
&settings_before,
|
||||
&settings_after
|
||||
);
|
||||
&settings::LinterSettings {
|
||||
preview: crate::settings::types::PreviewMode::Enabled,
|
||||
..settings::LinterSettings::for_rules(vec![
|
||||
Rule::MissingTrailingComma,
|
||||
Rule::TrailingCommaOnBareTuple,
|
||||
Rule::ProhibitedTrailingComma,
|
||||
])
|
||||
},
|
||||
)?;
|
||||
assert_diagnostics!(snapshot, diagnostics);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,33 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_commas/mod.rs
|
||||
---
|
||||
invalid-syntax: Starred expression cannot be used here
|
||||
--> COM81_syntax_error.py:3:5
|
||||
|
|
||||
1 | # Check for `flake8-commas` violation for a file containing syntax errors.
|
||||
2 | (
|
||||
3 | *args
|
||||
| ^^^^^
|
||||
4 | )
|
||||
|
|
||||
|
||||
invalid-syntax: Type parameter list cannot be empty
|
||||
--> COM81_syntax_error.py:6:9
|
||||
|
|
||||
4 | )
|
||||
5 |
|
||||
6 | def foo[(param1='test', param2='test',):
|
||||
| ^
|
||||
7 | pass
|
||||
|
|
||||
|
||||
COM819 Trailing comma prohibited
|
||||
--> COM81_syntax_error.py:6:38
|
||||
|
|
||||
4 | )
|
||||
5 |
|
||||
6 | def foo[(param1='test', param2='test',):
|
||||
| ^
|
||||
7 | pass
|
||||
|
|
||||
help: Remove trailing comma
|
||||
@@ -1,136 +0,0 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_commas/mod.rs
|
||||
---
|
||||
--- Linter settings ---
|
||||
-linter.preview = disabled
|
||||
+linter.preview = enabled
|
||||
|
||||
--- Summary ---
|
||||
Removed: 0
|
||||
Added: 6
|
||||
|
||||
--- Added ---
|
||||
COM812 [*] Trailing comma missing
|
||||
--> COM81.py:655:6
|
||||
|
|
||||
654 | type X[
|
||||
655 | T
|
||||
| ^
|
||||
656 | ] = T
|
||||
657 | def f[
|
||||
|
|
||||
help: Add trailing comma
|
||||
|
||||
ℹ Safe fix
|
||||
652 652 | }"""
|
||||
653 653 |
|
||||
654 654 | type X[
|
||||
655 |- T
|
||||
655 |+ T,
|
||||
656 656 | ] = T
|
||||
657 657 | def f[
|
||||
658 658 | T
|
||||
|
||||
|
||||
COM812 [*] Trailing comma missing
|
||||
--> COM81.py:658:6
|
||||
|
|
||||
656 | ] = T
|
||||
657 | def f[
|
||||
658 | T
|
||||
| ^
|
||||
659 | ](): pass
|
||||
660 | class C[
|
||||
|
|
||||
help: Add trailing comma
|
||||
|
||||
ℹ Safe fix
|
||||
655 655 | T
|
||||
656 656 | ] = T
|
||||
657 657 | def f[
|
||||
658 |- T
|
||||
658 |+ T,
|
||||
659 659 | ](): pass
|
||||
660 660 | class C[
|
||||
661 661 | T
|
||||
|
||||
|
||||
COM812 [*] Trailing comma missing
|
||||
--> COM81.py:661:6
|
||||
|
|
||||
659 | ](): pass
|
||||
660 | class C[
|
||||
661 | T
|
||||
| ^
|
||||
662 | ]: pass
|
||||
|
|
||||
help: Add trailing comma
|
||||
|
||||
ℹ Safe fix
|
||||
658 658 | T
|
||||
659 659 | ](): pass
|
||||
660 660 | class C[
|
||||
661 |- T
|
||||
661 |+ T,
|
||||
662 662 | ]: pass
|
||||
663 663 |
|
||||
664 664 | type X[T,] = T
|
||||
|
||||
|
||||
COM819 [*] Trailing comma prohibited
|
||||
--> COM81.py:664:9
|
||||
|
|
||||
662 | ]: pass
|
||||
663 |
|
||||
664 | type X[T,] = T
|
||||
| ^
|
||||
665 | def f[T,](): pass
|
||||
666 | class C[T,]: pass
|
||||
|
|
||||
help: Remove trailing comma
|
||||
|
||||
ℹ Safe fix
|
||||
661 661 | T
|
||||
662 662 | ]: pass
|
||||
663 663 |
|
||||
664 |-type X[T,] = T
|
||||
664 |+type X[T] = T
|
||||
665 665 | def f[T,](): pass
|
||||
666 666 | class C[T,]: pass
|
||||
|
||||
|
||||
COM819 [*] Trailing comma prohibited
|
||||
--> COM81.py:665:8
|
||||
|
|
||||
664 | type X[T,] = T
|
||||
665 | def f[T,](): pass
|
||||
| ^
|
||||
666 | class C[T,]: pass
|
||||
|
|
||||
help: Remove trailing comma
|
||||
|
||||
ℹ Safe fix
|
||||
662 662 | ]: pass
|
||||
663 663 |
|
||||
664 664 | type X[T,] = T
|
||||
665 |-def f[T,](): pass
|
||||
665 |+def f[T](): pass
|
||||
666 666 | class C[T,]: pass
|
||||
|
||||
|
||||
COM819 [*] Trailing comma prohibited
|
||||
--> COM81.py:666:10
|
||||
|
|
||||
664 | type X[T,] = T
|
||||
665 | def f[T,](): pass
|
||||
666 | class C[T,]: pass
|
||||
| ^
|
||||
|
|
||||
help: Remove trailing comma
|
||||
|
||||
ℹ Safe fix
|
||||
663 663 |
|
||||
664 664 | type X[T,] = T
|
||||
665 665 | def f[T,](): pass
|
||||
666 |-class C[T,]: pass
|
||||
666 |+class C[T]: pass
|
||||
@@ -1,10 +0,0 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_commas/mod.rs
|
||||
---
|
||||
--- Linter settings ---
|
||||
-linter.preview = disabled
|
||||
+linter.preview = enabled
|
||||
|
||||
--- Summary ---
|
||||
Removed: 0
|
||||
Added: 0
|
||||
@@ -209,18 +209,18 @@ fn fix_unnecessary_dict_comprehension(value: &Expr, generator: &Comprehension) -
|
||||
},
|
||||
keywords: Box::from([]),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
Expr::Call(ExprCall {
|
||||
func: Box::new(Expr::Name(ExprName {
|
||||
id: "dict.fromkeys".into(),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
})),
|
||||
arguments: args,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -178,21 +178,21 @@ pub(crate) fn multiple_starts_ends_with(checker: &Checker, expr: &Expr) {
|
||||
.collect(),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
parenthesized: true,
|
||||
});
|
||||
let node1 = Expr::Name(ast::ExprName {
|
||||
id: arg_name.into(),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
});
|
||||
let node2 = Expr::Attribute(ast::ExprAttribute {
|
||||
value: Box::new(node1),
|
||||
attr: Identifier::new(attr_name.to_string(), TextRange::default()),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
});
|
||||
let node3 = Expr::Call(ast::ExprCall {
|
||||
func: Box::new(node2),
|
||||
@@ -200,10 +200,10 @@ pub(crate) fn multiple_starts_ends_with(checker: &Checker, expr: &Expr) {
|
||||
args: Box::from([node]),
|
||||
keywords: Box::from([]),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
},
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
});
|
||||
let call = node3;
|
||||
|
||||
@@ -223,7 +223,7 @@ pub(crate) fn multiple_starts_ends_with(checker: &Checker, expr: &Expr) {
|
||||
})
|
||||
.collect(),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
});
|
||||
let bool_op = node;
|
||||
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
|
||||
|
||||
@@ -92,14 +92,14 @@ pub(crate) fn duplicate_literal_member<'a>(checker: &Checker, expr: &'a Expr) {
|
||||
Expr::Tuple(ast::ExprTuple {
|
||||
elts: unique_nodes.into_iter().cloned().collect(),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
ctx: ExprContext::Load,
|
||||
parenthesized: false,
|
||||
})
|
||||
}),
|
||||
value: subscript.value.clone(),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
ctx: ExprContext::Load,
|
||||
});
|
||||
let fix = Fix::applicable_edit(
|
||||
|
||||
@@ -187,7 +187,7 @@ fn generate_pep604_fix(
|
||||
op: Operator::BitOr,
|
||||
right: Box::new(right.clone()),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
}))
|
||||
} else {
|
||||
Some(right.clone())
|
||||
@@ -202,7 +202,7 @@ fn generate_pep604_fix(
|
||||
}
|
||||
|
||||
static VIRTUAL_NONE_LITERAL: Expr = Expr::NoneLiteral(ExprNoneLiteral {
|
||||
node_index: AtomicNodeIndex::NONE,
|
||||
node_index: AtomicNodeIndex::dummy(),
|
||||
range: TextRange::new(TextSize::new(0), TextSize::new(0)),
|
||||
});
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ use crate::{checkers::ast::Checker, fix};
|
||||
/// statement has no effect and should be omitted.
|
||||
///
|
||||
/// ## References
|
||||
/// - [Typing Style Guide](https://typing.python.org/en/latest/guides/writing_stubs.html#language-features)
|
||||
/// - [Static Typing with Python: Type Stubs](https://typing.python.org/en/latest/source/stubs.html)
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct FutureAnnotationsInStub;
|
||||
|
||||
|
||||
@@ -133,17 +133,17 @@ fn generate_union_fix(
|
||||
// Construct the expression as `Subscript[typing.Union, Tuple[expr, [expr, ...]]]`
|
||||
let new_expr = Expr::Subscript(ExprSubscript {
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
value: Box::new(Expr::Name(ExprName {
|
||||
id: Name::new(binding),
|
||||
ctx: ExprContext::Store,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
})),
|
||||
slice: Box::new(Expr::Tuple(ExprTuple {
|
||||
elts: nodes.into_iter().cloned().collect(),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
ctx: ExprContext::Load,
|
||||
parenthesized: false,
|
||||
})),
|
||||
|
||||
@@ -205,13 +205,13 @@ fn create_fix(
|
||||
let new_literal_expr = Expr::Subscript(ast::ExprSubscript {
|
||||
value: Box::new(literal_subscript.clone()),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
ctx: ExprContext::Load,
|
||||
slice: Box::new(if literal_elements.len() > 1 {
|
||||
Expr::Tuple(ast::ExprTuple {
|
||||
elts: literal_elements.into_iter().cloned().collect(),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
ctx: ExprContext::Load,
|
||||
parenthesized: true,
|
||||
})
|
||||
@@ -235,7 +235,7 @@ fn create_fix(
|
||||
UnionKind::BitOr => {
|
||||
let none_expr = Expr::NoneLiteral(ExprNoneLiteral {
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
});
|
||||
let union_expr = pep_604_union(&[new_literal_expr, none_expr]);
|
||||
let content = checker.generator().expr(&union_expr);
|
||||
|
||||
@@ -261,7 +261,7 @@ fn generate_pep604_fix(
|
||||
op: Operator::BitOr,
|
||||
right: Box::new(right.clone()),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
}))
|
||||
} else {
|
||||
Some(right.clone())
|
||||
|
||||
@@ -140,12 +140,12 @@ pub(crate) fn unnecessary_literal_union<'a>(checker: &Checker, expr: &'a Expr) {
|
||||
slice: Box::new(Expr::Tuple(ast::ExprTuple {
|
||||
elts: literal_exprs.into_iter().cloned().collect(),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
ctx: ExprContext::Load,
|
||||
parenthesized: true,
|
||||
})),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
ctx: ExprContext::Load,
|
||||
});
|
||||
|
||||
@@ -164,12 +164,12 @@ pub(crate) fn unnecessary_literal_union<'a>(checker: &Checker, expr: &'a Expr) {
|
||||
slice: Box::new(Expr::Tuple(ast::ExprTuple {
|
||||
elts,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
ctx: ExprContext::Load,
|
||||
parenthesized: true,
|
||||
})),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
ctx: ExprContext::Load,
|
||||
}))
|
||||
} else {
|
||||
|
||||
@@ -134,12 +134,12 @@ pub(crate) fn unnecessary_type_union<'a>(checker: &Checker, union: &'a Expr) {
|
||||
id: Name::new_static("type"),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
})),
|
||||
slice: Box::new(pep_604_union(&elts)),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
});
|
||||
|
||||
if other_exprs.is_empty() {
|
||||
@@ -159,7 +159,7 @@ pub(crate) fn unnecessary_type_union<'a>(checker: &Checker, union: &'a Expr) {
|
||||
id: Name::new_static("type"),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
})),
|
||||
slice: Box::new(Expr::Subscript(ast::ExprSubscript {
|
||||
value: subscript.value.clone(),
|
||||
@@ -171,22 +171,22 @@ pub(crate) fn unnecessary_type_union<'a>(checker: &Checker, union: &'a Expr) {
|
||||
id: type_member,
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
parenthesized: true,
|
||||
})),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
})),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
});
|
||||
|
||||
if other_exprs.is_empty() {
|
||||
@@ -202,12 +202,12 @@ pub(crate) fn unnecessary_type_union<'a>(checker: &Checker, union: &'a Expr) {
|
||||
elts: exprs.into_iter().cloned().collect(),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
parenthesized: true,
|
||||
})),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
});
|
||||
|
||||
checker.generator().expr(&union)
|
||||
|
||||
@@ -301,7 +301,7 @@ fn elts_to_csv(elts: &[Expr], generator: Generator, flags: StringLiteralFlags) -
|
||||
})
|
||||
.into_boxed_str(),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
flags,
|
||||
});
|
||||
Some(generator.expr(&node))
|
||||
@@ -367,14 +367,14 @@ fn check_names(checker: &Checker, call: &ExprCall, expr: &Expr, argvalues: &Expr
|
||||
Expr::from(ast::StringLiteral {
|
||||
value: Box::from(*name),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
flags: checker.default_string_flags(),
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
parenthesized: true,
|
||||
});
|
||||
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
|
||||
@@ -404,14 +404,14 @@ fn check_names(checker: &Checker, call: &ExprCall, expr: &Expr, argvalues: &Expr
|
||||
Expr::from(ast::StringLiteral {
|
||||
value: Box::from(*name),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
flags: checker.default_string_flags(),
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
});
|
||||
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
|
||||
checker.generator().expr(&node),
|
||||
@@ -440,7 +440,7 @@ fn check_names(checker: &Checker, call: &ExprCall, expr: &Expr, argvalues: &Expr
|
||||
elts: elts.clone(),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
});
|
||||
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
|
||||
checker.generator().expr(&node),
|
||||
@@ -485,7 +485,7 @@ fn check_names(checker: &Checker, call: &ExprCall, expr: &Expr, argvalues: &Expr
|
||||
elts: elts.clone(),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
parenthesized: true,
|
||||
});
|
||||
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
|
||||
|
||||
@@ -166,7 +166,7 @@ fn assert(expr: &Expr, msg: Option<&Expr>) -> Stmt {
|
||||
test: Box::new(expr.clone()),
|
||||
msg: msg.map(|msg| Box::new(msg.clone())),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ fn compare(left: &Expr, cmp_op: CmpOp, right: &Expr) -> Expr {
|
||||
ops: Box::from([cmp_op]),
|
||||
comparators: Box::from([right.clone()]),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ impl UnittestAssert {
|
||||
op: UnaryOp::Not,
|
||||
operand: Box::new(expr.clone()),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
}),
|
||||
msg,
|
||||
)
|
||||
@@ -370,7 +370,7 @@ impl UnittestAssert {
|
||||
};
|
||||
let node = Expr::NoneLiteral(ast::ExprNoneLiteral {
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
});
|
||||
let expr = compare(expr, cmp_op, &node);
|
||||
Ok(assert(&expr, msg))
|
||||
@@ -387,7 +387,7 @@ impl UnittestAssert {
|
||||
id: Name::new_static("isinstance"),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let node1 = ast::ExprCall {
|
||||
func: Box::new(node.into()),
|
||||
@@ -395,10 +395,10 @@ impl UnittestAssert {
|
||||
args: Box::from([(**obj).clone(), (**cls).clone()]),
|
||||
keywords: Box::from([]),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
},
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let isinstance = node1.into();
|
||||
if matches!(self, UnittestAssert::IsInstance) {
|
||||
@@ -408,7 +408,7 @@ impl UnittestAssert {
|
||||
op: UnaryOp::Not,
|
||||
operand: Box::new(isinstance),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let expr = node.into();
|
||||
Ok(assert(&expr, msg))
|
||||
@@ -429,14 +429,14 @@ impl UnittestAssert {
|
||||
id: Name::new_static("re"),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let node1 = ast::ExprAttribute {
|
||||
value: Box::new(node.into()),
|
||||
attr: Identifier::new("search".to_string(), TextRange::default()),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let node2 = ast::ExprCall {
|
||||
func: Box::new(node1.into()),
|
||||
@@ -444,10 +444,10 @@ impl UnittestAssert {
|
||||
args: Box::from([(**regex).clone(), (**text).clone()]),
|
||||
keywords: Box::from([]),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
},
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let re_search = node2.into();
|
||||
if matches!(self, UnittestAssert::Regex | UnittestAssert::RegexpMatches) {
|
||||
@@ -457,7 +457,7 @@ impl UnittestAssert {
|
||||
op: UnaryOp::Not,
|
||||
operand: Box::new(re_search),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
Ok(assert(&node.into(), msg))
|
||||
}
|
||||
|
||||
@@ -421,7 +421,7 @@ pub(crate) fn duplicate_isinstance_call(checker: &Checker, expr: &Expr) {
|
||||
.collect(),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
parenthesized: true,
|
||||
};
|
||||
let isinstance_call = ast::ExprCall {
|
||||
@@ -430,7 +430,7 @@ pub(crate) fn duplicate_isinstance_call(checker: &Checker, expr: &Expr) {
|
||||
id: Name::new_static("isinstance"),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
@@ -438,10 +438,10 @@ pub(crate) fn duplicate_isinstance_call(checker: &Checker, expr: &Expr) {
|
||||
args: Box::from([target.clone(), tuple.into()]),
|
||||
keywords: Box::from([]),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
},
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
}
|
||||
.into();
|
||||
|
||||
@@ -458,7 +458,7 @@ pub(crate) fn duplicate_isinstance_call(checker: &Checker, expr: &Expr) {
|
||||
.chain(after)
|
||||
.collect(),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
}
|
||||
.into();
|
||||
let fixed_source = checker.generator().expr(&bool_op);
|
||||
@@ -552,21 +552,21 @@ pub(crate) fn compare_with_tuple(checker: &Checker, expr: &Expr) {
|
||||
elts: comparators.into_iter().cloned().collect(),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
parenthesized: true,
|
||||
};
|
||||
let node1 = ast::ExprName {
|
||||
id: id.clone(),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let node2 = ast::ExprCompare {
|
||||
left: Box::new(node1.into()),
|
||||
ops: Box::from([CmpOp::In]),
|
||||
comparators: Box::from([node.into()]),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let in_expr = node2.into();
|
||||
let mut diagnostic = checker.report_diagnostic(
|
||||
@@ -589,7 +589,7 @@ pub(crate) fn compare_with_tuple(checker: &Checker, expr: &Expr) {
|
||||
op: BoolOp::Or,
|
||||
values: iter::once(in_expr).chain(unmatched).collect(),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
node.into()
|
||||
};
|
||||
|
||||
@@ -232,7 +232,7 @@ fn check_os_environ_subscript(checker: &Checker, expr: &Expr) {
|
||||
}
|
||||
}),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let new_env_var = node.into();
|
||||
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
|
||||
|
||||
@@ -188,7 +188,7 @@ pub(crate) fn if_expr_with_true_false(
|
||||
id: Name::new_static("bool"),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
@@ -196,10 +196,10 @@ pub(crate) fn if_expr_with_true_false(
|
||||
args: Box::from([test.clone()]),
|
||||
keywords: Box::from([]),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
},
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
@@ -227,7 +227,7 @@ pub(crate) fn if_expr_with_false_true(
|
||||
op: UnaryOp::Not,
|
||||
operand: Box::new(test.clone()),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
}
|
||||
.into(),
|
||||
),
|
||||
@@ -282,7 +282,7 @@ pub(crate) fn twisted_arms_in_ifexpr(
|
||||
body: Box::new(node1),
|
||||
orelse: Box::new(node),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
|
||||
checker.generator().expr(&node3.into()),
|
||||
|
||||
@@ -186,7 +186,7 @@ pub(crate) fn negation_with_equal_op(checker: &Checker, expr: &Expr, op: UnaryOp
|
||||
ops: Box::from([CmpOp::NotEq]),
|
||||
comparators: comparators.clone(),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
|
||||
checker.generator().expr(&node.into()),
|
||||
@@ -242,7 +242,7 @@ pub(crate) fn negation_with_not_equal_op(
|
||||
ops: Box::from([CmpOp::Eq]),
|
||||
comparators: comparators.clone(),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
|
||||
checker.generator().expr(&node.into()),
|
||||
@@ -284,7 +284,7 @@ pub(crate) fn double_negation(checker: &Checker, expr: &Expr, op: UnaryOp, opera
|
||||
id: Name::new_static("bool"),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let node1 = ast::ExprCall {
|
||||
func: Box::new(node.into()),
|
||||
@@ -292,10 +292,10 @@ pub(crate) fn double_negation(checker: &Checker, expr: &Expr, op: UnaryOp, opera
|
||||
args: Box::from([*operand.clone()]),
|
||||
keywords: Box::from([]),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
},
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
|
||||
checker.generator().expr(&node1.into()),
|
||||
|
||||
@@ -190,7 +190,7 @@ pub(crate) fn if_else_block_instead_of_dict_get(checker: &Checker, stmt_if: &ast
|
||||
attr: Identifier::new("get".to_string(), TextRange::default()),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let node3 = ast::ExprCall {
|
||||
func: Box::new(node2.into()),
|
||||
@@ -198,17 +198,17 @@ pub(crate) fn if_else_block_instead_of_dict_get(checker: &Checker, stmt_if: &ast
|
||||
args: Box::from([node1, node]),
|
||||
keywords: Box::from([]),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
},
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let node4 = expected_var.clone();
|
||||
let node5 = ast::StmtAssign {
|
||||
targets: vec![node4],
|
||||
value: Box::new(node3.into()),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let contents = checker.generator().stmt(&node5.into());
|
||||
|
||||
@@ -299,7 +299,7 @@ pub(crate) fn if_exp_instead_of_dict_get(
|
||||
attr: Identifier::new("get".to_string(), TextRange::default()),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let fixed_node = ast::ExprCall {
|
||||
func: Box::new(dict_get_node.into()),
|
||||
@@ -307,10 +307,10 @@ pub(crate) fn if_exp_instead_of_dict_get(
|
||||
args: Box::from([dict_key_node, default_value_node]),
|
||||
keywords: Box::from([]),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
},
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
|
||||
let contents = checker.generator().expr(&fixed_node.into());
|
||||
|
||||
@@ -266,13 +266,13 @@ fn assignment_ternary(
|
||||
body: Box::new(body_value.clone()),
|
||||
orelse: Box::new(orelse_value.clone()),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let node1 = ast::StmtAssign {
|
||||
targets: vec![target_var.clone()],
|
||||
value: Box::new(node.into()),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
node1.into()
|
||||
}
|
||||
@@ -282,13 +282,13 @@ fn assignment_binary_and(target_var: &Expr, left_value: &Expr, right_value: &Exp
|
||||
op: BoolOp::And,
|
||||
values: vec![left_value.clone(), right_value.clone()],
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let node1 = ast::StmtAssign {
|
||||
targets: vec![target_var.clone()],
|
||||
value: Box::new(node.into()),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
node1.into()
|
||||
}
|
||||
@@ -296,12 +296,12 @@ fn assignment_binary_and(target_var: &Expr, left_value: &Expr, right_value: &Exp
|
||||
fn assignment_binary_or(target_var: &Expr, left_value: &Expr, right_value: &Expr) -> Stmt {
|
||||
(ast::StmtAssign {
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
targets: vec![target_var.clone()],
|
||||
value: Box::new(
|
||||
(ast::ExprBoolOp {
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
op: BoolOp::Or,
|
||||
values: vec![left_value.clone(), right_value.clone()],
|
||||
})
|
||||
|
||||
@@ -256,7 +256,7 @@ pub(crate) fn needless_bool(checker: &Checker, stmt: &Stmt) {
|
||||
left: left.clone(),
|
||||
comparators: Box::new([right.clone()]),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ pub(crate) fn needless_bool(checker: &Checker, stmt: &Stmt) {
|
||||
op: ast::UnaryOp::Not,
|
||||
operand: Box::new(if_test.clone()),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
})),
|
||||
}
|
||||
} else if if_test.is_compare_expr() {
|
||||
@@ -277,7 +277,7 @@ pub(crate) fn needless_bool(checker: &Checker, stmt: &Stmt) {
|
||||
id: Name::new_static("bool"),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let call_node = ast::ExprCall {
|
||||
func: Box::new(func_node.into()),
|
||||
@@ -285,10 +285,10 @@ pub(crate) fn needless_bool(checker: &Checker, stmt: &Stmt) {
|
||||
args: Box::from([if_test.clone()]),
|
||||
keywords: Box::from([]),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
},
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
Some(Expr::Call(call_node))
|
||||
} else {
|
||||
@@ -301,7 +301,7 @@ pub(crate) fn needless_bool(checker: &Checker, stmt: &Stmt) {
|
||||
Stmt::Return(ast::StmtReturn {
|
||||
value: Some(Box::new(expr.clone())),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
@@ -165,7 +165,7 @@ pub(crate) fn convert_for_loop_to_any_all(checker: &Checker, stmt: &Stmt) {
|
||||
ops: Box::from([op]),
|
||||
comparators: Box::from([comparator.clone()]),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
node.into()
|
||||
} else {
|
||||
@@ -173,7 +173,7 @@ pub(crate) fn convert_for_loop_to_any_all(checker: &Checker, stmt: &Stmt) {
|
||||
op: UnaryOp::Not,
|
||||
operand: Box::new(loop_.test.clone()),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
node.into()
|
||||
}
|
||||
@@ -182,7 +182,7 @@ pub(crate) fn convert_for_loop_to_any_all(checker: &Checker, stmt: &Stmt) {
|
||||
op: UnaryOp::Not,
|
||||
operand: Box::new(loop_.test.clone()),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
node.into()
|
||||
}
|
||||
@@ -406,17 +406,17 @@ fn return_stmt(id: Name, test: &Expr, target: &Expr, iter: &Expr, generator: Gen
|
||||
ifs: vec![],
|
||||
is_async: false,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
}],
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
parenthesized: false,
|
||||
};
|
||||
let node1 = ast::ExprName {
|
||||
id,
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let node2 = ast::ExprCall {
|
||||
func: Box::new(node1.into()),
|
||||
@@ -424,15 +424,15 @@ fn return_stmt(id: Name, test: &Expr, target: &Expr, iter: &Expr, generator: Gen
|
||||
args: Box::from([node.into()]),
|
||||
keywords: Box::from([]),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
},
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let node3 = ast::StmtReturn {
|
||||
value: Some(Box::new(node2.into())),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
generator.stmt(&node3.into())
|
||||
}
|
||||
|
||||
@@ -163,14 +163,14 @@ fn construct_replacement(elts: &[&str], flags: StringLiteralFlags) -> Expr {
|
||||
Expr::from(StringLiteral {
|
||||
value: Box::from(*elt),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
flags: element_flags,
|
||||
})
|
||||
})
|
||||
.collect(),
|
||||
ctx: ExprContext::Load,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ fn fix_banned_relative_import(
|
||||
names: names.clone(),
|
||||
level: 0,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
let content = generator.stmt(&node.into());
|
||||
Some(Fix::unsafe_edit(Edit::range_replacement(
|
||||
|
||||
@@ -436,7 +436,7 @@ impl<'a> QuoteAnnotator<'a> {
|
||||
let annotation = subgenerator.expr(&expr_without_forward_references);
|
||||
generator.expr(&Expr::from(ast::StringLiteral {
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
value: annotation.into_boxed_str(),
|
||||
flags: self.flags,
|
||||
}))
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
use ruff_python_ast::{self as ast, Expr, ExprCall};
|
||||
use ruff_python_semantic::{SemanticModel, analyze::typing};
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::importer::ImportRequest;
|
||||
use crate::{Applicability, Edit, Fix, Violation};
|
||||
use ruff_python_ast::{self as ast, Expr, ExprCall};
|
||||
use ruff_python_semantic::{SemanticModel, analyze::typing};
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
pub(crate) fn is_keyword_only_argument_non_default(arguments: &ast::Arguments, name: &str) -> bool {
|
||||
arguments
|
||||
@@ -184,17 +183,3 @@ pub(crate) fn check_os_pathlib_two_arg_calls(
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn has_unknown_keywords_or_starred_expr(
|
||||
arguments: &ast::Arguments,
|
||||
allowed: &[&str],
|
||||
) -> bool {
|
||||
if arguments.args.iter().any(Expr::is_starred_expr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
arguments.keywords.iter().any(|kw| match &kw.arg {
|
||||
Some(arg) => !allowed.contains(&arg.as_str()),
|
||||
None => true,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -129,7 +129,6 @@ mod tests {
|
||||
#[test_case(Rule::OsPathGetatime, Path::new("PTH203.py"))]
|
||||
#[test_case(Rule::OsPathGetmtime, Path::new("PTH204.py"))]
|
||||
#[test_case(Rule::OsPathGetctime, Path::new("PTH205.py"))]
|
||||
#[test_case(Rule::OsSymlink, Path::new("PTH211.py"))]
|
||||
fn preview_flake8_use_pathlib(rule_code: Rule, path: &Path) -> Result<()> {
|
||||
let snapshot = format!(
|
||||
"preview__{}_{}",
|
||||
|
||||
@@ -2,8 +2,6 @@ pub(crate) use glob_rule::*;
|
||||
pub(crate) use invalid_pathlib_with_suffix::*;
|
||||
pub(crate) use os_chmod::*;
|
||||
pub(crate) use os_getcwd::*;
|
||||
pub(crate) use os_makedirs::*;
|
||||
pub(crate) use os_mkdir::*;
|
||||
pub(crate) use os_path_abspath::*;
|
||||
pub(crate) use os_path_basename::*;
|
||||
pub(crate) use os_path_dirname::*;
|
||||
@@ -24,7 +22,6 @@ pub(crate) use os_rename::*;
|
||||
pub(crate) use os_replace::*;
|
||||
pub(crate) use os_rmdir::*;
|
||||
pub(crate) use os_sep_split::*;
|
||||
pub(crate) use os_symlink::*;
|
||||
pub(crate) use os_unlink::*;
|
||||
pub(crate) use path_constructor_current_directory::*;
|
||||
pub(crate) use replaceable_by_pathlib::*;
|
||||
@@ -33,8 +30,6 @@ mod glob_rule;
|
||||
mod invalid_pathlib_with_suffix;
|
||||
mod os_chmod;
|
||||
mod os_getcwd;
|
||||
mod os_makedirs;
|
||||
mod os_mkdir;
|
||||
mod os_path_abspath;
|
||||
mod os_path_basename;
|
||||
mod os_path_dirname;
|
||||
@@ -55,7 +50,6 @@ mod os_rename;
|
||||
mod os_replace;
|
||||
mod os_rmdir;
|
||||
mod os_sep_split;
|
||||
mod os_symlink;
|
||||
mod os_unlink;
|
||||
mod path_constructor_current_directory;
|
||||
mod replaceable_by_pathlib;
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
use ruff_diagnostics::{Applicability, Edit, Fix};
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::{ArgOrKeyword, ExprCall};
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::importer::ImportRequest;
|
||||
use crate::preview::is_fix_os_makedirs_enabled;
|
||||
use crate::rules::flake8_use_pathlib::helpers::{
|
||||
has_unknown_keywords_or_starred_expr, is_pathlib_path_call,
|
||||
};
|
||||
use crate::{FixAvailability, Violation};
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for uses of `os.makedirs`.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// `pathlib` offers a high-level API for path manipulation, as compared to
|
||||
/// the lower-level API offered by `os`. When possible, using `Path` object
|
||||
/// methods such as `Path.mkdir(parents=True)` can improve readability over the
|
||||
/// `os` module's counterparts (e.g., `os.makedirs()`.
|
||||
///
|
||||
/// ## Examples
|
||||
/// ```python
|
||||
/// import os
|
||||
///
|
||||
/// os.makedirs("./nested/directory/")
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// from pathlib import Path
|
||||
///
|
||||
/// Path("./nested/directory/").mkdir(parents=True)
|
||||
/// ```
|
||||
///
|
||||
/// ## Known issues
|
||||
/// While using `pathlib` can improve the readability and type safety of your code,
|
||||
/// it can be less performant than the lower-level alternatives that work directly with strings,
|
||||
/// especially on older versions of Python.
|
||||
///
|
||||
/// ## Fix Safety
|
||||
/// This rule's fix is marked as unsafe if the replacement would remove comments attached to the original expression.
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: `Path.mkdir`](https://docs.python.org/3/library/pathlib.html#pathlib.Path.mkdir)
|
||||
/// - [Python documentation: `os.makedirs`](https://docs.python.org/3/library/os.html#os.makedirs)
|
||||
/// - [PEP 428 – The pathlib module – object-oriented filesystem paths](https://peps.python.org/pep-0428/)
|
||||
/// - [Correspondence between `os` and `pathlib`](https://docs.python.org/3/library/pathlib.html#correspondence-to-tools-in-the-os-module)
|
||||
/// - [Why you should be using pathlib](https://treyhunner.com/2018/12/why-you-should-be-using-pathlib/)
|
||||
/// - [No really, pathlib is great](https://treyhunner.com/2019/01/no-really-pathlib-is-great/)
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct OsMakedirs;
|
||||
|
||||
impl Violation for OsMakedirs {
|
||||
const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes;
|
||||
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
"`os.makedirs()` should be replaced by `Path.mkdir(parents=True)`".to_string()
|
||||
}
|
||||
|
||||
fn fix_title(&self) -> Option<String> {
|
||||
Some("Replace with `Path(...).mkdir(parents=True)`".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
/// PTH103
|
||||
pub(crate) fn os_makedirs(checker: &Checker, call: &ExprCall, segments: &[&str]) {
|
||||
if segments != ["os", "makedirs"] {
|
||||
return;
|
||||
}
|
||||
|
||||
let range = call.range();
|
||||
let mut diagnostic = checker.report_diagnostic(OsMakedirs, call.func.range());
|
||||
|
||||
let Some(name) = call.arguments.find_argument_value("name", 0) else {
|
||||
return;
|
||||
};
|
||||
|
||||
if !is_fix_os_makedirs_enabled(checker.settings()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Signature as of Python 3.13 (https://docs.python.org/3/library/os.html#os.makedirs)
|
||||
// ```text
|
||||
// 0 1 2
|
||||
// os.makedirs(name, mode=0o777, exist_ok=False)
|
||||
// ```
|
||||
// We should not offer autofixes if there are more arguments
|
||||
// than in the original signature
|
||||
if call.arguments.len() > 3 {
|
||||
return;
|
||||
}
|
||||
// We should not offer autofixes if there are keyword arguments
|
||||
// that don't match the original function signature
|
||||
if has_unknown_keywords_or_starred_expr(&call.arguments, &["name", "mode", "exist_ok"]) {
|
||||
return;
|
||||
}
|
||||
|
||||
diagnostic.try_set_fix(|| {
|
||||
let (import_edit, binding) = checker.importer().get_or_import_symbol(
|
||||
&ImportRequest::import("pathlib", "Path"),
|
||||
call.start(),
|
||||
checker.semantic(),
|
||||
)?;
|
||||
|
||||
let applicability = if checker.comment_ranges().intersects(range) {
|
||||
Applicability::Unsafe
|
||||
} else {
|
||||
Applicability::Safe
|
||||
};
|
||||
|
||||
let locator = checker.locator();
|
||||
|
||||
let name_code = locator.slice(name.range());
|
||||
|
||||
let mode = call.arguments.find_argument("mode", 1);
|
||||
let exist_ok = call.arguments.find_argument("exist_ok", 2);
|
||||
|
||||
let mkdir_args = match (mode, exist_ok) {
|
||||
// Default to a keyword argument when alone.
|
||||
(None, None) => "parents=True".to_string(),
|
||||
// If either argument is missing, it's safe to add `parents` at the end.
|
||||
(None, Some(arg)) | (Some(arg), None) => {
|
||||
format!("{}, parents=True", locator.slice(arg))
|
||||
}
|
||||
// If they're all positional, `parents` has to be positional too.
|
||||
(Some(ArgOrKeyword::Arg(mode)), Some(ArgOrKeyword::Arg(exist_ok))) => {
|
||||
format!("{}, True, {}", locator.slice(mode), locator.slice(exist_ok))
|
||||
}
|
||||
// If either argument is a keyword, we can put `parents` at the end again.
|
||||
(Some(mode), Some(exist_ok)) => format!(
|
||||
"{}, {}, parents=True",
|
||||
locator.slice(mode),
|
||||
locator.slice(exist_ok)
|
||||
),
|
||||
};
|
||||
|
||||
let replacement = if is_pathlib_path_call(checker, name) {
|
||||
format!("{name_code}.mkdir({mkdir_args})")
|
||||
} else {
|
||||
format!("{binding}({name_code}).mkdir({mkdir_args})")
|
||||
};
|
||||
|
||||
Ok(Fix::applicable_edits(
|
||||
Edit::range_replacement(replacement, range),
|
||||
[import_edit],
|
||||
applicability,
|
||||
))
|
||||
});
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
use ruff_diagnostics::{Applicability, Edit, Fix};
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::ExprCall;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::importer::ImportRequest;
|
||||
use crate::preview::is_fix_os_mkdir_enabled;
|
||||
use crate::rules::flake8_use_pathlib::helpers::{
|
||||
has_unknown_keywords_or_starred_expr, is_keyword_only_argument_non_default,
|
||||
is_pathlib_path_call,
|
||||
};
|
||||
use crate::{FixAvailability, Violation};
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for uses of `os.mkdir`.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// `pathlib` offers a high-level API for path manipulation, as compared to
|
||||
/// the lower-level API offered by `os`. When possible, using `Path` object
|
||||
/// methods such as `Path.mkdir()` can improve readability over the `os`
|
||||
/// module's counterparts (e.g., `os.mkdir()`).
|
||||
///
|
||||
/// ## Examples
|
||||
/// ```python
|
||||
/// import os
|
||||
///
|
||||
/// os.mkdir("./directory/")
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// from pathlib import Path
|
||||
///
|
||||
/// Path("./directory/").mkdir()
|
||||
/// ```
|
||||
///
|
||||
/// ## Known issues
|
||||
/// While using `pathlib` can improve the readability and type safety of your code,
|
||||
/// it can be less performant than the lower-level alternatives that work directly with strings,
|
||||
/// especially on older versions of Python.
|
||||
///
|
||||
/// ## Fix Safety
|
||||
/// This rule's fix is marked as unsafe if the replacement would remove comments attached to the original expression.
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: `Path.mkdir`](https://docs.python.org/3/library/pathlib.html#pathlib.Path.mkdir)
|
||||
/// - [Python documentation: `os.mkdir`](https://docs.python.org/3/library/os.html#os.mkdir)
|
||||
/// - [PEP 428 – The pathlib module – object-oriented filesystem paths](https://peps.python.org/pep-0428/)
|
||||
/// - [Correspondence between `os` and `pathlib`](https://docs.python.org/3/library/pathlib.html#correspondence-to-tools-in-the-os-module)
|
||||
/// - [Why you should be using pathlib](https://treyhunner.com/2018/12/why-you-should-be-using-pathlib/)
|
||||
/// - [No really, pathlib is great](https://treyhunner.com/2019/01/no-really-pathlib-is-great/)
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct OsMkdir;
|
||||
|
||||
impl Violation for OsMkdir {
|
||||
const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes;
|
||||
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
"`os.mkdir()` should be replaced by `Path.mkdir()`".to_string()
|
||||
}
|
||||
|
||||
fn fix_title(&self) -> Option<String> {
|
||||
Some("Replace with `Path(...).mkdir()`".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
/// PTH102
|
||||
pub(crate) fn os_mkdir(checker: &Checker, call: &ExprCall, segments: &[&str]) {
|
||||
if segments != ["os", "mkdir"] {
|
||||
return;
|
||||
}
|
||||
// `dir_fd` is not supported by pathlib, so check if it's set to non-default values.
|
||||
// Signature as of Python 3.13 (https://docs.python.org/3/library/os.html#os.mkdir)
|
||||
// ```text
|
||||
// 0 1 2
|
||||
// os.mkdir(path, mode=0o777, *, dir_fd=None)
|
||||
// ```
|
||||
if is_keyword_only_argument_non_default(&call.arguments, "dir_fd") {
|
||||
return;
|
||||
}
|
||||
|
||||
let range = call.range();
|
||||
let mut diagnostic = checker.report_diagnostic(OsMkdir, call.func.range());
|
||||
|
||||
let Some(path) = call.arguments.find_argument_value("path", 0) else {
|
||||
return;
|
||||
};
|
||||
|
||||
if !is_fix_os_mkdir_enabled(checker.settings()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if call.arguments.len() > 2 {
|
||||
return;
|
||||
}
|
||||
|
||||
if has_unknown_keywords_or_starred_expr(&call.arguments, &["path", "mode"]) {
|
||||
return;
|
||||
}
|
||||
|
||||
diagnostic.try_set_fix(|| {
|
||||
let (import_edit, binding) = checker.importer().get_or_import_symbol(
|
||||
&ImportRequest::import("pathlib", "Path"),
|
||||
call.start(),
|
||||
checker.semantic(),
|
||||
)?;
|
||||
|
||||
let applicability = if checker.comment_ranges().intersects(range) {
|
||||
Applicability::Unsafe
|
||||
} else {
|
||||
Applicability::Safe
|
||||
};
|
||||
|
||||
let path_code = checker.locator().slice(path.range());
|
||||
|
||||
let mkdir_args = call
|
||||
.arguments
|
||||
.find_argument_value("mode", 1)
|
||||
.map(|expr| format!("mode={}", checker.locator().slice(expr.range())))
|
||||
.unwrap_or_default();
|
||||
|
||||
let replacement = if is_pathlib_path_call(checker, path) {
|
||||
format!("{path_code}.mkdir({mkdir_args})")
|
||||
} else {
|
||||
format!("{binding}({path_code}).mkdir({mkdir_args})")
|
||||
};
|
||||
|
||||
Ok(Fix::applicable_edits(
|
||||
Edit::range_replacement(replacement, range),
|
||||
[import_edit],
|
||||
applicability,
|
||||
))
|
||||
});
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
use ruff_diagnostics::{Applicability, Edit, Fix};
|
||||
use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
use ruff_python_ast::ExprCall;
|
||||
use ruff_text_size::Ranged;
|
||||
|
||||
use crate::checkers::ast::Checker;
|
||||
use crate::importer::ImportRequest;
|
||||
use crate::preview::is_fix_os_symlink_enabled;
|
||||
use crate::rules::flake8_use_pathlib::helpers::{
|
||||
has_unknown_keywords_or_starred_expr, is_keyword_only_argument_non_default,
|
||||
is_pathlib_path_call,
|
||||
};
|
||||
use crate::{FixAvailability, Violation};
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for uses of `os.symlink`.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// `pathlib` offers a high-level API for path manipulation, as compared to
|
||||
/// the lower-level API offered by `os.symlink`.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// import os
|
||||
///
|
||||
/// os.symlink("usr/bin/python", "tmp/python", target_is_directory=False)
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// from pathlib import Path
|
||||
///
|
||||
/// Path("tmp/python").symlink_to("usr/bin/python")
|
||||
/// ```
|
||||
///
|
||||
/// ## Known issues
|
||||
/// While using `pathlib` can improve the readability and type safety of your code,
|
||||
/// it can be less performant than the lower-level alternatives that work directly with strings,
|
||||
/// especially on older versions of Python.
|
||||
///
|
||||
/// ## Fix Safety
|
||||
/// This rule's fix is marked as unsafe if the replacement would remove comments attached to the original expression.
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: `Path.symlink_to`](https://docs.python.org/3/library/pathlib.html#pathlib.Path.symlink_to)
|
||||
/// - [PEP 428 – The pathlib module – object-oriented filesystem paths](https://peps.python.org/pep-0428/)
|
||||
/// - [Correspondence between `os` and `pathlib`](https://docs.python.org/3/library/pathlib.html#correspondence-to-tools-in-the-os-module)
|
||||
/// - [Why you should be using pathlib](https://treyhunner.com/2018/12/why-you-should-be-using-pathlib/)
|
||||
/// - [No really, pathlib is great](https://treyhunner.com/2019/01/no-really-pathlib-is-great/)
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct OsSymlink;
|
||||
|
||||
impl Violation for OsSymlink {
|
||||
const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes;
|
||||
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
"`os.symlink` should be replaced by `Path.symlink_to`".to_string()
|
||||
}
|
||||
|
||||
fn fix_title(&self) -> Option<String> {
|
||||
Some("Replace with `Path(...).symlink_to(...)`".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
/// PTH211
|
||||
pub(crate) fn os_symlink(checker: &Checker, call: &ExprCall, segments: &[&str]) {
|
||||
if segments != ["os", "symlink"] {
|
||||
return;
|
||||
}
|
||||
|
||||
// `dir_fd` is not supported by pathlib, so check if there are non-default values.
|
||||
// Signature as of Python 3.13 (https://docs.python.org/3/library/os.html#os.symlink)
|
||||
// ```text
|
||||
// 0 1 2 3
|
||||
// os.symlink(src, dst, target_is_directory=False, *, dir_fd=None)
|
||||
// ```
|
||||
if is_keyword_only_argument_non_default(&call.arguments, "dir_fd") {
|
||||
return;
|
||||
}
|
||||
|
||||
let range = call.range();
|
||||
let mut diagnostic = checker.report_diagnostic(OsSymlink, call.func.range());
|
||||
|
||||
if !is_fix_os_symlink_enabled(checker.settings()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if call.arguments.len() > 3 {
|
||||
return;
|
||||
}
|
||||
|
||||
if has_unknown_keywords_or_starred_expr(
|
||||
&call.arguments,
|
||||
&["src", "dst", "target_is_directory", "dir_fd"],
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
let (Some(src), Some(dst)) = (
|
||||
call.arguments.find_argument_value("src", 0),
|
||||
call.arguments.find_argument_value("dst", 1),
|
||||
) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let target_is_directory_arg = call.arguments.find_argument_value("target_is_directory", 2);
|
||||
|
||||
if let Some(expr) = &target_is_directory_arg {
|
||||
if expr.as_boolean_literal_expr().is_none() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
diagnostic.try_set_fix(|| {
|
||||
let (import_edit, binding) = checker.importer().get_or_import_symbol(
|
||||
&ImportRequest::import("pathlib", "Path"),
|
||||
call.start(),
|
||||
checker.semantic(),
|
||||
)?;
|
||||
|
||||
let applicability = if checker.comment_ranges().intersects(range) {
|
||||
Applicability::Unsafe
|
||||
} else {
|
||||
Applicability::Safe
|
||||
};
|
||||
|
||||
let locator = checker.locator();
|
||||
let src_code = locator.slice(src.range());
|
||||
let dst_code = locator.slice(dst.range());
|
||||
|
||||
let target_is_directory = target_is_directory_arg
|
||||
.and_then(|expr| {
|
||||
let code = locator.slice(expr.range());
|
||||
expr.as_boolean_literal_expr()
|
||||
.is_none_or(|bl| bl.value)
|
||||
.then_some(format!(", target_is_directory={code}"))
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
let replacement = if is_pathlib_path_call(checker, dst) {
|
||||
format!("{dst_code}.symlink_to({src_code}{target_is_directory})")
|
||||
} else {
|
||||
format!("{binding}({dst_code}).symlink_to({src_code}{target_is_directory})")
|
||||
};
|
||||
|
||||
Ok(Fix::applicable_edits(
|
||||
Edit::range_replacement(replacement, range),
|
||||
[import_edit],
|
||||
applicability,
|
||||
))
|
||||
});
|
||||
}
|
||||
@@ -7,7 +7,10 @@ use crate::rules::flake8_use_pathlib::helpers::{
|
||||
};
|
||||
use crate::rules::flake8_use_pathlib::{
|
||||
rules::Glob,
|
||||
violations::{BuiltinOpen, Joiner, OsListdir, OsPathJoin, OsPathSplitext, OsStat, PyPath},
|
||||
violations::{
|
||||
BuiltinOpen, Joiner, OsListdir, OsMakedirs, OsMkdir, OsPathJoin, OsPathSplitext, OsStat,
|
||||
OsSymlink, PyPath,
|
||||
},
|
||||
};
|
||||
|
||||
pub(crate) fn replaceable_by_pathlib(checker: &Checker, call: &ExprCall) {
|
||||
@@ -17,6 +20,21 @@ pub(crate) fn replaceable_by_pathlib(checker: &Checker, call: &ExprCall) {
|
||||
|
||||
let range = call.func.range();
|
||||
match qualified_name.segments() {
|
||||
// PTH102
|
||||
["os", "makedirs"] => checker.report_diagnostic_if_enabled(OsMakedirs, range),
|
||||
// PTH103
|
||||
["os", "mkdir"] => {
|
||||
// `dir_fd` is not supported by pathlib, so check if it's set to non-default values.
|
||||
// Signature as of Python 3.13 (https://docs.python.org/3/library/os.html#os.mkdir)
|
||||
// ```text
|
||||
// 0 1 2
|
||||
// os.mkdir(path, mode=0o777, *, dir_fd=None)
|
||||
// ```
|
||||
if is_keyword_only_argument_non_default(&call.arguments, "dir_fd") {
|
||||
return;
|
||||
}
|
||||
checker.report_diagnostic_if_enabled(OsMkdir, range)
|
||||
}
|
||||
// PTH116
|
||||
["os", "stat"] => {
|
||||
// `dir_fd` is not supported by pathlib, so check if it's set to non-default values.
|
||||
@@ -60,6 +78,20 @@ pub(crate) fn replaceable_by_pathlib(checker: &Checker, call: &ExprCall) {
|
||||
),
|
||||
// PTH122
|
||||
["os", "path", "splitext"] => checker.report_diagnostic_if_enabled(OsPathSplitext, range),
|
||||
// PTH211
|
||||
["os", "symlink"] => {
|
||||
// `dir_fd` is not supported by pathlib, so check if there are non-default values.
|
||||
// Signature as of Python 3.13 (https://docs.python.org/3/library/os.html#os.symlink)
|
||||
// ```text
|
||||
// 0 1 2 3
|
||||
// os.symlink(src, dst, target_is_directory=False, *, dir_fd=None)
|
||||
// ```
|
||||
if is_keyword_only_argument_non_default(&call.arguments, "dir_fd") {
|
||||
return;
|
||||
}
|
||||
checker.report_diagnostic_if_enabled(OsSymlink, range)
|
||||
}
|
||||
|
||||
// PTH123
|
||||
["" | "builtins", "open"] => {
|
||||
// `closefd` and `opener` are not supported by pathlib, so check if they
|
||||
|
||||
@@ -9,7 +9,6 @@ PTH211 `os.symlink` should be replaced by `Path.symlink_to`
|
||||
6 | os.symlink(b"usr/bin/python", b"tmp/python")
|
||||
7 | Path("tmp/python").symlink_to("usr/bin/python") # Ok
|
||||
|
|
||||
help: Replace with `Path(...).symlink_to(...)`
|
||||
|
||||
PTH211 `os.symlink` should be replaced by `Path.symlink_to`
|
||||
--> PTH211.py:6:1
|
||||
@@ -19,7 +18,6 @@ PTH211 `os.symlink` should be replaced by `Path.symlink_to`
|
||||
| ^^^^^^^^^^
|
||||
7 | Path("tmp/python").symlink_to("usr/bin/python") # Ok
|
||||
|
|
||||
help: Replace with `Path(...).symlink_to(...)`
|
||||
|
||||
PTH211 `os.symlink` should be replaced by `Path.symlink_to`
|
||||
--> PTH211.py:9:1
|
||||
@@ -31,7 +29,6 @@ PTH211 `os.symlink` should be replaced by `Path.symlink_to`
|
||||
10 | os.symlink(b"usr/bin/python", b"tmp/python", target_is_directory=True)
|
||||
11 | Path("tmp/python").symlink_to("usr/bin/python", target_is_directory=True) # Ok
|
||||
|
|
||||
help: Replace with `Path(...).symlink_to(...)`
|
||||
|
||||
PTH211 `os.symlink` should be replaced by `Path.symlink_to`
|
||||
--> PTH211.py:10:1
|
||||
@@ -41,58 +38,3 @@ PTH211 `os.symlink` should be replaced by `Path.symlink_to`
|
||||
| ^^^^^^^^^^
|
||||
11 | Path("tmp/python").symlink_to("usr/bin/python", target_is_directory=True) # Ok
|
||||
|
|
||||
help: Replace with `Path(...).symlink_to(...)`
|
||||
|
||||
PTH211 `os.symlink` should be replaced by `Path.symlink_to`
|
||||
--> PTH211.py:17:1
|
||||
|
|
||||
15 | os.close(fd)
|
||||
16 |
|
||||
17 | os.symlink(src="usr/bin/python", dst="tmp/python", unknown=True)
|
||||
| ^^^^^^^^^^
|
||||
18 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory=False)
|
||||
|
|
||||
help: Replace with `Path(...).symlink_to(...)`
|
||||
|
||||
PTH211 `os.symlink` should be replaced by `Path.symlink_to`
|
||||
--> PTH211.py:18:1
|
||||
|
|
||||
17 | os.symlink(src="usr/bin/python", dst="tmp/python", unknown=True)
|
||||
18 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory=False)
|
||||
| ^^^^^^^^^^
|
||||
19 |
|
||||
20 | os.symlink(src="usr/bin/python", dst="tmp/python", dir_fd=None)
|
||||
|
|
||||
help: Replace with `Path(...).symlink_to(...)`
|
||||
|
||||
PTH211 `os.symlink` should be replaced by `Path.symlink_to`
|
||||
--> PTH211.py:20:1
|
||||
|
|
||||
18 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory=False)
|
||||
19 |
|
||||
20 | os.symlink(src="usr/bin/python", dst="tmp/python", dir_fd=None)
|
||||
| ^^^^^^^^^^
|
||||
21 |
|
||||
22 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory= True )
|
||||
|
|
||||
help: Replace with `Path(...).symlink_to(...)`
|
||||
|
||||
PTH211 `os.symlink` should be replaced by `Path.symlink_to`
|
||||
--> PTH211.py:22:1
|
||||
|
|
||||
20 | os.symlink(src="usr/bin/python", dst="tmp/python", dir_fd=None)
|
||||
21 |
|
||||
22 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory= True )
|
||||
| ^^^^^^^^^^
|
||||
23 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory="nonboolean")
|
||||
|
|
||||
help: Replace with `Path(...).symlink_to(...)`
|
||||
|
||||
PTH211 `os.symlink` should be replaced by `Path.symlink_to`
|
||||
--> PTH211.py:23:1
|
||||
|
|
||||
22 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory= True )
|
||||
23 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory="nonboolean")
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
help: Replace with `Path(...).symlink_to(...)`
|
||||
|
||||
@@ -34,7 +34,6 @@ PTH102 `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
10 | os.makedirs(p)
|
||||
11 | os.rename(p)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir()`
|
||||
|
||||
PTH103 `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
--> full_name.py:10:1
|
||||
@@ -46,7 +45,6 @@ PTH103 `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
11 | os.rename(p)
|
||||
12 | os.replace(p)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir(parents=True)`
|
||||
|
||||
PTH104 `os.rename()` should be replaced by `Path.rename()`
|
||||
--> full_name.py:11:1
|
||||
@@ -421,77 +419,5 @@ PTH109 `os.getcwd()` should be replaced by `Path.cwd()`
|
||||
108 | os.getcwd()
|
||||
109 | os.getcwdb()
|
||||
| ^^^^^^^^^^
|
||||
110 |
|
||||
111 | os.mkdir(path="directory")
|
||||
|
|
||||
help: Replace with `Path.cwd()`
|
||||
|
||||
PTH102 `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
--> full_name.py:111:1
|
||||
|
|
||||
109 | os.getcwdb()
|
||||
110 |
|
||||
111 | os.mkdir(path="directory")
|
||||
| ^^^^^^^^
|
||||
112 |
|
||||
113 | os.mkdir(
|
||||
|
|
||||
help: Replace with `Path(...).mkdir()`
|
||||
|
||||
PTH102 `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
--> full_name.py:113:1
|
||||
|
|
||||
111 | os.mkdir(path="directory")
|
||||
112 |
|
||||
113 | os.mkdir(
|
||||
| ^^^^^^^^
|
||||
114 | # comment 1
|
||||
115 | "directory",
|
||||
|
|
||||
help: Replace with `Path(...).mkdir()`
|
||||
|
||||
PTH103 `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
--> full_name.py:121:1
|
||||
|
|
||||
119 | os.mkdir("directory", mode=0o777, dir_fd=1)
|
||||
120 |
|
||||
121 | os.makedirs("name", 0o777, exist_ok=False)
|
||||
| ^^^^^^^^^^^
|
||||
122 |
|
||||
123 | os.makedirs("name", 0o777, False)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir(parents=True)`
|
||||
|
||||
PTH103 `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
--> full_name.py:123:1
|
||||
|
|
||||
121 | os.makedirs("name", 0o777, exist_ok=False)
|
||||
122 |
|
||||
123 | os.makedirs("name", 0o777, False)
|
||||
| ^^^^^^^^^^^
|
||||
124 |
|
||||
125 | os.makedirs(name="name", mode=0o777, exist_ok=False)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir(parents=True)`
|
||||
|
||||
PTH103 `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
--> full_name.py:125:1
|
||||
|
|
||||
123 | os.makedirs("name", 0o777, False)
|
||||
124 |
|
||||
125 | os.makedirs(name="name", mode=0o777, exist_ok=False)
|
||||
| ^^^^^^^^^^^
|
||||
126 |
|
||||
127 | os.makedirs("name", unknown_kwarg=True)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir(parents=True)`
|
||||
|
||||
PTH103 `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
--> full_name.py:127:1
|
||||
|
|
||||
125 | os.makedirs(name="name", mode=0o777, exist_ok=False)
|
||||
126 |
|
||||
127 | os.makedirs("name", unknown_kwarg=True)
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
help: Replace with `Path(...).mkdir(parents=True)`
|
||||
|
||||
@@ -34,7 +34,6 @@ PTH102 `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
10 | foo.makedirs(p)
|
||||
11 | foo.rename(p)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir()`
|
||||
|
||||
PTH103 `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
--> import_as.py:10:1
|
||||
@@ -46,7 +45,6 @@ PTH103 `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
11 | foo.rename(p)
|
||||
12 | foo.replace(p)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir(parents=True)`
|
||||
|
||||
PTH104 `os.rename()` should be replaced by `Path.rename()`
|
||||
--> import_as.py:11:1
|
||||
|
||||
@@ -34,7 +34,6 @@ PTH102 `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
12 | makedirs(p)
|
||||
13 | rename(p)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir()`
|
||||
|
||||
PTH103 `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
--> import_from.py:12:1
|
||||
@@ -46,7 +45,6 @@ PTH103 `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
13 | rename(p)
|
||||
14 | replace(p)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir(parents=True)`
|
||||
|
||||
PTH104 `os.rename()` should be replaced by `Path.rename()`
|
||||
--> import_from.py:13:1
|
||||
|
||||
@@ -34,7 +34,6 @@ PTH102 `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
17 | xmakedirs(p)
|
||||
18 | xrename(p)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir()`
|
||||
|
||||
PTH103 `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
--> import_from_as.py:17:1
|
||||
@@ -46,7 +45,6 @@ PTH103 `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
18 | xrename(p)
|
||||
19 | xreplace(p)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir(parents=True)`
|
||||
|
||||
PTH104 `os.rename()` should be replaced by `Path.rename()`
|
||||
--> import_from_as.py:18:1
|
||||
|
||||
@@ -1,166 +0,0 @@
|
||||
---
|
||||
source: crates/ruff_linter/src/rules/flake8_use_pathlib/mod.rs
|
||||
---
|
||||
PTH211 [*] `os.symlink` should be replaced by `Path.symlink_to`
|
||||
--> PTH211.py:5:1
|
||||
|
|
||||
5 | os.symlink("usr/bin/python", "tmp/python")
|
||||
| ^^^^^^^^^^
|
||||
6 | os.symlink(b"usr/bin/python", b"tmp/python")
|
||||
7 | Path("tmp/python").symlink_to("usr/bin/python") # Ok
|
||||
|
|
||||
help: Replace with `Path(...).symlink_to(...)`
|
||||
|
||||
ℹ Safe fix
|
||||
2 2 | from pathlib import Path
|
||||
3 3 |
|
||||
4 4 |
|
||||
5 |-os.symlink("usr/bin/python", "tmp/python")
|
||||
5 |+Path("tmp/python").symlink_to("usr/bin/python")
|
||||
6 6 | os.symlink(b"usr/bin/python", b"tmp/python")
|
||||
7 7 | Path("tmp/python").symlink_to("usr/bin/python") # Ok
|
||||
8 8 |
|
||||
|
||||
PTH211 [*] `os.symlink` should be replaced by `Path.symlink_to`
|
||||
--> PTH211.py:6:1
|
||||
|
|
||||
5 | os.symlink("usr/bin/python", "tmp/python")
|
||||
6 | os.symlink(b"usr/bin/python", b"tmp/python")
|
||||
| ^^^^^^^^^^
|
||||
7 | Path("tmp/python").symlink_to("usr/bin/python") # Ok
|
||||
|
|
||||
help: Replace with `Path(...).symlink_to(...)`
|
||||
|
||||
ℹ Safe fix
|
||||
3 3 |
|
||||
4 4 |
|
||||
5 5 | os.symlink("usr/bin/python", "tmp/python")
|
||||
6 |-os.symlink(b"usr/bin/python", b"tmp/python")
|
||||
6 |+Path(b"tmp/python").symlink_to(b"usr/bin/python")
|
||||
7 7 | Path("tmp/python").symlink_to("usr/bin/python") # Ok
|
||||
8 8 |
|
||||
9 9 | os.symlink("usr/bin/python", "tmp/python", target_is_directory=True)
|
||||
|
||||
PTH211 [*] `os.symlink` should be replaced by `Path.symlink_to`
|
||||
--> PTH211.py:9:1
|
||||
|
|
||||
7 | Path("tmp/python").symlink_to("usr/bin/python") # Ok
|
||||
8 |
|
||||
9 | os.symlink("usr/bin/python", "tmp/python", target_is_directory=True)
|
||||
| ^^^^^^^^^^
|
||||
10 | os.symlink(b"usr/bin/python", b"tmp/python", target_is_directory=True)
|
||||
11 | Path("tmp/python").symlink_to("usr/bin/python", target_is_directory=True) # Ok
|
||||
|
|
||||
help: Replace with `Path(...).symlink_to(...)`
|
||||
|
||||
ℹ Safe fix
|
||||
6 6 | os.symlink(b"usr/bin/python", b"tmp/python")
|
||||
7 7 | Path("tmp/python").symlink_to("usr/bin/python") # Ok
|
||||
8 8 |
|
||||
9 |-os.symlink("usr/bin/python", "tmp/python", target_is_directory=True)
|
||||
9 |+Path("tmp/python").symlink_to("usr/bin/python", target_is_directory=True)
|
||||
10 10 | os.symlink(b"usr/bin/python", b"tmp/python", target_is_directory=True)
|
||||
11 11 | Path("tmp/python").symlink_to("usr/bin/python", target_is_directory=True) # Ok
|
||||
12 12 |
|
||||
|
||||
PTH211 [*] `os.symlink` should be replaced by `Path.symlink_to`
|
||||
--> PTH211.py:10:1
|
||||
|
|
||||
9 | os.symlink("usr/bin/python", "tmp/python", target_is_directory=True)
|
||||
10 | os.symlink(b"usr/bin/python", b"tmp/python", target_is_directory=True)
|
||||
| ^^^^^^^^^^
|
||||
11 | Path("tmp/python").symlink_to("usr/bin/python", target_is_directory=True) # Ok
|
||||
|
|
||||
help: Replace with `Path(...).symlink_to(...)`
|
||||
|
||||
ℹ Safe fix
|
||||
7 7 | Path("tmp/python").symlink_to("usr/bin/python") # Ok
|
||||
8 8 |
|
||||
9 9 | os.symlink("usr/bin/python", "tmp/python", target_is_directory=True)
|
||||
10 |-os.symlink(b"usr/bin/python", b"tmp/python", target_is_directory=True)
|
||||
10 |+Path(b"tmp/python").symlink_to(b"usr/bin/python", target_is_directory=True)
|
||||
11 11 | Path("tmp/python").symlink_to("usr/bin/python", target_is_directory=True) # Ok
|
||||
12 12 |
|
||||
13 13 | fd = os.open(".", os.O_RDONLY)
|
||||
|
||||
PTH211 `os.symlink` should be replaced by `Path.symlink_to`
|
||||
--> PTH211.py:17:1
|
||||
|
|
||||
15 | os.close(fd)
|
||||
16 |
|
||||
17 | os.symlink(src="usr/bin/python", dst="tmp/python", unknown=True)
|
||||
| ^^^^^^^^^^
|
||||
18 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory=False)
|
||||
|
|
||||
help: Replace with `Path(...).symlink_to(...)`
|
||||
|
||||
PTH211 [*] `os.symlink` should be replaced by `Path.symlink_to`
|
||||
--> PTH211.py:18:1
|
||||
|
|
||||
17 | os.symlink(src="usr/bin/python", dst="tmp/python", unknown=True)
|
||||
18 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory=False)
|
||||
| ^^^^^^^^^^
|
||||
19 |
|
||||
20 | os.symlink(src="usr/bin/python", dst="tmp/python", dir_fd=None)
|
||||
|
|
||||
help: Replace with `Path(...).symlink_to(...)`
|
||||
|
||||
ℹ Safe fix
|
||||
15 15 | os.close(fd)
|
||||
16 16 |
|
||||
17 17 | os.symlink(src="usr/bin/python", dst="tmp/python", unknown=True)
|
||||
18 |-os.symlink("usr/bin/python", dst="tmp/python", target_is_directory=False)
|
||||
18 |+Path("tmp/python").symlink_to("usr/bin/python")
|
||||
19 19 |
|
||||
20 20 | os.symlink(src="usr/bin/python", dst="tmp/python", dir_fd=None)
|
||||
21 21 |
|
||||
|
||||
PTH211 [*] `os.symlink` should be replaced by `Path.symlink_to`
|
||||
--> PTH211.py:20:1
|
||||
|
|
||||
18 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory=False)
|
||||
19 |
|
||||
20 | os.symlink(src="usr/bin/python", dst="tmp/python", dir_fd=None)
|
||||
| ^^^^^^^^^^
|
||||
21 |
|
||||
22 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory= True )
|
||||
|
|
||||
help: Replace with `Path(...).symlink_to(...)`
|
||||
|
||||
ℹ Safe fix
|
||||
17 17 | os.symlink(src="usr/bin/python", dst="tmp/python", unknown=True)
|
||||
18 18 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory=False)
|
||||
19 19 |
|
||||
20 |-os.symlink(src="usr/bin/python", dst="tmp/python", dir_fd=None)
|
||||
20 |+Path("tmp/python").symlink_to("usr/bin/python")
|
||||
21 21 |
|
||||
22 22 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory= True )
|
||||
23 23 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory="nonboolean")
|
||||
|
||||
PTH211 [*] `os.symlink` should be replaced by `Path.symlink_to`
|
||||
--> PTH211.py:22:1
|
||||
|
|
||||
20 | os.symlink(src="usr/bin/python", dst="tmp/python", dir_fd=None)
|
||||
21 |
|
||||
22 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory= True )
|
||||
| ^^^^^^^^^^
|
||||
23 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory="nonboolean")
|
||||
|
|
||||
help: Replace with `Path(...).symlink_to(...)`
|
||||
|
||||
ℹ Safe fix
|
||||
19 19 |
|
||||
20 20 | os.symlink(src="usr/bin/python", dst="tmp/python", dir_fd=None)
|
||||
21 21 |
|
||||
22 |-os.symlink("usr/bin/python", dst="tmp/python", target_is_directory= True )
|
||||
22 |+Path("tmp/python").symlink_to("usr/bin/python", target_is_directory=True)
|
||||
23 23 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory="nonboolean")
|
||||
|
||||
PTH211 `os.symlink` should be replaced by `Path.symlink_to`
|
||||
--> PTH211.py:23:1
|
||||
|
|
||||
22 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory= True )
|
||||
23 | os.symlink("usr/bin/python", dst="tmp/python", target_is_directory="nonboolean")
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
help: Replace with `Path(...).symlink_to(...)`
|
||||
@@ -38,7 +38,7 @@ PTH101 `os.chmod()` should be replaced by `Path.chmod()`
|
||||
|
|
||||
help: Replace with `Path(...).chmod(...)`
|
||||
|
||||
PTH102 [*] `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
PTH102 `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
--> full_name.py:9:7
|
||||
|
|
||||
7 | a = os.path.abspath(p)
|
||||
@@ -48,25 +48,8 @@ PTH102 [*] `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
10 | os.makedirs(p)
|
||||
11 | os.rename(p)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir()`
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | import os
|
||||
2 2 | import os.path
|
||||
3 |+import pathlib
|
||||
3 4 |
|
||||
4 5 | p = "/foo"
|
||||
5 6 | q = "bar"
|
||||
6 7 |
|
||||
7 8 | a = os.path.abspath(p)
|
||||
8 9 | aa = os.chmod(p)
|
||||
9 |-aaa = os.mkdir(p)
|
||||
10 |+aaa = pathlib.Path(p).mkdir()
|
||||
10 11 | os.makedirs(p)
|
||||
11 12 | os.rename(p)
|
||||
12 13 | os.replace(p)
|
||||
|
||||
PTH103 [*] `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
PTH103 `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
--> full_name.py:10:1
|
||||
|
|
||||
8 | aa = os.chmod(p)
|
||||
@@ -76,24 +59,6 @@ PTH103 [*] `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
11 | os.rename(p)
|
||||
12 | os.replace(p)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir(parents=True)`
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | import os
|
||||
2 2 | import os.path
|
||||
3 |+import pathlib
|
||||
3 4 |
|
||||
4 5 | p = "/foo"
|
||||
5 6 | q = "bar"
|
||||
--------------------------------------------------------------------------------
|
||||
7 8 | a = os.path.abspath(p)
|
||||
8 9 | aa = os.chmod(p)
|
||||
9 10 | aaa = os.mkdir(p)
|
||||
10 |-os.makedirs(p)
|
||||
11 |+pathlib.Path(p).mkdir(parents=True)
|
||||
11 12 | os.rename(p)
|
||||
12 13 | os.replace(p)
|
||||
13 14 | os.rmdir(p)
|
||||
|
||||
PTH104 `os.rename()` should be replaced by `Path.rename()`
|
||||
--> full_name.py:11:1
|
||||
@@ -680,8 +645,6 @@ help: Replace with `Path.cwd()`
|
||||
108 |-os.getcwd()
|
||||
109 |+pathlib.Path.cwd()
|
||||
109 110 | os.getcwdb()
|
||||
110 111 |
|
||||
111 112 | os.mkdir(path="directory")
|
||||
|
||||
PTH109 [*] `os.getcwd()` should be replaced by `Path.cwd()`
|
||||
--> full_name.py:109:1
|
||||
@@ -689,8 +652,6 @@ PTH109 [*] `os.getcwd()` should be replaced by `Path.cwd()`
|
||||
108 | os.getcwd()
|
||||
109 | os.getcwdb()
|
||||
| ^^^^^^^^^^
|
||||
110 |
|
||||
111 | os.mkdir(path="directory")
|
||||
|
|
||||
help: Replace with `Path.cwd()`
|
||||
|
||||
@@ -707,164 +668,3 @@ help: Replace with `Path.cwd()`
|
||||
108 109 | os.getcwd()
|
||||
109 |-os.getcwdb()
|
||||
110 |+pathlib.Path.cwd()
|
||||
110 111 |
|
||||
111 112 | os.mkdir(path="directory")
|
||||
112 113 |
|
||||
|
||||
PTH102 [*] `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
--> full_name.py:111:1
|
||||
|
|
||||
109 | os.getcwdb()
|
||||
110 |
|
||||
111 | os.mkdir(path="directory")
|
||||
| ^^^^^^^^
|
||||
112 |
|
||||
113 | os.mkdir(
|
||||
|
|
||||
help: Replace with `Path(...).mkdir()`
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | import os
|
||||
2 2 | import os.path
|
||||
3 |+import pathlib
|
||||
3 4 |
|
||||
4 5 | p = "/foo"
|
||||
5 6 | q = "bar"
|
||||
--------------------------------------------------------------------------------
|
||||
108 109 | os.getcwd()
|
||||
109 110 | os.getcwdb()
|
||||
110 111 |
|
||||
111 |-os.mkdir(path="directory")
|
||||
112 |+pathlib.Path("directory").mkdir()
|
||||
112 113 |
|
||||
113 114 | os.mkdir(
|
||||
114 115 | # comment 1
|
||||
|
||||
PTH102 [*] `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
--> full_name.py:113:1
|
||||
|
|
||||
111 | os.mkdir(path="directory")
|
||||
112 |
|
||||
113 | os.mkdir(
|
||||
| ^^^^^^^^
|
||||
114 | # comment 1
|
||||
115 | "directory",
|
||||
|
|
||||
help: Replace with `Path(...).mkdir()`
|
||||
|
||||
ℹ Unsafe fix
|
||||
1 1 | import os
|
||||
2 2 | import os.path
|
||||
3 |+import pathlib
|
||||
3 4 |
|
||||
4 5 | p = "/foo"
|
||||
5 6 | q = "bar"
|
||||
--------------------------------------------------------------------------------
|
||||
110 111 |
|
||||
111 112 | os.mkdir(path="directory")
|
||||
112 113 |
|
||||
113 |-os.mkdir(
|
||||
114 |- # comment 1
|
||||
115 |- "directory",
|
||||
116 |- mode=0o777
|
||||
117 |-)
|
||||
114 |+pathlib.Path("directory").mkdir(mode=0o777)
|
||||
118 115 |
|
||||
119 116 | os.mkdir("directory", mode=0o777, dir_fd=1)
|
||||
120 117 |
|
||||
|
||||
PTH103 [*] `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
--> full_name.py:121:1
|
||||
|
|
||||
119 | os.mkdir("directory", mode=0o777, dir_fd=1)
|
||||
120 |
|
||||
121 | os.makedirs("name", 0o777, exist_ok=False)
|
||||
| ^^^^^^^^^^^
|
||||
122 |
|
||||
123 | os.makedirs("name", 0o777, False)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir(parents=True)`
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | import os
|
||||
2 2 | import os.path
|
||||
3 |+import pathlib
|
||||
3 4 |
|
||||
4 5 | p = "/foo"
|
||||
5 6 | q = "bar"
|
||||
--------------------------------------------------------------------------------
|
||||
118 119 |
|
||||
119 120 | os.mkdir("directory", mode=0o777, dir_fd=1)
|
||||
120 121 |
|
||||
121 |-os.makedirs("name", 0o777, exist_ok=False)
|
||||
122 |+pathlib.Path("name").mkdir(0o777, exist_ok=False, parents=True)
|
||||
122 123 |
|
||||
123 124 | os.makedirs("name", 0o777, False)
|
||||
124 125 |
|
||||
|
||||
PTH103 [*] `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
--> full_name.py:123:1
|
||||
|
|
||||
121 | os.makedirs("name", 0o777, exist_ok=False)
|
||||
122 |
|
||||
123 | os.makedirs("name", 0o777, False)
|
||||
| ^^^^^^^^^^^
|
||||
124 |
|
||||
125 | os.makedirs(name="name", mode=0o777, exist_ok=False)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir(parents=True)`
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | import os
|
||||
2 2 | import os.path
|
||||
3 |+import pathlib
|
||||
3 4 |
|
||||
4 5 | p = "/foo"
|
||||
5 6 | q = "bar"
|
||||
--------------------------------------------------------------------------------
|
||||
120 121 |
|
||||
121 122 | os.makedirs("name", 0o777, exist_ok=False)
|
||||
122 123 |
|
||||
123 |-os.makedirs("name", 0o777, False)
|
||||
124 |+pathlib.Path("name").mkdir(0o777, True, False)
|
||||
124 125 |
|
||||
125 126 | os.makedirs(name="name", mode=0o777, exist_ok=False)
|
||||
126 127 |
|
||||
|
||||
PTH103 [*] `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
--> full_name.py:125:1
|
||||
|
|
||||
123 | os.makedirs("name", 0o777, False)
|
||||
124 |
|
||||
125 | os.makedirs(name="name", mode=0o777, exist_ok=False)
|
||||
| ^^^^^^^^^^^
|
||||
126 |
|
||||
127 | os.makedirs("name", unknown_kwarg=True)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir(parents=True)`
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | import os
|
||||
2 2 | import os.path
|
||||
3 |+import pathlib
|
||||
3 4 |
|
||||
4 5 | p = "/foo"
|
||||
5 6 | q = "bar"
|
||||
--------------------------------------------------------------------------------
|
||||
122 123 |
|
||||
123 124 | os.makedirs("name", 0o777, False)
|
||||
124 125 |
|
||||
125 |-os.makedirs(name="name", mode=0o777, exist_ok=False)
|
||||
126 |+pathlib.Path("name").mkdir(mode=0o777, exist_ok=False, parents=True)
|
||||
126 127 |
|
||||
127 128 | os.makedirs("name", unknown_kwarg=True)
|
||||
|
||||
PTH103 `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
--> full_name.py:127:1
|
||||
|
|
||||
125 | os.makedirs(name="name", mode=0o777, exist_ok=False)
|
||||
126 |
|
||||
127 | os.makedirs("name", unknown_kwarg=True)
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
help: Replace with `Path(...).mkdir(parents=True)`
|
||||
|
||||
@@ -38,7 +38,7 @@ PTH101 `os.chmod()` should be replaced by `Path.chmod()`
|
||||
|
|
||||
help: Replace with `Path(...).chmod(...)`
|
||||
|
||||
PTH102 [*] `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
PTH102 `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
--> import_as.py:9:7
|
||||
|
|
||||
7 | a = foo_p.abspath(p)
|
||||
@@ -48,25 +48,8 @@ PTH102 [*] `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
10 | foo.makedirs(p)
|
||||
11 | foo.rename(p)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir()`
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | import os as foo
|
||||
2 2 | import os.path as foo_p
|
||||
3 |+import pathlib
|
||||
3 4 |
|
||||
4 5 | p = "/foo"
|
||||
5 6 | q = "bar"
|
||||
6 7 |
|
||||
7 8 | a = foo_p.abspath(p)
|
||||
8 9 | aa = foo.chmod(p)
|
||||
9 |-aaa = foo.mkdir(p)
|
||||
10 |+aaa = pathlib.Path(p).mkdir()
|
||||
10 11 | foo.makedirs(p)
|
||||
11 12 | foo.rename(p)
|
||||
12 13 | foo.replace(p)
|
||||
|
||||
PTH103 [*] `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
PTH103 `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
--> import_as.py:10:1
|
||||
|
|
||||
8 | aa = foo.chmod(p)
|
||||
@@ -76,24 +59,6 @@ PTH103 [*] `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
11 | foo.rename(p)
|
||||
12 | foo.replace(p)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir(parents=True)`
|
||||
|
||||
ℹ Safe fix
|
||||
1 1 | import os as foo
|
||||
2 2 | import os.path as foo_p
|
||||
3 |+import pathlib
|
||||
3 4 |
|
||||
4 5 | p = "/foo"
|
||||
5 6 | q = "bar"
|
||||
--------------------------------------------------------------------------------
|
||||
7 8 | a = foo_p.abspath(p)
|
||||
8 9 | aa = foo.chmod(p)
|
||||
9 10 | aaa = foo.mkdir(p)
|
||||
10 |-foo.makedirs(p)
|
||||
11 |+pathlib.Path(p).mkdir(parents=True)
|
||||
11 12 | foo.rename(p)
|
||||
12 13 | foo.replace(p)
|
||||
13 14 | foo.rmdir(p)
|
||||
|
||||
PTH104 `os.rename()` should be replaced by `Path.rename()`
|
||||
--> import_as.py:11:1
|
||||
|
||||
@@ -39,7 +39,7 @@ PTH101 `os.chmod()` should be replaced by `Path.chmod()`
|
||||
|
|
||||
help: Replace with `Path(...).chmod(...)`
|
||||
|
||||
PTH102 [*] `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
PTH102 `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
--> import_from.py:11:7
|
||||
|
|
||||
9 | a = abspath(p)
|
||||
@@ -49,26 +49,8 @@ PTH102 [*] `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
12 | makedirs(p)
|
||||
13 | rename(p)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir()`
|
||||
|
||||
ℹ Safe fix
|
||||
2 2 | from os import remove, unlink, getcwd, readlink, stat
|
||||
3 3 | from os.path import abspath, exists, expanduser, isdir, isfile, islink
|
||||
4 4 | from os.path import isabs, join, basename, dirname, samefile, splitext
|
||||
5 |+import pathlib
|
||||
5 6 |
|
||||
6 7 | p = "/foo"
|
||||
7 8 | q = "bar"
|
||||
8 9 |
|
||||
9 10 | a = abspath(p)
|
||||
10 11 | aa = chmod(p)
|
||||
11 |-aaa = mkdir(p)
|
||||
12 |+aaa = pathlib.Path(p).mkdir()
|
||||
12 13 | makedirs(p)
|
||||
13 14 | rename(p)
|
||||
14 15 | replace(p)
|
||||
|
||||
PTH103 [*] `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
PTH103 `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
--> import_from.py:12:1
|
||||
|
|
||||
10 | aa = chmod(p)
|
||||
@@ -78,25 +60,6 @@ PTH103 [*] `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
13 | rename(p)
|
||||
14 | replace(p)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir(parents=True)`
|
||||
|
||||
ℹ Safe fix
|
||||
2 2 | from os import remove, unlink, getcwd, readlink, stat
|
||||
3 3 | from os.path import abspath, exists, expanduser, isdir, isfile, islink
|
||||
4 4 | from os.path import isabs, join, basename, dirname, samefile, splitext
|
||||
5 |+import pathlib
|
||||
5 6 |
|
||||
6 7 | p = "/foo"
|
||||
7 8 | q = "bar"
|
||||
--------------------------------------------------------------------------------
|
||||
9 10 | a = abspath(p)
|
||||
10 11 | aa = chmod(p)
|
||||
11 12 | aaa = mkdir(p)
|
||||
12 |-makedirs(p)
|
||||
13 |+pathlib.Path(p).mkdir(parents=True)
|
||||
13 14 | rename(p)
|
||||
14 15 | replace(p)
|
||||
15 16 | rmdir(p)
|
||||
|
||||
PTH104 `os.rename()` should be replaced by `Path.rename()`
|
||||
--> import_from.py:13:1
|
||||
|
||||
@@ -39,7 +39,7 @@ PTH101 `os.chmod()` should be replaced by `Path.chmod()`
|
||||
|
|
||||
help: Replace with `Path(...).chmod(...)`
|
||||
|
||||
PTH102 [*] `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
PTH102 `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
--> import_from_as.py:16:7
|
||||
|
|
||||
14 | a = xabspath(p)
|
||||
@@ -49,26 +49,8 @@ PTH102 [*] `os.mkdir()` should be replaced by `Path.mkdir()`
|
||||
17 | xmakedirs(p)
|
||||
18 | xrename(p)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir()`
|
||||
|
||||
ℹ Safe fix
|
||||
7 7 | from os.path import isfile as xisfile, islink as xislink, isabs as xisabs
|
||||
8 8 | from os.path import join as xjoin, basename as xbasename, dirname as xdirname
|
||||
9 9 | from os.path import samefile as xsamefile, splitext as xsplitext
|
||||
10 |+import pathlib
|
||||
10 11 |
|
||||
11 12 | p = "/foo"
|
||||
12 13 | q = "bar"
|
||||
13 14 |
|
||||
14 15 | a = xabspath(p)
|
||||
15 16 | aa = xchmod(p)
|
||||
16 |-aaa = xmkdir(p)
|
||||
17 |+aaa = pathlib.Path(p).mkdir()
|
||||
17 18 | xmakedirs(p)
|
||||
18 19 | xrename(p)
|
||||
19 20 | xreplace(p)
|
||||
|
||||
PTH103 [*] `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
PTH103 `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
--> import_from_as.py:17:1
|
||||
|
|
||||
15 | aa = xchmod(p)
|
||||
@@ -78,25 +60,6 @@ PTH103 [*] `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
|
||||
18 | xrename(p)
|
||||
19 | xreplace(p)
|
||||
|
|
||||
help: Replace with `Path(...).mkdir(parents=True)`
|
||||
|
||||
ℹ Safe fix
|
||||
7 7 | from os.path import isfile as xisfile, islink as xislink, isabs as xisabs
|
||||
8 8 | from os.path import join as xjoin, basename as xbasename, dirname as xdirname
|
||||
9 9 | from os.path import samefile as xsamefile, splitext as xsplitext
|
||||
10 |+import pathlib
|
||||
10 11 |
|
||||
11 12 | p = "/foo"
|
||||
12 13 | q = "bar"
|
||||
--------------------------------------------------------------------------------
|
||||
14 15 | a = xabspath(p)
|
||||
15 16 | aa = xchmod(p)
|
||||
16 17 | aaa = xmkdir(p)
|
||||
17 |-xmakedirs(p)
|
||||
18 |+pathlib.Path(p).mkdir(parents=True)
|
||||
18 19 | xrename(p)
|
||||
19 20 | xreplace(p)
|
||||
20 21 | xrmdir(p)
|
||||
|
||||
PTH104 `os.rename()` should be replaced by `Path.rename()`
|
||||
--> import_from_as.py:18:1
|
||||
|
||||
@@ -2,6 +2,96 @@ use ruff_macros::{ViolationMetadata, derive_message_formats};
|
||||
|
||||
use crate::Violation;
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for uses of `os.makedirs`.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// `pathlib` offers a high-level API for path manipulation, as compared to
|
||||
/// the lower-level API offered by `os`. When possible, using `Path` object
|
||||
/// methods such as `Path.mkdir(parents=True)` can improve readability over the
|
||||
/// `os` module's counterparts (e.g., `os.makedirs()`.
|
||||
///
|
||||
/// ## Examples
|
||||
/// ```python
|
||||
/// import os
|
||||
///
|
||||
/// os.makedirs("./nested/directory/")
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// from pathlib import Path
|
||||
///
|
||||
/// Path("./nested/directory/").mkdir(parents=True)
|
||||
/// ```
|
||||
///
|
||||
/// ## Known issues
|
||||
/// While using `pathlib` can improve the readability and type safety of your code,
|
||||
/// it can be less performant than the lower-level alternatives that work directly with strings,
|
||||
/// especially on older versions of Python.
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: `Path.mkdir`](https://docs.python.org/3/library/pathlib.html#pathlib.Path.mkdir)
|
||||
/// - [Python documentation: `os.makedirs`](https://docs.python.org/3/library/os.html#os.makedirs)
|
||||
/// - [PEP 428 – The pathlib module – object-oriented filesystem paths](https://peps.python.org/pep-0428/)
|
||||
/// - [Correspondence between `os` and `pathlib`](https://docs.python.org/3/library/pathlib.html#correspondence-to-tools-in-the-os-module)
|
||||
/// - [Why you should be using pathlib](https://treyhunner.com/2018/12/why-you-should-be-using-pathlib/)
|
||||
/// - [No really, pathlib is great](https://treyhunner.com/2019/01/no-really-pathlib-is-great/)
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct OsMakedirs;
|
||||
|
||||
impl Violation for OsMakedirs {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
"`os.makedirs()` should be replaced by `Path.mkdir(parents=True)`".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for uses of `os.mkdir`.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// `pathlib` offers a high-level API for path manipulation, as compared to
|
||||
/// the lower-level API offered by `os`. When possible, using `Path` object
|
||||
/// methods such as `Path.mkdir()` can improve readability over the `os`
|
||||
/// module's counterparts (e.g., `os.mkdir()`).
|
||||
///
|
||||
/// ## Examples
|
||||
/// ```python
|
||||
/// import os
|
||||
///
|
||||
/// os.mkdir("./directory/")
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// from pathlib import Path
|
||||
///
|
||||
/// Path("./directory/").mkdir()
|
||||
/// ```
|
||||
///
|
||||
/// ## Known issues
|
||||
/// While using `pathlib` can improve the readability and type safety of your code,
|
||||
/// it can be less performant than the lower-level alternatives that work directly with strings,
|
||||
/// especially on older versions of Python.
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: `Path.mkdir`](https://docs.python.org/3/library/pathlib.html#pathlib.Path.mkdir)
|
||||
/// - [Python documentation: `os.mkdir`](https://docs.python.org/3/library/os.html#os.mkdir)
|
||||
/// - [PEP 428 – The pathlib module – object-oriented filesystem paths](https://peps.python.org/pep-0428/)
|
||||
/// - [Correspondence between `os` and `pathlib`](https://docs.python.org/3/library/pathlib.html#correspondence-to-tools-in-the-os-module)
|
||||
/// - [Why you should be using pathlib](https://treyhunner.com/2018/12/why-you-should-be-using-pathlib/)
|
||||
/// - [No really, pathlib is great](https://treyhunner.com/2019/01/no-really-pathlib-is-great/)
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct OsMkdir;
|
||||
|
||||
impl Violation for OsMkdir {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
"`os.mkdir()` should be replaced by `Path.mkdir()`".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for uses of `os.stat`.
|
||||
///
|
||||
@@ -310,3 +400,45 @@ impl Violation for OsListdir {
|
||||
"Use `pathlib.Path.iterdir()` instead.".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
/// ## What it does
|
||||
/// Checks for uses of `os.symlink`.
|
||||
///
|
||||
/// ## Why is this bad?
|
||||
/// `pathlib` offers a high-level API for path manipulation, as compared to
|
||||
/// the lower-level API offered by `os.symlink`.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```python
|
||||
/// import os
|
||||
///
|
||||
/// os.symlink("usr/bin/python", "tmp/python", target_is_directory=False)
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```python
|
||||
/// from pathlib import Path
|
||||
///
|
||||
/// Path("tmp/python").symlink_to("usr/bin/python")
|
||||
/// ```
|
||||
///
|
||||
/// ## Known issues
|
||||
/// While using `pathlib` can improve the readability and type safety of your code,
|
||||
/// it can be less performant than the lower-level alternatives that work directly with strings,
|
||||
/// especially on older versions of Python.
|
||||
///
|
||||
/// ## References
|
||||
/// - [Python documentation: `Path.symlink_to`](https://docs.python.org/3/library/pathlib.html#pathlib.Path.symlink_to)
|
||||
/// - [PEP 428 – The pathlib module – object-oriented filesystem paths](https://peps.python.org/pep-0428/)
|
||||
/// - [Correspondence between `os` and `pathlib`](https://docs.python.org/3/library/pathlib.html#correspondence-to-tools-in-the-os-module)
|
||||
/// - [Why you should be using pathlib](https://treyhunner.com/2018/12/why-you-should-be-using-pathlib/)
|
||||
/// - [No really, pathlib is great](https://treyhunner.com/2019/01/no-really-pathlib-is-great/)
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct OsSymlink;
|
||||
|
||||
impl Violation for OsSymlink {
|
||||
#[derive_message_formats]
|
||||
fn message(&self) -> String {
|
||||
"`os.symlink` should be replaced by `Path.symlink_to`".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ fn to_interpolated_string_interpolation_element(inner: &Expr) -> ast::Interpolat
|
||||
conversion: ConversionFlag::None,
|
||||
format_spec: None,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ pub(super) fn to_interpolated_string_literal_element(s: &str) -> ast::Interpolat
|
||||
ast::InterpolatedStringElement::Literal(ast::InterpolatedStringLiteralElement {
|
||||
value: Box::from(s),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ fn build_fstring(joiner: &str, joinees: &[Expr], flags: FStringFlags) -> Option<
|
||||
.into_boxed_str(),
|
||||
flags: flags?,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
};
|
||||
return Some(node.into());
|
||||
}
|
||||
@@ -114,7 +114,7 @@ fn build_fstring(joiner: &str, joinees: &[Expr], flags: FStringFlags) -> Option<
|
||||
let node = ast::FString {
|
||||
elements: f_string_elements.into(),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
flags,
|
||||
};
|
||||
Some(node.into())
|
||||
|
||||
@@ -60,7 +60,7 @@ const BLANK_LINES_NESTED_LEVEL: u32 = 1;
|
||||
/// ## References
|
||||
/// - [PEP 8: Blank Lines](https://peps.python.org/pep-0008/#blank-lines)
|
||||
/// - [Flake 8 rule](https://www.flake8rules.com/rules/E301.html)
|
||||
/// - [Typing Style Guide](https://typing.python.org/en/latest/guides/writing_stubs.html#blank-lines)
|
||||
/// - [Typing Style Guide](https://typing.python.org/en/latest/source/stubs.html#blank-lines)
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct BlankLineBetweenMethods;
|
||||
|
||||
@@ -113,7 +113,7 @@ impl AlwaysFixableViolation for BlankLineBetweenMethods {
|
||||
/// ## References
|
||||
/// - [PEP 8: Blank Lines](https://peps.python.org/pep-0008/#blank-lines)
|
||||
/// - [Flake 8 rule](https://www.flake8rules.com/rules/E302.html)
|
||||
/// - [Typing Style Guide](https://typing.python.org/en/latest/guides/writing_stubs.html#blank-lines)
|
||||
/// - [Typing Style Guide](https://typing.python.org/en/latest/source/stubs.html#blank-lines)
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct BlankLinesTopLevel {
|
||||
actual_blank_lines: u32,
|
||||
@@ -180,7 +180,7 @@ impl AlwaysFixableViolation for BlankLinesTopLevel {
|
||||
/// ## References
|
||||
/// - [PEP 8: Blank Lines](https://peps.python.org/pep-0008/#blank-lines)
|
||||
/// - [Flake 8 rule](https://www.flake8rules.com/rules/E303.html)
|
||||
/// - [Typing Style Guide](https://typing.python.org/en/latest/guides/writing_stubs.html#blank-lines)
|
||||
/// - [Typing Style Guide](https://typing.python.org/en/latest/source/stubs.html#blank-lines)
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct TooManyBlankLines {
|
||||
actual_blank_lines: u32,
|
||||
@@ -277,7 +277,7 @@ impl AlwaysFixableViolation for BlankLineAfterDecorator {
|
||||
/// ## References
|
||||
/// - [PEP 8: Blank Lines](https://peps.python.org/pep-0008/#blank-lines)
|
||||
/// - [Flake 8 rule](https://www.flake8rules.com/rules/E305.html)
|
||||
/// - [Typing Style Guide](https://typing.python.org/en/latest/guides/writing_stubs.html#blank-lines)
|
||||
/// - [Typing Style Guide](https://typing.python.org/en/latest/source/stubs.html#blank-lines)
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct BlankLinesAfterFunctionOrClass {
|
||||
actual_blank_lines: u32,
|
||||
@@ -331,7 +331,7 @@ impl AlwaysFixableViolation for BlankLinesAfterFunctionOrClass {
|
||||
/// ## References
|
||||
/// - [PEP 8: Blank Lines](https://peps.python.org/pep-0008/#blank-lines)
|
||||
/// - [Flake 8 rule](https://www.flake8rules.com/rules/E306.html)
|
||||
/// - [Typing Style Guide](https://typing.python.org/en/latest/guides/writing_stubs.html#blank-lines)
|
||||
/// - [Typing Style Guide](https://typing.python.org/en/latest/source/stubs.html#blank-lines)
|
||||
#[derive(ViolationMetadata)]
|
||||
pub(crate) struct BlankLinesBeforeNestedDefinition;
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ fn function(
|
||||
ExprEllipsisLiteral::default(),
|
||||
))),
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
});
|
||||
let parameters = lambda.parameters.as_deref().cloned().unwrap_or_default();
|
||||
if let Some(annotation) = annotation {
|
||||
@@ -230,7 +230,7 @@ fn function(
|
||||
returns: Some(Box::new(return_type)),
|
||||
type_params: None,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
});
|
||||
let generated = checker.generator().stmt(&func);
|
||||
|
||||
@@ -246,7 +246,7 @@ fn function(
|
||||
returns: None,
|
||||
type_params: None,
|
||||
range: TextRange::default(),
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::NONE,
|
||||
node_index: ruff_python_ast::AtomicNodeIndex::dummy(),
|
||||
});
|
||||
let generated = checker.generator().stmt(&function);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user