Compare commits

..

148 Commits

Author SHA1 Message Date
Charlie Marsh
6769ceeddf Remove stale preview documentation from stabilized rule behaviors (#9759)
These behaviors were stabilized, so the docs referring to them as
preview-only are incorrect.
2024-02-01 18:47:05 +00:00
Zanie Blue
386035fade Restore RUF011 documentation (#9758)
For consistency with other redirected rules as in
https://github.com/astral-sh/ruff/pull/9755

Follow-up to #9428
2024-02-01 17:48:47 +00:00
Zanie Blue
8c18fc70af Redirect PHG001 to S307 and PGH002 to G010 (#9756)
Follow-up to #9754 and #9689. Alternative to #9714.
Replaces #7506 and #7507
Same ideas as #9755
Part of #8931
2024-02-01 17:40:05 +00:00
Zanie Blue
f6812ee5eb Redirect TRY200 to B904 (#9755)
Follow-up to #9754 and #9689. Alternative to #9714.

Marks `TRY200` as removed and redirects to `B904` instead of marking as
deprecated and suggesting `B904` instead.
2024-02-01 16:52:06 +00:00
Zanie Blue
003a36071d Add tests for redirected rules (#9754)
Extends https://github.com/astral-sh/ruff/pull/9752 adding internal test
rules for redirection

Fixes a bug where we did not see warnings for exact codes that are
redirected (just prefixes)
2024-02-01 10:46:36 -06:00
Zanie Blue
dcc69f2eb7 Use fake rules for testing deprecation and removal infrastructure (#9752)
Updates #9689 and #9691 to use rule testing infrastructure from #9747
2024-02-01 10:28:50 -06:00
Zanie
1fb6ea6fc2 Fix bug where selection included deprecated rules during preview (#9746)
Cherry-picked from https://github.com/astral-sh/ruff/pull/9714 which is
being abandoned for now because we need to invest more into our
redirection infrastructure before it is feasible.

Fixes a bug in the implementation where we improperly included
deprecated rules in `RuleSelector.rules()` when preview is on. Includes
some clean-up of error messages and the implementation.
# Conflicts:
#	crates/ruff/tests/integration_test.rs
2024-02-01 08:57:47 -06:00
Charlie Marsh
28672fef4b Recategorize runtime-string-union to TCH010 (#9721)
## Summary

This rule was added to `flake8-type-checking` as `TC010`. We're about to
stabilize it, so we might as well use the correct code.

See: https://github.com/astral-sh/ruff/issues/9573.
2024-02-01 08:56:46 -06:00
Charlie Marsh
c1e673248d Stabilize some rules for v0.2.0 release (#9712)
## Summary

This PR stabilizes the preview rules from:

- `flake8-trio` (6 rules)
- `flake8-quotes` (1 rule)
- `pyupgrade` (1 rule)
- `flake8-pyi` (1 rule)
- `flake8-simplify` (2 rules)
- `flake8-bandit` (9 rules; 14 remain in preview)
- `flake8-type-checking` (1 rule)
- `numpy` (1 rule)
- `ruff` (4 rules, one elevated from nursery; 6 remain in preview as
they were added within the last 30 days)
- `flake8-logging` (4 rules)

I see these are largely uncontroversial.
2024-02-01 08:56:46 -06:00
Zanie Blue
8620c6a3cf Add rule removal infrastructure (#9691)
Similar to https://github.com/astral-sh/ruff/pull/9689 — retains removed
rules for better error messages and documentation but removed rules
_cannot_ be used in any context.

Removes PLR1706 as a useful test case and something we want to
accomplish in #9680 anyway. The rule was in preview so we do not need to
deprecate it first.

Closes https://github.com/astral-sh/ruff/issues/9007

## Test plan

<img width="1110" alt="Rules table"
src="https://github.com/astral-sh/ruff/assets/2586601/ac9fa682-623c-44aa-8e51-d8ab0d308355">

<img width="1110" alt="Rule page"
src="https://github.com/astral-sh/ruff/assets/2586601/05850b2d-7ca5-49bb-8df8-bb931bab25cd">
2024-02-01 08:56:46 -06:00
Zanie Blue
542d5f1881 Add rule deprecation infrastructure (#9689)
Adds a new `Deprecated` rule group in addition to `Stable` and
`Preview`.

Deprecated rules:
- Warn on explicit selection without preview
- Error on explicit selection with preview
- Are excluded when selected by prefix with preview

Deprecates `TRY200`, `ANN101`, and `ANN102` as a proof of concept. We
can consider deprecating them separately.
2024-02-01 08:56:46 -06:00
Zanie Blue
5b9132bc33 Remove the NURSERY selector from the json schema (#9695) 2024-02-01 08:56:46 -06:00
Zanie
7574b57d6b Always request the concise output format during ecosystem checks (#9708)
Fixes a regression in the ecosystem checks from
https://github.com/astral-sh/ruff/pull/9687 which was causing them to
run for multiple hours due to the size of the output.

We need the concise format for comparisons.

We should probably update the ecosystem checks to actually diff the full
output in the future because that'd be nice.
# Conflicts:
#	python/ruff-ecosystem/ruff_ecosystem/projects.py
2024-02-01 08:56:44 -06:00
Zanie
7c644d5e6f Error if nursery rules are selected without preview (#9683)
Extends #9682 to error if the nursery selector is used or nursery rules
are selected without preview.

Part of #7992 — we will remove this in 0.3.0 instead so we can provide
nice errors in 0.2.0.
# Conflicts:
#	crates/ruff/tests/integration_test.rs
#	crates/ruff_workspace/src/configuration.rs
2024-02-01 08:55:55 -06:00
Zanie
0001350a27 Replace --show-source and --no-show-source with --output_format=<full|concise> (#9687)
Fixes #7350

## Summary

* `--show-source` and `--no-show-source` are now deprecated.
* `output-format` supports two new variants, `full` and `concise`.
`text` is now a deprecated variant, and any use of it is treated as the
default serialization format.
* `--output-format` now default to `concise`
* In preview mode, `--output-format` defaults to `full`
* `--show-source` will still set `--output-format` to `full` if the
output format is not otherwise specified.
* likewise, `--no-show-source` can override an output format that was
set in a file-based configuration, though it will also be overridden by
`--output-format`

## Test Plan

A lot of tests were updated to use `--output-format=full`. Additional
tests were added to ensure the correct deprecation warnings appeared,
and that deprecated options behaved as intended.
# Conflicts:
#	crates/ruff/tests/integration_test.rs
2024-02-01 08:52:33 -06:00
Charlie Marsh
60dd13839c Remove preview gating for flake8-simplify rules (#9686)
## Summary

Un-gates detecting `dict.get` rewrites in `if` expressions (rather than
just `if` statements).
2024-02-01 08:46:59 -06:00
Charlie Marsh
2b6e093868 Remove preview gating for flake8-pie rules (#9684)
## Summary

Both of the preview behaviors gated here seem like improvements, so
let's make them stable in v0.2.0
2024-02-01 08:46:59 -06:00
Charlie Marsh
e201f45e5d Remove preview gating for pycodestyle rules (#9685)
## Summary

Un-gates the behavior to allow `sys.path` modifications between imports,
which removed a bunch of false positives in the ecosystem CI at the
time.
2024-02-01 08:46:59 -06:00
Zanie
d81a76d1ef Remove preview gating for newly-added stable fixes (#9681)
## Summary

At present, our versioning policy forbids the addition of safe fixes to
stable rules outside of a minor release, so we've accumulated a bunch of
new fixes that are behind `--preview`, and can be ungated in v0.2.0.

To find these, I just grepped for `preview.is_enabled()` and identified
all such cases. I then audited the `preview_rules` test fixtures and
removed any tests that existed only to test this autofix behavior.
# Conflicts:
#	crates/ruff_linter/src/rules/flake8_simplify/snapshots/ruff_linter__rules__flake8_simplify__tests__SIM114_SIM114.py.snap
#	crates/ruff_linter/src/rules/flake8_simplify/snapshots/ruff_linter__rules__flake8_simplify__tests__preview__SIM114_SIM114.py.snap
2024-02-01 08:46:59 -06:00
Zanie
e210c3c48b Recategorize static-key-dict-comprehension from RUF011 to B035 (#9428)
## Summary

This rule was added to flake8-bugbear. In general, we tend to prefer
redirecting to prominent plugins when our own rules are reimplemented
(since more projects have `B` activated than `RUF`).

## Test Plan

`cargo test`
# Conflicts:
#	crates/ruff_linter/src/rules/ruff/rules/mod.rs
2024-02-01 08:46:55 -06:00
Charlie Marsh
0b800a9bfb [flake8-pyi] Mark unaliased-collections-abc-set-import fix as safe (#9679)
## Summary

Prompted by
https://github.com/astral-sh/ruff/issues/8482#issuecomment-1859299411.
The rename is only unsafe when the symbol is exported, so we can narrow
the conditions.
2024-02-01 08:45:50 -06:00
Micha Reiser
5dba038de1 Add deprecation message for top-level lint settings (#9582) 2024-02-01 08:45:50 -06:00
Micha Reiser
c072707fe7 Promote lint. settings over top-level settings (#9476) 2024-02-01 08:45:50 -06:00
Zanie Blue
f18e7d40ac Add internal hidden rules for testing (#9747)
Updated implementation of https://github.com/astral-sh/ruff/pull/7369
which was left out in the cold.

This was motivated again following changes in #9691 and #9689 where we
could not test the changes without actually deprecating or removing
rules.

---

Follow-up to discussion in https://github.com/astral-sh/ruff/pull/7210

Moves integration tests from using rules that are transitively in
nursery / preview groups to dedicated test rules that only exist during
development. These rules always raise violations (they do not require
specific file behavior). The rules are not available in production or in
the documentation.

Uses features instead of `cfg(test)` for cross-crate support per
https://github.com/rust-lang/cargo/issues/8379
2024-02-01 08:44:51 -06:00
Aleksei Latyshev
2cc8acb0b7 [refurb] Implement metaclass_abcmeta (FURB180) (#9658)
## Summary

Implement [use-abc-shorthand
(FURB180)](https://github.com/dosisod/refurb/blob/master/refurb/checks/readability/use_abc_shorthand.py)
lint.

I changed the name to be more conformant with ruff rule-naming rules.


## Test Plan

cargo test
2024-01-31 22:31:12 +00:00
Charlie Marsh
ad83944ded Detect multi-statement lines in else removal (#9748)
The condition here wasn't quite right -- we can have multiple
statements, all on the same line.

Closes https://github.com/astral-sh/ruff/issues/9732.
2024-01-31 22:08:32 +00:00
Seo Sanghyeon
6e225cb57c Removing trailing whitespace inside multiline strings is unsafe (#9744)
Fix #8037.
2024-01-31 21:45:23 +00:00
dependabot[bot]
7992583908 Bump serde from 1.0.195 to 1.0.196 (#9741) 2024-01-31 10:48:50 -05:00
dependabot[bot]
1a46c9c2a2 Bump serde_with from 3.5.1 to 3.6.0 (#9740) 2024-01-31 10:48:44 -05:00
dependabot[bot]
3f4ab87061 Bump proc-macro2 from 1.0.76 to 1.0.78 (#9738) 2024-01-31 10:48:37 -05:00
Christopher Covington
7ae7bf6e30 Support IfExp with dual string arms in invalid-envvar-default (#9734)
## Summary

Just like #6537 and #6538 but for the `default` second parameter to
`getenv()`.

Also rename "BAD" to "BAR" in the tests, since those strings shouldn't
trigger the rule.

## Test Plan

Added passing and failing examples to `invalid_envvar_default.py`.
2024-01-31 10:41:24 -05:00
dependabot[bot]
9e3ff01ce8 Bump the actions group with 4 updates (#9737)
Bumps the actions group with 4 updates:
[tj-actions/changed-files](https://github.com/tj-actions/changed-files),
[actions/cache](https://github.com/actions/cache),
[peter-evans/find-comment](https://github.com/peter-evans/find-comment)
and
[peter-evans/create-or-update-comment](https://github.com/peter-evans/create-or-update-comment).

Updates `tj-actions/changed-files` from 41 to 42
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/tj-actions/changed-files/releases">tj-actions/changed-files's
releases</a>.</em></p>
<blockquote>
<h2>v42</h2>
<h1>Changes in v42.0.2</h1>
<h2>What's Changed</h2>
<ul>
<li>Upgraded to v42.0.1 by <a
href="https://github.com/tj-actions-bot"><code>@​tj-actions-bot</code></a>
in <a
href="https://redirect.github.com/tj-actions/changed-files/pull/1884">tj-actions/changed-files#1884</a></li>
<li>feat: enhance error handling for non-git directories by <a
href="https://github.com/jackton1"><code>@​jackton1</code></a> in <a
href="https://redirect.github.com/tj-actions/changed-files/pull/1885">tj-actions/changed-files#1885</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/tj-actions/changed-files/compare/v42...v42.0.2">https://github.com/tj-actions/changed-files/compare/v42...v42.0.2</a></p>
<hr />
<h1>Changes in v42.0.1</h1>
<h2>What's Changed</h2>
<ul>
<li>Upgraded to v42 by <a
href="https://github.com/tj-actions-bot"><code>@​tj-actions-bot</code></a>
in <a
href="https://redirect.github.com/tj-actions/changed-files/pull/1874">tj-actions/changed-files#1874</a></li>
<li>chore(deps): update tj-actions/eslint-changed-files action to v23 by
<a href="https://github.com/renovate"><code>@​renovate</code></a> in <a
href="https://redirect.github.com/tj-actions/changed-files/pull/1875">tj-actions/changed-files#1875</a></li>
<li>chore(deps): lock file maintenance by <a
href="https://github.com/renovate"><code>@​renovate</code></a> in <a
href="https://redirect.github.com/tj-actions/changed-files/pull/1876">tj-actions/changed-files#1876</a></li>
<li>chore: update README.md by <a
href="https://github.com/jackton1"><code>@​jackton1</code></a> in <a
href="https://redirect.github.com/tj-actions/changed-files/pull/1877">tj-actions/changed-files#1877</a></li>
<li>chore: rename example worflows from test to example by <a
href="https://github.com/jackton1"><code>@​jackton1</code></a> in <a
href="https://redirect.github.com/tj-actions/changed-files/pull/1878">tj-actions/changed-files#1878</a></li>
<li>chore(deps): lock file maintenance by <a
href="https://github.com/renovate"><code>@​renovate</code></a> in <a
href="https://redirect.github.com/tj-actions/changed-files/pull/1879">tj-actions/changed-files#1879</a></li>
<li>chore(deps): update dependency ts-jest to v29.1.2 by <a
href="https://github.com/renovate"><code>@​renovate</code></a> in <a
href="https://redirect.github.com/tj-actions/changed-files/pull/1880">tj-actions/changed-files#1880</a></li>
<li>chore(deps): update typescript-eslint monorepo to v6.19.1 by <a
href="https://github.com/renovate"><code>@​renovate</code></a> in <a
href="https://redirect.github.com/tj-actions/changed-files/pull/1881">tj-actions/changed-files#1881</a></li>
<li>chore(deps): update dependency <code>@​types/node</code> to v20.11.6
by <a href="https://github.com/renovate"><code>@​renovate</code></a> in
<a
href="https://redirect.github.com/tj-actions/changed-files/pull/1883">tj-actions/changed-files#1883</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/tj-actions/changed-files/compare/v42...v42.0.1">https://github.com/tj-actions/changed-files/compare/v42...v42.0.1</a></p>
<hr />
<h1>Changes in v42.0.0</h1>
<h2>🔥🔥 BREAKING CHANGE 🔥🔥</h2>
<ul>
<li>Input file patterns that end with a <code>/</code> would now match
all sub-files within the directory without requiring you to specify the
globstar pattern.</li>
</ul>
<h3></h3>
<pre lang="yaml"><code>...
      - name: Get changed files
        id: changed-files
        uses: tj-actions/changed-files@v42
        with:
          files: 'dir/'  # Would also be the same as dir/** 
</code></pre>
<h2>What's Changed</h2>
<ul>
<li>Upgraded to v41.1.2 by <a
href="https://github.com/tj-actions-bot"><code>@​tj-actions-bot</code></a>
in <a
href="https://redirect.github.com/tj-actions/changed-files/pull/1869">tj-actions/changed-files#1869</a></li>
<li>chore(deps): update dependency prettier to v3.2.4 by <a
href="https://github.com/renovate"><code>@​renovate</code></a> in <a
href="https://redirect.github.com/tj-actions/changed-files/pull/1871">tj-actions/changed-files#1871</a></li>
<li>fix: update input warning by <a
href="https://github.com/jackton1"><code>@​jackton1</code></a> in <a
href="https://redirect.github.com/tj-actions/changed-files/pull/1870">tj-actions/changed-files#1870</a></li>
<li>rename: unsupported REST API inputs constant name by <a
href="https://github.com/jackton1"><code>@​jackton1</code></a> in <a
href="https://redirect.github.com/tj-actions/changed-files/pull/1872">tj-actions/changed-files#1872</a></li>
<li>feat: add support for include/exclude all nested files when a
directory is specified and ends with a slash by <a
href="https://github.com/jackton1"><code>@​jackton1</code></a> in <a
href="https://redirect.github.com/tj-actions/changed-files/pull/1873">tj-actions/changed-files#1873</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/tj-actions/changed-files/blob/main/HISTORY.md">tj-actions/changed-files's
changelog</a>.</em></p>
<blockquote>
<h1>Changelog</h1>
<h1><a
href="https://github.com/tj-actions/changed-files/compare/v42.0.1...v42.0.2">42.0.2</a>
- (2024-01-25)</h1>
<h2><!-- raw HTML omitted -->🚀 Features</h2>
<ul>
<li>Enhance error handling for non-git directories (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/1885">#1885</a>)
(<a
href="90a06d6ba9">90a06d6</a>)
- (Tonye Jack)</li>
</ul>
<h2><!-- raw HTML omitted -->⬆️ Upgrades</h2>
<ul>
<li>Upgraded to v42.0.1 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/1884">#1884</a>)</li>
</ul>
<p>Co-authored-by: jackton1 <a
href="mailto:jackton1@users.noreply.github.com">jackton1@users.noreply.github.com</a>
(<a
href="2cb2c9234e">2cb2c92</a>)
- (tj-actions[bot])</p>
<h1><a
href="https://github.com/tj-actions/changed-files/compare/v42.0.0...v42.0.1">42.0.1</a>
- (2024-01-24)</h1>
<h2><!-- raw HTML omitted --> Add</h2>
<ul>
<li>Added missing changes and modified dist assets.
(<a
href="ea024b2d7f">ea024b2</a>)
- (GitHub Action)</li>
<li>Added missing changes and modified dist assets.
(<a
href="3af07c2040">3af07c2</a>)
- (GitHub Action)</li>
</ul>
<h2><!-- raw HTML omitted -->🔄 Update</h2>
<ul>
<li>Update env.ts (<a
href="3680129aa2">3680129</a>)
- (Tonye Jack)</li>
</ul>
<h2><!-- raw HTML omitted -->⚙️ Miscellaneous Tasks</h2>
<ul>
<li><strong>deps:</strong> Update dependency <code>@​types/node</code>
to v20.11.6 (<a
href="ac21d93904">ac21d93</a>)
- (renovate[bot])</li>
<li><strong>deps:</strong> Update typescript-eslint monorepo to v6.19.1
(<a
href="a4637ea6e7">a4637ea</a>)
- (renovate[bot])</li>
<li><strong>deps:</strong> Update dependency ts-jest to v29.1.2 (<a
href="fd9998cf5f">fd9998c</a>)
- (renovate[bot])</li>
<li><strong>deps:</strong> Lock file maintenance (<a
href="db4e584844">db4e584</a>)
- (renovate[bot])</li>
<li>Rename example worflows from test to example (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/1878">#1878</a>)
(<a
href="c6543c497a">c6543c4</a>)
- (Tonye Jack)</li>
<li>Update README.md (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/1877">#1877</a>)
(<a
href="88f9f3efbb">88f9f3e</a>)
- (Tonye Jack)</li>
<li><strong>deps:</strong> Lock file maintenance (<a
href="5d866cbe77">5d866cb</a>)
- (renovate[bot])</li>
<li><strong>deps:</strong> Update tj-actions/eslint-changed-files action
to v23 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/1875">#1875</a>)
(<a
href="346f237a17">346f237</a>)
- (renovate[bot])</li>
</ul>
<h2><!-- raw HTML omitted -->⬆️ Upgrades</h2>
<ul>
<li>Upgraded to v42 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/1874">#1874</a>)</li>
</ul>
<p>Co-authored-by: jackton1 <a
href="mailto:jackton1@users.noreply.github.com">jackton1@users.noreply.github.com</a>
(<a
href="c037f1e7c5">c037f1e</a>)
- (tj-actions[bot])</p>
<h1><a
href="https://github.com/tj-actions/changed-files/compare/v41.1.2...v42.0.0">42.0.0</a>
- (2024-01-18)</h1>
<h2><!-- raw HTML omitted -->🚀 Features</h2>
<ul>
<li>Add support for include/exclude all nested files when a directory is
specified and ends with a slash (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/1873">#1873</a>)
(<a
href="ae82ed4ae0">ae82ed4</a>)
- (Tonye Jack)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="90a06d6ba9"><code>90a06d6</code></a>
feat: enhance error handling for non-git directories (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/1885">#1885</a>)</li>
<li><a
href="2cb2c9234e"><code>2cb2c92</code></a>
Upgraded to v42.0.1 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/1884">#1884</a>)</li>
<li><a
href="ac21d93904"><code>ac21d93</code></a>
chore(deps): update dependency <code>@​types/node</code> to
v20.11.6</li>
<li><a
href="a4637ea6e7"><code>a4637ea</code></a>
chore(deps): update typescript-eslint monorepo to v6.19.1</li>
<li><a
href="fd9998cf5f"><code>fd9998c</code></a>
chore(deps): update dependency ts-jest to v29.1.2</li>
<li><a
href="ea024b2d7f"><code>ea024b2</code></a>
Added missing changes and modified dist assets.</li>
<li><a
href="db4e584844"><code>db4e584</code></a>
chore(deps): lock file maintenance</li>
<li><a
href="c6543c497a"><code>c6543c4</code></a>
chore: rename example worflows from test to example (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/1878">#1878</a>)</li>
<li><a
href="88f9f3efbb"><code>88f9f3e</code></a>
chore: update README.md (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/1877">#1877</a>)</li>
<li><a
href="3af07c2040"><code>3af07c2</code></a>
Added missing changes and modified dist assets.</li>
<li>Additional commits viewable in <a
href="https://github.com/tj-actions/changed-files/compare/v41...v42">compare
view</a></li>
</ul>
</details>
<br />

Updates `actions/cache` from 3 to 4
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/cache/releases">actions/cache's
releases</a>.</em></p>
<blockquote>
<h2>v4.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update action to node20 by <a
href="https://github.com/takost"><code>@​takost</code></a> in <a
href="https://redirect.github.com/actions/cache/pull/1284">actions/cache#1284</a></li>
<li>feat: save-always flag by <a
href="https://github.com/to-s"><code>@​to-s</code></a> in <a
href="https://redirect.github.com/actions/cache/pull/1242">actions/cache#1242</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/takost"><code>@​takost</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/cache/pull/1284">actions/cache#1284</a></li>
<li><a href="https://github.com/to-s"><code>@​to-s</code></a> made their
first contribution in <a
href="https://redirect.github.com/actions/cache/pull/1242">actions/cache#1242</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/cache/compare/v3...v4.0.0">https://github.com/actions/cache/compare/v3...v4.0.0</a></p>
<h2>v3.3.3</h2>
<h2>What's Changed</h2>
<ul>
<li>Cache v3.3.3 by <a
href="https://github.com/robherley"><code>@​robherley</code></a> in <a
href="https://redirect.github.com/actions/cache/pull/1302">actions/cache#1302</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/robherley"><code>@​robherley</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/cache/pull/1302">actions/cache#1302</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/cache/compare/v3...v3.3.3">https://github.com/actions/cache/compare/v3...v3.3.3</a></p>
<h2>v3.3.2</h2>
<h2>What's Changed</h2>
<ul>
<li>Fixed readme with new segment timeout values by <a
href="https://github.com/kotewar"><code>@​kotewar</code></a> in <a
href="https://redirect.github.com/actions/cache/pull/1133">actions/cache#1133</a></li>
<li>Readme fixes by <a
href="https://github.com/kotewar"><code>@​kotewar</code></a> in <a
href="https://redirect.github.com/actions/cache/pull/1134">actions/cache#1134</a></li>
<li>Updated description of the lookup-only input for main action by <a
href="https://github.com/kotewar"><code>@​kotewar</code></a> in <a
href="https://redirect.github.com/actions/cache/pull/1130">actions/cache#1130</a></li>
<li>Change two new actions mention as quoted text by <a
href="https://github.com/bishal-pdMSFT"><code>@​bishal-pdMSFT</code></a>
in <a
href="https://redirect.github.com/actions/cache/pull/1131">actions/cache#1131</a></li>
<li>Update Cross-OS Caching tips by <a
href="https://github.com/pdotl"><code>@​pdotl</code></a> in <a
href="https://redirect.github.com/actions/cache/pull/1122">actions/cache#1122</a></li>
<li>Bazel example (Take <a
href="https://redirect.github.com/actions/cache/issues/2">#2</a>️⃣) by
<a href="https://github.com/vorburger"><code>@​vorburger</code></a> in
<a
href="https://redirect.github.com/actions/cache/pull/1132">actions/cache#1132</a></li>
<li>Remove actions to add new PRs and issues to a project board by <a
href="https://github.com/jorendorff"><code>@​jorendorff</code></a> in <a
href="https://redirect.github.com/actions/cache/pull/1187">actions/cache#1187</a></li>
<li>Consume latest toolkit and fix dangling promise bug by <a
href="https://github.com/chkimes"><code>@​chkimes</code></a> in <a
href="https://redirect.github.com/actions/cache/pull/1217">actions/cache#1217</a></li>
<li>Bump action version to 3.3.2 by <a
href="https://github.com/bethanyj28"><code>@​bethanyj28</code></a> in <a
href="https://redirect.github.com/actions/cache/pull/1236">actions/cache#1236</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/vorburger"><code>@​vorburger</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/cache/pull/1132">actions/cache#1132</a></li>
<li><a
href="https://github.com/jorendorff"><code>@​jorendorff</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/cache/pull/1187">actions/cache#1187</a></li>
<li><a href="https://github.com/chkimes"><code>@​chkimes</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/cache/pull/1217">actions/cache#1217</a></li>
<li><a
href="https://github.com/bethanyj28"><code>@​bethanyj28</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/cache/pull/1236">actions/cache#1236</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/cache/compare/v3...v3.3.2">https://github.com/actions/cache/compare/v3...v3.3.2</a></p>
<h2>v3.3.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Reduced download segment size to 128 MB and timeout to 10 minutes by
<a href="https://github.com/kotewar"><code>@​kotewar</code></a> in <a
href="https://redirect.github.com/actions/cache/pull/1129">actions/cache#1129</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/cache/compare/v3...v3.3.1">https://github.com/actions/cache/compare/v3...v3.3.1</a></p>
<h2>v3.3.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Bug: Permission is missing in cache delete example by <a
href="https://github.com/kotokaze"><code>@​kotokaze</code></a> in <a
href="https://redirect.github.com/actions/cache/pull/1123">actions/cache#1123</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/actions/cache/blob/main/RELEASES.md">actions/cache's
changelog</a>.</em></p>
<blockquote>
<h1>Releases</h1>
<h3>3.0.0</h3>
<ul>
<li>Updated minimum runner version support from node 12 -&gt; node
16</li>
</ul>
<h3>3.0.1</h3>
<ul>
<li>Added support for caching from GHES 3.5.</li>
<li>Fixed download issue for files &gt; 2GB during restore.</li>
</ul>
<h3>3.0.2</h3>
<ul>
<li>Added support for dynamic cache size cap on GHES.</li>
</ul>
<h3>3.0.3</h3>
<ul>
<li>Fixed avoiding empty cache save when no files are available for
caching. (<a
href="https://redirect.github.com/actions/cache/issues/624">issue</a>)</li>
</ul>
<h3>3.0.4</h3>
<ul>
<li>Fixed tar creation error while trying to create tar with path as
<code>~/</code> home folder on <code>ubuntu-latest</code>. (<a
href="https://redirect.github.com/actions/cache/issues/689">issue</a>)</li>
</ul>
<h3>3.0.5</h3>
<ul>
<li>Removed error handling by consuming actions/cache 3.0 toolkit, Now
cache server error handling will be done by toolkit. (<a
href="https://redirect.github.com/actions/cache/pull/834">PR</a>)</li>
</ul>
<h3>3.0.6</h3>
<ul>
<li>Fixed <a
href="https://redirect.github.com/actions/cache/issues/809">#809</a> -
zstd -d: no such file or directory error</li>
<li>Fixed <a
href="https://redirect.github.com/actions/cache/issues/833">#833</a> -
cache doesn't work with github workspace directory</li>
</ul>
<h3>3.0.7</h3>
<ul>
<li>Fixed <a
href="https://redirect.github.com/actions/cache/issues/810">#810</a> -
download stuck issue. A new timeout is introduced in the download
process to abort the download if it gets stuck and doesn't finish within
an hour.</li>
</ul>
<h3>3.0.8</h3>
<ul>
<li>Fix zstd not working for windows on gnu tar in issues <a
href="https://redirect.github.com/actions/cache/issues/888">#888</a> and
<a
href="https://redirect.github.com/actions/cache/issues/891">#891</a>.</li>
<li>Allowing users to provide a custom timeout as input for aborting
download of a cache segment using an environment variable
<code>SEGMENT_DOWNLOAD_TIMEOUT_MINS</code>. Default is 60 minutes.</li>
</ul>
<h3>3.0.9</h3>
<ul>
<li>Enhanced the warning message for cache unavailablity in case of
GHES.</li>
</ul>
<h3>3.0.10</h3>
<ul>
<li>Fix a bug with sorting inputs.</li>
<li>Update definition for restore-keys in README.md</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="13aacd865c"><code>13aacd8</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/cache/issues/1242">#1242</a>
from to-s/main</li>
<li><a
href="53b35c5439"><code>53b35c5</code></a>
Merge branch 'main' into main</li>
<li><a
href="65b8989fab"><code>65b8989</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/cache/issues/1284">#1284</a>
from takost/update-to-node-20</li>
<li><a
href="d0be34d544"><code>d0be34d</code></a>
Fix dist</li>
<li><a
href="66cf064d47"><code>66cf064</code></a>
Merge branch 'main' into update-to-node-20</li>
<li><a
href="1326563738"><code>1326563</code></a>
Merge branch 'main' into main</li>
<li><a
href="e71876755e"><code>e718767</code></a>
Fix format</li>
<li><a
href="01229828ff"><code>0122982</code></a>
Apply workaround for earlyExit</li>
<li><a
href="3185ecfd61"><code>3185ecf</code></a>
Update &quot;only-&quot; actions to node20</li>
<li><a
href="25618a0a67"><code>25618a0</code></a>
Bump version</li>
<li>Additional commits viewable in <a
href="https://github.com/actions/cache/compare/v3...v4">compare
view</a></li>
</ul>
</details>
<br />

Updates `peter-evans/find-comment` from 2 to 3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/peter-evans/find-comment/releases">peter-evans/find-comment's
releases</a>.</em></p>
<blockquote>
<h2>Find Comment v3.0.0</h2>
<p>⚙️  Updated runtime to Node.js 20</p>
<ul>
<li>The action now requires a minimum version of <a
href="https://github.com/actions/runner/releases/tag/v2.308.0">v2.308.0</a>
for the Actions runner. Update self-hosted runners to v2.308.0 or later
to ensure compatibility.</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>build(deps-dev): bump prettier from 2.8.7 to 2.8.8 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/173">peter-evans/find-comment#173</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.15.13 to
18.16.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/175">peter-evans/find-comment#175</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/parser</code> from
5.59.0 to 5.59.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/176">peter-evans/find-comment#176</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 5.59.0 to 5.59.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/174">peter-evans/find-comment#174</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 5.59.1 to 5.59.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/177">peter-evans/find-comment#177</a></li>
<li>build(deps-dev): bump eslint from 8.39.0 to 8.40.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/179">peter-evans/find-comment#179</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/parser</code> from
5.59.1 to 5.59.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/178">peter-evans/find-comment#178</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.16.3 to
18.16.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/180">peter-evans/find-comment#180</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 5.59.2 to 5.59.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/181">peter-evans/find-comment#181</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/parser</code> from
5.59.2 to 5.59.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/183">peter-evans/find-comment#183</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.16.5 to
18.16.9 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/182">peter-evans/find-comment#182</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/parser</code> from
5.59.5 to 5.59.6 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/184">peter-evans/find-comment#184</a></li>
<li>build(deps-dev): bump eslint from 8.40.0 to 8.41.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/186">peter-evans/find-comment#186</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.16.9 to
18.16.13 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/187">peter-evans/find-comment#187</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 5.59.5 to 5.59.6 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/185">peter-evans/find-comment#185</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.16.13 to
18.16.16 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/188">peter-evans/find-comment#188</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/parser</code> from
5.59.6 to 5.59.7 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/190">peter-evans/find-comment#190</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 5.59.6 to 5.59.7 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/189">peter-evans/find-comment#189</a></li>
<li>build(deps-dev): bump eslint from 8.41.0 to 8.42.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/191">peter-evans/find-comment#191</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/parser</code> from
5.59.7 to 5.59.8 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/193">peter-evans/find-comment#193</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 5.59.7 to 5.59.8 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/194">peter-evans/find-comment#194</a></li>
<li>build(deps-dev): bump eslint-plugin-github from 4.7.0 to 4.8.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/192">peter-evans/find-comment#192</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 5.59.8 to 5.59.9 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/195">peter-evans/find-comment#195</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/parser</code> from
5.59.8 to 5.59.9 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/197">peter-evans/find-comment#197</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.16.16 to
18.16.17 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/196">peter-evans/find-comment#196</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/parser</code> from
5.59.9 to 5.59.11 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/198">peter-evans/find-comment#198</a></li>
<li>build(deps-dev): bump eslint from 8.42.0 to 8.43.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/199">peter-evans/find-comment#199</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.16.17 to
18.16.18 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/200">peter-evans/find-comment#200</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 5.59.9 to 5.59.11 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/201">peter-evans/find-comment#201</a></li>
<li>build(deps-dev): bump eslint-plugin-jest from 27.2.1 to 27.2.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/202">peter-evans/find-comment#202</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 5.59.11 to 5.60.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/203">peter-evans/find-comment#203</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/parser</code> from
5.59.11 to 5.60.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/204">peter-evans/find-comment#204</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.16.18 to
18.16.19 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/205">peter-evans/find-comment#205</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/parser</code> from
5.60.0 to 5.60.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/206">peter-evans/find-comment#206</a></li>
<li>build(deps-dev): bump eslint from 8.43.0 to 8.44.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/207">peter-evans/find-comment#207</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 5.60.0 to 5.60.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/208">peter-evans/find-comment#208</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 5.60.1 to 5.61.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/209">peter-evans/find-comment#209</a></li>
<li>build(deps): bump tough-cookie from 4.1.2 to 4.1.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/211">peter-evans/find-comment#211</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/parser</code> from
5.60.1 to 5.61.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/210">peter-evans/find-comment#210</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 5.61.0 to 5.62.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/212">peter-evans/find-comment#212</a></li>
<li>build(deps-dev): bump eslint from 8.44.0 to 8.45.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/214">peter-evans/find-comment#214</a></li>
<li>build(deps-dev): bump eslint-plugin-jest from 27.2.2 to 27.2.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/215">peter-evans/find-comment#215</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/parser</code> from
5.61.0 to 5.62.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/213">peter-evans/find-comment#213</a></li>
<li>build(deps-dev): bump eslint-plugin-github from 4.8.0 to 4.9.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/216">peter-evans/find-comment#216</a></li>
<li>build(deps-dev): bump word-wrap from 1.2.3 to 1.2.4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/find-comment/pull/217">peter-evans/find-comment#217</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="d5fe37641a"><code>d5fe376</code></a>
feat: update runtime to node 20 (<a
href="https://redirect.github.com/peter-evans/find-comment/issues/282">#282</a>)</li>
<li><a
href="e3754082ec"><code>e375408</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.6 to 18.19.8
(<a
href="https://redirect.github.com/peter-evans/find-comment/issues/279">#279</a>)</li>
<li><a
href="6f781399d6"><code>6f78139</code></a>
build(deps-dev): bump prettier from 3.2.1 to 3.2.4 (<a
href="https://redirect.github.com/peter-evans/find-comment/issues/278">#278</a>)</li>
<li><a
href="663f5b8fd8"><code>663f5b8</code></a>
build(deps-dev): bump eslint-plugin-jest from 27.6.1 to 27.6.3 (<a
href="https://redirect.github.com/peter-evans/find-comment/issues/276">#276</a>)</li>
<li><a
href="1950d48590"><code>1950d48</code></a>
build(deps-dev): bump prettier from 3.1.1 to 3.2.1 (<a
href="https://redirect.github.com/peter-evans/find-comment/issues/277">#277</a>)</li>
<li><a
href="4c49b27bc3"><code>4c49b27</code></a>
build(deps-dev): bump eslint-plugin-prettier from 5.1.2 to 5.1.3 (<a
href="https://redirect.github.com/peter-evans/find-comment/issues/275">#275</a>)</li>
<li><a
href="141f79c0a8"><code>141f79c</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.4 to 18.19.6
(<a
href="https://redirect.github.com/peter-evans/find-comment/issues/274">#274</a>)</li>
<li><a
href="90d027df0e"><code>90d027d</code></a>
build(deps-dev): bump eslint-plugin-jest from 27.6.0 to 27.6.1 (<a
href="https://redirect.github.com/peter-evans/find-comment/issues/273">#273</a>)</li>
<li><a
href="4541d1b6b0"><code>4541d1b</code></a>
build(deps-dev): bump eslint-plugin-prettier from 5.1.1 to 5.1.2 (<a
href="https://redirect.github.com/peter-evans/find-comment/issues/272">#272</a>)</li>
<li><a
href="3e2c601e8c"><code>3e2c601</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.3 to 18.19.4
(<a
href="https://redirect.github.com/peter-evans/find-comment/issues/271">#271</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/peter-evans/find-comment/compare/v2...v3">compare
view</a></li>
</ul>
</details>
<br />

Updates `peter-evans/create-or-update-comment` from 3 to 4
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/peter-evans/create-or-update-comment/releases">peter-evans/create-or-update-comment's
releases</a>.</em></p>
<blockquote>
<h2>Create or Update Comment v4.0.0</h2>
<p>⚙️  Updated runtime to Node.js 20</p>
<ul>
<li>The action now requires a minimum version of <a
href="https://github.com/actions/runner/releases/tag/v2.308.0">v2.308.0</a>
for the Actions runner. Update self-hosted runners to v2.308.0 or later
to ensure compatibility.</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>build(deps): bump actions/setup-node from 3 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/273">peter-evans/create-or-update-comment#273</a></li>
<li>build(deps-dev): bump <code>@​vercel/ncc</code> from 0.38.0 to
0.38.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/274">peter-evans/create-or-update-comment#274</a></li>
<li>build(deps-dev): bump eslint-plugin-jest from 27.4.2 to 27.4.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/276">peter-evans/create-or-update-comment#276</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.18.5 to
18.18.6 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/277">peter-evans/create-or-update-comment#277</a></li>
<li>build(deps-dev): bump eslint from 8.51.0 to 8.52.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/275">peter-evans/create-or-update-comment#275</a></li>
<li>build(deps-dev): bump eslint-plugin-jest from 27.4.3 to 27.6.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/278">peter-evans/create-or-update-comment#278</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.18.6 to
18.18.8 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/279">peter-evans/create-or-update-comment#279</a></li>
<li>build(deps-dev): bump eslint from 8.52.0 to 8.53.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/280">peter-evans/create-or-update-comment#280</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.18.8 to
18.18.9 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/281">peter-evans/create-or-update-comment#281</a></li>
<li>build(deps-dev): bump prettier from 3.0.3 to 3.1.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/282">peter-evans/create-or-update-comment#282</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.18.9 to
18.18.12 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/283">peter-evans/create-or-update-comment#283</a></li>
<li>build(deps-dev): bump eslint from 8.53.0 to 8.54.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/284">peter-evans/create-or-update-comment#284</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.18.12 to
18.18.13 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/285">peter-evans/create-or-update-comment#285</a></li>
<li>build(deps-dev): bump eslint from 8.54.0 to 8.55.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/286">peter-evans/create-or-update-comment#286</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.18.13 to
18.19.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/287">peter-evans/create-or-update-comment#287</a></li>
<li>build(deps): bump chuhlomin/render-template from 1.8 to 1.9 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/288">peter-evans/create-or-update-comment#288</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.19.2 to
18.19.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/289">peter-evans/create-or-update-comment#289</a></li>
<li>build(deps-dev): bump prettier from 3.1.0 to 3.1.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/290">peter-evans/create-or-update-comment#290</a></li>
<li>build(deps-dev): bump eslint-plugin-prettier from 5.0.1 to 5.1.0 by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/292">peter-evans/create-or-update-comment#292</a></li>
<li>build(deps-dev): bump eslint from 8.55.0 to 8.56.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/293">peter-evans/create-or-update-comment#293</a></li>
<li>build(deps): bump actions/download-artifact from 3 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/295">peter-evans/create-or-update-comment#295</a></li>
<li>build(deps-dev): bump eslint-plugin-prettier from 5.1.0 to 5.1.2 by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/296">peter-evans/create-or-update-comment#296</a></li>
<li>build(deps-dev): bump eslint-plugin-jest from 27.6.0 to 27.6.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/297">peter-evans/create-or-update-comment#297</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.19.3 to
18.19.4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/298">peter-evans/create-or-update-comment#298</a></li>
<li>build(deps-dev): bump eslint-plugin-prettier from 5.1.2 to 5.1.3 by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/299">peter-evans/create-or-update-comment#299</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.19.4 to
18.19.6 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/300">peter-evans/create-or-update-comment#300</a></li>
<li>build(deps-dev): bump prettier from 3.1.1 to 3.2.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/301">peter-evans/create-or-update-comment#301</a></li>
<li>build(deps-dev): bump eslint-plugin-jest from 27.6.1 to 27.6.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/302">peter-evans/create-or-update-comment#302</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.19.6 to
18.19.7 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/303">peter-evans/create-or-update-comment#303</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.19.7 to
18.19.8 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/304">peter-evans/create-or-update-comment#304</a></li>
<li>build(deps-dev): bump prettier from 3.2.3 to 3.2.4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/305">peter-evans/create-or-update-comment#305</a></li>
<li>feat: update runtime to node 20 by <a
href="https://github.com/peter-evans"><code>@​peter-evans</code></a> in
<a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/306">peter-evans/create-or-update-comment#306</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/peter-evans/create-or-update-comment/compare/v3.1.0...v4.0.0">https://github.com/peter-evans/create-or-update-comment/compare/v3.1.0...v4.0.0</a></p>
<h2>Create or Update Comment v3.1.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Add truncate warning to body of comment by <a
href="https://github.com/ethanmdavidson"><code>@​ethanmdavidson</code></a>
and <a
href="https://github.com/peter-evans"><code>@​peter-evans</code></a> in
<a
href="https://redirect.github.com/peter-evans/create-or-update-comment/pull/272">peter-evans/create-or-update-comment#272</a></li>
<li>46 dependency updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/peter-evans/create-or-update-comment/compare/v3.0.2...v3.1.0">https://github.com/peter-evans/create-or-update-comment/compare/v3.0.2...v3.1.0</a></p>
<h2>Create or Update Comment v3.0.2</h2>
<h2>What's Changed</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="71345be026"><code>71345be</code></a>
feat: update runtime to node 20 (<a
href="https://redirect.github.com/peter-evans/create-or-update-comment/issues/306">#306</a>)</li>
<li><a
href="d41bfe36e5"><code>d41bfe3</code></a>
build(deps-dev): bump prettier from 3.2.3 to 3.2.4 (<a
href="https://redirect.github.com/peter-evans/create-or-update-comment/issues/305">#305</a>)</li>
<li><a
href="73b4b9e4e3"><code>73b4b9e</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.7 to 18.19.8
(<a
href="https://redirect.github.com/peter-evans/create-or-update-comment/issues/304">#304</a>)</li>
<li><a
href="b865fac7fa"><code>b865fac</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.6 to 18.19.7
(<a
href="https://redirect.github.com/peter-evans/create-or-update-comment/issues/303">#303</a>)</li>
<li><a
href="52b668a928"><code>52b668a</code></a>
build(deps-dev): bump eslint-plugin-jest from 27.6.1 to 27.6.3 (<a
href="https://redirect.github.com/peter-evans/create-or-update-comment/issues/302">#302</a>)</li>
<li><a
href="974f56a1c3"><code>974f56a</code></a>
build(deps-dev): bump prettier from 3.1.1 to 3.2.3 (<a
href="https://redirect.github.com/peter-evans/create-or-update-comment/issues/301">#301</a>)</li>
<li><a
href="2cbfe8b17b"><code>2cbfe8b</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.4 to 18.19.6
(<a
href="https://redirect.github.com/peter-evans/create-or-update-comment/issues/300">#300</a>)</li>
<li><a
href="761872a701"><code>761872a</code></a>
build(deps-dev): bump eslint-plugin-prettier from 5.1.2 to 5.1.3 (<a
href="https://redirect.github.com/peter-evans/create-or-update-comment/issues/299">#299</a>)</li>
<li><a
href="72c3238a49"><code>72c3238</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.3 to 18.19.4
(<a
href="https://redirect.github.com/peter-evans/create-or-update-comment/issues/298">#298</a>)</li>
<li><a
href="07daf7bbdb"><code>07daf7b</code></a>
build(deps-dev): bump eslint-plugin-jest from 27.6.0 to 27.6.1 (<a
href="https://redirect.github.com/peter-evans/create-or-update-comment/issues/297">#297</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/peter-evans/create-or-update-comment/compare/v3...v4">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-31 09:39:57 -06:00
dependabot[bot]
63a7de9018 Bump wild from 2.2.0 to 2.2.1 (#9739) 2024-01-31 15:37:30 +00:00
dependabot[bot]
b77021b9ed Bump clap from 4.4.13 to 4.4.18 (#9742) 2024-01-31 15:37:00 +00:00
Charlie Marsh
f0066e1b89 Use publicly available Apple Silicon runners (#9726)
## Summary

This PR switches over to the `macos-14` runners for our macOS wheel
builds, which are GitHub's newly announced public M1 macOS runners
(https://github.blog/changelog/2024-01-30-github-actions-introducing-the-new-m1-macos-runner-available-to-open-source/).

Before:

- x64_64: 10m 38s
(https://github.com/astral-sh/ruff/actions/runs/7703465381/job/20993903864)
- Universal: 19m 35s
(https://github.com/astral-sh/ruff/actions/runs/7703465381/job/20993902533)

After:

- x64_64: 3m 30s
(https://github.com/astral-sh/ruff/actions/runs/7719827902/job/21043743558?pr=9726)
- Universal: 5m 59s
(https://github.com/astral-sh/ruff/actions/runs/7719827902/job/21043743243?pr=9726)

So it's like > 3x speedup for what is currently the bottleneck in our
release pipeline.
2024-01-31 10:36:41 -05:00
Zanie Blue
7642fb7f27 Excludes upload and download artifact dependencies from dependabot (#9736)
e.g. in https://github.com/astral-sh/ruff/pull/9667 we cannot upgrade
them but want to upgrade the rest
2024-01-31 15:18:19 +00:00
Sai-Suraj-27
7a1fa0e5d8 Update README.md by adding ivy repository to the who's using Ruff section (#9735)
## Summary
I have recently made a contribution to a big python based repo
**replacing flake8 with ruff**
(https://github.com/unifyai/ivy/pull/27779). So, as per this
[discussion](https://github.com/astral-sh/ruff/discussions/9731). I am
making this PR to add the [ivy](https://github.com/unifyai/ivy)
repository (**with > 13k stars **) to the Ruff's readme

## Test Plan
No, need of any tests for the changes made.
2024-01-31 15:09:26 +00:00
Micha Reiser
ce14f4dea5 Range formatting API (#9635) 2024-01-31 11:13:37 +01:00
Alex Waygood
6bb126415d RUF023: Don't sort __match_args__, only __slots__ (#9724)
Fixes #9723. I'm pretty embarrassed I forgot that order was important
here :(
2024-01-30 22:44:49 +00:00
Dhruv Manilawala
541aef4e6c Implement blank_line_after_nested_stub_class preview style (#9155)
## Summary

This PR implements the `blank_line_after_nested_stub_class` preview
style in the formatter.

The logic is divided into 3 parts:
1. In between preceding and following nodes at top level and nested
suite
2. When there's a trailing comment after the class
3. When there is no following node from (1) which is the case when it's
the last or the only node in a suite

We handle (3) with `FormatLeadingAlternateBranchComments`.

## Test Plan

- Add new test cases and update existing snapshots
- Checked the `typeshed` diff

fixes: #8891
2024-01-31 00:09:38 +05:30
Mikko Leppänen
79f0522eb7 [flake8-async] Take pathlib.Path into account when analyzing async functions (#9703)
## Summary

This review contains a fix for
[ASYNC101](https://docs.astral.sh/ruff/rules/open-sleep-or-subprocess-in-async-function/)
(open-sleep-or-subprocess-in-async-function)

The problem is that ruff does not take open calls from pathlib.Path into
account in async functions. Path.open() call is still a blocking call.
In addition, PTH123 suggests to use pathlib.Path instead of os.open. So
this might create an additional confusion.

See: https://github.com/astral-sh/ruff/issues/6892

## Test Plan

```bash
cargo test
```
2024-01-30 17:42:50 +00:00
Alex Waygood
0c8d140321 RUF022, RUF023: never add two trailing commas to the end of a sequence (#9698)
Fixes the issues highlighted in
https://github.com/astral-sh/ruff/issues/8402#issuecomment-1916203707
and
https://github.com/astral-sh/ruff/issues/8402#issuecomment-1916213693
2024-01-30 17:19:38 +00:00
Zanie Blue
f38fb2432f Add timeouts to all CI jobs (#9709)
To prevent jobs from running far beyond their expected time
2024-01-30 11:13:23 -06:00
Steve C
f0e598ea84 [flake8-return] Fix indentation syntax error (RET505) (#9705)
## Summary

Fix for
https://github.com/astral-sh/ruff/issues/8402#issuecomment-1916223126

## Test Plan

`cargo test`
2024-01-30 16:46:04 +00:00
Bartosz Sławecki
b6a96452fc [pylint] Add __mro_entries__ to known dunder methods (PLW3201) (#9706)
## Summary

This change adds
[`__mro_entries__`](https://docs.python.org/3/reference/datamodel.html#object.__mro_entries__)
to the list of known dunder methods.
2024-01-30 11:41:19 -05:00
Steve C
214563261d [flake8-simplify] - Fix syntax error in autofix (SIM114) (#9704)
## Summary

A fix for
https://github.com/astral-sh/ruff/issues/8402#issuecomment-1916215124

Improves the code, as well. :)

## Test Plan

`cargo test`
2024-01-30 11:36:44 -05:00
Micha Reiser
3c7fea769c Show source-type in formatter snapshot tests with options (#9699) 2024-01-30 10:08:50 +00:00
Steve C
dacda0f202 [pylint] Show verbatim constant in magic-value-comparison (PLR2004) (#9694)
## Summary

Tweaks PLR2004 to show the literal source text, rather than the constant
value.

I noticed this when I had a hexadecimal constant, and the linter turned
it into base-10.

Now, if you have `0x300`, it will show `0x300` instead of `768`.

Also, added backticks around the constant in the output message.

## Test Plan

`cargo test`
2024-01-30 00:22:09 -05:00
Charlie Marsh
95e1444c90 Remove empty section from changelog (#9693) 2024-01-29 19:52:13 -05:00
Charlie Marsh
a7755d7a8d Bump version to v0.1.15 (#9690) 2024-01-29 17:44:05 -05:00
Charlie Marsh
11449acfd9 Avoid marking InitVar as a typing-only annotation (#9688)
## Summary

Given:

```python
from dataclasses import InitVar, dataclass

@dataclass
class C:
    i: int
    j: int = None
    database: InitVar[DatabaseType] = None

    def __post_init__(self, database):
        if self.j is None and database is not None:
            self.j = database.lookup('j')

c = C(10, database=my_database)
```

We should avoid marking `InitVar` as typing-only, since it _is_ required
by the dataclass at runtime.

Note that by default, we _already_ don't flag this, since the
`@dataclass` member is needed at runtime too -- so it's only a problem
with `strict` mode.

Closes https://github.com/astral-sh/ruff/issues/9666.
2024-01-29 16:27:20 -05:00
Zanie Blue
4ccbacd44b Error if the NURSERY selector is used with preview (#9682)
Changes our warning for combined use of `--preview` and `--select
NURSERY` to a hard error.

This should go out _before_ #9680 where we will ban use of `NURSERY`
outside of preview as well (see #9683).

Part of https://github.com/astral-sh/ruff/issues/7992
2024-01-29 13:33:46 -06:00
Charlie Marsh
05a2f52206 Document literal-membership fix safety conditions (#9677)
## Summary

This seems safe to me. See
https://github.com/astral-sh/ruff/issues/8482#issuecomment-1859299411.

## Test Plan

`cargo test`
2024-01-29 17:48:40 +00:00
Charlie Marsh
a6f7100b55 [pycodestyle] Allow dtype comparisons in type-comparison (#9676)
## Summary

Per https://github.com/astral-sh/ruff/issues/9570:

> `dtype` are a bit of a strange beast, but definitely best thought of
as instances, not classes, and they are meant to be comparable not just
to their own class, but also to the corresponding scalar types (e.g.,
`x.dtype == np.float32`) and strings (e.g., `x.dtype == ['i1,i4']`;
basically, `__eq__` always tries to do `dtype(other)`.

This PR thus allows comparisons to `dtype` in preview.

Closes https://github.com/astral-sh/ruff/issues/9570.

## Test Plan

`cargo test`
2024-01-29 12:39:01 -05:00
Charlie Marsh
50122d2308 [flake8-pytest-style] Add fix safety documentation for duplicate-parameterize-test-cases (#9678)
See:
https://github.com/astral-sh/ruff/issues/8482#issuecomment-1859299411.
2024-01-29 17:33:22 +00:00
Mikko Leppänen
ad2cfa3dba [flake8-return] Consider exception suppress for unnecessary assignment (#9673)
## Summary

This review contains a fix for
[RET504](https://docs.astral.sh/ruff/rules/unnecessary-assign/)
(unnecessary-assign)

The problem is that Ruff suggests combining a return statement inside
contextlib.suppress. Even though it is an unsafe fix it might lead to an
invalid code that is not equivalent to the original one.

See: https://github.com/astral-sh/ruff/issues/5909

## Test Plan

```bash
cargo test
```
2024-01-29 12:29:05 -05:00
Micha Reiser
0045032905 Set source type: Stub for black tests with options (#9674) 2024-01-29 15:54:30 +01:00
Charlie Marsh
bea8f2ee3a Detect automagic-like assignments in notebooks (#9653)
## Summary

Given a statement like `colors = 6`, we currently treat the cell as an
automagic (since `colors` is an automagic) -- i.e., we assume it's
equivalent to `%colors = 6`. This PR adds some additional detection
whereby if the statement is an _assignment_, we avoid treating it as
such. I audited the list of automagics, and I believe this is safe for
all of them.

Closes https://github.com/astral-sh/ruff/issues/8526.

Closes https://github.com/astral-sh/ruff/issues/9648.

## Test Plan

`cargo test`
2024-01-29 12:55:44 +00:00
dependabot[bot]
c8074b0e18 Bump serde_with from 3.5.0 to 3.5.1 (#9672)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-29 10:10:22 +00:00
dependabot[bot]
740d8538de Bump chrono from 0.4.31 to 0.4.33 (#9671)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-29 11:01:46 +01:00
dependabot[bot]
341d7447a0 Bump serde_json from 1.0.111 to 1.0.113 (#9670)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-29 11:00:55 +01:00
dependabot[bot]
2e8aff647b Bump rayon from 1.8.0 to 1.8.1 (#9669)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-29 11:00:41 +01:00
dependabot[bot]
e555cf0ae4 Bump wasm-bindgen-test from 0.3.39 to 0.3.40 (#9668)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-29 10:59:58 +01:00
Mikko Leppänen
b9139a31d5 [flake8-pie] Omit bound tuples passed to .startswith or .endswith (#9661)
## Summary

This review contains a fix for
[PIE810](https://docs.astral.sh/ruff/rules/multiple-starts-ends-with/)
(multiple-starts-ends-with)

The problem is that ruff suggests combining multiple startswith/endswith
calls into a single call even though there might be a call with tuple of
strs. This leads to calling startswith/endswith with tuple of tuple of
strs which is incorrect and violates startswith/endswith conctract and
results in runtime failure.

However the following will be valid and fixed correctly => 
```python
x = ("hello", "world")
y = "h"
z = "w"
msg = "hello world"

if msg.startswith(x) or msg.startswith(y) or msg.startswith(z) :
      sys.exit(1)
```
```
ruff --fix --select PIE810 --unsafe-fixes
```
=> 
```python
if msg.startswith(x) or msg.startswith((y,z)):
      sys.exit(1)
```

See: https://github.com/astral-sh/ruff/issues/8906

## Test Plan

```bash
cargo test
```
2024-01-28 19:29:04 +00:00
Charlie Marsh
7329bf459c Avoid panic when fixing inlined else blocks (#9657)
Closes https://github.com/astral-sh/ruff/issues/9655.
2024-01-27 14:15:33 +00:00
Charlie Marsh
157d5bacfc [pydocstyle] Re-implement last-line-after-section (D413) (#9654)
## Summary

This rule was just incorrect, it didn't match the examples in the docs.
(It's a very rarely-used rule since it's not included in any of the
conventions.)

Closes https://github.com/astral-sh/ruff/issues/9452.
2024-01-26 19:30:59 +00:00
Mikko Leppänen
d496c164d3 [ruff] Guard against use of default_factory as a keyword argument (RUF026) (#9651)
## Summary

Add a rule for defaultdict(default_factory=callable). Instead suggest
using defaultdict(callable).

See: https://github.com/astral-sh/ruff/issues/9509

If a user tries to bind a "non-callable" to default_factory, the rule
ignores it. Another option would be to warn that it's probably not what
you want. Because Python allows the following:

```python 
from collections import defaultdict

defaultdict(default_factory=1)
```
this raises after you actually try to use it:

```python
dd = defaultdict(default_factory=1)
dd[1]
```
=> 
```bash
KeyError: 1
```

Instead using callable directly in the constructor it will raise (not
being a callable):

```python 
from collections import defaultdict

defaultdict(1)
```
=> 
```bash
TypeError: first argument must be callable or None
```




## Test Plan

```bash
cargo test
```
2024-01-26 19:10:05 +00:00
Charlie Marsh
b61b0edeea Add Pydantic's BaseConfig to default-copy list (#9650)
Closes https://github.com/astral-sh/ruff/issues/9647.
2024-01-26 14:54:48 +00:00
Charlie Marsh
79a0ddc112 Avoid rendering display-only rules as fixable (#9649)
Closes https://github.com/astral-sh/ruff/issues/9505.

The `ERA` rule is no longer marked as fixable:

![Screenshot 2024-01-26 at 9 17
48 AM](https://github.com/astral-sh/ruff/assets/1309177/fdc6217f-38ff-4098-b6ca-37ff51b710ab)
2024-01-26 09:47:01 -05:00
Micha Reiser
91046e4c81 Preserve indent around multiline strings (#9637) 2024-01-26 08:18:30 +01:00
Micha Reiser
5fe0fdd0a8 Delete is_node_with_body method (#9643) 2024-01-25 14:41:13 +00:00
Steve C
ffd13e65ae [flake8-return] - Add fixes for (RET505, RET506, RET507, RET508) (#9595) 2024-01-25 08:28:32 +01:00
Steve C
dba2cb79cb [pylint] Implement too-many-nested-blocks (PLR1702) (#9172)
## Summary

Implement
[`PLR1702`/`too-many-nested-blocks`](https://pylint.readthedocs.io/en/latest/user_guide/messages/refactor/too-many-nested-blocks.html)

See: #970 

## Test Plan

`cargo test`
2024-01-24 19:30:01 +00:00
Mikko Leppänen
45628a5883 [flake8-return] Take NoReturn annotation into account when analyzing implicit returns (#9636)
## Summary

When we are analyzing the implicit return rule this change add an
additional check to verify if the call expression has been annotated
with NoReturn type from typing module.

See: https://github.com/astral-sh/ruff/issues/5474

## Test Plan

```bash
cargo test
```
2024-01-24 17:19:26 +00:00
Andrew Gallant
fc3e2664f9 help: enable auto-wrapping of help output (#9633)
Previously, without the 'wrap_help' feature enabled, Clap would not do
any auto-wrapping of help text. For help text with long lines, this
tends to lead to non-ideal formatting. It can be especially difficult to
read when the width of the terminal is smaller.

This commit enables 'wrap_help', which will automatically cause Clap to
query the terminal size and wrap according to that. Or, if the terminal
size cannot be determined, it will default to a maximum line width of
100.

Ref https://github.com/astral-sh/ruff/pull/9599#discussion_r1464992692
2024-01-24 10:51:07 -05:00
Charlie Marsh
b0d6fd7343 Generate custom JSON schema for dynamic setting (#9632)
## Summary

If you paste in the TOML for our default configuration (from the docs),
it's rejected by our JSON Schema:

![Screenshot 2024-01-23 at 10 08
09 PM](https://github.com/astral-sh/ruff/assets/1309177/7b4ea6e8-07db-4590-bd1e-73a01a35d747)

It seems like the issue is with:

```toml
# Set the line length limit used when formatting code snippets in
# docstrings.
#
# This only has an effect when the `docstring-code-format` setting is
# enabled.
docstring-code-line-length = "dynamic"
```

Specifically, since that value uses a custom Serde implementation, I
guess Schemars bails out? This PR adds a custom representation to allow
`"dynamic"` (but no other strings):

![Screenshot 2024-01-23 at 10 27
21 PM](https://github.com/astral-sh/ruff/assets/1309177/ab7809d4-b077-44e9-8f98-ed893aaefe5d)

This seems like it should work but I don't have a great way to test it.

Closes https://github.com/astral-sh/ruff/issues/9630.
2024-01-24 04:26:02 +00:00
Charlie Marsh
87821252d7 Update SchemaStore script to install npm dependencies (#9631)
## Summary

SchemaStore now depends on some Prettier plugins, so we need to install
Prettier and its plugins as part of the project (rather than relying on
a global install).

## Test Plan

Ran the script!
2024-01-23 23:19:36 -05:00
Akira Noda
57313d9d63 [pylint] Implement assigning-non-slot (E0237) (#9623)
## Summary

Implement [assigning-non-slot /
E0237](https://pylint.readthedocs.io/en/latest/user_guide/messages/error/assigning-non-slot.html)

related #970

## Test Plan

`cargo test`
2024-01-24 02:50:22 +00:00
Mikko Leppänen
eab1a6862b [ruff] Detect unnecessary dict comprehensions for iterables (RUF025) (#9613)
## Summary

Checks for unnecessary `dict` comprehension when creating a new
dictionary from iterable. Suggest to replace with
`dict.fromkeys(iterable)`

See: https://github.com/astral-sh/ruff/issues/9592

## Test Plan

```bash
cargo test
```
2024-01-24 02:15:38 +00:00
Micha Reiser
395bf3dc98 Fix the input for black's line ranges test file (#9622) 2024-01-23 10:40:23 +00:00
Charlie Marsh
47b8a897e7 [flake8-simplify] Support inverted returns in needless-bool (SIM103) (#9619)
Closes https://github.com/astral-sh/ruff/issues/9618.
2024-01-23 03:26:53 +00:00
dependabot[bot]
e81976f754 Bump ignore from 0.4.21 to 0.4.22 (#9606)
Bumps [ignore](https://github.com/BurntSushi/ripgrep) from 0.4.21 to
0.4.22.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="2c3897585d"><code>2c38975</code></a>
ignore-0.4.22</li>
<li><a
href="c8e4a84519"><code>c8e4a84</code></a>
cli: prefix all non-fatal error messages with 'rg: '</li>
<li><a
href="b9c774937f"><code>b9c7749</code></a>
ignore: fix reference cycle for compiled matchers</li>
<li><a
href="67dd809a80"><code>67dd809</code></a>
ignore: add some 'allow(dead_code)' annotations</li>
<li><a
href="e0a85678e1"><code>e0a8567</code></a>
complete/fish: improve shell completions for fish</li>
<li><a
href="56c7ad175a"><code>56c7ad1</code></a>
ignore/types: add Lean</li>
<li><a
href="2a4dba3fbf"><code>2a4dba3</code></a>
ignore/types: add meson.options</li>
<li><a
href="daa157b5f9"><code>daa157b</code></a>
core: actually implement --sortr=path</li>
<li><a
href="0096c74c11"><code>0096c74</code></a>
grep-0.3.1</li>
<li><a
href="8c48355b03"><code>8c48355</code></a>
deps: bump grep-printer to 0.2.1</li>
<li>Additional commits viewable in <a
href="https://github.com/BurntSushi/ripgrep/compare/ignore-0.4.21...ignore-0.4.22">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ignore&package-manager=cargo&previous-version=0.4.21&new-version=0.4.22)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-22 08:00:16 -05:00
Alex Waygood
f5061dbb8e Add a rule/autofix to sort __slots__ and __match_args__ (#9564)
## Summary

This PR introduces a new rule to sort `__slots__` and `__match_args__`
according to a [natural sort](https://en.wikipedia.org/wiki/Natural_sort_order), as was
requested in https://github.com/astral-sh/ruff/issues/1198#issuecomment-1881418365.

The implementation here generalises some of the machinery introduced in
3aae16f1bd
so that different kinds of sorts can be applied to lists of string
literals. (We use an "isort-style" sort for `__all__`, but that isn't
really appropriate for `__slots__` and `__match_args__`, where nearly
all items will be snake_case.) Several sections of code have been moved
from `sort_dunder_all.rs` to a new module, `sorting_helpers.rs`, which
`sort_dunder_all.rs` and `sort_dunder_slots.rs` both make use of.

`__match_args__` is very similar to `__all__`, in that it can only be a
tuple or a list. `__slots__` differs from the other two, however, in
that it can be any iterable of strings. If slots is a dictionary, the
values are used by the builtin `help()` function as per-attribute
docstrings that show up in the output of `help()`. (There's no
particular use-case for making `__slots__` a set, but it's perfectly
legal at runtime, so there's no reason for us not to handle it in this
rule.)

Note that we don't do an autofix for multiline `__slots__` if `__slots__` is a dictionary: that's out of scope. Everything else, we can nearly always fix, however.

## Test Plan

`cargo test` / `cargo insta review`.

I also ran this rule on CPython, and the diff looked pretty good

---

Co-authored-by: Micha Reiser <micha@reiser.io>
2024-01-22 12:21:55 +00:00
dependabot[bot]
a3d667ed04 Bump shlex from 1.2.0 to 1.3.0 (#9609)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-22 08:39:48 +00:00
dependabot[bot]
76a069d0c9 Bump serde_with from 3.4.0 to 3.5.0 (#9608)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-22 08:39:28 +00:00
dependabot[bot]
b994fb3ce0 Bump smallvec from 1.11.2 to 1.13.1 (#9607)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-22 09:31:09 +01:00
dependabot[bot]
40a0231189 Bump serde_json from 1.0.109 to 1.0.111 (#9605)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-22 09:29:46 +01:00
Steve C
9c8a4d927e [flake8-simplify] Add fix for if-with-same-arms (SIM114) (#9591)
## Summary

 add fix for `if-with-same-arms` / `SIM114`

Also preserves comments!

## Test Plan

`cargo test`
2024-01-22 04:37:18 +00:00
trag1c
836e4406a5 Corrected code block hyperlink (#9602)
## Summary

Apparently MkDocs doesn't like when reference-style links have
formatting inside :)

<details>
<summary>Screenshots (before and after the change)</summary>
<img width="1235" alt="61353"
src="https://github.com/astral-sh/ruff/assets/77130613/e32a82bd-0c5d-4edb-998f-b53659a6c54d">

<img width="1237" alt="15526"
src="https://github.com/astral-sh/ruff/assets/77130613/bdafcda5-eb9c-4af6-af03-b4849c1e5c81">
</details>
2024-01-21 22:57:34 -05:00
Steve C
e54ed28ba9 [pylint] Add fix for collapsible-else-if (PLR5501) (#9594)
## Summary

adds a fix for `collapsible-else-if` / `PLR5501`

## Test Plan

`cargo test`
2024-01-21 19:53:15 -05:00
Tom Kuson
1e4b421a00 [ruff] Implement mutable-fromkeys-value (RUF024) (#9597)
## Summary

Implement rule `mutable-fromkeys-value` (`RUF023`).

Autofixes

```python
dict.fromkeys(foo, [])
```

to

```python
{key: [] for key in foo}
```

The fix is marked as unsafe as it changes runtime behaviour. It also
uses `key` as the comprehension variable, which may not always be
desired.

Closes #4613.

## Test Plan

`cargo test`
2024-01-22 00:22:02 +00:00
Charlie Marsh
a1f3cda190 Include global --config when determining namespace packages (#9603)
## Summary

When determining whether _any_ settings have namespace packages, we need
to consider the global settings (as would be provided via `--config`).
This was a subtle fallout of a refactor.

Closes https://github.com/astral-sh/ruff/issues/9579.

## Test Plan

Tested locally by compiling Ruff and running against this
[namespace-test](https://github.com/gokay05/namespace-test) repo.
2024-01-21 19:10:43 -05:00
Steve C
837984168a [pycodestyle] Add fix for multiple-imports-on-one-line (E401) (#9518)
## Summary

Add autofix for `multiple_imports_on_one_line`, `E401`

## Test Plan

`cargo test`
2024-01-21 15:33:38 -05:00
Charlie Marsh
b64aa1e86d Split pycodestyle import rules into separate files (#9600) 2024-01-21 19:30:00 +00:00
Steve C
9e5f3f1b1b [pylint] Add fix for useless-else-on-loop (PLW0120) (#9590)
## Summary

adds fix for `useless-else-on-loop` / `PLW0120`.

## Test Plan

`cargo test`
2024-01-21 11:17:58 -05:00
Robert Craigie
9dc59cbb81 Docs: fix isort rule code (#9598)
## Summary

Fixes a typo in the docs, the isort rule code in an example was not
correct.
2024-01-21 15:30:14 +00:00
Zanie Blue
a42600e9a2 Always unset the required-version option during ecosystem checks (#9593)
Uses our existing configuration overrides to unset the
`required-version` option in ecosystem projects during checks.

The downside to this approach, is we will now update the config file of
_every_ project (with a config file). This roughly normalizes the configuration file, as we
don't preserve comments and such. We could instead do a more targeted
approach applying this override to projects which we know use this
setting 🤷‍♀️
2024-01-20 23:07:11 -06:00
Steve C
49a445a23d [pylint] Implement potential-index-error (PLE0643) (#9545)
## Summary

add `potential-index-error` rule (`PLE0643`)

See: #970 

## Test Plan

`cargo test`
2024-01-21 03:59:48 +00:00
Charlie Marsh
866bea60a5 Bump version to v0.1.14 (#9581) 2024-01-19 12:54:39 -05:00
Charlie Marsh
df617c3093 [flake8-blind-except] Document exceptions to blind-except rule (#9580)
Closes https://github.com/astral-sh/ruff/issues/9571.
2024-01-19 16:58:31 +00:00
Micha Reiser
47ad7b4500 Approximate tokens len (#9546) 2024-01-19 17:39:37 +01:00
Alex Waygood
b3a6f0ce81 [flake8-pyi] Fix PYI049 false negatives on call-based TypedDicts (#9567)
## Summary

Fixes another of the bullet points from #8771

## Test Plan

`cargo test` / `cargo insta review`
2024-01-18 10:01:21 +00:00
Thomas M Kehrenberg
7be706641d [pylint] Exclude self and cls when counting method arguments (#9563)
## Summary

This PR detects whether PLR0917 is being applied to a method or class
method, and if so, it ignores the first argument for the purposes of
counting the number of positional arguments.

## Test Plan

New tests have been added to the corresponding fixture.

Closes #9552.
2024-01-18 03:17:45 +00:00
Alex Waygood
848e473f69 [flake8-pyi] Fix PYI047 false negatives on PEP-695 type aliases (#9566)
## Summary

Fixes one of the issues listed in
https://github.com/astral-sh/ruff/issues/8771. Fairly straightforward!

## Test Plan

`cargo test` / `cargo insta review`
2024-01-17 22:14:18 -05:00
Mark Byrne
368e2793b5 Documentation update for URL giving 'page not found' (#9565)
## Summary

Documentation - update the link in CONTRIBUTING.md to point to the
`ruff_python_parser` crate. It currently gives a `page not found`.
2024-01-17 10:57:54 -05:00
Charlie Marsh
29c130f326 Make ruff the default binary (#9558)
## Summary

This makes `cargo run` equivalent to `cargo run -p ruff` which is almost
always what you want.
2024-01-16 18:31:24 -05:00
Charlie Marsh
8118d29419 Rename ruff_cli crate to ruff (#9557)
## Summary

Long ago, we had a single `ruff` crate. We started to break that up, and
at some point, we wanted to separate the CLI from the core library. So
we created `ruff_cli`, which created a `ruff` binary. Later, the `ruff`
crate was renamed to `ruff_linter` and further broken up into additional
crates.

(This is all from memory -- I didn't bother to look through the history
to ensure that this is 100% correct :))

Now that `ruff` no longer exists, this PR renames `ruff_cli` to `ruff`.
The primary benefit is that the binary target and the crate name are now
the same, which helps with downstream tooling like `cargo-dist`, and
also removes some complexity from the crate and `Cargo.toml` itself.

## Test Plan

- Ran `rm -rf target/release`.
- Ran `cargo build --release`.
- Verified that `./target/release/ruff` was created.
2024-01-16 17:47:01 -05:00
Charlie Marsh
45d374d838 [refurb] Avoid bailing when reimplemented-operator is called on function (#9556)
Closes https://github.com/astral-sh/ruff/issues/9549.
2024-01-16 20:26:18 +00:00
Charlie Marsh
8788d57030 Add instructions on using noqa with isort rules (#9555)
Closes https://github.com/astral-sh/ruff/issues/9554.
2024-01-16 20:19:33 +00:00
Tom Kuson
f426c0fdaf [pylint] (Re-)Implement import-private-name (C2701) (#9553)
## Summary

#5920 with a fix for the erroneous slice in `module_name`. Fixes #9547.

## Test Plan

Added `import bbb.ccc._ddd as eee` to the test fixture to ensure it no
longer panics.

`cargo test`
2024-01-16 14:03:11 -05:00
Alex Waygood
3aae16f1bd Add rule and autofix to sort the contents of __all__ (#9474)
## Summary

This implements the rule proposed in #1198 (though it doesn't close the
issue, as there are some open questions about configuration that might
merit some further discussion).

## Test Plan

`cargo test` / `cargo insta review`. I also ran this PR branch on the CPython
codebase with `--fix --select=RUF022 --preview `, and the results looked
pretty good to me.

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
Co-authored-by: Andrew Gallant <andrew@astral.sh>
2024-01-16 14:42:47 +00:00
Hugo
3064312818 Bump ring dependency (#9550)
## Summary

This enabled building ruff on
[ppc64le](https://en.wikipedia.org/wiki/Ppc64).

See: https://gitlab.alpinelinux.org/alpine/aports/-/issues/15642


## Test Plan

I built ruff on x86_64 and arm64 and ran all tests with it. No failures.

There are no user-facing changes.
2024-01-16 08:51:52 -05:00
Micha Reiser
f9191b07c5 Revert "[pylint] Implement import-private-name (C2701)" (#9547) 2024-01-16 08:33:21 +00:00
Micha Reiser
21f2d0c90b Add an explicit fast path for whitespace to is_identifier_continuation (#9532) 2024-01-16 08:23:43 +00:00
Tom Kuson
2b605527bd [pylint] Implement import-private-name (C2701) (#5920)
## Summary

Implements [`import-private-name`
(`C2701`)](https://pylint.pycqa.org/en/latest/user_guide/messages/convention/import-private-name.html)
as `import-private-name` (`PLC2701`). Includes documentation.

Related to #970.

Closes https://github.com/astral-sh/ruff/issues/9138.

### PEP 420 namespace package limitation

`checker.module_path` doesn't seem to support automatic detection of
namespace packages (PEP 420). This leads to 'false' positives (Pylint
allows both).

Currently, for this to work like Pylint, users would have to [manually
input known namespace
packages](https://beta.ruff.rs/docs/settings/#namespace-packages).

## Test Plan

`cargo test`
2024-01-16 05:17:42 +00:00
Steve C
7ef7e0ddb6 [tryceratops] Add fix for error-instead-of-exception (TRY400) (#9520)
## Summary

add autofix for `error-instead-of-exception` (`TRY400`)

## Test Plan

`cargo test`
2024-01-16 03:00:04 +00:00
Steve C
2bddde2627 [pygrep_hooks] Add fix for deprecated-log-warn (PGH002) (#9519)
## Summary

add autofix for `deprecated_log_warn` (`PGH002`)

## Test Plan

`cargo test`

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2024-01-15 21:54:40 -05:00
Charlie Marsh
9a2f3e2cef Ignore preview status for fixable and unfixable selectors (#9538)
## Summary

Right now, if you run with `explicit-preview-rules`, and use something
like `select = ["RUF017"]`, we won't actually enable fixing for that
rule, because `fixable = ["ALL"]` (the default) won't include `RUF017`
due to the `explicit-preview-rules`.

The framing in this PR is that `explicit-preview-rules` should only
affect the enablement selectors, whereas the fixable selectors should
just include all possible matching rules. I think this will lead to the
most intuitive behavior.

Closes https://github.com/astral-sh/ruff/issues/9282. (An alternative to
https://github.com/astral-sh/ruff/pull/9284.)
2024-01-15 21:48:41 -05:00
Charlie Marsh
f9331c7683 Recursively visit deferred AST nodes (#9541)
## Summary

This PR is a more holistic fix for
https://github.com/astral-sh/ruff/issues/9534 and
https://github.com/astral-sh/ruff/issues/9159.

When we visit the AST, we track nodes that we need to visit _later_
(deferred nodes). For example, when visiting a function, we defer the
function body, since we don't want to visit the body until we've visited
the rest of the statements in the containing scope.

However, deferred nodes can themselves contain deferred nodes... For
example, a function body can contain a lambda (which contains a deferred
body). And then there are rarer cases, like a lambda inside of a type
annotation.

The aforementioned issues were fixed by reordering the deferral visits
to catch common cases. But even with those fixes, we still fail on cases
like:

```python
from __future__ import annotations

import re
from typing import cast

cast(lambda: re.match, 1)
```

Since we don't expect lambdas to appear inside of type definitions.

This PR modifies the `Checker` to keep visiting until all the deferred
stacks are empty. We _already_ do this for any one kind of deferred
node; now, we do it for _all_ of them at a level above.
2024-01-15 20:34:38 -05:00
Charlie Marsh
da275b8572 Visit deferred lambdas before type definitions (#9540)
## Summary

This is effectively the same problem as
https://github.com/astral-sh/ruff/pull/9175. And this just papers over
it again, though I'm gonna try a more holistic fix in a follow-up PR.
The _real_ fix here is that we need to continue to visit deferred items
until they're exhausted since, e.g., we still get this case wrong
(flagging `re` as unused):

```python
import re

cast(lambda: re.match, 1)
```

Closes https://github.com/astral-sh/ruff/issues/9534.
2024-01-15 20:08:40 -05:00
Charlie Marsh
b983ab1c6c Update contributing docs to use cargo bench -p ruff_benchmark (#9535)
## Summary

I found that `cargo benchmark lexer` didn't work as expected:

```shell
❯ cargo benchmark lexer
    Finished bench [optimized] target(s) in 0.08s
     Running benches/formatter.rs (target/release/deps/formatter-4e1d9bf9d3ba529d)
     Running benches/linter.rs (target/release/deps/linter-e449086ddfd8ad8c)
```

Turns out that `cargo bench -p ruff_benchmark` is now recommended over
`cargo benchmark`, so updating the docs to reflect that.
2024-01-15 14:57:30 -05:00
Alex Waygood
a1e65a92bd Move is_tuple_parenthesized from the formatter to ruff_python_ast (#9533)
This allows it to be used in the linter as well as the formatter. It
will be useful in #9474
2024-01-15 16:10:40 +00:00
Charlie Marsh
64aac5d526 Bump cloudflare/wrangler-action to v3.4.1 (#9531)
This is a subset of https://github.com/astral-sh/ruff/pull/9526 that
should be safe to apply.
2024-01-15 10:55:52 -05:00
Charlie Marsh
896cecddd3 Bump tj-actions/changed-files to v41 (#9530)
This is a subset of https://github.com/astral-sh/ruff/pull/9526 that
should be safe to apply.
2024-01-15 10:34:42 -05:00
yataka
0753968ef3 add the "__prepare__" method to the list of recognized dunder method (#9529)
## Summary
Closes #9508 .
Add `__prepare__` method to dunder method list in
`is_known_dunder_method`.

## Test Plan
1. add "__prepare__" method to `Apple` class in
crates/ruff_linter/resources/test/fixtures/pylint/bad_dunder_method_name.py.
2. run `cargo test`
2024-01-15 14:37:19 +00:00
dependabot[bot]
66804eca6d Bump similar from 2.3.0 to 2.4.0 (#9521)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-15 10:30:58 +01:00
dependabot[bot]
f8f38b7640 Bump assert_cmd from 2.0.12 to 2.0.13 (#9523)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-15 10:30:21 +01:00
dependabot[bot]
2e375860dd Bump js-sys from 0.3.66 to 0.3.67 (#9524)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-15 10:29:18 +01:00
dependabot[bot]
15740306ea Bump semver from 1.0.20 to 1.0.21 (#9525)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-15 10:28:03 +01:00
Steve C
6183b8e98b [refurb] Implement regex-flag-alias with fix (FURB167) (#9516)
## Summary

add
[`FURB167`/`use-long-regex-flag`](https://github.com/dosisod/refurb/blob/master/refurb/checks/regex/use_long_flag.py)
with autofix

See: #1348 

## Test Plan

`cargo test`

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2024-01-14 23:40:17 +00:00
Steve C
0c0d3db1b5 [flake8-bugbear] Add fix for duplicate-value (B033) (#9510)
## Summary

Adds autofix for
[B033](https://docs.astral.sh/ruff/rules/duplicate-value/)

## Test Plan

`cargo test`
2024-01-14 23:20:16 +00:00
Charlie Marsh
953d48b7f4 [flake8-simplify] Avoid some more enumerate-for-loop false positives (SIM113) (#9515)
Avoids, e.g., [this false
positive](a4fad5dda1/zerver/data_import/slack.py (L634))
from the ecosystem check.
2024-01-14 13:02:13 -05:00
Chammika Mannakkara
0003c730e0 [flake8-simplify] Implement enumerate-for-loop (SIM113) (#7777)
Implements SIM113 from #998

Added tests
Limitations 
   - No fix yet
   - Only flag cases where index variable immediately precede `for` loop

@charliermarsh please review and let me know any improvements

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2024-01-14 11:00:59 -05:00
port19
b6ce4f5f3a update emacs integration section to include emacs-ruff-format (#9403)
## Summary

For emacs users just seeking a ruff formatter, apheleia is overkill.
Instead, a melpa package
[emacs-ruff-format](https://github.com/scop/emacs-ruff-format) exists
now.
This change prepends a mention of this package, without removing
apheleia as an alternative.

## Test Plan

This is how I integrated ruff into my emacs.
2024-01-14 02:55:51 +00:00
Hoël Bagard
e8d7a6dfce Use the LinterSettings's tab size when expanding indent (#9506)
## Summary
In the `logical_lines`'s `expand_indent` , respect the
`LinterSettings::tab_size` setting instead of hardcoding the size of
tabs to 8.

Also see [this
conversation](https://github.com/astral-sh/ruff/pull/9266#discussion_r1447102212)

## Test Plan

Tested by running `cargo test`
2024-01-13 21:06:50 -05:00
pabepadu
ef2798f758 fix(docs): admonition in dark mode (#9502)
## Summary

The admonition in dark mode are in actually same as in light mode here:
https://docs.astral.sh/ruff/formatter/#ruff-format

I propose to move admonition in real dark mode as shown below:
- Before the PR https://github.com/astral-sh/ruff/pull/9385

![image](https://github.com/astral-sh/ruff/assets/45884742/abb7e0db-bf12-49cd-9f9b-e353accd571f)
- Current version

![image](https://github.com/astral-sh/ruff/assets/45884742/da8ab46d-dc87-412e-be2b-ac937cd87666)
- Proposal

![image](https://github.com/astral-sh/ruff/assets/45884742/7279cb02-e6af-4320-9dee-486fbfddcbc8)

Close #9501

## Test Plan

Documentation was regenerated via mkdocs and the supplied requirements.
2024-01-13 07:43:13 -05:00
Charlie Marsh
957a1f35c4 Ignore unnecessary dunder calls within dunder definitions (#9496)
Closes https://github.com/astral-sh/ruff/issues/9486.
2024-01-12 14:48:42 -05:00
Charlie Marsh
009430e034 [ruff] Avoid treating named expressions as static keys (RUF011) (#9494)
Closes https://github.com/astral-sh/ruff/issues/9487.
2024-01-12 14:33:45 -05:00
Jane Lewis
7504bf347b --show-settings displays active settings in a far more readable format (#9464)
<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

Fixes #8334.

`Display` has been implemented for `ruff_workspace::Settings`, which
gives a much nicer and more readable output to `--show-settings`.

Internally, a `display_settings` utility macro has been implemented to
reduce the boilerplate of the display code.

### Work to be done

- [x] A lot of formatting for `Vec<_>` and `HashSet<_>` types have been
stubbed out, using `Debug` as a fallback. There should be a way to add
generic formatting support for these types as a modifier in
`display_settings`.
- [x] Several complex types were also stubbed out and need proper
`Display` implementations rather than falling back on `Debug`.
- [x] An open question needs to be answered: how important is it that
the output be valid TOML? Some types in settings, such as a hash-map
from a glob pattern to a multi-variant enum, will be hard to rework into
valid _and_ readable TOML.
- [x] Tests need to be implemented.

## Test Plan

Tests consist of a snapshot test for the default `--show-settings`
output and a doctest for `display_settings!`.
2024-01-12 14:30:29 -05:00
Charlie Marsh
fee64b52ba Limit inplace diagnostics to methods that accept inplace (#9495)
## Summary

This should reduce false positives like
https://github.com/astral-sh/ruff/issues/9491, by ignoring methods that
are clearly not on a DataFrame.

Closes https://github.com/astral-sh/ruff/issues/9491.
2024-01-12 14:12:54 -05:00
Charlie Marsh
3261d16e61 Add --extension support to the formatter (#9483)
## Summary

We added `--extension` to `ruff check`, but it's equally applicable to
`ruff format`.

Closes https://github.com/astral-sh/ruff/issues/9482.

Resolves https://github.com/astral-sh/ruff/discussions/9481.

## Test Plan

`cargo test`
2024-01-12 18:53:25 +00:00
Charlie Marsh
d16c4a2d25 Bump version to v0.1.13 (#9493) 2024-01-12 09:27:39 -05:00
Aleksei Latyshev
1602df1643 Fix message for __aenter__ in PLC2801 (#9492)
<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

Fix the message for `__aenter__ ` in PLC2801 (introduced in
https://github.com/astral-sh/ruff/pull/9166)
There is no `aenter` builtin in Python, so the current message is
misleading.
I take the message from original lint
https://github.com/pylint-dev/pylint/blob/main/pylint/constants.py#L211

P.S. I think here should be more accurate synchronization with original
lint (e.g. the current implementation will not lint `__enter__` on my
first sight), but it is out-of-scope of this change.

<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan

<!-- How was it tested? -->
2024-01-12 08:48:45 -05:00
Alex Waygood
395cdf04e5 Fix backticks in RUF021 docs (#9488)
The docs for this rule aren't generating properly:
https://docs.astral.sh/ruff/rules/parenthesize-chained-operators/#why-is-this-bad.
I assume this is the reason why!
2024-01-12 09:00:44 +00:00
KotlinIsland
3daf6e1b6d (🐞) Add the missing period in error message (#9485)
<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->
I noticed that there should be a missing period added to some of the new
error messages for Unnecessary dunder call:
```
sandpit\test.py:6:16: PLC2801 Unnecessary dunder call to `__getattribute__`. Access attribute directly or use getattr built-in function..
```
## Test Plan

Static analysis of the implementation, as this has no existing test
cases.
2024-01-11 23:43:46 -05:00
Charlie Marsh
a31a314b2b Account for possibly-empty f-string values in truthiness logic (#9484)
Closes https://github.com/astral-sh/ruff/issues/9479.
2024-01-11 21:16:19 -05:00
Charlie Marsh
f9dd7bb190 Remove unreachable-code feature (#9463)
## Summary

We haven't found time to flip this on, so feels like it's best to remove
it for now -- can always restore from source when we get back to it.
2024-01-11 20:24:57 -05:00
Charlie Marsh
350dcb807a Include base pyproject when initializing cache settings (#9480)
## Summary

Regression from
https://github.com/astral-sh/ruff/pull/9453/files#diff-80a9c2637c432502a7075c792cc60db92282dd786999a78bfa9bb6f025afab35L482.

Closes https://github.com/astral-sh/ruff/issues/9478.

## Test Plan

```
rm -rf .ruff_cache
cargo run -p ruff_cli -- check ../foo.py
```

Failed prior to this PR; passes afterwards. The file must be outside of
the current working directory, and must not have a `pyproject.toml` in
any parent directory.
2024-01-11 19:18:49 -05:00
616 changed files with 23433 additions and 10893 deletions

View File

@@ -9,6 +9,10 @@ updates:
actions:
patterns:
- "*"
ignore:
# The latest versions of these are not compatible with our release workflow
- dependency-name: "actions/upload-artifact"
- dependency-name: "actions/download-artifact"
- package-ecosystem: "cargo"
directory: "/"

View File

@@ -35,7 +35,7 @@ jobs:
with:
fetch-depth: 0
- uses: tj-actions/changed-files@v40
- uses: tj-actions/changed-files@v42
id: changed
with:
files_yaml: |
@@ -76,6 +76,7 @@ jobs:
cargo-fmt:
name: "cargo fmt"
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: "Install Rust toolchain"
@@ -87,6 +88,7 @@ jobs:
runs-on: ubuntu-latest
needs: determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- name: "Install Rust toolchain"
@@ -100,10 +102,11 @@ jobs:
run: cargo clippy -p ruff_wasm --target wasm32-unknown-unknown --all-features --locked -- -D warnings
cargo-test-linux:
name: "cargo test (linux)"
runs-on: ubuntu-latest
needs: determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
name: "cargo test (linux)"
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- name: "Install Rust toolchain"
@@ -114,7 +117,10 @@ jobs:
tool: cargo-insta
- uses: Swatinem/rust-cache@v2
- name: "Run tests"
run: cargo insta test --all --all-features --unreferenced reject
run: cargo insta test --all --exclude ruff_dev --all-features --unreferenced reject
- name: "Run dev tests"
# e.g. generating the schema — these should not run with all features enabled
run: cargo insta test -p ruff_dev --unreferenced reject
# Check for broken links in the documentation.
- run: cargo doc --all --no-deps
env:
@@ -126,10 +132,11 @@ jobs:
path: target/debug/ruff
cargo-test-windows:
name: "cargo test (windows)"
runs-on: windows-latest
needs: determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
name: "cargo test (windows)"
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- name: "Install Rust toolchain"
@@ -142,13 +149,14 @@ jobs:
- 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
run: cargo insta test --all --exclude ruff_dev --all-features
cargo-test-wasm:
name: "cargo test (wasm)"
runs-on: ubuntu-latest
needs: determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
name: "cargo test (wasm)"
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: "Install Rust toolchain"
@@ -166,10 +174,11 @@ jobs:
wasm-pack test --node
cargo-fuzz:
name: "cargo fuzz"
runs-on: ubuntu-latest
needs: determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
name: "cargo fuzz"
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: "Install Rust toolchain"
@@ -188,6 +197,7 @@ jobs:
runs-on: ubuntu-latest
needs: determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- name: "Install Rust toolchain"
@@ -213,6 +223,7 @@ jobs:
if: github.event_name == 'pull_request' && ${{
needs.determine_changes.outputs.code == 'true'
}}
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
@@ -322,6 +333,7 @@ jobs:
runs-on: ubuntu-latest
needs: determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- name: "Install nightly Rust toolchain"
@@ -336,6 +348,7 @@ jobs:
python-package:
name: "python package"
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
@@ -360,6 +373,7 @@ jobs:
pre-commit:
name: "pre-commit"
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
@@ -371,7 +385,7 @@ jobs:
- name: "Install pre-commit"
run: pip install pre-commit
- name: "Cache pre-commit"
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ~/.cache/pre-commit
key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
@@ -388,6 +402,7 @@ jobs:
docs:
name: "mkdocs"
runs-on: ubuntu-latest
timeout-minutes: 10
env:
MKDOCS_INSIDERS_SSH_KEY_EXISTS: ${{ secrets.MKDOCS_INSIDERS_SSH_KEY != '' }}
steps:
@@ -425,6 +440,7 @@ jobs:
runs-on: ubuntu-latest
needs: determine_changes
if: needs.determine_changes.outputs.formatter == 'true' || github.ref == 'refs/heads/main'
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: "Install Rust toolchain"
@@ -441,6 +457,7 @@ jobs:
check-ruff-lsp:
name: "test ruff-lsp"
runs-on: ubuntu-latest
timeout-minutes: 5
needs:
- cargo-test-linux
- determine_changes
@@ -484,6 +501,7 @@ jobs:
runs-on: ubuntu-latest
needs: determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
timeout-minutes: 20
steps:
- name: "Checkout Branch"
uses: actions/checkout@v4

View File

@@ -47,7 +47,7 @@ jobs:
run: mkdocs build --strict -f mkdocs.public.yml
- name: "Deploy to Cloudflare Pages"
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
uses: cloudflare/wrangler-action@v3.3.2
uses: cloudflare/wrangler-action@v3.4.1
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }}

View File

@@ -40,7 +40,7 @@ jobs:
working-directory: playground
- name: "Deploy to Cloudflare Pages"
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
uses: cloudflare/wrangler-action@v3.3.2
uses: cloudflare/wrangler-action@v3.4.1
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }}

View File

@@ -61,7 +61,7 @@ jobs:
echo 'EOF' >> $GITHUB_OUTPUT
- name: Find existing comment
uses: peter-evans/find-comment@v2
uses: peter-evans/find-comment@v3
if: steps.generate-comment.outcome == 'success'
id: find-comment
with:
@@ -71,7 +71,7 @@ jobs:
- name: Create or update comment
if: steps.find-comment.outcome == 'success'
uses: peter-evans/create-or-update-comment@v3
uses: peter-evans/create-or-update-comment@v4
with:
comment-id: ${{ steps.find-comment.outputs.comment-id }}
issue-number: ${{ steps.pr-number.outputs.pr-number }}

View File

@@ -58,7 +58,7 @@ jobs:
path: dist
macos-x86_64:
runs-on: macos-latest
runs-on: macos-14
steps:
- uses: actions/checkout@v4
with:
@@ -74,11 +74,6 @@ jobs:
with:
target: x86_64
args: --release --locked --out dist
- name: "Test wheel - x86_64"
run: |
pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
ruff --help
python -m ruff --help
- name: "Upload wheels"
uses: actions/upload-artifact@v3
with:
@@ -98,7 +93,7 @@ jobs:
*.sha256
macos-universal:
runs-on: macos-latest
runs-on: macos-14
steps:
- uses: actions/checkout@v4
with:

View File

@@ -4,7 +4,7 @@ exclude: |
(?x)^(
crates/ruff_linter/resources/.*|
crates/ruff_linter/src/rules/.*/snapshots/.*|
crates/ruff_cli/resources/.*|
crates/ruff/resources/.*|
crates/ruff_python_formatter/resources/.*|
crates/ruff_python_formatter/tests/snapshots/.*|
crates/ruff_python_resolver/resources/.*|

View File

@@ -1,5 +1,107 @@
# Changelog
## 0.1.15
### Preview features
- Error when `NURSERY` selector is used with `--preview` ([#9682](https://github.com/astral-sh/ruff/pull/9682))
- Preserve indentation around multiline strings in formatter ([#9637](https://github.com/astral-sh/ruff/pull/9637))
- \[`flake8-return`\] Add fixes for all rules (`RET505`, `RET506`, `RET507`, `RET508`) ([#9595](https://github.com/astral-sh/ruff/pull/9595))
- \[`flake8-simplify`\] Add fix for `if-with-same-arms` (`SIM114`) ([#9591](https://github.com/astral-sh/ruff/pull/9591))
- \[`pycodestyle`\] Add fix for `multiple-imports-on-one-line` (`E401`) ([#9518](https://github.com/astral-sh/ruff/pull/9518))
- \[`pylint`\] Add fix for `collapsible-else-if` (`PLR5501`) ([#9594](https://github.com/astral-sh/ruff/pull/9594))
- \[`pylint`\] Add fix for `useless-else-on-loop` (`PLW0120`) ([#9590](https://github.com/astral-sh/ruff/pull/9590))
- \[`pylint`\] Implement `assigning-non-slot` (`E0237`) ([#9623](https://github.com/astral-sh/ruff/pull/9623))
- \[`pylint`\] Implement `potential-index-error` (`PLE0643`) ([#9545](https://github.com/astral-sh/ruff/pull/9545))
- \[`pylint`\] Implement `too-many-nested-blocks` (`PLR1702`) ([#9172](https://github.com/astral-sh/ruff/pull/9172))
- \[`ruff`\] Add rule to sort `__slots__` and `__match_args__` ([#9564](https://github.com/astral-sh/ruff/pull/9564))
- \[`ruff`\] Detect unnecessary `dict` comprehensions for iterables (`RUF025`) ([#9613](https://github.com/astral-sh/ruff/pull/9613))
- \[`ruff`\] Guard against use of `default_factory` as a keyword argument (`RUF026`) ([#9651](https://github.com/astral-sh/ruff/pull/9651))
- \[`ruff`\] Implement `mutable-fromkeys-value` (`RUF024`) ([#9597](https://github.com/astral-sh/ruff/pull/9597))
### CLI
- Enable auto-wrapping of `--help` output ([#9633](https://github.com/astral-sh/ruff/pull/9633))
### Bug fixes
- Avoid rendering display-only rules as fixable ([#9649](https://github.com/astral-sh/ruff/pull/9649))
- Detect automagic-like assignments in notebooks ([#9653](https://github.com/astral-sh/ruff/pull/9653))
- Generate custom JSON schema for dynamic setting ([#9632](https://github.com/astral-sh/ruff/pull/9632))
- \[`flake8-no-pep420`\] Include global `--config` when determining namespace packages ([#9603](https://github.com/astral-sh/ruff/pull/9603))
- \[`flake8-pie`\] Omit bound tuples passed to `.startswith` or `.endswith` ([#9661](https://github.com/astral-sh/ruff/pull/9661))
- \[`flake8-return`\] Avoid panic when fixing inlined else blocks ([#9657](https://github.com/astral-sh/ruff/pull/9657))
- \[`flake8-return`\] Consider exception suppression in unnecessary assignment ([#9673](https://github.com/astral-sh/ruff/pull/9673))
- \[`flake8-return`\] Take `NoReturn` annotation into account when analyzing implicit returns ([#9636](https://github.com/astral-sh/ruff/pull/9636))
- \[`flake8-simplify`\] Support inverted returns in `needless-bool` (`SIM103`) ([#9619](https://github.com/astral-sh/ruff/pull/9619))
- \[`flake8-type-checking`\] Add Pydantic's `BaseConfig` to default-copy list ([#9650](https://github.com/astral-sh/ruff/pull/9650))
- \[`flake8-type-checking`\] Avoid marking `InitVar` as a typing-only annotation ([#9688](https://github.com/astral-sh/ruff/pull/9688))
- \[`pycodestyle`\] Allow `dtype` comparisons in `type-comparison` ([#9676](https://github.com/astral-sh/ruff/pull/9676))
- \[`pydocstyle`\] Re-implement `last-line-after-section` (`D413`) ([#9654](https://github.com/astral-sh/ruff/pull/9654))
### Documentation
- \[`flake8-pytest-style`\] Add fix safety documentation for `duplicate-parameterize-test-cases` ([#9678](https://github.com/astral-sh/ruff/pull/9678))
- \[`pylint`\] Document `literal-membership` fix safety conditions ([#9677](https://github.com/astral-sh/ruff/pull/9677))
- \[`isort`\] Fix reference to `isort` rule code ([#9598](https://github.com/astral-sh/ruff/pull/9598))
## 0.1.14
### Preview features
- \[`flake8-bugbear`\] Add fix for `duplicate-value` (`B033`) ([#9510](https://github.com/astral-sh/ruff/pull/9510))
- \[`flake8-simplify`\] Implement `enumerate-for-loop` (`SIM113`) ([#7777](https://github.com/astral-sh/ruff/pull/7777))
- \[`pygrep_hooks`\] Add fix for `deprecated-log-warn` (`PGH002`) ([#9519](https://github.com/astral-sh/ruff/pull/9519))
- \[`pylint`\] Implement `import-private-name` (`C2701`) ([#5920](https://github.com/astral-sh/ruff/pull/5920))
- \[`refurb`\] Implement `regex-flag-alias` with fix (`FURB167`) ([#9516](https://github.com/astral-sh/ruff/pull/9516))
- \[`ruff`\] Add rule and fix to sort contents of `__all__` (`RUF022`) ([#9474](https://github.com/astral-sh/ruff/pull/9474))
- \[`tryceratops`\] Add fix for `error-instead-of-exception` (`TRY400`) ([#9520](https://github.com/astral-sh/ruff/pull/9520))
### Rule changes
- \[`flake8-pyi`\] Fix `PYI047` false negatives on PEP-695 type aliases ([#9566](https://github.com/astral-sh/ruff/pull/9566))
- \[`flake8-pyi`\] Fix `PYI049` false negatives on call-based `TypedDict`s ([#9567](https://github.com/astral-sh/ruff/pull/9567))
- \[`pylint`\] Exclude `self` and `cls` when counting method arguments (`PLR0917`) ([#9563](https://github.com/astral-sh/ruff/pull/9563))
### CLI
- `--show-settings` displays active settings in a far more readable format ([#9464](https://github.com/astral-sh/ruff/pull/9464))
- Add `--extension` support to the formatter ([#9483](https://github.com/astral-sh/ruff/pull/9483))
### Configuration
- Ignore preview status for fixable and unfixable selectors ([#9538](https://github.com/astral-sh/ruff/pull/9538))
- \[`pycodestyle`\] Use the configured tab size when expanding indents ([#9506](https://github.com/astral-sh/ruff/pull/9506))
### Bug fixes
- Recursively visit deferred AST nodes ([#9541](https://github.com/astral-sh/ruff/pull/9541))
- Visit deferred lambdas before type definitions ([#9540](https://github.com/astral-sh/ruff/pull/9540))
- \[`flake8-simplify`\] Avoid some more `enumerate-for-loop` false positives (`SIM113`) ([#9515](https://github.com/astral-sh/ruff/pull/9515))
- \[`pandas-vet`\] Limit inplace diagnostics to methods that accept inplace ([#9495](https://github.com/astral-sh/ruff/pull/9495))
- \[`pylint`\] Add the `__prepare__` method to the list of recognized dunder method ([#9529](https://github.com/astral-sh/ruff/pull/9529))
- \[`pylint`\] Ignore unnecessary dunder calls within dunder definitions ([#9496](https://github.com/astral-sh/ruff/pull/9496))
- \[`refurb`\] Avoid bailing when `reimplemented-operator` is called on function (`FURB118`) ([#9556](https://github.com/astral-sh/ruff/pull/9556))
- \[`ruff`\] Avoid treating named expressions as static keys (`RUF011`) ([#9494](https://github.com/astral-sh/ruff/pull/9494))
### Documentation
- Add instructions on using `noqa` with isort rules ([#9555](https://github.com/astral-sh/ruff/pull/9555))
- Documentation update for URL giving 'page not found' ([#9565](https://github.com/astral-sh/ruff/pull/9565))
- Fix admonition in dark mode ([#9502](https://github.com/astral-sh/ruff/pull/9502))
- Update contributing docs to use `cargo bench -p ruff_benchmark` ([#9535](https://github.com/astral-sh/ruff/pull/9535))
- Update emacs integration section to include `emacs-ruff-format` ([#9403](https://github.com/astral-sh/ruff/pull/9403))
- \[`flake8-blind-except`\] Document exceptions to `blind-except` rule ([#9580](https://github.com/astral-sh/ruff/pull/9580))
## 0.1.13
### Bug fixes
- Include base pyproject when initializing cache settings ([#9480](https://github.com/astral-sh/ruff/pull/9480))
- \[`flake8-simplify`\] Account for possibly-empty f-string values in truthiness logic ([#9484](https://github.com/astral-sh/ruff/pull/9484))
- \[`pylint`\] Add the missing period in `unnecessary-dunder-call` ([#9485](https://github.com/astral-sh/ruff/pull/9485))
- \[`pylint`\] Fix `__aenter__` message in `unnecessary-dunder-call` ([#9492](https://github.com/astral-sh/ruff/pull/9492))
## 0.1.12
### Preview features

View File

@@ -81,7 +81,7 @@ pre-commit install
After cloning the repository, run Ruff locally from the repository root with:
```shell
cargo run -p ruff_cli -- check /path/to/file.py --no-cache
cargo run -p ruff -- check /path/to/file.py --no-cache
```
Prior to opening a pull request, ensure that your code has been auto-formatted,
@@ -120,7 +120,7 @@ At the time of writing, the repository includes the following crates:
If you're working on a rule, this is the crate for you.
- `crates/ruff_benchmark`: binary crate for running micro-benchmarks.
- `crates/ruff_cache`: library crate for caching lint results.
- `crates/ruff_cli`: binary crate containing Ruff's command-line interface.
- `crates/ruff`: binary crate containing Ruff's command-line interface.
- `crates/ruff_dev`: binary crate containing utilities used in the development of Ruff itself (e.g.,
`cargo dev generate-all`), see the [`cargo dev`](#cargo-dev) section below.
- `crates/ruff_diagnostics`: library crate for the rule-independent abstractions in the lint
@@ -231,7 +231,7 @@ 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:
```shell
cargo run -p ruff_cli -- check crates/ruff_linter/resources/test/fixtures/pycodestyle/E402.py --no-cache --select E402
cargo run -p ruff -- check crates/ruff_linter/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
@@ -252,7 +252,7 @@ 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.
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 `Args` struct in `crates/ruff/src/args.rs`.
Second, the `pyproject.toml` options are defined in `crates/ruff_workspace/src/options.rs` (via the
`Options` struct), `crates/ruff_workspace/src/configuration.rs` (via the `Configuration` struct),
@@ -518,10 +518,10 @@ if the benchmark improved/regressed compared to that baseline.
```shell
# Run once on your "baseline" code
cargo benchmark --save-baseline=main
cargo bench -p ruff_benchmark -- --save-baseline=main
# Then iterate with
cargo benchmark --baseline=main
cargo bench -p ruff_benchmark -- --baseline=main
```
#### PR Summary
@@ -531,10 +531,10 @@ This is useful to illustrate the improvements of a PR.
```shell
# On main
cargo benchmark --save-baseline=main
cargo bench -p ruff_benchmark -- --save-baseline=main
# After applying your changes
cargo benchmark --save-baseline=pr
cargo bench -p ruff_benchmark -- --save-baseline=pr
critcmp main pr
```
@@ -547,10 +547,10 @@ cargo install critcmp
#### Tips
- Use `cargo benchmark <filter>` to only run specific benchmarks. For example: `cargo benchmark linter/pydantic`
to only run the pydantic tests.
- Use `cargo benchmark --quiet` for a more cleaned up output (without statistical relevance)
- Use `cargo benchmark --quick` to get faster results (more prone to noise)
- Use `cargo bench -p ruff_benchmark <filter>` to only run specific benchmarks. For example: `cargo benchmark lexer`
to only run the lexer benchmarks.
- Use `cargo bench -p ruff_benchmark -- --quiet` for a more cleaned up output (without statistical relevance)
- Use `cargo bench -p ruff_benchmark -- --quick` to get faster results (more prone to noise)
### Profiling Projects
@@ -618,7 +618,7 @@ Otherwise, follow the instructions from the linux section.
utils with it:
- `cargo dev print-ast <file>`: Print the AST of a python file using the
[RustPython parser](https://github.com/astral-sh/RustPython-Parser/tree/main/parser) that is
[RustPython parser](https://github.com/astral-sh/ruff/tree/main/crates/ruff_python_parser) that is
mainly used in Ruff. For `if True: pass # comment`, you can see the syntax tree, the byte offsets
for start and stop of each node and also how the `:` token, the comment and whitespace are not
represented anymore:

234
Cargo.lock generated
View File

@@ -75,9 +75,9 @@ dependencies = [
[[package]]
name = "anstream"
version = "0.6.4"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44"
checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -154,9 +154,9 @@ dependencies = [
[[package]]
name = "assert_cmd"
version = "2.0.12"
version = "2.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6"
checksum = "00ad3f3a942eee60335ab4342358c161ee296829e0d16ff42fc1d6cb07815467"
dependencies = [
"anstyle",
"bstr",
@@ -273,14 +273,14 @@ dependencies = [
[[package]]
name = "chrono"
version = "0.4.31"
version = "0.4.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb"
dependencies = [
"android-tzdata",
"iana-time-zone",
"num-traits",
"windows-targets 0.48.5",
"windows-targets 0.52.0",
]
[[package]]
@@ -312,9 +312,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.4.13"
version = "4.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52bdc885e4cacc7f7c9eedc1ef6da641603180c783c41a15c264944deeaab642"
checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c"
dependencies = [
"clap_builder",
"clap_derive",
@@ -322,14 +322,15 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.4.12"
version = "4.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9"
checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
"strsim",
"terminal_size",
]
[[package]]
@@ -956,9 +957,9 @@ dependencies = [
[[package]]
name = "ignore"
version = "0.4.21"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "747ad1b4ae841a78e8aba0d63adbfbeaea26b517b63705d47856b73015d27060"
checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1"
dependencies = [
"crossbeam-deque",
"globset",
@@ -1146,9 +1147,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "js-sys"
version = "0.3.66"
version = "0.3.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1"
dependencies = [
"wasm-bindgen",
]
@@ -1770,9 +1771,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.76"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
@@ -1855,9 +1856,9 @@ dependencies = [
[[package]]
name = "rayon"
version = "1.8.0"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051"
dependencies = [
"either",
"rayon-core",
@@ -1865,9 +1866,9 @@ dependencies = [
[[package]]
name = "rayon-core"
version = "1.12.0"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
@@ -1990,55 +1991,21 @@ dependencies = [
[[package]]
name = "ring"
version = "0.16.20"
version = "0.17.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74"
dependencies = [
"cc",
"getrandom",
"libc",
"once_cell",
"spin",
"untrusted",
"web-sys",
"winapi",
"windows-sys 0.48.0",
]
[[package]]
name = "ruff_benchmark"
version = "0.0.0"
dependencies = [
"codspeed-criterion-compat",
"criterion",
"mimalloc",
"once_cell",
"ruff_linter",
"ruff_python_ast",
"ruff_python_formatter",
"ruff_python_index",
"ruff_python_parser",
"serde",
"serde_json",
"tikv-jemallocator",
"ureq",
"url",
]
[[package]]
name = "ruff_cache"
version = "0.0.0"
dependencies = [
"filetime",
"glob",
"globset",
"itertools 0.12.0",
"regex",
"ruff_macros",
"seahash",
]
[[package]]
name = "ruff_cli"
version = "0.1.12"
name = "ruff"
version = "0.1.15"
dependencies = [
"anyhow",
"argfile",
@@ -2087,6 +2054,39 @@ dependencies = [
"wild",
]
[[package]]
name = "ruff_benchmark"
version = "0.0.0"
dependencies = [
"codspeed-criterion-compat",
"criterion",
"mimalloc",
"once_cell",
"ruff_linter",
"ruff_python_ast",
"ruff_python_formatter",
"ruff_python_index",
"ruff_python_parser",
"serde",
"serde_json",
"tikv-jemallocator",
"ureq",
"url",
]
[[package]]
name = "ruff_cache"
version = "0.0.0"
dependencies = [
"filetime",
"glob",
"globset",
"itertools 0.12.0",
"regex",
"ruff_macros",
"seahash",
]
[[package]]
name = "ruff_dev"
version = "0.0.0"
@@ -2103,7 +2103,7 @@ dependencies = [
"pretty_assertions",
"rayon",
"regex",
"ruff_cli",
"ruff",
"ruff_diagnostics",
"ruff_formatter",
"ruff_linter",
@@ -2165,7 +2165,7 @@ dependencies = [
[[package]]
name = "ruff_linter"
version = "0.1.12"
version = "0.1.15"
dependencies = [
"aho-corasick",
"annotate-snippets 0.9.2",
@@ -2417,7 +2417,7 @@ dependencies = [
[[package]]
name = "ruff_shrinking"
version = "0.1.12"
version = "0.1.15"
dependencies = [
"anyhow",
"clap",
@@ -2541,9 +2541,9 @@ dependencies = [
[[package]]
name = "rustls"
version = "0.21.7"
version = "0.21.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8"
checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba"
dependencies = [
"log",
"ring",
@@ -2553,9 +2553,9 @@ dependencies = [
[[package]]
name = "rustls-webpki"
version = "0.101.4"
version = "0.101.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d"
checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
dependencies = [
"ring",
"untrusted",
@@ -2620,9 +2620,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "sct"
version = "0.7.0"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
dependencies = [
"ring",
"untrusted",
@@ -2636,15 +2636,15 @@ checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]]
name = "semver"
version = "1.0.20"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
[[package]]
name = "serde"
version = "1.0.195"
version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
dependencies = [
"serde_derive",
]
@@ -2662,9 +2662,9 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.195"
version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
dependencies = [
"proc-macro2",
"quote",
@@ -2684,9 +2684,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.109"
version = "1.0.113"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9"
checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
dependencies = [
"itoa",
"ryu",
@@ -2713,9 +2713,9 @@ dependencies = [
[[package]]
name = "serde_with"
version = "3.4.0"
version = "3.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23"
checksum = "1b0ed1662c5a68664f45b76d18deb0e234aff37207086803165c961eb695e981"
dependencies = [
"serde",
"serde_with_macros",
@@ -2723,9 +2723,9 @@ dependencies = [
[[package]]
name = "serde_with_macros"
version = "3.4.0"
version = "3.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788"
checksum = "568577ff0ef47b879f736cd66740e022f3672788cdf002a05a4e609ea5a6fb15"
dependencies = [
"darling",
"proc-macro2",
@@ -2753,15 +2753,15 @@ dependencies = [
[[package]]
name = "shlex"
version = "1.2.0"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "similar"
version = "2.3.0"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2aeaf503862c419d66959f5d7ca015337d864e9c49485d771b732e2a20453597"
checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21"
[[package]]
name = "siphasher"
@@ -2771,15 +2771,15 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
[[package]]
name = "smallvec"
version = "1.11.2"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
[[package]]
name = "spin"
version = "0.5.2"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]]
name = "static_assertions"
@@ -2892,6 +2892,16 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "terminal_size"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7"
dependencies = [
"rustix",
"windows-sys 0.48.0",
]
[[package]]
name = "terminfo"
version = "0.8.0"
@@ -3260,9 +3270,9 @@ dependencies = [
[[package]]
name = "untrusted"
version = "0.7.1"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "ureq"
@@ -3393,9 +3403,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.89"
version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -3403,9 +3413,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.89"
version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd"
dependencies = [
"bumpalo",
"log",
@@ -3418,9 +3428,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.39"
version = "0.4.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12"
checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461"
dependencies = [
"cfg-if",
"js-sys",
@@ -3430,9 +3440,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.89"
version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -3440,9 +3450,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.89"
version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7"
dependencies = [
"proc-macro2",
"quote",
@@ -3453,15 +3463,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.89"
version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b"
[[package]]
name = "wasm-bindgen-test"
version = "0.3.39"
version = "0.3.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cf9242c0d27999b831eae4767b2a146feb0b27d332d553e605864acd2afd403"
checksum = "139bd73305d50e1c1c4333210c0db43d989395b64a237bd35c10ef3832a7f70c"
dependencies = [
"console_error_panic_hook",
"js-sys",
@@ -3473,9 +3483,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.3.39"
version = "0.3.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "794645f5408c9a039fd09f4d113cdfb2e7eba5ff1956b07bcf701cf4b394fe89"
checksum = "70072aebfe5da66d2716002c729a14e4aec4da0e23cc2ea66323dac541c93928"
dependencies = [
"proc-macro2",
"quote",
@@ -3494,9 +3504,9 @@ dependencies = [
[[package]]
name = "webpki-roots"
version = "0.25.2"
version = "0.25.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc"
checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10"
[[package]]
name = "which"
@@ -3511,9 +3521,9 @@ dependencies = [
[[package]]
name = "wild"
version = "2.2.0"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10d01931a94d5a115a53f95292f51d316856b68a035618eb831bbba593a30b67"
checksum = "a3131afc8c575281e1e80f36ed6a092aa502c08b18ed7524e86fbbb12bb410e1"
dependencies = [
"glob",
]

View File

@@ -16,12 +16,12 @@ aho-corasick = { version = "1.1.2" }
annotate-snippets = { version = "0.9.2", features = ["color"] }
anyhow = { version = "1.0.79" }
argfile = { version = "0.1.6" }
assert_cmd = { version = "2.0.8" }
assert_cmd = { version = "2.0.13" }
bincode = { version = "1.3.3" }
bitflags = { version = "2.4.1" }
cachedir = { version = "0.3.1" }
chrono = { version = "0.4.31", default-features = false, features = ["clock"] }
clap = { version = "4.4.13", features = ["derive"] }
chrono = { version = "0.4.33", default-features = false, features = ["clock"] }
clap = { version = "4.4.18", features = ["derive"] }
clap_complete_command = { version = "0.5.1" }
clearscreen = { version = "2.0.0" }
codspeed-criterion-compat = { version = "2.3.3", default-features = false }
@@ -40,7 +40,7 @@ fs-err = { version ="2.11.0"}
glob = { version = "0.3.1" }
globset = { version = "0.4.14" }
hexf-parse = { version ="0.2.1"}
ignore = { version = "0.4.21" }
ignore = { version = "0.4.22" }
imara-diff ={ version = "0.1.5"}
imperative = { version = "1.0.4" }
indicatif ={ version = "0.17.7"}
@@ -50,7 +50,7 @@ insta-cmd = { version = "0.4.0" }
is-macro = { version = "0.3.4" }
is-wsl = { version = "0.4.0" }
itertools = { version = "0.12.0" }
js-sys = { version = "0.3.66" }
js-sys = { version = "0.3.67" }
lalrpop-util = { version = "0.20.0", default-features = false }
lexical-parse-float = { version = "0.8.0", features = ["format"] }
libcst = { version = "1.1.0", default-features = false }
@@ -64,27 +64,27 @@ path-absolutize = { version = "3.1.1" }
pathdiff = { version = "0.2.1" }
pep440_rs = { version = "0.4.0", features = ["serde"] }
pretty_assertions = "1.3.0"
proc-macro2 = { version = "1.0.73" }
proc-macro2 = { version = "1.0.78" }
pyproject-toml = { version = "0.8.1" }
quick-junit = { version = "0.3.5" }
quote = { version = "1.0.23" }
rand = { version = "0.8.5" }
rayon = { version = "1.8.0" }
rayon = { version = "1.8.1" }
regex = { version = "1.10.2" }
result-like = { version = "0.5.0" }
rustc-hash = { version = "1.1.0" }
schemars = { version = "0.8.16" }
seahash = { version ="4.1.0"}
semver = { version = "1.0.20" }
serde = { version = "1.0.195", features = ["derive"] }
semver = { version = "1.0.21" }
serde = { version = "1.0.196", features = ["derive"] }
serde-wasm-bindgen = { version = "0.6.3" }
serde_json = { version = "1.0.109" }
serde_json = { version = "1.0.113" }
serde_test = { version = "1.0.152" }
serde_with = { version = "3.4.0", default-features = false, features = ["macros"] }
serde_with = { version = "3.6.0", default-features = false, features = ["macros"] }
shellexpand = { version = "3.0.0" }
shlex = { version ="1.2.0"}
similar = { version = "2.3.0", features = ["inline"] }
smallvec = { version = "1.11.2" }
shlex = { version ="1.3.0"}
similar = { version = "2.4.0", features = ["inline"] }
smallvec = { version = "1.13.1" }
static_assertions = "1.1.0"
strum = { version = "0.25.0", features = ["strum_macros"] }
strum_macros = { version = "0.25.3" }
@@ -107,7 +107,7 @@ url = { version = "2.5.0" }
uuid = { version = "1.6.1", features = ["v4", "fast-rng", "macro-diagnostics", "js"] }
walkdir = { version = "2.3.2" }
wasm-bindgen = { version = "0.2.84" }
wasm-bindgen-test = { version = "0.3.39" }
wasm-bindgen-test = { version = "0.3.40" }
wild = { version = "2" }
[workspace.lints.rust]

View File

@@ -150,7 +150,7 @@ Ruff can also be used as a [pre-commit](https://pre-commit.com/) hook via [`ruff
```yaml
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.1.12
rev: v0.1.15
hooks:
# Run the linter.
- id: ruff
@@ -402,6 +402,7 @@ Ruff is used by a number of major open-source projects and companies, including:
[Diffusers](https://github.com/huggingface/diffusers))
- ING Bank ([popmon](https://github.com/ing-bank/popmon), [probatus](https://github.com/ing-bank/probatus))
- [Ibis](https://github.com/ibis-project/ibis)
- [ivy](https://github.com/unifyai/ivy)
- [Jupyter](https://github.com/jupyter-server/jupyter_server)
- [LangChain](https://github.com/hwchase17/langchain)
- [Litestar](https://litestar.dev/)

View File

@@ -1,6 +1,6 @@
[package]
name = "ruff_cli"
version = "0.1.12"
name = "ruff"
version = "0.1.15"
publish = false
authors = { workspace = true }
edition = { workspace = true }
@@ -10,9 +10,7 @@ documentation = { workspace = true }
repository = { workspace = true }
license = { workspace = true }
readme = "../../README.md"
[[bin]]
name = "ruff"
default-run = "ruff"
[dependencies]
ruff_cache = { path = "../ruff_cache" }
@@ -32,7 +30,7 @@ bincode = { workspace = true }
bitflags = { workspace = true }
cachedir = { workspace = true }
chrono = { workspace = true }
clap = { workspace = true, features = ["derive", "env"] }
clap = { workspace = true, features = ["derive", "env", "wrap_help"] }
clap_complete_command = { workspace = true }
clearscreen = { workspace = true }
colored = { workspace = true }
@@ -56,6 +54,8 @@ walkdir = { workspace = true }
wild = { workspace = true }
[dev-dependencies]
# Enable test rules during development
ruff_linter = { path = "../ruff_linter", features = ["clap", "test-rules"] }
assert_cmd = { workspace = true }
# Avoid writing colored snapshots when running tests from the terminal
colored = { workspace = true, features = ["no-color"]}

View File

@@ -11,7 +11,7 @@ use ruff_linter::settings::types::{
ExtensionPair, FilePattern, PatternPrefixPair, PerFileIgnore, PreviewMode, PythonVersion,
SerializationFormat, UnsafeFixes,
};
use ruff_linter::{RuleParser, RuleSelector, RuleSelectorParser};
use ruff_linter::{warn_user, RuleParser, RuleSelector, RuleSelectorParser};
use ruff_workspace::configuration::{Configuration, RuleSelection};
use ruff_workspace::options::PycodestyleOptions;
use ruff_workspace::resolver::ConfigurationTransformer;
@@ -83,7 +83,7 @@ pub enum Command {
},
}
// The `Parser` derive is for ruff_dev, for ruff_cli `Args` would be sufficient
// The `Parser` derive is for ruff_dev, for ruff `Args` would be sufficient
#[derive(Clone, Debug, clap::Parser)]
#[allow(clippy::struct_excessive_bools)]
pub struct CheckCommand {
@@ -104,6 +104,7 @@ pub struct CheckCommand {
no_unsafe_fixes: bool,
/// Show violations with source code.
/// Use `--no-show-source` to disable.
/// (Deprecated: use `--output-format=full` or `--output-format=concise` instead of `--show-source` and `--no-show-source`, respectively)
#[arg(long, overrides_with("no_show_source"))]
show_source: bool,
#[clap(long, overrides_with("show_source"), hide = true)]
@@ -131,6 +132,8 @@ pub struct CheckCommand {
ignore_noqa: bool,
/// Output serialization format for violations.
/// The default serialization format is "concise".
/// In preview mode, the default serialization format is "full".
#[arg(long, value_enum, env = "RUFF_OUTPUT_FORMAT")]
pub output_format: Option<SerializationFormat>,
@@ -290,6 +293,10 @@ pub struct CheckCommand {
/// The name of the file when passing it through stdin.
#[arg(long, help_heading = "Miscellaneous")]
pub stdin_filename: Option<PathBuf>,
/// List of mappings from file extension to language (one of ["python", "ipynb", "pyi"]). For
/// example, to treat `.ipy` files as IPython notebooks, use `--extension ipy:ipynb`.
#[arg(long, value_delimiter = ',')]
pub extension: Option<Vec<ExtensionPair>>,
/// Exit with status code "0", even upon detecting lint violations.
#[arg(
short,
@@ -352,9 +359,6 @@ pub struct CheckCommand {
conflicts_with = "watch",
)]
pub show_settings: bool,
/// List of mappings from file extension to language (one of ["python", "ipynb", "pyi"]).
#[arg(long, value_delimiter = ',', hide = true)]
pub extension: Option<Vec<ExtensionPair>>,
/// Dev-only argument to show fixes
#[arg(long, hide = true)]
pub ecosystem_ci: bool,
@@ -423,6 +427,10 @@ pub struct FormatCommand {
/// The name of the file when passing it through stdin.
#[arg(long, help_heading = "Miscellaneous")]
pub stdin_filename: Option<PathBuf>,
/// List of mappings from file extension to language (one of ["python", "ipynb", "pyi"]). For
/// example, to treat `.ipy` files as IPython notebooks, use `--extension ipy:ipynb`.
#[arg(long, value_delimiter = ',')]
pub extension: Option<Vec<ExtensionPair>>,
/// The minimum Python version that should be supported.
#[arg(long, value_enum)]
pub target_version: Option<PythonVersion>,
@@ -528,7 +536,6 @@ impl CheckCommand {
self.no_respect_gitignore,
),
select: self.select,
show_source: resolve_bool_arg(self.show_source, self.no_show_source),
target_version: self.target_version,
unfixable: self.unfixable,
// TODO(charlie): Included in `pyproject.toml`, but not inherited.
@@ -538,7 +545,11 @@ impl CheckCommand {
unsafe_fixes: resolve_bool_arg(self.unsafe_fixes, self.no_unsafe_fixes)
.map(UnsafeFixes::from),
force_exclude: resolve_bool_arg(self.force_exclude, self.no_force_exclude),
output_format: self.output_format,
output_format: resolve_output_format(
self.output_format,
resolve_bool_arg(self.show_source, self.no_show_source),
resolve_bool_arg(self.preview, self.no_preview).unwrap_or_default(),
),
show_fixes: resolve_bool_arg(self.show_fixes, self.no_show_fixes),
extension: self.extension,
},
@@ -571,6 +582,7 @@ impl FormatCommand {
force_exclude: resolve_bool_arg(self.force_exclude, self.no_force_exclude),
target_version: self.target_version,
cache_dir: self.cache_dir,
extension: self.extension,
// Unsupported on the formatter CLI, but required on `Overrides`.
..CliOverrides::default()
@@ -588,6 +600,43 @@ fn resolve_bool_arg(yes: bool, no: bool) -> Option<bool> {
}
}
fn resolve_output_format(
output_format: Option<SerializationFormat>,
show_sources: Option<bool>,
preview: bool,
) -> Option<SerializationFormat> {
Some(match (output_format, show_sources) {
(Some(o), None) => o,
(Some(SerializationFormat::Grouped), Some(true)) => {
warn_user!("`--show-source` with `--output-format=grouped` is deprecated, and will not show source files. Use `--output-format=full` to show source information.");
SerializationFormat::Grouped
}
(Some(fmt), Some(true)) => {
warn_user!("The `--show-source` argument is deprecated and has been ignored in favor of `--output-format={fmt}`.");
fmt
}
(Some(fmt), Some(false)) => {
warn_user!("The `--no-show-source` argument is deprecated and has been ignored in favor of `--output-format={fmt}`.");
fmt
}
(None, Some(true)) => {
warn_user!("The `--show-source` argument is deprecated. Use `--output-format=full` instead.");
SerializationFormat::Full
}
(None, Some(false)) => {
warn_user!("The `--no-show-source` argument is deprecated. Use `--output-format=concise` instead.");
SerializationFormat::Concise
}
(None, None) => return None
}).map(|format| match format {
SerializationFormat::Text => {
warn_user!("`--output-format=text` is deprecated. Use `--output-format=full` or `--output-format=concise` instead. `text` will be treated as `{}`.", SerializationFormat::default(preview));
SerializationFormat::default(preview)
},
other => other
})
}
/// CLI settings that are distinct from configuration (commands, lists of files,
/// etc.).
#[allow(clippy::struct_excessive_bools)]
@@ -642,7 +691,6 @@ pub struct CliOverrides {
pub preview: Option<PreviewMode>,
pub respect_gitignore: Option<bool>,
pub select: Option<Vec<RuleSelector>>,
pub show_source: Option<bool>,
pub target_version: Option<PythonVersion>,
pub unfixable: Option<Vec<RuleSelector>>,
// TODO(charlie): Captured in pyproject.toml as a default, but not part of `Settings`.
@@ -729,9 +777,6 @@ impl ConfigurationTransformer for CliOverrides {
if let Some(respect_gitignore) = &self.respect_gitignore {
config.respect_gitignore = Some(*respect_gitignore);
}
if let Some(show_source) = &self.show_source {
config.show_source = Some(*show_source);
}
if let Some(show_fixes) = &self.show_fixes {
config.show_fixes = Some(*show_fixes);
}
@@ -739,7 +784,7 @@ impl ConfigurationTransformer for CliOverrides {
config.target_version = Some(*target_version);
}
if let Some(extension) = &self.extension {
config.lint.extension = Some(extension.clone().into_iter().collect());
config.extension = Some(extension.iter().cloned().collect());
}
config

View File

@@ -106,13 +106,19 @@ pub(crate) fn format(
match entry {
Ok(resolved_file) => {
let path = resolved_file.path();
let SourceType::Python(source_type) = SourceType::from(&path) else {
// Ignore any non-Python files.
return None;
};
let settings = resolver.resolve(path);
let source_type = match settings.formatter.extension.get(path) {
None => match SourceType::from(path) {
SourceType::Python(source_type) => source_type,
SourceType::Toml(_) => {
// Ignore any non-Python files.
return None;
}
},
Some(language) => PySourceType::from(language),
};
// Ignore files that are excluded from formatting
if (settings.file_resolver.force_exclude || !resolved_file.is_root())
&& match_exclusion(

View File

@@ -53,16 +53,23 @@ pub(crate) fn format_stdin(cli: &FormatArguments, overrides: &CliOverrides) -> R
}
let path = cli.stdin_filename.as_deref();
let settings = &resolver.base_settings().formatter;
let SourceType::Python(source_type) = path.map(SourceType::from).unwrap_or_default() else {
if mode.is_write() {
parrot_stdin()?;
}
return Ok(ExitStatus::Success);
let source_type = match path.and_then(|path| settings.extension.get(path)) {
None => match path.map(SourceType::from).unwrap_or_default() {
SourceType::Python(source_type) => source_type,
SourceType::Toml(_) => {
if mode.is_write() {
parrot_stdin()?;
}
return Ok(ExitStatus::Success);
}
},
Some(language) => PySourceType::from(language),
};
// Format the file.
match format_source_code(path, &resolver.base_settings().formatter, source_type, mode) {
match format_source_code(path, settings, source_type, mode) {
Ok(result) => match mode {
FormatMode::Write => Ok(ExitStatus::Success),
FormatMode::Check | FormatMode::Diff => {

View File

@@ -35,7 +35,7 @@ pub(crate) fn show_settings(
if let Some(settings_path) = pyproject_config.path.as_ref() {
writeln!(writer, "Settings path: {settings_path:?}")?;
}
writeln!(writer, "{settings:#?}")?;
write!(writer, "{settings}")?;
Ok(())
}

View File

@@ -1,5 +1,5 @@
---
source: crates/ruff_cli/src/commands/check.rs
source: crates/ruff/src/commands/check.rs
---
/home/ferris/project/code.py:1:1: E902 Permission denied (os error 13)
/home/ferris/project/notebook.ipynb:1:1: E902 Permission denied (os error 13)

View File

@@ -17,7 +17,7 @@ use ruff_linter::logging::DisplayParseError;
use ruff_linter::message::Message;
use ruff_linter::pyproject_toml::lint_pyproject_toml;
use ruff_linter::registry::AsRule;
use ruff_linter::settings::types::{ExtensionMapping, UnsafeFixes};
use ruff_linter::settings::types::UnsafeFixes;
use ruff_linter::settings::{flags, LinterSettings};
use ruff_linter::source_kind::{SourceError, SourceKind};
use ruff_linter::{fs, IOError, SyntaxError};
@@ -179,11 +179,6 @@ impl AddAssign for FixMap {
}
}
fn override_source_type(path: Option<&Path>, extension: &ExtensionMapping) -> Option<PySourceType> {
let ext = path?.extension()?.to_str()?;
extension.get(ext).map(PySourceType::from)
}
/// Lint the source code at the given `Path`.
pub(crate) fn lint_path(
path: &Path,
@@ -228,7 +223,7 @@ pub(crate) fn lint_path(
debug!("Checking: {}", path.display());
let source_type = match override_source_type(Some(path), &settings.extension) {
let source_type = match settings.extension.get(path).map(PySourceType::from) {
Some(source_type) => source_type,
None => match SourceType::from(path) {
SourceType::Toml(TomlSourceType::Pyproject) => {
@@ -398,15 +393,14 @@ pub(crate) fn lint_stdin(
fix_mode: flags::FixMode,
) -> Result<Diagnostics> {
// TODO(charlie): Support `pyproject.toml`.
let source_type = if let Some(source_type) =
override_source_type(path, &settings.linter.extension)
{
source_type
} else {
let SourceType::Python(source_type) = path.map(SourceType::from).unwrap_or_default() else {
return Ok(Diagnostics::default());
};
source_type
let source_type = match path.and_then(|path| settings.linter.extension.get(path)) {
None => match path.map(SourceType::from).unwrap_or_default() {
SourceType::Python(source_type) => source_type,
SourceType::Toml(_) => {
return Ok(Diagnostics::default());
}
},
Some(language) => PySourceType::from(language),
};
// Extract the sources from the file.

View File

@@ -255,7 +255,6 @@ pub fn check(args: CheckCommand, log_level: LogLevel) -> Result<ExitStatus> {
unsafe_fixes,
output_format,
show_fixes,
show_source,
..
} = pyproject_config.settings;
@@ -284,9 +283,6 @@ pub fn check(args: CheckCommand, log_level: LogLevel) -> Result<ExitStatus> {
if show_fixes {
printer_flags |= PrinterFlags::SHOW_FIX_SUMMARY;
}
if show_source {
printer_flags |= PrinterFlags::SHOW_SOURCE;
}
if cli.ecosystem_ci {
warn_user!(
"The formatting of fixes emitted by this option is a work-in-progress, subject to \
@@ -325,9 +321,14 @@ pub fn check(args: CheckCommand, log_level: LogLevel) -> Result<ExitStatus> {
printer_flags,
);
let preview = overrides.preview.unwrap_or_default().is_enabled();
if cli.watch {
if output_format != SerializationFormat::Text {
warn_user!("`--output-format text` is always used in watch mode.");
if output_format != SerializationFormat::default(preview) {
warn_user!(
"`--output-format {}` is always used in watch mode.",
SerializationFormat::default(preview)
);
}
// Configure the file watcher.
@@ -353,7 +354,7 @@ pub fn check(args: CheckCommand, log_level: LogLevel) -> Result<ExitStatus> {
fix_mode,
unsafe_fixes,
)?;
printer.write_continuously(&mut writer, &messages)?;
printer.write_continuously(&mut writer, &messages, preview)?;
// In watch mode, we may need to re-resolve the configuration.
// TODO(charlie): Re-compute other derivative values, like the `printer`.
@@ -386,7 +387,7 @@ pub fn check(args: CheckCommand, log_level: LogLevel) -> Result<ExitStatus> {
fix_mode,
unsafe_fixes,
)?;
printer.write_continuously(&mut writer, &messages)?;
printer.write_continuously(&mut writer, &messages, preview)?;
}
Err(err) => return Err(err.into()),
}

View File

@@ -3,8 +3,8 @@ use std::process::ExitCode;
use clap::{Parser, Subcommand};
use colored::Colorize;
use ruff_cli::args::{Args, Command};
use ruff_cli::{run, ExitStatus};
use ruff::args::{Args, Command};
use ruff::{run, ExitStatus};
#[cfg(target_os = "windows")]
#[global_allocator]

View File

@@ -27,8 +27,6 @@ bitflags! {
pub(crate) struct Flags: u8 {
/// Whether to show violations when emitting diagnostics.
const SHOW_VIOLATIONS = 0b0000_0001;
/// Whether to show the source code when emitting diagnostics.
const SHOW_SOURCE = 0b000_0010;
/// Whether to show a summary of the fixed violations when emitting diagnostics.
const SHOW_FIX_SUMMARY = 0b0000_0100;
/// Whether to show a diff of each fixed violation when emitting diagnostics.
@@ -218,7 +216,10 @@ impl Printer {
if !self.flags.intersects(Flags::SHOW_VIOLATIONS) {
if matches!(
self.format,
SerializationFormat::Text | SerializationFormat::Grouped
SerializationFormat::Text
| SerializationFormat::Full
| SerializationFormat::Concise
| SerializationFormat::Grouped
) {
if self.flags.intersects(Flags::SHOW_FIX_SUMMARY) {
if !diagnostics.fixed.is_empty() {
@@ -245,11 +246,12 @@ impl Printer {
SerializationFormat::Junit => {
JunitEmitter.emit(writer, &diagnostics.messages, &context)?;
}
SerializationFormat::Text => {
SerializationFormat::Concise
| SerializationFormat::Full => {
TextEmitter::default()
.with_show_fix_status(show_fix_status(self.fix_mode, fixables.as_ref()))
.with_show_fix_diff(self.flags.intersects(Flags::SHOW_FIX_DIFF))
.with_show_source(self.flags.intersects(Flags::SHOW_SOURCE))
.with_show_source(self.format == SerializationFormat::Full)
.with_unsafe_fixes(self.unsafe_fixes)
.emit(writer, &diagnostics.messages, &context)?;
@@ -265,7 +267,6 @@ impl Printer {
}
SerializationFormat::Grouped => {
GroupedEmitter::default()
.with_show_source(self.flags.intersects(Flags::SHOW_SOURCE))
.with_show_fix_status(show_fix_status(self.fix_mode, fixables.as_ref()))
.with_unsafe_fixes(self.unsafe_fixes)
.emit(writer, &diagnostics.messages, &context)?;
@@ -294,6 +295,7 @@ impl Printer {
SerializationFormat::Sarif => {
SarifEmitter.emit(writer, &diagnostics.messages, &context)?;
}
SerializationFormat::Text => unreachable!("Text is deprecated and should have been automatically converted to the default serialization format")
}
writer.flush()?;
@@ -342,7 +344,9 @@ impl Printer {
}
match self.format {
SerializationFormat::Text => {
SerializationFormat::Text
| SerializationFormat::Full
| SerializationFormat::Concise => {
// Compute the maximum number of digits in the count and code, for all messages,
// to enable pretty-printing.
let count_width = num_digits(
@@ -403,6 +407,7 @@ impl Printer {
&self,
writer: &mut dyn Write,
diagnostics: &Diagnostics,
preview: bool,
) -> Result<()> {
if matches!(self.log_level, LogLevel::Silent) {
return Ok(());
@@ -430,7 +435,7 @@ impl Printer {
let context = EmitterContext::new(&diagnostics.notebook_indexes);
TextEmitter::default()
.with_show_fix_status(show_fix_status(self.fix_mode, fixables.as_ref()))
.with_show_source(self.flags.intersects(Flags::SHOW_SOURCE))
.with_show_source(preview)
.with_unsafe_fixes(self.unsafe_fixes)
.emit(writer, &diagnostics.messages, &context)?;
}

View File

@@ -0,0 +1,5 @@
---
source: crates/ruff/src/version.rs
expression: version
---
0.0.0

View File

@@ -1,5 +1,5 @@
---
source: crates/ruff_cli/src/version.rs
source: crates/ruff/src/version.rs
expression: version
---
0.0.0 (53b0f5d92 2023-10-19)

View File

@@ -1,5 +1,5 @@
---
source: crates/ruff_cli/src/version.rs
source: crates/ruff/src/version.rs
expression: version
---
0.0.0+24 (53b0f5d92 2023-10-19)

View File

@@ -1,5 +1,5 @@
---
source: crates/ruff_cli/src/version.rs
source: crates/ruff/src/version.rs
expression: version
---
{

View File

@@ -0,0 +1,149 @@
//! A test suite that ensures deprecated command line options have appropriate warnings / behaviors
use ruff_linter::settings::types::SerializationFormat;
use std::process::Command;
use insta_cmd::{assert_cmd_snapshot, get_cargo_bin};
const BIN_NAME: &str = "ruff";
const STDIN: &str = "l = 1";
fn ruff_check(show_source: Option<bool>, output_format: Option<String>) -> Command {
let mut cmd = Command::new(get_cargo_bin(BIN_NAME));
let output_format = output_format.unwrap_or(format!("{}", SerializationFormat::default(false)));
cmd.arg("--output-format");
cmd.arg(output_format);
cmd.arg("--no-cache");
match show_source {
Some(true) => {
cmd.arg("--show-source");
}
Some(false) => {
cmd.arg("--no-show-source");
}
None => {}
}
cmd.arg("-");
cmd
}
#[test]
fn ensure_show_source_is_deprecated() {
assert_cmd_snapshot!(ruff_check(Some(true), None).pass_stdin(STDIN), @r###"
success: false
exit_code: 1
----- stdout -----
-:1:1: E741 Ambiguous variable name: `l`
Found 1 error.
----- stderr -----
warning: The `--show-source` argument is deprecated and has been ignored in favor of `--output-format=concise`.
"###);
}
#[test]
fn ensure_no_show_source_is_deprecated() {
assert_cmd_snapshot!(ruff_check(Some(false), None).pass_stdin(STDIN), @r###"
success: false
exit_code: 1
----- stdout -----
-:1:1: E741 Ambiguous variable name: `l`
Found 1 error.
----- stderr -----
warning: The `--no-show-source` argument is deprecated and has been ignored in favor of `--output-format=concise`.
"###);
}
#[test]
fn ensure_output_format_is_deprecated() {
assert_cmd_snapshot!(ruff_check(None, Some("text".into())).pass_stdin(STDIN), @r###"
success: false
exit_code: 1
----- stdout -----
-:1:1: E741 Ambiguous variable name: `l`
Found 1 error.
----- stderr -----
warning: `--output-format=text` is deprecated. Use `--output-format=full` or `--output-format=concise` instead. `text` will be treated as `concise`.
"###);
}
#[test]
fn ensure_output_format_overrides_show_source() {
assert_cmd_snapshot!(ruff_check(Some(true), Some("concise".into())).pass_stdin(STDIN), @r###"
success: false
exit_code: 1
----- stdout -----
-:1:1: E741 Ambiguous variable name: `l`
Found 1 error.
----- stderr -----
warning: The `--show-source` argument is deprecated and has been ignored in favor of `--output-format=concise`.
"###);
}
#[test]
fn ensure_full_output_format_overrides_no_show_source() {
assert_cmd_snapshot!(ruff_check(Some(false), Some("full".into())).pass_stdin(STDIN), @r###"
success: false
exit_code: 1
----- stdout -----
-:1:1: E741 Ambiguous variable name: `l`
|
1 | l = 1
| ^ E741
|
Found 1 error.
----- stderr -----
warning: The `--no-show-source` argument is deprecated and has been ignored in favor of `--output-format=full`.
"###);
}
#[test]
fn ensure_output_format_uses_concise_over_no_show_source() {
assert_cmd_snapshot!(ruff_check(Some(false), Some("concise".into())).pass_stdin(STDIN), @r###"
success: false
exit_code: 1
----- stdout -----
-:1:1: E741 Ambiguous variable name: `l`
Found 1 error.
----- stderr -----
warning: The `--no-show-source` argument is deprecated and has been ignored in favor of `--output-format=concise`.
"###);
}
#[test]
fn ensure_deprecated_output_format_overrides_show_source() {
assert_cmd_snapshot!(ruff_check(Some(true), Some("text".into())).pass_stdin(STDIN), @r###"
success: false
exit_code: 1
----- stdout -----
-:1:1: E741 Ambiguous variable name: `l`
Found 1 error.
----- stderr -----
warning: The `--show-source` argument is deprecated and has been ignored in favor of `--output-format=text`.
warning: `--output-format=text` is deprecated. Use `--output-format=full` or `--output-format=concise` instead. `text` will be treated as `concise`.
"###);
}
#[test]
fn ensure_deprecated_output_format_overrides_no_show_source() {
assert_cmd_snapshot!(ruff_check(Some(false), Some("text".into())).pass_stdin(STDIN), @r###"
success: false
exit_code: 1
----- stdout -----
-:1:1: E741 Ambiguous variable name: `l`
Found 1 error.
----- stderr -----
warning: The `--no-show-source` argument is deprecated and has been ignored in favor of `--output-format=text`.
warning: `--output-format=text` is deprecated. Use `--output-format=full` or `--output-format=concise` instead. `text` will be treated as `concise`.
"###);
}

View File

@@ -508,6 +508,11 @@ if __name__ == '__main__':
say_hy("dear Ruff contributor")
----- stderr -----
warning: The top-level linter settings are deprecated in favour of their counterparts in the `lint` section. Please update the following options in your configuration:
- 'extend-select' -> 'lint.extend-select'
- 'ignore' -> 'lint.ignore'
"###);
Ok(())
}
@@ -546,6 +551,11 @@ if __name__ == '__main__':
say_hy("dear Ruff contributor")
----- stderr -----
warning: The top-level linter settings are deprecated in favour of their counterparts in the `lint` section. Please update the following options in your configuration:
- 'extend-select' -> 'lint.extend-select'
- 'ignore' -> 'lint.ignore'
"###);
Ok(())
}
@@ -1468,3 +1478,73 @@ fn test_notebook_trailing_semicolon() {
----- stderr -----
"###);
}
#[test]
fn extension() -> Result<()> {
let tempdir = TempDir::new()?;
let ruff_toml = tempdir.path().join("ruff.toml");
fs::write(
&ruff_toml,
r#"
include = ["*.ipy"]
"#,
)?;
fs::write(
tempdir.path().join("main.ipy"),
r#"
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "ad6f36d9-4b7d-4562-8d00-f15a0f1fbb6d",
"metadata": {},
"outputs": [],
"source": [
"x=1"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.0"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
"#,
)?;
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
.current_dir(tempdir.path())
.arg("format")
.arg("--no-cache")
.args(["--config", &ruff_toml.file_name().unwrap().to_string_lossy()])
.args(["--extension", "ipy:ipynb"])
.arg("."), @r###"
success: true
exit_code: 0
----- stdout -----
1 file reformatted
----- stderr -----
"###);
Ok(())
}

View File

@@ -11,7 +11,7 @@ use insta_cmd::{assert_cmd_snapshot, get_cargo_bin};
use tempfile::TempDir;
const BIN_NAME: &str = "ruff";
const STDIN_BASE_OPTIONS: &[&str] = &["--no-cache", "--output-format", "text"];
const STDIN_BASE_OPTIONS: &[&str] = &["--no-cache", "--output-format", "concise"];
#[test]
fn top_level_options() -> Result<()> {
@@ -44,6 +44,11 @@ inline-quotes = "single"
[*] 2 fixable with the `--fix` option.
----- stderr -----
warning: The top-level linter settings are deprecated in favour of their counterparts in the `lint` section. Please update the following options in your configuration:
- 'extend-select' -> 'lint.extend-select'
- 'flake8-quotes' -> 'lint.flake8-quotes'
"###);
Ok(())
}
@@ -114,6 +119,10 @@ inline-quotes = "single"
[*] 2 fixable with the `--fix` option.
----- stderr -----
warning: The top-level linter settings are deprecated in favour of their counterparts in the `lint` section. Please update the following options in your configuration:
- 'extend-select' -> 'lint.extend-select'
"###);
Ok(())
}
@@ -153,6 +162,10 @@ inline-quotes = "single"
[*] 2 fixable with the `--fix` option.
----- stderr -----
warning: The top-level linter settings are deprecated in favour of their counterparts in the `lint` section. Please update the following options in your configuration:
- 'flake8-quotes' -> 'lint.flake8-quotes'
"###);
Ok(())
}
@@ -228,6 +241,10 @@ OTHER = "OTHER"
[*] 3 fixable with the `--fix` option.
----- stderr -----
warning: The top-level linter settings are deprecated in favour of their counterparts in the `lint` section. Please update the following options in your configuration:
- 'extend-select' -> 'lint.extend-select'
"###);
Ok(())
}
@@ -271,6 +288,10 @@ if __name__ == "__main__":
[*] 2 fixable with the `--fix` option.
----- stderr -----
warning: The top-level linter settings are deprecated in favour of their counterparts in the `lint` section. Please update the following options in your configuration:
- 'extend-select' -> 'lint.extend-select'
"###);
Ok(())
}
@@ -309,6 +330,11 @@ _ = "---------------------------------------------------------------------------
Found 1 error.
----- stderr -----
warning: The top-level linter settings are deprecated in favour of their counterparts in the `lint` section. Please update the following options in your configuration:
- 'select' -> 'lint.select'
- 'pycodestyle' -> 'lint.pycodestyle'
"###);
Ok(())
}
@@ -351,6 +377,10 @@ if __name__ == "__main__":
[*] 1 fixable with the `--fix` option.
----- stderr -----
warning: The top-level linter settings are deprecated in favour of their counterparts in the `lint` section. Please update the following options in your configuration:
- 'extend-select' -> 'lint.extend-select'
"###);
Ok(())
}
@@ -393,6 +423,10 @@ if __name__ == "__main__":
[*] 1 fixable with the `--fix` option.
----- stderr -----
warning: The top-level linter settings are deprecated in favour of their counterparts in the `lint` section. Please update the following options in your configuration:
- 'extend-select' -> 'lint.extend-select'
"###);
Ok(())
}
@@ -436,3 +470,75 @@ ignore = ["D203", "D212"]
"###);
Ok(())
}
#[test]
fn extension() -> Result<()> {
let tempdir = TempDir::new()?;
let ruff_toml = tempdir.path().join("ruff.toml");
fs::write(
&ruff_toml,
r#"
include = ["*.ipy"]
"#,
)?;
fs::write(
tempdir.path().join("main.ipy"),
r#"
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "ad6f36d9-4b7d-4562-8d00-f15a0f1fbb6d",
"metadata": {},
"outputs": [],
"source": [
"import os"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.0"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
"#,
)?;
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
.current_dir(tempdir.path())
.arg("check")
.args(STDIN_BASE_OPTIONS)
.args(["--config", &ruff_toml.file_name().unwrap().to_string_lossy()])
.args(["--extension", "ipy:ipynb"])
.arg("."), @r###"
success: false
exit_code: 1
----- stdout -----
main.ipy:cell 1:1:8: F401 [*] `os` imported but unused
Found 1 error.
[*] 1 fixable with the `--fix` option.
----- stderr -----
"###);
Ok(())
}

View File

@@ -39,6 +39,10 @@ fn check_project_include_defaults() {
[BASEPATH]/include-test/subdirectory/c.py
----- stderr -----
warning: The top-level linter settings are deprecated in favour of their counterparts in the `lint` section. Please update the following options in your configuration:
- 'select' -> 'lint.select'
"###);
});
}

View File

@@ -0,0 +1,29 @@
use insta_cmd::{assert_cmd_snapshot, get_cargo_bin};
use std::path::Path;
use std::process::Command;
const BIN_NAME: &str = "ruff";
#[cfg(not(target_os = "windows"))]
const TEST_FILTERS: &[(&str, &str)] = &[
("\"[^\\*\"]*/pyproject.toml", "\"[BASEPATH]/pyproject.toml"),
("\".*/crates", "\"[BASEPATH]/crates"),
("\".*/\\.ruff_cache", "\"[BASEPATH]/.ruff_cache"),
("\".*/ruff\"", "\"[BASEPATH]\""),
];
#[cfg(target_os = "windows")]
const TEST_FILTERS: &[(&str, &str)] = &[
(r#""[^\*"]*\\pyproject.toml"#, "\"[BASEPATH]/pyproject.toml"),
(r#"".*\\crates"#, "\"[BASEPATH]/crates"),
(r#"".*\\\.ruff_cache"#, "\"[BASEPATH]/.ruff_cache"),
(r#"".*\\ruff""#, "\"[BASEPATH]\""),
(r#"\\+(\w\w|\s|")"#, "/$1"),
];
#[test]
fn display_default_settings() {
insta::with_settings!({ filters => TEST_FILTERS.to_vec() }, {
assert_cmd_snapshot!(Command::new(get_cargo_bin(BIN_NAME))
.args(["check", "--show-settings", "unformatted.py"]).current_dir(Path::new("./resources/test/fixtures")));
});
}

View File

@@ -1,5 +1,5 @@
---
source: crates/ruff_cli/tests/integration_test.rs
source: crates/ruff/tests/integration_test.rs
info:
program: ruff
args:
@@ -51,7 +51,7 @@ else:
```
## Options
- `pyflakes.extend-generics`
- `lint.pyflakes.extend-generics`
## References
- [Python documentation: `import`](https://docs.python.org/3/reference/simple_stmts.html#the-import-statement)

View File

@@ -1,5 +1,5 @@
---
source: crates/ruff_cli/tests/integration_test.rs
source: crates/ruff/tests/integration_test.rs
info:
program: ruff
args:

View File

@@ -0,0 +1,367 @@
---
source: crates/ruff/tests/show_settings.rs
info:
program: ruff
args:
- check
- "--show-settings"
- unformatted.py
---
success: true
exit_code: 0
----- stdout -----
Resolved settings for: "[BASEPATH]/crates/ruff/resources/test/fixtures/unformatted.py"
Settings path: "[BASEPATH]/pyproject.toml"
# General Settings
cache_dir = "[BASEPATH]/.ruff_cache"
fix = false
fix_only = false
output_format = concise
show_fixes = false
unsafe_fixes = hint
# File Resolver Settings
file_resolver.exclude = [
".bzr",
".direnv",
".eggs",
".git",
".git-rewrite",
".hg",
".ipynb_checkpoints",
".mypy_cache",
".nox",
".pants.d",
".pyenv",
".pytest_cache",
".pytype",
".ruff_cache",
".svn",
".tox",
".venv",
".vscode",
"__pypackages__",
"_build",
"buck-out",
"build",
"dist",
"node_modules",
"site-packages",
"venv",
]
file_resolver.extend_exclude = [
"crates/ruff_linter/resources/",
"crates/ruff_python_formatter/resources/",
]
file_resolver.force_exclude = false
file_resolver.include = [
"*.py",
"*.pyi",
"**/pyproject.toml",
]
file_resolver.extend_include = []
file_resolver.respect_gitignore = true
file_resolver.project_root = "[BASEPATH]"
# Linter Settings
linter.exclude = []
linter.project_root = "[BASEPATH]"
linter.rules.enabled = [
MultipleImportsOnOneLine,
ModuleImportNotAtTopOfFile,
MultipleStatementsOnOneLineColon,
MultipleStatementsOnOneLineSemicolon,
UselessSemicolon,
NoneComparison,
TrueFalseComparison,
NotInTest,
NotIsTest,
TypeComparison,
BareExcept,
LambdaAssignment,
AmbiguousVariableName,
AmbiguousClassName,
AmbiguousFunctionName,
IOError,
SyntaxError,
UnusedImport,
ImportShadowedByLoopVar,
UndefinedLocalWithImportStar,
LateFutureImport,
UndefinedLocalWithImportStarUsage,
UndefinedLocalWithNestedImportStarUsage,
FutureFeatureNotDefined,
PercentFormatInvalidFormat,
PercentFormatExpectedMapping,
PercentFormatExpectedSequence,
PercentFormatExtraNamedArguments,
PercentFormatMissingArgument,
PercentFormatMixedPositionalAndNamed,
PercentFormatPositionalCountMismatch,
PercentFormatStarRequiresSequence,
PercentFormatUnsupportedFormatCharacter,
StringDotFormatInvalidFormat,
StringDotFormatExtraNamedArguments,
StringDotFormatExtraPositionalArguments,
StringDotFormatMissingArguments,
StringDotFormatMixingAutomatic,
FStringMissingPlaceholders,
MultiValueRepeatedKeyLiteral,
MultiValueRepeatedKeyVariable,
ExpressionsInStarAssignment,
MultipleStarredExpressions,
AssertTuple,
IsLiteral,
InvalidPrintSyntax,
IfTuple,
BreakOutsideLoop,
ContinueOutsideLoop,
YieldOutsideFunction,
ReturnOutsideFunction,
DefaultExceptNotLast,
ForwardAnnotationSyntaxError,
RedefinedWhileUnused,
UndefinedName,
UndefinedExport,
UndefinedLocal,
UnusedVariable,
UnusedAnnotation,
RaiseNotImplemented,
]
linter.rules.should_fix = [
MultipleImportsOnOneLine,
ModuleImportNotAtTopOfFile,
MultipleStatementsOnOneLineColon,
MultipleStatementsOnOneLineSemicolon,
UselessSemicolon,
NoneComparison,
TrueFalseComparison,
NotInTest,
NotIsTest,
TypeComparison,
BareExcept,
LambdaAssignment,
AmbiguousVariableName,
AmbiguousClassName,
AmbiguousFunctionName,
IOError,
SyntaxError,
UnusedImport,
ImportShadowedByLoopVar,
UndefinedLocalWithImportStar,
LateFutureImport,
UndefinedLocalWithImportStarUsage,
UndefinedLocalWithNestedImportStarUsage,
FutureFeatureNotDefined,
PercentFormatInvalidFormat,
PercentFormatExpectedMapping,
PercentFormatExpectedSequence,
PercentFormatExtraNamedArguments,
PercentFormatMissingArgument,
PercentFormatMixedPositionalAndNamed,
PercentFormatPositionalCountMismatch,
PercentFormatStarRequiresSequence,
PercentFormatUnsupportedFormatCharacter,
StringDotFormatInvalidFormat,
StringDotFormatExtraNamedArguments,
StringDotFormatExtraPositionalArguments,
StringDotFormatMissingArguments,
StringDotFormatMixingAutomatic,
FStringMissingPlaceholders,
MultiValueRepeatedKeyLiteral,
MultiValueRepeatedKeyVariable,
ExpressionsInStarAssignment,
MultipleStarredExpressions,
AssertTuple,
IsLiteral,
InvalidPrintSyntax,
IfTuple,
BreakOutsideLoop,
ContinueOutsideLoop,
YieldOutsideFunction,
ReturnOutsideFunction,
DefaultExceptNotLast,
ForwardAnnotationSyntaxError,
RedefinedWhileUnused,
UndefinedName,
UndefinedExport,
UndefinedLocal,
UnusedVariable,
UnusedAnnotation,
RaiseNotImplemented,
]
linter.per_file_ignores = {}
linter.safety_table.forced_safe = []
linter.safety_table.forced_unsafe = []
linter.target_version = Py37
linter.preview = disabled
linter.explicit_preview_rules = false
linter.extension.mapping = {}
linter.allowed_confusables = []
linter.builtins = []
linter.dummy_variable_rgx = ^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$
linter.external = []
linter.ignore_init_module_imports = false
linter.logger_objects = []
linter.namespace_packages = []
linter.src = ["[BASEPATH]"]
linter.tab_size = 4
linter.line_length = 88
linter.task_tags = [
TODO,
FIXME,
XXX,
]
linter.typing_modules = []
# Linter Plugins
linter.flake8_annotations.mypy_init_return = false
linter.flake8_annotations.suppress_dummy_args = false
linter.flake8_annotations.suppress_none_returning = false
linter.flake8_annotations.allow_star_arg_any = false
linter.flake8_annotations.ignore_fully_untyped = false
linter.flake8_bandit.hardcoded_tmp_directory = [
/tmp,
/var/tmp,
/dev/shm,
]
linter.flake8_bandit.check_typed_exception = false
linter.flake8_bugbear.extend_immutable_calls = []
linter.flake8_builtins.builtins_ignorelist = []
linter.flake8_comprehensions.allow_dict_calls_with_keyword_arguments = false
linter.flake8_copyright.notice_rgx = (?i)Copyright\s+(\(C\)\s+)?\d{4}(-\d{4})*
linter.flake8_copyright.author = none
linter.flake8_copyright.min_file_size = 0
linter.flake8_errmsg.max_string_length = 0
linter.flake8_gettext.functions_names = [
_,
gettext,
ngettext,
]
linter.flake8_implicit_str_concat.allow_multiline = true
linter.flake8_import_conventions.aliases = {"matplotlib": "mpl", "matplotlib.pyplot": "plt", "pandas": "pd", "seaborn": "sns", "tensorflow": "tf", "networkx": "nx", "plotly.express": "px", "polars": "pl", "numpy": "np", "panel": "pn", "pyarrow": "pa", "altair": "alt", "tkinter": "tk", "holoviews": "hv"}
linter.flake8_import_conventions.banned_aliases = {}
linter.flake8_import_conventions.banned_from = []
linter.flake8_pytest_style.fixture_parentheses = true
linter.flake8_pytest_style.parametrize_names_type = tuple
linter.flake8_pytest_style.parametrize_values_type = list
linter.flake8_pytest_style.parametrize_values_row_type = tuple
linter.flake8_pytest_style.raises_require_match_for = [
BaseException,
Exception,
ValueError,
OSError,
IOError,
EnvironmentError,
socket.error,
]
linter.flake8_pytest_style.raises_extend_require_match_for = []
linter.flake8_pytest_style.mark_parentheses = true
linter.flake8_quotes.inline_quotes = double
linter.flake8_quotes.multiline_quotes = double
linter.flake8_quotes.docstring_quotes = double
linter.flake8_quotes.avoid_escape = true
linter.flake8_self.ignore_names = [
_make,
_asdict,
_replace,
_fields,
_field_defaults,
_name_,
_value_,
]
linter.flake8_tidy_imports.ban_relative_imports = "parents"
linter.flake8_tidy_imports.banned_api = {}
linter.flake8_tidy_imports.banned_module_level_imports = []
linter.flake8_type_checking.strict = false
linter.flake8_type_checking.exempt_modules = [
typing,
typing_extensions,
]
linter.flake8_type_checking.runtime_required_base_classes = []
linter.flake8_type_checking.runtime_required_decorators = []
linter.flake8_type_checking.quote_annotations = false
linter.flake8_unused_arguments.ignore_variadic_names = false
linter.isort.required_imports = []
linter.isort.combine_as_imports = false
linter.isort.force_single_line = false
linter.isort.force_sort_within_sections = false
linter.isort.detect_same_package = true
linter.isort.case_sensitive = false
linter.isort.force_wrap_aliases = false
linter.isort.force_to_top = []
linter.isort.known_modules = {}
linter.isort.order_by_type = true
linter.isort.relative_imports_order = furthest_to_closest
linter.isort.single_line_exclusions = []
linter.isort.split_on_trailing_comma = true
linter.isort.classes = []
linter.isort.constants = []
linter.isort.variables = []
linter.isort.no_lines_before = []
linter.isort.lines_after_imports = -1
linter.isort.lines_between_types = 0
linter.isort.forced_separate = []
linter.isort.section_order = [
known { type = future },
known { type = standard_library },
known { type = third_party },
known { type = first_party },
known { type = local_folder },
]
linter.isort.no_sections = false
linter.isort.from_first = false
linter.isort.length_sort = false
linter.isort.length_sort_straight = false
linter.mccabe.max_complexity = 10
linter.pep8_naming.ignore_names = [
setUp,
tearDown,
setUpClass,
tearDownClass,
setUpModule,
tearDownModule,
asyncSetUp,
asyncTearDown,
setUpTestData,
failureException,
longMessage,
maxDiff,
]
linter.pep8_naming.classmethod_decorators = []
linter.pep8_naming.staticmethod_decorators = []
linter.pycodestyle.max_line_length = 88
linter.pycodestyle.max_doc_length = none
linter.pycodestyle.ignore_overlong_task_comments = false
linter.pyflakes.extend_generics = []
linter.pylint.allow_magic_value_types = [
str,
bytes,
]
linter.pylint.allow_dunder_method_names = []
linter.pylint.max_args = 5
linter.pylint.max_positional_args = 5
linter.pylint.max_returns = 6
linter.pylint.max_bool_expr = 5
linter.pylint.max_branches = 12
linter.pylint.max_statements = 50
linter.pylint.max_public_methods = 20
linter.pylint.max_locals = 15
linter.pyupgrade.keep_runtime_typing = false
# Formatter Settings
formatter.exclude = []
formatter.target_version = Py37
formatter.preview = disabled
formatter.line_width = 88
formatter.line_ending = auto
formatter.indent_style = space
formatter.indent_width = 4
formatter.quote_style = double
formatter.magic_trailing_comma = respect
formatter.docstring_code_format = disabled
formatter.docstring_code_line_width = dynamic
----- stderr -----

View File

@@ -1,5 +1,16 @@
# Ruff Benchmarks
The `ruff_benchmark` crate benchmarks the linter and the formatter on individual files.
The `ruff_benchmark` crate benchmarks the linter and the formatter on individual files:
```shell
# Run once on the "baseline".
cargo bench -p ruff_benchmark -- --save-baseline=main
# Compare against the "baseline".
cargo bench -p ruff_benchmark -- --baseline=main
# Run the lexer benchmarks.
cargo bench -p ruff_benchmark lexer -- --baseline=main
```
See [CONTRIBUTING.md](../../CONTRIBUTING.md) on how to use these benchmarks.

View File

@@ -7,7 +7,7 @@ use ruff_benchmark::{TestCase, TestFile, TestFileDownloadError};
use ruff_python_formatter::{format_module_ast, PreviewMode, PyFormatOptions};
use ruff_python_index::CommentRangesBuilder;
use ruff_python_parser::lexer::lex;
use ruff_python_parser::{parse_tokens, Mode};
use ruff_python_parser::{allocate_tokens_vec, parse_tokens, Mode};
#[cfg(target_os = "windows")]
#[global_allocator]
@@ -52,7 +52,7 @@ fn benchmark_formatter(criterion: &mut Criterion) {
BenchmarkId::from_parameter(case.name()),
&case,
|b, case| {
let mut tokens = Vec::new();
let mut tokens = allocate_tokens_vec(case.code());
let mut comment_ranges = CommentRangesBuilder::default();
for result in lex(case.code(), Mode::Module) {

View File

@@ -1,5 +0,0 @@
---
source: crates/ruff_cli/src/version.rs
expression: version
---
0.0.0

View File

@@ -11,21 +11,21 @@ repository = { workspace = true }
license = { workspace = true }
[dependencies]
ruff_linter = { path = "../ruff_linter", features = ["schemars"] }
ruff_cli = { path = "../ruff_cli" }
ruff = { path = "../ruff" }
ruff_diagnostics = { path = "../ruff_diagnostics" }
ruff_formatter = { path = "../ruff_formatter" }
ruff_linter = { path = "../ruff_linter", features = ["schemars"] }
ruff_notebook = { path = "../ruff_notebook" }
ruff_python_ast = { path = "../ruff_python_ast" }
ruff_python_codegen = { path = "../ruff_python_codegen" }
ruff_python_formatter = { path = "../ruff_python_formatter" }
ruff_notebook = { path = "../ruff_notebook" }
ruff_python_parser = { path = "../ruff_python_parser" }
ruff_python_stdlib = { path = "../ruff_python_stdlib" }
ruff_python_trivia = { path = "../ruff_python_trivia" }
ruff_workspace = { path = "../ruff_workspace", features = ["schemars"]}
anyhow = { workspace = true }
clap = { workspace = true }
clap = { workspace = true, features = ["wrap_help"] }
ignore = { workspace = true }
imara-diff = { workspace = true }
indicatif = { workspace = true }

View File

@@ -27,8 +27,8 @@ use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::EnvFilter;
use ruff_cli::args::{CliOverrides, FormatArguments, FormatCommand, LogLevelArgs};
use ruff_cli::resolve::resolve;
use ruff::args::{CliOverrides, FormatArguments, FormatCommand, LogLevelArgs};
use ruff::resolve::resolve;
use ruff_formatter::{FormatError, LineWidth, PrintError};
use ruff_linter::logging::LogLevel;
use ruff_linter::settings::types::{FilePattern, FilePatternSet};
@@ -67,7 +67,7 @@ fn find_pyproject_config(
Ok(pyproject_config)
}
/// Find files that ruff would check so we can format them. Adapted from `ruff_cli`.
/// Find files that ruff would check so we can format them. Adapted from `ruff`.
#[allow(clippy::type_complexity)]
fn ruff_check_paths<'a>(
pyproject_config: &'a PyprojectConfig,
@@ -287,7 +287,7 @@ fn setup_logging(log_level_args: &LogLevelArgs, log_file: Option<&Path>) -> io::
LogLevel::Quiet => tracing::Level::WARN,
LogLevel::Silent => tracing::Level::ERROR,
};
// 1. `RUST_LOG=`, 2. explicit CLI log level, 3. info, the ruff_cli default
// 1. `RUST_LOG=`, 2. explicit CLI log level, 3. info, the ruff default
let filter_layer = EnvFilter::try_from_default_env().unwrap_or_else(|_| {
EnvFilter::builder()
.with_default_directive(log_level.into())
@@ -461,7 +461,7 @@ fn format_dev_project(
// TODO(konstin): Respect black's excludes.
// Find files to check (or in this case, format twice). Adapted from ruff_cli
// Find files to check (or in this case, format twice). Adapted from ruff
// First argument is ignored
let (cli, overrides) = parse_cli(files)?;
let pyproject_config = find_pyproject_config(&cli, &overrides)?;

View File

@@ -8,7 +8,7 @@ use anyhow::{bail, Context, Result};
use clap::CommandFactory;
use pretty_assertions::StrComparison;
use ruff_cli::args;
use ruff::args;
use crate::generate_all::{Mode, REGENERATE_ALL_COMMAND};
use crate::ROOT_DIR;
@@ -114,12 +114,15 @@ pub(super) fn main(args: &Args) -> Result<()> {
/// Returns the output of `ruff help`.
fn help_text() -> String {
args::Args::command().render_help().to_string()
args::Args::command()
.term_width(79)
.render_help()
.to_string()
}
/// Returns the output of a given subcommand (e.g., `ruff help check`).
fn subcommand_help_text(subcommand: &str) -> Result<String> {
let mut cmd = args::Args::command();
let mut cmd = args::Args::command().term_width(79);
// The build call is necessary for the help output to contain `Usage: ruff
// check` instead of `Usage: check` see https://github.com/clap-rs/clap/issues/4685

View File

@@ -26,9 +26,9 @@ pub(crate) fn main(args: &Args) -> Result<()> {
for rule in Rule::iter() {
if let Some(explanation) = rule.explanation() {
let mut output = String::new();
output.push_str(&format!("# {} ({})", rule.as_ref(), rule.noqa_code()));
output.push('\n');
output.push('\n');
let (linter, _) = Linter::parse_code(&rule.noqa_code().to_string()).unwrap();
if linter.url().is_some() {
@@ -37,6 +37,22 @@ pub(crate) fn main(args: &Args) -> Result<()> {
output.push('\n');
}
if rule.is_deprecated() {
output.push_str(
r"**Warning: This rule is deprecated and will be removed in a future release.**",
);
output.push('\n');
output.push('\n');
}
if rule.is_removed() {
output.push_str(
r"**Warning: This rule has been removed and its documentation is only available for historical reasons.**",
);
output.push('\n');
output.push('\n');
}
let fix_availability = rule.fixable();
if matches!(
fix_availability,
@@ -116,7 +132,7 @@ fn process_documentation(documentation: &str, out: &mut String, rule_name: &str)
}
}
let anchor = option.replace('.', "-");
let anchor = option.replace('.', "_");
out.push_str(&format!("- [`{option}`][{option}]\n"));
after.push_str(&format!("[{option}]: ../settings.md#{anchor}\n"));
@@ -142,13 +158,13 @@ mod tests {
let mut output = String::new();
process_documentation(
"
See also [`mccabe.max-complexity`] and [`task-tags`].
See also [`lint.mccabe.max-complexity`] and [`lint.task-tags`].
Something [`else`][other].
## Options
- `task-tags`
- `mccabe.max-complexity`
- `lint.task-tags`
- `lint.mccabe.max-complexity`
[other]: http://example.com.",
&mut output,
@@ -157,18 +173,18 @@ Something [`else`][other].
assert_eq!(
output,
"
See also [`mccabe.max-complexity`][mccabe.max-complexity] and [`task-tags`][task-tags].
See also [`lint.mccabe.max-complexity`][lint.mccabe.max-complexity] and [`lint.task-tags`][lint.task-tags].
Something [`else`][other].
## Options
- [`task-tags`][task-tags]
- [`mccabe.max-complexity`][mccabe.max-complexity]
- [`lint.task-tags`][lint.task-tags]
- [`lint.mccabe.max-complexity`][lint.mccabe.max-complexity]
[other]: http://example.com.
[task-tags]: ../settings.md#task-tags
[mccabe.max-complexity]: ../settings.md#mccabe-max-complexity
[lint.task-tags]: ../settings.md#lint_task-tags
[lint.mccabe.max-complexity]: ../settings.md#lint_mccabe_max-complexity
"
);
}

View File

@@ -1,6 +1,7 @@
//! Generate a Markdown-compatible listing of configuration options for `pyproject.toml`.
//!
//! Used for <https://docs.astral.sh/ruff/settings/>.
use itertools::Itertools;
use std::fmt::Write;
use ruff_python_trivia::textwrap;
@@ -9,16 +10,29 @@ use ruff_workspace::options_base::{OptionField, OptionSet, OptionsMetadata, Visi
pub(crate) fn generate() -> String {
let mut output = String::new();
generate_set(&mut output, &Set::Toplevel(Options::metadata()));
generate_set(
&mut output,
Set::Toplevel(Options::metadata()),
&mut Vec::new(),
);
output
}
fn generate_set(output: &mut String, set: &Set) {
if set.level() < 2 {
writeln!(output, "### {title}\n", title = set.title()).unwrap();
} else {
writeln!(output, "#### {title}\n", title = set.title()).unwrap();
fn generate_set(output: &mut String, set: Set, parents: &mut Vec<Set>) {
match &set {
Set::Toplevel(_) => {
output.push_str("### Top-level\n");
}
Set::Named { name, .. } => {
let title = parents
.iter()
.filter_map(|set| set.name())
.chain(std::iter::once(name.as_str()))
.join(".");
writeln!(output, "#### `{title}`\n",).unwrap();
}
}
if let Some(documentation) = set.metadata().documentation() {
@@ -35,72 +49,68 @@ fn generate_set(output: &mut String, set: &Set) {
fields.sort_unstable_by(|(name, _), (name2, _)| name.cmp(name2));
sets.sort_unstable_by(|(name, _), (name2, _)| name.cmp(name2));
parents.push(set);
// Generate the fields.
for (name, field) in &fields {
emit_field(output, name, field, set);
emit_field(output, name, field, parents.as_slice());
output.push_str("---\n\n");
}
// Generate all the sub-sets.
for (set_name, sub_set) in &sets {
generate_set(output, &Set::Named(set_name, *sub_set, set.level() + 1));
generate_set(
output,
Set::Named {
name: set_name.to_string(),
set: *sub_set,
},
parents,
);
}
parents.pop();
}
enum Set<'a> {
enum Set {
Toplevel(OptionSet),
Named(&'a str, OptionSet, u32),
Named { name: String, set: OptionSet },
}
impl<'a> Set<'a> {
fn name(&self) -> Option<&'a str> {
impl Set {
fn name(&self) -> Option<&str> {
match self {
Set::Toplevel(_) => None,
Set::Named(name, _, _) => Some(name),
}
}
fn title(&self) -> &'a str {
match self {
Set::Toplevel(_) => "Top-level",
Set::Named(name, _, _) => name,
Set::Named { name, .. } => Some(name),
}
}
fn metadata(&self) -> &OptionSet {
match self {
Set::Toplevel(set) => set,
Set::Named(_, set, _) => set,
}
}
fn level(&self) -> u32 {
match self {
Set::Toplevel(_) => 0,
Set::Named(_, _, level) => *level,
Set::Named { set, .. } => set,
}
}
}
fn emit_field(output: &mut String, name: &str, field: &OptionField, parent_set: &Set) {
let header_level = if parent_set.level() < 2 {
"####"
} else {
"#####"
};
fn emit_field(output: &mut String, name: &str, field: &OptionField, parents: &[Set]) {
let header_level = if parents.is_empty() { "####" } else { "#####" };
let parents_anchor = parents.iter().filter_map(|parent| parent.name()).join("_");
if parents_anchor.is_empty() {
output.push_str(&format!(
"{header_level} [`{name}`](#{name}) {{: #{name} }}\n"
));
} else {
output.push_str(&format!(
"{header_level} [`{name}`](#{parents_anchor}_{name}) {{: #{parents_anchor}_{name} }}\n"
));
// if there's a set name, we need to add it to the anchor
if let Some(set_name) = parent_set.name() {
// the anchor used to just be the name, but now it's the group name
// for backwards compatibility, we need to keep the old anchor
output.push_str(&format!("<span id=\"{name}\"></span>\n"));
output.push_str(&format!(
"{header_level} [`{name}`](#{set_name}-{name}) {{: #{set_name}-{name} }}\n"
));
} else {
output.push_str(&format!("{header_level} [`{name}`](#{name})\n"));
}
output.push('\n');
if let Some(deprecated) = &field.deprecated {
@@ -129,12 +139,12 @@ fn emit_field(output: &mut String, name: &str, field: &OptionField, parent_set:
output.push_str("**Example usage**:\n\n");
output.push_str(&format_tab(
"pyproject.toml",
&format_header(field.scope, parent_set, ConfigurationFile::PyprojectToml),
&format_header(field.scope, parents, ConfigurationFile::PyprojectToml),
field.example,
));
output.push_str(&format_tab(
"ruff.toml",
&format_header(field.scope, parent_set, ConfigurationFile::RuffToml),
&format_header(field.scope, parents, ConfigurationFile::RuffToml),
field.example,
));
output.push('\n');
@@ -152,52 +162,22 @@ fn format_tab(tab_name: &str, header: &str, content: &str) -> String {
/// Format the TOML header for the example usage for a given option.
///
/// For example: `[tool.ruff.format]` or `[tool.ruff.lint.isort]`.
fn format_header(
scope: Option<&str>,
parent_set: &Set,
configuration: ConfigurationFile,
) -> String {
match configuration {
ConfigurationFile::PyprojectToml => {
let mut header = if let Some(set_name) = parent_set.name() {
if set_name == "format" {
String::from("tool.ruff.format")
} else {
format!("tool.ruff.lint.{set_name}")
}
} else {
"tool.ruff".to_string()
};
if let Some(scope) = scope {
if !header.is_empty() {
header.push('.');
}
header.push_str(scope);
}
format!("[{header}]")
}
ConfigurationFile::RuffToml => {
let mut header = if let Some(set_name) = parent_set.name() {
if set_name == "format" {
String::from("format")
} else {
format!("lint.{set_name}")
}
} else {
String::new()
};
if let Some(scope) = scope {
if !header.is_empty() {
header.push('.');
}
header.push_str(scope);
}
if header.is_empty() {
String::new()
} else {
format!("[{header}]")
}
}
fn format_header(scope: Option<&str>, parents: &[Set], configuration: ConfigurationFile) -> String {
let tool_parent = match configuration {
ConfigurationFile::PyprojectToml => Some("tool.ruff"),
ConfigurationFile::RuffToml => None,
};
let header = tool_parent
.into_iter()
.chain(parents.iter().filter_map(|parent| parent.name()))
.chain(scope)
.join(".");
if header.is_empty() {
String::new()
} else {
format!("[{header}]")
}
}

View File

@@ -3,6 +3,7 @@
//! Used for <https://docs.astral.sh/ruff/rules/>.
use itertools::Itertools;
use ruff_linter::codes::RuleGroup;
use std::borrow::Cow;
use strum::IntoEnumIterator;
@@ -14,6 +15,10 @@ use ruff_workspace::options_base::OptionsMetadata;
const FIX_SYMBOL: &str = "🛠️";
const PREVIEW_SYMBOL: &str = "🧪";
const REMOVED_SYMBOL: &str = "";
const WARNING_SYMBOL: &str = "⚠️";
const STABLE_SYMBOL: &str = "✔️";
const SPACER: &str = "&nbsp;&nbsp;&nbsp;&nbsp;";
fn generate_table(table_out: &mut String, rules: impl IntoIterator<Item = Rule>, linter: &Linter) {
table_out.push_str("| Code | Name | Message | |");
@@ -21,20 +26,33 @@ fn generate_table(table_out: &mut String, rules: impl IntoIterator<Item = Rule>,
table_out.push_str("| ---- | ---- | ------- | ------: |");
table_out.push('\n');
for rule in rules {
let status_token = match rule.group() {
RuleGroup::Removed => {
format!("<span title='Rule has been removed'>{REMOVED_SYMBOL}</span>")
}
RuleGroup::Deprecated => {
format!("<span title='Rule has been deprecated'>{WARNING_SYMBOL}</span>")
}
#[allow(deprecated)]
RuleGroup::Preview | RuleGroup::Nursery => {
format!("<span title='Rule is in preview'>{PREVIEW_SYMBOL}</span>")
}
RuleGroup::Stable => {
// A full opacity checkmark is a bit aggressive for indicating stable
format!("<span title='Rule is stable' style='opacity: 0.6'>{STABLE_SYMBOL}</span>")
}
};
let fix_token = match rule.fixable() {
FixAvailability::Always | FixAvailability::Sometimes => {
format!("<span title='Automatic fix available'>{FIX_SYMBOL}</span>")
}
FixAvailability::None => {
format!("<span style='opacity: 0.1' aria-hidden='true'>{FIX_SYMBOL}</span>")
format!("<span title='Automatic fix not available' style='opacity: 0.1' aria-hidden='true'>{FIX_SYMBOL}</span>")
}
};
let preview_token = if rule.is_preview() || rule.is_nursery() {
format!("<span title='Rule is in preview'>{PREVIEW_SYMBOL}</span>")
} else {
format!("<span style='opacity: 0.1' aria-hidden='true'>{PREVIEW_SYMBOL}</span>")
};
let status_token = format!("{fix_token} {preview_token}");
let tokens = format!("{status_token} {fix_token}");
let rule_name = rule.as_ref();
@@ -48,9 +66,20 @@ fn generate_table(table_out: &mut String, rules: impl IntoIterator<Item = Rule>,
Cow::Borrowed(message)
};
// Start and end of style spans
let mut ss = "";
let mut se = "";
if rule.is_removed() {
ss = "<span style='opacity: 0.5', title='This rule has been removed'>";
se = "</span>";
} else if rule.is_deprecated() {
ss = "<span style='opacity: 0.8', title='This rule has been deprecated'>";
se = "</span>";
}
#[allow(clippy::or_fun_call)]
table_out.push_str(&format!(
"| {0}{1} {{ #{0}{1} }} | {2} | {3} | {4} |",
"| {ss}{0}{1}{se} {{ #{0}{1} }} | {ss}{2}{se} | {ss}{3}{se} | {ss}{4}{se} |",
linter.common_prefix(),
linter.code_for_rule(rule).unwrap(),
rule.explanation()
@@ -58,7 +87,7 @@ fn generate_table(table_out: &mut String, rules: impl IntoIterator<Item = Rule>,
.then_some(format_args!("[{rule_name}](rules/{rule_name}.md)"))
.unwrap_or(format_args!("{rule_name}")),
message,
status_token,
tokens,
));
table_out.push('\n');
}
@@ -69,15 +98,33 @@ pub(crate) fn generate() -> String {
// Generate the table string.
let mut table_out = String::new();
table_out.push_str(&format!(
"The {FIX_SYMBOL} emoji indicates that a rule is automatically fixable by the `--fix` command-line option."));
table_out.push('\n');
table_out.push_str("### Legend");
table_out.push('\n');
table_out.push_str(&format!(
"The {PREVIEW_SYMBOL} emoji indicates that a rule is in [\"preview\"](faq.md#what-is-preview)."
"{SPACER}{STABLE_SYMBOL}{SPACER} The rule is stable."
));
table_out.push('\n');
table_out.push_str("<br />");
table_out.push_str(&format!(
"{SPACER}{PREVIEW_SYMBOL}{SPACER} The rule is unstable and is in [\"preview\"](faq.md#what-is-preview)."
));
table_out.push_str("<br />");
table_out.push_str(&format!(
"{SPACER}{WARNING_SYMBOL}{SPACER} The rule has been deprecated and will be removed in a future release."
));
table_out.push_str("<br />");
table_out.push_str(&format!(
"{SPACER}{REMOVED_SYMBOL}{SPACER} The rule has been removed only the documentation is available."
));
table_out.push_str("<br />");
table_out.push_str(&format!(
"{SPACER}{FIX_SYMBOL}{SPACER} The rule is automatically fixable by the `--fix` command-line option."
));
table_out.push_str("<br />");
table_out.push('\n');
for linter in Linter::iter() {

View File

@@ -4,7 +4,7 @@
use anyhow::Result;
use clap::{Parser, Subcommand};
use ruff_cli::check;
use ruff::check;
use ruff_linter::logging::{set_up_logging, LogLevel};
use std::process::ExitCode;
@@ -56,9 +56,9 @@ enum Command {
/// Run a ruff command n times for profiling/benchmarking
Repeat {
#[clap(flatten)]
args: ruff_cli::args::CheckCommand,
args: ruff::args::CheckCommand,
#[clap(flatten)]
log_level_args: ruff_cli::args::LogLevelArgs,
log_level_args: ruff::args::LogLevelArgs,
/// Run this many times
#[clap(long)]
repeat: usize,

View File

@@ -328,6 +328,12 @@ pub struct SourcePosition(TextSize);
impl<Context> Format<Context> for SourcePosition {
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
if let Some(FormatElement::SourcePosition(last_position)) = f.buffer.elements().last() {
if *last_position == self.0 {
return Ok(());
}
}
f.write_element(FormatElement::SourcePosition(self.0));
Ok(())
@@ -353,8 +359,8 @@ where
Context: FormatContext,
{
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
if let Some(source_position) = self.position {
f.write_element(FormatElement::SourcePosition(source_position));
if let Some(position) = self.position {
source_position(position).fmt(f)?;
}
f.write_element(FormatElement::Text {

View File

@@ -35,6 +35,7 @@ mod source_code;
use crate::formatter::Formatter;
use crate::group_id::UniqueGroupIdBuilder;
use crate::prelude::TagKind;
use std::fmt;
use std::fmt::{Debug, Display};
use std::marker::PhantomData;
use std::num::{NonZeroU16, NonZeroU8, TryFromIntError};
@@ -52,7 +53,7 @@ pub use crate::diagnostics::{ActualStart, FormatError, InvalidDocumentError, Pri
pub use format_element::{normalize_newlines, FormatElement, LINE_TERMINATORS};
pub use group_id::GroupId;
use ruff_macros::CacheKey;
use ruff_text_size::{TextRange, TextSize};
use ruff_text_size::{TextLen, TextRange, TextSize};
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash, CacheKey)]
#[cfg_attr(
@@ -113,6 +114,12 @@ impl Default for IndentWidth {
}
}
impl Display for IndentWidth {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.0, f)
}
}
impl TryFrom<u8> for IndentWidth {
type Error = TryFromIntError;
@@ -146,6 +153,12 @@ impl Default for LineWidth {
}
}
impl Display for LineWidth {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.0, f)
}
}
impl TryFrom<u16> for LineWidth {
type Error = TryFromIntError;
@@ -419,6 +432,90 @@ impl Printed {
pub fn take_verbatim_ranges(&mut self) -> Vec<TextRange> {
std::mem::take(&mut self.verbatim_ranges)
}
/// Slices the formatted code to the sub-slices that covers the passed `source_range`.
///
/// The implementation uses the source map generated during formatting to find the closest range
/// in the formatted document that covers `source_range` or more. The returned slice
/// matches the `source_range` exactly (except indent, see below) if the formatter emits [`FormatElement::SourcePosition`] for
/// the range's offsets.
///
/// Returns the entire document if the source map is empty.
#[must_use]
pub fn slice_range(self, source_range: TextRange) -> PrintedRange {
let mut start_marker: Option<SourceMarker> = None;
let mut end_marker: Option<SourceMarker> = None;
// Note: The printer can generate multiple source map entries for the same source position.
// For example if you have:
// * `source_position(276)`
// * `token("def")`
// * `token("foo")`
// * `source_position(284)`
// The printer uses the source position 276 for both the tokens `def` and `foo` because that's the only position it knows of.
//
// Warning: Source markers are often emitted sorted by their source position but it's not guaranteed.
// They are only guaranteed to be sorted in increasing order by their destination position.
for marker in self.sourcemap {
// Take the closest start marker, but skip over start_markers that have the same start.
if marker.source <= source_range.start()
&& !start_marker.is_some_and(|existing| existing.source >= marker.source)
{
start_marker = Some(marker);
}
if marker.source >= source_range.end()
&& !end_marker.is_some_and(|existing| existing.source <= marker.source)
{
end_marker = Some(marker);
}
}
let start = start_marker.map(|marker| marker.dest).unwrap_or_default();
let end = end_marker.map_or_else(|| self.code.text_len(), |marker| marker.dest);
let code_range = TextRange::new(start, end);
PrintedRange {
code: self.code[code_range].to_string(),
source_range,
}
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct PrintedRange {
code: String,
source_range: TextRange,
}
impl PrintedRange {
pub fn new(code: String, source_range: TextRange) -> Self {
Self { code, source_range }
}
pub fn empty() -> Self {
Self {
code: String::new(),
source_range: TextRange::default(),
}
}
/// The formatted code.
pub fn as_code(&self) -> &str {
&self.code
}
/// The range the formatted code corresponds to in the source document.
pub fn source_range(&self) -> TextRange {
self.source_range
}
#[must_use]
pub fn with_code(self, code: String) -> Self {
Self { code, ..self }
}
}
/// Public return type of the formatter

View File

@@ -60,7 +60,10 @@ impl<'a> Printer<'a> {
document: &'a Document,
indent: u16,
) -> PrintResult<Printed> {
let mut stack = PrintCallStack::new(PrintElementArgs::new(Indention::Level(indent)));
let indentation = Indention::Level(indent);
self.state.pending_indent = indentation;
let mut stack = PrintCallStack::new(PrintElementArgs::new(indentation));
let mut queue: PrintQueue<'a> = PrintQueue::new(document.as_ref());
loop {
@@ -143,7 +146,13 @@ impl<'a> Printer<'a> {
FormatElement::SourcePosition(position) => {
self.state.source_position = *position;
self.push_marker();
// The printer defers printing indents until the next text
// is printed. Pushing the marker now would mean that the
// mapped range includes the indent range, which we don't want.
// Only add a marker if we're not in an indented context, e.g. at the end of the file.
if self.state.pending_indent.is_empty() {
self.push_marker();
}
}
FormatElement::LineSuffixBoundary => {
@@ -511,11 +520,12 @@ impl<'a> Printer<'a> {
dest: self.state.buffer.text_len(),
};
if let Some(last) = self.state.source_markers.last() {
if last != &marker {
self.state.source_markers.push(marker);
}
} else {
if self
.state
.source_markers
.last()
.map_or(true, |last| last != &marker)
{
self.state.source_markers.push(marker);
}
}

View File

@@ -1,6 +1,6 @@
[package]
name = "ruff_linter"
version = "0.1.12"
version = "0.1.15"
publish = false
authors = { workspace = true }
edition = { workspace = true }
@@ -85,8 +85,8 @@ tempfile = { workspace = true }
[features]
default = []
schemars = ["dep:schemars"]
# Enables the UnreachableCode rule
unreachable-code = []
# Enables rules for internal integration tests
test-rules = []
[lints]
workspace = true

View File

View File

View File

View File

@@ -1,31 +1,87 @@
import os
import subprocess
import time
from pathlib import Path
# Violation cases:
async def foo():
async def func():
open("foo")
async def foo():
async def func():
time.sleep(1)
async def foo():
async def func():
subprocess.run("foo")
async def foo():
async def func():
subprocess.call("foo")
async def foo():
async def func():
subprocess.foo(0)
async def foo():
async def func():
os.wait4(10)
async def foo():
async def func():
os.wait(12)
# Violation cases for pathlib:
async def func():
Path("foo").open() # ASYNC101
async def func():
p = Path("foo")
p.open() # ASYNC101
async def func():
with Path("foo").open() as f: # ASYNC101
pass
async def func() -> None:
p = Path("foo")
async def bar():
p.open() # ASYNC101
async def func() -> None:
(p1, p2) = (Path("foo"), Path("bar"))
p1.open() # ASYNC101
# Non-violation cases for pathlib:
class Foo:
def open(self):
pass
async def func():
Foo().open() # OK
async def func():
def open():
pass
open() # OK
def func():
Path("foo").open() # OK

View File

@@ -2,10 +2,28 @@
# Errors.
###
incorrect_set = {"value1", 23, 5, "value1"}
incorrect_set = {1, 1, 2}
incorrect_set_multiline = {
"value1",
23,
5,
"value1",
# B033
}
incorrect_set = {1, 1}
incorrect_set = {1, 1,}
incorrect_set = {0, 1, 1,}
incorrect_set = {0, 1, 1}
incorrect_set = {
0,
1,
1,
}
###
# Non-errors.
###
correct_set = {"value1", 23, 5}
correct_set = {5, "5"}
correct_set = {5}
correct_set = {}

View File

@@ -10,6 +10,8 @@ constant = 5
{value.attribute: value.upper() for value in data for constant in data}
{constant[value]: value.upper() for value in data for constant in data}
{value[constant]: value.upper() for value in data for constant in data}
{local_id: token for token in tokens if (local_id := _extract_local_id(token)) is not None}
{key: kwargs.get(key) for key in kwargs.keys() if not params.get(key)}
# Errors
{"key": value.upper() for value in data}
@@ -20,3 +22,5 @@ constant = 5
{constant + constant: value.upper() for value in data}
{constant.attribute: value.upper() for value in data}
{constant[0]: value.upper() for value in data}
{tokens: token for token in tokens}

View File

@@ -9,6 +9,22 @@ obj.startswith(foo) or obj.startswith("foo")
# error
obj.endswith(foo) or obj.startswith(foo) or obj.startswith("foo")
def func():
msg = "hello world"
x = "h"
y = ("h", "e", "l", "l", "o")
z = "w"
if msg.startswith(x) or msg.startswith(y) or msg.startswith(z): # Error
print("yes")
def func():
msg = "hello world"
if msg.startswith(("h", "e", "l", "l", "o")) or msg.startswith("h") or msg.startswith("w"): # Error
print("yes")
# ok
obj.startswith(("foo", "bar"))
# ok
@@ -17,3 +33,46 @@ obj.endswith(("foo", "bar"))
obj.startswith("foo") or obj.endswith("bar")
# ok
obj.startswith("foo") or abc.startswith("bar")
def func():
msg = "hello world"
x = "h"
y = ("h", "e", "l", "l", "o")
if msg.startswith(x) or msg.startswith(y): # OK
print("yes")
def func():
msg = "hello world"
y = ("h", "e", "l", "l", "o")
if msg.startswith(y): # OK
print("yes")
def func():
msg = "hello world"
y = ("h", "e", "l", "l", "o")
if msg.startswith(y) or msg.startswith(y): # OK
print("yes")
def func():
msg = "hello world"
y = ("h", "e", "l", "l", "o")
x = ("w", "o", "r", "l", "d")
if msg.startswith(y) or msg.startswith(x) or msg.startswith("h"): # OK
print("yes")
def func():
msg = "hello world"
y = ("h", "e", "l", "l", "o")
x = ("w", "o", "r", "l", "d")
if msg.startswith(y) or msg.endswith(x) or msg.startswith("h"): # OK
print("yes")

View File

@@ -20,3 +20,12 @@ else:
def func2(arg: _PrivateTypeAlias) -> None: ...
type _UnusedPEP695 = int
type _UnusedGeneric695[T] = list[T]
type _UsedPEP695 = str
type _UsedGeneric695[T] = tuple[T, ...]
def func4(arg: _UsedPEP695) -> None: ...
def func5(arg: _UsedGeneric695[bytes]) -> None: ...

View File

@@ -20,3 +20,12 @@ else:
def func2(arg: _PrivateTypeAlias) -> None: ...
type _UnusedPEP695 = int
type _UnusedGeneric695[T] = list[T]
type _UsedPEP695 = str
type _UsedGeneric695[T] = tuple[T, ...]
def func4(arg: _UsedPEP695) -> None: ...
def func5(arg: _UsedGeneric695[bytes]) -> None: ...

View File

@@ -16,3 +16,8 @@ class _UsedTypedDict(TypedDict):
class _CustomClass(_UsedTypedDict):
bar: list[int]
_UnusedTypedDict3 = TypedDict("_UnusedTypedDict3", {"foo": int})
_UsedTypedDict3 = TypedDict("_UsedTypedDict3", {"bar": bytes})
def uses_UsedTypedDict3(arg: _UsedTypedDict3) -> None: ...

View File

@@ -30,3 +30,8 @@ else:
class _CustomClass2(_UsedTypedDict2):
bar: list[int]
_UnusedTypedDict3 = TypedDict("_UnusedTypedDict3", {"foo": int})
_UsedTypedDict3 = TypedDict("_UsedTypedDict3", {"bar": bytes})
def uses_UsedTypedDict3(arg: _UsedTypedDict3) -> None: ...

View File

@@ -1,14 +1,15 @@
import _thread
import builtins
import os
import posix
from posix import abort
import sys as std_sys
import typing
import typing_extensions
import _thread
import _winapi
from posix import abort
from typing import NoReturn
import _winapi
import pytest
import typing_extensions
from pytest import xfail as py_xfail
###
@@ -326,3 +327,44 @@ def end_of_file():
if False:
return 1
x = 2 \
# function return type annotation NoReturn
def foo(x: int) -> int:
def bar() -> NoReturn:
abort()
if x == 5:
return 5
bar()
def foo(string: str) -> str:
def raises(value: str) -> NoReturn:
raise RuntimeError("something went wrong")
match string:
case "a":
return "first"
case "b":
return "second"
case "c":
return "third"
case _:
raises(string)
def foo() -> int:
def baz() -> int:
return 1
def bar() -> NoReturn:
a = 1 + 2
raise AssertionError("Very bad")
if baz() > 3:
return 1
bar()

View File

@@ -363,3 +363,46 @@ def foo():
def mavko_debari(P_kbar):
D=0.4853881 + 3.6006116*P - 0.0117368*(P-1.3822)**2
return D
# contextlib suppress in with statement
import contextlib
def foo():
x = 2
with contextlib.suppress(Exception):
x = x + 1
return x
def foo(data):
with open("in.txt") as file_out, contextlib.suppress(IOError):
file_out.write(data)
data = 10
return data
def foo(data):
with open("in.txt") as file_out:
file_out.write(data)
with contextlib.suppress(IOError):
data = 10
return data
def foo():
y = 1
x = 2
with contextlib.suppress(Exception):
x = 1
y = y + 2
return y # RET504
def foo():
y = 1
if y > 0:
with contextlib.suppress(Exception):
y = 2
return y

View File

@@ -103,6 +103,14 @@ def bar4(x):
return None
def fibo(n):
if n<2:
return n;
else:
last = 1;
last2 = 0;
###
# Non-error
###
@@ -131,6 +139,51 @@ def bar3(x, y, z):
return None
def bar4(x):
if True:
return
else:
# comment
pass
def bar5():
if True:
return
else: # comment
pass
def bar6():
if True:
return
else\
:\
# comment
pass
def bar7():
if True:
return
else\
: # comment
pass
def bar8():
if True:
return
else: pass
def bar9():
if True:
return
else:\
pass
x = 0
if x == 1:
@@ -139,3 +192,9 @@ elif x == 2:
y = "b"
else:
y = "c"
# Regression test for: https://github.com/astral-sh/ruff/issues/9732
def sb(self):
if self._sb is not None: return self._sb
else: self._sb = '\033[01;%dm'; self._sa = '\033[0;0m';

View File

@@ -0,0 +1,195 @@
def func():
# SIM113
idx = 0
for x in range(5):
g(x, idx)
idx += 1
h(x)
def func():
# SIM113
sum = 0
idx = 0
for x in range(5):
if g(x):
break
idx += 1
sum += h(x, idx)
def func():
# SIM113
idx = 0
for x, y in zip(range(5), range(5)):
g(x)
h(x, y)
idx += 1
def func():
# SIM113
idx = 0
sum = 0
for x in range(5):
sum += h(x, idx)
idx += 1
def func():
# SIM113
sum, idx = 0, 0
for x in range(5):
g(x, idx)
idx += 1
h(x)
def func():
# OK (index doesn't start at 0
idx = 10
for x in range(5):
g(x, idx)
idx += 1
h(x)
def func():
# OK (incremented by more than 1)
idx = 0
for x in range(5):
g(x, idx)
idx += 2
h(x)
def func():
# OK (incremented in `if`)
idx = 0
for x in range(5):
if g(x):
idx += 1
h(x)
def func():
# OK (`continue` in match-case)
idx = 0
for x in range(5):
match g(x):
case 1:
h(x)
case 2:
continue
case _:
h(idx)
idx += 1
def func():
# OK (`continue` inside `with` clause)
idx = 0
for x in range(5):
with context as c:
if g(x):
continue
h(x, idx, c)
idx += 1
def func():
# OK (incremented in `try` block)
idx = 0
for x in range(5):
try:
g(x, idx)
except:
h(x)
continue
idx += 1
def func(idx: 0):
# OK (index is an argument)
for x in range(5):
g(x, idx)
idx += 1
def func(x: int):
# OK (index _may_ be non-zero)
if x > 0:
idx = 1
else:
idx = 0
for x in range(5):
g(x, idx)
idx += 1
h(x)
def func():
# OK
idx = 0
for x in range(5):
g(x, idx)
idx += 1
idx += 1
h(x)
def func():
# OK
idx = 0
for x in range(5):
g(x, idx)
idx += 1
if idx > 10:
idx *= 2
h(x)
def func():
# OK (index used after loop)
idx = 0
for x in range(5):
g(x, idx)
idx += 1
h(x)
print(idx)
def func():
# OK (index within nested loop)
idx = 0
for x in range(5):
for y in range(5):
g(x, idx)
idx += 1
def func():
# OK (index used within inner)
idx = 0
def inner():
print(idx)
for x in range(5):
for y in range(5):
g(x, idx)
idx += 1
def func():
# OK (index used as nonlocal inner)
idx = 0
def inner():
nonlocal idx
idx = 3
for x in range(5):
for y in range(5):
g(x, idx)
idx += 1

View File

@@ -4,6 +4,11 @@ if a:
elif c:
b
if a: # we preserve comments, too!
b
elif c: # but not on the second branch
b
if x == 1:
for _ in range(20):
print("hello")
@@ -63,6 +68,10 @@ elif result.eofs == "F":
errors = 1
elif result.eofs == "E":
errors = 1
elif result.eofs == "X":
errors = 1
elif result.eofs == "C":
errors = 1
# OK
@@ -70,7 +79,7 @@ def complicated_calc(*arg, **kwargs):
return 42
def foo(p):
def func(p):
if p == 2:
return complicated_calc(microsecond=0)
elif p == 3:
@@ -103,7 +112,7 @@ elif c:
x = 1
def foo():
def func():
a = True
b = False
if a > b: # end-of-line
@@ -114,3 +123,28 @@ def foo():
return 4
elif b is None:
return 4
def func():
"""Ensure that the named expression is parenthesized when merged."""
a = True
b = False
if a > b: # end-of-line
return 3
elif a := 1:
return 3
if a: # we preserve comments, too!
b
elif c: # but not on the second branch
b
if a: b # here's a comment
elif c: b
if(x > 200): pass
elif(100 < x and x < 200 and 300 < y and y < 800):
pass

View File

@@ -160,3 +160,10 @@ def secondToTime(s0: int) -> (int, int, int) or str:
def secondToTime(s0: int) -> ((int, int, int) or str):
m, s = divmod(s0, 60)
# Regression test for: https://github.com/astral-sh/ruff/issues/9479
print(f"{a}{b}" or "bar")
print(f"{a}{''}" or "bar")
print(f"{''}{''}" or "bar")
print(f"{1}{''}" or "bar")

View File

@@ -147,3 +147,9 @@ if (a and [] and False and []) == (a and []): # SIM223
if f(a and [] and False and []): # SIM223
pass
# Regression test for: https://github.com/astral-sh/ruff/issues/9479
print(f"{a}{b}" and "bar")
print(f"{a}{''}" and "bar")
print(f"{''}{''}" and "bar")
print(f"{1}{''}" and "bar")

View File

@@ -1,18 +0,0 @@
from __future__ import annotations
from typing import TypeVar
x: "int" | str # TCH006
x: ("int" | str) | "bool" # TCH006
def func():
x: "int" | str # OK
z: list[str, str | "int"] = [] # TCH006
type A = Value["int" | str] # OK
OldS = TypeVar('OldS', int | 'str', str) # TCH006

View File

@@ -1,16 +0,0 @@
from typing import TypeVar
x: "int" | str # TCH006
x: ("int" | str) | "bool" # TCH006
def func():
x: "int" | str # OK
z: list[str, str | "int"] = [] # TCH006
type A = Value["int" | str] # OK
OldS = TypeVar('OldS', int | 'str', str) # TCH006

View File

@@ -0,0 +1,18 @@
from __future__ import annotations
from typing import TypeVar
x: "int" | str # TCH010
x: ("int" | str) | "bool" # TCH010
def func():
x: "int" | str # OK
z: list[str, str | "int"] = [] # TCH010
type A = Value["int" | str] # OK
OldS = TypeVar('OldS', int | 'str', str) # TCH010

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