Compare commits

..

10 Commits

Author SHA1 Message Date
Zanie
ab6f173bc1 Add tag ltieral 2023-09-15 14:55:37 -05:00
Zanie
500d1b854b Demo full changes 2023-09-15 14:54:24 -05:00
Zanie
1c0c00d22d Unshallow main 2023-09-15 14:39:00 -05:00
Zanie
675cc216cb Test an older commit 2023-09-15 14:38:02 -05:00
Zanie
3fcfa50212 Try checking out main isntead of a the commit 2023-09-15 14:36:55 -05:00
Zanie
bf0d645692 Remove unshallow 2023-09-15 14:32:54 -05:00
Zanie
f392791b69 Fix depth 2023-09-15 14:31:53 -05:00
Zanie
b015a06966 Use a full clone 2023-09-15 14:29:24 -05:00
Zanie Blue
8cf0708b96 Remove branch 2023-09-15 14:27:09 -05:00
Zanie
3bc593ad7f DEBUG: Test main branch check for release 2023-09-15 14:22:49 -05:00
5449 changed files with 179634 additions and 233954 deletions

4
.gitattributes vendored
View File

@@ -1,7 +1,7 @@
* text=auto eol=lf * text=auto eol=lf
crates/ruff_linter/resources/test/fixtures/isort/line_ending_crlf.py text eol=crlf crates/ruff/resources/test/fixtures/isort/line_ending_crlf.py text eol=crlf
crates/ruff_linter/resources/test/fixtures/pycodestyle/W605_1.py text eol=crlf crates/ruff/resources/test/fixtures/pycodestyle/W605_1.py text eol=crlf
ruff.schema.json linguist-generated=true text=auto eol=lf ruff.schema.json linguist-generated=true text=auto eol=lf
*.md.snap linguist-language=Markdown *.md.snap linguist-language=Markdown

2
.github/CODEOWNERS vendored
View File

@@ -6,4 +6,4 @@
# - Order is important. The last matching pattern has the most precedence. # - Order is important. The last matching pattern has the most precedence.
# Jupyter # Jupyter
/crates/ruff_linter/src/jupyter/ @dhruvmanila /crates/ruff/src/jupyter/ @dhruvmanila

View File

@@ -9,5 +9,5 @@ updates:
- package-ecosystem: "cargo" - package-ecosystem: "cargo"
directory: "/" directory: "/"
schedule: schedule:
interval: "weekly" interval: "daily"
labels: ["internal"] labels: ["internal"]

28
.github/release.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
# https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes#configuring-automatically-generated-release-notes
changelog:
exclude:
labels:
- internal
- documentation
- formatter
categories:
- title: Breaking Changes
labels:
- breaking
- title: Rules
labels:
- rule
- autofix
- title: Settings
labels:
- configuration
- cli
- title: Bug Fixes
labels:
- bug
- title: Preview
labels:
- preview
- title: Other Changes
labels:
- "*"

View File

@@ -30,7 +30,7 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: tj-actions/changed-files@v40 - uses: tj-actions/changed-files@v39
id: changed id: changed
with: with:
files_yaml: | files_yaml: |
@@ -43,7 +43,6 @@ jobs:
- "!crates/ruff_dev/**" - "!crates/ruff_dev/**"
- "!crates/ruff_shrinking/**" - "!crates/ruff_shrinking/**"
- scripts/* - scripts/*
- .github/workflows/ci.yaml
formatter: formatter:
- Cargo.toml - Cargo.toml
@@ -58,7 +57,6 @@ jobs:
- crates/ruff_python_parser/** - crates/ruff_python_parser/**
- crates/ruff_dev/** - crates/ruff_dev/**
- scripts/* - scripts/*
- .github/workflows/ci.yaml
cargo-fmt: cargo-fmt:
name: "cargo fmt" name: "cargo fmt"
@@ -84,9 +82,12 @@ jobs:
- name: "Clippy (wasm)" - name: "Clippy (wasm)"
run: cargo clippy -p ruff_wasm --target wasm32-unknown-unknown --all-features -- -D warnings run: cargo clippy -p ruff_wasm --target wasm32-unknown-unknown --all-features -- -D warnings
cargo-test-linux: cargo-test:
runs-on: ubuntu-latest strategy:
name: "cargo test (linux)" matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
name: "cargo test | ${{ matrix.os }}"
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: "Install Rust toolchain" - name: "Install Rust toolchain"
@@ -95,55 +96,31 @@ jobs:
uses: taiki-e/install-action@v2 uses: taiki-e/install-action@v2
with: with:
tool: cargo-insta tool: cargo-insta
- run: pip install black[d]==23.1.0
- uses: Swatinem/rust-cache@v2 - uses: Swatinem/rust-cache@v2
- name: "Run tests" - name: "Run tests (Ubuntu)"
if: ${{ matrix.os == 'ubuntu-latest' }}
run: cargo insta test --all --all-features --unreferenced reject run: cargo insta test --all --all-features --unreferenced reject
- name: "Run tests (Windows)"
if: ${{ matrix.os == 'windows-latest' }}
shell: bash
# We can't reject unreferenced snapshots on windows because flake8_executable can't run on windows
run: cargo insta test --all --all-features
- run: cargo test --package ruff_cli --test black_compatibility_test -- --ignored
# TODO: Skipped as it's currently broken. The resource were moved from the
# ruff_cli to ruff crate, but this test was not updated.
if: false
# Check for broken links in the documentation. # Check for broken links in the documentation.
- run: cargo doc --all --no-deps - run: cargo doc --all --no-deps
env: env:
# Setting RUSTDOCFLAGS because `cargo doc --check` isn't yet implemented (https://github.com/rust-lang/cargo/issues/10025). # Setting RUSTDOCFLAGS because `cargo doc --check` isn't yet implemented (https://github.com/rust-lang/cargo/issues/10025).
RUSTDOCFLAGS: "-D warnings" RUSTDOCFLAGS: "-D warnings"
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
if: ${{ matrix.os == 'ubuntu-latest' }}
with: with:
name: ruff name: ruff
path: target/debug/ruff path: target/debug/ruff
cargo-test-windows:
runs-on: windows-latest
name: "cargo test (windows)"
steps:
- uses: actions/checkout@v4
- name: "Install Rust toolchain"
run: rustup show
- name: "Install cargo insta"
uses: taiki-e/install-action@v2
with:
tool: cargo-insta
- uses: Swatinem/rust-cache@v2
- name: "Run tests"
shell: bash
# We can't reject unreferenced snapshots on windows because flake8_executable can't run on windows
run: cargo insta test --all --all-features
cargo-test-wasm:
runs-on: ubuntu-latest
name: "cargo test (wasm)"
steps:
- uses: actions/checkout@v4
- name: "Install Rust toolchain"
run: rustup target add wasm32-unknown-unknown
- uses: actions/setup-node@v4
with:
node-version: 18
cache: "npm"
cache-dependency-path: playground/package-lock.json
- uses: jetli/wasm-pack-action@v0.4.0
- uses: Swatinem/rust-cache@v2
- name: "Run wasm-pack"
run: |
cd crates/ruff_wasm
wasm-pack test --node
cargo-fuzz: cargo-fuzz:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: "cargo fuzz" name: "cargo fuzz"
@@ -160,6 +137,25 @@ jobs:
tool: cargo-fuzz@0.11 tool: cargo-fuzz@0.11
- run: cargo fuzz build -s none - run: cargo fuzz build -s none
cargo-test-wasm:
runs-on: ubuntu-latest
name: "cargo test (wasm)"
steps:
- uses: actions/checkout@v4
- name: "Install Rust toolchain"
run: rustup target add wasm32-unknown-unknown
- uses: actions/setup-node@v3
with:
node-version: 18
cache: "npm"
cache-dependency-path: playground/package-lock.json
- uses: jetli/wasm-pack-action@v0.4.0
- uses: Swatinem/rust-cache@v2
- name: "Run wasm-pack"
run: |
cd crates/ruff_wasm
wasm-pack test --node
scripts: scripts:
name: "test scripts" name: "test scripts"
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -181,14 +177,10 @@ jobs:
name: "ecosystem" name: "ecosystem"
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: needs:
- cargo-test-linux - cargo-test
- determine_changes - determine_changes
# Only runs on pull requests, since that is the only we way we can find the base version for comparison. # Only runs on pull requests, since that is the only we way we can find the base version for comparison.
# Ecosystem check needs linter and/or formatter changes. if: github.event_name == 'pull_request' && needs.determine_changes.outputs.linter == 'true'
if: github.event_name == 'pull_request' && ${{
needs.determine_changes.outputs.linter == 'true' ||
needs.determine_changes.outputs.formatter == 'true'
}}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-python@v4 - uses: actions/setup-python@v4
@@ -196,89 +188,27 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }} python-version: ${{ env.PYTHON_VERSION }}
- uses: actions/download-artifact@v3 - uses: actions/download-artifact@v3
name: Download comparison Ruff binary name: Download Ruff binary
id: ruff-target id: ruff-target
with: with:
name: ruff name: ruff
path: target/debug path: target/debug
- uses: dawidd6/action-download-artifact@v2 - uses: dawidd6/action-download-artifact@v2
name: Download baseline Ruff binary name: Download base results
with: with:
name: ruff name: ruff
branch: ${{ github.event.pull_request.base.ref }} branch: ${{ github.event.pull_request.base.ref }}
check_artifacts: true check_artifacts: true
- name: Install ruff-ecosystem - name: Run ecosystem check
run: |
pip install ./python/ruff-ecosystem
- name: Run `ruff check` stable ecosystem check
if: ${{ needs.determine_changes.outputs.linter == 'true' }}
run: | run: |
# Make executable, since artifact download doesn't preserve this # Make executable, since artifact download doesn't preserve this
chmod +x ./ruff ${{ steps.ruff-target.outputs.download-path }}/ruff chmod +x ruff ${{ steps.ruff-target.outputs.download-path }}/ruff
# Set pipefail to avoid hiding errors with tee scripts/check_ecosystem.py ruff ${{ steps.ruff-target.outputs.download-path }}/ruff | tee ecosystem-result
set -eo pipefail cat ecosystem-result > $GITHUB_STEP_SUMMARY
ruff-ecosystem check ./ruff ${{ steps.ruff-target.outputs.download-path }}/ruff --cache ./checkouts --output-format markdown | tee ecosystem-result-check-stable
cat ecosystem-result-check-stable > $GITHUB_STEP_SUMMARY
echo "### Linter (stable)" > ecosystem-result
cat ecosystem-result-check-stable >> ecosystem-result
echo "" >> ecosystem-result
- name: Run `ruff check` preview ecosystem check
if: ${{ needs.determine_changes.outputs.linter == 'true' }}
run: |
# Make executable, since artifact download doesn't preserve this
chmod +x ./ruff ${{ steps.ruff-target.outputs.download-path }}/ruff
# Set pipefail to avoid hiding errors with tee
set -eo pipefail
ruff-ecosystem check ./ruff ${{ steps.ruff-target.outputs.download-path }}/ruff --cache ./checkouts --output-format markdown --force-preview | tee ecosystem-result-check-preview
cat ecosystem-result-check-preview > $GITHUB_STEP_SUMMARY
echo "### Linter (preview)" >> ecosystem-result
cat ecosystem-result-check-preview >> ecosystem-result
echo "" >> ecosystem-result
- name: Run `ruff format` stable ecosystem check
if: ${{ needs.determine_changes.outputs.formatter == 'true' }}
run: |
# Make executable, since artifact download doesn't preserve this
chmod +x ./ruff ${{ steps.ruff-target.outputs.download-path }}/ruff
# Set pipefail to avoid hiding errors with tee
set -eo pipefail
ruff-ecosystem format ./ruff ${{ steps.ruff-target.outputs.download-path }}/ruff --cache ./checkouts --output-format markdown | tee ecosystem-result-format-stable
cat ecosystem-result-format-stable > $GITHUB_STEP_SUMMARY
echo "### Formatter (stable)" >> ecosystem-result
cat ecosystem-result-format-stable >> ecosystem-result
echo "" >> ecosystem-result
- name: Run `ruff format` preview ecosystem check
if: ${{ needs.determine_changes.outputs.formatter == 'true' }}
run: |
# Make executable, since artifact download doesn't preserve this
chmod +x ./ruff ${{ steps.ruff-target.outputs.download-path }}/ruff
# Set pipefail to avoid hiding errors with tee
set -eo pipefail
ruff-ecosystem format ./ruff ${{ steps.ruff-target.outputs.download-path }}/ruff --cache ./checkouts --output-format markdown --force-preview | tee ecosystem-result-format-preview
cat ecosystem-result-format-preview > $GITHUB_STEP_SUMMARY
echo "### Formatter (preview)" >> ecosystem-result
cat ecosystem-result-format-preview >> ecosystem-result
echo "" >> ecosystem-result
- name: Export pull request number
run: |
echo ${{ github.event.number }} > pr-number echo ${{ github.event.number }} > pr-number
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
@@ -300,12 +230,12 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: "Install nightly Rust toolchain" - name: "Install nightly Rust toolchain"
# Only pinned to make caching work, update freely # Only pinned to make caching work, update freely
run: rustup toolchain install nightly-2023-10-15 run: rustup toolchain install nightly-2023-06-08
- uses: Swatinem/rust-cache@v2 - uses: Swatinem/rust-cache@v2
- name: "Install cargo-udeps" - name: "Install cargo-udeps"
uses: taiki-e/install-action@cargo-udeps uses: taiki-e/install-action@cargo-udeps
- name: "Run cargo-udeps" - name: "Run cargo-udeps"
run: cargo +nightly-2023-10-15 udeps run: cargo +nightly-2023-06-08 udeps
python-package: python-package:
name: "python package" name: "python package"
@@ -394,8 +324,8 @@ jobs:
if: ${{ env.MKDOCS_INSIDERS_SSH_KEY_EXISTS != 'true' }} if: ${{ env.MKDOCS_INSIDERS_SSH_KEY_EXISTS != 'true' }}
run: mkdocs build --strict -f mkdocs.generated.yml run: mkdocs build --strict -f mkdocs.generated.yml
check-formatter-instability-and-black-similarity: check-formatter-ecosystem:
name: "formatter instabilities and black similarity" name: "Formatter ecosystem and progress checks"
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: determine_changes needs: determine_changes
if: needs.determine_changes.outputs.formatter == 'true' || github.ref == 'refs/heads/main' if: needs.determine_changes.outputs.formatter == 'true' || github.ref == 'refs/heads/main'
@@ -412,45 +342,6 @@ jobs:
- name: "Remove checkouts from cache" - name: "Remove checkouts from cache"
run: rm -r target/progress_projects run: rm -r target/progress_projects
check-ruff-lsp:
name: "test ruff-lsp"
runs-on: ubuntu-latest
needs: cargo-test-linux
steps:
- uses: extractions/setup-just@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v4
name: "Download ruff-lsp source"
with:
repository: "astral-sh/ruff-lsp"
- uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
- uses: actions/download-artifact@v3
name: Download development ruff binary
id: ruff-target
with:
name: ruff
path: target/debug
- name: Install ruff-lsp dependencies
run: |
just install
- name: Run ruff-lsp tests
run: |
# Setup development binary
pip uninstall --yes ruff
chmod +x ${{ steps.ruff-target.outputs.download-path }}/ruff
export PATH=${{ steps.ruff-target.outputs.download-path }}:$PATH
ruff version
just test
benchmarks: benchmarks:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@@ -475,3 +366,31 @@ jobs:
with: with:
run: cargo codspeed run run: cargo codspeed run
token: ${{ secrets.CODSPEED_TOKEN }} token: ${{ secrets.CODSPEED_TOKEN }}
tmp:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: main # We checkout the main branch to check for the commit
- name: Check main branch
run: |
# Fetch the main branch since a shallow checkout is used by default
git fetch origin main --unshallow
if ! git branch --contains 0c030b5bf31e425cb6070db7386243eca6dbd8f1 | grep -E '(^|\s)main$'; then
echo "The specified sha is not on the main branch" >&2
exit 1
fi
- name: Check tag consistency
run: |
# Switch to the commit we want to release
git checkout 0c030b5bf31e425cb6070db7386243eca6dbd8f1
version=$(grep "version = " pyproject.toml | sed -e 's/version = "\(.*\)"/\1/g')
if [ "0.0.290" != "${version}" ]; then
echo "The input tag does not match the version from pyproject.toml:" >&2
echo "0.0.290" >&2
echo "${version}" >&2
exit 1
else
echo "Releasing ${version}"
fi

View File

@@ -47,9 +47,9 @@ jobs:
run: mkdocs build --strict -f mkdocs.generated.yml run: mkdocs build --strict -f mkdocs.generated.yml
- name: "Deploy to Cloudflare Pages" - name: "Deploy to Cloudflare Pages"
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }} if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
uses: cloudflare/wrangler-action@v3.3.2 uses: cloudflare/wrangler-action@v3.1.1
with: with:
apiToken: ${{ secrets.CF_API_TOKEN }} apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }} accountId: ${{ secrets.CF_ACCOUNT_ID }}
# `github.head_ref` is only set during pull requests and for manual runs or tags we use `main` to deploy to production # `github.head_ref` is only set during pull requests and for manual runs or tags we use `main` to deploy to production
command: pages deploy site --project-name=astral-docs --branch ${{ github.head_ref || 'main' }} --commit-hash ${GITHUB_SHA} command: pages deploy site --project-name=ruff-docs --branch ${{ github.head_ref || 'main' }} --commit-hash ${GITHUB_SHA}

View File

@@ -20,7 +20,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: "Install Rust toolchain" - name: "Install Rust toolchain"
run: rustup target add wasm32-unknown-unknown run: rustup target add wasm32-unknown-unknown
- uses: actions/setup-node@v4 - uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 18
cache: "npm" cache: "npm"
@@ -40,9 +40,8 @@ jobs:
working-directory: playground working-directory: playground
- name: "Deploy to Cloudflare Pages" - name: "Deploy to Cloudflare Pages"
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }} if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
uses: cloudflare/wrangler-action@v3.3.2 uses: cloudflare/wrangler-action@v3.1.1
with: with:
apiToken: ${{ secrets.CF_API_TOKEN }} apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }} accountId: ${{ secrets.CF_ACCOUNT_ID }}
# `github.head_ref` is only set during pull requests and for manual runs or tags we use `main` to deploy to production command: pages publish playground/dist --project-name=ruff --branch ${GITHUB_HEAD_REF} --commit-hash ${GITHUB_SHA}
command: pages deploy playground/dist --project-name=ruff-playground --branch ${{ github.head_ref || 'main' }} --commit-hash ${GITHUB_SHA}

View File

@@ -1,4 +1,4 @@
name: Ecosystem check comment name: PR Check Comment
on: on:
workflow_run: workflow_run:
@@ -18,13 +18,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: dawidd6/action-download-artifact@v2 - uses: dawidd6/action-download-artifact@v2
name: Download pull request number name: Download PR Number
with: with:
name: pr-number name: pr-number
run_id: ${{ github.event.workflow_run.id || github.event.inputs.workflow_run_id }} run_id: ${{ github.event.workflow_run.id || github.event.inputs.workflow_run_id }}
if_no_artifact_found: ignore if_no_artifact_found: ignore
- name: Parse pull request number - name: Extract PR Number
id: pr-number id: pr-number
run: | run: |
if [[ -f pr-number ]] if [[ -f pr-number ]]
@@ -33,7 +33,7 @@ jobs:
fi fi
- uses: dawidd6/action-download-artifact@v2 - uses: dawidd6/action-download-artifact@v2
name: "Download ecosystem results" name: "Download Ecosystem Result"
id: download-ecosystem-result id: download-ecosystem-result
if: steps.pr-number.outputs.pr-number if: steps.pr-number.outputs.pr-number
with: with:
@@ -41,18 +41,15 @@ jobs:
workflow: ci.yaml workflow: ci.yaml
pr: ${{ steps.pr-number.outputs.pr-number }} pr: ${{ steps.pr-number.outputs.pr-number }}
path: pr/ecosystem path: pr/ecosystem
workflow_conclusion: completed
if_no_artifact_found: ignore if_no_artifact_found: ignore
- name: Generate comment content - name: Generate Comment
id: generate-comment id: generate-comment
if: steps.download-ecosystem-result.outputs.found_artifact == 'true' if: steps.download-ecosystem-result.outputs.found_artifact == 'true'
run: | run: |
# Note this identifier is used to find the comment to update on echo '## PR Check Results' >> comment.txt
# subsequent runs
echo '<!-- generated-comment ecosystem -->' >> comment.txt
echo '## `ruff-ecosystem` results' >> comment.txt echo "### Ecosystem" >> comment.txt
cat pr/ecosystem/ecosystem-result >> comment.txt cat pr/ecosystem/ecosystem-result >> comment.txt
echo "" >> comment.txt echo "" >> comment.txt
@@ -60,14 +57,14 @@ jobs:
cat comment.txt >> $GITHUB_OUTPUT cat comment.txt >> $GITHUB_OUTPUT
echo 'EOF' >> $GITHUB_OUTPUT echo 'EOF' >> $GITHUB_OUTPUT
- name: Find existing comment - name: Find Comment
uses: peter-evans/find-comment@v2 uses: peter-evans/find-comment@v2
if: steps.generate-comment.outcome == 'success' if: steps.generate-comment.outcome == 'success'
id: find-comment id: find-comment
with: with:
issue-number: ${{ steps.pr-number.outputs.pr-number }} issue-number: ${{ steps.pr-number.outputs.pr-number }}
comment-author: "github-actions[bot]" comment-author: "github-actions[bot]"
body-includes: "<!-- generated-comment ecosystem -->" body-includes: PR Check Results
- name: Create or update comment - name: Create or update comment
if: steps.find-comment.outcome == 'success' if: steps.find-comment.outcome == 'success'

View File

@@ -48,6 +48,7 @@ jobs:
args: --out dist args: --out dist
- name: "Test sdist" - name: "Test sdist"
run: | run: |
rustup default $(cat rust-toolchain)
pip install dist/${{ env.PACKAGE_NAME }}-*.tar.gz --force-reinstall pip install dist/${{ env.PACKAGE_NAME }}-*.tar.gz --force-reinstall
ruff --help ruff --help
python -m ruff --help python -m ruff --help
@@ -418,7 +419,18 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
ref: main # We checkout the main branch to check for the commit ref: ${{ inputs.sha }}
- name: Check tag consistency
run: |
version=$(grep "version = " pyproject.toml | sed -e 's/version = "\(.*\)"/\1/g')
if [ "${{ inputs.tag }}" != "${version}" ]; then
echo "The input tag does not match the version from pyproject.toml:" >&2
echo "${{ inputs.tag }}" >&2
echo "${version}" >&2
exit 1
else
echo "Releasing ${version}"
fi
- name: Check main branch - name: Check main branch
if: ${{ inputs.sha }} if: ${{ inputs.sha }}
run: | run: |
@@ -428,18 +440,17 @@ jobs:
echo "The specified sha is not on the main branch" >&2 echo "The specified sha is not on the main branch" >&2
exit 1 exit 1
fi fi
- name: Check tag consistency - name: Check SHA consistency
if: ${{ inputs.sha }}
run: | run: |
# Switch to the commit we want to release git_sha=$(git rev-parse HEAD)
git checkout ${{ inputs.sha }} if [ "${{ inputs.sha }}" != "${git_sha}" ]; then
version=$(grep "version = " pyproject.toml | sed -e 's/version = "\(.*\)"/\1/g') echo "The specified sha does not match the git checkout" >&2
if [ "${{ inputs.tag }}" != "${version}" ]; then echo "${{ inputs.sha }}" >&2
echo "The input tag does not match the version from pyproject.toml:" >&2 echo "${git_sha}" >&2
echo "${{ inputs.tag }}" >&2
echo "${version}" >&2
exit 1 exit 1
else else
echo "Releasing ${version}" echo "Releasing ${git_sha}"
fi fi
upload-release: upload-release:

8
.gitignore vendored
View File

@@ -1,5 +1,5 @@
# Benchmarking cpython (CONTRIBUTING.md) # Benchmarking cpython (CONTRIBUTING.md)
crates/ruff_linter/resources/test/cpython crates/ruff/resources/test/cpython
# generate_mkdocs.py # generate_mkdocs.py
mkdocs.generated.yml mkdocs.generated.yml
# check_ecosystem.py # check_ecosystem.py
@@ -208,9 +208,3 @@ cython_debug/
# VIM # VIM
.*.sw? .*.sw?
.sw? .sw?
# Custom re-inclusions for the resolver test cases
!crates/ruff_python_resolver/resources/test/airflow/venv/
!crates/ruff_python_resolver/resources/test/airflow/venv/lib
!crates/ruff_python_resolver/resources/test/airflow/venv/lib/python3.11/site-packages/_watchdog_fsevents.cpython-311-darwin.so
!crates/ruff_python_resolver/resources/test/airflow/venv/lib/python3.11/site-packages/orjson/orjson.cpython-311-darwin.so

View File

@@ -13,8 +13,3 @@ MD041: false
# MD013/line-length # MD013/line-length
MD013: false MD013: false
# MD024/no-duplicate-heading
MD024:
# Allow when nested under different parents e.g. CHANGELOG.md
allow_different_nesting: true

View File

@@ -2,8 +2,8 @@ fail_fast: true
exclude: | exclude: |
(?x)^( (?x)^(
crates/ruff_linter/resources/.*| crates/ruff/resources/.*|
crates/ruff_linter/src/rules/.*/snapshots/.*| crates/ruff/src/rules/.*/snapshots/.*|
crates/ruff_cli/resources/.*| crates/ruff_cli/resources/.*|
crates/ruff_python_formatter/resources/.*| crates/ruff_python_formatter/resources/.*|
crates/ruff_python_formatter/tests/snapshots/.*| crates/ruff_python_formatter/tests/snapshots/.*|
@@ -13,35 +13,24 @@ exclude: |
repos: repos:
- repo: https://github.com/abravalheri/validate-pyproject - repo: https://github.com/abravalheri/validate-pyproject
rev: v0.15 rev: v0.12.1
hooks: hooks:
- id: validate-pyproject - id: validate-pyproject
- repo: https://github.com/executablebooks/mdformat - repo: https://github.com/executablebooks/mdformat
rev: 0.7.17 rev: 0.7.16
hooks: hooks:
- id: mdformat - id: mdformat
additional_dependencies: additional_dependencies:
- mdformat-mkdocs - mdformat-mkdocs
- mdformat-admon
exclude: |
(?x)^(
docs/formatter/black\.md
| docs/\w+\.md
)$
- repo: https://github.com/igorshubovych/markdownlint-cli - repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.37.0 rev: v0.33.0
hooks: hooks:
- id: markdownlint-fix - id: markdownlint-fix
exclude: |
(?x)^(
docs/formatter/black\.md
| docs/\w+\.md
)$
- repo: https://github.com/crate-ci/typos - repo: https://github.com/crate-ci/typos
rev: v1.16.22 rev: v1.14.12
hooks: hooks:
- id: typos - id: typos
@@ -53,24 +42,27 @@ repos:
language: system language: system
types: [rust] types: [rust]
pass_filenames: false # This makes it a lot faster pass_filenames: false # This makes it a lot faster
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.4
hooks:
- id: ruff-format
- id: ruff - id: ruff
args: [--fix, --exit-non-zero-on-fix] name: ruff
entry: cargo run --bin ruff -- check --no-cache --force-exclude --fix --exit-non-zero-on-fix
language: system
types_or: [python, pyi] types_or: [python, pyi]
require_serial: true require_serial: true
exclude: | exclude: |
(?x)^( (?x)^(
crates/ruff_linter/resources/.*| crates/ruff/resources/.*|
crates/ruff_python_formatter/resources/.* crates/ruff_python_formatter/resources/.*
)$ )$
# Black
- repo: https://github.com/psf/black
rev: 23.1.0
hooks:
- id: black
# Prettier # Prettier
- repo: https://github.com/pre-commit/mirrors-prettier - repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.0.3 rev: v3.0.0
hooks: hooks:
- id: prettier - id: prettier
types: [yaml] types: [yaml]

View File

@@ -1,35 +1,5 @@
# Breaking Changes # Breaking Changes
## 0.1.0
### The deprecated `format` setting has been removed
Ruff previously used the `format` setting, `--format` CLI option, and `RUFF_FORMAT` environment variable to
configure the output format of the CLI. This usage was deprecated in `v0.0.291` — the `format` setting is now used
to control Ruff's code formatting. As of this release:
- The `format` setting cannot be used to configure the output format, use `output-format` instead
- The `RUFF_FORMAT` environment variable is ignored, use `RUFF_OUTPUT_FORMAT` instead
- The `--format` option has been removed from `ruff check`, use `--output-format` instead
### Unsafe fixes are not applied by default ([#7769](https://github.com/astral-sh/ruff/pull/7769))
Ruff labels fixes as "safe" and "unsafe". The meaning and intent of your code will be retained when applying safe
fixes, but the meaning could be changed when applying unsafe fixes. Previously, unsafe fixes were always displayed
and applied when fixing was enabled. Now, unsafe fixes are hidden by default and not applied. The `--unsafe-fixes`
flag or `unsafe-fixes` configuration option can be used to enable unsafe fixes.
See the [docs](https://docs.astral.sh/ruff/configuration/#fix-safety) for details.
### Remove formatter-conflicting rules from the default rule set ([#7900](https://github.com/astral-sh/ruff/pull/7900))
Previously, Ruff enabled all implemented rules in Pycodestyle (`E`) by default. Ruff now only includes the
Pycodestyle prefixes `E4`, `E7`, and `E9` to exclude rules that conflict with automatic formatters. Consequently,
the stable rule set no longer includes `line-too-long` (`E501`) and `mixed-spaces-and-tabs` (`E101`). Other
excluded Pycodestyle rules include whitespace enforcement in `E1` and `E2`; these rules are currently in preview, and are already omitted by default.
This change only affects those using Ruff under its default rule set. Users that include `E` in their `select` will experience no change in behavior.
## 0.0.288 ## 0.0.288
### Remove support for emoji identifiers ([#7212](https://github.com/astral-sh/ruff/pull/7212)) ### Remove support for emoji identifiers ([#7212](https://github.com/astral-sh/ruff/pull/7212))
@@ -329,4 +299,4 @@ default.
`pyproject.toml` files are now resolved hierarchically, such that for each Python file, we find `pyproject.toml` files are now resolved hierarchically, such that for each Python file, we find
the first `pyproject.toml` file in its path, and use that to determine its lint settings. the first `pyproject.toml` file in its path, and use that to determine its lint settings.
See the [documentation](https://docs.astral.sh/ruff/configuration/#python-file-discovery) for more. See the [documentation](https://beta.ruff.rs/docs/configuration/#python-file-discovery) for more.

View File

@@ -1,384 +0,0 @@
# Changelog
## 0.1.5
### Preview features
- \[`flake8-bandit`\] Implement `mako-templates` (`S702`) ([#8533](https://github.com/astral-sh/ruff/pull/8533))
- \[`flake8-trio`\] Implement `TRIO105` ([#8490](https://github.com/astral-sh/ruff/pull/8490))
- \[`flake8-trio`\] Implement `TRIO109` ([#8534](https://github.com/astral-sh/ruff/pull/8534))
- \[`flake8-trio`\] Implement `TRIO110` ([#8537](https://github.com/astral-sh/ruff/pull/8537))
- \[`flake8-trio`\] Implement `TRIO115` ([#8486](https://github.com/astral-sh/ruff/pull/8486))
- \[`refurb`\] Implement `type-none-comparison` (`FURB169`) ([#8487](https://github.com/astral-sh/ruff/pull/8487))
- Flag all comparisons against builtin types in `E721` ([#8491](https://github.com/astral-sh/ruff/pull/8491))
- Make `SIM118` fix as safe when the expression is a known dictionary ([#8525](https://github.com/astral-sh/ruff/pull/8525))
### Formatter
- Fix multiline lambda expression statement formatting ([#8466](https://github.com/astral-sh/ruff/pull/8466))
### CLI
- Add hidden `--extension` to override inference of source type from file extension ([#8373](https://github.com/astral-sh/ruff/pull/8373))
### Configuration
- Account for selector specificity when merging `extend_unsafe_fixes` and `override extend_safe_fixes` ([#8444](https://github.com/astral-sh/ruff/pull/8444))
- Add support for disabling cache with `RUFF_NO_CACHE` environment variable ([#8538](https://github.com/astral-sh/ruff/pull/8538))
### Bug fixes
- \[`E721`\] Flag comparisons to `memoryview` ([#8485](https://github.com/astral-sh/ruff/pull/8485))
- Allow collapsed-ellipsis bodies in other statements ([#8499](https://github.com/astral-sh/ruff/pull/8499))
- Avoid `D301` autofix for `u` prefixed strings ([#8495](https://github.com/astral-sh/ruff/pull/8495))
- Only flag `flake8-trio` rules when `trio` import is present ([#8550](https://github.com/astral-sh/ruff/pull/8550))
- Reject more syntactically invalid Python programs ([#8524](https://github.com/astral-sh/ruff/pull/8524))
- Avoid raising `TRIO115` violations for `trio.sleep(...)` calls with non-number values ([#8532](https://github.com/astral-sh/ruff/pull/8532))
- Fix `F841` false negative on assignment to multiple variables ([#8489](https://github.com/astral-sh/ruff/pull/8489))
### Documentation
- Fix link to isort `known-first-party` ([#8562](https://github.com/astral-sh/ruff/pull/8562))
- Add notes on fix safety to a few rules ([#8500](https://github.com/astral-sh/ruff/pull/8500))
- Add missing toml config tabs ([#8512](https://github.com/astral-sh/ruff/pull/8512))
- Add instructions for configuration of Emacs ([#8488](https://github.com/astral-sh/ruff/pull/8488))
- Improve detail link contrast in dark mode ([#8548](https://github.com/astral-sh/ruff/pull/8548))
- Fix typo in example ([#8506](https://github.com/astral-sh/ruff/pull/8506))
- Added tabs for configuration files in the documentation ([#8480](https://github.com/astral-sh/ruff/pull/8480))
- Recommend `project.requires-python` over `target-version` ([#8513](https://github.com/astral-sh/ruff/pull/8513))
- Add singleton escape hatch to `B008` documentation ([#8501](https://github.com/astral-sh/ruff/pull/8501))
- Fix tab configuration docs ([#8502](https://github.com/astral-sh/ruff/pull/8502))
## 0.1.4
### Preview features
- \[`flake8-trio`\] Implement `timeout-without-await` (`TRIO001`) ([#8439](https://github.com/astral-sh/ruff/pull/8439))
- \[`numpy`\] Implement NumPy 2.0 migration rule (`NPY200`) ([#7702](https://github.com/astral-sh/ruff/pull/7702))
- \[`pylint`\] Implement `bad-open-mode` (`W1501`) ([#8294](https://github.com/astral-sh/ruff/pull/8294))
- \[`pylint`\] Implement `import-outside-toplevel` (`C0415`) rule ([#5180](https://github.com/astral-sh/ruff/pull/5180))
- \[`pylint`\] Implement `useless-with-lock` (`W2101`) ([#8321](https://github.com/astral-sh/ruff/pull/8321))
- \[`pyupgrade`\] Implement `timeout-error-alias` (`UP041`) ([#8476](https://github.com/astral-sh/ruff/pull/8476))
- \[`refurb`\] Implement `isinstance-type-none` (`FURB168`) ([#8308](https://github.com/astral-sh/ruff/pull/8308))
- Detect confusable Unicode-to-Unicode units in `RUF001`, `RUF002`, and `RUF003` ([#4430](https://github.com/astral-sh/ruff/pull/4430))
- Add newline after module docstrings in preview style ([#8283](https://github.com/astral-sh/ruff/pull/8283))
### Formatter
- Add a note on line-too-long to the formatter docs ([#8314](https://github.com/astral-sh/ruff/pull/8314))
- Preserve trailing statement semicolons when using `fmt: skip` ([#8273](https://github.com/astral-sh/ruff/pull/8273))
- Preserve trailing semicolons when using `fmt: off` ([#8275](https://github.com/astral-sh/ruff/pull/8275))
- Avoid duplicating linter-formatter compatibility warnings ([#8292](https://github.com/astral-sh/ruff/pull/8292))
- Avoid inserting a newline after function docstrings ([#8375](https://github.com/astral-sh/ruff/pull/8375))
- Insert newline between docstring and following own line comment ([#8216](https://github.com/astral-sh/ruff/pull/8216))
- Split tuples in return positions by comma first ([#8280](https://github.com/astral-sh/ruff/pull/8280))
- Avoid treating byte strings as docstrings ([#8350](https://github.com/astral-sh/ruff/pull/8350))
- Add `--line-length` option to `format` command ([#8363](https://github.com/astral-sh/ruff/pull/8363))
- Avoid parenthesizing unsplittable because of comments ([#8431](https://github.com/astral-sh/ruff/pull/8431))
### CLI
- Add `--output-format` to `ruff rule` and `ruff linter` ([#8203](https://github.com/astral-sh/ruff/pull/8203))
### Bug fixes
- Respect `--force-exclude` in `lint.exclude` and `format.exclude` ([#8393](https://github.com/astral-sh/ruff/pull/8393))
- Respect `--extend-per-file-ignores` on the CLI ([#8329](https://github.com/astral-sh/ruff/pull/8329))
- Extend `bad-dunder-method-name` to permit `__index__` ([#8300](https://github.com/astral-sh/ruff/pull/8300))
- Fix panic with 8 in octal escape ([#8356](https://github.com/astral-sh/ruff/pull/8356))
- Avoid raising `D300` when both triple quote styles are present ([#8462](https://github.com/astral-sh/ruff/pull/8462))
- Consider unterminated f-strings in `FStringRanges` ([#8154](https://github.com/astral-sh/ruff/pull/8154))
- Avoid including literal `shell=True` for truthy, non-`True` diagnostics ([#8359](https://github.com/astral-sh/ruff/pull/8359))
- Avoid triggering single-element test for starred expressions ([#8433](https://github.com/astral-sh/ruff/pull/8433))
- Detect and ignore Jupyter automagics ([#8398](https://github.com/astral-sh/ruff/pull/8398))
- Fix invalid E231 error with f-strings ([#8369](https://github.com/astral-sh/ruff/pull/8369))
- Avoid triggering `NamedTuple` rewrite with starred annotation ([#8434](https://github.com/astral-sh/ruff/pull/8434))
- Avoid un-setting bracket flag in logical lines ([#8380](https://github.com/astral-sh/ruff/pull/8380))
- Place 'r' prefix before 'f' for raw format strings ([#8464](https://github.com/astral-sh/ruff/pull/8464))
- Remove trailing periods from NumPy 2.0 code actions ([#8475](https://github.com/astral-sh/ruff/pull/8475))
- Fix bug where `PLE1307` was raised when formatting `%c` with characters ([#8407](https://github.com/astral-sh/ruff/pull/8407))
- Remove unicode flag from comparable ([#8440](https://github.com/astral-sh/ruff/pull/8440))
- Improve B015 message ([#8295](https://github.com/astral-sh/ruff/pull/8295))
- Use `fixedOverflowWidgets` for playground popover ([#8458](https://github.com/astral-sh/ruff/pull/8458))
- Mark `byte_bounds` as a non-backwards-compatible NumPy 2.0 change ([#8474](https://github.com/astral-sh/ruff/pull/8474))
### Internals
- Add a dedicated cache directory per Ruff version ([#8333](https://github.com/astral-sh/ruff/pull/8333))
- Allow selective caching for `--fix` and `--diff` ([#8316](https://github.com/astral-sh/ruff/pull/8316))
- Improve performance of comment parsing ([#8193](https://github.com/astral-sh/ruff/pull/8193))
- Improve performance of string parsing ([#8227](https://github.com/astral-sh/ruff/pull/8227))
- Use a dedicated sort key for isort import sorting ([#7963](https://github.com/astral-sh/ruff/pull/7963))
## 0.1.3
This release includes a variety of improvements to the Ruff formatter, removing several known and
unintentional deviations from Black.
### Formatter
- Avoid space around pow for `None`, `True` and `False` ([#8189](https://github.com/astral-sh/ruff/pull/8189))
- Avoid sorting all paths in the format command ([#8181](https://github.com/astral-sh/ruff/pull/8181))
- Insert necessary blank line between class and leading comments ([#8224](https://github.com/astral-sh/ruff/pull/8224))
- Avoid introducing new parentheses in annotated assignments ([#8233](https://github.com/astral-sh/ruff/pull/8233))
- Refine the warnings about incompatible linter options ([#8196](https://github.com/astral-sh/ruff/pull/8196))
- Add test and basic implementation for formatter preview mode ([#8044](https://github.com/astral-sh/ruff/pull/8044))
- Refine warning about incompatible `isort` settings ([#8192](https://github.com/astral-sh/ruff/pull/8192))
- Only omit optional parentheses for starting or ending with parentheses ([#8238](https://github.com/astral-sh/ruff/pull/8238))
- Use source type to determine parser mode for formatting ([#8205](https://github.com/astral-sh/ruff/pull/8205))
- Don't warn about magic trailing comma when `isort.force-single-line` is true ([#8244](https://github.com/astral-sh/ruff/pull/8244))
- Use `SourceKind::diff` for formatter ([#8240](https://github.com/astral-sh/ruff/pull/8240))
- Fix `fmt:off` with trailing child comment ([#8234](https://github.com/astral-sh/ruff/pull/8234))
- Formatter parentheses support for `IpyEscapeCommand` ([#8207](https://github.com/astral-sh/ruff/pull/8207))
### Linter
- \[`pylint`\] Add buffer methods to `bad-dunder-method-name` (`PLW3201`) exclusions ([#8190](https://github.com/astral-sh/ruff/pull/8190))
- Match rule prefixes from `external` codes setting in `unused-noqa` ([#8177](https://github.com/astral-sh/ruff/pull/8177))
- Use `line-length` setting for isort in lieu of `pycodestyle.max-line-length` ([#8235](https://github.com/astral-sh/ruff/pull/8235))
- Update fix for `unnecessary-paren-on-raise-exception` to unsafe for unknown types ([#8231](https://github.com/astral-sh/ruff/pull/8231))
- Correct quick fix message for `W605` ([#8255](https://github.com/astral-sh/ruff/pull/8255))
### Documentation
- Fix typo in max-doc-length documentation ([#8201](https://github.com/astral-sh/ruff/pull/8201))
- Improve documentation around linter-formatter conflicts ([#8257](https://github.com/astral-sh/ruff/pull/8257))
- Fix link to error suppression documentation in `unused-noqa` ([#8172](https://github.com/astral-sh/ruff/pull/8172))
- Add `external` option to `unused-noqa` documentation ([#8171](https://github.com/astral-sh/ruff/pull/8171))
- Add title attribute to icons ([#8060](https://github.com/astral-sh/ruff/pull/8060))
- Clarify unsafe case in RSE102 ([#8256](https://github.com/astral-sh/ruff/pull/8256))
- Fix skipping formatting examples ([#8210](https://github.com/astral-sh/ruff/pull/8210))
- docs: fix name of `magic-trailing-comma` option in README ([#8200](https://github.com/astral-sh/ruff/pull/8200))
- Add note about scope of rule changing in versioning policy ([#8169](https://github.com/astral-sh/ruff/pull/8169))
- Document: Fix default lint rules ([#8218](https://github.com/astral-sh/ruff/pull/8218))
- Fix a wrong setting in configuration.md ([#8186](https://github.com/astral-sh/ruff/pull/8186))
- Fix misspelled TOML headers in the tutorial ([#8209](https://github.com/astral-sh/ruff/pull/8209))
## 0.1.2
This release includes the Beta version of the Ruff formatter — an extremely fast, Black-compatible Python formatter.
Try it today with `ruff format`! [Check out the blog post](https://astral.sh/blog/the-ruff-formatter) and [read the docs](https://docs.astral.sh/ruff/formatter/).
### Preview features
- \[`pylint`\] Implement `non-ascii-module-import` (`C2403`) ([#8056](https://github.com/astral-sh/ruff/pull/8056))
- \[`pylint`\] implement `non-ascii-name` (`C2401`) ([#8038](https://github.com/astral-sh/ruff/pull/8038))
- \[`pylint`\] Implement unnecessary-lambda (W0108) ([#7953](https://github.com/astral-sh/ruff/pull/7953))
- \[`refurb`\] Implement `read-whole-file` (`FURB101`) ([#7682](https://github.com/astral-sh/ruff/pull/7682))
- Add fix for `E223`, `E224`, and `E242` ([#8143](https://github.com/astral-sh/ruff/pull/8143))
- Add fix for `E225`, `E226`, `E227`, and `E228` ([#8136](https://github.com/astral-sh/ruff/pull/8136))
- Add fix for `E252` ([#8142](https://github.com/astral-sh/ruff/pull/8142))
- Add fix for `E261` ([#8114](https://github.com/astral-sh/ruff/pull/8114))
- Add fix for `E273` and `E274` ([#8144](https://github.com/astral-sh/ruff/pull/8144))
- Add fix for `E275` ([#8133](https://github.com/astral-sh/ruff/pull/8133))
- Update `SIM401` to catch ternary operations ([#7415](https://github.com/astral-sh/ruff/pull/7415))
- Update `E721` to allow `is` and `is` not for direct type comparisons ([#7905](https://github.com/astral-sh/ruff/pull/7905))
### Rule changes
- Add `backports.strenum` to `deprecated-imports` ([#8113](https://github.com/astral-sh/ruff/pull/8113))
- Update `SIM112` to ignore `https_proxy`, `http_proxy`, and `no_proxy` ([#8140](https://github.com/astral-sh/ruff/pull/8140))
- Update fix for `literal-membership` (`PLR6201`) to be unsafe ([#8097](https://github.com/astral-sh/ruff/pull/8097))
- Update fix for `mutable-argument-defaults` (`B006`) to be unsafe ([#8108](https://github.com/astral-sh/ruff/pull/8108))
### Formatter
- Change `line-ending` default to `auto` ([#8057](https://github.com/astral-sh/ruff/pull/8057))
- Respect parenthesized generators in `has_own_parentheses` ([#8100](https://github.com/astral-sh/ruff/pull/8100))
- Add caching to formatter ([#8089](https://github.com/astral-sh/ruff/pull/8089))
- Remove `--line-length` option from `format` command ([#8131](https://github.com/astral-sh/ruff/pull/8131))
- Add formatter to `line-length` documentation ([#8150](https://github.com/astral-sh/ruff/pull/8150))
- Warn about incompatible formatter options ([#8088](https://github.com/astral-sh/ruff/pull/8088))
- Fix range of unparenthesized tuple subject in match statement ([#8101](https://github.com/astral-sh/ruff/pull/8101))
- Remove experimental formatter warning ([#8148](https://github.com/astral-sh/ruff/pull/8148))
- Don't move type param opening parenthesis comment ([#8163](https://github.com/astral-sh/ruff/pull/8163))
- Update versions in format benchmark script ([#8110](https://github.com/astral-sh/ruff/pull/8110))
- Avoid loading files for cached format results ([#8134](https://github.com/astral-sh/ruff/pull/8134))
### CLI
- Show the `ruff format` command in help menus ([#8167](https://github.com/astral-sh/ruff/pull/8167))
- Add `ruff version` command with long version display ([#8034](https://github.com/astral-sh/ruff/pull/8034))
### Configuration
- New `pycodestyle.max-line-length` option ([#8039](https://github.com/astral-sh/ruff/pull/8039))
### Bug fixes
- Detect `sys.version_info` slices in `outdated-version-block` ([#8112](https://github.com/astral-sh/ruff/pull/8112))
- Avoid if-else simplification for `TYPE_CHECKING` blocks ([#8072](https://github.com/astral-sh/ruff/pull/8072))
- Avoid false-positive print separator diagnostic with starred argument ([#8079](https://github.com/astral-sh/ruff/pull/8079))
### Documentation
- Fix message for `too-many-arguments` lint ([#8092](https://github.com/astral-sh/ruff/pull/8092))
- Fix `extend-unsafe-fixes` and `extend-safe-fixes` example ([#8139](https://github.com/astral-sh/ruff/pull/8139))
- Add links to `flake8-import-conventions` options ([#8115](https://github.com/astral-sh/ruff/pull/8115))
- Rework the documentation to incorporate the Ruff formatter ([#7732](https://github.com/astral-sh/ruff/pull/7732))
- Fix `Options` JSON schema description ([#8081](https://github.com/astral-sh/ruff/pull/8081))
- Fix typo (`pytext` -> `pytest`) ([#8117](https://github.com/astral-sh/ruff/pull/8117))
- Improve `magic-value-comparison` example in docs ([#8111](https://github.com/astral-sh/ruff/pull/8111))
## 0.1.1
### Rule changes
- Add unsafe fix for `escape-sequence-in-docstring` (`D301`) ([#7970](https://github.com/astral-sh/ruff/pull/7970))
### Configuration
- Respect `#(deprecated)` attribute in configuration options ([#8035](https://github.com/astral-sh/ruff/pull/8035))
- Add `[format|lint].exclude` options ([#8000](https://github.com/astral-sh/ruff/pull/8000))
- Respect `tab-size` setting in formatter ([#8006](https://github.com/astral-sh/ruff/pull/8006))
- Add `lint.preview` ([#8002](https://github.com/astral-sh/ruff/pull/8002))
### Preview features
- \[`pylint`\] Implement `literal-membership` (`PLR6201`) ([#7973](https://github.com/astral-sh/ruff/pull/7973))
- \[`pylint`\] Implement `too-many-boolean-expressions` (`PLR0916`) ([#7975](https://github.com/astral-sh/ruff/pull/7975))
- \[`pylint`\] Implement `misplaced-bare-raise` (`E0704`) ([#7961](https://github.com/astral-sh/ruff/pull/7961))
- \[`pylint`\] Implement `global-at-module-level` (`W0604`) ([#8058](https://github.com/astral-sh/ruff/pull/8058))
- \[`pylint`\] Implement `unspecified-encoding` (`PLW1514`) ([#7939](https://github.com/astral-sh/ruff/pull/7939))
- Add fix for `triple-single-quotes` (`D300`) ([#7967](https://github.com/astral-sh/ruff/pull/7967))
### Formatter
- New code style badge for `ruff format` ([#7878](https://github.com/astral-sh/ruff/pull/7878))
- Fix comments outside expression parentheses ([#7873](https://github.com/astral-sh/ruff/pull/7873))
- Add `--target-version` to `ruff format` ([#8055](https://github.com/astral-sh/ruff/pull/8055))
- Skip over parentheses when detecting `in` keyword ([#8054](https://github.com/astral-sh/ruff/pull/8054))
- Add `--diff` option to `ruff format` ([#7937](https://github.com/astral-sh/ruff/pull/7937))
- Insert newline after nested function or class statements ([#7946](https://github.com/astral-sh/ruff/pull/7946))
- Use `pass` over ellipsis in non-function/class contexts ([#8049](https://github.com/astral-sh/ruff/pull/8049))
### Bug fixes
- Lazily evaluate all PEP 695 type alias values ([#8033](https://github.com/astral-sh/ruff/pull/8033))
- Avoid failed assertion when showing fixes from stdin ([#8029](https://github.com/astral-sh/ruff/pull/8029))
- Avoid flagging HTTP and HTTPS literals in urllib-open ([#8046](https://github.com/astral-sh/ruff/pull/8046))
- Avoid flagging `bad-dunder-method-name` for `_` ([#8015](https://github.com/astral-sh/ruff/pull/8015))
- Remove Python 2-only methods from `URLOpen` audit ([#8047](https://github.com/astral-sh/ruff/pull/8047))
- Use set bracket replacement for `iteration-over-set` to preserve whitespace and comments ([#8001](https://github.com/astral-sh/ruff/pull/8001))
### Documentation
- Update tutorial to match revised Ruff defaults ([#8066](https://github.com/astral-sh/ruff/pull/8066))
- Update rule `B005` docs ([#8028](https://github.com/astral-sh/ruff/pull/8028))
- Update GitHub actions example in docs to use `--output-format` ([#8014](https://github.com/astral-sh/ruff/pull/8014))
- Document `lint.preview` and `format.preview` ([#8032](https://github.com/astral-sh/ruff/pull/8032))
- Clarify that new rules should be added to `RuleGroup::Preview`. ([#7989](https://github.com/astral-sh/ruff/pull/7989))
## 0.1.0
This is the first release which uses the `CHANGELOG` file. See [GitHub Releases](https://github.com/astral-sh/ruff/releases) for prior changelog entries.
Read Ruff's new [versioning policy](https://docs.astral.sh/ruff/versioning/).
### Breaking changes
- Unsafe fixes are no longer displayed or applied without opt-in ([#7769](https://github.com/astral-sh/ruff/pull/7769))
- Drop formatting specific rules from the default set ([#7900](https://github.com/astral-sh/ruff/pull/7900))
- The deprecated `format` setting has been removed ([#7984](https://github.com/astral-sh/ruff/pull/7984))
- The `format` setting cannot be used to configure the output format, use `output-format` instead
- The `RUFF_FORMAT` environment variable is ignored, use `RUFF_OUTPUT_FORMAT` instead
- The `--format` option has been removed from `ruff check`, use `--output-format` instead
### Rule changes
- Extend `reimplemented-starmap` (`FURB140`) to catch calls with a single and starred argument ([#7768](https://github.com/astral-sh/ruff/pull/7768))
- Improve cases covered by `RUF015` ([#7848](https://github.com/astral-sh/ruff/pull/7848))
- Update `SIM15` to allow `open` followed by `close` ([#7916](https://github.com/astral-sh/ruff/pull/7916))
- Respect `msgspec.Struct` default-copy semantics in `RUF012` ([#7786](https://github.com/astral-sh/ruff/pull/7786))
- Add `sqlalchemy` methods to \`flake8-boolean-trap\`\` exclusion list ([#7874](https://github.com/astral-sh/ruff/pull/7874))
- Add fix for `PLR1714` ([#7910](https://github.com/astral-sh/ruff/pull/7910))
- Add fix for `PIE804` ([#7884](https://github.com/astral-sh/ruff/pull/7884))
- Add fix for `PLC0208` ([#7887](https://github.com/astral-sh/ruff/pull/7887))
- Add fix for `PYI055` ([#7886](https://github.com/astral-sh/ruff/pull/7886))
- Update `non-pep695-type-alias` to require `--unsafe-fixes` outside of stub files ([#7836](https://github.com/astral-sh/ruff/pull/7836))
- Improve fix message for `UP018` ([#7913](https://github.com/astral-sh/ruff/pull/7913))
- Update `PLW3201` to support `Enum` [sunder names](https://docs.python.org/3/library/enum.html#supported-sunder-names) ([#7987](https://github.com/astral-sh/ruff/pull/7987))
### Preview features
- Only show warnings for empty preview selectors when enabling rules ([#7842](https://github.com/astral-sh/ruff/pull/7842))
- Add `unnecessary-key-check` to simplify `key in dct and dct[key]` to `dct.get(key)` ([#7895](https://github.com/astral-sh/ruff/pull/7895))
- Add `assignment-in-assert` to prevent walrus expressions in assert statements ([#7856](https://github.com/astral-sh/ruff/pull/7856))
- \[`refurb`\] Add `single-item-membership-test` (`FURB171`) ([#7815](https://github.com/astral-sh/ruff/pull/7815))
- \[`pylint`\] Add `and-or-ternary` (`R1706`) ([#7811](https://github.com/astral-sh/ruff/pull/7811))
_New rules are added in [preview](https://docs.astral.sh/ruff/preview/)._
### Configuration
- Add `unsafe-fixes` setting ([#7769](https://github.com/astral-sh/ruff/pull/7769))
- Add `extend-safe-fixes` and `extend-unsafe-fixes` for promoting and demoting fixes ([#7841](https://github.com/astral-sh/ruff/pull/7841))
### CLI
- Added `--unsafe-fixes` option for opt-in to display and apply unsafe fixes ([#7769](https://github.com/astral-sh/ruff/pull/7769))
- Fix use of deprecated `--format` option in warning ([#7837](https://github.com/astral-sh/ruff/pull/7837))
- Show changed files when running under `--check` ([#7788](https://github.com/astral-sh/ruff/pull/7788))
- Write summary messages to stderr when fixing via stdin instead of omitting them ([#7838](https://github.com/astral-sh/ruff/pull/7838))
- Update fix summary message in `check --diff` to include unsafe fix hints ([#7790](https://github.com/astral-sh/ruff/pull/7790))
- Add notebook `cell` field to JSON output format ([#7664](https://github.com/astral-sh/ruff/pull/7664))
- Rename applicability levels to `Safe`, `Unsafe`, and `Display` ([#7843](https://github.com/astral-sh/ruff/pull/7843))
### Bug fixes
- Fix bug where f-strings were allowed in match pattern literal ([#7857](https://github.com/astral-sh/ruff/pull/7857))
- Fix `SIM110` with a yield in the condition ([#7801](https://github.com/astral-sh/ruff/pull/7801))
- Preserve trailing comments in `C414` fixes ([#7775](https://github.com/astral-sh/ruff/pull/7775))
- Check sequence type before triggering `unnecessary-enumerate` `len` suggestion ([#7781](https://github.com/astral-sh/ruff/pull/7781))
- Use correct start location for class/function clause header ([#7802](https://github.com/astral-sh/ruff/pull/7802))
- Fix incorrect fixes for `SIM101` ([#7798](https://github.com/astral-sh/ruff/pull/7798))
- Format comment before parameter default correctly ([#7870](https://github.com/astral-sh/ruff/pull/7870))
- Fix `E251` false positive inside f-strings ([#7894](https://github.com/astral-sh/ruff/pull/7894))
- Allow bindings to be created and referenced within annotations ([#7885](https://github.com/astral-sh/ruff/pull/7885))
- Show per-cell diffs when analyzing notebooks over `stdin` ([#7789](https://github.com/astral-sh/ruff/pull/7789))
- Avoid curly brace escape in f-string format spec ([#7780](https://github.com/astral-sh/ruff/pull/7780))
- Fix lexing single-quoted f-string with multi-line format spec ([#7787](https://github.com/astral-sh/ruff/pull/7787))
- Consider nursery rules to be in-preview for `ruff rule` ([#7812](https://github.com/astral-sh/ruff/pull/7812))
- Report precise location for invalid conversion flag ([#7809](https://github.com/astral-sh/ruff/pull/7809))
- Visit pattern match guard as a boolean test ([#7911](https://github.com/astral-sh/ruff/pull/7911))
- Respect `--unfixable` in `ISC` rules ([#7917](https://github.com/astral-sh/ruff/pull/7917))
- Fix edge case with `PIE804` ([#7922](https://github.com/astral-sh/ruff/pull/7922))
- Show custom message in `PTH118` for `Path.joinpath` with starred arguments ([#7852](https://github.com/astral-sh/ruff/pull/7852))
- Fix false negative in `outdated-version-block` when using greater than comparisons ([#7920](https://github.com/astral-sh/ruff/pull/7920))
- Avoid converting f-strings within Django `gettext` calls ([#7898](https://github.com/astral-sh/ruff/pull/7898))
- Fix false positive in `PLR6301` ([#7933](https://github.com/astral-sh/ruff/pull/7933))
- Treat type aliases as typing-only expressions e.g. resolves false positive in `TCH004` ([#7968](https://github.com/astral-sh/ruff/pull/7968))
- Resolve `cache-dir` relative to project root ([#7962](https://github.com/astral-sh/ruff/pull/7962))
- Respect subscripted base classes in type-checking rules e.g. resolves false positive in `TCH003` ([#7954](https://github.com/astral-sh/ruff/pull/7954))
- Fix JSON schema limit for `line-length` ([#7883](https://github.com/astral-sh/ruff/pull/7883))
- Fix commented-out `coalesce` keyword ([#7876](https://github.com/astral-sh/ruff/pull/7876))
### Documentation
- Document `reimplemented-starmap` performance effects ([#7846](https://github.com/astral-sh/ruff/pull/7846))
- Default to following the system dark/light mode ([#7888](https://github.com/astral-sh/ruff/pull/7888))
- Add documentation for fixes ([#7901](https://github.com/astral-sh/ruff/pull/7901))
- Fix typo in docs of `PLR6301` ([#7831](https://github.com/astral-sh/ruff/pull/7831))
- Update `UP038` docs to note that it results in slower code ([#7872](https://github.com/astral-sh/ruff/pull/7872))
- crlf -> cr-lf ([#7766](https://github.com/astral-sh/ruff/pull/7766))
- Add an example of an unsafe fix ([#7924](https://github.com/astral-sh/ruff/pull/7924))
- Fix documented examples for `unnecessary-subscript-reversal` ([#7774](https://github.com/astral-sh/ruff/pull/7774))
- Correct error in tuple example in ruff formatter docs ([#7822](https://github.com/astral-sh/ruff/pull/7822))
- Add versioning policy to documentation ([#7923](https://github.com/astral-sh/ruff/pull/7923))
- Fix invalid code in `FURB177` example ([#7832](https://github.com/astral-sh/ruff/pull/7832))
### Formatter
- Less scary `ruff format` message ([#7867](https://github.com/astral-sh/ruff/pull/7867))
- Remove spaces from import statements ([#7859](https://github.com/astral-sh/ruff/pull/7859))
- Formatter quoting for f-strings with triple quotes ([#7826](https://github.com/astral-sh/ruff/pull/7826))
- Update `ruff_python_formatter` generate.py comment ([#7850](https://github.com/astral-sh/ruff/pull/7850))
- Document one-call chaining deviation ([#7767](https://github.com/astral-sh/ruff/pull/7767))
- Allow f-string modifications in line-shrinking cases ([#7818](https://github.com/astral-sh/ruff/pull/7818))
- Add trailing comment deviation to README ([#7827](https://github.com/astral-sh/ruff/pull/7827))
- Add trailing zero between dot and exponential ([#7956](https://github.com/astral-sh/ruff/pull/7956))
- Force parentheses for power operations in unary expressions ([#7955](https://github.com/astral-sh/ruff/pull/7955))
### Playground
- Fix playground `Quick Fix` action ([#7824](https://github.com/astral-sh/ruff/pull/7824))

View File

@@ -72,7 +72,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at reported to the community leaders responsible for enforcement at
<charlie.r.marsh@gmail.com>. charlie.r.marsh@gmail.com.
All complaints will be reviewed and investigated promptly and fairly. All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the All community leaders are obligated to respect the privacy and security of the

View File

@@ -112,11 +112,11 @@ Ruff is structured as a monorepo with a [flat crate structure](https://matklad.g
such that all crates are contained in a flat `crates` directory. 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 The vast majority of the code, including all lint rules, lives in the `ruff` crate (located at
`crates/ruff_linter`). As a contributor, that's the crate that'll be most relevant to you. `crates/ruff`). As a contributor, that's the crate that'll be most relevant to you.
At the time of writing, the repository includes the following crates: At time of writing, the repository includes the following crates:
- `crates/ruff_linter`: library crate containing all lint rules and the core logic for running them. - `crates/ruff`: library crate containing all lint rules and the core logic for running them.
If you're working on a rule, this is the crate for you. If you're working on a rule, this is the crate for you.
- `crates/ruff_benchmark`: binary crate for running micro-benchmarks. - `crates/ruff_benchmark`: binary crate for running micro-benchmarks.
- `crates/ruff_cache`: library crate for caching lint results. - `crates/ruff_cache`: library crate for caching lint results.
@@ -153,7 +153,7 @@ At a high level, the steps involved in adding a new lint rule are as follows:
1. Determine a name for the new rule as per our [rule naming convention](#rule-naming-convention) 1. Determine a name for the new rule as per our [rule naming convention](#rule-naming-convention)
(e.g., `AssertFalse`, as in, "allow `assert False`"). (e.g., `AssertFalse`, as in, "allow `assert False`").
1. Create a file for your rule (e.g., `crates/ruff_linter/src/rules/flake8_bugbear/rules/assert_false.rs`). 1. Create a file for your rule (e.g., `crates/ruff/src/rules/flake8_bugbear/rules/assert_false.rs`).
1. In that file, define a violation struct (e.g., `pub struct AssertFalse`). You can grep for 1. In that file, define a violation struct (e.g., `pub struct AssertFalse`). You can grep for
`#[violation]` to see examples. `#[violation]` to see examples.
@@ -162,22 +162,21 @@ At a high level, the steps involved in adding a new lint rule are as follows:
(e.g., `pub(crate) fn assert_false`) based on whatever inputs are required for the rule (e.g., (e.g., `pub(crate) fn assert_false`) based on whatever inputs are required for the rule (e.g.,
an `ast::StmtAssert` node). an `ast::StmtAssert` node).
1. Define the logic for invoking the diagnostic in `crates/ruff_linter/src/checkers/ast/analyze` (for 1. Define the logic for invoking the diagnostic in `crates/ruff/src/checkers/ast/analyze` (for
AST-based rules), `crates/ruff_linter/src/checkers/tokens.rs` (for token-based rules), AST-based rules), `crates/ruff/src/checkers/tokens.rs` (for token-based rules),
`crates/ruff_linter/src/checkers/physical_lines.rs` (for text-based rules), `crates/ruff/src/checkers/physical_lines.rs` (for text-based rules),
`crates/ruff_linter/src/checkers/filesystem.rs` (for filesystem-based rules), etc. For AST-based rules, `crates/ruff/src/checkers/filesystem.rs` (for filesystem-based rules), etc. For AST-based rules,
you'll likely want to modify `analyze/statement.rs` (if your rule is based on analyzing you'll likely want to modify `analyze/statement.rs` (if your rule is based on analyzing
statements, like imports) or `analyze/expression.rs` (if your rule is based on analyzing statements, like imports) or `analyze/expression.rs` (if your rule is based on analyzing
expressions, like function calls). expressions, like function calls).
1. Map the violation struct to a rule code in `crates/ruff_linter/src/codes.rs` (e.g., `B011`). New rules 1. Map the violation struct to a rule code in `crates/ruff/src/codes.rs` (e.g., `B011`).
should be added in `RuleGroup::Preview`.
1. Add proper [testing](#rule-testing-fixtures-and-snapshots) for your rule. 1. Add proper [testing](#rule-testing-fixtures-and-snapshots) for your rule.
1. Update the generated files (documentation and generated code). 1. Update the generated files (documentation and generated code).
To trigger the violation, you'll likely want to augment the logic in `crates/ruff_linter/src/checkers/ast.rs` To trigger the violation, you'll likely want to augment the logic in `crates/ruff/src/checkers/ast.rs`
to call your new function at the appropriate time and with the appropriate inputs. The `Checker` to call your new function at the appropriate time and with the appropriate inputs. The `Checker`
defined therein is a Python AST visitor, which iterates over the AST, building up a semantic model, defined therein is a Python AST visitor, which iterates over the AST, building up a semantic model,
and calling out to lint rule analyzer functions as it goes. and calling out to lint rule analyzer functions as it goes.
@@ -205,7 +204,7 @@ As such, rule names should...
For example, `AssertFalse` guards against `assert False` statements. For example, `AssertFalse` guards against `assert False` statements.
- _Not_ contain instructions on how to fix the violation, which instead belong in the rule - _Not_ contain instructions on how to fix the violation, which instead belong in the rule
documentation and the `fix_title`. documentation and the `autofix_title`.
- _Not_ contain a redundant prefix, like `Disallow` or `Banned`, which are already implied by the - _Not_ contain a redundant prefix, like `Disallow` or `Banned`, which are already implied by the
convention. convention.
@@ -222,7 +221,7 @@ Ruff's output for each fixture, which you can then commit alongside your changes
Once you've completed the code for the rule itself, you can define tests with the following steps: Once you've completed the code for the rule itself, you can define tests with the following steps:
1. Add a Python file to `crates/ruff_linter/resources/test/fixtures/[linter]` that contains the code you 1. Add a Python file to `crates/ruff/resources/test/fixtures/[linter]` that contains the code you
want to test. The file name should match the rule name (e.g., `E402.py`), and it should include want to test. The file name should match the rule name (e.g., `E402.py`), and it should include
examples of both violations and non-violations. examples of both violations and non-violations.
@@ -231,16 +230,16 @@ Once you've completed the code for the rule itself, you can define tests with th
For example, if you're adding a new rule named `E402`, you would run: For example, if you're adding a new rule named `E402`, you would run:
```shell ```shell
cargo run -p ruff_cli -- check crates/ruff_linter/resources/test/fixtures/pycodestyle/E402.py --no-cache --select E402 cargo run -p ruff_cli -- check crates/ruff/resources/test/fixtures/pycodestyle/E402.py --no-cache --select E402
``` ```
**Note:** Only a subset of rules are enabled by default. When testing a new rule, ensure that **Note:** Only a subset of rules are enabled by default. When testing a new rule, ensure that
you activate it by adding `--select ${rule_code}` to the command. you activate it by adding `--select ${rule_code}` to the command.
1. Add the test to the relevant `crates/ruff_linter/src/rules/[linter]/mod.rs` file. If you're contributing 1. Add the test to the relevant `crates/ruff/src/rules/[linter]/mod.rs` file. If you're contributing
a rule to a pre-existing set, you should be able to find a similar example to pattern-match a rule to a pre-existing set, you should be able to find a similar example to pattern-match
against. If you're adding a new linter, you'll need to create a new `mod.rs` file (see, against. If you're adding a new linter, you'll need to create a new `mod.rs` file (see,
e.g., `crates/ruff_linter/src/rules/flake8_bugbear/mod.rs`) e.g., `crates/ruff/src/rules/flake8_bugbear/mod.rs`)
1. Run `cargo test`. Your test will fail, but you'll be prompted to follow-up 1. Run `cargo test`. Your test will fail, but you'll be prompted to follow-up
with `cargo insta review`. Run `cargo insta review`, review and accept the generated snapshot, with `cargo insta review`. Run `cargo insta review`, review and accept the generated snapshot,
@@ -252,24 +251,25 @@ Once you've completed the code for the rule itself, you can define tests with th
Ruff's user-facing settings live in a few different places. Ruff's user-facing settings live in a few different places.
First, the command-line options are defined via the `Args` struct in `crates/ruff_cli/src/args.rs`. First, the command-line options are defined via the `Cli` struct in `crates/ruff/src/cli.rs`.
Second, the `pyproject.toml` options are defined in `crates/ruff_workspace/src/options.rs` (via the Second, the `pyproject.toml` options are defined in `crates/ruff/src/settings/options.rs` (via the
`Options` struct), `crates/ruff_workspace/src/configuration.rs` (via the `Configuration` struct), `Options` struct), `crates/ruff/src/settings/configuration.rs` (via the `Configuration` struct), and
and `crates/ruff_workspace/src/settings.rs` (via the `Settings` struct), which then includes `crates/ruff/src/settings/mod.rs` (via the `Settings` struct). These represent, respectively: the
the `LinterSettings` struct as a field. schema used to parse the `pyproject.toml` file; an internal, intermediate representation; and the
final, internal representation used to power Ruff.
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 To add a new configuration option, you'll likely want to modify these latter few files (along with
`arg.rs`, if appropriate). If you want to pattern-match against an existing example, grep for `cli.rs`, if appropriate). If you want to pattern-match against an existing example, grep for
`dummy_variable_rgx`, which defines a regular expression to match against acceptable unused `dummy_variable_rgx`, which defines a regular expression to match against acceptable unused
variables (e.g., `_`). variables (e.g., `_`).
Note that plugin-specific configuration options are defined in their own modules (e.g., Note that plugin-specific configuration options are defined in their own modules (e.g.,
`Settings` in `crates/ruff_linter/src/flake8_unused_arguments/settings.rs` coupled with `crates/ruff/src/flake8_unused_arguments/settings.rs`).
`Flake8UnusedArgumentsOptions` in `crates/ruff_workspace/src/options.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`.
Finally, regenerate the documentation and generated code with `cargo dev generate-all`. Finally, regenerate the documentation and generated code with `cargo dev generate-all`.
@@ -315,18 +315,9 @@ even patch releases may contain [non-backwards-compatible changes](https://semve
### Creating a new release ### Creating a new release
We use an experimental in-house tool for managing releases. 1. Update the version with `rg 0.0.269 --files-with-matches | xargs sed -i 's/0.0.269/0.0.270/g'`
1. Update `BREAKING_CHANGES.md`
1. Install `rooster`: `pip install git+https://github.com/zanieb/rooster@main` 1. Create a PR with the version and `BREAKING_CHANGES.md` updated
1. Run `rooster release`; this command will:
- Generate a changelog entry in `CHANGELOG.md`
- Update versions in `pyproject.toml` and `Cargo.toml`
- Update references to versions in the `README.md` and documentation
1. The changelog should then be editorialized for consistency
- Often labels will be missing from pull requests they will need to be manually organized into the proper section
- Changes should be edited to be user-facing descriptions, avoiding internal details
1. Highlight any breaking changes in `BREAKING_CHANGES.md`
1. Create a pull request with the changelog and version updates
1. Merge the PR 1. Merge the PR
1. Run the release workflow with the version number (without starting `v`) as input. Make sure 1. Run the release workflow with the version number (without starting `v`) as input. Make sure
main has your merged PR as last commit main has your merged PR as last commit
@@ -339,26 +330,23 @@ We use an experimental in-house tool for managing releases.
1. Attach artifacts to draft GitHub release 1. Attach artifacts to draft GitHub release
1. Trigger downstream repositories. This can fail non-catastrophically, as we can run any 1. Trigger downstream repositories. This can fail non-catastrophically, as we can run any
downstream jobs manually if needed. downstream jobs manually if needed.
1. Publish the GitHub release 1. Create release notes in GitHub UI and promote from draft.
1. Open the draft release in the GitHub release section
1. Copy the changelog for the release into the GitHub release
- See previous releases for formatting of section headers
1. Generate the contributor list with `rooster contributors` and add to the release notes
1. If needed, [update the schemastore](https://github.com/charliermarsh/ruff/blob/main/scripts/update_schemastore.py) 1. If needed, [update the schemastore](https://github.com/charliermarsh/ruff/blob/main/scripts/update_schemastore.py)
1. If needed, update the `ruff-lsp` and `ruff-vscode` repositories. 1. If needed, update the `ruff-lsp` and `ruff-vscode` repositories.
## Ecosystem CI ## Ecosystem CI
GitHub Actions will run your changes against a number of real-world projects from GitHub and GitHub Actions will run your changes against a number of real-world projects from GitHub and
report on any linter or formatter differences. You can also run those checks locally via: report on any diagnostic differences. You can also run those checks locally via:
```shell ```shell
pip install -e ./python/ruff-ecosystem python scripts/check_ecosystem.py path/to/your/ruff path/to/older/ruff
ruff-ecosystem check ruff "./target/debug/ruff"
ruff-ecosystem format ruff "./target/debug/ruff"
``` ```
See the [ruff-ecosystem package](https://github.com/astral-sh/ruff/tree/main/python/ruff-ecosystem) for more details. You can also run the Ecosystem CI check in a Docker container across a larger set of projects by
downloading the [`known-github-tomls.json`](https://github.com/akx/ruff-usage-aggregate/blob/master/data/known-github-tomls.jsonl)
as `github_search.jsonl` and following the instructions in [scripts/Dockerfile.ecosystem](https://github.com/astral-sh/ruff/blob/main/scripts/Dockerfile.ecosystem).
Note that this check will take a while to run.
## Benchmarking and Profiling ## Benchmarking and Profiling
@@ -374,46 +362,46 @@ First, clone [CPython](https://github.com/python/cpython). It's a large and dive
which makes it a good target for benchmarking. which makes it a good target for benchmarking.
```shell ```shell
git clone --branch 3.10 https://github.com/python/cpython.git crates/ruff_linter/resources/test/cpython git clone --branch 3.10 https://github.com/python/cpython.git crates/ruff/resources/test/cpython
``` ```
To benchmark the release build: To benchmark the release build:
```shell ```shell
cargo build --release && hyperfine --warmup 10 \ cargo build --release && hyperfine --warmup 10 \
"./target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache -e" \ "./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache -e" \
"./target/release/ruff ./crates/ruff_linter/resources/test/cpython/ -e" "./target/release/ruff ./crates/ruff/resources/test/cpython/ -e"
Benchmark 1: ./target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache 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] 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 Range (min … max): 289.9 ms … 301.6 ms 10 runs
Benchmark 2: ./target/release/ruff ./crates/ruff_linter/resources/test/cpython/ 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] 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 Range (min … max): 45.0 ms … 66.7 ms 62 runs
Summary Summary
'./target/release/ruff ./crates/ruff_linter/resources/test/cpython/' ran './target/release/ruff ./crates/ruff/resources/test/cpython/' ran
6.12 ± 0.41 times faster than './target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache' 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: To benchmark against the ecosystem's existing tools:
```shell ```shell
hyperfine --ignore-failure --warmup 5 \ hyperfine --ignore-failure --warmup 5 \
"./target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache" \ "./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache" \
"pyflakes crates/ruff_linter/resources/test/cpython" \ "pyflakes crates/ruff/resources/test/cpython" \
"autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython" \ "autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython" \
"pycodestyle crates/ruff_linter/resources/test/cpython" \ "pycodestyle crates/ruff/resources/test/cpython" \
"flake8 crates/ruff_linter/resources/test/cpython" "flake8 crates/ruff/resources/test/cpython"
Benchmark 1: ./target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache 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] 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 Range (min … max): 291.1 ms … 302.8 ms 10 runs
Warning: Ignoring non-zero exit code. Warning: Ignoring non-zero exit code.
Benchmark 2: pyflakes crates/ruff_linter/resources/test/cpython Benchmark 2: pyflakes crates/ruff/resources/test/cpython
Time (mean ± σ): 15.786 s ± 0.143 s [User: 15.560 s, System: 0.214 s] 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 Range (min … max): 15.640 s … 16.157 s 10 runs
@@ -423,31 +411,31 @@ Benchmark 3: autoflake --recursive --expand-star-imports --remove-all-unused-imp
Time (mean ± σ): 6.175 s ± 0.169 s [User: 54.102 s, System: 1.057 s] 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 Range (min … max): 5.950 s … 6.391 s 10 runs
Benchmark 4: pycodestyle crates/ruff_linter/resources/test/cpython Benchmark 4: pycodestyle crates/ruff/resources/test/cpython
Time (mean ± σ): 46.921 s ± 0.508 s [User: 46.699 s, System: 0.202 s] 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 Range (min … max): 46.171 s … 47.863 s 10 runs
Warning: Ignoring non-zero exit code. Warning: Ignoring non-zero exit code.
Benchmark 5: flake8 crates/ruff_linter/resources/test/cpython Benchmark 5: flake8 crates/ruff/resources/test/cpython
Time (mean ± σ): 12.260 s ± 0.321 s [User: 102.934 s, System: 1.230 s] 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 Range (min … max): 11.848 s … 12.933 s 10 runs
Warning: Ignoring non-zero exit code. Warning: Ignoring non-zero exit code.
Summary Summary
'./target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache' ran './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' 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_linter/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_linter/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_linter/resources/test/cpython' 159.43 ± 2.48 times faster than 'pycodestyle crates/ruff/resources/test/cpython'
``` ```
To benchmark a subset of rules, e.g. `LineTooLong` and `DocLineTooLong`: To benchmark a subset of rules, e.g. `LineTooLong` and `DocLineTooLong`:
```shell ```shell
cargo build --release && hyperfine --warmup 10 \ cargo build --release && hyperfine --warmup 10 \
"./target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache -e --select W505,E501" "./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache -e --select W505,E501"
``` ```
You can run `poetry install` from `./scripts/benchmarks` to create a working environment for the You can run `poetry install` from `./scripts/benchmarks` to create a working environment for the
@@ -480,10 +468,10 @@ rm Lib/test/bad_coding.py \
Lib/test/test_typing.py Lib/test/test_typing.py
``` ```
Then, from `crates/ruff_linter/resources/test/cpython`, run: `time pylint -j 0 -E $(git ls-files '*.py')`. This 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. will execute Pylint with maximum parallelism and only report errors.
To benchmark Pyupgrade, run the following from `crates/ruff_linter/resources/test/cpython`: To benchmark Pyupgrade, run the following from `crates/ruff/resources/test/cpython`:
```shell ```shell
hyperfine --ignore-failure --warmup 5 --prepare "git reset --hard HEAD" \ hyperfine --ignore-failure --warmup 5 --prepare "git reset --hard HEAD" \
@@ -731,8 +719,8 @@ Module {
- `cargo dev generate-cli-help`, `cargo dev generate-docs` and `cargo dev generate-json-schema`: - `cargo dev generate-cli-help`, `cargo dev generate-docs` and `cargo dev generate-json-schema`:
Update just `docs/configuration.md`, `docs/rules` and `ruff.schema.json` respectively. Update just `docs/configuration.md`, `docs/rules` and `ruff.schema.json` respectively.
- `cargo dev generate-options`: Generate a markdown-compatible table of all `pyproject.toml` - `cargo dev generate-options`: Generate a markdown-compatible table of all `pyproject.toml`
options. Used for <https://docs.astral.sh/ruff/settings/>. options. Used for <https://beta.ruff.rs/docs/settings/>
- `cargo dev generate-rules-table`: Generate a markdown-compatible table of all rules. Used for <https://docs.astral.sh/ruff/rules/>. - `cargo dev generate-rules-table`: Generate a markdown-compatible table of all rules. Used for <https://beta.ruff.rs/docs/rules/>
- `cargo dev round-trip <python file or jupyter notebook>`: Read a Python file or Jupyter Notebook, - `cargo dev round-trip <python file or jupyter notebook>`: Read a Python file or Jupyter Notebook,
parse it, serialize the parsed representation and write it back. Used to check how good our parse it, serialize the parsed representation and write it back. Used to check how good our
representation is so that fixes don't rewrite irrelevant parts of a file. representation is so that fixes don't rewrite irrelevant parts of a file.
@@ -790,7 +778,7 @@ To understand Ruff's import categorization system, we first need to define two c
- "Package root": The top-most directory defining the Python package that includes a given Python - "Package root": The top-most directory defining the Python package that includes a given Python
file. To find the package root for a given Python file, traverse up its parent directories until file. To find the package root for a given Python file, traverse up its parent directories until
you reach a parent directory that doesn't contain an `__init__.py` file (and isn't marked as you reach a parent directory that doesn't contain an `__init__.py` file (and isn't marked as
a [namespace package](https://docs.astral.sh/ruff/settings/#namespace-packages)); take the directory a [namespace package](https://beta.ruff.rs/docs/settings/#namespace-packages)); take the directory
just before that, i.e., the first directory in the package. just before that, i.e., the first directory in the package.
For example, given: For example, given:
@@ -879,7 +867,7 @@ There are three ways in which an import can be categorized as "first-party":
package (e.g., `from foo import bar` or `import foo.bar`), they'll be classified as first-party package (e.g., `from foo import bar` or `import foo.bar`), they'll be classified as first-party
automatically. This check is as simple as comparing the first segment of the current file's automatically. This check is as simple as comparing the first segment of the current file's
module path to the first segment of the import. module path to the first segment of the import.
1. **Source roots**: Ruff supports a `[src](https://docs.astral.sh/ruff/settings/#src)` setting, which 1. **Source roots**: Ruff supports a `[src](https://beta.ruff.rs/docs/settings/#src)` setting, which
sets the directories to scan when identifying first-party imports. The algorithm is sets the directories to scan when identifying first-party imports. The algorithm is
straightforward: given an import, like `import foo`, iterate over the directories enumerated in straightforward: given an import, like `import foo`, iterate over the directories enumerated in
the `src` setting and, for each directory, check for the existence of a subdirectory `foo` or a the `src` setting and, for each directory, check for the existence of a subdirectory `foo` or a
@@ -889,5 +877,5 @@ By default, `src` is set to the project root. In the above example, we'd want to
`src = ["./src"]` to ensure that we locate `./my_project/src/foo` and thus categorize `import foo` `src = ["./src"]` to ensure that we locate `./my_project/src/foo` and thus categorize `import foo`
as first-party in `baz.py`. In practice, for this limited example, setting `src = ["./src"]` is as first-party in `baz.py`. In practice, for this limited example, setting `src = ["./src"]` is
unnecessary, as all imports within `./my_project/src/foo` would be categorized as first-party via unnecessary, as all imports within `./my_project/src/foo` would be categorized as first-party via
the same-package heuristic; but if your project contains multiple packages, you'll want to set `src` the same-package heuristic; but your project contains multiple packages, you'll want to set `src`
explicitly. explicitly.

812
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -5,56 +5,59 @@ resolver = "2"
[workspace.package] [workspace.package]
edition = "2021" edition = "2021"
rust-version = "1.71" rust-version = "1.71"
homepage = "https://docs.astral.sh/ruff" homepage = "https://beta.ruff.rs/docs"
documentation = "https://docs.astral.sh/ruff" documentation = "https://beta.ruff.rs/docs"
repository = "https://github.com/astral-sh/ruff" repository = "https://github.com/astral-sh/ruff"
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"] authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
license = "MIT" license = "MIT"
[workspace.dependencies] [workspace.dependencies]
anyhow = { version = "1.0.69" } anyhow = { version = "1.0.69" }
bitflags = { version = "2.4.1" } bitflags = { version = "2.3.1" }
chrono = { version = "0.4.31", default-features = false, features = ["clock"] } chrono = { version = "0.4.30", default-features = false, features = ["clock"] }
clap = { version = "4.4.7", features = ["derive"] } clap = { version = "4.4.3", features = ["derive"] }
colored = { version = "2.0.0" } colored = { version = "2.0.0" }
filetime = { version = "0.2.20" } filetime = { version = "0.2.20" }
glob = { version = "0.3.1" } glob = { version = "0.3.1" }
globset = { version = "0.4.10" } globset = { version = "0.4.10" }
ignore = { version = "0.4.20" } ignore = { version = "0.4.20" }
insta = { version = "1.34.0", feature = ["filters", "glob"] } insta = { version = "1.31.0", feature = ["filters", "glob"] }
is-macro = { version = "0.3.0" } is-macro = { version = "0.3.0" }
itertools = { version = "0.11.0" } itertools = { version = "0.10.5" }
libcst = { version = "1.1.0", default-features = false }
log = { version = "0.4.17" } log = { version = "0.4.17" }
memchr = { version = "2.6.4" } memchr = "2.6.3"
num-bigint = { version = "0.4.3" }
num-traits = { version = "0.2.15" }
once_cell = { version = "1.17.1" } once_cell = { version = "1.17.1" }
path-absolutize = { version = "3.1.1" } path-absolutize = { version = "3.1.1" }
proc-macro2 = { version = "1.0.69" } proc-macro2 = { version = "1.0.67" }
quote = { version = "1.0.23" } quote = { version = "1.0.23" }
regex = { version = "1.10.2" } regex = { version = "1.9.5" }
rustc-hash = { version = "1.1.0" } rustc-hash = { version = "1.1.0" }
schemars = { version = "0.8.15" } schemars = { version = "0.8.12" }
serde = { version = "1.0.190", features = ["derive"] } serde = { version = "1.0.152", features = ["derive"] }
serde_json = { version = "1.0.108" } serde_json = { version = "1.0.106" }
shellexpand = { version = "3.0.0" } shellexpand = { version = "3.0.0" }
similar = { version = "2.3.0", features = ["inline"] } similar = { version = "2.2.1", features = ["inline"] }
smallvec = { version = "1.11.1" } smallvec = { version = "1.10.0" }
static_assertions = "1.1.0" static_assertions = "1.1.0"
strum = { version = "0.25.0", features = ["strum_macros"] } strum = { version = "0.25.0", features = ["strum_macros"] }
strum_macros = { version = "0.25.3" } strum_macros = { version = "0.25.2" }
syn = { version = "2.0.39" } syn = { version = "2.0.33" }
test-case = { version = "3.2.1" } test-case = { version = "3.0.0" }
thiserror = { version = "1.0.50" } thiserror = { version = "1.0.48" }
toml = { version = "0.7.8" } toml = { version = "0.7.8" }
tracing = { version = "0.1.40" } tracing = "0.1.37"
tracing-indicatif = { version = "0.3.4" } tracing-indicatif = "0.3.4"
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
unicode-ident = { version = "1.0.12" } unicode-ident = "1.0.11"
unicode_names2 = { version = "1.2.0" } unicode-width = "0.1.10"
unicode-width = { version = "0.1.11" } uuid = { version = "1.4.1", features = ["v4", "fast-rng", "macro-diagnostics", "js"] }
uuid = { version = "1.5.0", features = ["v4", "fast-rng", "macro-diagnostics", "js"] }
wsl = { version = "0.1.0" } wsl = { version = "0.1.0" }
# v1.0.1
libcst = { version = "0.1.0", default-features = false }
[profile.release] [profile.release]
lto = "fat" lto = "fat"
codegen-units = 1 codegen-units = 1

47
LICENSE
View File

@@ -1194,27 +1194,7 @@ are:
- flake8-self, licensed as follows: - flake8-self, licensed as follows:
""" """
MIT License Freely Distributable
Copyright (c) 2023 Korijn van Golen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
""" """
- flake8-django, licensed under the GPL license. - flake8-django, licensed under the GPL license.
@@ -1269,31 +1249,6 @@ are:
SOFTWARE. SOFTWARE.
""" """
- flake8-trio, licensed as follows:
"""
MIT License
Copyright (c) 2022 Zac Hatfield-Dodds
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
- Pyright, licensed as follows: - Pyright, licensed as follows:
""" """
MIT License MIT License

128
README.md
View File

@@ -8,9 +8,9 @@
[![image](https://img.shields.io/pypi/pyversions/ruff.svg)](https://pypi.python.org/pypi/ruff) [![image](https://img.shields.io/pypi/pyversions/ruff.svg)](https://pypi.python.org/pypi/ruff)
[![Actions status](https://github.com/astral-sh/ruff/workflows/CI/badge.svg)](https://github.com/astral-sh/ruff/actions) [![Actions status](https://github.com/astral-sh/ruff/workflows/CI/badge.svg)](https://github.com/astral-sh/ruff/actions)
[**Discord**](https://discord.gg/c9MhzV8aU5) | [**Docs**](https://docs.astral.sh/ruff/) | [**Playground**](https://play.ruff.rs/) [**Discord**](https://discord.gg/c9MhzV8aU5) | [**Docs**](https://beta.ruff.rs/docs/) | [**Playground**](https://play.ruff.rs/)
An extremely fast Python linter and code formatter, written in Rust. An extremely fast Python linter, written in Rust.
<p align="center"> <p align="center">
<picture align="center"> <picture align="center">
@@ -24,27 +24,28 @@ An extremely fast Python linter and code formatter, written in Rust.
<i>Linting the CPython codebase from scratch.</i> <i>Linting the CPython codebase from scratch.</i>
</p> </p>
- ⚡️ 10-100x faster than existing linters (like Flake8) and formatters (like Black) - ⚡️ 10-100x faster than existing linters
- 🐍 Installable via `pip` - 🐍 Installable via `pip`
- 🛠️ `pyproject.toml` support - 🛠️ `pyproject.toml` support
- 🤝 Python 3.12 compatibility - 🤝 Python 3.11 compatibility
- ⚖️ Drop-in parity with [Flake8](https://docs.astral.sh/ruff/faq/#how-does-ruff-compare-to-flake8), isort, and Black
- 📦 Built-in caching, to avoid re-analyzing unchanged files - 📦 Built-in caching, to avoid re-analyzing unchanged files
- 🔧 Fix support, for automatic error correction (e.g., automatically remove unused imports) - 🔧 Autofix support, for automatic error correction (e.g., automatically remove unused imports)
- 📏 Over [700 built-in rules](https://docs.astral.sh/ruff/rules/), with native re-implementations - 📏 Over [600 built-in rules](https://beta.ruff.rs/docs/rules/)
of popular Flake8 plugins, like flake8-bugbear - ⚖️ [Near-parity](https://beta.ruff.rs/docs/faq/#how-does-ruff-compare-to-flake8) with the
- ⌨️ First-party [editor integrations](https://docs.astral.sh/ruff/integrations/) for built-in Flake8 rule set
- 🔌 Native re-implementations of dozens of Flake8 plugins, like flake8-bugbear
- ⌨️ First-party [editor integrations](https://beta.ruff.rs/docs/editor-integrations/) for
[VS Code](https://github.com/astral-sh/ruff-vscode) and [more](https://github.com/astral-sh/ruff-lsp) [VS Code](https://github.com/astral-sh/ruff-vscode) and [more](https://github.com/astral-sh/ruff-lsp)
- 🌎 Monorepo-friendly, with [hierarchical and cascading configuration](https://docs.astral.sh/ruff/configuration/#pyprojecttoml-discovery) - 🌎 Monorepo-friendly, with [hierarchical and cascading configuration](https://beta.ruff.rs/docs/configuration/#pyprojecttoml-discovery)
Ruff aims to be orders of magnitude faster than alternative tools while integrating more Ruff aims to be orders of magnitude faster than alternative tools while integrating more
functionality behind a single, common interface. functionality behind a single, common interface.
Ruff can be used to replace [Flake8](https://pypi.org/project/flake8/) (plus dozens of plugins), Ruff can be used to replace [Flake8](https://pypi.org/project/flake8/) (plus dozens of plugins),
[Black](https://github.com/psf/black), [isort](https://pypi.org/project/isort/), [isort](https://pypi.org/project/isort/), [pydocstyle](https://pypi.org/project/pydocstyle/),
[pydocstyle](https://pypi.org/project/pydocstyle/), [pyupgrade](https://pypi.org/project/pyupgrade/), [yesqa](https://github.com/asottile/yesqa), [eradicate](https://pypi.org/project/eradicate/),
[autoflake](https://pypi.org/project/autoflake/), and more, all while executing tens or hundreds of [pyupgrade](https://pypi.org/project/pyupgrade/), and [autoflake](https://pypi.org/project/autoflake/),
times faster than any individual tool. all while executing tens or hundreds of times faster than any individual tool.
Ruff is extremely actively developed and used in major open-source projects like: Ruff is extremely actively developed and used in major open-source projects like:
@@ -97,7 +98,7 @@ developer of [Zulip](https://github.com/zulip/zulip):
## Table of Contents ## Table of Contents
For more, see the [documentation](https://docs.astral.sh/ruff/). For more, see the [documentation](https://beta.ruff.rs/docs/).
1. [Getting Started](#getting-started) 1. [Getting Started](#getting-started)
1. [Configuration](#configuration) 1. [Configuration](#configuration)
@@ -110,7 +111,7 @@ For more, see the [documentation](https://docs.astral.sh/ruff/).
## Getting Started ## Getting Started
For more, see the [documentation](https://docs.astral.sh/ruff/). For more, see the [documentation](https://beta.ruff.rs/docs/).
### Installation ### Installation
@@ -121,42 +122,27 @@ pip install ruff
``` ```
You can also install Ruff via [Homebrew](https://formulae.brew.sh/formula/ruff), [Conda](https://anaconda.org/conda-forge/ruff), You can also install Ruff via [Homebrew](https://formulae.brew.sh/formula/ruff), [Conda](https://anaconda.org/conda-forge/ruff),
and with [a variety of other package managers](https://docs.astral.sh/ruff/installation/). and with [a variety of other package managers](https://beta.ruff.rs/docs/installation/).
### Usage ### Usage
To run Ruff as a linter, try any of the following: To run Ruff, try any of the following:
```shell ```shell
ruff check . # Lint all files in the current directory (and any subdirectories). ruff check . # Lint all files in the current directory (and any subdirectories)
ruff check path/to/code/ # Lint all files in `/path/to/code` (and any subdirectories). ruff check path/to/code/ # Lint all files in `/path/to/code` (and any subdirectories)
ruff check path/to/code/*.py # Lint all `.py` files in `/path/to/code`. ruff check path/to/code/*.py # Lint all `.py` files in `/path/to/code`
ruff check path/to/code/to/file.py # Lint `file.py`. ruff check path/to/code/to/file.py # Lint `file.py`
ruff check @arguments.txt # Lint using an input file, treating its contents as newline-delimited command-line arguments.
``` ```
Or, to run Ruff as a formatter: Ruff can also be used as a [pre-commit](https://pre-commit.com) hook:
```shell
ruff format . # Format all files in the current directory (and any subdirectories).
ruff format path/to/code/ # Format all files in `/path/to/code` (and any subdirectories).
ruff format path/to/code/*.py # Format all `.py` files in `/path/to/code`.
ruff format path/to/code/to/file.py # Format `file.py`.
ruff format @arguments.txt # Format using an input file, treating its contents as newline-delimited command-line arguments.
```
Ruff can also be used as a [pre-commit](https://pre-commit.com/) hook via [`ruff-pre-commit`](https://github.com/astral-sh/ruff-pre-commit):
```yaml ```yaml
- repo: https://github.com/astral-sh/ruff-pre-commit - repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version. # Ruff version.
rev: v0.1.5 rev: v0.0.290
hooks: hooks:
# Run the linter.
- id: ruff - id: ruff
args: [ --fix ]
# Run the formatter.
- id: ruff-format
``` ```
Ruff can also be used as a [VS Code extension](https://github.com/astral-sh/ruff-vscode) or Ruff can also be used as a [VS Code extension](https://github.com/astral-sh/ruff-vscode) or
@@ -179,13 +165,21 @@ jobs:
### Configuration ### Configuration
Ruff can be configured through a `pyproject.toml`, `ruff.toml`, or `.ruff.toml` file (see: Ruff can be configured through a `pyproject.toml`, `ruff.toml`, or `.ruff.toml` file (see:
[_Configuration_](https://docs.astral.sh/ruff/configuration/), or [_Settings_](https://docs.astral.sh/ruff/settings/) [_Configuration_](https://beta.ruff.rs/docs/configuration/), or [_Settings_](https://beta.ruff.rs/docs/settings/)
for a complete list of all configuration options). for a complete list of all configuration options).
If left unspecified, Ruff's default configuration is equivalent to: If left unspecified, the default configuration is equivalent to:
```toml ```toml
[tool.ruff] [tool.ruff]
# Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default.
select = ["E", "F"]
ignore = []
# Allow autofix for all enabled rules (when `--fix`) is provided.
fixable = ["A", "B", "C", "D", "E", "F", "G", "I", "N", "Q", "S", "T", "W", "ANN", "ARG", "BLE", "COM", "DJ", "DTZ", "EM", "ERA", "EXE", "FBT", "ICN", "INP", "ISC", "NPY", "PD", "PGH", "PIE", "PL", "PT", "PTH", "PYI", "RET", "RSE", "RUF", "SIM", "SLF", "TCH", "TID", "TRY", "UP", "YTT"]
unfixable = []
# Exclude a variety of commonly ignored directories. # Exclude a variety of commonly ignored directories.
exclude = [ exclude = [
".bzr", ".bzr",
@@ -213,57 +207,39 @@ exclude = [
# Same as Black. # Same as Black.
line-length = 88 line-length = 88
indent-width = 4
# Assume Python 3.8
target-version = "py38"
[tool.ruff.lint]
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
select = ["E4", "E7", "E9", "F"]
ignore = []
# Allow fix for all enabled rules (when `--fix`) is provided.
fixable = ["ALL"]
unfixable = []
# Allow unused variables when underscore-prefixed. # Allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
[tool.ruff.format] # Assume Python 3.8
# Like Black, use double quotes for strings. target-version = "py38"
quote-style = "double"
# Like Black, indent with spaces, rather than tabs. [tool.ruff.mccabe]
indent-style = "space" # Unlike Flake8, default to a complexity level of 10.
max-complexity = 10
# Like Black, respect magic trailing commas.
skip-magic-trailing-comma = false
# Like Black, automatically detect the appropriate line ending.
line-ending = "auto"
``` ```
Some configuration options can be provided via the command-line, such as those related to Some configuration options can be provided via the command-line, such as those related to
rule enablement and disablement, file discovery, and logging level: rule enablement and disablement, file discovery, logging level, and more:
```shell ```shell
ruff check path/to/code/ --select F401 --select F403 --quiet ruff check path/to/code/ --select F401 --select F403 --quiet
``` ```
See `ruff help` for more on Ruff's top-level commands, or `ruff help check` and `ruff help format` See `ruff help` for more on Ruff's top-level commands, or `ruff help check` for more on the
for more on the linting and formatting commands, respectively. linting command.
## Rules ## Rules
<!-- Begin section: Rules --> <!-- Begin section: Rules -->
**Ruff supports over 700 lint rules**, many of which are inspired by popular tools like Flake8, **Ruff supports over 600 lint rules**, many of which are inspired by popular tools like Flake8,
isort, pyupgrade, and others. Regardless of the rule's origin, Ruff re-implements every rule in isort, pyupgrade, and others. Regardless of the rule's origin, Ruff re-implements every rule in
Rust as a first-party feature. Rust as a first-party feature.
By default, Ruff enables Flake8's `F` rules, along with a subset of the `E` rules, omitting any By default, Ruff enables Flake8's `E` and `F` rules. Ruff supports all rules from the `F` category,
stylistic rules that overlap with the use of a formatter, like `ruff format` or and a [subset](https://beta.ruff.rs/docs/rules/#error-e) of the `E` category, omitting those
stylistic rules made obsolete by the use of an autoformatter, like
[Black](https://github.com/psf/black). [Black](https://github.com/psf/black).
If you're just getting started with Ruff, **the default rule set is a great place to start**: it If you're just getting started with Ruff, **the default rule set is a great place to start**: it
@@ -314,7 +290,6 @@ quality tools, including:
- [flake8-super](https://pypi.org/project/flake8-super/) - [flake8-super](https://pypi.org/project/flake8-super/)
- [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/) - [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
- [flake8-todos](https://pypi.org/project/flake8-todos/) - [flake8-todos](https://pypi.org/project/flake8-todos/)
- [flake8-trio](https://pypi.org/project/flake8-trio/)
- [flake8-type-checking](https://pypi.org/project/flake8-type-checking/) - [flake8-type-checking](https://pypi.org/project/flake8-type-checking/)
- [flake8-use-pathlib](https://pypi.org/project/flake8-use-pathlib/) - [flake8-use-pathlib](https://pypi.org/project/flake8-use-pathlib/)
- [flynt](https://pypi.org/project/flynt/) ([#2102](https://github.com/astral-sh/ruff/issues/2102)) - [flynt](https://pypi.org/project/flynt/) ([#2102](https://github.com/astral-sh/ruff/issues/2102))
@@ -329,12 +304,12 @@ quality tools, including:
- [tryceratops](https://pypi.org/project/tryceratops/) - [tryceratops](https://pypi.org/project/tryceratops/)
- [yesqa](https://pypi.org/project/yesqa/) - [yesqa](https://pypi.org/project/yesqa/)
For a complete enumeration of the supported rules, see [_Rules_](https://docs.astral.sh/ruff/rules/). For a complete enumeration of the supported rules, see [_Rules_](https://beta.ruff.rs/docs/rules/).
## Contributing ## Contributing
Contributions are welcome and highly appreciated. To get started, check out the Contributions are welcome and highly appreciated. To get started, check out the
[**contributing guidelines**](https://docs.astral.sh/ruff/contributing/). [**contributing guidelines**](https://beta.ruff.rs/docs/contributing/).
You can also join us on [**Discord**](https://discord.gg/c9MhzV8aU5). You can also join us on [**Discord**](https://discord.gg/c9MhzV8aU5).
@@ -356,7 +331,7 @@ In some cases, Ruff includes a "direct" Rust port of the corresponding tool.
We're grateful to the maintainers of these tools for their work, and for all We're grateful to the maintainers of these tools for their work, and for all
the value they've provided to the Python community. the value they've provided to the Python community.
Ruff's formatter is built on a fork of Rome's [`rome_formatter`](https://github.com/rome/tools/tree/main/crates/rome_formatter), Ruff's autoformatter is built on a fork of Rome's [`rome_formatter`](https://github.com/rome/tools/tree/main/crates/rome_formatter),
and again draws on both API and implementation details from [Rome](https://github.com/rome/tools), and again draws on both API and implementation details from [Rome](https://github.com/rome/tools),
[Prettier](https://github.com/prettier/prettier), and [Black](https://github.com/psf/black). [Prettier](https://github.com/prettier/prettier), and [Black](https://github.com/psf/black).
@@ -410,13 +385,11 @@ Ruff is used by a number of major open-source projects and companies, including:
- [Mypy](https://github.com/python/mypy) - [Mypy](https://github.com/python/mypy)
- Netflix ([Dispatch](https://github.com/Netflix/dispatch)) - Netflix ([Dispatch](https://github.com/Netflix/dispatch))
- [Neon](https://github.com/neondatabase/neon) - [Neon](https://github.com/neondatabase/neon)
- [NoneBot](https://github.com/nonebot/nonebot2)
- [ONNX](https://github.com/onnx/onnx) - [ONNX](https://github.com/onnx/onnx)
- [OpenBB](https://github.com/OpenBB-finance/OpenBBTerminal) - [OpenBB](https://github.com/OpenBB-finance/OpenBBTerminal)
- [PDM](https://github.com/pdm-project/pdm) - [PDM](https://github.com/pdm-project/pdm)
- [PaddlePaddle](https://github.com/PaddlePaddle/Paddle) - [PaddlePaddle](https://github.com/PaddlePaddle/Paddle)
- [Pandas](https://github.com/pandas-dev/pandas) - [Pandas](https://github.com/pandas-dev/pandas)
- [Pillow](https://github.com/python-pillow/Pillow)
- [Poetry](https://github.com/python-poetry/poetry) - [Poetry](https://github.com/python-poetry/poetry)
- [Polars](https://github.com/pola-rs/polars) - [Polars](https://github.com/pola-rs/polars)
- [PostHog](https://github.com/PostHog/posthog) - [PostHog](https://github.com/PostHog/posthog)
@@ -425,7 +398,6 @@ Ruff is used by a number of major open-source projects and companies, including:
- [PyTorch](https://github.com/pytorch/pytorch) - [PyTorch](https://github.com/pytorch/pytorch)
- [Pydantic](https://github.com/pydantic/pydantic) - [Pydantic](https://github.com/pydantic/pydantic)
- [Pylint](https://github.com/PyCQA/pylint) - [Pylint](https://github.com/PyCQA/pylint)
- [PyMC-Marketing](https://github.com/pymc-labs/pymc-marketing)
- [Reflex](https://github.com/reflex-dev/reflex) - [Reflex](https://github.com/reflex-dev/reflex)
- [Rippling](https://rippling.com) - [Rippling](https://rippling.com)
- [Robyn](https://github.com/sansyrox/robyn) - [Robyn](https://github.com/sansyrox/robyn)

View File

@@ -1,6 +1,5 @@
[files] [files]
# https://github.com/crate-ci/typos/issues/868 extend-exclude = ["resources", "snapshots"]
extend-exclude = ["**/resources/**/*", "**/snapshots/**/*"]
[default.extend-words] [default.extend-words]
hel = "hel" hel = "hel"

View File

@@ -1,8 +0,0 @@
{
"label": "code style",
"message": "Ruff",
"logoSvg": "<svg width=\"510\" height=\"622\" viewBox=\"0 0 510 622\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M206.701 0C200.964 0 196.314 4.64131 196.314 10.3667V41.4667C196.314 47.192 191.663 51.8333 185.927 51.8333H156.843C151.107 51.8333 146.456 56.4746 146.456 62.2V145.133C146.456 150.859 141.806 155.5 136.069 155.5H106.986C101.249 155.5 96.5988 160.141 96.5988 165.867V222.883C96.5988 228.609 91.9484 233.25 86.2118 233.25H57.1283C51.3917 233.25 46.7413 237.891 46.7413 243.617V300.633C46.7413 306.359 42.0909 311 36.3544 311H10.387C4.6504 311 0 315.641 0 321.367V352.467C0 358.192 4.6504 362.833 10.387 362.833H145.418C151.154 362.833 155.804 367.475 155.804 373.2V430.217C155.804 435.942 151.154 440.583 145.418 440.583H116.334C110.597 440.583 105.947 445.225 105.947 450.95V507.967C105.947 513.692 101.297 518.333 95.5601 518.333H66.4766C60.74 518.333 56.0896 522.975 56.0896 528.7V611.633C56.0896 617.359 60.74 622 66.4766 622H149.572C155.309 622 159.959 617.359 159.959 611.633V570.167H201.507C207.244 570.167 211.894 565.525 211.894 559.8V528.7C211.894 522.975 216.544 518.333 222.281 518.333H251.365C257.101 518.333 261.752 513.692 261.752 507.967V476.867C261.752 471.141 266.402 466.5 272.138 466.5H301.222C306.959 466.5 311.609 461.859 311.609 456.133V425.033C311.609 419.308 316.259 414.667 321.996 414.667H351.079C356.816 414.667 361.466 410.025 361.466 404.3V373.2C361.466 367.475 366.117 362.833 371.853 362.833H400.937C406.673 362.833 411.324 358.192 411.324 352.467V321.367C411.324 315.641 415.974 311 421.711 311H450.794C456.531 311 461.181 306.359 461.181 300.633V217.7C461.181 211.975 456.531 207.333 450.794 207.333H420.672C414.936 207.333 410.285 202.692 410.285 196.967V165.867C410.285 160.141 414.936 155.5 420.672 155.5H449.756C455.492 155.5 460.143 150.859 460.143 145.133V114.033C460.143 108.308 464.793 103.667 470.53 103.667H499.613C505.35 103.667 510 99.0253 510 93.3V10.3667C510 4.64132 505.35 0 499.613 0H206.701ZM168.269 440.583C162.532 440.583 157.882 445.225 157.882 450.95V507.967C157.882 513.692 153.231 518.333 147.495 518.333H118.411C112.675 518.333 108.024 522.975 108.024 528.7V559.8C108.024 565.525 112.675 570.167 118.411 570.167H159.959V528.7C159.959 522.975 164.61 518.333 170.346 518.333H199.43C205.166 518.333 209.817 513.692 209.817 507.967V476.867C209.817 471.141 214.467 466.5 220.204 466.5H249.287C255.024 466.5 259.674 461.859 259.674 456.133V425.033C259.674 419.308 264.325 414.667 270.061 414.667H299.145C304.881 414.667 309.532 410.025 309.532 404.3V373.2C309.532 367.475 314.182 362.833 319.919 362.833H349.002C354.739 362.833 359.389 358.192 359.389 352.467V321.367C359.389 315.641 364.039 311 369.776 311H398.859C404.596 311 409.246 306.359 409.246 300.633V269.533C409.246 263.808 404.596 259.167 398.859 259.167H318.88C313.143 259.167 308.493 254.525 308.493 248.8V217.7C308.493 211.975 313.143 207.333 318.88 207.333H347.963C353.7 207.333 358.35 202.692 358.35 196.967V165.867C358.35 160.141 363.001 155.5 368.737 155.5H397.821C403.557 155.5 408.208 150.859 408.208 145.133V114.033C408.208 108.308 412.858 103.667 418.595 103.667H447.678C453.415 103.667 458.065 99.0253 458.065 93.3V62.2C458.065 56.4746 453.415 51.8333 447.678 51.8333H208.778C203.041 51.8333 198.391 56.4746 198.391 62.2V145.133C198.391 150.859 193.741 155.5 188.004 155.5H158.921C153.184 155.5 148.534 160.141 148.534 165.867V222.883C148.534 228.609 143.883 233.25 138.147 233.25H109.063C103.327 233.25 98.6762 237.891 98.6762 243.617V300.633C98.6762 306.359 103.327 311 109.063 311H197.352C203.089 311 207.739 315.641 207.739 321.367V430.217C207.739 435.942 203.089 440.583 197.352 440.583H168.269Z\" fill=\"#D7FF64\"/></svg>",
"logoWidth": 10,
"labelColor": "grey",
"color": "#261230"
}

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "flake8-to-ruff" name = "flake8-to-ruff"
version = "0.1.5" version = "0.0.290"
description = """ description = """
Convert Flake8 configuration files to Ruff configuration files. Convert Flake8 configuration files to Ruff configuration files.
""" """
@@ -13,7 +13,7 @@ repository = { workspace = true }
license = { workspace = true } license = { workspace = true }
[dependencies] [dependencies]
ruff_linter = { path = "../ruff_linter", default-features = false } ruff = { path = "../ruff", default-features = false }
ruff_workspace = { path = "../ruff_workspace" } ruff_workspace = { path = "../ruff_workspace" }
anyhow = { workspace = true } anyhow = { workspace = true }
@@ -23,7 +23,7 @@ configparser = { version = "3.0.2" }
itertools = { workspace = true } itertools = { workspace = true }
log = { workspace = true } log = { workspace = true }
once_cell = { workspace = true } once_cell = { workspace = true }
pep440_rs = { version = "0.3.12", features = ["serde"] } pep440_rs = { version = "0.3.1", features = ["serde"] }
regex = { workspace = true } regex = { workspace = true }
rustc-hash = { workspace = true } rustc-hash = { workspace = true }
serde = { workspace = true } serde = { workspace = true }

View File

@@ -86,7 +86,7 @@ flake8-to-ruff path/to/.flake8 --plugin flake8-builtins --plugin flake8-quotes
configuration options that don't exist in Flake8.) configuration options that don't exist in Flake8.)
1. Ruff will omit any rule codes that are unimplemented or unsupported by Ruff, including rule 1. Ruff will omit any rule codes that are unimplemented or unsupported by Ruff, including rule
codes from unsupported plugins. (See the codes from unsupported plugins. (See the
[documentation](https://docs.astral.sh/ruff/faq/#how-does-ruff-compare-to-flake8) for the complete [documentation](https://beta.ruff.rs/docs/faq/#how-does-ruff-compare-to-flake8) for the complete
list of supported plugins.) list of supported plugins.)
## License ## License

View File

@@ -1,7 +1,7 @@
//! Extract Black configuration settings from a pyproject.toml. //! Extract Black configuration settings from a pyproject.toml.
use ruff_linter::line_width::LineLength; use ruff::line_width::LineLength;
use ruff_linter::settings::types::PythonVersion; use ruff::settings::types::PythonVersion;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default)] #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default)]

View File

@@ -3,22 +3,21 @@ use std::str::FromStr;
use itertools::Itertools; use itertools::Itertools;
use ruff_linter::line_width::LineLength; use ruff::line_width::LineLength;
use ruff_linter::registry::Linter; use ruff::registry::Linter;
use ruff_linter::rule_selector::RuleSelector; use ruff::rule_selector::RuleSelector;
use ruff_linter::rules::flake8_pytest_style::types::{ use ruff::rules::flake8_pytest_style::types::{
ParametrizeNameType, ParametrizeValuesRowType, ParametrizeValuesType, ParametrizeNameType, ParametrizeValuesRowType, ParametrizeValuesType,
}; };
use ruff_linter::rules::flake8_quotes::settings::Quote; use ruff::rules::flake8_quotes::settings::Quote;
use ruff_linter::rules::flake8_tidy_imports::settings::Strictness; use ruff::rules::flake8_tidy_imports::settings::Strictness;
use ruff_linter::rules::pydocstyle::settings::Convention; use ruff::rules::pydocstyle::settings::Convention;
use ruff_linter::settings::types::PythonVersion; use ruff::settings::types::PythonVersion;
use ruff_linter::settings::DEFAULT_SELECTORS; use ruff::warn_user;
use ruff_linter::warn_user;
use ruff_workspace::options::{ use ruff_workspace::options::{
Flake8AnnotationsOptions, Flake8BugbearOptions, Flake8BuiltinsOptions, Flake8ErrMsgOptions, Flake8AnnotationsOptions, Flake8BugbearOptions, Flake8BuiltinsOptions, Flake8ErrMsgOptions,
Flake8PytestStyleOptions, Flake8QuotesOptions, Flake8TidyImportsOptions, LintCommonOptions, Flake8PytestStyleOptions, Flake8QuotesOptions, Flake8TidyImportsOptions, McCabeOptions,
LintOptions, McCabeOptions, Options, Pep8NamingOptions, PydocstyleOptions, Options, Pep8NamingOptions, PydocstyleOptions,
}; };
use ruff_workspace::pyproject::Pyproject; use ruff_workspace::pyproject::Pyproject;
@@ -26,6 +25,11 @@ use super::external_config::ExternalConfig;
use super::plugin::Plugin; use super::plugin::Plugin;
use super::{parser, plugin}; use super::{parser, plugin};
const DEFAULT_SELECTORS: &[RuleSelector] = &[
RuleSelector::Linter(Linter::Pyflakes),
RuleSelector::Linter(Linter::Pycodestyle),
];
pub(crate) fn convert( pub(crate) fn convert(
config: &HashMap<String, HashMap<String, Option<String>>>, config: &HashMap<String, HashMap<String, Option<String>>>,
external_config: &ExternalConfig, external_config: &ExternalConfig,
@@ -99,7 +103,6 @@ pub(crate) fn convert(
// Parse each supported option. // Parse each supported option.
let mut options = Options::default(); let mut options = Options::default();
let mut lint_options = LintCommonOptions::default();
let mut flake8_annotations = Flake8AnnotationsOptions::default(); let mut flake8_annotations = Flake8AnnotationsOptions::default();
let mut flake8_bugbear = Flake8BugbearOptions::default(); let mut flake8_bugbear = Flake8BugbearOptions::default();
let mut flake8_builtins = Flake8BuiltinsOptions::default(); let mut flake8_builtins = Flake8BuiltinsOptions::default();
@@ -147,7 +150,7 @@ pub(crate) fn convert(
"per-file-ignores" | "per_file_ignores" => { "per-file-ignores" | "per_file_ignores" => {
match parser::parse_files_to_codes_mapping(value.as_ref()) { match parser::parse_files_to_codes_mapping(value.as_ref()) {
Ok(per_file_ignores) => { Ok(per_file_ignores) => {
lint_options.per_file_ignores = options.per_file_ignores =
Some(parser::collect_per_file_ignores(per_file_ignores)); Some(parser::collect_per_file_ignores(per_file_ignores));
} }
Err(e) => { Err(e) => {
@@ -355,47 +358,47 @@ pub(crate) fn convert(
} }
// Deduplicate and sort. // Deduplicate and sort.
lint_options.select = Some( options.select = Some(
select select
.into_iter() .into_iter()
.sorted_by_key(RuleSelector::prefix_and_code) .sorted_by_key(RuleSelector::prefix_and_code)
.collect(), .collect(),
); );
lint_options.ignore = Some( options.ignore = Some(
ignore ignore
.into_iter() .into_iter()
.sorted_by_key(RuleSelector::prefix_and_code) .sorted_by_key(RuleSelector::prefix_and_code)
.collect(), .collect(),
); );
if flake8_annotations != Flake8AnnotationsOptions::default() { if flake8_annotations != Flake8AnnotationsOptions::default() {
lint_options.flake8_annotations = Some(flake8_annotations); options.flake8_annotations = Some(flake8_annotations);
} }
if flake8_bugbear != Flake8BugbearOptions::default() { if flake8_bugbear != Flake8BugbearOptions::default() {
lint_options.flake8_bugbear = Some(flake8_bugbear); options.flake8_bugbear = Some(flake8_bugbear);
} }
if flake8_builtins != Flake8BuiltinsOptions::default() { if flake8_builtins != Flake8BuiltinsOptions::default() {
lint_options.flake8_builtins = Some(flake8_builtins); options.flake8_builtins = Some(flake8_builtins);
} }
if flake8_errmsg != Flake8ErrMsgOptions::default() { if flake8_errmsg != Flake8ErrMsgOptions::default() {
lint_options.flake8_errmsg = Some(flake8_errmsg); options.flake8_errmsg = Some(flake8_errmsg);
} }
if flake8_pytest_style != Flake8PytestStyleOptions::default() { if flake8_pytest_style != Flake8PytestStyleOptions::default() {
lint_options.flake8_pytest_style = Some(flake8_pytest_style); options.flake8_pytest_style = Some(flake8_pytest_style);
} }
if flake8_quotes != Flake8QuotesOptions::default() { if flake8_quotes != Flake8QuotesOptions::default() {
lint_options.flake8_quotes = Some(flake8_quotes); options.flake8_quotes = Some(flake8_quotes);
} }
if flake8_tidy_imports != Flake8TidyImportsOptions::default() { if flake8_tidy_imports != Flake8TidyImportsOptions::default() {
lint_options.flake8_tidy_imports = Some(flake8_tidy_imports); options.flake8_tidy_imports = Some(flake8_tidy_imports);
} }
if mccabe != McCabeOptions::default() { if mccabe != McCabeOptions::default() {
lint_options.mccabe = Some(mccabe); options.mccabe = Some(mccabe);
} }
if pep8_naming != Pep8NamingOptions::default() { if pep8_naming != Pep8NamingOptions::default() {
lint_options.pep8_naming = Some(pep8_naming); options.pep8_naming = Some(pep8_naming);
} }
if pydocstyle != PydocstyleOptions::default() { if pydocstyle != PydocstyleOptions::default() {
lint_options.pydocstyle = Some(pydocstyle); options.pydocstyle = Some(pydocstyle);
} }
// Extract any settings from the existing `pyproject.toml`. // Extract any settings from the existing `pyproject.toml`.
@@ -433,13 +436,6 @@ pub(crate) fn convert(
} }
} }
if lint_options != LintCommonOptions::default() {
options.lint = Some(LintOptions {
common: lint_options,
..LintOptions::default()
});
}
// Create the pyproject.toml. // Create the pyproject.toml.
Pyproject::new(options) Pyproject::new(options)
} }
@@ -462,15 +458,13 @@ mod tests {
use pep440_rs::VersionSpecifiers; use pep440_rs::VersionSpecifiers;
use pretty_assertions::assert_eq; use pretty_assertions::assert_eq;
use ruff_linter::line_width::LineLength; use ruff::line_width::LineLength;
use ruff_linter::registry::Linter; use ruff::registry::Linter;
use ruff_linter::rule_selector::RuleSelector; use ruff::rule_selector::RuleSelector;
use ruff_linter::rules::flake8_quotes; use ruff::rules::flake8_quotes;
use ruff_linter::rules::pydocstyle::settings::Convention; use ruff::rules::pydocstyle::settings::Convention;
use ruff_linter::settings::types::PythonVersion; use ruff::settings::types::PythonVersion;
use ruff_workspace::options::{ use ruff_workspace::options::{Flake8QuotesOptions, Options, PydocstyleOptions};
Flake8QuotesOptions, LintCommonOptions, LintOptions, Options, PydocstyleOptions,
};
use ruff_workspace::pyproject::Pyproject; use ruff_workspace::pyproject::Pyproject;
use crate::converter::DEFAULT_SELECTORS; use crate::converter::DEFAULT_SELECTORS;
@@ -480,8 +474,8 @@ mod tests {
use super::super::plugin::Plugin; use super::super::plugin::Plugin;
use super::convert; use super::convert;
fn lint_default_options(plugins: impl IntoIterator<Item = RuleSelector>) -> LintCommonOptions { fn default_options(plugins: impl IntoIterator<Item = RuleSelector>) -> Options {
LintCommonOptions { Options {
ignore: Some(vec![]), ignore: Some(vec![]),
select: Some( select: Some(
DEFAULT_SELECTORS DEFAULT_SELECTORS
@@ -491,7 +485,7 @@ mod tests {
.sorted_by_key(RuleSelector::prefix_and_code) .sorted_by_key(RuleSelector::prefix_and_code)
.collect(), .collect(),
), ),
..LintCommonOptions::default() ..Options::default()
} }
} }
@@ -502,13 +496,7 @@ mod tests {
&ExternalConfig::default(), &ExternalConfig::default(),
None, None,
); );
let expected = Pyproject::new(Options { let expected = Pyproject::new(default_options([]));
lint: Some(LintOptions {
common: lint_default_options([]),
..LintOptions::default()
}),
..Options::default()
});
assert_eq!(actual, expected); assert_eq!(actual, expected);
} }
@@ -524,11 +512,7 @@ mod tests {
); );
let expected = Pyproject::new(Options { let expected = Pyproject::new(Options {
line_length: Some(LineLength::try_from(100).unwrap()), line_length: Some(LineLength::try_from(100).unwrap()),
lint: Some(LintOptions { ..default_options([])
common: lint_default_options([]),
..LintOptions::default()
}),
..Options::default()
}); });
assert_eq!(actual, expected); assert_eq!(actual, expected);
} }
@@ -545,11 +529,7 @@ mod tests {
); );
let expected = Pyproject::new(Options { let expected = Pyproject::new(Options {
line_length: Some(LineLength::try_from(100).unwrap()), line_length: Some(LineLength::try_from(100).unwrap()),
lint: Some(LintOptions { ..default_options([])
common: lint_default_options([]),
..LintOptions::default()
}),
..Options::default()
}); });
assert_eq!(actual, expected); assert_eq!(actual, expected);
} }
@@ -564,13 +544,7 @@ mod tests {
&ExternalConfig::default(), &ExternalConfig::default(),
Some(vec![]), Some(vec![]),
); );
let expected = Pyproject::new(Options { let expected = Pyproject::new(default_options([]));
lint: Some(LintOptions {
common: lint_default_options([]),
..LintOptions::default()
}),
..Options::default()
});
assert_eq!(actual, expected); assert_eq!(actual, expected);
} }
@@ -585,19 +559,13 @@ mod tests {
Some(vec![]), Some(vec![]),
); );
let expected = Pyproject::new(Options { let expected = Pyproject::new(Options {
lint: Some(LintOptions { flake8_quotes: Some(Flake8QuotesOptions {
common: LintCommonOptions { inline_quotes: Some(flake8_quotes::settings::Quote::Single),
flake8_quotes: Some(Flake8QuotesOptions { multiline_quotes: None,
inline_quotes: Some(flake8_quotes::settings::Quote::Single), docstring_quotes: None,
multiline_quotes: None, avoid_escape: None,
docstring_quotes: None,
avoid_escape: None,
}),
..lint_default_options([])
},
..LintOptions::default()
}), }),
..Options::default() ..default_options([])
}); });
assert_eq!(actual, expected); assert_eq!(actual, expected);
} }
@@ -616,18 +584,12 @@ mod tests {
Some(vec![Plugin::Flake8Docstrings]), Some(vec![Plugin::Flake8Docstrings]),
); );
let expected = Pyproject::new(Options { let expected = Pyproject::new(Options {
lint: Some(LintOptions { pydocstyle: Some(PydocstyleOptions {
common: LintCommonOptions { convention: Some(Convention::Numpy),
pydocstyle: Some(PydocstyleOptions { ignore_decorators: None,
convention: Some(Convention::Numpy), property_decorators: None,
ignore_decorators: None,
property_decorators: None,
}),
..lint_default_options([Linter::Pydocstyle.into()])
},
..LintOptions::default()
}), }),
..Options::default() ..default_options([Linter::Pydocstyle.into()])
}); });
assert_eq!(actual, expected); assert_eq!(actual, expected);
} }
@@ -643,19 +605,13 @@ mod tests {
None, None,
); );
let expected = Pyproject::new(Options { let expected = Pyproject::new(Options {
lint: Some(LintOptions { flake8_quotes: Some(Flake8QuotesOptions {
common: LintCommonOptions { inline_quotes: Some(flake8_quotes::settings::Quote::Single),
flake8_quotes: Some(Flake8QuotesOptions { multiline_quotes: None,
inline_quotes: Some(flake8_quotes::settings::Quote::Single), docstring_quotes: None,
multiline_quotes: None, avoid_escape: None,
docstring_quotes: None,
avoid_escape: None,
}),
..lint_default_options([Linter::Flake8Quotes.into()])
},
..LintOptions::default()
}), }),
..Options::default() ..default_options([Linter::Flake8Quotes.into()])
}); });
assert_eq!(actual, expected); assert_eq!(actual, expected);
} }
@@ -674,11 +630,7 @@ mod tests {
); );
let expected = Pyproject::new(Options { let expected = Pyproject::new(Options {
target_version: Some(PythonVersion::Py38), target_version: Some(PythonVersion::Py38),
lint: Some(LintOptions { ..default_options([])
common: lint_default_options([]),
..LintOptions::default()
}),
..Options::default()
}); });
assert_eq!(actual, expected); assert_eq!(actual, expected);

View File

@@ -19,7 +19,7 @@ use crate::converter::convert;
use crate::external_config::ExternalConfig; use crate::external_config::ExternalConfig;
use crate::plugin::Plugin; use crate::plugin::Plugin;
use crate::pyproject::parse; use crate::pyproject::parse;
use ruff_linter::logging::{set_up_logging, LogLevel}; use ruff::logging::{set_up_logging, LogLevel};
#[derive(Parser)] #[derive(Parser)]
#[command( #[command(

View File

@@ -3,11 +3,10 @@ use std::str::FromStr;
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use regex::Regex; use regex::Regex;
use ruff::settings::types::PatternPrefixPair;
use ruff::{warn_user, RuleSelector};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use ruff_linter::settings::types::PatternPrefixPair;
use ruff_linter::{warn_user, RuleSelector};
static COMMA_SEPARATED_LIST_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"[,\s]").unwrap()); static COMMA_SEPARATED_LIST_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"[,\s]").unwrap());
/// Parse a comma-separated list of `RuleSelector` values (e.g., /// Parse a comma-separated list of `RuleSelector` values (e.g.,
@@ -184,7 +183,7 @@ pub(crate) fn collect_per_file_ignores(
for pair in pairs { for pair in pairs {
per_file_ignores per_file_ignores
.entry(pair.pattern) .entry(pair.pattern)
.or_default() .or_insert_with(Vec::new)
.push(pair.prefix); .push(pair.prefix);
} }
per_file_ignores per_file_ignores
@@ -193,11 +192,11 @@ pub(crate) fn collect_per_file_ignores(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use anyhow::Result; use anyhow::Result;
use ruff::RuleSelector;
use ruff_linter::codes; use ruff::codes;
use ruff_linter::registry::Linter; use ruff::registry::Linter;
use ruff_linter::settings::types::PatternPrefixPair; use ruff::settings::types::PatternPrefixPair;
use ruff_linter::RuleSelector;
use super::{parse_files_to_codes_mapping, parse_prefix_codes, parse_strings}; use super::{parse_files_to_codes_mapping, parse_prefix_codes, parse_strings};

View File

@@ -3,9 +3,9 @@ use std::fmt;
use std::str::FromStr; use std::str::FromStr;
use anyhow::anyhow; use anyhow::anyhow;
use ruff_linter::registry::Linter; use ruff::registry::Linter;
use ruff_linter::rule_selector::PreviewOptions; use ruff::settings::types::PreviewMode;
use ruff_linter::RuleSelector; use ruff::RuleSelector;
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub enum Plugin { pub enum Plugin {
@@ -332,7 +332,7 @@ pub(crate) fn infer_plugins_from_codes(selectors: &HashSet<RuleSelector>) -> Vec
.filter(|plugin| { .filter(|plugin| {
for selector in selectors { for selector in selectors {
if selector if selector
.rules(&PreviewOptions::default()) .rules(PreviewMode::Disabled)
.any(|rule| Linter::from(plugin).rules().any(|r| r == rule)) .any(|rule| Linter::from(plugin).rules().any(|r| r == rule))
{ {
return true; return true;

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "ruff_linter" name = "ruff"
version = "0.1.5" version = "0.0.290"
publish = false publish = false
authors = { workspace = true } authors = { workspace = true }
edition = { workspace = true } edition = { workspace = true }
@@ -9,8 +9,10 @@ homepage = { workspace = true }
documentation = { workspace = true } documentation = { workspace = true }
repository = { workspace = true } repository = { workspace = true }
license = { workspace = true } license = { workspace = true }
readme = "README.md"
[lib] [lib]
name = "ruff"
[dependencies] [dependencies]
ruff_cache = { path = "../ruff_cache" } ruff_cache = { path = "../ruff_cache" }
@@ -29,7 +31,6 @@ ruff_python_parser = { path = "../ruff_python_parser" }
ruff_source_file = { path = "../ruff_source_file", features = ["serde"] } ruff_source_file = { path = "../ruff_source_file", features = ["serde"] }
ruff_text_size = { path = "../ruff_text_size" } ruff_text_size = { path = "../ruff_text_size" }
aho-corasick = { version = "1.1.2" }
annotate-snippets = { version = "0.9.1", features = ["color"] } annotate-snippets = { version = "0.9.1", features = ["color"] }
anyhow = { workspace = true } anyhow = { workspace = true }
bitflags = { workspace = true } bitflags = { workspace = true }
@@ -46,20 +47,22 @@ libcst = { workspace = true }
log = { workspace = true } log = { workspace = true }
memchr = { workspace = true } memchr = { workspace = true }
natord = { version = "1.0.9" } natord = { version = "1.0.9" }
num-bigint = { workspace = true }
num-traits = { workspace = true }
once_cell = { workspace = true } once_cell = { workspace = true }
path-absolutize = { workspace = true, features = [ path-absolutize = { workspace = true, features = [
"once_cell_cache", "once_cell_cache",
"use_unix_paths_on_wasm", "use_unix_paths_on_wasm",
] } ] }
pathdiff = { version = "0.2.1" } pathdiff = { version = "0.2.1" }
pep440_rs = { version = "0.3.12", features = ["serde"] } pep440_rs = { version = "0.3.1", features = ["serde"] }
pyproject-toml = { version = "0.8.0" } pyproject-toml = { version = "0.7.0" }
quick-junit = { version = "0.3.2" } quick-junit = { version = "0.3.2" }
regex = { workspace = true } regex = { workspace = true }
result-like = { version = "0.4.6" } result-like = { version = "0.4.6" }
rustc-hash = { workspace = true } rustc-hash = { workspace = true }
schemars = { workspace = true, optional = true } schemars = { workspace = true, optional = true }
semver = { version = "1.0.20" } semver = { version = "1.0.16" }
serde = { workspace = true } serde = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
similar = { workspace = true } similar = { workspace = true }
@@ -70,7 +73,7 @@ thiserror = { workspace = true }
toml = { workspace = true } toml = { workspace = true }
typed-arena = { version = "2.0.2" } typed-arena = { version = "2.0.2" }
unicode-width = { workspace = true } unicode-width = { workspace = true }
unicode_names2 = { workspace = true } unicode_names2 = { version = "0.6.0", git = "https://github.com/youknowone/unicode_names2.git", rev = "4ce16aa85cbcdd9cc830410f1a72ef9a235f2fde" }
wsl = { version = "0.1.0" } wsl = { version = "0.1.0" }
[dev-dependencies] [dev-dependencies]
@@ -79,7 +82,7 @@ pretty_assertions = "1.3.0"
test-case = { workspace = true } test-case = { workspace = true }
# Disable colored output in tests # Disable colored output in tests
colored = { workspace = true, features = ["no-color"] } colored = { workspace = true, features = ["no-color"] }
tempfile = "3.8.1" tempfile = "3.6.0"
[features] [features]
default = [] default = []

View File

@@ -158,9 +158,3 @@ class Foo:
@decorator() @decorator()
def __init__(self: "Foo", foo: int): def __init__(self: "Foo", foo: int):
... ...
# Regression test for: https://github.com/astral-sh/ruff/issues/7711
class Class:
def __init__(self):
print(f"{self.attr=}")

View File

@@ -20,4 +20,3 @@ os.chmod(keyfile, stat.S_IRWXO | stat.S_IRWXG | stat.S_IRWXU) # Error
os.chmod("~/hidden_exec", stat.S_IXGRP) # Error os.chmod("~/hidden_exec", stat.S_IXGRP) # Error
os.chmod("~/hidden_exec", stat.S_IXOTH) # OK os.chmod("~/hidden_exec", stat.S_IXOTH) # OK
os.chmod("/etc/passwd", stat.S_IWOTH) # Error os.chmod("/etc/passwd", stat.S_IWOTH) # Error
os.chmod("/etc/passwd", 0o100000000) # Error

Some files were not shown because too many files have changed in this diff Show More