diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 4c37cea22c..7db3627dc6 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -3,8 +3,8 @@ Thank you for taking the time to report an issue! We're glad to have you involve
If you're filing a bug report, please consider including the following information:
-- A minimal code snippet that reproduces the bug.
-- The command you invoked (e.g., `ruff /path/to/file.py --fix`), ideally including the `--isolated` flag.
-- The current Ruff settings (any relevant sections from your `pyproject.toml`).
-- The current Ruff version (`ruff --version`).
+* A minimal code snippet that reproduces the bug.
+* The command you invoked (e.g., `ruff /path/to/file.py --fix`), ideally including the `--isolated` flag.
+* The current Ruff settings (any relevant sections from your `pyproject.toml`).
+* The current Ruff version (`ruff --version`).
-->
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index bf88c0dce9..0a0f8854d8 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -56,7 +56,7 @@ jobs:
cargo-test:
strategy:
matrix:
- os: [ ubuntu-latest, windows-latest ]
+ os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
name: "cargo test | ${{ matrix.os }}"
steps:
@@ -95,8 +95,8 @@ jobs:
- run: ./scripts/add_rule.py --name DoTheThing --code PLC999 --linter pylint
- run: cargo check
- run: |
- ./scripts/add_plugin.py test --url https://pypi.org/project/-test/0.1.0/ --prefix TST
- ./scripts/add_rule.py --name FirstRule --code TST001 --linter test
+ ./scripts/add_plugin.py test --url https://pypi.org/project/-test/0.1.0/ --prefix TST
+ ./scripts/add_rule.py --name FirstRule --code TST001 --linter test
- run: cargo check
maturin-build:
@@ -118,7 +118,7 @@ jobs:
name: "spell check"
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v3
- - uses: crate-ci/typos@master
- with:
- files: .
+ - uses: actions/checkout@v3
+ - uses: crate-ci/typos@master
+ with:
+ files: .
diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml
index 71021e8287..f3e48d468f 100644
--- a/.github/workflows/docs.yaml
+++ b/.github/workflows/docs.yaml
@@ -6,10 +6,9 @@ on:
- README.md
- mkdocs.template.yml
- .github/workflows/docs.yaml
- branches: [ main ]
+ branches: [main]
workflow_dispatch:
-
jobs:
mkdocs:
runs-on: ubuntu-latest
diff --git a/.github/workflows/playground.yaml b/.github/workflows/playground.yaml
index e4fc5efa3f..02eea99203 100644
--- a/.github/workflows/playground.yaml
+++ b/.github/workflows/playground.yaml
@@ -15,7 +15,7 @@ jobs:
publish:
runs-on: ubuntu-latest
env:
- CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
+ CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
steps:
- uses: actions/checkout@v3
- name: "Install Rust toolchain"
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 058892fc1a..9b012f90f0 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,16 +1,19 @@
repos:
- - repo: https://github.com/charliermarsh/ruff-pre-commit
- rev: v0.0.240
- hooks:
- - id: ruff
- args: [--fix]
- exclude: ^resources
-
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.10.1
hooks:
- id: validate-pyproject
+ - repo: https://github.com/igorshubovych/markdownlint-cli
+ rev: v0.33.0
+ hooks:
+ - id: markdownlint-fix
+ args:
+ - --disable
+ - MD013 # line-length
+ - MD033 # no-inline-html
+ - --
+
- repo: local
hooks:
- id: cargo-fmt
@@ -23,9 +26,19 @@ repos:
entry: cargo clippy --workspace --all-targets --all-features -- -D warnings -W clippy::pedantic
language: rust
pass_filenames: false
+ - id: ruff
+ name: ruff
+ entry: cargo run -- --no-cache --fix
+ language: rust
+ types_or: [python, pyi]
+ require_serial: true
+ exclude: ^resources
- id: dev-generate-all
name: dev-generate-all
entry: cargo dev generate-all
language: rust
pass_filenames: false
exclude: target
+
+ci:
+ skip: [cargo-fmt, clippy, dev-generate-all]
diff --git a/BREAKING_CHANGES.md b/BREAKING_CHANGES.md
index 3dbd91a9a1..532583c80f 100644
--- a/BREAKING_CHANGES.md
+++ b/BREAKING_CHANGES.md
@@ -43,16 +43,18 @@ upgrades.
`--explain`, `--clean`, and `--generate-shell-completion` are now implemented as subcommands:
- ruff . # Still works! And will always work.
- ruff check . # New! Also works.
+```console
+ruff . # Still works! And will always work.
+ruff check . # New! Also works.
- ruff --explain E402 # Still works.
- ruff rule E402 # New! Also works. (And preferred.)
+ruff --explain E402 # Still works.
+ruff rule E402 # New! Also works. (And preferred.)
- # Oops! The command has to come first.
- ruff --format json --explain E402 # No longer works.
- ruff --explain E402 --format json # Still works!
- ruff rule E402 --format json # Works! (And preferred.)
+# Oops! The command has to come first.
+ruff --format json --explain E402 # No longer works.
+ruff --explain E402 --format json # Still works!
+ruff rule E402 --format json # Works! (And preferred.)
+```
This change is largely backwards compatible -- most users should experience
no change in behavior. However, please note the following exceptions:
@@ -60,7 +62,9 @@ no change in behavior. However, please note the following exceptions:
* Subcommands will now fail when invoked with unsupported arguments, instead
of silently ignoring them. For example, the following will now fail:
- ruff --clean --respect-gitignore
+ ```console
+ ruff --clean --respect-gitignore
+ ```
(the `clean` command doesn't support `--respect-gitignore`.)
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index d809ca6b1e..71074c4faa 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -106,7 +106,7 @@ Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
-standards, including sustained inappropriate behavior, harassment of an
+standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
@@ -115,14 +115,12 @@ the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
-version 2.0, available at
-https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
+version 2.0, available [here](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html).
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
-For answers to common questions about this code of conduct, see the FAQ at
-https://www.contributor-covenant.org/faq. Translations are available at
-https://www.contributor-covenant.org/translations.
+For answers to common questions about this code of conduct, see the [FAQ](https://www.contributor-covenant.org/faq).
+Translations are available [here](https://www.contributor-covenant.org/translations).
diff --git a/README.md b/README.md
index 67bbb2e5c7..421d08c815 100644
--- a/README.md
+++ b/README.md
@@ -24,16 +24,16 @@ An extremely fast Python linter, written in Rust.
Linting the CPython codebase from scratch.
-- ⚡️ 10-100x faster than existing linters
-- 🐍 Installable via `pip`
-- 🤝 Python 3.11 compatibility
-- 🛠️ `pyproject.toml` support
-- 📦 Built-in caching, to avoid re-analyzing unchanged files
-- 🔧 Autofix support, for automatic error correction (e.g., automatically remove unused imports)
-- ⚖️ [Near-parity](#how-does-ruff-compare-to-flake8) with the built-in Flake8 rule set
-- 🔌 Native re-implementations of dozens of Flake8 plugins, like [flake8-bugbear](https://pypi.org/project/flake8-bugbear/)
-- ⌨️ First-party editor integrations for [VS Code](https://github.com/charliermarsh/ruff-vscode) and [more](https://github.com/charliermarsh/ruff-lsp)
-- 🌎 Monorepo-friendly, with [hierarchical and cascading configuration](#pyprojecttoml-discovery)
+* ⚡️ 10-100x faster than existing linters
+* 🐍 Installable via `pip`
+* 🤝 Python 3.11 compatibility
+* 🛠️ `pyproject.toml` support
+* 📦 Built-in caching, to avoid re-analyzing unchanged files
+* 🔧 Autofix support, for automatic error correction (e.g., automatically remove unused imports)
+* ⚖️ [Near-parity](#how-does-ruff-compare-to-flake8) with the built-in Flake8 rule set
+* 🔌 Native re-implementations of dozens of Flake8 plugins, like [flake8-bugbear](https://pypi.org/project/flake8-bugbear/)
+* ⌨️ First-party editor integrations for [VS Code](https://github.com/charliermarsh/ruff-vscode) and [more](https://github.com/charliermarsh/ruff-lsp)
+* 🌎 Monorepo-friendly, with [hierarchical and cascading configuration](#pyprojecttoml-discovery)
Ruff aims to be orders of magnitude faster than alternative tools while integrating more
functionality behind a single, common interface.
@@ -46,32 +46,32 @@ 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:
-- [pandas](https://github.com/pandas-dev/pandas)
-- [FastAPI](https://github.com/tiangolo/fastapi)
-- [Apache Airflow](https://github.com/apache/airflow)
-- [SciPy](https://github.com/scipy/scipy)
-- [Bokeh](https://github.com/bokeh/bokeh)
-- [Zulip](https://github.com/zulip/zulip)
-- [Pydantic](https://github.com/pydantic/pydantic)
-- [Dagster](https://github.com/dagster-io/dagster)
-- [Dagger](https://github.com/dagger/dagger)
-- [Sphinx](https://github.com/sphinx-doc/sphinx)
-- [Hatch](https://github.com/pypa/hatch)
-- [Jupyter](https://github.com/jupyter-server/jupyter_server)
-- [Great Expectations](https://github.com/great-expectations/great_expectations)
-- [Polars](https://github.com/pola-rs/polars)
-- [Ibis](https://github.com/ibis-project/ibis)
-- [Synapse (Matrix)](https://github.com/matrix-org/synapse)
-- [SnowCLI (Snowflake)](https://github.com/Snowflake-Labs/snowcli)
-- [Saleor](https://github.com/saleor/saleor)
-- [OpenBB](https://github.com/OpenBB-finance/OpenBBTerminal)
-- [Home Assistant](https://github.com/home-assistant/core)
-- [Cryptography (PyCA)](https://github.com/pyca/cryptography)
-- [cibuildwheel (PyPA)](https://github.com/pypa/cibuildwheel)
-- [build (PyPA)](https://github.com/pypa/build)
-- [Babel](https://github.com/python-babel/babel)
-- [featuretools](https://github.com/alteryx/featuretools)
-- [meson-python](https://github.com/mesonbuild/meson-python)
+* [pandas](https://github.com/pandas-dev/pandas)
+* [FastAPI](https://github.com/tiangolo/fastapi)
+* [Apache Airflow](https://github.com/apache/airflow)
+* [SciPy](https://github.com/scipy/scipy)
+* [Bokeh](https://github.com/bokeh/bokeh)
+* [Zulip](https://github.com/zulip/zulip)
+* [Pydantic](https://github.com/pydantic/pydantic)
+* [Dagster](https://github.com/dagster-io/dagster)
+* [Dagger](https://github.com/dagger/dagger)
+* [Sphinx](https://github.com/sphinx-doc/sphinx)
+* [Hatch](https://github.com/pypa/hatch)
+* [Jupyter](https://github.com/jupyter-server/jupyter_server)
+* [Great Expectations](https://github.com/great-expectations/great_expectations)
+* [Polars](https://github.com/pola-rs/polars)
+* [Ibis](https://github.com/ibis-project/ibis)
+* [Synapse (Matrix)](https://github.com/matrix-org/synapse)
+* [SnowCLI (Snowflake)](https://github.com/Snowflake-Labs/snowcli)
+* [Saleor](https://github.com/saleor/saleor)
+* [OpenBB](https://github.com/OpenBB-finance/OpenBBTerminal)
+* [Home Assistant](https://github.com/home-assistant/core)
+* [Cryptography (PyCA)](https://github.com/pyca/cryptography)
+* [cibuildwheel (PyPA)](https://github.com/pypa/cibuildwheel)
+* [build (PyPA)](https://github.com/pypa/build)
+* [Babel](https://github.com/python-babel/babel)
+* [featuretools](https://github.com/alteryx/featuretools)
+* [meson-python](https://github.com/mesonbuild/meson-python)
Read the [launch blog post](https://notes.crmarsh.com/python-tooling-could-be-much-much-faster) or
the most recent [project update](https://notes.crmarsh.com/ruff-the-first-200-releases).
@@ -89,7 +89,7 @@ co-creator of [GraphQL](https://graphql.org/):
> Why is Ruff a gamechanger? Primarily because it is nearly 1000x faster. Literally. Not a typo. On
> our largest module (dagster itself, 250k LOC) pylint takes about 2.5 minutes, parallelized across 4
-> cores on my M1. Running ruff against our *entire* codebase takes .4 seconds.
+> cores on my M1. Running ruff against our _entire_ codebase takes .4 seconds.
[**Bryan Van de Ven**](https://github.com/bokeh/bokeh/pull/12605), co-creator
of [Bokeh](https://github.com/bokeh/bokeh/), original author
@@ -340,13 +340,13 @@ for the pydocstyle plugin.
If you're wondering how to configure Ruff, here are some **recommended guidelines**:
-- Prefer `select` and `ignore` over `extend-select` and `extend-ignore`, to make your rule set
+* Prefer `select` and `ignore` over `extend-select` and `extend-ignore`, to make your rule set
explicit.
-- Use `ALL` with discretion. Enabling `ALL` will implicitly enable new rules whenever you upgrade.
-- Start with a small set of rules (`select = ["E", "F"]`) and add a category at-a-time. For example,
+* Use `ALL` with discretion. Enabling `ALL` will implicitly enable new rules whenever you upgrade.
+* Start with a small set of rules (`select = ["E", "F"]`) and add a category at-a-time. For example,
you might consider expanding to `select = ["E", "F", "B"]` to enable the popular flake8-bugbear
extension.
-- By default, Ruff's autofix is aggressive. If you find that it's too aggressive for your liking,
+* By default, Ruff's autofix is aggressive. If you find that it's too aggressive for your liking,
consider turning off autofix for specific rules or categories (see: [FAQ](#ruff-tried-to-fix-something-but-it-broke-my-code-what-should-i-do)).
As an alternative to `pyproject.toml`, Ruff will also respect a `ruff.toml` file, which implements
@@ -383,7 +383,8 @@ ruff path/to/code/ --select F401 --select F403 --quiet
See `ruff help` for more on Ruff's top-level commands:
-```
+
+```text
Ruff: An extremely fast Python linter.
Usage: ruff [OPTIONS]
@@ -406,12 +407,14 @@ Log levels:
For help with a specific command, see: `ruff help `.
```
+
Or `ruff help check` for more on the linting command:
-```
+
+```text
Run Ruff on the given files or directories (default)
Usage: ruff check [OPTIONS] [FILES]...
@@ -480,6 +483,7 @@ Log levels:
-q, --quiet Print lint violations, but nothing else
-s, --silent Disable all logging (but still exit with status code "1" upon detecting lint violations)
```
+
### `pyproject.toml` discovery
@@ -639,6 +643,7 @@ The 🛠 emoji indicates that a rule is automatically fixable by the `--fix` com
+
### Pyflakes (F)
For more, see [Pyflakes](https://pypi.org/project/pyflakes/) on PyPI.
@@ -694,6 +699,7 @@ For more, see [Pyflakes](https://pypi.org/project/pyflakes/) on PyPI.
For more, see [pycodestyle](https://pypi.org/project/pycodestyle/) on PyPI.
#### Error (E)
+
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| E101 | mixed-spaces-and-tabs | Indentation contains mixed spaces and tabs | |
@@ -714,6 +720,7 @@ For more, see [pycodestyle](https://pypi.org/project/pycodestyle/) on PyPI.
| E999 | syntax-error | SyntaxError: {message} | |
#### Warning (W)
+
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| W292 | no-new-line-at-end-of-file | No newline at end of file | 🛠 |
@@ -1315,12 +1322,14 @@ For more, see [pygrep-hooks](https://github.com/pre-commit/pygrep-hooks) on GitH
For more, see [Pylint](https://pypi.org/project/pylint/) on PyPI.
#### Convention (PLC)
+
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| PLC0414 | useless-import-alias | Import alias does not rename original package | 🛠 |
| PLC3002 | unnecessary-direct-lambda-call | Lambda expression called directly. Execute the expression inline instead. | |
#### Error (PLE)
+
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| PLE0117 | nonlocal-without-binding | Nonlocal name `{name}` found without binding | |
@@ -1330,6 +1339,7 @@ For more, see [Pylint](https://pypi.org/project/pylint/) on PyPI.
| PLE1142 | await-outside-async | `await` should be used within an async function | |
#### Refactor (PLR)
+
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| PLR0133 | constant-comparison | Two constants compared in a comparison, consider replacing `{left_constant} {op} {right_constant}` | |
@@ -1342,6 +1352,7 @@ For more, see [Pylint](https://pypi.org/project/pylint/) on PyPI.
| PLR2004 | magic-value-comparison | Magic value used in comparison, consider replacing {value} with a constant variable | |
#### Warning (PLW)
+
| Code | Name | Message | Fix |
| ---- | ---- | ------- | --- |
| PLW0120 | useless-else-on-loop | Else clause on loop without a break statement, remove the else and de-indent all the code inside it | |
@@ -1402,7 +1413,7 @@ For more, see [flake8-self](https://pypi.org/project/flake8-self/) on PyPI.
Download the [Ruff VS Code extension](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff),
which supports autofix actions, import sorting, and more.
-
+
### Language Server Protocol (Official)
@@ -1547,13 +1558,14 @@ let g:ale_fixers = {
```yaml
tools:
python-ruff: &python-ruff
- lint-command: 'ruff --config ~/myconfigs/linters/ruff.toml --quiet ${INPUT}'
+ lint-command: "ruff --config ~/myconfigs/linters/ruff.toml --quiet ${INPUT}"
lint-stdin: true
lint-formats:
- - '%f:%l:%c: %m'
- format-command: 'ruff --stdin-filename ${INPUT} --config ~/myconfigs/linters/ruff.toml --fix --exit-zero --quiet -'
+ - "%f:%l:%c: %m"
+ format-command: "ruff --stdin-filename ${INPUT} --config ~/myconfigs/linters/ruff.toml --fix --exit-zero --quiet -"
format-stdin: true
```
+
@@ -1570,8 +1582,8 @@ null_ls.setup({
}
})
```
-
+
### PyCharm (External Tool)
@@ -1644,47 +1656,47 @@ implements all of the `F` rules (which originate from Pyflakes), along with a su
Ruff also re-implements some of the most popular Flake8 plugins and related code quality tools
natively, including:
-- [autoflake](https://pypi.org/project/autoflake/) ([#1647](https://github.com/charliermarsh/ruff/issues/1647))
-- [eradicate](https://pypi.org/project/eradicate/)
-- [flake8-2020](https://pypi.org/project/flake8-2020/)
-- [flake8-annotations](https://pypi.org/project/flake8-annotations/)
-- [flake8-bandit](https://pypi.org/project/flake8-bandit/) ([#1646](https://github.com/charliermarsh/ruff/issues/1646))
-- [flake8-blind-except](https://pypi.org/project/flake8-blind-except/)
-- [flake8-boolean-trap](https://pypi.org/project/flake8-boolean-trap/)
-- [flake8-bugbear](https://pypi.org/project/flake8-bugbear/)
-- [flake8-builtins](https://pypi.org/project/flake8-builtins/)
-- [flake8-commas](https://pypi.org/project/flake8-commas/)
-- [flake8-comprehensions](https://pypi.org/project/flake8-comprehensions/)
-- [flake8-datetimez](https://pypi.org/project/flake8-datetimez/)
-- [flake8-debugger](https://pypi.org/project/flake8-debugger/)
-- [flake8-docstrings](https://pypi.org/project/flake8-docstrings/)
-- [flake8-eradicate](https://pypi.org/project/flake8-eradicate/)
-- [flake8-errmsg](https://pypi.org/project/flake8-errmsg/)
-- [flake8-executable](https://pypi.org/project/flake8-executable/)
-- [flake8-implicit-str-concat](https://pypi.org/project/flake8-implicit-str-concat/)
-- [flake8-import-conventions](https://github.com/joaopalmeiro/flake8-import-conventions)
-- [flake8-logging-format](https://pypi.org/project/flake8-logging-format/)
-- [flake8-no-pep420](https://pypi.org/project/flake8-no-pep420)
-- [flake8-pie](https://pypi.org/project/flake8-pie/)
-- [flake8-print](https://pypi.org/project/flake8-print/)
-- [flake8-pytest-style](https://pypi.org/project/flake8-pytest-style/)
-- [flake8-quotes](https://pypi.org/project/flake8-quotes/)
-- [flake8-raise](https://pypi.org/project/flake8-raise/)
-- [flake8-return](https://pypi.org/project/flake8-return/)
-- [flake8-self](https://pypi.org/project/flake8-self/)
-- [flake8-simplify](https://pypi.org/project/flake8-simplify/) ([#998](https://github.com/charliermarsh/ruff/issues/998))
-- [flake8-super](https://pypi.org/project/flake8-super/)
-- [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
-- [flake8-type-checking](https://pypi.org/project/flake8-type-checking/)
-- [flake8-use-pathlib](https://pypi.org/project/flake8-use-pathlib/)
-- [isort](https://pypi.org/project/isort/)
-- [mccabe](https://pypi.org/project/mccabe/)
-- [pandas-vet](https://pypi.org/project/pandas-vet/)
-- [pep8-naming](https://pypi.org/project/pep8-naming/)
-- [pydocstyle](https://pypi.org/project/pydocstyle/)
-- [pygrep-hooks](https://github.com/pre-commit/pygrep-hooks) ([#980](https://github.com/charliermarsh/ruff/issues/980))
-- [pyupgrade](https://pypi.org/project/pyupgrade/) ([#827](https://github.com/charliermarsh/ruff/issues/827))
-- [yesqa](https://github.com/asottile/yesqa)
+* [autoflake](https://pypi.org/project/autoflake/) ([#1647](https://github.com/charliermarsh/ruff/issues/1647))
+* [eradicate](https://pypi.org/project/eradicate/)
+* [flake8-2020](https://pypi.org/project/flake8-2020/)
+* [flake8-annotations](https://pypi.org/project/flake8-annotations/)
+* [flake8-bandit](https://pypi.org/project/flake8-bandit/) ([#1646](https://github.com/charliermarsh/ruff/issues/1646))
+* [flake8-blind-except](https://pypi.org/project/flake8-blind-except/)
+* [flake8-boolean-trap](https://pypi.org/project/flake8-boolean-trap/)
+* [flake8-bugbear](https://pypi.org/project/flake8-bugbear/)
+* [flake8-builtins](https://pypi.org/project/flake8-builtins/)
+* [flake8-commas](https://pypi.org/project/flake8-commas/)
+* [flake8-comprehensions](https://pypi.org/project/flake8-comprehensions/)
+* [flake8-datetimez](https://pypi.org/project/flake8-datetimez/)
+* [flake8-debugger](https://pypi.org/project/flake8-debugger/)
+* [flake8-docstrings](https://pypi.org/project/flake8-docstrings/)
+* [flake8-eradicate](https://pypi.org/project/flake8-eradicate/)
+* [flake8-errmsg](https://pypi.org/project/flake8-errmsg/)
+* [flake8-executable](https://pypi.org/project/flake8-executable/)
+* [flake8-implicit-str-concat](https://pypi.org/project/flake8-implicit-str-concat/)
+* [flake8-import-conventions](https://github.com/joaopalmeiro/flake8-import-conventions)
+* [flake8-logging-format](https://pypi.org/project/flake8-logging-format/)
+* [flake8-no-pep420](https://pypi.org/project/flake8-no-pep420)
+* [flake8-pie](https://pypi.org/project/flake8-pie/)
+* [flake8-print](https://pypi.org/project/flake8-print/)
+* [flake8-pytest-style](https://pypi.org/project/flake8-pytest-style/)
+* [flake8-quotes](https://pypi.org/project/flake8-quotes/)
+* [flake8-raise](https://pypi.org/project/flake8-raise/)
+* [flake8-return](https://pypi.org/project/flake8-return/)
+* [flake8-self](https://pypi.org/project/flake8-self/)
+* [flake8-simplify](https://pypi.org/project/flake8-simplify/) ([#998](https://github.com/charliermarsh/ruff/issues/998))
+* [flake8-super](https://pypi.org/project/flake8-super/)
+* [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
+* [flake8-type-checking](https://pypi.org/project/flake8-type-checking/)
+* [flake8-use-pathlib](https://pypi.org/project/flake8-use-pathlib/)
+* [isort](https://pypi.org/project/isort/)
+* [mccabe](https://pypi.org/project/mccabe/)
+* [pandas-vet](https://pypi.org/project/pandas-vet/)
+* [pep8-naming](https://pypi.org/project/pep8-naming/)
+* [pydocstyle](https://pypi.org/project/pydocstyle/)
+* [pygrep-hooks](https://github.com/pre-commit/pygrep-hooks) ([#980](https://github.com/charliermarsh/ruff/issues/980))
+* [pyupgrade](https://pypi.org/project/pyupgrade/) ([#827](https://github.com/charliermarsh/ruff/issues/827))
+* [yesqa](https://github.com/asottile/yesqa)
Note that, in some cases, Ruff uses different rule codes and prefixes than would be found in the
originating Flake8 plugins. For example, Ruff uses `TID252` to represent the `I252` rule from
@@ -1700,8 +1712,8 @@ Beyond the rule set, Ruff suffers from the following limitations vis-à-vis Flak
There are a few other minor incompatibilities between Ruff and the originating Flake8 plugins:
-- Ruff doesn't implement all the "opinionated" lint rules from flake8-bugbear.
-- Depending on your project structure, Ruff and isort can differ in their detection of first-party
+* Ruff doesn't implement all the "opinionated" lint rules from flake8-bugbear.
+* Depending on your project structure, Ruff and isort can differ in their detection of first-party
code. (This is often solved by modifying the `src` property, e.g., to `src = ["src"]`, if your
code is nested in a `src` directory.)
@@ -1743,41 +1755,41 @@ feedback on type errors.
Today, Ruff can be used to replace Flake8 when used with any of the following plugins:
-- [flake8-2020](https://pypi.org/project/flake8-2020/)
-- [flake8-annotations](https://pypi.org/project/flake8-annotations/)
-- [flake8-bandit](https://pypi.org/project/flake8-bandit/) ([#1646](https://github.com/charliermarsh/ruff/issues/1646))
-- [flake8-blind-except](https://pypi.org/project/flake8-blind-except/)
-- [flake8-boolean-trap](https://pypi.org/project/flake8-boolean-trap/)
-- [flake8-bugbear](https://pypi.org/project/flake8-bugbear/)
-- [flake8-builtins](https://pypi.org/project/flake8-builtins/)
-- [flake8-commas](https://pypi.org/project/flake8-commas/)
-- [flake8-comprehensions](https://pypi.org/project/flake8-comprehensions/)
-- [flake8-datetimez](https://pypi.org/project/flake8-datetimez/)
-- [flake8-debugger](https://pypi.org/project/flake8-debugger/)
-- [flake8-docstrings](https://pypi.org/project/flake8-docstrings/)
-- [flake8-eradicate](https://pypi.org/project/flake8-eradicate/)
-- [flake8-errmsg](https://pypi.org/project/flake8-errmsg/)
-- [flake8-executable](https://pypi.org/project/flake8-executable/)
-- [flake8-implicit-str-concat](https://pypi.org/project/flake8-implicit-str-concat/)
-- [flake8-import-conventions](https://github.com/joaopalmeiro/flake8-import-conventions)
-- [flake8-logging-format](https://pypi.org/project/flake8-logging-format/)
-- [flake8-no-pep420](https://pypi.org/project/flake8-no-pep420)
-- [flake8-pie](https://pypi.org/project/flake8-pie/)
-- [flake8-print](https://pypi.org/project/flake8-print/)
-- [flake8-pytest-style](https://pypi.org/project/flake8-pytest-style/)
-- [flake8-quotes](https://pypi.org/project/flake8-quotes/)
-- [flake8-raise](https://pypi.org/project/flake8-raise/)
-- [flake8-return](https://pypi.org/project/flake8-return/)
-- [flake8-self](https://pypi.org/project/flake8-self/)
-- [flake8-simplify](https://pypi.org/project/flake8-simplify/) ([#998](https://github.com/charliermarsh/ruff/issues/998))
-- [flake8-super](https://pypi.org/project/flake8-super/)
-- [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
-- [flake8-type-checking](https://pypi.org/project/flake8-type-checking/)
-- [flake8-use-pathlib](https://pypi.org/project/flake8-use-pathlib/)
-- [mccabe](https://pypi.org/project/mccabe/)
-- [pandas-vet](https://pypi.org/project/pandas-vet/)
-- [pep8-naming](https://pypi.org/project/pep8-naming/)
-- [pydocstyle](https://pypi.org/project/pydocstyle/)
+* [flake8-2020](https://pypi.org/project/flake8-2020/)
+* [flake8-annotations](https://pypi.org/project/flake8-annotations/)
+* [flake8-bandit](https://pypi.org/project/flake8-bandit/) ([#1646](https://github.com/charliermarsh/ruff/issues/1646))
+* [flake8-blind-except](https://pypi.org/project/flake8-blind-except/)
+* [flake8-boolean-trap](https://pypi.org/project/flake8-boolean-trap/)
+* [flake8-bugbear](https://pypi.org/project/flake8-bugbear/)
+* [flake8-builtins](https://pypi.org/project/flake8-builtins/)
+* [flake8-commas](https://pypi.org/project/flake8-commas/)
+* [flake8-comprehensions](https://pypi.org/project/flake8-comprehensions/)
+* [flake8-datetimez](https://pypi.org/project/flake8-datetimez/)
+* [flake8-debugger](https://pypi.org/project/flake8-debugger/)
+* [flake8-docstrings](https://pypi.org/project/flake8-docstrings/)
+* [flake8-eradicate](https://pypi.org/project/flake8-eradicate/)
+* [flake8-errmsg](https://pypi.org/project/flake8-errmsg/)
+* [flake8-executable](https://pypi.org/project/flake8-executable/)
+* [flake8-implicit-str-concat](https://pypi.org/project/flake8-implicit-str-concat/)
+* [flake8-import-conventions](https://github.com/joaopalmeiro/flake8-import-conventions)
+* [flake8-logging-format](https://pypi.org/project/flake8-logging-format/)
+* [flake8-no-pep420](https://pypi.org/project/flake8-no-pep420)
+* [flake8-pie](https://pypi.org/project/flake8-pie/)
+* [flake8-print](https://pypi.org/project/flake8-print/)
+* [flake8-pytest-style](https://pypi.org/project/flake8-pytest-style/)
+* [flake8-quotes](https://pypi.org/project/flake8-quotes/)
+* [flake8-raise](https://pypi.org/project/flake8-raise/)
+* [flake8-return](https://pypi.org/project/flake8-return/)
+* [flake8-self](https://pypi.org/project/flake8-self/)
+* [flake8-simplify](https://pypi.org/project/flake8-simplify/) ([#998](https://github.com/charliermarsh/ruff/issues/998))
+* [flake8-super](https://pypi.org/project/flake8-super/)
+* [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
+* [flake8-type-checking](https://pypi.org/project/flake8-type-checking/)
+* [flake8-use-pathlib](https://pypi.org/project/flake8-use-pathlib/)
+* [mccabe](https://pypi.org/project/mccabe/)
+* [pandas-vet](https://pypi.org/project/pandas-vet/)
+* [pep8-naming](https://pypi.org/project/pep8-naming/)
+* [pydocstyle](https://pypi.org/project/pydocstyle/)
Ruff can also replace [isort](https://pypi.org/project/isort/),
[yesqa](https://github.com/asottile/yesqa), [eradicate](https://pypi.org/project/eradicate/),
@@ -2084,6 +2096,7 @@ Benchmark 1: find . -type f -name "*.py" | xargs -P 0 pyupgrade --py311-plus
+
#### [`allowed-confusables`](#allowed-confusables)
A list of allowed "confusable" Unicode characters to ignore when
@@ -2174,10 +2187,10 @@ A list of file patterns to exclude from linting.
Exclusions are based on globs, and can be either:
-- Single-path patterns, like `.mypy_cache` (to exclude any directory
+* Single-path patterns, like `.mypy_cache` (to exclude any directory
named `.mypy_cache` in the tree), `foo.py` (to exclude any file named
`foo.py`), or `foo_*.py` (to exclude any file matching `foo_*.py` ).
-- Relative patterns, like `directory/foo.py` (to exclude that specific
+* Relative patterns, like `directory/foo.py` (to exclude that specific
file) or `directory/*.py` (to exclude any Python files in
`directory`). Note that these paths are relative to the project root
(e.g., the directory containing your `pyproject.toml`).
@@ -2233,10 +2246,10 @@ specified by `exclude`.
Exclusions are based on globs, and can be either:
-- Single-path patterns, like `.mypy_cache` (to exclude any directory
+* Single-path patterns, like `.mypy_cache` (to exclude any directory
named `.mypy_cache` in the tree), `foo.py` (to exclude any file named
`foo.py`), or `foo_*.py` (to exclude any file matching `foo_*.py` ).
-- Relative patterns, like `directory/foo.py` (to exclude that specific
+* Relative patterns, like `directory/foo.py` (to exclude that specific
file) or `directory/*.py` (to exclude any Python files in
`directory`). Note that these paths are relative to the project root
(e.g., the directory containing your `pyproject.toml`).
@@ -2810,8 +2823,8 @@ suppress-dummy-args = true
Whether to suppress `ANN200`-level violations for functions that meet
either of the following criteria:
-- Contain no `return` statement.
-- Explicit `return` statement(s) all return `None` (explicitly or
+* Contain no `return` statement.
+* Explicit `return` statement(s) all return `None` (explicitly or
implicitly).
**Default value**: `false`
@@ -3063,10 +3076,11 @@ mark-parentheses = true
Expected type for multiple argument names in `@pytest.mark.parametrize`.
The following values are supported:
+
* `csv` — a comma-separated list, e.g.
`@pytest.mark.parametrize('name1,name2', ...)`
-* `tuple` (default) — e.g. `@pytest.mark.parametrize(('name1', 'name2'),
- ...)`
+* `tuple` (default) — e.g.
+ `@pytest.mark.parametrize(('name1', 'name2'), ...)`
* `list` — e.g. `@pytest.mark.parametrize(['name1', 'name2'], ...)`
**Default value**: `tuple`
@@ -3086,10 +3100,11 @@ parametrize-names-type = "list"
Expected type for each row of values in `@pytest.mark.parametrize` in
case of multiple parameters. The following values are supported:
-* `tuple` (default) — e.g. `@pytest.mark.parametrize(('name1', 'name2'),
- [(1, 2), (3, 4)])`
-* `list` — e.g. `@pytest.mark.parametrize(('name1', 'name2'), [[1, 2],
- [3, 4]])`
+
+* `tuple` (default) — e.g.
+ `@pytest.mark.parametrize(('name1', 'name2'), [(1, 2), (3, 4)])`
+* `list` — e.g.
+ `@pytest.mark.parametrize(('name1', 'name2'), [[1, 2], [3, 4]])`
**Default value**: `tuple`
@@ -3108,6 +3123,7 @@ parametrize-values-row-type = "list"
Expected type for the list of values rows in `@pytest.mark.parametrize`.
The following values are supported:
+
* `tuple` — e.g. `@pytest.mark.parametrize('name', (1, 2, 3))`
* `list` (default) — e.g. `@pytest.mark.parametrize('name', [1, 2, 3])`
@@ -3307,7 +3323,7 @@ exempt-modules = ["typing", "typing_extensions"]
Enforce TC001, TC002, and TC003 rules even when valid runtime imports
are present for the same module.
-See: https://github.com/snok/flake8-type-checking#strict.
+See flake8-type-checking's [strict](https://github.com/snok/flake8-type-checking#strict) option.
**Default value**: `false`
diff --git a/playground/README.md b/playground/README.md
index b60817f87d..ffd031b1c5 100644
--- a/playground/README.md
+++ b/playground/README.md
@@ -4,10 +4,10 @@ In-browser playground for Ruff. Available [https://ruff.pages.dev/](https://ruff
## Getting started
-- To build the WASM module, run `wasm-pack build --target web --out-dir playground/src/pkg` from the
+* To build the WASM module, run `wasm-pack build --target web --out-dir playground/src/pkg` from the
root directory.
-- Install TypeScript dependencies with: `npm install`.
-- Start the development server with: `npm run dev`.
+* Install TypeScript dependencies with: `npm install`.
+* Start the development server with: `npm run dev`.
## Implementation
diff --git a/playground/index.html b/playground/index.html
index d116aa23d1..4719d71b9b 100644
--- a/playground/index.html
+++ b/playground/index.html
@@ -1,4 +1,4 @@
-
+
diff --git a/pyproject.toml b/pyproject.toml
index e0cb401107..6523db3ee6 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -9,31 +9,34 @@ build-backend = "maturin"
name = "ruff"
version = "0.0.240"
description = "An extremely fast Python linter, written in Rust."
-authors = [
- { name = "Charlie Marsh", email = "charlie.r.marsh@gmail.com" },
-]
-maintainers = [
- { name = "Charlie Marsh", email = "charlie.r.marsh@gmail.com" },
-]
+authors = [{ name = "Charlie Marsh", email = "charlie.r.marsh@gmail.com" }]
+maintainers = [{ name = "Charlie Marsh", email = "charlie.r.marsh@gmail.com" }]
readme = "README.md"
requires-python = ">=3.7"
license = { file = "LICENSE" }
-keywords = ["automation", "flake8", "pycodestyle", "pyflakes", "pylint", "clippy"]
+keywords = [
+ "automation",
+ "flake8",
+ "pycodestyle",
+ "pyflakes",
+ "pylint",
+ "clippy",
+]
classifiers = [
- "Development Status :: 3 - Alpha",
- "Environment :: Console",
- "Intended Audience :: Developers",
- "License :: OSI Approved :: MIT License",
- "Operating System :: OS Independent",
- "Programming Language :: Python",
- "Programming Language :: Python :: 3.7",
- "Programming Language :: Python :: 3.8",
- "Programming Language :: Python :: 3.9",
- "Programming Language :: Python :: 3.10",
- "Programming Language :: Python :: 3.11",
- "Programming Language :: Python :: 3 :: Only",
- "Topic :: Software Development :: Libraries :: Python Modules",
- "Topic :: Software Development :: Quality Assurance",
+ "Development Status :: 3 - Alpha",
+ "Environment :: Console",
+ "Intended Audience :: Developers",
+ "License :: OSI Approved :: MIT License",
+ "Operating System :: OS Independent",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 3.7",
+ "Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3 :: Only",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+ "Topic :: Software Development :: Quality Assurance",
]
urls = { repository = "https://github.com/charliermarsh/ruff" }
@@ -42,3 +45,6 @@ bindings = "bin"
manifest-path = "ruff_cli/Cargo.toml"
python-source = "python"
strip = true
+
+[tool.ruff.per-file-ignores]
+"setup.py" = ["INP001"]
diff --git a/python/ruff/__main__.py b/python/ruff/__main__.py
index 947caea0a9..1c30d2b596 100644
--- a/python/ruff/__main__.py
+++ b/python/ruff/__main__.py
@@ -1,7 +1,8 @@
import os
import sys
import sysconfig
+from pathlib import Path
if __name__ == "__main__":
- ruff = os.path.join(sysconfig.get_path("scripts"), "ruff")
+ ruff = Path(sysconfig.get_path("scripts")) / "ruff"
sys.exit(os.spawnv(os.P_WAIT, ruff, [ruff, *sys.argv[1:]]))
diff --git a/resources/test/project/README.md b/resources/test/project/README.md
index e985823b33..e5993e537d 100644
--- a/resources/test/project/README.md
+++ b/resources/test/project/README.md
@@ -7,7 +7,7 @@ behaviors.
Running from the repo root should pick up and enforce the appropriate settings for each package:
-```
+```console
∴ cargo run resources/test/project/
resources/test/project/examples/.dotfiles/script.py:1:1: I001 Import block is un-sorted or un-formatted
resources/test/project/examples/.dotfiles/script.py:1:8: F401 `numpy` imported but unused
@@ -22,7 +22,7 @@ Found 7 errors.
Running from the project directory itself should exhibit the same behavior:
-```
+```console
∴ (cd resources/test/project/ && cargo run .)
examples/.dotfiles/script.py:1:1: I001 Import block is un-sorted or un-formatted
examples/.dotfiles/script.py:1:8: F401 `numpy` imported but unused
@@ -38,7 +38,7 @@ Found 7 errors.
Running from the sub-package directory should exhibit the same behavior, but omit the top-level
files:
-```
+```console
∴ (cd resources/test/project/examples/docs && cargo run .)
docs/file.py:1:1: I001 Import block is un-sorted or un-formatted
docs/file.py:8:5: F841 Local variable `x` is assigned to but never used
@@ -49,7 +49,7 @@ Found 2 errors.
`--config` should force Ruff to use the specified `pyproject.toml` for all files, and resolve
file paths from the current working directory:
-```
+```console
∴ (cargo run -- --config=resources/test/project/pyproject.toml resources/test/project/)
resources/test/project/examples/.dotfiles/script.py:1:8: F401 `numpy` imported but unused
resources/test/project/examples/.dotfiles/script.py:2:17: F401 `app.app_file` imported but unused
@@ -67,7 +67,7 @@ Found 9 errors.
Running from a parent directory should "ignore" the `exclude` (hence, `concepts/file.py` gets
included in the output):
-```
+```console
∴ (cd resources/test/project/examples && cargo run -- --config=docs/ruff.toml .)
docs/docs/concepts/file.py:5:5: F841 Local variable `x` is assigned to but never used
docs/docs/file.py:1:1: I001 Import block is un-sorted or un-formatted
@@ -79,7 +79,7 @@ Found 4 errors.
Passing an excluded directory directly should report errors in the contained files:
-```
+```console
∴ cargo run resources/test/project/examples/excluded/
resources/test/project/examples/excluded/script.py:1:8: F401 `os` imported but unused
Found 1 error.
@@ -88,7 +88,7 @@ Found 1 error.
Unless we `--force-exclude`:
-```
+```console
∴ cargo run resources/test/project/examples/excluded/ --force-exclude
warning: No Python files found under the given path(s)
∴ cargo run resources/test/project/examples/excluded/script.py --force-exclude
diff --git a/ruff.schema.json b/ruff.schema.json
index 303ee250f5..205785d1ca 100644
--- a/ruff.schema.json
+++ b/ruff.schema.json
@@ -40,7 +40,7 @@
]
},
"exclude": {
- "description": "A list of file patterns to exclude from linting.\n\nExclusions are based on globs, and can be either:\n\n- Single-path patterns, like `.mypy_cache` (to exclude any directory named `.mypy_cache` in the tree), `foo.py` (to exclude any file named `foo.py`), or `foo_*.py` (to exclude any file matching `foo_*.py` ). - Relative patterns, like `directory/foo.py` (to exclude that specific file) or `directory/*.py` (to exclude any Python files in `directory`). Note that these paths are relative to the project root (e.g., the directory containing your `pyproject.toml`).\n\nFor more information on the glob syntax, refer to the [`globset` documentation](https://docs.rs/globset/latest/globset/#syntax).\n\nNote that you'll typically want to use [`extend-exclude`](#extend-exclude) to modify the excluded paths.",
+ "description": "A list of file patterns to exclude from linting.\n\nExclusions are based on globs, and can be either:\n\n* Single-path patterns, like `.mypy_cache` (to exclude any directory named `.mypy_cache` in the tree), `foo.py` (to exclude any file named `foo.py`), or `foo_*.py` (to exclude any file matching `foo_*.py` ). * Relative patterns, like `directory/foo.py` (to exclude that specific file) or `directory/*.py` (to exclude any Python files in `directory`). Note that these paths are relative to the project root (e.g., the directory containing your `pyproject.toml`).\n\nFor more information on the glob syntax, refer to the [`globset` documentation](https://docs.rs/globset/latest/globset/#syntax).\n\nNote that you'll typically want to use [`extend-exclude`](#extend-exclude) to modify the excluded paths.",
"type": [
"array",
"null"
@@ -57,7 +57,7 @@
]
},
"extend-exclude": {
- "description": "A list of file patterns to omit from linting, in addition to those specified by `exclude`.\n\nExclusions are based on globs, and can be either:\n\n- Single-path patterns, like `.mypy_cache` (to exclude any directory named `.mypy_cache` in the tree), `foo.py` (to exclude any file named `foo.py`), or `foo_*.py` (to exclude any file matching `foo_*.py` ). - Relative patterns, like `directory/foo.py` (to exclude that specific file) or `directory/*.py` (to exclude any Python files in `directory`). Note that these paths are relative to the project root (e.g., the directory containing your `pyproject.toml`).\n\nFor more information on the glob syntax, refer to the [`globset` documentation](https://docs.rs/globset/latest/globset/#syntax).",
+ "description": "A list of file patterns to omit from linting, in addition to those specified by `exclude`.\n\nExclusions are based on globs, and can be either:\n\n* Single-path patterns, like `.mypy_cache` (to exclude any directory named `.mypy_cache` in the tree), `foo.py` (to exclude any file named `foo.py`), or `foo_*.py` (to exclude any file matching `foo_*.py` ). * Relative patterns, like `directory/foo.py` (to exclude that specific file) or `directory/*.py` (to exclude any Python files in `directory`). Note that these paths are relative to the project root (e.g., the directory containing your `pyproject.toml`).\n\nFor more information on the glob syntax, refer to the [`globset` documentation](https://docs.rs/globset/latest/globset/#syntax).",
"type": [
"array",
"null"
@@ -556,7 +556,7 @@
]
},
"suppress-none-returning": {
- "description": "Whether to suppress `ANN200`-level violations for functions that meet either of the following criteria:\n\n- Contain no `return` statement. - Explicit `return` statement(s) all return `None` (explicitly or implicitly).",
+ "description": "Whether to suppress `ANN200`-level violations for functions that meet either of the following criteria:\n\n* Contain no `return` statement. * Explicit `return` statement(s) all return `None` (explicitly or implicitly).",
"type": [
"boolean",
"null"
@@ -702,7 +702,7 @@
]
},
"parametrize-names-type": {
- "description": "Expected type for multiple argument names in `@pytest.mark.parametrize`. The following values are supported: * `csv` — a comma-separated list, e.g. `@pytest.mark.parametrize('name1,name2', ...)` * `tuple` (default) — e.g. `@pytest.mark.parametrize(('name1', 'name2'), ...)` * `list` — e.g. `@pytest.mark.parametrize(['name1', 'name2'], ...)`",
+ "description": "Expected type for multiple argument names in `@pytest.mark.parametrize`. The following values are supported:\n\n* `csv` — a comma-separated list, e.g. `@pytest.mark.parametrize('name1,name2', ...)` * `tuple` (default) — e.g. `@pytest.mark.parametrize(('name1', 'name2'), ...)` * `list` — e.g. `@pytest.mark.parametrize(['name1', 'name2'], ...)`",
"anyOf": [
{
"$ref": "#/definitions/ParametrizeNameType"
@@ -713,7 +713,7 @@
]
},
"parametrize-values-row-type": {
- "description": "Expected type for each row of values in `@pytest.mark.parametrize` in case of multiple parameters. The following values are supported: * `tuple` (default) — e.g. `@pytest.mark.parametrize(('name1', 'name2'), [(1, 2), (3, 4)])` * `list` — e.g. `@pytest.mark.parametrize(('name1', 'name2'), [[1, 2], [3, 4]])`",
+ "description": "Expected type for each row of values in `@pytest.mark.parametrize` in case of multiple parameters. The following values are supported:\n\n* `tuple` (default) — e.g. `@pytest.mark.parametrize(('name1', 'name2'), [(1, 2), (3, 4)])` * `list` — e.g. `@pytest.mark.parametrize(('name1', 'name2'), [[1, 2], [3, 4]])`",
"anyOf": [
{
"$ref": "#/definitions/ParametrizeValuesRowType"
@@ -724,7 +724,7 @@
]
},
"parametrize-values-type": {
- "description": "Expected type for the list of values rows in `@pytest.mark.parametrize`. The following values are supported: * `tuple` — e.g. `@pytest.mark.parametrize('name', (1, 2, 3))` * `list` (default) — e.g. `@pytest.mark.parametrize('name', [1, 2, 3])`",
+ "description": "Expected type for the list of values rows in `@pytest.mark.parametrize`. The following values are supported:\n\n* `tuple` — e.g. `@pytest.mark.parametrize('name', (1, 2, 3))` * `list` (default) — e.g. `@pytest.mark.parametrize('name', [1, 2, 3])`",
"anyOf": [
{
"$ref": "#/definitions/ParametrizeValuesType"
@@ -844,7 +844,7 @@
}
},
"strict": {
- "description": "Enforce TC001, TC002, and TC003 rules even when valid runtime imports are present for the same module. See: https://github.com/snok/flake8-type-checking#strict.",
+ "description": "Enforce TC001, TC002, and TC003 rules even when valid runtime imports are present for the same module. See flake8-type-checking's [strict](https://github.com/snok/flake8-type-checking#strict) option.",
"type": [
"boolean",
"null"
diff --git a/ruff_dev/src/generate_cli_help.rs b/ruff_dev/src/generate_cli_help.rs
index d137eb47c5..704cde435e 100644
--- a/ruff_dev/src/generate_cli_help.rs
+++ b/ruff_dev/src/generate_cli_help.rs
@@ -4,10 +4,10 @@ use crate::utils::replace_readme_section;
use anyhow::Result;
use std::str;
-const COMMAND_HELP_BEGIN_PRAGMA: &str = "";
+const COMMAND_HELP_BEGIN_PRAGMA: &str = "\n";
const COMMAND_HELP_END_PRAGMA: &str = "";
-const SUBCOMMAND_HELP_BEGIN_PRAGMA: &str = "";
+const SUBCOMMAND_HELP_BEGIN_PRAGMA: &str = "\n";
const SUBCOMMAND_HELP_END_PRAGMA: &str = "";
#[derive(clap::Args)]
@@ -33,12 +33,12 @@ pub fn main(args: &Args) -> Result<()> {
print!("{subcommand_help}");
} else {
replace_readme_section(
- &format!("```\n{command_help}\n```\n"),
+ &format!("```text\n{command_help}\n```\n\n"),
COMMAND_HELP_BEGIN_PRAGMA,
COMMAND_HELP_END_PRAGMA,
)?;
replace_readme_section(
- &format!("```\n{subcommand_help}\n```\n"),
+ &format!("```text\n{subcommand_help}\n```\n\n"),
SUBCOMMAND_HELP_BEGIN_PRAGMA,
SUBCOMMAND_HELP_END_PRAGMA,
)?;
diff --git a/ruff_dev/src/generate_options.rs b/ruff_dev/src/generate_options.rs
index 32d4855f03..7576b096b3 100644
--- a/ruff_dev/src/generate_options.rs
+++ b/ruff_dev/src/generate_options.rs
@@ -7,7 +7,7 @@ use ruff::settings::options_base::{ConfigurationOptions, OptionEntry, OptionFiel
use crate::utils::replace_readme_section;
-const BEGIN_PRAGMA: &str = "";
+const BEGIN_PRAGMA: &str = "\n";
const END_PRAGMA: &str = "";
#[derive(clap::Args)]
diff --git a/ruff_dev/src/generate_rules_table.rs b/ruff_dev/src/generate_rules_table.rs
index b5685f4212..d8c05f8a36 100644
--- a/ruff_dev/src/generate_rules_table.rs
+++ b/ruff_dev/src/generate_rules_table.rs
@@ -7,7 +7,7 @@ use strum::IntoEnumIterator;
use crate::utils::replace_readme_section;
-const TABLE_BEGIN_PRAGMA: &str = "";
+const TABLE_BEGIN_PRAGMA: &str = "\n";
const TABLE_END_PRAGMA: &str = "";
const TOC_BEGIN_PRAGMA: &str = "";
@@ -97,6 +97,7 @@ pub fn main(args: &Args) -> Result<()> {
for LinterCategory(prefix, name, selector) in categories {
table_out.push_str(&format!("#### {name} ({prefix})"));
table_out.push('\n');
+ table_out.push('\n');
generate_table(&mut table_out, selector);
}
} else {
diff --git a/scripts/add_rule.py b/scripts/add_rule.py
index 8e7ee84d02..f5b9223656 100755
--- a/scripts/add_rule.py
+++ b/scripts/add_rule.py
@@ -21,7 +21,7 @@ def snake_case(name: str) -> str:
).lstrip("_")
-def main(*, name: str, code: str, linter: str) -> None:
+def main(*, name: str, code: str, linter: str) -> None: # noqa: PLR0915
"""Generate boilerplate for a new rule."""
# Create a test fixture.
with (ROOT_DIR / "resources/test/fixtures" / dir_name(linter) / f"{code}.py").open(
diff --git a/setup.py b/setup.py
index a8d82c4a0a..115c9e361d 100644
--- a/setup.py
+++ b/setup.py
@@ -9,7 +9,7 @@ Unsupported installation method
===============================
ruff no longer supports installation with `python setup.py install`.
Please use `python -m pip install .` instead.
-"""
+""",
)
sys.exit(1)
diff --git a/src/rules/flake8_annotations/settings.rs b/src/rules/flake8_annotations/settings.rs
index 41340b1592..0789d90066 100644
--- a/src/rules/flake8_annotations/settings.rs
+++ b/src/rules/flake8_annotations/settings.rs
@@ -37,8 +37,8 @@ pub struct Options {
/// Whether to suppress `ANN200`-level violations for functions that meet
/// either of the following criteria:
///
- /// - Contain no `return` statement.
- /// - Explicit `return` statement(s) all return `None` (explicitly or
+ /// * Contain no `return` statement.
+ /// * Explicit `return` statement(s) all return `None` (explicitly or
/// implicitly).
pub suppress_none_returning: Option,
#[option(
diff --git a/src/rules/flake8_pytest_style/settings.rs b/src/rules/flake8_pytest_style/settings.rs
index fb85267dcd..029db61e3d 100644
--- a/src/rules/flake8_pytest_style/settings.rs
+++ b/src/rules/flake8_pytest_style/settings.rs
@@ -47,10 +47,11 @@ pub struct Options {
)]
/// Expected type for multiple argument names in `@pytest.mark.parametrize`.
/// The following values are supported:
+ ///
/// * `csv` — a comma-separated list, e.g.
/// `@pytest.mark.parametrize('name1,name2', ...)`
- /// * `tuple` (default) — e.g. `@pytest.mark.parametrize(('name1', 'name2'),
- /// ...)`
+ /// * `tuple` (default) — e.g.
+ /// `@pytest.mark.parametrize(('name1', 'name2'), ...)`
/// * `list` — e.g. `@pytest.mark.parametrize(['name1', 'name2'], ...)`
pub parametrize_names_type: Option,
#[option(
@@ -60,6 +61,7 @@ pub struct Options {
)]
/// Expected type for the list of values rows in `@pytest.mark.parametrize`.
/// The following values are supported:
+ ///
/// * `tuple` — e.g. `@pytest.mark.parametrize('name', (1, 2, 3))`
/// * `list` (default) — e.g. `@pytest.mark.parametrize('name', [1, 2, 3])`
pub parametrize_values_type: Option,
@@ -70,10 +72,11 @@ pub struct Options {
)]
/// Expected type for each row of values in `@pytest.mark.parametrize` in
/// case of multiple parameters. The following values are supported:
- /// * `tuple` (default) — e.g. `@pytest.mark.parametrize(('name1', 'name2'),
- /// [(1, 2), (3, 4)])`
- /// * `list` — e.g. `@pytest.mark.parametrize(('name1', 'name2'), [[1, 2],
- /// [3, 4]])`
+ ///
+ /// * `tuple` (default) — e.g.
+ /// `@pytest.mark.parametrize(('name1', 'name2'), [(1, 2), (3, 4)])`
+ /// * `list` — e.g.
+ /// `@pytest.mark.parametrize(('name1', 'name2'), [[1, 2], [3, 4]])`
pub parametrize_values_row_type: Option,
#[option(
default = r#"["BaseException", "Exception", "ValueError", "OSError", "IOError", "EnvironmentError", "socket.error"]"#,
diff --git a/src/rules/flake8_type_checking/settings.rs b/src/rules/flake8_type_checking/settings.rs
index 862ecf1b1b..49dcc7ffcb 100644
--- a/src/rules/flake8_type_checking/settings.rs
+++ b/src/rules/flake8_type_checking/settings.rs
@@ -22,7 +22,7 @@ pub struct Options {
)]
/// Enforce TC001, TC002, and TC003 rules even when valid runtime imports
/// are present for the same module.
- /// See: https://github.com/snok/flake8-type-checking#strict.
+ /// See flake8-type-checking's [strict](https://github.com/snok/flake8-type-checking#strict) option.
pub strict: Option,
#[option(
default = "[\"typing\"]",
diff --git a/src/settings/options.rs b/src/settings/options.rs
index c2fbf6eebb..d1594a07b1 100644
--- a/src/settings/options.rs
+++ b/src/settings/options.rs
@@ -80,10 +80,10 @@ pub struct Options {
///
/// Exclusions are based on globs, and can be either:
///
- /// - Single-path patterns, like `.mypy_cache` (to exclude any directory
+ /// * Single-path patterns, like `.mypy_cache` (to exclude any directory
/// named `.mypy_cache` in the tree), `foo.py` (to exclude any file named
/// `foo.py`), or `foo_*.py` (to exclude any file matching `foo_*.py` ).
- /// - Relative patterns, like `directory/foo.py` (to exclude that specific
+ /// * Relative patterns, like `directory/foo.py` (to exclude that specific
/// file) or `directory/*.py` (to exclude any Python files in
/// `directory`). Note that these paths are relative to the project root
/// (e.g., the directory containing your `pyproject.toml`).
@@ -124,10 +124,10 @@ pub struct Options {
///
/// Exclusions are based on globs, and can be either:
///
- /// - Single-path patterns, like `.mypy_cache` (to exclude any directory
+ /// * Single-path patterns, like `.mypy_cache` (to exclude any directory
/// named `.mypy_cache` in the tree), `foo.py` (to exclude any file named
/// `foo.py`), or `foo_*.py` (to exclude any file matching `foo_*.py` ).
- /// - Relative patterns, like `directory/foo.py` (to exclude that specific
+ /// * Relative patterns, like `directory/foo.py` (to exclude that specific
/// file) or `directory/*.py` (to exclude any Python files in
/// `directory`). Note that these paths are relative to the project root
/// (e.g., the directory containing your `pyproject.toml`).