Compare commits
2 Commits
v0.0.243
...
charlie/fl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7479c943a4 | ||
|
|
e4303e2c68 |
@@ -1,28 +1,2 @@
|
||||
[alias]
|
||||
dev = "run --package ruff_dev --bin ruff_dev"
|
||||
|
||||
[target.'cfg(all())']
|
||||
rustflags = [
|
||||
# CLIPPY LINT SETTINGS
|
||||
# This is a workaround to configure lints for the entire workspace, pending the ability to configure this via TOML.
|
||||
# See: `https://github.com/rust-lang/cargo/issues/5034`
|
||||
# `https://github.com/EmbarkStudios/rust-ecosystem/issues/22#issuecomment-947011395`
|
||||
"-Dunsafe_code",
|
||||
"-Wclippy::pedantic",
|
||||
# Allowed pedantic lints
|
||||
"-Wclippy::char_lit_as_u8",
|
||||
"-Aclippy::collapsible_else_if",
|
||||
"-Aclippy::collapsible_if",
|
||||
"-Aclippy::implicit_hasher",
|
||||
"-Aclippy::match_same_arms",
|
||||
"-Aclippy::missing_errors_doc",
|
||||
"-Aclippy::missing_panics_doc",
|
||||
"-Aclippy::module_name_repetitions",
|
||||
"-Aclippy::must_use_candidate",
|
||||
"-Aclippy::similar_names",
|
||||
"-Aclippy::too_many_lines",
|
||||
# Disallowed restriction lints
|
||||
"-Wclippy::print_stdout",
|
||||
"-Wclippy::print_stderr",
|
||||
"-Wclippy::dbg_macro",
|
||||
]
|
||||
|
||||
8
.github/ISSUE_TEMPLATE.md
vendored
8
.github/ISSUE_TEMPLATE.md
vendored
@@ -3,8 +3,8 @@ Thank you for taking the time to report an issue! We're glad to have you involve
|
||||
|
||||
If you're filing a bug report, please consider including the following information:
|
||||
|
||||
* A minimal code snippet that reproduces the bug.
|
||||
* The command you invoked (e.g., `ruff /path/to/file.py --fix`), ideally including the `--isolated` flag.
|
||||
* The current Ruff settings (any relevant sections from your `pyproject.toml`).
|
||||
* The current Ruff version (`ruff --version`).
|
||||
- A minimal code snippet that reproduces the bug.
|
||||
- The command you invoked (e.g., `ruff /path/to/file.py --fix`), ideally including the `--isolated` flag.
|
||||
- The current Ruff settings (any relevant sections from your `pyproject.toml`).
|
||||
- The current Ruff version (`ruff --version`).
|
||||
-->
|
||||
|
||||
19
.github/release.yml
vendored
19
.github/release.yml
vendored
@@ -1,19 +0,0 @@
|
||||
# https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes#configuring-automatically-generated-release-notes
|
||||
changelog:
|
||||
categories:
|
||||
- title: Breaking Changes
|
||||
labels:
|
||||
- breaking
|
||||
- title: Rules
|
||||
labels:
|
||||
- rule
|
||||
- autofix
|
||||
- title: Settings
|
||||
labels:
|
||||
- configuration
|
||||
- title: Bug Fixes
|
||||
labels:
|
||||
- bug
|
||||
- title: Other Changes
|
||||
labels:
|
||||
- "*"
|
||||
129
.github/workflows/ci.yaml
vendored
129
.github/workflows/ci.yaml
vendored
@@ -4,7 +4,7 @@ on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
branches: [main]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
|
||||
@@ -13,7 +13,6 @@ concurrency:
|
||||
env:
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_NET_RETRY: 10
|
||||
CARGO_TERM_COLOR: always
|
||||
RUSTUP_MAX_RETRIES: 10
|
||||
|
||||
jobs:
|
||||
@@ -22,13 +21,16 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: nightly-2022-11-01
|
||||
override: true
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- run: cargo build --all
|
||||
- run: ./target/debug/ruff_dev generate-all
|
||||
- run: git diff --quiet README.md || echo "::error file=README.md::This file is outdated. Run 'cargo dev generate-all'."
|
||||
- run: git diff --quiet ruff.schema.json || echo "::error file=ruff.schema.json::This file is outdated. Run 'cargo dev generate-all'."
|
||||
- run: git diff --quiet README.md || echo "::error file=README.md::This file is outdated. Run 'cargo +nightly dev generate-all'."
|
||||
- run: git diff --quiet ruff.schema.json || echo "::error file=ruff.schema.json::This file is outdated. Run 'cargo +nightly dev generate-all'."
|
||||
- run: git diff --exit-code -- README.md ruff.schema.json
|
||||
|
||||
cargo-fmt:
|
||||
@@ -36,8 +38,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup component add rustfmt
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: nightly-2022-11-01
|
||||
override: true
|
||||
components: rustfmt
|
||||
- run: cargo fmt --all --check
|
||||
|
||||
cargo_clippy:
|
||||
@@ -45,80 +51,111 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: "Install Rust toolchain"
|
||||
run: |
|
||||
rustup component add clippy
|
||||
rustup target add wasm32-unknown-unknown
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: nightly-2022-11-01
|
||||
override: true
|
||||
components: clippy
|
||||
target: wasm32-unknown-unknown
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- run: cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
- run: cargo clippy -p ruff --target wasm32-unknown-unknown --all-features -- -D warnings
|
||||
- run: cargo clippy --workspace --all-targets --all-features -- -D warnings -W clippy::pedantic
|
||||
- run: cargo clippy -p ruff --target wasm32-unknown-unknown --all-features -- -D warnings -W clippy::pedantic
|
||||
|
||||
cargo-test:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: "cargo test | ${{ matrix.os }}"
|
||||
name: "cargo test"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: 1.65.0
|
||||
override: true
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- run: cargo install cargo-insta
|
||||
- run: pip install black[d]==22.12.0
|
||||
- name: "Run tests (Ubuntu)"
|
||||
if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||
- name: Run tests
|
||||
run: |
|
||||
cargo insta test --all --all-features --delete-unreferenced-snapshots
|
||||
git diff --exit-code
|
||||
- name: "Run tests (Windows)"
|
||||
if: ${{ matrix.os == 'windows-latest' }}
|
||||
shell: bash
|
||||
run: |
|
||||
cargo insta test --all --all-features
|
||||
cargo insta test --all --delete-unreferenced-snapshots
|
||||
git diff --exit-code
|
||||
- run: cargo test --package ruff_cli --test black_compatibility_test -- --ignored
|
||||
# Check for broken links in the documentation.
|
||||
- run: cargo doc --all --no-deps
|
||||
env:
|
||||
# Setting RUSTDOCFLAGS because `cargo doc --check` isn't yet implemented (https://github.com/rust-lang/cargo/issues/10025).
|
||||
RUSTDOCFLAGS: "-D warnings"
|
||||
# Setting RUSTDOCFLAGS because `cargo doc --check` isn't yet implemented (https://github.com/rust-lang/cargo/issues/10025).
|
||||
- run: RUSTDOCFLAGS="-D warnings" cargo doc --all --no-deps
|
||||
|
||||
scripts:
|
||||
name: "test scripts"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
override: true
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- run: ./scripts/add_rule.py --name DoTheThing --code PLC999 --linter pylint
|
||||
- run: cargo check
|
||||
- run: |
|
||||
./scripts/add_plugin.py test --url https://pypi.org/project/-test/0.1.0/ --prefix TST
|
||||
./scripts/add_rule.py --name FirstRule --code TST001 --linter test
|
||||
./scripts/add_plugin.py test --url https://pypi.org/project/-test/0.1.0/ --prefix TST
|
||||
./scripts/add_rule.py --name FirstRule --code TST001 --linter test
|
||||
- run: cargo check
|
||||
|
||||
# TODO(charlie): Re-enable the `wasm-pack` tests.
|
||||
# See: https://github.com/charliermarsh/ruff/issues/1425
|
||||
# wasm-pack-test:
|
||||
# name: "wasm-pack test"
|
||||
# runs-on: ubuntu-latest
|
||||
# env:
|
||||
# WASM_BINDGEN_TEST_TIMEOUT: 60
|
||||
# steps:
|
||||
# - uses: actions/checkout@v3
|
||||
# - uses: actions-rs/toolchain@v1
|
||||
# with:
|
||||
# profile: minimal
|
||||
# toolchain: nightly-2022-11-01
|
||||
# override: true
|
||||
# - uses: actions/cache@v3
|
||||
# env:
|
||||
# cache-name: cache-cargo
|
||||
# with:
|
||||
# path: |
|
||||
# ~/.cargo/registry
|
||||
# ~/.cargo/git
|
||||
# key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
|
||||
# restore-keys: |
|
||||
# ${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
# ${{ runner.os }}-build-
|
||||
# ${{ runner.os }}-
|
||||
# - uses: jetli/wasm-pack-action@v0.4.0
|
||||
# - uses: jetli/wasm-bindgen-action@v0.2.0
|
||||
# - run: wasm-pack test --node
|
||||
|
||||
maturin-build:
|
||||
name: "maturin build"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: 1.65.0
|
||||
override: true
|
||||
- uses: Swatinem/rust-cache@v1
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.11"
|
||||
- run: pip install maturin
|
||||
- run: maturin build -b bin
|
||||
- run: python scripts/transform_readme.py --target pypi
|
||||
|
||||
typos:
|
||||
name: "spell check"
|
||||
name: Spell Check with Typos
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: crate-ci/typos@master
|
||||
with:
|
||||
files: .
|
||||
- name: Checkout Actions Repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Check spelling of file.txt
|
||||
uses: crate-ci/typos@master
|
||||
with:
|
||||
files: .
|
||||
|
||||
34
.github/workflows/docs.yaml
vendored
34
.github/workflows/docs.yaml
vendored
@@ -1,34 +0,0 @@
|
||||
name: mkdocs
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- README.md
|
||||
- mkdocs.template.yml
|
||||
- .github/workflows/docs.yaml
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
mkdocs:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
- name: "Install dependencies"
|
||||
run: |
|
||||
pip install "mkdocs~=1.4.2" "mkdocs-material~=9.0.6"
|
||||
- name: "Copy README File"
|
||||
run: |
|
||||
python scripts/transform_readme.py --target mkdocs
|
||||
python scripts/generate_mkdocs.py
|
||||
mkdocs build --strict
|
||||
- name: "Deploy to Cloudflare Pages"
|
||||
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
|
||||
uses: cloudflare/wrangler-action@2.0.0
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
accountId: ${{ secrets.CF_ACCOUNT_ID }}
|
||||
command: pages publish site --project-name=ruff-docs --branch ${GITHUB_HEAD_REF} --commit-hash ${GITHUB_SHA}
|
||||
148
.github/workflows/flake8-to-ruff.yaml
vendored
148
.github/workflows/flake8-to-ruff.yaml
vendored
@@ -1,6 +1,7 @@
|
||||
name: "[flake8-to-ruff] Release"
|
||||
|
||||
on: workflow_dispatch
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -9,55 +10,63 @@ concurrency:
|
||||
env:
|
||||
PACKAGE_NAME: flake8-to-ruff
|
||||
CRATE_NAME: flake8_to_ruff
|
||||
PYTHON_VERSION: "3.7" # to build abi3 wheels
|
||||
PYTHON_VERSION: "3.11"
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_NET_RETRY: 10
|
||||
CARGO_TERM_COLOR: always
|
||||
RUSTUP_MAX_RETRIES: 10
|
||||
|
||||
jobs:
|
||||
macos-x86_64:
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-12
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
architecture: x64
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- name: "Build wheels - x86_64"
|
||||
- name: Install Rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
profile: minimal
|
||||
default: true
|
||||
- name: Build wheels - x86_64
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
target: x86_64
|
||||
args: --release --out dist --sdist -m ./${{ env.CRATE_NAME }}/Cargo.toml
|
||||
- name: "Install built wheel - x86_64"
|
||||
- name: Install built wheel - x86_64
|
||||
run: |
|
||||
pip install dist/${{ env.CRATE_NAME }}-*.whl --force-reinstall
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wheels
|
||||
path: dist
|
||||
|
||||
macos-universal:
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-14
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
architecture: x64
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- name: "Build wheels - universal2"
|
||||
- name: Install Rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
profile: minimal
|
||||
default: true
|
||||
- name: Build wheels - universal2
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
args: --release --universal2 --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
|
||||
- name: "Install built wheel - universal2"
|
||||
- name: Install built wheel - universal2
|
||||
run: |
|
||||
pip install dist/${{ env.CRATE_NAME }}-*universal2.whl --force-reinstall
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wheels
|
||||
path: dist
|
||||
@@ -73,19 +82,23 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
architecture: ${{ matrix.target }}
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- name: "Build wheels"
|
||||
- name: Install Rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
profile: minimal
|
||||
default: true
|
||||
- name: Build wheels
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
args: --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
|
||||
- name: "Install built wheel"
|
||||
- name: Install built wheel
|
||||
shell: bash
|
||||
run: |
|
||||
python -m pip install dist/${{ env.CRATE_NAME }}-*.whl --force-reinstall
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wheels
|
||||
path: dist
|
||||
@@ -101,18 +114,18 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
architecture: x64
|
||||
- name: "Build wheels"
|
||||
- name: Build wheels
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: auto
|
||||
args: --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
|
||||
- name: "Install built wheel"
|
||||
- name: Install built wheel
|
||||
if: matrix.target == 'x86_64'
|
||||
run: |
|
||||
pip install dist/${{ env.CRATE_NAME }}-*.whl --force-reinstall
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wheels
|
||||
path: dist
|
||||
@@ -127,13 +140,13 @@ jobs:
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
- name: "Build wheels"
|
||||
- name: Build wheels
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: auto
|
||||
args: --no-default-features --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
|
||||
- uses: uraimo/run-on-arch-action@v2.5.0
|
||||
- uses: uraimo/run-on-arch-action@v2.0.5
|
||||
if: matrix.target != 'ppc64'
|
||||
name: Install built wheel
|
||||
with:
|
||||
@@ -146,8 +159,8 @@ jobs:
|
||||
pip3 install -U pip
|
||||
run: |
|
||||
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wheels
|
||||
path: dist
|
||||
@@ -165,13 +178,13 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
architecture: x64
|
||||
- name: "Build wheels"
|
||||
- name: Build wheels
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: musllinux_1_2
|
||||
args: --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
|
||||
- name: "Install built wheel"
|
||||
- name: Install built wheel
|
||||
if: matrix.target == 'x86_64-unknown-linux-musl'
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
@@ -180,8 +193,8 @@ jobs:
|
||||
run: |
|
||||
apk add py3-pip
|
||||
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links /io/dist/ --force-reinstall
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wheels
|
||||
path: dist
|
||||
@@ -200,7 +213,7 @@ jobs:
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
- name: "Build wheels"
|
||||
- name: Build wheels
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
target: ${{ matrix.platform.target }}
|
||||
@@ -216,67 +229,8 @@ jobs:
|
||||
apk add py3-pip
|
||||
run: |
|
||||
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wheels
|
||||
path: dist
|
||||
|
||||
pypy:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
target: [x86_64, aarch64]
|
||||
python-version:
|
||||
- "3.7"
|
||||
- "3.8"
|
||||
- "3.9"
|
||||
exclude:
|
||||
- os: macos-latest
|
||||
target: aarch64
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: pypy${{ matrix.python-version }}
|
||||
- name: "Build wheels"
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: auto
|
||||
args: --release --out dist -i pypy${{ matrix.python-version }} -m ./${{ env.CRATE_NAME }}/Cargo.toml
|
||||
- name: "Install built wheel"
|
||||
if: matrix.target == 'x86_64'
|
||||
run: |
|
||||
pip install dist/${{ env.CRATE_NAME }}-*.whl --force-reinstall
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: wheels
|
||||
path: dist
|
||||
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- macos-universal
|
||||
- macos-x86_64
|
||||
- windows
|
||||
- linux
|
||||
- linux-cross
|
||||
- musllinux
|
||||
- musllinux-cross
|
||||
- pypy
|
||||
steps:
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: wheels
|
||||
- uses: actions/setup-python@v4
|
||||
- name: "Publish to PyPi"
|
||||
env:
|
||||
TWINE_USERNAME: __token__
|
||||
TWINE_PASSWORD: ${{ secrets.FLAKE8_TO_RUFF_TOKEN }}
|
||||
run: |
|
||||
pip install --upgrade twine
|
||||
twine upload --skip-existing *
|
||||
|
||||
13
.github/workflows/playground.yaml
vendored
13
.github/workflows/playground.yaml
vendored
@@ -8,18 +8,21 @@ on:
|
||||
env:
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_NET_RETRY: 10
|
||||
CARGO_TERM_COLOR: always
|
||||
RUSTUP_MAX_RETRIES: 10
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
|
||||
CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup target add wasm32-unknown-unknown
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: nightly-2022-11-01
|
||||
override: true
|
||||
target: wasm32-unknown-unknown
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
@@ -28,7 +31,7 @@ jobs:
|
||||
- uses: jetli/wasm-pack-action@v0.4.0
|
||||
- uses: jetli/wasm-bindgen-action@v0.2.0
|
||||
- name: "Run wasm-pack"
|
||||
run: wasm-pack build --target web --out-dir ../../playground/src/pkg crates/ruff
|
||||
run: wasm-pack build --target web --out-dir playground/src/pkg . -- -p ruff
|
||||
- name: "Install Node dependencies"
|
||||
run: npm ci
|
||||
working-directory: playground
|
||||
|
||||
106
.github/workflows/ruff.yaml
vendored
106
.github/workflows/ruff.yaml
vendored
@@ -1,7 +1,6 @@
|
||||
name: "[ruff] Release"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
@@ -14,7 +13,6 @@ env:
|
||||
PYTHON_VERSION: "3.7" # to build abi3 wheels
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_NET_RETRY: 10
|
||||
CARGO_TERM_COLOR: always
|
||||
RUSTUP_MAX_RETRIES: 10
|
||||
|
||||
jobs:
|
||||
@@ -26,18 +24,22 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
architecture: x64
|
||||
- name: "Prep README.md"
|
||||
run: python scripts/transform_readme.py --target pypi
|
||||
- name: "Build wheels - x86_64"
|
||||
- name: Install Rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
profile: minimal
|
||||
default: true
|
||||
- name: Build wheels - x86_64
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
target: x86_64
|
||||
args: --release --out dist --sdist
|
||||
- name: "Install built wheel - x86_64"
|
||||
- name: Install built wheel - x86_64
|
||||
run: |
|
||||
pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wheels
|
||||
path: dist
|
||||
@@ -49,17 +51,21 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
architecture: x64
|
||||
- name: "Prep README.md"
|
||||
run: python scripts/transform_readme.py --target pypi
|
||||
- name: "Build wheels - universal2"
|
||||
- name: Install Rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
profile: minimal
|
||||
default: true
|
||||
- name: Build wheels - universal2
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
args: --release --universal2 --out dist
|
||||
- name: "Install built wheel - universal2"
|
||||
- name: Install built wheel - universal2
|
||||
run: |
|
||||
pip install dist/${{ env.PACKAGE_NAME }}-*universal2.whl --force-reinstall
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wheels
|
||||
path: dist
|
||||
@@ -75,19 +81,23 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
architecture: ${{ matrix.target }}
|
||||
- name: "Prep README.md"
|
||||
run: python scripts/transform_readme.py --target pypi
|
||||
- name: "Build wheels"
|
||||
- name: Install Rust toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
profile: minimal
|
||||
default: true
|
||||
- name: Build wheels
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
args: --release --out dist
|
||||
- name: "Install built wheel"
|
||||
- name: Install built wheel
|
||||
shell: bash
|
||||
run: |
|
||||
python -m pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wheels
|
||||
path: dist
|
||||
@@ -103,20 +113,18 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
architecture: x64
|
||||
- name: "Prep README.md"
|
||||
run: python scripts/transform_readme.py --target pypi
|
||||
- name: "Build wheels"
|
||||
- name: Build wheels
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: auto
|
||||
args: --release --out dist
|
||||
- name: "Install built wheel"
|
||||
- name: Install built wheel
|
||||
if: matrix.target == 'x86_64'
|
||||
run: |
|
||||
pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wheels
|
||||
path: dist
|
||||
@@ -131,15 +139,13 @@ jobs:
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
- name: "Prep README.md"
|
||||
run: python scripts/transform_readme.py --target pypi
|
||||
- name: "Build wheels"
|
||||
- name: Build wheels
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: auto
|
||||
args: --release --out dist
|
||||
- uses: uraimo/run-on-arch-action@v2.5.0
|
||||
args: --no-default-features --release --out dist
|
||||
- uses: uraimo/run-on-arch-action@v2.0.5
|
||||
if: matrix.target != 'ppc64'
|
||||
name: Install built wheel
|
||||
with:
|
||||
@@ -152,8 +158,8 @@ jobs:
|
||||
pip3 install -U pip
|
||||
run: |
|
||||
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wheels
|
||||
path: dist
|
||||
@@ -171,15 +177,13 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
architecture: x64
|
||||
- name: "Prep README.md"
|
||||
run: python scripts/transform_readme.py --target pypi
|
||||
- name: "Build wheels"
|
||||
- name: Build wheels
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: musllinux_1_2
|
||||
args: --release --out dist
|
||||
- name: "Install built wheel"
|
||||
- name: Install built wheel
|
||||
if: matrix.target == 'x86_64-unknown-linux-musl'
|
||||
uses: addnab/docker-run-action@v3
|
||||
with:
|
||||
@@ -188,8 +192,8 @@ jobs:
|
||||
run: |
|
||||
apk add py3-pip
|
||||
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links /io/dist/ --force-reinstall
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wheels
|
||||
path: dist
|
||||
@@ -208,9 +212,7 @@ jobs:
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
- name: "Prep README.md"
|
||||
run: python scripts/transform_readme.py --target pypi
|
||||
- name: "Build wheels"
|
||||
- name: Build wheels
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
target: ${{ matrix.platform.target }}
|
||||
@@ -226,8 +228,8 @@ jobs:
|
||||
apk add py3-pip
|
||||
run: |
|
||||
pip3 install ${{ env.PACKAGE_NAME }} --no-index --find-links dist/ --force-reinstall
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wheels
|
||||
path: dist
|
||||
@@ -250,20 +252,18 @@ jobs:
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: pypy${{ matrix.python-version }}
|
||||
- name: "Prep README.md"
|
||||
run: python scripts/transform_readme.py --target pypi
|
||||
- name: "Build wheels"
|
||||
- name: Build wheels
|
||||
uses: messense/maturin-action@v1
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
manylinux: auto
|
||||
args: --release --out dist -i pypy${{ matrix.python-version }}
|
||||
- name: "Install built wheel"
|
||||
- name: Install built wheel
|
||||
if: matrix.target == 'x86_64'
|
||||
run: |
|
||||
pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
|
||||
- name: "Upload wheels"
|
||||
uses: actions/upload-artifact@v3
|
||||
- name: Upload wheels
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: wheels
|
||||
path: dist
|
||||
@@ -282,17 +282,17 @@ jobs:
|
||||
- pypy
|
||||
if: "startsWith(github.ref, 'refs/tags/')"
|
||||
steps:
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: wheels
|
||||
- uses: actions/setup-python@v4
|
||||
- name: "Publish to PyPi"
|
||||
- name: Publish to PyPi
|
||||
env:
|
||||
TWINE_USERNAME: __token__
|
||||
TWINE_PASSWORD: ${{ secrets.RUFF_TOKEN }}
|
||||
run: |
|
||||
pip install --upgrade twine
|
||||
twine upload --skip-existing *
|
||||
- name: "Update pre-commit mirror"
|
||||
- name: Update pre-commit mirror
|
||||
run: |
|
||||
curl -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.RUFF_PRE_COMMIT_PAT }}" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/charliermarsh/ruff-pre-commit/dispatches --data '{"event_type": "pypi_release"}'
|
||||
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -1,9 +1,6 @@
|
||||
# Local cache
|
||||
.ruff_cache
|
||||
crates/ruff/resources/test/cpython
|
||||
docs/
|
||||
mkdocs.yml
|
||||
.overrides
|
||||
resources/test/cpython
|
||||
|
||||
###
|
||||
# Rust.gitignore
|
||||
@@ -185,6 +182,3 @@ cython_debug/
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
.idea/
|
||||
.vimspector.json
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
repos:
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: v0.0.231
|
||||
hooks:
|
||||
- id: ruff
|
||||
|
||||
- repo: https://github.com/abravalheri/validate-pyproject
|
||||
rev: v0.10.1
|
||||
hooks:
|
||||
- id: validate-pyproject
|
||||
|
||||
- repo: https://github.com/igorshubovych/markdownlint-cli
|
||||
rev: v0.33.0
|
||||
hooks:
|
||||
- id: markdownlint-fix
|
||||
args:
|
||||
- --disable
|
||||
- MD013 # line-length
|
||||
- MD033 # no-inline-html
|
||||
- --
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: cargo-fmt
|
||||
@@ -21,24 +16,3 @@ repos:
|
||||
entry: cargo fmt --
|
||||
language: rust
|
||||
types: [rust]
|
||||
- id: clippy
|
||||
name: clippy
|
||||
entry: cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
language: rust
|
||||
pass_filenames: false
|
||||
- id: ruff
|
||||
name: ruff
|
||||
entry: cargo run -- --no-cache --fix
|
||||
language: rust
|
||||
types_or: [python, pyi]
|
||||
require_serial: true
|
||||
exclude: ^crates/ruff/resources
|
||||
- id: dev-generate-all
|
||||
name: dev-generate-all
|
||||
entry: cargo dev generate-all
|
||||
language: rust
|
||||
pass_filenames: false
|
||||
exclude: target
|
||||
|
||||
ci:
|
||||
skip: [cargo-fmt, clippy, dev-generate-all]
|
||||
|
||||
@@ -1,85 +1,5 @@
|
||||
# Breaking Changes
|
||||
|
||||
## 0.0.238
|
||||
|
||||
### `select`, `extend-select`, `ignore`, and `extend-ignore` have new semantics ([#2312](https://github.com/charliermarsh/ruff/pull/2312))
|
||||
|
||||
Previously, the interplay between `select` and its related options could lead to unexpected
|
||||
behavior. For example, `ruff --select E501 --ignore ALL` and `ruff --select E501 --extend-ignore
|
||||
ALL` behaved differently. (See [#2312](https://github.com/charliermarsh/ruff/pull/2312) for more
|
||||
examples.)
|
||||
|
||||
When Ruff determines the enabled rule set, it has to reconcile `select` and `ignore` from a variety
|
||||
of sources, including the current `pyproject.toml`, any inherited `pyproject.toml` files, and the
|
||||
CLI.
|
||||
|
||||
The new semantics are such that Ruff uses the "highest-priority" `select` as the basis for the rule
|
||||
set, and then applies any `extend-select`, `ignore`, and `extend-ignore` adjustments. CLI options
|
||||
are given higher priority than `pyproject.toml` options, and the current `pyproject.toml` file is
|
||||
given higher priority than any inherited `pyproject.toml` files.
|
||||
|
||||
`extend-select` and `extend-ignore` are no longer given "top priority"; instead, they merely append
|
||||
to the `select` and `ignore` lists, as in Flake8.
|
||||
|
||||
This change is largely backwards compatible -- most users should experience no change in behavior.
|
||||
However, as an example of a breaking change, consider the following:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
ignore = ["F401"]
|
||||
```
|
||||
|
||||
Running `ruff --select F` would previously have enabled all `F` rules, apart from `F401`. Now, it
|
||||
will enable all `F` rules, including `F401`, as the command line's `--select` resets the resolution.
|
||||
|
||||
### `remove-six-compat` (`UP016`) has been removed ([#2332](https://github.com/charliermarsh/ruff/pull/2332))
|
||||
|
||||
The `remove-six-compat` rule has been removed. This rule was only useful for one-time Python 2-to-3
|
||||
upgrades.
|
||||
|
||||
## 0.0.237
|
||||
|
||||
### `--explain`, `--clean`, and `--generate-shell-completion` are now subcommands ([#2190](https://github.com/charliermarsh/ruff/pull/2190))
|
||||
|
||||
`--explain`, `--clean`, and `--generate-shell-completion` are now implemented as subcommands:
|
||||
|
||||
```console
|
||||
ruff . # Still works! And will always work.
|
||||
ruff check . # New! Also works.
|
||||
|
||||
ruff --explain E402 # Still works.
|
||||
ruff rule E402 # New! Also works. (And preferred.)
|
||||
|
||||
# Oops! The command has to come first.
|
||||
ruff --format json --explain E402 # No longer works.
|
||||
ruff --explain E402 --format json # Still works!
|
||||
ruff rule E402 --format json # Works! (And preferred.)
|
||||
```
|
||||
|
||||
This change is largely backwards compatible -- most users should experience
|
||||
no change in behavior. However, please note the following exceptions:
|
||||
|
||||
* Subcommands will now fail when invoked with unsupported arguments, instead
|
||||
of silently ignoring them. For example, the following will now fail:
|
||||
|
||||
```console
|
||||
ruff --clean --respect-gitignore
|
||||
```
|
||||
|
||||
(the `clean` command doesn't support `--respect-gitignore`.)
|
||||
|
||||
* The semantics of `ruff <arg>` have changed slightly when `<arg>` is a valid subcommand.
|
||||
For example, prior to this release, running `ruff rule` would run `ruff` over a file or
|
||||
directory called `rule`. Now, `ruff rule` would invoke the `rule` subcommand. This should
|
||||
only impact projects with files or directories named `rule`, `check`, `explain`, `clean`,
|
||||
or `generate-shell-completion`.
|
||||
|
||||
* Scripts that invoke ruff should supply `--` before any positional arguments.
|
||||
(The semantics of `ruff -- <arg>` have not changed.)
|
||||
|
||||
* `--explain` previously treated `--format grouped` as a synonym for `--format text`.
|
||||
This is no longer supported; instead, use `--format text`.
|
||||
|
||||
## 0.0.226
|
||||
|
||||
### `misplaced-comparison-constant` (`PLC2201`) was deprecated in favor of `SIM300` ([#1980](https://github.com/charliermarsh/ruff/pull/1980))
|
||||
|
||||
@@ -106,7 +106,7 @@ Violating these terms may lead to a permanent ban.
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
@@ -115,12 +115,14 @@ the community.
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available [here](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html).
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the [FAQ](https://www.contributor-covenant.org/faq).
|
||||
Translations are available [here](https://www.contributor-covenant.org/translations).
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
||||
|
||||
235
CONTRIBUTING.md
235
CONTRIBUTING.md
@@ -4,14 +4,10 @@ Welcome! We're happy to have you here. Thank you in advance for your contributio
|
||||
|
||||
## The basics
|
||||
|
||||
Ruff welcomes contributions in the form of Pull Requests.
|
||||
|
||||
For small changes (e.g., bug fixes), feel free to submit a PR.
|
||||
|
||||
For larger changes (e.g., new lint rules, new functionality, new configuration options), consider
|
||||
creating an [**issue**](https://github.com/charliermarsh/ruff/issues) outlining your proposed
|
||||
change. You can also join us on [**Discord**](https://discord.gg/Z8KbeK24) to discuss your idea with
|
||||
the community.
|
||||
Ruff welcomes contributions in the form of Pull Requests. For small changes (e.g., bug fixes), feel
|
||||
free to submit a PR. For larger changes (e.g., new lint rules, new functionality, new configuration
|
||||
options), consider submitting an [Issue](https://github.com/charliermarsh/ruff/issues) outlining
|
||||
your proposed change.
|
||||
|
||||
If you're looking for a place to start, we recommend implementing a new lint rule (see:
|
||||
[_Adding a new lint rule_](#example-adding-a-new-lint-rule), which will allow you to learn from and
|
||||
@@ -20,7 +16,8 @@ existing Python plugins, which can be used as a reference implementation.
|
||||
|
||||
As a concrete example: consider taking on one of the rules from the [`tryceratops`](https://github.com/charliermarsh/ruff/issues/2056)
|
||||
plugin, and looking to the originating [Python source](https://github.com/guilatrova/tryceratops)
|
||||
for guidance.
|
||||
for guidance. [`flake8-simplify`](https://github.com/charliermarsh/ruff/issues/998) has a few rules
|
||||
left too.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
@@ -38,108 +35,79 @@ cargo install cargo-insta
|
||||
After cloning the repository, run Ruff locally with:
|
||||
|
||||
```shell
|
||||
cargo run /path/to/file.py --no-cache
|
||||
cargo run resources/test/fixtures --no-cache
|
||||
```
|
||||
|
||||
Prior to opening a pull request, ensure that your code has been auto-formatted,
|
||||
and that it passes both the lint and test validation checks:
|
||||
and that it passes both the lint and test validation checks.
|
||||
|
||||
For rustfmt and Clippy, we use [nightly Rust][nightly], as it is stricter than stable Rust.
|
||||
(However, tests and builds use stable Rust.)
|
||||
|
||||
```shell
|
||||
cargo fmt --all # Auto-formatting...
|
||||
cargo clippy --fix --workspace --all-targets --all-features # Linting...
|
||||
cargo test --all # Testing...
|
||||
cargo +nightly fmt --all # Auto-formatting...
|
||||
cargo +nightly clippy --fix --workspace --all-targets --all-features -- -W clippy::pedantic # Linting...
|
||||
cargo test --all # Testing...
|
||||
```
|
||||
|
||||
These checks will run on GitHub Actions when you open your Pull Request, but running them locally
|
||||
will save you time and expedite the merge process.
|
||||
|
||||
Note that many code changes also require updating the snapshot tests, which is done interactively
|
||||
after running `cargo test` like so:
|
||||
|
||||
```shell
|
||||
cargo insta review
|
||||
```
|
||||
|
||||
If you have `pre-commit` [installed](https://pre-commit.com/#installation) then you can use it to
|
||||
assist with formatting and linting. The following command will run the `pre-commit` hooks:
|
||||
|
||||
```shell
|
||||
pre-commit run --all-files
|
||||
```
|
||||
|
||||
Your Pull Request will be reviewed by a maintainer, which may involve a few rounds of iteration
|
||||
prior to merging.
|
||||
|
||||
### Project structure
|
||||
|
||||
Ruff is structured as a monorepo with a [flat crate structure](https://matklad.github.io/2021/08/22/large-rust-workspaces.html),
|
||||
such that all crates are contained in a flat `crates` directory.
|
||||
|
||||
The vast majority of the code, including all lint rules, lives in the `ruff` crate (located at
|
||||
`crates/ruff`). As a contributor, that's the crate that'll be most relevant to you.
|
||||
|
||||
At time of writing, the repository includes the following crates:
|
||||
|
||||
- `crates/ruff`: library crate containing all lint rules and the core logic for running them.
|
||||
- `crates/ruff_cli`: binary crate containing Ruff's command-line interface.
|
||||
- `crates/ruff_dev`: binary crate containing utilities used in the development of Ruff itself (e.g., `cargo dev generate-all`).
|
||||
- `crates/ruff_macros`: library crate containing macros used by Ruff.
|
||||
- `crates/ruff_python`: library crate implementing Python-specific functionality (e.g., lists of standard library modules by versionb).
|
||||
- `crates/flake8_to_ruff`: binary crate for generating Ruff configuration from Flake8 configuration.
|
||||
|
||||
### Example: Adding a new lint rule
|
||||
|
||||
At a high level, the steps involved in adding a new lint rule are as follows:
|
||||
|
||||
1. Create a file for your rule (e.g., `crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs`).
|
||||
1. Create a file for your rule (e.g., `src/rules/flake8_bugbear/rules/abstract_base_class.rs`).
|
||||
2. In that file, define a violation struct. You can grep for `define_violation!` to see examples.
|
||||
3. Map the violation struct to a rule code in `crates/ruff/src/registry.rs` (e.g., `E402`).
|
||||
4. Define the logic for triggering the violation in `crates/ruff/src/checkers/ast.rs` (for AST-based
|
||||
checks), `crates/ruff/src/checkers/tokens.rs` (for token-based checks), `crates/ruff/src/checkers/lines.rs`
|
||||
(for text-based checks), or `crates/ruff/src/checkers/filesystem.rs` (for filesystem-based
|
||||
checks).
|
||||
3. Map the violation struct to a rule code in `src/registry.rs` (e.g., `E402`).
|
||||
4. Define the logic for triggering the violation in `src/checkers/ast.rs` (for AST-based checks),
|
||||
`src/checkers/tokens.rs` (for token-based checks), `src/checkers/lines.rs` (for text-based
|
||||
checks), or `src/checkers/filesystem.rs` (for filesystem-based checks).
|
||||
5. Add a test fixture.
|
||||
6. Update the generated files (documentation and generated code).
|
||||
|
||||
To define the violation, start by creating a dedicated file for your rule under the appropriate
|
||||
rule linter (e.g., `crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs`). That file should
|
||||
rule linter (e.g., `src/rules/flake8_bugbear/rules/abstract_base_class.rs`). That file should
|
||||
contain a struct defined via `define_violation!`, along with a function that creates the violation
|
||||
based on any required inputs. (Many of the existing examples live in `crates/ruff/src/violations.rs`,
|
||||
but we're looking to place new rules in their own files.)
|
||||
based on any required inputs. (Many of the existing examples live in `src/violations.rs`, but we're
|
||||
looking to place new rules in their own files.)
|
||||
|
||||
To trigger the violation, you'll likely want to augment the logic in `crates/ruff/src/checkers/ast.rs`,
|
||||
which defines the Python AST visitor, responsible for iterating over the abstract syntax tree and
|
||||
To trigger the violation, you'll likely want to augment the logic in `src/checkers/ast.rs`, which
|
||||
defines the Python AST visitor, responsible for iterating over the abstract syntax tree and
|
||||
collecting diagnostics as it goes.
|
||||
|
||||
If you need to inspect the AST, you can run `cargo dev print-ast` with a Python file. Grep
|
||||
If you need to inspect the AST, you can run `cargo +nightly dev print-ast` with a Python file. Grep
|
||||
for the `Check::new` invocations to understand how other, similar rules are implemented.
|
||||
|
||||
To add a test fixture, create a file under `crates/ruff/resources/test/fixtures/[linter]`, named to match
|
||||
the code you defined earlier (e.g., `crates/ruff/resources/test/fixtures/pycodestyle/E402.py`). This file should
|
||||
To add a test fixture, create a file under `resources/test/fixtures/[linter]`, named to match
|
||||
the code you defined earlier (e.g., `resources/test/fixtures/pycodestyle/E402.py`). This file should
|
||||
contain a variety of violations and non-violations designed to evaluate and demonstrate the behavior
|
||||
of your lint rule.
|
||||
|
||||
Run `cargo dev generate-all` to generate the code for your new fixture. Then run Ruff
|
||||
locally with (e.g.) `cargo run crates/ruff/resources/test/fixtures/pycodestyle/E402.py --no-cache --select E402`.
|
||||
Run `cargo +nightly dev generate-all` to generate the code for your new fixture. Then run Ruff
|
||||
locally with (e.g.) `cargo run resources/test/fixtures/pycodestyle/E402.py --no-cache --select E402`.
|
||||
|
||||
Once you're satisfied with the output, codify the behavior as a snapshot test by adding a new
|
||||
`test_case` macro in the relevant `crates/ruff/src/[linter]/mod.rs` file. Then, run `cargo test --all`.
|
||||
`test_case` macro in the relevant `src/[linter]/mod.rs` file. Then, run `cargo test --all`.
|
||||
Your test will fail, but you'll be prompted to follow-up with `cargo insta review`. Accept the
|
||||
generated snapshot, then commit the snapshot file alongside the rest of your changes.
|
||||
|
||||
Finally, regenerate the documentation and generated code with `cargo dev generate-all`.
|
||||
Finally, regenerate the documentation and generated code with `cargo +nightly dev generate-all`.
|
||||
|
||||
### Example: Adding a new configuration option
|
||||
|
||||
Ruff's user-facing settings live in a few different places.
|
||||
|
||||
First, the command-line options are defined via the `Cli` struct in `crates/ruff/src/cli.rs`.
|
||||
First, the command-line options are defined via the `Cli` struct in `src/cli.rs`.
|
||||
|
||||
Second, the `pyproject.toml` options are defined in `crates/ruff/src/settings/options.rs` (via the
|
||||
`Options` struct), `crates/ruff/src/settings/configuration.rs` (via the `Configuration` struct), and
|
||||
`crates/ruff/src/settings/mod.rs` (via the `Settings` struct). These represent, respectively: the
|
||||
schema used to parse the `pyproject.toml` file; an internal, intermediate representation; and the
|
||||
final, internal representation used to power Ruff.
|
||||
Second, the `pyproject.toml` options are defined in `src/settings/options.rs` (via the `Options`
|
||||
struct), `src/settings/configuration.rs` (via the `Configuration` struct), and `src/settings/mod.rs`
|
||||
(via the `Settings` struct). These represent, respectively: the schema used to parse the
|
||||
`pyproject.toml` file; an internal, intermediate representation; and the final, internal
|
||||
representation used to power Ruff.
|
||||
|
||||
To add a new configuration option, you'll likely want to modify these latter few files (along with
|
||||
`cli.rs`, if appropriate). If you want to pattern-match against an existing example, grep for
|
||||
@@ -147,13 +115,13 @@ To add a new configuration option, you'll likely want to modify these latter few
|
||||
variables (e.g., `_`).
|
||||
|
||||
Note that plugin-specific configuration options are defined in their own modules (e.g.,
|
||||
`crates/ruff/src/flake8_unused_arguments/settings.rs`).
|
||||
`src/flake8_unused_arguments/settings.rs`).
|
||||
|
||||
You may also want to add the new configuration option to the `flake8-to-ruff` tool, which is
|
||||
responsible for converting `flake8` configuration files to Ruff's TOML format. This logic
|
||||
lives in `crates/ruff/src/flake8_to_ruff/converter.rs`.
|
||||
lives in `flake8_to_ruff/src/converter.rs`.
|
||||
|
||||
Finally, regenerate the documentation and generated code with `cargo dev generate-all`.
|
||||
Finally, regenerate the documentation and generated code with `cargo +nightly dev generate-all`.
|
||||
|
||||
## Release process
|
||||
|
||||
@@ -164,125 +132,4 @@ them to [PyPI](https://pypi.org/project/ruff/).
|
||||
Ruff follows the [semver](https://semver.org/) versioning standard. However, as pre-1.0 software,
|
||||
even patch releases may contain [non-backwards-compatible changes](https://semver.org/#spec-item-4).
|
||||
|
||||
## Benchmarks
|
||||
|
||||
First, clone [CPython](https://github.com/python/cpython). It's a large and diverse Python codebase,
|
||||
which makes it a good target for benchmarking.
|
||||
|
||||
```shell
|
||||
git clone --branch 3.10 https://github.com/python/cpython.git crates/ruff/resources/test/cpython
|
||||
```
|
||||
|
||||
To benchmark the release build:
|
||||
|
||||
```shell
|
||||
cargo build --release && hyperfine --ignore-failure --warmup 10 \
|
||||
"./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache" \
|
||||
"./target/release/ruff ./crates/ruff/resources/test/cpython/"
|
||||
|
||||
Benchmark 1: ./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache
|
||||
Time (mean ± σ): 293.8 ms ± 3.2 ms [User: 2384.6 ms, System: 90.3 ms]
|
||||
Range (min … max): 289.9 ms … 301.6 ms 10 runs
|
||||
|
||||
Warning: Ignoring non-zero exit code.
|
||||
|
||||
Benchmark 2: ./target/release/ruff ./crates/ruff/resources/test/cpython/
|
||||
Time (mean ± σ): 48.0 ms ± 3.1 ms [User: 65.2 ms, System: 124.7 ms]
|
||||
Range (min … max): 45.0 ms … 66.7 ms 62 runs
|
||||
|
||||
Warning: Ignoring non-zero exit code.
|
||||
|
||||
Summary
|
||||
'./target/release/ruff ./crates/ruff/resources/test/cpython/' ran
|
||||
6.12 ± 0.41 times faster than './target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache'
|
||||
```
|
||||
|
||||
To benchmark against the ecosystem's existing tools:
|
||||
|
||||
```shell
|
||||
hyperfine --ignore-failure --warmup 5 \
|
||||
"./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache" \
|
||||
"pyflakes crates/ruff/resources/test/cpython" \
|
||||
"autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython" \
|
||||
"pycodestyle crates/ruff/resources/test/cpython" \
|
||||
"flake8 crates/ruff/resources/test/cpython"
|
||||
|
||||
Benchmark 1: ./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache
|
||||
Time (mean ± σ): 294.3 ms ± 3.3 ms [User: 2467.5 ms, System: 89.6 ms]
|
||||
Range (min … max): 291.1 ms … 302.8 ms 10 runs
|
||||
|
||||
Warning: Ignoring non-zero exit code.
|
||||
|
||||
Benchmark 2: pyflakes crates/ruff/resources/test/cpython
|
||||
Time (mean ± σ): 15.786 s ± 0.143 s [User: 15.560 s, System: 0.214 s]
|
||||
Range (min … max): 15.640 s … 16.157 s 10 runs
|
||||
|
||||
Warning: Ignoring non-zero exit code.
|
||||
|
||||
Benchmark 3: autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython
|
||||
Time (mean ± σ): 6.175 s ± 0.169 s [User: 54.102 s, System: 1.057 s]
|
||||
Range (min … max): 5.950 s … 6.391 s 10 runs
|
||||
|
||||
Benchmark 4: pycodestyle crates/ruff/resources/test/cpython
|
||||
Time (mean ± σ): 46.921 s ± 0.508 s [User: 46.699 s, System: 0.202 s]
|
||||
Range (min … max): 46.171 s … 47.863 s 10 runs
|
||||
|
||||
Warning: Ignoring non-zero exit code.
|
||||
|
||||
Benchmark 5: flake8 crates/ruff/resources/test/cpython
|
||||
Time (mean ± σ): 12.260 s ± 0.321 s [User: 102.934 s, System: 1.230 s]
|
||||
Range (min … max): 11.848 s … 12.933 s 10 runs
|
||||
|
||||
Warning: Ignoring non-zero exit code.
|
||||
|
||||
Summary
|
||||
'./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache' ran
|
||||
20.98 ± 0.62 times faster than 'autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython'
|
||||
41.66 ± 1.18 times faster than 'flake8 crates/ruff/resources/test/cpython'
|
||||
53.64 ± 0.77 times faster than 'pyflakes crates/ruff/resources/test/cpython'
|
||||
159.43 ± 2.48 times faster than 'pycodestyle crates/ruff/resources/test/cpython'
|
||||
```
|
||||
|
||||
You can run `poetry install` from `./scripts` to create a working environment for the above. All
|
||||
reported benchmarks were computed using the versions specified by `./scripts/pyproject.toml`
|
||||
on Python 3.11.
|
||||
|
||||
To benchmark Pylint, remove the following files from the CPython repository:
|
||||
|
||||
```shell
|
||||
rm Lib/test/bad_coding.py \
|
||||
Lib/test/bad_coding2.py \
|
||||
Lib/test/bad_getattr.py \
|
||||
Lib/test/bad_getattr2.py \
|
||||
Lib/test/bad_getattr3.py \
|
||||
Lib/test/badcert.pem \
|
||||
Lib/test/badkey.pem \
|
||||
Lib/test/badsyntax_3131.py \
|
||||
Lib/test/badsyntax_future10.py \
|
||||
Lib/test/badsyntax_future3.py \
|
||||
Lib/test/badsyntax_future4.py \
|
||||
Lib/test/badsyntax_future5.py \
|
||||
Lib/test/badsyntax_future6.py \
|
||||
Lib/test/badsyntax_future7.py \
|
||||
Lib/test/badsyntax_future8.py \
|
||||
Lib/test/badsyntax_future9.py \
|
||||
Lib/test/badsyntax_pep3120.py \
|
||||
Lib/test/test_asyncio/test_runners.py \
|
||||
Lib/test/test_copy.py \
|
||||
Lib/test/test_inspect.py \
|
||||
Lib/test/test_typing.py
|
||||
```
|
||||
|
||||
Then, from `crates/ruff/resources/test/cpython`, run: `time pylint -j 0 -E $(git ls-files '*.py')`. This
|
||||
will execute Pylint with maximum parallelism and only report errors.
|
||||
|
||||
To benchmark Pyupgrade, run the following from `crates/ruff/resources/test/cpython`:
|
||||
|
||||
```shell
|
||||
hyperfine --ignore-failure --warmup 5 --prepare "git reset --hard HEAD" \
|
||||
"find . -type f -name \"*.py\" | xargs -P 0 pyupgrade --py311-plus"
|
||||
|
||||
Benchmark 1: find . -type f -name "*.py" | xargs -P 0 pyupgrade --py311-plus
|
||||
Time (mean ± σ): 30.119 s ± 0.195 s [User: 28.638 s, System: 0.390 s]
|
||||
Range (min … max): 29.813 s … 30.356 s 10 runs
|
||||
```
|
||||
[nightly]: https://rust-lang.github.io/rustup/concepts/channels.html#working-with-nightly-rust
|
||||
|
||||
592
Cargo.lock
generated
592
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
83
Cargo.toml
83
Cargo.toml
@@ -1,6 +1,85 @@
|
||||
[workspace]
|
||||
members = ["crates/*"]
|
||||
default-members = ["crates/ruff", "crates/ruff_cli"]
|
||||
members = [
|
||||
"flake8_to_ruff",
|
||||
"ruff_dev",
|
||||
"ruff_cli",
|
||||
]
|
||||
default-members = [".", "ruff_cli"]
|
||||
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.231"
|
||||
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.65.0"
|
||||
documentation = "https://github.com/charliermarsh/ruff"
|
||||
homepage = "https://github.com/charliermarsh/ruff"
|
||||
repository = "https://github.com/charliermarsh/ruff"
|
||||
readme = "README.md"
|
||||
license = "MIT"
|
||||
|
||||
[lib]
|
||||
name = "ruff"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
anyhow = { version = "1.0.66" }
|
||||
bitflags = { version = "1.3.2" }
|
||||
cfg-if = { version = "1.0.0" }
|
||||
chrono = { version = "0.4.21", default-features = false, features = ["clock"] }
|
||||
clap = { version = "4.0.1", features = ["derive", "env"] }
|
||||
colored = { version = "2.0.0" }
|
||||
dirs = { version = "4.0.0" }
|
||||
fern = { version = "0.6.1" }
|
||||
glob = { version = "0.3.0" }
|
||||
globset = { version = "0.4.9" }
|
||||
ignore = { version = "0.4.18" }
|
||||
imperative = { version = "1.0.3" }
|
||||
itertools = { version = "0.10.5" }
|
||||
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "f2f0b7a487a8725d161fe8b3ed73a6758b21e177" }
|
||||
log = { version = "0.4.17" }
|
||||
natord = { version = "1.0.9" }
|
||||
nohash-hasher = { version = "0.2.0" }
|
||||
num-bigint = { version = "0.4.3" }
|
||||
num-traits = "0.2.15"
|
||||
once_cell = { version = "1.16.0" }
|
||||
path-absolutize = { version = "3.0.14", features = ["once_cell_cache", "use_unix_paths_on_wasm"] }
|
||||
regex = { version = "1.6.0" }
|
||||
ruff_macros = { version = "0.0.231", path = "ruff_macros" }
|
||||
rustc-hash = { version = "1.1.0" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "4f38cb68e4a97aeea9eb19673803a0bd5f655383" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "4f38cb68e4a97aeea9eb19673803a0bd5f655383" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "4f38cb68e4a97aeea9eb19673803a0bd5f655383" }
|
||||
schemars = { version = "0.8.11" }
|
||||
semver = { version = "1.0.16" }
|
||||
serde = { version = "1.0.147", features = ["derive"] }
|
||||
shellexpand = { version = "3.0.0" }
|
||||
smallvec = { version = "1.10.0" }
|
||||
strum = { version = "0.24.1", features = ["strum_macros"] }
|
||||
strum_macros = { version = "0.24.3" }
|
||||
textwrap = { version = "0.16.0" }
|
||||
thiserror = { version = "1.0" }
|
||||
titlecase = { version = "2.2.1" }
|
||||
toml_edit = { version = "0.17.1", features = ["easy"] }
|
||||
|
||||
# https://docs.rs/getrandom/0.2.7/getrandom/#webassembly-support
|
||||
# For (future) wasm-pack support
|
||||
[target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dependencies]
|
||||
getrandom = { version = "0.2.7", features = ["js"] }
|
||||
console_error_panic_hook = { version = "0.1.7" }
|
||||
console_log = { version = "0.2.0" }
|
||||
serde-wasm-bindgen = { version = "0.4" }
|
||||
js-sys = { version = "0.3.60" }
|
||||
wasm-bindgen = { version = "0.2.83" }
|
||||
|
||||
[dev-dependencies]
|
||||
insta = { version = "1.19.1", features = ["yaml"] }
|
||||
test-case = { version = "2.2.2" }
|
||||
wasm-bindgen-test = { version = "0.3.33" }
|
||||
|
||||
[target.'cfg(not(target_family = "wasm"))'.dev-dependencies]
|
||||
criterion = { version = "0.4.0" }
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
[files]
|
||||
extend-exclude = ["snapshots"]
|
||||
@@ -1,83 +0,0 @@
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.243"
|
||||
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
|
||||
edition = "2021"
|
||||
rust-version = "1.65.0"
|
||||
documentation = "https://github.com/charliermarsh/ruff"
|
||||
homepage = "https://github.com/charliermarsh/ruff"
|
||||
repository = "https://github.com/charliermarsh/ruff"
|
||||
readme = "README.md"
|
||||
license = "MIT"
|
||||
|
||||
[lib]
|
||||
name = "ruff"
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
anyhow = { version = "1.0.66" }
|
||||
bisection = { version = "0.1.0" }
|
||||
bitflags = { version = "1.3.2" }
|
||||
cfg-if = { version = "1.0.0" }
|
||||
chrono = { version = "0.4.21", default-features = false, features = ["clock"] }
|
||||
clap = { version = "4.0.1", features = ["derive", "env"] }
|
||||
colored = { version = "2.0.0" }
|
||||
dirs = { version = "4.0.0" }
|
||||
fern = { version = "0.6.1" }
|
||||
glob = { version = "0.3.0" }
|
||||
globset = { version = "0.4.9" }
|
||||
ignore = { version = "0.4.18" }
|
||||
imperative = { version = "1.0.3" }
|
||||
itertools = { version = "0.10.5" }
|
||||
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "f2f0b7a487a8725d161fe8b3ed73a6758b21e177" }
|
||||
log = { version = "0.4.17" }
|
||||
natord = { version = "1.0.9" }
|
||||
nohash-hasher = { version = "0.2.0" }
|
||||
num-bigint = { version = "0.4.3" }
|
||||
num-traits = "0.2.15"
|
||||
once_cell = { version = "1.16.0" }
|
||||
path-absolutize = { version = "3.0.14", features = ["once_cell_cache", "use_unix_paths_on_wasm"] }
|
||||
regex = { version = "1.6.0" }
|
||||
ruff_macros = { version = "0.0.243", path = "../ruff_macros" }
|
||||
ruff_python = { version = "0.0.243", path = "../ruff_python" }
|
||||
rustc-hash = { version = "1.1.0" }
|
||||
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "adc23253e4b58980b407ba2760dbe61681d752fc" }
|
||||
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "adc23253e4b58980b407ba2760dbe61681d752fc" }
|
||||
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "adc23253e4b58980b407ba2760dbe61681d752fc" }
|
||||
schemars = { version = "0.8.11" }
|
||||
semver = { version = "1.0.16" }
|
||||
serde = { version = "1.0.147", features = ["derive"] }
|
||||
shellexpand = { version = "3.0.0" }
|
||||
smallvec = { version = "1.10.0" }
|
||||
strum = { version = "0.24.1", features = ["strum_macros"] }
|
||||
strum_macros = { version = "0.24.3" }
|
||||
textwrap = { version = "0.16.0" }
|
||||
thiserror = { version = "1.0" }
|
||||
titlecase = { version = "2.2.1" }
|
||||
toml = { version = "0.6.0" }
|
||||
|
||||
# https://docs.rs/getrandom/0.2.7/getrandom/#webassembly-support
|
||||
# For (future) wasm-pack support
|
||||
[target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dependencies]
|
||||
getrandom = { version = "0.2.7", features = ["js"] }
|
||||
console_error_panic_hook = { version = "0.1.7" }
|
||||
console_log = { version = "0.2.0" }
|
||||
serde-wasm-bindgen = { version = "0.4" }
|
||||
js-sys = { version = "0.3.60" }
|
||||
wasm-bindgen = { version = "0.2.83" }
|
||||
|
||||
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
||||
is_executable = "1.0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
insta = { version = "1.19.0", features = ["yaml", "redactions"] }
|
||||
test-case = { version = "2.2.2" }
|
||||
wasm-bindgen-test = { version = "0.3.33" }
|
||||
|
||||
[target.'cfg(not(target_family = "wasm"))'.dev-dependencies]
|
||||
criterion = { version = "0.4.0" }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
logical_lines = []
|
||||
@@ -1,14 +0,0 @@
|
||||
try:
|
||||
pass
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except ValueError:
|
||||
pass
|
||||
@@ -1,88 +0,0 @@
|
||||
for i in range(10):
|
||||
print(i)
|
||||
|
||||
print(i) # name no longer defined on Python 3; no warning yet
|
||||
|
||||
for i in range(10): # name not used within the loop; B007
|
||||
print(10)
|
||||
|
||||
print(i) # name no longer defined on Python 3; no warning yet
|
||||
|
||||
|
||||
for _ in range(10): # _ is okay for a throw-away variable
|
||||
print(10)
|
||||
|
||||
|
||||
for i in range(10):
|
||||
for j in range(10):
|
||||
for k in range(10): # k not used, i and j used transitively
|
||||
print(i + j)
|
||||
|
||||
|
||||
def strange_generator():
|
||||
for i in range(10):
|
||||
for j in range(10):
|
||||
for k in range(10):
|
||||
for l in range(10):
|
||||
yield i, (j, (k, l))
|
||||
|
||||
|
||||
for i, (j, (k, l)) in strange_generator(): # i, k not used
|
||||
print(j, l)
|
||||
|
||||
FMT = "{foo} {bar}"
|
||||
for foo, bar in [(1, 2)]:
|
||||
if foo:
|
||||
print(FMT.format(**locals()))
|
||||
|
||||
for foo, bar in [(1, 2)]:
|
||||
if foo:
|
||||
print(FMT.format(**globals()))
|
||||
|
||||
for foo, bar in [(1, 2)]:
|
||||
if foo:
|
||||
print(FMT.format(**vars()))
|
||||
|
||||
for foo, bar in [(1, 2)]:
|
||||
print(FMT.format(foo=foo, bar=eval("bar")))
|
||||
|
||||
|
||||
def f():
|
||||
# Fixable.
|
||||
for foo, bar, baz in (["1", "2", "3"],):
|
||||
if foo or baz:
|
||||
break
|
||||
|
||||
|
||||
def f():
|
||||
# Unfixable due to usage of `bar` outside of loop.
|
||||
for foo, bar, baz in (["1", "2", "3"],):
|
||||
if foo or baz:
|
||||
break
|
||||
|
||||
print(bar)
|
||||
|
||||
|
||||
def f():
|
||||
# Fixable.
|
||||
for foo, bar, baz in (["1", "2", "3"],):
|
||||
if foo or baz:
|
||||
break
|
||||
|
||||
bar = 1
|
||||
|
||||
|
||||
def f():
|
||||
# Fixable.
|
||||
for foo, bar, baz in (["1", "2", "3"],):
|
||||
if foo or baz:
|
||||
break
|
||||
|
||||
bar = 1
|
||||
print(bar)
|
||||
|
||||
|
||||
# Unfixable due to trailing underscore (`_line_` wouldn't be considered an ignorable
|
||||
# variable name).
|
||||
for line_ in range(self.header_lines):
|
||||
fp.readline()
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
if __name__ == '__main__':
|
||||
print('I should be executable.')
|
||||
@@ -1,2 +0,0 @@
|
||||
if __name__ == '__main__':
|
||||
print('I should be executable.')
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
if __name__ == '__main__':
|
||||
print('I should be executable.')
|
||||
@@ -1,2 +0,0 @@
|
||||
if __name__ == '__main__':
|
||||
print('I should be executable.')
|
||||
@@ -1,2 +0,0 @@
|
||||
if __name__ == '__main__':
|
||||
print('I should be executable.')
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
if __name__ == '__main__':
|
||||
print('I should be executable.')
|
||||
@@ -1,3 +0,0 @@
|
||||
import logging
|
||||
|
||||
logging.info("Hello {}".format("World!"))
|
||||
@@ -1,3 +0,0 @@
|
||||
import logging
|
||||
|
||||
logging.info("Hello %s" % "World!")
|
||||
@@ -1,3 +0,0 @@
|
||||
import logging
|
||||
|
||||
logging.info("Hello" + " " + "World!")
|
||||
@@ -1,4 +0,0 @@
|
||||
import logging
|
||||
|
||||
name = "world"
|
||||
logging.info(f"Hello {name}")
|
||||
@@ -1,3 +0,0 @@
|
||||
import logging
|
||||
|
||||
logging.warn("Hello World!")
|
||||
@@ -1,8 +0,0 @@
|
||||
import logging
|
||||
|
||||
logging.info(
|
||||
"Hello world!",
|
||||
extra={
|
||||
"name": "foobar",
|
||||
},
|
||||
)
|
||||
@@ -1,8 +0,0 @@
|
||||
import logging
|
||||
|
||||
logging.info(
|
||||
"Hello world!",
|
||||
extra=dict(
|
||||
name="foobar",
|
||||
),
|
||||
)
|
||||
@@ -1,21 +0,0 @@
|
||||
import logging
|
||||
import sys
|
||||
|
||||
# G201
|
||||
try:
|
||||
pass
|
||||
except:
|
||||
logging.error("Hello World", exc_info=True)
|
||||
|
||||
try:
|
||||
pass
|
||||
except:
|
||||
logging.error("Hello World", exc_info=sys.exc_info())
|
||||
|
||||
# OK
|
||||
try:
|
||||
pass
|
||||
except:
|
||||
logging.error("Hello World", exc_info=False)
|
||||
|
||||
logging.error("Hello World", exc_info=sys.exc_info())
|
||||
@@ -1,21 +0,0 @@
|
||||
import logging
|
||||
import sys
|
||||
|
||||
# G202
|
||||
try:
|
||||
pass
|
||||
except:
|
||||
logging.exception("Hello World", exc_info=True)
|
||||
|
||||
try:
|
||||
pass
|
||||
except:
|
||||
logging.exception("Hello World", exc_info=sys.exc_info())
|
||||
|
||||
# OK
|
||||
try:
|
||||
pass
|
||||
except:
|
||||
logging.exception("Hello World", exc_info=False)
|
||||
|
||||
logging.exception("Hello World", exc_info=True)
|
||||
@@ -1,7 +0,0 @@
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("target_dir", type=Path)
|
||||
args = parser.parse_args()
|
||||
parser.error(f"Target directory {args.target_dir} does not exist")
|
||||
@@ -1,8 +0,0 @@
|
||||
import logging
|
||||
|
||||
logging.info(
|
||||
"Hello {world}!",
|
||||
extra=dict(
|
||||
world="World",
|
||||
),
|
||||
)
|
||||
@@ -1,8 +0,0 @@
|
||||
import logging
|
||||
|
||||
logging.info(
|
||||
"Hello {world}!",
|
||||
extra=dict(
|
||||
world="{}".format("World"),
|
||||
),
|
||||
)
|
||||
@@ -1,3 +0,0 @@
|
||||
import logging
|
||||
|
||||
logging.info("Hello World!")
|
||||
@@ -1,3 +0,0 @@
|
||||
import warnings
|
||||
|
||||
warnings.warn("Hello World!")
|
||||
@@ -1,17 +0,0 @@
|
||||
# error
|
||||
obj.startswith("foo") or obj.startswith("bar")
|
||||
# error
|
||||
obj.endswith("foo") or obj.endswith("bar")
|
||||
# error
|
||||
obj.startswith(foo) or obj.startswith(bar)
|
||||
# error
|
||||
obj.startswith(foo) or obj.startswith("foo")
|
||||
|
||||
# ok
|
||||
obj.startswith(("foo", "bar"))
|
||||
# ok
|
||||
obj.endswith(("foo", "bar"))
|
||||
# ok
|
||||
obj.startswith("foo") or obj.endswith("bar")
|
||||
# ok
|
||||
obj.startswith("foo") or abc.startswith("bar")
|
||||
@@ -1,73 +0,0 @@
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def ok_no_scope():
|
||||
...
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def ok_other_scope():
|
||||
...
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def error():
|
||||
...
|
||||
|
||||
|
||||
@pytest.fixture(scope="function", name="my_fixture")
|
||||
def error_multiple_args():
|
||||
...
|
||||
|
||||
|
||||
@pytest.fixture(name="my_fixture", scope="function")
|
||||
def error_multiple_args():
|
||||
...
|
||||
|
||||
|
||||
@pytest.fixture(name="my_fixture", scope="function", **kwargs)
|
||||
def error_second_arg():
|
||||
...
|
||||
|
||||
|
||||
# pytest.fixture does not take positional arguments, however this
|
||||
# tests the general case as we use a helper function that should
|
||||
# work for all cases.
|
||||
@pytest.fixture("my_fixture", scope="function")
|
||||
def error_arg():
|
||||
...
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
scope="function",
|
||||
name="my_fixture",
|
||||
)
|
||||
def error_multiple_args():
|
||||
...
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
name="my_fixture",
|
||||
scope="function",
|
||||
)
|
||||
def error_multiple_args():
|
||||
...
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
"hello",
|
||||
name,
|
||||
*args
|
||||
,
|
||||
|
||||
# another comment ,)
|
||||
|
||||
scope=\
|
||||
"function" # some comment ),
|
||||
,
|
||||
|
||||
name2=name, name3="my_fixture", **kwargs
|
||||
)
|
||||
def error_multiple_args():
|
||||
...
|
||||
@@ -1,4 +0,0 @@
|
||||
this_should_be_linted = "double quote string"
|
||||
this_should_be_linted = u"double quote string"
|
||||
this_should_be_linted = f"double quote string"
|
||||
this_should_be_linted = f"double {'quote'} string"
|
||||
@@ -1,27 +0,0 @@
|
||||
x = (
|
||||
"This"
|
||||
"is"
|
||||
"not"
|
||||
)
|
||||
|
||||
x = (
|
||||
"This" \
|
||||
"is" \
|
||||
"not"
|
||||
)
|
||||
|
||||
x = (
|
||||
"This"
|
||||
"is 'actually'"
|
||||
"fine"
|
||||
)
|
||||
|
||||
x = (
|
||||
"This" \
|
||||
"is 'actually'" \
|
||||
"fine"
|
||||
)
|
||||
|
||||
if True:
|
||||
"This can use 'double' quotes"
|
||||
"But this needs to be changed"
|
||||
@@ -1,4 +0,0 @@
|
||||
this_should_be_linted = 'single quote string'
|
||||
this_should_be_linted = u'double quote string'
|
||||
this_should_be_linted = f'double quote string'
|
||||
this_should_be_linted = f'double {"quote"} string'
|
||||
@@ -1,27 +0,0 @@
|
||||
x = (
|
||||
'This'
|
||||
'is'
|
||||
'not'
|
||||
)
|
||||
|
||||
x = (
|
||||
'This' \
|
||||
'is' \
|
||||
'not'
|
||||
)
|
||||
|
||||
x = (
|
||||
'This'
|
||||
'is "actually"'
|
||||
'fine'
|
||||
)
|
||||
|
||||
x = (
|
||||
'This' \
|
||||
'is "actually"' \
|
||||
'fine'
|
||||
)
|
||||
|
||||
if True:
|
||||
'This can use "single" quotes'
|
||||
'But this needs to be changed'
|
||||
@@ -1,34 +0,0 @@
|
||||
try:
|
||||
y = 6 + "7"
|
||||
except TypeError:
|
||||
# RSE102
|
||||
raise ValueError()
|
||||
|
||||
try:
|
||||
x = 1 / 0
|
||||
except ZeroDivisionError:
|
||||
raise
|
||||
|
||||
# RSE102
|
||||
raise TypeError()
|
||||
|
||||
# RSE102
|
||||
raise TypeError ()
|
||||
|
||||
# RSE102
|
||||
raise TypeError \
|
||||
()
|
||||
|
||||
# RSE102
|
||||
raise TypeError(
|
||||
|
||||
)
|
||||
|
||||
# RSE102
|
||||
raise TypeError(
|
||||
# Hello, world!
|
||||
)
|
||||
|
||||
raise AssertionError
|
||||
|
||||
raise AttributeError("test message")
|
||||
@@ -1,59 +0,0 @@
|
||||
class BazMeta(type):
|
||||
_private_count = 1
|
||||
|
||||
def __new__(mcs, name, bases, attrs):
|
||||
if mcs._private_count <= 5:
|
||||
mcs.some_method()
|
||||
|
||||
return super().__new__(mcs, name, bases, attrs)
|
||||
|
||||
def some_method():
|
||||
pass
|
||||
|
||||
|
||||
class Bar:
|
||||
_private = True
|
||||
|
||||
@classmethod
|
||||
def is_private(cls):
|
||||
return cls._private
|
||||
|
||||
|
||||
class Foo(metaclass=BazMeta):
|
||||
|
||||
def __init__(self):
|
||||
self.public_thing = "foo"
|
||||
self._private_thing = "bar"
|
||||
self.__really_private_thing = "baz"
|
||||
self.bar = Bar()
|
||||
|
||||
def __str__(self):
|
||||
return "foo"
|
||||
|
||||
def get_bar():
|
||||
if self.bar._private: # SLF001
|
||||
return None
|
||||
return self.bar
|
||||
|
||||
def public_func(self):
|
||||
pass
|
||||
|
||||
def _private_func(self):
|
||||
pass
|
||||
|
||||
def __really_private_func(self, arg):
|
||||
pass
|
||||
|
||||
|
||||
foo = Foo()
|
||||
|
||||
print(foo.public_thing)
|
||||
print(foo.public_func())
|
||||
print(foo.__dict__)
|
||||
print(foo.__str__())
|
||||
|
||||
print(foo._private_thing) # SLF001
|
||||
print(foo.__really_private_thing) # SLF001
|
||||
print(foo._private_func()) # SLF001
|
||||
print(foo.__really_private_func(1)) # SLF001
|
||||
print(foo.bar._private) # SLF001
|
||||
@@ -1,28 +0,0 @@
|
||||
# Errors
|
||||
"yoda" == compare # SIM300
|
||||
"yoda" == compare # SIM300
|
||||
42 == age # SIM300
|
||||
("a", "b") == compare # SIM300
|
||||
"yoda" <= compare # SIM300
|
||||
"yoda" < compare # SIM300
|
||||
42 > age # SIM300
|
||||
YODA == age # SIM300
|
||||
YODA > age # SIM300
|
||||
YODA >= age # SIM300
|
||||
JediOrder.YODA == age # SIM300
|
||||
0 < (number - 100) # SIM300
|
||||
|
||||
# OK
|
||||
compare == "yoda"
|
||||
age == 42
|
||||
compare == ("a", "b")
|
||||
x == y
|
||||
"yoda" == compare == 1
|
||||
"yoda" == compare == someothervar
|
||||
"yoda" == "yoda"
|
||||
age == YODA
|
||||
age < YODA
|
||||
age <= YODA
|
||||
YODA == YODA
|
||||
age == JediOrder.YODA
|
||||
(number - 100) > 0
|
||||
@@ -1,28 +0,0 @@
|
||||
"""Tests to determine first-party import classification.
|
||||
|
||||
For typing-only import detection tests, see `TCH002.py`.
|
||||
"""
|
||||
|
||||
|
||||
def f():
|
||||
import TYP001
|
||||
|
||||
x: TYP001
|
||||
|
||||
|
||||
def f():
|
||||
import TYP001
|
||||
|
||||
print(TYP001)
|
||||
|
||||
|
||||
def f():
|
||||
from . import TYP001
|
||||
|
||||
x: TYP001
|
||||
|
||||
|
||||
def f():
|
||||
from . import TYP001
|
||||
|
||||
print(TYP001)
|
||||
@@ -1,148 +0,0 @@
|
||||
"""Tests to determine accurate detection of typing-only imports."""
|
||||
|
||||
|
||||
def f():
|
||||
import pandas as pd # TCH002
|
||||
|
||||
x: pd.DataFrame
|
||||
|
||||
|
||||
def f():
|
||||
from pandas import DataFrame # TCH002
|
||||
|
||||
x: DataFrame
|
||||
|
||||
|
||||
def f():
|
||||
from pandas import DataFrame as df # TCH002
|
||||
|
||||
x: df
|
||||
|
||||
|
||||
def f():
|
||||
import pandas as pd # TCH002
|
||||
|
||||
x: pd.DataFrame = 1
|
||||
|
||||
|
||||
def f():
|
||||
from pandas import DataFrame # TCH002
|
||||
|
||||
x: DataFrame = 2
|
||||
|
||||
|
||||
def f():
|
||||
from pandas import DataFrame as df # TCH002
|
||||
|
||||
x: df = 3
|
||||
|
||||
|
||||
def f():
|
||||
import pandas as pd # TCH002
|
||||
|
||||
x: "pd.DataFrame" = 1
|
||||
|
||||
|
||||
def f():
|
||||
import pandas as pd
|
||||
|
||||
x = dict["pd.DataFrame", "pd.DataFrame"] # TCH002
|
||||
|
||||
|
||||
def f():
|
||||
import pandas as pd
|
||||
|
||||
print(pd)
|
||||
|
||||
|
||||
def f():
|
||||
from pandas import DataFrame
|
||||
|
||||
print(DataFrame)
|
||||
|
||||
|
||||
def f():
|
||||
from pandas import DataFrame
|
||||
|
||||
def f():
|
||||
print(DataFrame)
|
||||
|
||||
|
||||
def f():
|
||||
from typing import Dict, Any
|
||||
|
||||
def example() -> Any:
|
||||
return 1
|
||||
|
||||
x: Dict[int] = 20
|
||||
|
||||
|
||||
def f():
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Dict
|
||||
x: Dict[int] = 20
|
||||
|
||||
|
||||
def f():
|
||||
from pathlib import Path
|
||||
|
||||
class ImportVisitor(ast.NodeTransformer):
|
||||
def __init__(self, cwd: Path) -> None:
|
||||
self.cwd = cwd
|
||||
origin = Path(spec.origin)
|
||||
|
||||
class ExampleClass:
|
||||
def __init__(self):
|
||||
self.cwd = Path(pandas.getcwd())
|
||||
|
||||
|
||||
def f():
|
||||
import pandas
|
||||
|
||||
class Migration:
|
||||
enum = pandas
|
||||
|
||||
|
||||
def f():
|
||||
import pandas
|
||||
|
||||
class Migration:
|
||||
enum = pandas.EnumClass
|
||||
|
||||
|
||||
def f():
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from pandas import y
|
||||
|
||||
if TYPE_CHECKING:
|
||||
_type = x
|
||||
else:
|
||||
_type = y
|
||||
|
||||
|
||||
def f():
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from pandas import y
|
||||
|
||||
if TYPE_CHECKING:
|
||||
_type = x
|
||||
elif True:
|
||||
_type = y
|
||||
|
||||
|
||||
def f():
|
||||
from typing import cast
|
||||
|
||||
import pandas as pd
|
||||
|
||||
x = cast(pd.DataFrame, 2)
|
||||
|
||||
|
||||
def f():
|
||||
import pandas as pd
|
||||
|
||||
x = dict[pd.DataFrame, pd.DataFrame]
|
||||
@@ -1,16 +0,0 @@
|
||||
"""Tests to determine standard library import classification.
|
||||
|
||||
For typing-only import detection tests, see `TCH002.py`.
|
||||
"""
|
||||
|
||||
|
||||
def f():
|
||||
import os
|
||||
|
||||
x: os
|
||||
|
||||
|
||||
def f():
|
||||
import os
|
||||
|
||||
print(os)
|
||||
@@ -1,5 +0,0 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from datetime import datetime
|
||||
x = datetime
|
||||
@@ -1,8 +0,0 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from datetime import date
|
||||
|
||||
|
||||
def example():
|
||||
return date()
|
||||
@@ -1,6 +0,0 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any
|
||||
|
||||
CustomType = Any
|
||||
@@ -1,11 +0,0 @@
|
||||
from typing import TYPE_CHECKING, Type
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any
|
||||
|
||||
|
||||
def example(*args: Any, **kwargs: Any):
|
||||
return
|
||||
|
||||
|
||||
my_type: Type[Any] | Any
|
||||
@@ -1,8 +0,0 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import List, Sequence, Set
|
||||
|
||||
|
||||
def example(a: List[int], /, b: Sequence[int], *, c: Set[int]):
|
||||
return
|
||||
@@ -1,10 +0,0 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pandas import DataFrame
|
||||
|
||||
|
||||
def example():
|
||||
from pandas import DataFrame
|
||||
|
||||
x = DataFrame
|
||||
@@ -1,10 +0,0 @@
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import AsyncIterator, List
|
||||
|
||||
|
||||
class Example:
|
||||
async def example(self) -> AsyncIterator[List[str]]:
|
||||
yield 0
|
||||
@@ -1,7 +0,0 @@
|
||||
from typing import TYPE_CHECKING
|
||||
from weakref import WeakKeyDictionary
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any
|
||||
|
||||
d = WeakKeyDictionary["Any", "Any"]()
|
||||
@@ -1,16 +0,0 @@
|
||||
def f():
|
||||
import pandas as pd
|
||||
|
||||
x: pd.DataFrame
|
||||
|
||||
|
||||
def f():
|
||||
import pandas.core.frame as pd
|
||||
|
||||
x: pd.DataFrame
|
||||
|
||||
|
||||
def f():
|
||||
import flask
|
||||
|
||||
x: flask
|
||||
@@ -1,54 +0,0 @@
|
||||
def f():
|
||||
# Even in strict mode, this shouldn't rase an error, since `pkg` is used at runtime,
|
||||
# and implicitly imports `pkg.bar`.
|
||||
import pkg
|
||||
import pkg.bar
|
||||
|
||||
def test(value: pkg.bar.A):
|
||||
return pkg.B()
|
||||
|
||||
|
||||
def f():
|
||||
# Even in strict mode, this shouldn't rase an error, since `pkg.bar` is used at
|
||||
# runtime, and implicitly imports `pkg`.
|
||||
import pkg
|
||||
import pkg.bar
|
||||
|
||||
def test(value: pkg.A):
|
||||
return pkg.bar.B()
|
||||
|
||||
|
||||
def f():
|
||||
# In un-strict mode, this shouldn't rase an error, since `pkg` is used at runtime.
|
||||
import pkg
|
||||
from pkg import A
|
||||
|
||||
def test(value: A):
|
||||
return pkg.B()
|
||||
|
||||
|
||||
def f():
|
||||
# In un-strict mode, this shouldn't rase an error, since `pkg` is used at runtime.
|
||||
from pkg import A, B
|
||||
|
||||
def test(value: A):
|
||||
return B()
|
||||
|
||||
|
||||
def f():
|
||||
# Even in strict mode, this shouldn't rase an error, since `pkg.baz` is used at
|
||||
# runtime, and implicitly imports `pkg.bar`.
|
||||
import pkg.bar
|
||||
import pkg.baz
|
||||
|
||||
def test(value: pkg.bar.A):
|
||||
return pkg.baz.B()
|
||||
|
||||
|
||||
def f():
|
||||
# In un-strict mode, this _should_ rase an error, since `pkg` is used at runtime.
|
||||
import pkg
|
||||
from pkg.bar import A
|
||||
|
||||
def test(value: A):
|
||||
return pkg.B()
|
||||
@@ -1,3 +0,0 @@
|
||||
from pathlib import Path
|
||||
|
||||
(Path("") / "").open()
|
||||
@@ -1,8 +0,0 @@
|
||||
# office_helper and tests are both first-party,
|
||||
# but we want tests and experiments to be separated, in that order
|
||||
from office_helper.core import CoreState
|
||||
import tests.common.foo as tcf
|
||||
from tests.common import async_mock_service
|
||||
from experiments.starry import *
|
||||
from experiments.weird import varieties
|
||||
from office_helper.assistants import entity_registry as er
|
||||
@@ -1,13 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from requests import Session
|
||||
|
||||
from my_first_party import my_first_party_object
|
||||
|
||||
from . import my_local_folder_object
|
||||
class Thing(object):
|
||||
name: str
|
||||
def __init__(self, name: str):
|
||||
self.name = name
|
||||
@@ -1,22 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from requests import Session
|
||||
|
||||
from my_first_party import my_first_party_object
|
||||
|
||||
from . import my_local_folder_object
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
my_local_folder_object.get()
|
||||
@@ -1,9 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from requests import Session
|
||||
|
||||
from my_first_party import my_first_party_object
|
||||
|
||||
from . import my_local_folder_object
|
||||
@@ -1,29 +0,0 @@
|
||||
from numpy import (
|
||||
cos,
|
||||
int8,
|
||||
int16,
|
||||
int32,
|
||||
int64,
|
||||
sin,
|
||||
tan,
|
||||
uint8,
|
||||
uint16,
|
||||
uint32,
|
||||
uint64,
|
||||
)
|
||||
|
||||
if True:
|
||||
# inside nested block
|
||||
from numpy import (
|
||||
cos,
|
||||
int8,
|
||||
int16,
|
||||
int32,
|
||||
int64,
|
||||
sin,
|
||||
tan,
|
||||
uint8,
|
||||
uint16,
|
||||
uint32,
|
||||
uint64,
|
||||
)
|
||||
@@ -1,13 +0,0 @@
|
||||
from numpy import (
|
||||
cos,
|
||||
int8,
|
||||
int16,
|
||||
int32,
|
||||
int64,
|
||||
sin,
|
||||
tan,
|
||||
uint8,
|
||||
uint16,
|
||||
uint32,
|
||||
uint64,
|
||||
)
|
||||
@@ -1,5 +0,0 @@
|
||||
[tool.ruff]
|
||||
line-length = 88
|
||||
|
||||
[tool.ruff.isort]
|
||||
lines-after-imports = 3
|
||||
@@ -1,3 +0,0 @@
|
||||
from .logging import config_logging
|
||||
from .settings import ENV
|
||||
from .settings import *
|
||||
@@ -1,20 +0,0 @@
|
||||
import pandas as pd
|
||||
|
||||
x = pd.DataFrame()
|
||||
|
||||
x.drop(["a"], axis=1, inplace=True)
|
||||
|
||||
x.drop(["a"], axis=1, inplace=True)
|
||||
|
||||
x.drop(
|
||||
inplace=True,
|
||||
columns=["a"],
|
||||
axis=1,
|
||||
)
|
||||
|
||||
if True:
|
||||
x.drop(
|
||||
inplace=True,
|
||||
columns=["a"],
|
||||
axis=1,
|
||||
)
|
||||
@@ -1,40 +0,0 @@
|
||||
import collections
|
||||
from collections import namedtuple
|
||||
from typing import TypeVar
|
||||
from typing import NewType
|
||||
from typing import NamedTuple, TypedDict
|
||||
|
||||
GLOBAL: str = "foo"
|
||||
|
||||
|
||||
def assign():
|
||||
global GLOBAL
|
||||
GLOBAL = "bar"
|
||||
lower = 0
|
||||
Camel = 0
|
||||
CONSTANT = 0
|
||||
_ = 0
|
||||
|
||||
MyObj1 = collections.namedtuple("MyObj1", ["a", "b"])
|
||||
MyObj2 = namedtuple("MyObj12", ["a", "b"])
|
||||
|
||||
T = TypeVar("T")
|
||||
UserId = NewType("UserId", int)
|
||||
|
||||
Employee = NamedTuple('Employee', [('name', str), ('id', int)])
|
||||
|
||||
Point2D = TypedDict('Point2D', {'in': int, 'x-y': int})
|
||||
|
||||
|
||||
def aug_assign(rank, world_size):
|
||||
global CURRENT_PORT
|
||||
|
||||
CURRENT_PORT += 1
|
||||
if CURRENT_PORT > MAX_PORT:
|
||||
CURRENT_PORT = START_PORT
|
||||
|
||||
|
||||
def loop_assign():
|
||||
global CURRENT_PORT
|
||||
for CURRENT_PORT in range(5):
|
||||
pass
|
||||
@@ -1,42 +0,0 @@
|
||||
#: E111
|
||||
if x > 2:
|
||||
print(x)
|
||||
#: E111 E117
|
||||
if True:
|
||||
print()
|
||||
#: E112
|
||||
if False:
|
||||
print()
|
||||
#: E113
|
||||
print()
|
||||
print()
|
||||
#: E114 E116
|
||||
mimetype = 'application/x-directory'
|
||||
# 'httpd/unix-directory'
|
||||
create_date = False
|
||||
#: E116 E116 E116
|
||||
def start(self):
|
||||
if True:
|
||||
self.master.start()
|
||||
# try:
|
||||
# self.master.start()
|
||||
# except MasterExit:
|
||||
# self.shutdown()
|
||||
# finally:
|
||||
# sys.exit()
|
||||
#: E115 E115 E115 E115 E115 E115
|
||||
def start(self):
|
||||
if True:
|
||||
# try:
|
||||
# self.master.start()
|
||||
# except MasterExit:
|
||||
# self.shutdown()
|
||||
# finally:
|
||||
# sys.exit()
|
||||
self.master.start()
|
||||
#: E117
|
||||
def start():
|
||||
print()
|
||||
#: E117 W191
|
||||
def start():
|
||||
print()
|
||||
@@ -1,78 +0,0 @@
|
||||
#: E201:1:6
|
||||
spam( ham[1], {eggs: 2})
|
||||
#: E201:1:10
|
||||
spam(ham[ 1], {eggs: 2})
|
||||
#: E201:1:15
|
||||
spam(ham[1], { eggs: 2})
|
||||
#: E201:1:6
|
||||
spam( ham[1], {eggs: 2})
|
||||
#: E201:1:10
|
||||
spam(ham[ 1], {eggs: 2})
|
||||
#: E201:1:15
|
||||
spam(ham[1], { eggs: 2})
|
||||
#: Okay
|
||||
spam(ham[1], {eggs: 2})
|
||||
#:
|
||||
|
||||
|
||||
#: E202:1:23
|
||||
spam(ham[1], {eggs: 2} )
|
||||
#: E202:1:22
|
||||
spam(ham[1], {eggs: 2 })
|
||||
#: E202:1:11
|
||||
spam(ham[1 ], {eggs: 2})
|
||||
#: E202:1:23
|
||||
spam(ham[1], {eggs: 2} )
|
||||
#: E202:1:22
|
||||
spam(ham[1], {eggs: 2 })
|
||||
#: E202:1:11
|
||||
spam(ham[1 ], {eggs: 2})
|
||||
#: Okay
|
||||
spam(ham[1], {eggs: 2})
|
||||
|
||||
result = func(
|
||||
arg1='some value',
|
||||
arg2='another value',
|
||||
)
|
||||
|
||||
result = func(
|
||||
arg1='some value',
|
||||
arg2='another value'
|
||||
)
|
||||
|
||||
result = [
|
||||
item for item in items
|
||||
if item > 5
|
||||
]
|
||||
#:
|
||||
|
||||
|
||||
#: E203:1:10
|
||||
if x == 4 :
|
||||
print x, y
|
||||
x, y = y, x
|
||||
#: E203:1:10
|
||||
if x == 4 :
|
||||
print x, y
|
||||
x, y = y, x
|
||||
#: E203:2:15 E702:2:16
|
||||
if x == 4:
|
||||
print x, y ; x, y = y, x
|
||||
#: E203:2:15 E702:2:16
|
||||
if x == 4:
|
||||
print x, y ; x, y = y, x
|
||||
#: E203:3:13
|
||||
if x == 4:
|
||||
print x, y
|
||||
x, y = y , x
|
||||
#: E203:3:13
|
||||
if x == 4:
|
||||
print x, y
|
||||
x, y = y , x
|
||||
#: Okay
|
||||
if x == 4:
|
||||
print x, y
|
||||
x, y = y, x
|
||||
a[b1, :] == a[b1, ...]
|
||||
b = a[:, b1]
|
||||
#:
|
||||
@@ -1,171 +0,0 @@
|
||||
#: E221
|
||||
a = 12 + 3
|
||||
b = 4 + 5
|
||||
#: E221 E221
|
||||
x = 1
|
||||
y = 2
|
||||
long_variable = 3
|
||||
#: E221 E221
|
||||
x[0] = 1
|
||||
x[1] = 2
|
||||
long_variable = 3
|
||||
#: E221 E221
|
||||
x = f(x) + 1
|
||||
y = long_variable + 2
|
||||
z = x[0] + 3
|
||||
#: E221:3:14
|
||||
text = """
|
||||
bar
|
||||
foo %s""" % rofl
|
||||
#: Okay
|
||||
x = 1
|
||||
y = 2
|
||||
long_variable = 3
|
||||
#:
|
||||
|
||||
|
||||
#: E222
|
||||
a = a + 1
|
||||
b = b + 10
|
||||
#: E222 E222
|
||||
x = -1
|
||||
y = -2
|
||||
long_variable = 3
|
||||
#: E222 E222
|
||||
x[0] = 1
|
||||
x[1] = 2
|
||||
long_variable = 3
|
||||
#:
|
||||
|
||||
|
||||
#: E223
|
||||
foobart = 4
|
||||
a = 3 # aligned with tab
|
||||
#:
|
||||
|
||||
|
||||
#: E224
|
||||
a += 1
|
||||
b += 1000
|
||||
#:
|
||||
|
||||
|
||||
#: E225
|
||||
submitted +=1
|
||||
#: E225
|
||||
submitted+= 1
|
||||
#: E225
|
||||
c =-1
|
||||
#: E225
|
||||
x = x /2 - 1
|
||||
#: E225
|
||||
c = alpha -4
|
||||
#: E225
|
||||
c = alpha- 4
|
||||
#: E225
|
||||
z = x **y
|
||||
#: E225
|
||||
z = (x + 1) **y
|
||||
#: E225
|
||||
z = (x + 1)** y
|
||||
#: E225
|
||||
_1kB = _1MB >>10
|
||||
#: E225
|
||||
_1kB = _1MB>> 10
|
||||
#: E225 E225
|
||||
i=i+ 1
|
||||
#: E225 E225
|
||||
i=i +1
|
||||
#: E225
|
||||
i = 1and 1
|
||||
#: E225
|
||||
i = 1or 0
|
||||
#: E225
|
||||
1is 1
|
||||
#: E225
|
||||
1in []
|
||||
#: E225
|
||||
i = 1 @2
|
||||
#: E225
|
||||
i = 1@ 2
|
||||
#: E225 E226
|
||||
i=i+1
|
||||
#: E225 E226
|
||||
i =i+1
|
||||
#: E225 E226
|
||||
i= i+1
|
||||
#: E225 E226
|
||||
c = (a +b)*(a - b)
|
||||
#: E225 E226
|
||||
c = (a+ b)*(a - b)
|
||||
#:
|
||||
|
||||
#: E226
|
||||
z = 2//30
|
||||
#: E226 E226
|
||||
c = (a+b) * (a-b)
|
||||
#: E226
|
||||
norman = True+False
|
||||
#: E226
|
||||
x = x*2 - 1
|
||||
#: E226
|
||||
x = x/2 - 1
|
||||
#: E226 E226
|
||||
hypot2 = x*x + y*y
|
||||
#: E226
|
||||
c = (a + b)*(a - b)
|
||||
#: E226
|
||||
def halves(n):
|
||||
return (i//2 for i in range(n))
|
||||
#: E227
|
||||
_1kB = _1MB>>10
|
||||
#: E227
|
||||
_1MB = _1kB<<10
|
||||
#: E227
|
||||
a = b|c
|
||||
#: E227
|
||||
b = c&a
|
||||
#: E227
|
||||
c = b^a
|
||||
#: E228
|
||||
a = b%c
|
||||
#: E228
|
||||
msg = fmt%(errno, errmsg)
|
||||
#: E228
|
||||
msg = "Error %d occurred"%errno
|
||||
#:
|
||||
|
||||
#: Okay
|
||||
i = i + 1
|
||||
submitted += 1
|
||||
x = x * 2 - 1
|
||||
hypot2 = x * x + y * y
|
||||
c = (a + b) * (a - b)
|
||||
_1MiB = 2 ** 20
|
||||
_1TiB = 2**30
|
||||
foo(bar, key='word', *args, **kwargs)
|
||||
baz(**kwargs)
|
||||
negative = -1
|
||||
spam(-1)
|
||||
-negative
|
||||
func1(lambda *args, **kw: (args, kw))
|
||||
func2(lambda a, b=h[:], c=0: (a, b, c))
|
||||
if not -5 < x < +5:
|
||||
print >>sys.stderr, "x is out of range."
|
||||
print >> sys.stdout, "x is an integer."
|
||||
x = x / 2 - 1
|
||||
x = 1 @ 2
|
||||
|
||||
if alpha[:-i]:
|
||||
*a, b = (1, 2, 3)
|
||||
|
||||
|
||||
def squares(n):
|
||||
return (i**2 for i in range(n))
|
||||
|
||||
|
||||
ENG_PREFIXES = {
|
||||
-6: "\u03bc", # Greek letter mu
|
||||
-3: "m",
|
||||
}
|
||||
#:
|
||||
@@ -1,87 +0,0 @@
|
||||
"""Test: no-blank-line-after-function special-cases around comment handling."""
|
||||
|
||||
# OK
|
||||
def outer():
|
||||
"""This is a docstring."""
|
||||
def inner():
|
||||
return
|
||||
|
||||
return inner
|
||||
|
||||
|
||||
# OK
|
||||
def outer():
|
||||
"""This is a docstring."""
|
||||
|
||||
def inner():
|
||||
return
|
||||
|
||||
return inner
|
||||
|
||||
|
||||
# OK
|
||||
def outer():
|
||||
"""This is a docstring."""
|
||||
# This is a comment.
|
||||
def inner():
|
||||
return
|
||||
|
||||
return inner
|
||||
|
||||
|
||||
# OK
|
||||
def outer():
|
||||
"""This is a docstring."""
|
||||
|
||||
# This is a comment.
|
||||
def inner():
|
||||
return
|
||||
|
||||
return inner
|
||||
|
||||
|
||||
# OK
|
||||
def outer():
|
||||
"""This is a docstring."""
|
||||
|
||||
# This is a comment.
|
||||
# Followed by another comment.
|
||||
def inner():
|
||||
return
|
||||
|
||||
return inner
|
||||
|
||||
|
||||
# D202
|
||||
def outer():
|
||||
"""This is a docstring."""
|
||||
|
||||
|
||||
def inner():
|
||||
return
|
||||
|
||||
return inner
|
||||
|
||||
|
||||
# D202
|
||||
def outer():
|
||||
"""This is a docstring."""
|
||||
|
||||
|
||||
# This is a comment.
|
||||
def inner():
|
||||
return
|
||||
|
||||
return inner
|
||||
|
||||
|
||||
# D202
|
||||
def outer():
|
||||
"""This is a docstring."""
|
||||
|
||||
# This is a comment.
|
||||
|
||||
def inner():
|
||||
return
|
||||
|
||||
return inner
|
||||
@@ -1,6 +0,0 @@
|
||||
"""Test: explicit re-export of shadowed builtins."""
|
||||
|
||||
from concurrent.futures import (
|
||||
CancelledError as CancelledError,
|
||||
TimeoutError as TimeoutError,
|
||||
)
|
||||
@@ -1,53 +0,0 @@
|
||||
"""Test: noqa directives."""
|
||||
|
||||
from typing_extensions import List, Sequence
|
||||
|
||||
# This should ignore both errors.
|
||||
from typing import ( # noqa: F811
|
||||
List,
|
||||
Sequence,
|
||||
)
|
||||
|
||||
# This should ignore both errors.
|
||||
from typing import ( # noqa
|
||||
List,
|
||||
Sequence,
|
||||
)
|
||||
|
||||
# This should ignore both errors.
|
||||
from typing import (
|
||||
List, # noqa: F811
|
||||
Sequence, # noqa: F811
|
||||
)
|
||||
|
||||
# This should ignore both errors.
|
||||
from typing import (
|
||||
List, # noqa
|
||||
Sequence, # noqa
|
||||
)
|
||||
|
||||
# This should ignore the first error.
|
||||
from typing import (
|
||||
List, # noqa: F811
|
||||
Sequence,
|
||||
)
|
||||
|
||||
# This should ignore both errors.
|
||||
from typing import ( # noqa
|
||||
List,
|
||||
Sequence,
|
||||
)
|
||||
|
||||
# This should ignore both errors.
|
||||
from typing import List, Sequence # noqa: F811
|
||||
|
||||
# This should ignore both errors.
|
||||
from typing import List, Sequence # noqa
|
||||
|
||||
|
||||
def f():
|
||||
# This should ignore both errors.
|
||||
from typing import ( # noqa: F811
|
||||
List,
|
||||
Sequence,
|
||||
)
|
||||
@@ -1,3 +0,0 @@
|
||||
a = 1
|
||||
|
||||
__all__ = list(["a", "b"])
|
||||
@@ -1,15 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
# Test case for https://github.com/charliermarsh/ruff/issues/1552
|
||||
def f():
|
||||
x = 0
|
||||
list()[x:]
|
||||
|
||||
|
||||
# Test case for https://github.com/charliermarsh/ruff/issues/2603
|
||||
def f():
|
||||
KeyTupleT = tuple[str, ...]
|
||||
|
||||
keys_checked: set[KeyTupleT] = set()
|
||||
return keys_checked
|
||||
@@ -1,26 +0,0 @@
|
||||
def f():
|
||||
from typing import Literal
|
||||
|
||||
# OK
|
||||
x: Literal["foo"]
|
||||
|
||||
|
||||
def f():
|
||||
from .typical import Literal
|
||||
|
||||
# OK
|
||||
x: Literal["foo"]
|
||||
|
||||
|
||||
def f():
|
||||
from . import typical
|
||||
|
||||
# OK
|
||||
x: typical.Literal["foo"]
|
||||
|
||||
|
||||
def f():
|
||||
from .atypical import Literal
|
||||
|
||||
# F821
|
||||
x: Literal["foo"]
|
||||
@@ -1,33 +0,0 @@
|
||||
def f():
|
||||
from typing import Literal
|
||||
|
||||
# OK
|
||||
x: Literal["foo"]
|
||||
|
||||
|
||||
def f():
|
||||
from ..typical import Literal
|
||||
|
||||
# OK
|
||||
x: Literal["foo"]
|
||||
|
||||
|
||||
def f():
|
||||
from .. import typical
|
||||
|
||||
# OK
|
||||
x: typical.Literal["foo"]
|
||||
|
||||
|
||||
def f():
|
||||
from .typical import Literal
|
||||
|
||||
# F821
|
||||
x: Literal["foo"]
|
||||
|
||||
|
||||
def f():
|
||||
from .atypical import Literal
|
||||
|
||||
# F821
|
||||
x: Literal["foo"]
|
||||
@@ -1,73 +0,0 @@
|
||||
# PLE1310
|
||||
"Hello World".strip("Hello")
|
||||
|
||||
# PLE1310
|
||||
"Hello World".strip("Hello")
|
||||
|
||||
# PLE1310
|
||||
"Hello World".strip(u"Hello")
|
||||
|
||||
# PLE1310
|
||||
"Hello World".strip(r"Hello")
|
||||
|
||||
# PLE1310
|
||||
"Hello World".strip("Hello\t")
|
||||
|
||||
# PLE1310
|
||||
"Hello World".strip(r"Hello\t")
|
||||
|
||||
# PLE1310
|
||||
"Hello World".strip("Hello\\")
|
||||
|
||||
# PLE1310
|
||||
"Hello World".strip(r"Hello\\")
|
||||
|
||||
# PLE1310
|
||||
"Hello World".strip("🤣🤣🤣🤣🙃👀😀")
|
||||
|
||||
# PLE1310
|
||||
"Hello World".strip(
|
||||
"""
|
||||
there are a lot of characters to strip
|
||||
"""
|
||||
)
|
||||
|
||||
# PLE1310
|
||||
"Hello World".strip("can we get a long " \
|
||||
"string of characters to strip " \
|
||||
"please?")
|
||||
|
||||
# PLE1310
|
||||
"Hello World".strip(
|
||||
"can we get a long "
|
||||
"string of characters to strip "
|
||||
"please?"
|
||||
)
|
||||
|
||||
# PLE1310
|
||||
"Hello World".strip(
|
||||
"can \t we get a long"
|
||||
"string \t of characters to strip"
|
||||
"please?"
|
||||
)
|
||||
|
||||
# PLE1310
|
||||
"Hello World".strip(
|
||||
"abc def"
|
||||
"ghi"
|
||||
)
|
||||
|
||||
# PLE1310
|
||||
u''.strip('http://')
|
||||
|
||||
# PLE1310
|
||||
u''.lstrip('http://')
|
||||
|
||||
# PLE1310
|
||||
b''.rstrip('http://')
|
||||
|
||||
# OK
|
||||
''.strip('Hi')
|
||||
|
||||
# OK
|
||||
''.strip()
|
||||
@@ -1,38 +0,0 @@
|
||||
###
|
||||
# Errors.
|
||||
###
|
||||
def f():
|
||||
global X
|
||||
|
||||
|
||||
def f():
|
||||
global X
|
||||
|
||||
print(X)
|
||||
|
||||
|
||||
###
|
||||
# Non-errors.
|
||||
###
|
||||
def f():
|
||||
global X
|
||||
|
||||
X = 1
|
||||
|
||||
|
||||
def f():
|
||||
global X
|
||||
|
||||
(X, y) = (1, 2)
|
||||
|
||||
|
||||
def f():
|
||||
global X
|
||||
|
||||
del X
|
||||
|
||||
|
||||
def f():
|
||||
global X
|
||||
|
||||
X += 1
|
||||
@@ -1,31 +0,0 @@
|
||||
__all__ = "CONST" # [invalid-all-format]
|
||||
|
||||
__all__ = ["Hello"] + {"world"} # [invalid-all-format]
|
||||
|
||||
__all__ += {"world"} # [invalid-all-format]
|
||||
|
||||
__all__ = {"world"} + ["Hello"] # [invalid-all-format]
|
||||
|
||||
__all__ = {"world"} + list(["Hello"]) # [invalid-all-format]
|
||||
|
||||
__all__ = list(["Hello"]) + {"world"} # [invalid-all-format]
|
||||
|
||||
__all__ = (x for x in ["Hello", "world"]) # [invalid-all-format]
|
||||
|
||||
__all__ = {x for x in ["Hello", "world"]} # [invalid-all-format]
|
||||
|
||||
__all__ = ["Hello"]
|
||||
|
||||
__all__ = ("Hello",)
|
||||
|
||||
__all__ = ["Hello"] + ("world",)
|
||||
|
||||
__all__ = [x for x in ["Hello", "world"]]
|
||||
|
||||
__all__ = list(["Hello", "world"])
|
||||
|
||||
__all__ = list({"Hello", "world"})
|
||||
|
||||
__all__ = list(["Hello"]) + list(["world"])
|
||||
|
||||
__all__ = tuple(["Hello"]) + ("world",)
|
||||
@@ -1,15 +0,0 @@
|
||||
__all__ = (
|
||||
None, # [invalid-all-object]
|
||||
Fruit,
|
||||
Worm,
|
||||
)
|
||||
|
||||
__all__ = list([None, "Fruit", "Worm"]) # [invalid-all-object]
|
||||
|
||||
|
||||
class Fruit:
|
||||
pass
|
||||
|
||||
|
||||
class Worm:
|
||||
pass
|
||||
@@ -1,34 +0,0 @@
|
||||
def f(x, y, z, t, u, v, w, r): # Too many arguments (8/5)
|
||||
pass
|
||||
|
||||
|
||||
def f(x, y, z, t, u): # OK
|
||||
pass
|
||||
|
||||
|
||||
def f(x): # OK
|
||||
pass
|
||||
|
||||
|
||||
def f(x, y, z, _t, _u, _v, _w, r): # OK (underscore-prefixed names are ignored
|
||||
pass
|
||||
|
||||
|
||||
def f(x, y, z, u=1, v=1, r=1): # Too many arguments (6/5)
|
||||
pass
|
||||
|
||||
|
||||
def f(x=1, y=1, z=1): # OK
|
||||
pass
|
||||
|
||||
|
||||
def f(x, y, z, /, u, v, w): # OK
|
||||
pass
|
||||
|
||||
|
||||
def f(x, y, z, *, u, v, w): # OK
|
||||
pass
|
||||
|
||||
|
||||
def f(x, y, z, a, b, c, *, u, v, w): # Too many arguments (6/5)
|
||||
pass
|
||||
@@ -1,10 +0,0 @@
|
||||
# Too many args (6/4) for max_args=4
|
||||
# OK for dummy_variable_rgx ~ "skip_.*"
|
||||
def f(x, y, z, skip_t, skip_u, skip_v):
|
||||
pass
|
||||
|
||||
|
||||
# Too many args (6/4) for max_args=4
|
||||
# Too many args (6/5) for dummy_variable_rgx ~ "skip_.*"
|
||||
def f(x, y, z, t, u, v):
|
||||
pass
|
||||
@@ -1,72 +0,0 @@
|
||||
"""
|
||||
Test for too many branches.
|
||||
Taken from the pylint source 2023-02-03
|
||||
"""
|
||||
# pylint: disable=using-constant-test
|
||||
def wrong(): # [too-many-branches]
|
||||
""" Has too many branches. """
|
||||
if 1:
|
||||
pass
|
||||
elif 1:
|
||||
pass
|
||||
elif 1:
|
||||
pass
|
||||
elif 1:
|
||||
pass
|
||||
elif 1:
|
||||
pass
|
||||
elif 1:
|
||||
pass
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
pass
|
||||
if 2:
|
||||
pass
|
||||
while True:
|
||||
pass
|
||||
if 1:
|
||||
pass
|
||||
elif 2:
|
||||
pass
|
||||
elif 3:
|
||||
pass
|
||||
|
||||
def good():
|
||||
""" Too many branches only if we take
|
||||
into consideration the nested functions.
|
||||
"""
|
||||
def nested_1():
|
||||
""" empty """
|
||||
if 1:
|
||||
pass
|
||||
elif 2:
|
||||
pass
|
||||
elif 3:
|
||||
pass
|
||||
elif 4:
|
||||
pass
|
||||
|
||||
nested_1()
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
pass
|
||||
try:
|
||||
pass
|
||||
finally:
|
||||
pass
|
||||
if 1:
|
||||
pass
|
||||
elif 2:
|
||||
pass
|
||||
elif 3:
|
||||
pass
|
||||
elif 4:
|
||||
pass
|
||||
elif 5:
|
||||
pass
|
||||
elif 6:
|
||||
pass
|
||||
elif 7:
|
||||
pass
|
||||
@@ -1,19 +0,0 @@
|
||||
def f(x):
|
||||
if x:
|
||||
pass
|
||||
|
||||
|
||||
def g(x):
|
||||
if x:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
|
||||
def h(x):
|
||||
return
|
||||
|
||||
def i(x):
|
||||
if x:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
@@ -1,41 +0,0 @@
|
||||
"""
|
||||
https://github.com/PyCQA/pylint/blob/69eca9b3f9856c3033957b769358803ee48e8e47/tests/functional/t/too/too_many_return_statements.py
|
||||
"""
|
||||
def stupid_function(arg): # [too-many-return-statements]
|
||||
if arg == 1:
|
||||
return 1
|
||||
if arg == 2:
|
||||
return 2
|
||||
if arg == 3:
|
||||
return 3
|
||||
if arg == 4:
|
||||
return 4
|
||||
if arg == 5:
|
||||
return 5
|
||||
if arg == 6:
|
||||
return 6
|
||||
if arg == 7:
|
||||
return 7
|
||||
if arg == 8:
|
||||
return 8
|
||||
if arg == 9:
|
||||
return 9
|
||||
if arg == 10:
|
||||
return 10
|
||||
return None
|
||||
|
||||
|
||||
def many_yield(text):
|
||||
"""Not a problem"""
|
||||
if text:
|
||||
yield f" line 1: {text}\n"
|
||||
yield " line 2\n"
|
||||
yield " line 3\n"
|
||||
yield " line 4\n"
|
||||
yield " line 5\n"
|
||||
else:
|
||||
yield " line 6\n"
|
||||
yield " line 7\n"
|
||||
yield " line 8\n"
|
||||
yield " line 9\n"
|
||||
yield " line 10\n"
|
||||
@@ -1,5 +0,0 @@
|
||||
def f(x): # Too many return statements (2/1)
|
||||
if x == 1:
|
||||
return
|
||||
if x == 2:
|
||||
return
|
||||
@@ -1,56 +0,0 @@
|
||||
def f(): # OK
|
||||
return
|
||||
|
||||
|
||||
async def f(): # Too many statements (52/50)
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
print()
|
||||
@@ -1,8 +0,0 @@
|
||||
# Too may statements (2/1) for max_statements=1
|
||||
def f(x):
|
||||
pass
|
||||
|
||||
|
||||
def f(x):
|
||||
def g(x):
|
||||
pass
|
||||
@@ -1,15 +0,0 @@
|
||||
# Valid calls; no errors expected.
|
||||
|
||||
'{}'.format(1)
|
||||
|
||||
x = ('{0} {1}',)
|
||||
|
||||
'{0} {0}'.format(1)
|
||||
|
||||
'{0:<{1}}'.format(1, 4)
|
||||
|
||||
f"{0}".format(a)
|
||||
|
||||
f"{0}".format(1)
|
||||
|
||||
print(f"{0}".format(1))
|
||||
@@ -1,28 +0,0 @@
|
||||
# These SHOULD change
|
||||
|
||||
args = list(range(10))
|
||||
kwargs = {x: x for x in range(10)}
|
||||
|
||||
"{0}".format(*args)
|
||||
|
||||
"{0}".format(**kwargs)
|
||||
|
||||
"{0}_{1}".format(*args)
|
||||
|
||||
"{0}_{1}".format(1, *args)
|
||||
|
||||
"{1}_{0}".format(*args)
|
||||
|
||||
"{1}_{0}".format(1, *args)
|
||||
|
||||
"{0}_{1}".format(1, 2, *args)
|
||||
|
||||
"{0}_{1}".format(*args, 1, 2)
|
||||
|
||||
"{0}_{1}_{2}".format(1, **kwargs)
|
||||
|
||||
"{0}_{1}_{2}".format(1, 2, **kwargs)
|
||||
|
||||
"{0}_{1}_{2}".format(1, 2, 3, **kwargs)
|
||||
|
||||
"{0}_{1}_{2}".format(1, 2, 3, *args, **kwargs)
|
||||
@@ -1,50 +0,0 @@
|
||||
# UP035
|
||||
from collections import Mapping
|
||||
|
||||
from collections import Mapping as MAP
|
||||
|
||||
from collections import Mapping, Sequence
|
||||
|
||||
from collections import Counter, Mapping
|
||||
|
||||
from collections import (Counter, Mapping)
|
||||
|
||||
from collections import (Counter,
|
||||
Mapping)
|
||||
|
||||
from collections import Counter, \
|
||||
Mapping
|
||||
|
||||
from collections import Counter, Mapping, Sequence
|
||||
|
||||
from collections import Mapping as mapping, Counter
|
||||
|
||||
if True:
|
||||
from collections import Mapping, Counter
|
||||
|
||||
if True:
|
||||
if True:
|
||||
pass
|
||||
from collections import Mapping, Counter
|
||||
|
||||
if True: from collections import Mapping
|
||||
|
||||
import os
|
||||
from collections import Counter, Mapping
|
||||
import sys
|
||||
|
||||
if True:
|
||||
from collections import (
|
||||
Mapping,
|
||||
Callable,
|
||||
Bad,
|
||||
Good,
|
||||
)
|
||||
|
||||
from typing import Callable, Match, Pattern, List
|
||||
|
||||
if True: from collections import (
|
||||
Mapping, Counter)
|
||||
|
||||
# OK
|
||||
from a import b
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user