Compare commits

...

635 Commits

Author SHA1 Message Date
Charlie Marsh
4a7167520a Match pylint logic 2023-03-17 17:31:34 -04:00
Charlie Marsh
41ab37e792 Rebase 2023-03-17 17:07:51 -04:00
Charlie Marsh
0b1806fdfa Merge branch 'main' into useless_return 2023-03-17 17:04:37 -04:00
Tomer Chachamu
1dd3cbd047 [pylint] invalid-characters-* (#3552) 2023-03-17 19:30:41 +00:00
Johan
bd935cbd49 [flake8-bugbear] Add no-explicit-stacklevel (B028) (#3550) 2023-03-17 19:20:08 +00:00
Charlie Marsh
babd0a05ac Avoid adding dashed line outside of docstring (#3581) 2023-03-17 14:40:32 -04:00
Micha Reiser
87fab4a2e1 Benchmark all rules (#3570) 2023-03-17 19:29:39 +01:00
Charlie Marsh
2e21920adf Respect type overrides in E721 (#3582) 2023-03-17 14:29:05 -04:00
Micha Reiser
dedf4cbdeb refactor: Move scope and binding types to scope.rs (#3573) 2023-03-17 17:31:33 +01:00
Micha Reiser
92179e6369 Scope and Binding IDs (#3572) 2023-03-17 17:12:27 +01:00
Evan Rittenhouse
33d2457909 Prefer itertools.pairwise() over zip() for successive pairs (RUF007) (#3501) 2023-03-16 23:50:45 -04:00
Charlie Marsh
373a77e8c2 Avoid C1901 violations within subscripts (#3517) 2023-03-17 02:52:05 +00:00
Jacob Latonis
73df267635 [pylint]: Implement continue-in-finally (E0116) (#3541) 2023-03-17 02:47:49 +00:00
Jonathan Plasse
f5e5caaa25 Fix autofix conflict between D209 and D400 (#3564) 2023-03-17 02:36:25 +00:00
Henry Schreiner
d9ed0aae69 ci(check_ecosystem): add cibuildwheel (#3567) 2023-03-16 22:34:56 -04:00
Charlie Marsh
e0df62b841 Rewrite mock import with starred imports (#3566) 2023-03-16 20:54:29 -04:00
Henry Schreiner
bbc87b7177 ci(check_ecosystem): add scikit-build-core (#3563) 2023-03-16 19:46:42 -04:00
Charlie Marsh
667130a4c3 Add some additional users to the users list (#3565) 2023-03-16 23:32:17 +00:00
Nyakku Shigure
72febf98b7 add PaddlePaddle to Who's Using Ruff? (#3562) 2023-03-16 14:20:11 -04:00
Xuehai Pan
e99e1fae2b ci: add python/typeshed to ecosystem check (#3559) 2023-03-16 14:19:48 -04:00
Micha Reiser
eff84442bc refactor: Add Copy implementation to Rule (#3556) 2023-03-16 17:50:18 +01:00
Micha Reiser
aa51ecedc5 ci: Benchmark CI Step (#3480) 2023-03-16 09:05:10 +01:00
Edgar R. M
9ae9cc9d2f Use value > max style in pylint and mccabe messages (#3553) 2023-03-16 01:37:25 -04:00
Micha Reiser
de1106b95a Allow dispatching the PR comment job for testing (#3535) 2023-03-15 09:34:53 +01:00
Charlie Marsh
e636c5fcf0 Avoid unused argument violations in .pyi files (#3533) 2023-03-15 03:17:19 +00:00
Charlie Marsh
12dfd57211 Bump version to v0.0.256 (#3531) 2023-03-14 22:52:21 -04:00
Charlie Marsh
d188d242a0 Avoid tracking as-imports separately with force-single-line (#3530) 2023-03-15 02:26:01 +00:00
Charlie Marsh
57796c5e59 Add last remaining deprecated typing imports (#3529) 2023-03-15 00:08:09 +00:00
Charlie Marsh
2545869797 Avoid PEP 604 isinstance errors for starred tuples (#3527) 2023-03-14 22:08:43 +00:00
Charlie Marsh
58353a4bf4 Avoid PEP 604 panic with empty tuple (#3526) 2023-03-14 22:02:15 +00:00
Charlie Marsh
a36139ae21 Replicate inline comments when splitting single-line imports (#3521) 2023-03-14 14:48:12 -04:00
Jonathan Plasse
7e904111b1 Fix PYI011 and add auto-fix (#3492) 2023-03-14 14:43:09 -04:00
Charlie Marsh
344daebb1b Refine complexity rules for try-except-else-finally (#3519) 2023-03-14 14:40:33 -04:00
Charlie Marsh
432059de35 Allow # ruff: prefix for isort action comments (#3493) 2023-03-14 14:34:28 -04:00
Charlie Marsh
c50d6da8b4 Allow string percent formatting in os.getenv (#3518) 2023-03-14 14:27:21 -04:00
Charlie Marsh
1b738f88c4 Allow f-strings and concatenations in os.getenv (#3516) 2023-03-14 17:46:34 +00:00
Charlie Marsh
1eff3dffa5 Ensure that redirect warnings appear exactly once per code (#3500) 2023-03-14 15:22:14 +00:00
Xuehai Pan
8c7317eb8d ci: fix missing short tag for cloudflare/wrangler-action (#3513) 2023-03-14 15:16:09 +00:00
Charlie Marsh
106a93eab0 Make Clap an optional feature for ruff crate (#3498) 2023-03-14 11:02:05 -04:00
Xuehai Pan
78c2b0ac47 ci: add dependabot integration for GitHub Actions (#3504) 2023-03-14 10:31:26 -04:00
Micha Reiser
d5700d7c69 Add Micro Benchmark (#3466) 2023-03-14 08:35:07 +01:00
Samuel Cormier-Iijima
3a7bdb39c9 Fix base ref determination for artifact download in ecosystem CI check (#3499) 2023-03-13 22:37:12 -04:00
Grzegorz Bokota
a82fe4a139 Fix lack of not in PLC1901 error message (#3497) 2023-03-13 19:19:41 -04:00
Charlie Marsh
62ff3b62e3 Add requires-python inference to docs (#3495) 2023-03-13 18:14:39 -04:00
Charlie Marsh
1e5db58b7b Include individual path checks in --verbose logging (#3489) 2023-03-13 17:13:47 -04:00
Charlie Marsh
a6e998d639 Remove Wasm-specific Rayon workarounds (#3490) 2023-03-13 16:48:43 -04:00
Charlie Marsh
a8c1915e2e Remove erroneous C4-to-C40 redirect (#3488) 2023-03-13 19:52:05 +00:00
Xuehai Pan
c515a1b31a PYI011: allow math constants in defaults (#3484) 2023-03-13 14:23:00 -04:00
Charlie Marsh
aa97a092bd Bump version to v0.0.255 (#3485) 2023-03-13 14:06:51 -04:00
Micha Reiser
685c242761 refactor(ruff_python_ast): Split get_argument (#3478) 2023-03-13 18:18:25 +01:00
Jonathan Plasse
b540407b74 Infer target-version from project metadata (#3470)
* Infer target-version from project metadata

* Fix requires-python with ">=3.8.16"

* Load requires-python at runtime

* Use upstream VersionSpecifiers

* Add debug information when parsing ruff.toml

* Display debug only if target_version is not set

* Bump pep440-rs to add impl Error for Pep440Error
2023-03-13 18:16:01 +01:00
Charlie Marsh
3a5fbd6d74 Upgrade RustPython to fix Serde dependency (#3481) 2023-03-13 12:29:31 -04:00
Charlie Marsh
227679b5cb Re-enable the T and C linter prefix selectors (#3452) 2023-03-13 08:20:30 -04:00
Charlie Marsh
c2750a59ab Implement an iterator for universal newlines (#3454)
# Summary

We need to support CR line endings (as opposed to LF and CRLF line endings, which are already supported). They're rare, but they do appear in Python code, and we tend to panic on any file that uses them.

Our `Locator` abstraction now supports CR line endings. However, Rust's `str#lines` implementation does _not_.

This PR adds a `UniversalNewlineIterator` implementation that respects all of CR, LF, and CRLF line endings, and plugs it into most of the `.lines()` call sites.

As an alternative design, it could be nice if we could leverage `Locator` for this. We've already computed all of the line endings, so we could probably iterate much more efficiently?

# Test Plan

Largely relying on automated testing, however, also ran over some known failure cases, like #3404.
2023-03-13 00:01:29 -04:00
Charlie Marsh
2a4d6ab3b2 Remove unnecessary Path::new from fs calls (#3476) 2023-03-12 23:18:23 -04:00
Charlie Marsh
7a80bcec58 Output GitLab paths relative to CI_PROJECT_DIR (#3475) 2023-03-13 03:03:37 +00:00
Y.D.X
297749a3a8 [doc] Update FAQ on Flake8 for structural pattern matching (#3473) 2023-03-13 02:27:22 +00:00
Charlie Marsh
8955e32b5c Respect ignores for runtime-import-in-type-checking-block (TCH004) (#3474) 2023-03-13 02:23:26 +00:00
Charlie Marsh
cd192eddf9 Add some new users to the README (#3471) 2023-03-13 00:08:58 +00:00
Jacob Latonis
675227db5c pylint: E1507 invalid-envvar-value (#3467) 2023-03-12 21:43:06 +00:00
Charlie Marsh
a65c6806a6 Avoid respecting noqa directives when RUF100 is enabled (#3469) 2023-03-12 14:37:35 -04:00
Calum Young
6c576872d4 List changes for all ecosystem repos (#3461) 2023-03-12 14:30:38 -04:00
Xuehai Pan
9858df1ac9 [FIX] PYI011: recognize Bool / Float / Complex numbers as simple defaults (#3459) 2023-03-12 17:34:09 +00:00
Charlie Marsh
7fb7268e8a Use a hash to fingerprint GitLab CI output (#3456) 2023-03-12 00:22:39 -05:00
Jacob Latonis
0f78f27713 pylint: W1508 invalid-envvar-default (#3449) 2023-03-11 16:44:42 -05:00
Charlie Marsh
12a6fc7041 Avoid removing un-aliased exceptions in OSError-aliased handlers (#3451) 2023-03-11 15:24:11 -05:00
Micha Reiser
d2988043af perf: Optimize UTF8/ASCII byte offset index (#3439) 2023-03-11 13:12:10 +01:00
Micha Reiser
cc8b13d3a7 refactor: Replace Vec in options metadata with static array (#3433) 2023-03-11 09:03:56 +00:00
Charlie Marsh
1e081cf9a6 Flag deprecated (but renamed) imports in UP035 (#3448) 2023-03-11 01:06:32 -05:00
Charlie Marsh
841bcf1cdd Remove unnecessary Serde derives (#3447) 2023-03-11 00:16:51 -05:00
Charlie Marsh
7062d1db16 Run ecosystem CI checks without --isolated (#3445) 2023-03-10 19:03:51 -05:00
Jonathan Plasse
8b561313aa Remove empty line after RUF100 auto-fix (#3414) 2023-03-10 22:57:13 +00:00
Samuel Cormier-Iijima
cfa2924664 Setup ecosystem CI (#3390)
This PR sets up an "ecosystem" check as an optional part of the CI step for pull requests. The primary piece of this is a new script in `scripts/check_ecosystem.py` which takes two ruff binaries as input and compares their outputs against a corpus of open-source code in parallel. I used ruff's `text` reporting format and stdlib's `difflib` (rather than JSON output and jsondiffs) to avoid adding another dependency. There is a new ecosystem-comment workflow to add a comment to the PR (see [this link](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/) which explains why it needs to be done as a new workflow for security reasons).
2023-03-10 17:39:07 -05:00
Florian Best
a3aeec6377 docs(pycodestyle): document rules (#3407) 2023-03-10 22:36:38 +00:00
Micha Reiser
b983d5eb3f fix: method red not found in release builds (#3434) 2023-03-10 10:17:35 +01:00
kyoto7250
bb3bb24b59 Autofix PIE810 rule violations (#3411) 2023-03-10 05:17:22 +00:00
Charlie Marsh
872829ca72 When "Args" and "Parameters" are present, prefer NumPy style (#3430) 2023-03-10 02:58:05 +00:00
Charlie Marsh
2383228709 Respect --show-fixes with --fix-only (#3426) 2023-03-09 21:37:39 +00:00
Aryaman Marathe
952307d39d [pylint] C1901: compare-to-empty-string (#3405) 2023-03-09 21:33:34 +00:00
Charlie Marsh
024caca233 Introduce a ruff_diagnostics crate (#3409)
## Summary

This PR moves `Diagnostic`, `DiagnosticKind`, and `Fix` into their own crate, which will enable us to further split up Ruff, since sub-linter crates (which need to implement functions that return `Diagnostic`) can now depend on `ruff_diagnostics` rather than Ruff.
2023-03-09 20:48:57 +00:00
DanCardin
08ec11a31e fix: Emit a more useful error if an extend points at a non-existent ruff.toml file. (#3417) 2023-03-09 19:55:09 +00:00
Micha Reiser
bd05a8a74d fix: WASM tests (#3415) 2023-03-09 11:27:59 +01:00
Micha Reiser
229f1c34cb refactor: Extract ruff_wasm (#3401) 2023-03-09 10:07:39 +00:00
Charlie Marsh
a7f3532395 Ignore multiply-assigned variables in RET504 (#3393) 2023-03-08 19:11:55 -05:00
Aaron Cunningham
3349ceb969 [flake8-bugbear] Add flake8-bugbear's B030 rule (#3400) 2023-03-08 20:41:29 +00:00
Charlie Marsh
da1f83fe32 Remove core module from ruff_python_formatter (#3373) 2023-03-08 19:11:39 +00:00
Charlie Marsh
0a9d259f9c Remove copied core modules from ruff_python_formatter (#3371) 2023-03-08 19:03:40 +00:00
Charlie Marsh
130e733023 Implement From<Located> for Range (#3377) 2023-03-08 18:50:20 +00:00
Charlie Marsh
ff2c0dd491 Use shared leading_quote implementation in ruff_python_formatter (#3396) 2023-03-08 18:21:59 +00:00
Charlie Marsh
dfe1cad928 Rename DiagnosticKind#commit to DiagnosticKind#suggestion (#3397) 2023-03-08 18:06:19 +00:00
Charlie Marsh
ffad0bcdaa Decouple Diagnostic from "all violations" enumeration (#3352) 2023-03-08 17:51:37 +00:00
Jonathan Plasse
bc869d4f52 Fix PIE802 broken auto-fix with trailing comma (#3402) 2023-03-08 12:49:01 -05:00
Micha Reiser
a3de791f0a Make ruff_cli binary a small wrapper around lib (#3398) 2023-03-08 12:11:55 +01:00
Charlie Marsh
d9dfec30eb Catch RET504 usages via decorators (#3395) 2023-03-08 00:38:01 +00:00
Charlie Marsh
3f04def3a5 Remap ChainMap, Counter, and OrderedDict imports to collections (#3392) 2023-03-07 23:53:35 +00:00
Charlie Marsh
98177754de Handle multi-line fixes for byte-string prefixing (#3391) 2023-03-07 23:33:47 +00:00
Tom Forbes
8d5374762c Relax minimum rust version to allow for point releases (#3389) 2023-03-07 13:52:25 -05:00
Charlie Marsh
bad6bdda1f Create a rust_python_ast crate (#3370)
This PR productionizes @MichaReiser's suggestion in https://github.com/charliermarsh/ruff/issues/1820#issuecomment-1440204423, by creating a separate crate for the `ast` module (`rust_python_ast`). This will enable us to further split up the `ruff` crate, as we'll be able to create (e.g.) separate sub-linter crates that have access to these common AST utilities.

This was mostly a straightforward copy (with adjustments to module imports), as the few dependencies that _did_ require modifications were handled in #3366, #3367, and #3368.
2023-03-07 15:18:40 +00:00
Charlie Marsh
a5d302fcbf Pass Range struct by value (#3376) 2023-03-07 09:53:31 -05:00
Charlie Marsh
bced58ce40 Rename runtime-evaluated-baseclasses to runtime-evaluated-base-classes (#3379) 2023-03-07 09:51:12 -05:00
Aaron Cunningham
10e252e2fb Updated forced-separate type from Rust to abstract (#3380) 2023-03-07 09:35:39 -05:00
Sasan Jacob Rasti
4dead7541f Implement configuration options runtime-evaluated-decorators and runtime-evaluated-baseclasses for flake8-type-checking (#3292) 2023-03-06 23:34:19 -05:00
Charlie Marsh
fea1af5a63 Include entire prefix when reporting rule selector errors (#3375) 2023-03-07 00:04:52 +00:00
Charlie Marsh
c0ad875339 Remove unnecessary quote-stripping method (#3372) 2023-03-06 18:28:20 -05:00
Charlie Marsh
8437399496 Remove AST checker's dependency on resolver (#3368) 2023-03-06 21:45:09 +00:00
StefanBRas
074f5634a5 Remove duplicate info in azure format (#3369) 2023-03-06 16:40:03 -05:00
Charlie Marsh
694d41897a Move visibility module into ast crate (#3367) 2023-03-06 20:14:47 +00:00
Charlie Marsh
e1ebd9130d Don't enforce typing-import rules in .pyi files (#3362) 2023-03-06 15:03:34 -05:00
Charlie Marsh
fc8ca6edd2 Remove source_code's dependency on pydocstyle (#3366) 2023-03-06 15:01:01 -05:00
konstin
709dba2e71 Remove old define_violation! (in favor of #[violation]) (#3310) 2023-03-06 17:00:29 +00:00
Charlie Marsh
d1c48016eb Rename ruff_python crate to ruff_python_stdlib (#3354)
In hindsight, `ruff_python` is too general. A good giveaway is that it's actually a prefix of some other crates. The intent of this crate is to reimplement pieces of the Python standard library and CPython itself, so `ruff_python_stdlib` feels appropriate.
2023-03-06 13:43:22 +00:00
konstin
348a38d261 Deprecate define violation (#3358)
* Add `#[violation]` proc macro as a replacement for `define_violation!`

* Switch all rules to #[violation]
2023-03-06 10:59:06 +00:00
konstin
22e6778e17 Add cargo dev generate-all --check and catch outdated docs in cargo test (#3320) 2023-03-06 11:28:38 +01:00
StefanBRas
30c71dc59a Add Azure Devops as a -format option. (#3335) 2023-03-06 02:48:39 +00:00
Charlie Marsh
5d8591fec4 Skip byte-order-mark at start of file (#3343) 2023-03-05 21:37:14 -05:00
Carlos Gonçalves
673aa6e90f feat(e231): add rule + autofix (#3344) 2023-03-05 20:09:35 +00:00
Charlie Marsh
51fe9f7d4b Treat unary operations on constants as constant-like (#3348) 2023-03-04 16:30:33 -05:00
Charlie Marsh
d7767b2bad Use u8 to represent ambiguous representants (#3345) 2023-03-04 16:01:05 -05:00
Charlie Marsh
40d3b40c14 Move binding and scope tracking into a separate ast::Context struct (#3298) 2023-03-04 14:01:20 -05:00
Charlie Marsh
376ef929b1 Upgrade RustPython (#3341) 2023-03-04 14:01:03 -05:00
Jonathan Plasse
8828e12283 Bump dependencies and move more shared dependencies into workspace (#3340) 2023-03-04 12:36:26 -05:00
Charlie Marsh
f13633cc9f Avoid panicking in invalid_escape_sequence (#3338) 2023-03-04 12:14:33 -05:00
Evan Rittenhouse
889c05c87e Explicitly put Path(...) in Pathlib violations (#3333) 2023-03-04 04:33:12 +00:00
Charlie Marsh
bbbc44336e Bump version to 0.0.254 (#3331) 2023-03-03 19:11:07 -05:00
Charlie Marsh
d216b2aaa8 Treat callables within type definitions as default-non-types (#3329) 2023-03-03 23:07:30 +00:00
Charlie Marsh
367cc43c42 Un-gate PEP 604 isinstance rewrites from keep_runtime_typing checks (#3328) 2023-03-03 17:29:41 -05:00
Charlie Marsh
b5b26d5a3e Gate PEP604 isinstance rewrites behind Python 3.10+ (#3327) 2023-03-03 22:22:14 +00:00
Charlie Marsh
dedf8aa5cc Use presence of convention-specific sections during docstring inference (#3325) 2023-03-03 17:13:11 -05:00
Charlie Marsh
eb42ce9319 Extend RET503 autofixes to "end of statement", including comments (#3324) 2023-03-03 19:15:55 +00:00
Micha Reiser
cdbe2ee496 refactor: Introduce CacheKey trait (#3323)
This PR introduces a new `CacheKey` trait for types that can be used as a cache key.

I'm not entirely sure if this is worth the "overhead", but I was surprised to find `HashableHashSet` and got scared when I looked at the time complexity of the `hash` function. These implementations must be extremely slow in hashed collections.

I then searched for usages and quickly realized that only the cache uses these `Hash` implementations, where performance is less sensitive.

This PR introduces a new `CacheKey` trait to communicate the difference between a hash and computing a key for the cache. The new trait can be implemented for types that don't implement `Hash` for performance reasons, and we can define additional constraints on the implementation:  For example, we'll want to enforce portability when we add remote caching support. Using a different trait further allows us not to implement it for types without stable identities (e.g. pointers) or use other implementations than the standard hash function.
2023-03-03 18:29:49 +00:00
konstin
d1288dc2b1 Remove maturin build from CI (#3322)
maturin build generally works when cargo build works, so imho it's not worth running it with every CI run.
2023-03-03 16:50:26 +01:00
konstin
3bcffb5bdd Add flake-pyi PYI033 "Do not use type comments in stubs" (#3302) 2023-03-03 10:45:34 -05:00
Martin Packman
98209be8aa Detect quote style ignoring docstrings (#3306)
Currently the quote style of the first string in a file is used for autodetecting what to use when rewriting code for fixes. This is an okay heuristic, but often the first line in a file is a docstring, rather than a string constant, and it's not uncommon for pre-Black code to have different quoting styles for those.

For example, in the Google style guide:
https://google.github.io/styleguide/pyguide.html
> Be consistent with your choice of string quote character within a file. Pick ' or " and stick with it. ... Docstrings must use """ regardless.

This branch adjusts the logic to instead skip over any `"""` triple doublequote string tokens. The default, if there are no single quoted strings, is still to use double quote as the style.
2023-03-02 23:59:33 -05:00
Charlie Marsh
a03fa93c3a Abort when unable to fix relative imports past module root (#3319) 2023-03-03 04:38:51 +00:00
Charlie Marsh
4de3882088 Upgrade RustPython (#3316) 2023-03-02 22:59:29 -05:00
Charlie Marsh
3a98b68dc0 Always include @classmethod and @staticmethod in decorator lists (#3314) 2023-03-03 03:49:04 +00:00
Carlos Gonçalves
7e291e542d feat(e225,226,227,228): add rules (#3300) 2023-03-02 22:54:45 +00:00
Carlos Gonçalves
6f649d6579 feat(E211): add rule + autofix (#3313) 2023-03-02 22:48:04 +00:00
Yaroslav Chvanov
508bc605a5 Implement property-decorators configuration option for pydocstyle (#3311) 2023-03-02 16:59:56 -05:00
Charlie Marsh
ffdf6e35e6 Treat function type annotations within classes as runtime-required (#3312) 2023-03-02 16:45:26 -05:00
Martin Lehoux
886992c6c2 Replace tuples with type union in isinstance or issubclass calls (#3280) 2023-03-02 15:59:15 -05:00
Charlie Marsh
187104e396 Flag out-of-date docs on CI (#3309) 2023-03-02 15:55:39 -05:00
Charlie Marsh
3ed539d50e Add a CLI flag to force-ignore noqa directives (#3296) 2023-03-01 22:28:13 -05:00
Charlie Marsh
4a70a4c323 Ignore unused imports in ModuleNotFoundError blocks (#3288) 2023-03-01 18:08:37 -05:00
Charlie Marsh
310f13c7db Redirect RUF004 to B026 (#3293) 2023-03-01 13:00:02 -05:00
konstin
2168404fc2 flake8-pyi PYI006 bad version info comparison (#3291)
Implement PYI006 "bad version info comparison"

## What it does

Ensures that you only `<` and `>=` for version info comparisons with
`sys.version_info` in `.pyi` files. All other comparisons such as
`<`, `<=` and `==` are banned.

## Why is this bad?

```python
>>> import sys
>>> print(sys.version_info)
sys.version_info(major=3, minor=8, micro=10, releaselevel='final', serial=0)
>>> print(sys.version_info > (3, 8))
True
>>> print(sys.version_info == (3, 8))
False
>>> print(sys.version_info <= (3, 8))
False
>>> print(sys.version_info in (3, 8))
False
```

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-03-01 18:58:57 +01:00
Charlie Marsh
a032b66c2e Avoid PEP 585 rewrites when builtins are shadowed (#3286) 2023-02-28 23:25:42 +00:00
Charlie Marsh
af5f7dbd83 Avoid pluralization for single --add-noqa result (#3282) 2023-02-28 15:41:18 -05:00
Charlie Marsh
8066607ea3 Add a preliminary tutorial (#3281) 2023-02-28 20:31:27 +00:00
Andy Freeland
0ed9fccce9 Upgrade RustPython (#3277)
Fixes #3207.
2023-02-28 12:21:28 -05:00
Carlos Gonçalves
074a343a63 feat(E251,E252): add rules (#3274) 2023-02-28 12:02:36 -05:00
Charlie Marsh
c7e09b54b0 Use expression span for yoda-conditions fixes (#3276) 2023-02-28 16:59:02 +00:00
Charlie Marsh
67d1f74587 Avoid raising TRY200 violations within new scopes (#3275) 2023-02-28 11:56:29 -05:00
Matthew Lloyd
1c79dff3bd Improve the message for PLW2901: use "outer" and "inner" judiciously (#3263) 2023-02-28 16:33:01 +00:00
Charlie Marsh
f5f09b489b Introduce dedicated CST tokens for other operator kinds (#3267) 2023-02-27 23:54:57 -05:00
Charlie Marsh
061495a9eb Make BoolOp its own located token (#3265) 2023-02-28 03:43:28 +00:00
Charlie Marsh
470e1c1754 Preserve comments on non-defaulted arguments (#3264) 2023-02-27 23:41:40 +00:00
Charlie Marsh
16be691712 Enable more non-panicking formatter tests (#3262) 2023-02-27 18:21:53 -05:00
Charlie Marsh
270015865b Don't flag keyword-based logging format strings (#3261) 2023-02-27 23:11:13 +00:00
Charlie Marsh
ccfa9d5b20 Deduplicate SIM116 errors (#3260) 2023-02-27 18:08:45 -05:00
Charlie Marsh
2261e194a0 Create dedicated Body nodes in the formatter CST (#3223) 2023-02-27 22:55:05 +00:00
Ville Skyttä
cd6413ca09 Match non-lowercase with S105 again (#3258) 2023-02-27 16:38:23 -05:00
Charlie Marsh
c65585e14a Use identifier_range for a few more rules (#3254) 2023-02-27 18:23:33 +00:00
Charlie Marsh
d2a6ed7be6 Upgrade RustPython (#3252) 2023-02-27 18:21:06 +00:00
Charlie Marsh
16e2dae0c2 Handle empty NamedTuple and TypedDict conversions (#3251) 2023-02-27 11:18:34 -05:00
Carlos Gonçalves
e8ba9c9e21 feat(W191): add indentation_contains_tabs (#3249) 2023-02-27 10:36:03 -05:00
Jonathan Plasse
d285f5c90a Run automatically format code blocks with Black (#3191) 2023-02-27 10:14:05 -05:00
Charlie Marsh
386ca7c9a1 Bump version to 0.0.253 (#3245) 2023-02-26 23:10:04 -05:00
Charlie Marsh
40c5abf16e Avoid flagging Pylint logging rules with starred arguments (#3244) 2023-02-26 22:58:24 -05:00
Matthew Lloyd
7e7aec7d74 Expand the range of the COM812 autofix to include the preceding token (#3241)
This prevents the UP034 autofix simultaneously stripping the
parentheses from generators in the same linter pass, which causes
a SyntaxError.

Closes #3234.

With this fix:

```python
$ cat test.py
the_first_one = next(
    (i for i in range(10) if i // 2 == 0)
)

$ cargo run --bin ruff check test.py --no-cache --select UP034,COM812 --fix
    Finished dev [unoptimized + debuginfo] target(s) in 0.08s
     Running `target/debug/ruff check test.py --no-cache --select UP034,COM812 --fix`
Found 1 error (1 fixed, 0 remaining).

$ cat test.py
the_first_one = next(
    i for i in range(10) if i // 2 == 0
)
```

* Use format

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-02-27 03:47:07 +00:00
Ivan Gozali
4b5538f74e [pylint] W0603: global-statement (#3227)
Implements pylint rule [W0603: global-statement](https://pylint.readthedocs.io/en/latest/user_guide/messages/warning/global-statement.html).

Currently checks for global statement usage in a few StmtKinds (as tested in the `pylint` `global-statement` test case [here](b70d2abd7f/tests/functional/g/globals.py)):

* Assign
* AugAssign
* ClassDef
* FunctionDef | AsyncFunctionDef
* Import
* ImportFrom
* Delete
2023-02-26 23:40:24 +00:00
Charlie Marsh
36d134fd41 Bump lint rule count to 500+ (#3240) 2023-02-26 18:10:09 -05:00
Chris Chan
0b7d6b9097 Implement pylint's else-if-used rule (PLR5501) (#3231)
Attempt to implement else-if-used
https://pylint.pycqa.org/en/latest/user_guide/messages/refactor/else-if-used.html

Issue #970
2023-02-26 22:42:33 +00:00
Nick Pope
994e2e0903 Rename some flake8-simplify rules (#2915)
Renames the following rules that stood out to me at a glance as needing better names:

- `or-true` to `expr-or-true`
- `and-false` to `expr-and-false`
- `a-or-not-a` to `expr-or-not-expr`
- `a-and-not-a` to `expr-and-not-expr`

Related to #2902.
2023-02-26 22:35:15 +00:00
Luc Khai Hai
bc79f540e4 [flake8-django] DJ003, DJ006, DJ007 (#3236)
Implements [flake8-django](https://github.com/rocioar/flake8-django) rules:
- DJ03
- DJ06
- DJ07
2023-02-26 22:29:42 +00:00
Steve Dignam
3a78b59314 [flake8-pyi]: PYI011, PYI014 (#3238)
Implement PYI011 and PYI014 with the latest changes:

https://github.com/PyCQA/flake8-pyi/pull/326
https://github.com/PyCQA/flake8-pyi/issues/316

rel: https://github.com/charliermarsh/ruff/issues/848
rel: 4212bec43d/pyi.py (L718)
2023-02-26 22:11:58 +00:00
Edgar R. M
5f83851329 [pydocstyle]: Implement ignore-decorators (#3229) 2023-02-26 21:40:01 +00:00
Carlos Gonçalves
484ce7b8fc feat(E275): add Missing whitespace after keyword (#3225) 2023-02-26 21:36:05 +00:00
Charlie Marsh
1c75071136 Implement basic rendering of remaining AST nodes (#3233) 2023-02-26 05:05:56 +00:00
Charlie Marsh
51bca19c1d Add builders for common comment rendering (#3232) 2023-02-26 04:16:24 +00:00
Steve Dignam
a8a312e862 [flake8-pyi]: PYI009, PYI010, PYI021 (#3230)
PYI009 and PYI010 are very similar, always use `...` in function and class bodies in stubs.

PYI021 bans doc strings in stubs.

I think all of these rules should be relatively straightforward to implement auto fixes for but can do that later once we get all the other rules added.

rel: https://github.com/charliermarsh/ruff/issues/848
2023-02-25 22:29:04 -05:00
Ran Benita
33c31cda27 Add noqa_row to diagnostics JSON format (#3228)
In ruff-lsp (https://github.com/charliermarsh/ruff-lsp/pull/76) we want to add a "Disable \<rule\> for this line" quickfix. However, finding the correct line into which the `noqa` comment should be inserted is non-trivial (multi-line strings for example).

Ruff already has this info, so expose it in the JSON output for use by ruff-lsp.
2023-02-25 18:13:16 -05:00
Edgar R. M
cd9fbeb560 [bandit]: Do not treat "passed" as "password" for S105/S106/S107 (#3222) 2023-02-25 15:32:53 -05:00
Jeong YunWon
84e96cdcd9 More enum work (#3212) 2023-02-25 11:40:16 -05:00
tomecki
d20474da87 fix for autofix 2023-02-25 13:12:27 +01:00
tomecki
b7df7ee370 Merge branch 'useless_return' of github.com:tomecki/ruff into useless_return 2023-02-25 13:08:38 +01:00
tomecki
d6f0d1fab2 Merge branch 'charliermarsh:main' into useless_return 2023-02-25 13:08:09 +01:00
tomecki
c9bf979e61 Merge branch 'main' into useless_return 2023-02-25 13:06:51 +01:00
tomecki
e556fb4c77 Update crates/ruff/src/rules/pylint/rules/useless_return.rs
Co-authored-by: Jeong YunWon <69878+youknowone@users.noreply.github.com>
2023-02-25 12:59:13 +01:00
Charlie Marsh
248590224a Avoid flagging logging-too-few-args with no arguments (#3220) 2023-02-24 21:57:49 -05:00
Charlie Marsh
bbc55cdb04 Allow ruff.toml file to be dot-prefixed (as .ruff.toml) (#3221) 2023-02-24 23:14:26 +00:00
Charlie Marsh
2792439eac Add TextMate to editor-integrations.md (#3219) 2023-02-24 22:57:33 +00:00
Charlie Marsh
0694aee1b6 Avoid EXE001 and EXE002 errors from stdin input (#3218) 2023-02-24 22:55:32 +00:00
Charlie Marsh
a17b5c134a Avoid rewriting any PEP 604 runtime annotations (#3217)
Following `pyupgrade`, we'll just _never_ touch these.

Closes #2981.

Closes #3215.
2023-02-24 22:39:58 +00:00
Charlie Marsh
42f61535b5 Normalize treatment of aliased and unaliased imports (#3216) 2023-02-24 22:11:03 +00:00
Carlos Gonçalves
1c01b3c934 fix(docs): broken links inside Configuration.md (#3205) 2023-02-24 18:55:33 +00:00
Jonathan Plasse
39b9a1637f Fix Markdown errors in docs (#3187) 2023-02-24 13:06:48 -05:00
Jonathan Plasse
2c692e3acf Remove --all from cargo fmt|test (#3208) 2023-02-24 12:52:59 -05:00
monosans
24add5f56c Avoid boolean-trap rules for ConfigParser get() methods (#3209) 2023-02-24 12:52:33 -05:00
Samuel Cormier-Iijima
0b7736ad79 [flake8-tidy-imports] fix autofix for relative imports (#3197) 2023-02-23 23:40:28 -05:00
Charlie Marsh
eef85067c8 Exclude globsets for --show-settings (#3201) 2023-02-24 04:23:00 +00:00
Jeong YunWon
da98fab4ae Adapt is-macro for a few enums (#3182) 2023-02-24 04:06:56 +00:00
Charlie Marsh
0f37a98d91 Use then-some pattern for sometimes-fixable rules (#3199) 2023-02-24 03:57:14 +00:00
Charlie Marsh
f38624824d Avoid autofixing some PT violations when comments are present (#3198) 2023-02-24 03:48:41 +00:00
Charlie Marsh
159422071e Handle end-of-line comments on excepthandler and alias (#3196) 2023-02-23 22:35:39 -05:00
Charlie Marsh
6eaacf96be Introduce a new CST element for slice segments (#3195) 2023-02-24 00:49:41 +00:00
Charlie Marsh
eb15371453 Make Locator available in AST-to-CST conversion pass (#3194) 2023-02-23 19:43:03 -05:00
Matt Nawara
198b301baf [pycodestyle] trailing-whitespace, blank-line-contains-whitespace (W291, W293) (#3122) 2023-02-23 19:04:45 -05:00
Jeong YunWon
c8c575dd43 Adapt BoolLike to flags (#3175) 2023-02-23 16:31:46 -05:00
Jonathan Plasse
6e54cd8233 Normalize relative markdown links (#3190) 2023-02-23 16:24:31 -05:00
Jonathan Plasse
a688a237d7 Add black to pre-commit (#3192) 2023-02-23 16:24:23 -05:00
Charlie Marsh
bda2a0007a Parenthesize numbers during attribute accesses (#3189) 2023-02-23 14:57:23 -05:00
Charlie Marsh
32d165b7ad Implement complex literal formatting (#3186) 2023-02-23 19:09:33 +00:00
Charlie Marsh
ac79bf4ee9 Implement float literal formatting (#3184) 2023-02-23 14:02:23 -05:00
Charlie Marsh
376eab3a53 Implement integer literal formatting (#3183) 2023-02-23 18:31:56 +00:00
Charlie Marsh
08be7bd285 Add a TODO to string_literal (#3181) 2023-02-23 12:46:20 -05:00
Charlie Marsh
f5241451d8 Use writeln with --show-settings (#3180) 2023-02-23 17:23:31 +00:00
Charlie Marsh
c9fe0708cb Run cargo update (#3179) 2023-02-23 12:09:36 -05:00
Charlie Marsh
09f8c487ea Update RustPython to support *tuple annotations (#3178) 2023-02-23 16:58:38 +00:00
Charlie Marsh
1e7233a8eb Add support for reformatting byte strings (#3176) 2023-02-23 16:50:24 +00:00
Charlie Marsh
f967f344fc Add support for basic Constant::Str formatting (#3173)
This PR enables us to apply the proper quotation marks, including support for escapes. There are some significant TODOs, especially around implicit concatenations like:

```py
(
  "abc"
  "def"
)
```

Which are represented as a single AST node, which requires us to tokenize _within_ the formatter to identify all the individual string parts.
2023-02-23 16:23:10 +00:00
Charlie Marsh
095f005bf4 Move RustPython vendored and helper code into its own crate (#3171) 2023-02-23 14:14:16 +00:00
Charlie Marsh
0f04aa2a5f Bind star patterns in match statements (#3169) 2023-02-23 12:39:03 +00:00
Jonathan Plasse
ad7ba77fff Fix ExceptionGroup F821 false positive (#3167) 2023-02-23 12:36:11 +00:00
Jeong YunWon
77d43795f8 Replace Autofix::is_enabled to result_like::BoolLike (#3165) 2023-02-23 07:29:13 -05:00
Jeong YunWon
4357f2be0f Add Autofix::is_enabled() to remove repeative patterns (#3159) 2023-02-22 23:52:07 -05:00
Charlie Marsh
e5c1f95545 Check-in updated snapshot (#3161) 2023-02-23 03:42:27 +00:00
Charlie Marsh
227ff62a4e Don't touch tuple brackets after in (#3160) 2023-02-23 03:10:24 +00:00
Charlie Marsh
d8e4902516 Un-modify tupleassign and function2 tests (#3158)
I manually changed these in #3080 and #3083 to get the tests passing (with notes around the deviations) -- but that's no longer necessary, now that we have proper testing that takes deviations into account.
2023-02-23 02:37:25 +00:00
Matthew Lloyd
e66739884f Add note about prioritizing naming convention over preservation (#3157) 2023-02-23 02:32:46 +00:00
Charlie Marsh
5fd827545b Add a trailing newline to all .py.expect files (#3156)
This just re-formats all the `.py.expect` files with Black, both to add a trailing newline and be doubly-certain that they're correctly formatted.

I also ensured that we add a hard line break after each statement, and that we avoid including an extra newline in the generated Markdown (since the code should contain the exact expected newlines).
2023-02-23 02:29:27 +00:00
Matthew Lloyd
c1ddcb8a60 [flake8-pie] Unnecessary list comprehension, with autofix (PIE802) (#3149) 2023-02-22 20:58:45 -05:00
Charlie Marsh
48a317d5f6 Change via to using (#3155) 2023-02-23 01:47:15 +00:00
Charlie Marsh
74e18b6cff Split up some docs sections (#3154) 2023-02-22 20:18:10 -05:00
Charlie Marsh
21d02cd51f Omit non-.py[i] files from module naming rules (#3153) 2023-02-23 00:38:46 +00:00
Charlie Marsh
049e77b939 Follow-up with some small doc changes (#3152) 2023-02-23 00:35:22 +00:00
Charlie Marsh
b9bfb81e36 Move configuration out of README and into permanent docs (#3150) 2023-02-22 19:25:53 -05:00
Charlie Marsh
2d4fae45d9 Avoid flagging unfixable TypedDict and NamedTuple definitions (#3148) 2023-02-22 23:23:25 +00:00
Charlie Marsh
726adb7efc Avoid suggesting 'is' for constant literals (#3146) 2023-02-22 22:37:22 +00:00
Charlie Marsh
dbdfdeb0e1 Add pre-commit note to docs (#3145) 2023-02-22 17:22:47 -05:00
Charlie Marsh
1c41789c2a Bump version to 0.0.252 (#3142) 2023-02-22 14:50:14 -05:00
Charlie Marsh
2f9de335db Upgrade RustPython to match new flattened exports (#3141) 2023-02-22 19:36:13 +00:00
Ran Benita
ba61bb6a6c Fix isort no-lines-before preceded by an empty section (#3139)
Fix isort no-lines-before preceded by an empty section

Fix #3138.
2023-02-22 14:35:53 -05:00
Charlie Marsh
17ab71ff75 Include match in nested block check (#3137) 2023-02-22 14:32:08 -05:00
Charlie Marsh
4ad4e3e091 Avoid useless-else-on-loop for break within match (#3136) 2023-02-22 19:12:44 +00:00
Florian Best
6ced5122e4 refactor(use-from-import): build fixed variant via AST (#3132) 2023-02-22 13:17:37 -05:00
Marijn Valk
7d55b417f7 add delta-rs to list of users (#3133) 2023-02-22 13:07:58 -05:00
Charlie Marsh
f0e0efc46f Upgrade RustPython to handle trailing commas in map patterns (#3130) 2023-02-22 11:17:13 -05:00
Charlie Marsh
1efa2e07ad Avoid match statement misidentification in token rules (#3129) 2023-02-22 15:44:45 +00:00
Charlie Marsh
df3932f750 Use file-specific quote for C408 (#3128) 2023-02-22 15:26:46 +00:00
Rupert Tombs
817d0b4902 Fix =/== error in ManualDictLookup (#3117) 2023-02-22 15:14:30 +00:00
Micha Reiser
ffd8e958fc chore: Upgrade Rust to 1.67.0 (#3125) 2023-02-22 10:03:17 -05:00
Micha Reiser
ed33b75bad test(ruff_python_formatter): Run all Black tests (#2993)
This PR changes the testing infrastructure to run all black tests and:

* Pass if Ruff and Black generate the same formatting
* Fail and write a markdown snapshot that shows the input code, the differences between Black and Ruff, Ruffs output, and Blacks output

This is achieved by introducing a new `fixture` macro (open to better name suggestions) that "duplicates" the attributed test for every file that matches the specified glob pattern. Creating a new test for each file over having a test that iterates over all files has the advantage that you can run a single test, and that test failures indicate which case is failing. 

The `fixture` macro also makes it straightforward to e.g. setup our own spec tests that test very specific formatting by creating a new folder and use insta to assert the formatted output.
2023-02-22 09:25:06 -05:00
Micha Reiser
262e768fd3 refactor(ruff): Implement doc_lines_from_tokens as iterator (#3124)
This is a nit refactor... It implements the extraction of document lines as an iterator instead of a Vector to avoid the extra allocation.
2023-02-22 09:22:06 -05:00
Ran Benita
bc3a9ce003 Mark typing.assert_never as no return (#3121)
This function always raises, so RET503 shouldn't trigger for it.
2023-02-22 09:15:39 -05:00
tomecki
02ae14037b Merge branch 'main' into useless_return 2023-02-22 09:38:18 +01:00
Charlie Marsh
48005d87f8 Add missing backticks from rustdoc (#3112) 2023-02-22 05:03:06 +00:00
Charlie Marsh
e37e9c2ca3 Skip EXE001 and EXE002 rules on Windows (#3111) 2023-02-21 23:39:56 -05:00
Matthieu Devlin
8fde63b323 [pylint] Implement E1205 and E106 (#3084) 2023-02-21 22:53:11 -05:00
Matthew Lloyd
97338e4cd6 [pylint] redefined-loop-name (W2901) (#3022)
Slightly broadens W2901 to cover `with` statements too.

Closes #2972.
2023-02-22 03:23:47 +00:00
Charlie Marsh
9645790a8b Support shell expansion for --config argument (#3107) 2023-02-21 23:33:41 +00:00
Charlie Marsh
18800c6884 Include file permissions in cache key (#3104) 2023-02-21 18:20:06 -05:00
Charlie Marsh
fd638a2e54 Bump version to 0.0.251 (#3105) 2023-02-21 18:13:59 -05:00
Charlie Marsh
fa1459d56e Avoid prefer-list-builtin for lambdas with *args or **kwargs (#3102) 2023-02-21 17:44:37 -05:00
Charlie Marsh
d93c5811ea Create bindings for MatchAs patterns (#3098) 2023-02-21 22:04:09 +00:00
Charlie Marsh
06e426f509 Bump version to 0.0.250 (#3095) 2023-02-21 15:20:46 -05:00
tomecki
385ccb2a50 rename for clarity 2023-02-21 20:54:22 +01:00
Carlos Gonçalves
6eb014b3b2 feat(B032): add b032 flake8_bugbear (#3085) 2023-02-21 19:53:29 +00:00
tomecki
ecacccbd5e cleanup 2023-02-21 20:39:33 +01:00
Charlie Marsh
d9fd78d907 Ignore setters in flake8-boolean-trap (#3092) 2023-02-21 19:31:00 +00:00
tomecki
bd7b472902 Merge branch 'main' into useless_return 2023-02-21 20:28:48 +01:00
tomecki
89b1b06dc7 wip 2023-02-21 20:28:33 +01:00
Charlie Marsh
37df07d2e0 Re-add compatibility to README (#3091) 2023-02-21 18:57:47 +00:00
Charlie Marsh
d5c65b5f1b Add support for structural pattern matching (#3047) 2023-02-21 18:52:10 +00:00
Charlie Marsh
cdc4e86158 Add support for TryStar (#3089) 2023-02-21 13:42:20 -05:00
Charlie Marsh
50ec6d3b0f Use LibCST to fix chained assertions (#3087) 2023-02-21 13:10:31 -05:00
Charlie Marsh
a6eb60cdd5 Enable function2 test (#3083) 2023-02-21 04:37:50 +00:00
Charlie Marsh
90c04b9cff Enable tupleassign test (#3080) 2023-02-21 00:42:23 +00:00
Charlie Marsh
b701cca779 Enable some already-passing Black tests (#3079) 2023-02-21 00:10:35 +00:00
Charlie Marsh
ce8953442d Add support for trailing colons in slice expressions (#3077) 2023-02-20 23:24:32 +00:00
Charlie Marsh
7d4e513a82 Omit while-True loops from implicit return enforcement (#3076) 2023-02-20 18:22:28 -05:00
Charlie Marsh
35f7f7b66d Avoid boolean-trap rules for positional-only builtin calls (#3075) 2023-02-20 23:08:18 +00:00
Charlie Marsh
6e02405bd6 Add StmtKind::Try; fix trailing newlines (#3074) 2023-02-20 22:55:32 +00:00
Carlos Gonçalves
b657468346 feat(B029): Add B029 from flake8-bugbear (#3068) 2023-02-20 15:57:13 -05:00
Micha Reiser
f72ed255e5 chore: Use LF on all platforms (#3005)
I worked on #2993 and ran into issues that the formatter tests are failing on Windows because `writeln!` emits `\n` as line terminator on all platforms, but `git` on Windows converted the line endings in the snapshots to `\r\n`.

I then tried to replicate the issue on my Windows machine and was surprised that all linter snapshot tests are failing on my machine. I figured out after some time that it is due to my global git config keeping the input line endings rather than converting to `\r\n`. 

Luckily, I've been made aware of #2033 which introduced an "override" for the `assert_yaml_snapshot` macro that normalizes new lines, by splitting the formatted string using the platform-specific newline character. This is a clever approach and gives nice diffs for multiline fixes but makes assumptions about the setup contributors use and requires special care whenever we use line endings inside of tests. 

I recommend that we remove the special new line handling and use `.gitattributes` to enforce the use of `LF` on all platforms [guide](https://docs.github.com/en/get-started/getting-started-with-git/configuring-git-to-handle-line-endings). This gives us platform agnostic tests without having to worry about line endings in our tests or different git configurations.

## Note

It may be necessary for Windows contributors to run the following command to update the line endings of their files

```bash
git rm --cached -r .
git reset --hard
```
2023-02-20 20:13:37 +00:00
Charlie Marsh
7e9dea0027 Change contributing suggestion (#3067) 2023-02-20 20:05:38 +00:00
Colin Delahunty
9545958ad8 [flake8-simplify]: Implement manual-dict-lookup (#2767) 2023-02-20 20:00:59 +00:00
Colin Delahunty
41faa335d1 [tryceratops]: Verbose Log Messages (#3036) 2023-02-20 18:21:04 +00:00
Charlie Marsh
4cfa350112 Bump version to 0.0.249 (#3063) 2023-02-20 13:11:29 -05:00
Charlie Marsh
41f163fc8d Avoid assert() to assert statement conversion in expressions (#3062) 2023-02-20 17:49:22 +00:00
Charlie Marsh
d21dd994e6 Increase expected size of FormatElement (#3049) 2023-02-20 12:47:35 -05:00
Josh Karpel
6f5a6b8c8b Do not autofix E731 in class bodies (#3050) 2023-02-20 12:38:42 -05:00
Jeong YunWon
35606d7b05 clean up to fix nightly clippy warnings and dedents (#3057) 2023-02-20 09:33:47 -05:00
Matthew Lloyd
3ad257cfea Add PDM to "Who's Using Ruff?" (#3048) 2023-02-20 03:58:22 +00:00
Charlie Marsh
b39f960cd1 Relax constraints on pep8-naming module validation (#3043) 2023-02-19 17:34:23 -05:00
Charlie Marsh
c297d46899 Remove unused AsFormat trait for Option<T> (#3041)
We should re-add this, but it's currently unused and doesn't compile under 1.66.0.

See: #3039.
2023-02-19 20:19:35 +00:00
Jonathan Plasse
d6a100028c Update docs and pre-commit after #3006 (#3038) 2023-02-19 14:23:01 -05:00
Jonathan Plasse
35d4e03f2a Fix ruff_dev regex workspace dependency (#3037) 2023-02-19 18:02:08 +00:00
Charlie Marsh
41e77bb01d Add some additional users to "Who's Using Ruff?" (#3035) 2023-02-19 16:30:01 +00:00
Charlie Marsh
2ff3dd5fbe Bump version to 0.0.248 (#3034) 2023-02-19 16:21:30 +00:00
Charlie Marsh
0f0e7a521a Avoid false-positives for break in with (#3032) 2023-02-19 11:17:04 -05:00
Jonathan Plasse
b75663be6d Add missing rust-version in crates (#3009) 2023-02-19 15:07:17 +00:00
Tomer Chachamu
4d3d04ee61 [PLE0101] error when __init__ returns a value (#3007) 2023-02-19 14:54:43 +00:00
Manuel Jacob
87422ba362 Add configuration option for C408 to allow dict calls with keyword arguments. (#2977)
When creating a dict with string keys, some prefer to call dict instead of writing a dict literal.
For example: `dict(a=1, b=2, c=3)` instead of `{"a": 1, "b": 2, "c": 3}`.
2023-02-19 14:47:03 +00:00
Jeremy Goh
c1d2976fff [docs] Add docs for flake8-implicit-str-concat rules (#3028) 2023-02-19 14:38:59 +00:00
Jeremy Goh
13281cd9ca [docs] Add some docs for flake8-simplify (#3027) 2023-02-19 14:26:56 +00:00
Jonathan Plasse
e53652779d Avoid raising B027 violations in .pyi files (#3016) 2023-02-19 14:21:33 +00:00
Jonathan Plasse
db4c611c6f Fix broken links and markdown style (#3017) 2023-02-19 08:46:49 -05:00
Charlie Marsh
c25be31eb1 Fix documentation-link detection in generate_mkdocs.py (#3030) 2023-02-19 12:20:44 +00:00
Micha Reiser
a7c533634d chore: Remove default_members from Cargo.toml (#3006)
This PR removes the `default_members` from the workspace configuration. 

## Why

I'm not familiar with the motivation for why the `default_members` setting was added initially, and I do not object to keeping it. I'll explain my motivation for removing it below. 

My main reason for removing the `default_members` override is that new contributors may not know that `cargo test`, `cargo build`, and other commands only run on a subset of crates. They may then be surprised that their PRs are failing in CI, but everything works locally. 

My guess why `default_members` was added is to speed up the development workflow. That's fair, but I question the value because `ruff` is the heaviest crate to build.
2023-02-19 07:18:47 -05:00
Simon Brugman
cfa6883431 docs(readme): add Diffusers (#3029) 2023-02-19 07:10:02 -05:00
Nyakku Shigure
216aa929af Remove duplicate underline in B007 autofix message (#3021) 2023-02-18 19:38:20 -05:00
Simon Brugman
9e45424ed6 [pycodestyle] autofix useless semicolons (#3001) 2023-02-17 18:52:42 -05:00
Charlie Marsh
db7f16e276 Support positional messages in assertion rewrites (#3002) 2023-02-17 23:44:13 +00:00
Charlie Marsh
a10a500a26 Ignore namedtuple methods in flake8-self (#2998) 2023-02-17 17:16:25 -05:00
Charlie Marsh
b9fef7cef7 Unlink flake8-bugbear in summary (#2997) 2023-02-17 15:58:33 -05:00
Charlie Marsh
34294ccc00 Deduplicate user list (#2996) 2023-02-17 20:07:42 +00:00
Simon Brugman
a934d01bdb [flake8-tidy-imports] extend autofix of relative imports (#2990)
This extends the autofix for TID252 to work with for relative imports without `module` (i.e. `from .. import`). Tested with `matplotlib` and `bokeh`.
(Previously it would panic on unwrap of the module) 

Note that pandas has [replaced](6057d7a93e) `absolufy-imports` with `ruff` now!
2023-02-17 19:35:28 +00:00
Simon Brugman
0dd590f137 Fix for F541 unescape f-string (#2971) 2023-02-17 14:27:01 -05:00
Charlie Marsh
909a5c3253 Avoid zero-indexed column for IOError (#2995) 2023-02-17 14:14:28 -05:00
Charlie Marsh
5c987874c4 Enforce D403 on methods (#2992) 2023-02-17 18:05:48 +00:00
Nyakku Shigure
0cfe4f9c69 Remove a whitespace in B004 message (#2991) 2023-02-17 12:37:08 -05:00
Charlie Marsh
6a369e4a30 Remove via from sentence in README (#2987) 2023-02-17 13:49:09 +00:00
Charlie Marsh
6f97e2c457 Split list of users into top-level and dedicated section (#2986) 2023-02-17 13:36:32 +00:00
Charlie Marsh
bebd412469 Adjust header depth in docs (#2985) 2023-02-17 13:19:55 +00:00
Charlie Marsh
cd1f57b713 Move FAQ into MkDocs (#2984) 2023-02-17 13:15:53 +00:00
Charlie Marsh
a0912deb2b Move editor integrations into MkDocs (#2983) 2023-02-17 13:12:20 +00:00
Charlie Marsh
50ee14a418 Fix references to specific settings in README.md (#2982) 2023-02-17 13:07:37 +00:00
Martin Fischer
f5adbbebc5 Fix table of contents enumeration 2023-02-17 07:55:50 -05:00
Martin Fischer
c88e05dc1b Merge Reference README section into Configuration section 2023-02-17 07:55:50 -05:00
Martin Fischer
d658bfc024 Remove options from README 2023-02-17 07:55:50 -05:00
Martin Fischer
b0d72c47b4 refactor: Move Top-level heading into ruff_dev 2023-02-17 07:55:50 -05:00
Martin Fischer
8195873cdf Remove rule tables from README 2023-02-17 07:55:50 -05:00
Martin Fischer
bf8108469f Remove auto-generated table of contents 2023-02-17 07:55:50 -05:00
Martin Fischer
a2277cfeba refactor: Move fix symbol legend into ruff_dev 2023-02-17 07:55:50 -05:00
Charlie Marsh
180541a924 Unify comment terminology with that of rome_formatter (#2979) 2023-02-17 03:02:25 +00:00
Simon Brugman
34664a0ca0 [numpy] numpy-legacy-random (#2960)
The new `Generator` in NumPy uses bits provided by [PCG64](https://numpy.org/doc/stable/reference/random/bit_generators/pcg64.html#numpy.random.PCG64) which has better statistical properties than the legacy [MT19937](https://numpy.org/doc/stable/reference/random/bit_generators/mt19937.html#numpy.random.MT19937) used in [RandomState](https://numpy.org/doc/stable/reference/random/legacy.html#numpy.random.RandomState). Global random functions can also be problematic with parallel processing.

This rule is probably quite useful for data scientists (perhaps in combination with `nbqa`)

References:
- [Legacy Random Generation](https://numpy.org/doc/stable/reference/random/legacy.html#legacy)
- [Random Sampling](https://numpy.org/doc/stable/reference/random/index.html#random-quick-start)
- [Using PyTorch + NumPy? You're making a mistake.](https://tanelp.github.io/posts/a-bug-that-plagues-thousands-of-open-source-ml-projects/)
2023-02-17 02:06:30 +00:00
Charlie Marsh
e081455b06 Add support for file-scoped noqa directives (#2978)
# Summary

This allows users to do things like:

```py
# ruff: noqa: F401
```

...to ignore all `F401` directives in a file. It's equivalent to `per-file-ignores`, but allows users to specify the behavior inline.

Note that Flake8 does _not_ support this, so we _don't_ respect `# flake8: noqa: F401`. (Flake8 treats that as equivalent to `# flake8: noqa`, so ignores _all_ errors in the file. I think all of [these usages](https://cs.github.com/?scopeName=All+repos&scope=&q=%22%23+flake8%3A+noqa%3A+%22) are probably mistakes!)

A couple notes on the details:

- If a user has `# ruff: noqa: F401` in the file, but also `# noqa: F401` on a line that would legitimately trigger an `F401` violation, we _do_ mark that as "unused" for `RUF100` purposes. This may be the wrong choice. The `noqa` is legitimately unused, but it's also not "wrong". It's just redundant.
- If a user has `# ruff: noqa: F401`, and runs `--add-noqa`, we _won't_ add `# noqa: F401` to any lines (which seems like the obvious right choice to me).

Closes #1054 (which has some extra pieces that I'll carve out into a separate issue).

Closes #2446.
2023-02-17 01:59:01 +00:00
Artem Mukhin
4f18fa6733 Add test case for '\u' prefix in B005 (#2976)
Based on #2958.
2023-02-16 19:45:29 -05:00
Charlie Marsh
6088a36cd3 Use line_suffix for end-of-line comments (#2975) 2023-02-16 18:37:40 -05:00
Charlie Marsh
66a162fa40 Handle non-from __future__ imports (#2974)
These are uncommon, but currently panic.

Closes #2967.
2023-02-16 22:56:03 +00:00
Mike Taves
e6722f92ed Add Rust Trove classifier (#2973) 2023-02-16 17:38:36 -05:00
Charlie Marsh
750c28868f Enable jemalloc on FreeBSD and NetBSD (#2965) 2023-02-16 15:21:34 -05:00
Charlie Marsh
5157f584ab Improve pow operator spacing (#2970)
Ensure that we add spaces to expressions like `foo.bar() ** 2`.
2023-02-16 15:17:32 -05:00
Charlie Marsh
1c01ec21cb Regenerate expected Black snapshots (#2968) 2023-02-16 19:39:17 +00:00
Manuel Jacob
879512742f Skip .pytype directory by default. (#2966)
Pytype stores .pyi files in .pytype that ruff shouldn’t check or touch.
2023-02-16 14:38:08 -05:00
Florian Best
a919041dda feat(isort): Implement isort.force_to_top (#2877) 2023-02-16 19:01:59 +00:00
Charlie Marsh
059601d968 Avoid trying to fix implicit returns with control flow (#2962) 2023-02-16 13:42:46 -05:00
Charlie Marsh
2ec1701543 Remove link in asyncio.create_task (#2963) 2023-02-16 17:50:56 +00:00
Charlie Marsh
370c3a5daf Remove mdcat dependency (#2959) 2023-02-16 12:09:37 -05:00
Charlie Marsh
fdcb78fd8c Avoid jemallocator on BSD (#2957) 2023-02-16 11:48:51 -05:00
Simon Brugman
2a744d24e5 docs: flake8-self remove unnecessary backticks (#2951) 2023-02-16 08:25:34 -05:00
Simon Brugman
cc30738148 Implement flake8-module-naming (#2855)
- Implement N999 (following flake8-module-naming) in pep8_naming
- Refactor pep8_naming: split rules.rs into file per rule
- Documentation for majority of the violations

Closes https://github.com/charliermarsh/ruff/issues/2734
2023-02-16 04:20:33 +00:00
Edgar R. M
147c6ff1db Exclude crates/ruff_python_formatter/resources from pre-commit check (#2947) 2023-02-15 22:56:42 -05:00
Charlie Marsh
036380e6a8 Fix add-required-import with multi-line offsets (#2946) 2023-02-16 03:24:55 +00:00
Charlie Marsh
b6587e51ee Use an enum to represent composition kind (#2945) 2023-02-15 22:14:00 -05:00
Simon Brugman
1bc37110d4 [flake8-pytest-style] autofix for composite-assertion (PT018) (#2732) 2023-02-16 00:36:07 +00:00
Lunarmagpie
28acdb76cf Add support for ensure_future for RUF006 (#2943) 2023-02-15 23:18:11 +00:00
Martin Fischer
7b09972c97 Merge convert-loop-to-any & convert-loop-to-all to reimplemented-builtin 2023-02-15 16:24:31 -05:00
Charlie Marsh
f8d46d09ef Implement asyncio-dangling-task to track asyncio.create_task calls (#2935)
This rule guards against `asyncio.create_task` usages of the form:

```py
asyncio.create_task(coordinator.ws_connect())  # Error
```

...which can lead to unexpected bugs due to the lack of a strong reference to the created task. See Will McGugan's blog post for reference: https://textual.textualize.io/blog/2023/02/11/the-heisenbug-lurking-in-your-async-code/.

Note that we can't detect issues like:

```py
def f():
    # Stored as `task`, but never used...
    task = asyncio.create_task(coordinator.ws_connect())
```

So that would be a false negative. But this catches the common case of failing to assign the task in any way.

Closes #2809.
2023-02-15 15:19:03 -05:00
Martin Fischer
294cd95c54 Update clap to fix ruff check --help description
My two clap bug fixes[1][2] have been merged and released
(see the change in README.md).

[1]: https://github.com/clap-rs/clap/pull/4710
[2]: https://github.com/clap-rs/clap/pull/4712
2023-02-15 13:30:06 -05:00
Charlie Marsh
d8e709648d Add Transformers to README (#2933) 2023-02-15 17:09:50 +00:00
Charlie Marsh
52cc4d6537 Deduplicate files provided on the command-line (#2931) 2023-02-15 12:08:34 -05:00
messense
08e9d12137 Upload ruff binaries to GitHub release (#2930) 2023-02-15 12:07:47 -05:00
Charlie Marsh
39fdc71b49 Bump version to 0.0.247 (#2932) 2023-02-15 12:06:58 -05:00
Charlie Marsh
6b0736cf4b Allow private accesses on current class (#2929) 2023-02-15 16:52:05 +00:00
Charlie Marsh
58269a918a Apply nullable-model-string-field to all classes (#2928) 2023-02-15 15:54:14 +00:00
Sawbez
9168a12679 [docs] flake8-self Private member access docs (#2912) 2023-02-15 15:42:38 +00:00
Charlie Marsh
cb971d3a48 Respect self as positional-only argument in annotation rules (#2927) 2023-02-15 15:25:17 +00:00
Charlie Marsh
57a5071b4e Rename some methods on Locator (#2926) 2023-02-15 10:21:49 -05:00
Charlie Marsh
976fe364d4 Remove setup.py (#2922) 2023-02-15 14:35:11 +00:00
messense
028c7855b2 Simplify release workflows (#2913)
* No need to build for PyPy since it only contains a binary so the platform tag is the same as CPython
* Update `maturin-action` location
2023-02-15 08:15:19 -05:00
Nick Pope
e5179f67fd Remove autogenerated docs/rules/*.md files (#2917) 2023-02-15 08:11:11 -05:00
Simon Brugman
c9c199dbca Remove testing resource introduced in #2891 (#2916) 2023-02-15 08:10:58 -05:00
Martin Fischer
70e378b736 Implement shell autocompletion for rule codes
For example:

    $ ruff check --select=EM<Tab>
    EM          -- flake8-errmsg
    EM10   EM1  --
    EM101       -- raw-string-in-exception
    EM102       -- f-string-in-exception
    EM103       -- dot-format-in-exception

(You will need to enable autocompletion as described
 in the Autocompletion section in the README.)

Fixes #2808.

(The --help help change in the README is due to a clap bug,
 for which I already submitted a fix:
 https://github.com/clap-rs/clap/pull/4710.)
2023-02-15 08:09:34 -05:00
Charlie Marsh
ca49b00e55 Add initial formatter implementation (#2883)
# Summary

This PR contains the code for the autoformatter proof-of-concept.

## Crate structure

The primary formatting hook is the `fmt` function in `crates/ruff_python_formatter/src/lib.rs`.

The current formatter approach is outlined in `crates/ruff_python_formatter/src/lib.rs`, and is structured as follows:

- Tokenize the code using the RustPython lexer.
- In `crates/ruff_python_formatter/src/trivia.rs`, extract a variety of trivia tokens from the token stream. These include comments, trailing commas, and empty lines.
- Generate the AST via the RustPython parser.
- In `crates/ruff_python_formatter/src/cst.rs`, convert the AST to a CST structure. As of now, the CST is nearly identical to the AST, except that every node gets a `trivia` vector. But we might want to modify it further.
- In `crates/ruff_python_formatter/src/attachment.rs`, attach each trivia token to the corresponding CST node. The logic for this is mostly in `decorate_trivia` and is ported almost directly from Prettier (given each token, find its preceding, following, and enclosing nodes, then attach the token to the appropriate node in a second pass).
- In `crates/ruff_python_formatter/src/newlines.rs`, normalize newlines to match Black’s preferences. This involves traversing the CST and inserting or removing `TriviaToken` values as we go.
- Call `format!` on the CST, which delegates to type-specific formatter implementations (e.g., `crates/ruff_python_formatter/src/format/stmt.rs` for `Stmt` nodes, and similar for `Expr` nodes; the others are trivial). Those type-specific implementations delegate to kind-specific functions (e.g., `format_func_def`).

## Testing and iteration

The formatter is being developed against the Black test suite, which was copied over in-full to `crates/ruff_python_formatter/resources/test/fixtures/black`.

The Black fixtures had to be modified to create `[insta](https://github.com/mitsuhiko/insta)`-compatible snapshots, which now exist in the repo.

My approach thus far has been to try and improve coverage by tackling fixtures one-by-one.

## What works, and what doesn’t

- *Most* nodes are supported at a basic level (though there are a few stragglers at time of writing, like `StmtKind::Try`).
- Newlines are properly preserved in most cases.
- Magic trailing commas are properly preserved in some (but not all) cases.
- Trivial leading and trailing standalone comments mostly work (although maybe not at the end of a file).
- Inline comments, and comments within expressions, often don’t work -- they work in a few cases, but it’s one-off right now. (We’re probably associating them with the “right” nodes more often than we are actually rendering them in the right place.)
- We don’t properly normalize string quotes. (At present, we just repeat any constants verbatim.)
- We’re mishandling a bunch of wrapping cases (if we treat Black as the reference implementation). Here are a few examples (demonstrating Black's stable behavior):

```py
# In some cases, if the end expression is "self-closing" (functions,
# lists, dictionaries, sets, subscript accesses, and any length-two
# boolean operations that end in these elments), Black
# will wrap like this...
if some_expression and f(
    b,
    c,
    d,
):
    pass

# ...whereas we do this:
if (
    some_expression
    and f(
        b,
        c,
        d,
    )
):
    pass

# If function arguments can fit on a single line, then Black will
# format them like this, rather than exploding them vertically.
if f(
    a, b, c, d, e, f, g, ...
):
    pass
```

- We don’t properly preserve parentheses in all cases. Black preserves parentheses in some but not all cases.
2023-02-15 04:06:35 +00:00
Charlie Marsh
f661c90bd7 Remove dependency on ruff_rowan (#2875)
This PR removes the dependency on `ruff_rowan` (i.e., Rome's fork of rust-analyzer's `rowan`), and in turn, trims out a lot of code in `ruff_formatter` that isn't necessary (or isn't _yet_ necessary) to power the autoformatter.

We may end up pulling some of this back in -- TBD. For example, the autoformatter has its own comment representation right now, but we may eventually want to use the `comments.rs` data structures defined in `rome_formatter`.
2023-02-15 03:54:08 +00:00
Charlie Marsh
5a84df293f Allow printing of consecutive empty lines (#2874) 2023-02-14 22:35:02 -05:00
Charlie Marsh
23d9309111 Remove JetBrains webinar badge (#2910) 2023-02-15 03:28:12 +00:00
Charlie Marsh
98ea94fdb7 Add StaticTextSlice kind to FormatElement enum (#2873)
Given our current parser abstractions, we need the ability to tell `ruff_formatter` to print a pre-defined slice from a fixed string of source code, which we've introduced here as `FormatElement::StaticTextSlice`.
2023-02-14 22:27:52 -05:00
Charlie Marsh
746e1d3436 Add contributors to acknowledgements (#2909) 2023-02-15 03:15:38 +00:00
Charlie Marsh
016ff01a04 Add an FAQ question around Python version support (#2908) 2023-02-15 03:11:44 +00:00
Charlie Marsh
298498e934 Add an Acknowledgements section to the README (#2907) 2023-02-15 00:25:07 +00:00
Charlie Marsh
3ef1c2e303 Add rome_formatter fork as ruff_formatter (#2872)
The Ruff autoformatter is going to be based on an intermediate representation (IR) formatted via [Wadler's algorithm](https://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf). This is architecturally similar to [Rome](https://github.com/rome/tools), Prettier, [Skip](https://github.com/skiplang/skip/blob/master/src/tools/printer/printer.sk), and others.

This PR adds a fork of the `rome_formatter` crate from [Rome](https://github.com/rome/tools), renamed here to `ruff_formatter`, which provides generic definitions for a formatter IR as well as a generic IR printer. (We've also pulled in `rome_rowan`, `rome_text_size`, and `rome_text_edit`, though some of these will be removed in future PRs.)

Why fork? `rome_formatter` contains code that's specific to Rome's AST representation (e.g., it relies on a fork of rust-analyzer's `rowan`), and we'll likely want to support different abstractions and formatting capabilities (there are already a few changes coming in future PRs). Once we've dropped `ruff_rowan` and trimmed down `ruff_formatter` to the code we currently need, it's also not a huge surface area to maintain and update.
2023-02-14 19:22:55 -05:00
Simon Brugman
ac028cd9f8 [numpy] deprecated type aliases (#2810)
Closes https://github.com/charliermarsh/ruff/issues/2455

Used `NPY` as prefix code as agreed in the issue.
2023-02-14 23:45:12 +00:00
Edgar R. M
c0eb5c28d1 [docs] Add docs for flake8-errmsg (#2888) 2023-02-14 23:21:34 +00:00
Martin Fischer
a77b4566e4 Fix option links in mkdocs rule pages
In 28c9263722 I introduced automatic
linkification of option references in rule documentation,
which automatically converted the following:

    ## Options

    * `namespace-packages`

to:

    ## Options

    * [`namespace-packages`]

    [`namespace-packages`]: ../../settings#namespace-packages

While the above is a correct CommonMark[1] link definition,
what I was missing was that we used mkdocs for our documentation
generation, which as it turns out uses a non-CommonMark-compliant
Markdown parser, namely Python-Markdown, which contrary to CommonMark
doesn't support link definitions containing code tags.

This commit fixes the broken links via a regex hack.

[1]: https://commonmark.org/
2023-02-14 17:56:21 -05:00
Martin Fischer
860993187e Fix link relativization in generate_mkdocs.py 2023-02-14 17:56:21 -05:00
Charlie Marsh
58d4e00604 Add publish = false to unpublished crates (#2905) 2023-02-14 22:41:14 +00:00
Simon Legner
2d95912699 docs: fix ruff generate-shell-completion (#2904) 2023-02-14 22:38:29 +00:00
Simon Brugman
4f927fbacc [flake8-tidy-imports] autofix relative imports (#2891)
Previous fix was bugged. This one is only fixing when the `module_path` is present, making it far more robust.

Closes #2764 and closes #2869
2023-02-14 22:24:59 +00:00
Anders Kaseorg
2e41301520 Switch some quotes to backticks in errors (#2889)
Improves consistency with the style decision in #723, I think.
2023-02-14 22:24:41 +00:00
Martin Fischer
3179fc110d Disable many-to-one mapping for now 2023-02-14 16:16:12 -05:00
Martin Fischer
03ae0118b7 many-to-one 9/9: Update table generation 2023-02-14 16:16:12 -05:00
Martin Fischer
05176890ee many-to-one 8/9: Drop codes from registry
This commit was generated by running:

    fastmod --accept-all '[A-Z]+[0-9]+ => ' '' crates/ruff/src/registry.rs
2023-02-14 16:16:12 -05:00
Martin Fischer
849b947b3e many-to-one 7/9: Update JSON schema 2023-02-14 16:16:12 -05:00
Martin Fischer
c314e10e54 many-to-one 6/9: Implement ruff_macros::map_codes 2023-02-14 16:16:12 -05:00
Martin Fischer
9eda286dcd many-to-one 5/9: Generate codes.rs from registry.rs
# This commit was generated by running the following Python code:
# (followed by `sed -Ei 's/(mod registry;)/\1mod codes;/' crates/ruff/src/lib.rs`
# and `cargo fmt`).

import json
import re
import subprocess

def parse_registry():
    file = open('crates/ruff/src/registry.rs')

    rules = []

    while next(file) != 'ruff_macros::register_rules!(\n':
        continue

    while (line := next(file)) != ');\n':
        line = line.strip().rstrip(',')
        if line.startswith('//') or line.startswith('#['):
            rules.append(line)
            continue
        code, path = line.split(' => ')
        name = path.rsplit('::')[-1]
        rules.append((code, name))

    while (line := next(file)) != 'pub enum Linter {\n':
        continue

    prefixes = []
    prefix2linter = []

    while (line := next(file).strip()) != '}':
        if line.startswith('//'):
            continue
        if line.startswith('#[prefix = '):
            prefixes.append(line.split()[-1].strip('"]'))
        else:
            for prefix in prefixes:
                prefix2linter.append((prefix, line.rstrip(',')))
            prefixes.clear()

    prefix2linter.sort(key = lambda t: len(t[0]), reverse=True)

    return rules, prefix2linter

rules, prefix2linter = parse_registry()

def parse_code(code):
    prefix = re.match('[A-Z]+', code).group()
    if prefix in ('E', 'W'):
        return 'Pycodestyle', code

    for prefix, linter in prefix2linter:
        if code.startswith(prefix):
            return linter, code[len(prefix) :]

    assert False

text = '''
use crate::registry::{Linter, Rule};

pub fn code_to_rule(linter: Linter, code: &str) -> Option<Rule> {
    #[allow(clippy::enum_glob_use)]
    use Linter::*;

    Some(match (linter, code) {
'''

for entry in rules:
    if isinstance(entry, str):
        if entry.startswith('//'):
            text += '\n' + entry
        else:
            text += entry
    else:
        namespace, code = parse_code(entry[0])
        text += f'({namespace}, "{code}") => Rule::{entry[1]},'
    text += '\n'

text += '''
       _ => return  None,
    })
}
'''

with open('crates/ruff/src/codes.rs', 'w') as f:
    f.write(text)
2023-02-14 16:16:12 -05:00
Martin Fischer
65a3461519 many-to-one 4/9: Rename define_rule_mapping! to register_rules!
Currently the define_rule_mapping! macro generates both the Rule enum as
well as the RuleCodePrefix enum and the mapping between the two.  After
this commit series the macro will only generate the Rule enum and the
RuleCodePrefix enum and the mapping will be generated by a new map_codes
proc macro, so we rename the macro now to fit its new purpose.
2023-02-14 16:16:12 -05:00
Martin Fischer
1b8d2df3bf many-to-one 3/9: Update RuleSelector::short_code
Same reasoning as for the previous commit ... one &'static str
becomes two &'static str because we split the RuleCodePrefix enum.
Note that the .unwrap() we have to add now, will actually
be removed in the 6th commit.
2023-02-14 16:16:12 -05:00
Martin Fischer
179ead0157 many-to-one 2/9: Newtype Rule::noqa_code return type
Rule::noqa_code previously return a single &'static str,
which was possible because we had one enum listing all
rule code prefixes. This commit series will however split up
the RuleCodePrefix enum into several enums ... so we'll end up
with two &'static str ... this commit wraps the return type
of Rule::noqa_code into a newtype so that we can easily change
it to return two &'static str in the 6th commit of this series.
2023-02-14 16:16:12 -05:00
Martin Fischer
d451c7a506 many-to-one 1/9: Rename Rule::code to Rule::noqa_code
Post this commit series several codes can be mapped to a single rule,
this commit therefore renames Rule::code to Rule::noqa_code,
which is the code that --add-noqa will add to ignore a rule.
2023-02-14 16:16:12 -05:00
Martin Fischer
502ce80c91 many-to-one 0/9: Introduce RuleSelector::Linter variant
We want to remove the variants denoting whole Linters
from the RuleCodePrefix enum, so we have to introduce
a new RuleSelector::Linter variant.
2023-02-14 16:16:12 -05:00
Charlie Marsh
49d22d8fe2 Ignore non-imperative-mood in Google docstring convention (#2900) 2023-02-14 20:42:20 +00:00
Chris May
08e0b76587 Add headers to configutation options (#2896)
This completes the word from the discussion in #2643, adding headers to clarify the `pyproject.toml` and `ruff.toml` sections.
2023-02-14 13:45:59 -05:00
Charlie Marsh
f7515739ac Improve consistency of some rule docs (#2887) 2023-02-14 04:36:37 +00:00
Sawbez
53e810ed3e [docs] Add docs for the entirety of flake8-builtins (#2840) 2023-02-14 04:30:30 +00:00
Charlie Marsh
66a195f805 Extend B904 to else branches (#2886) 2023-02-14 03:58:15 +00:00
Jeremiah England
b8483975a4 docs(SIM114): fix typo in example Python code (#2884) 2023-02-14 03:23:19 +00:00
Charlie Marsh
4dd2032687 Unversion unpublished crates (#2882) 2023-02-14 03:03:49 +00:00
Charlie Marsh
c6c15d5cf9 Avoid unnecessary-else violations in elif branches (#2881)
Long-time source of confusion -- two reports over 1800 issues apart.

Closes #1035.

Closes #2879.
2023-02-14 02:51:12 +00:00
Charlie Marsh
2bf7b35268 Re-enable custom allocators (#2876) 2023-02-14 02:37:22 +00:00
Charlie Marsh
6d1adc85fc Remove autofix for prefer-type-error (#2880) 2023-02-14 02:26:22 +00:00
Martin Fischer
02285c18d1 Remove autogenerated docs/rules/*.md files 2023-02-13 19:34:06 -05:00
Martin Fischer
8120d7c974 Change rule page links in README from GitHub to beta.ruff.rs 2023-02-13 19:34:06 -05:00
Martin Fischer
c858804ed4 refactor: Move docs/ gitignores to docs/.gitignore 2023-02-13 19:34:06 -05:00
Anders Kaseorg
b9d075c252 Alphabetize flake8-raise and flake8-self in documentation (#2871) 2023-02-13 18:03:09 -05:00
Charlie Marsh
7627e840c9 Avoid noqa removal upon unhandled syntax errors (#2864) 2023-02-13 10:37:55 -05:00
Charlie Marsh
3c03e2cb2e Rename flake8-django rules to match convention (#2861) 2023-02-13 15:30:04 +00:00
Charlie Marsh
aeae63b7ea Avoid false-positives for runtime-types in type checking blocks (#2863) 2023-02-13 10:26:34 -05:00
Charlie Marsh
7be17c5f1e Avoid false-positives with multi-byte characters in B005 (#2862) 2023-02-13 15:07:55 +00:00
Charlie Marsh
6128346b08 Re-show --target-version on CLI interface (#2859) 2023-02-13 15:04:11 +00:00
Charlie Marsh
1705574e75 Handle multiple receiver decorators in receiver-decorator (#2858) 2023-02-13 14:57:11 +00:00
Charlie Marsh
15f65fa8d6 Run cargo dev generate-all (#2860) 2023-02-13 14:55:44 +00:00
Ville Skyttä
d1cf0ee52b Remove "blanket" from RUF100 README message (#2844) 2023-02-13 14:43:35 +00:00
Florian Best
32520ff07f ci(gitignore): ignore VIM files (#2856) 2023-02-13 09:29:53 -05:00
Ville Skyttä
3659236580 Remove no longer needed setup.py INP001 ignore (#2846) 2023-02-13 09:00:35 -05:00
Charlie Marsh
dde69d50b5 Move more dependencies into workspace dependencies (#2842) 2023-02-13 04:19:26 +00:00
Charlie Marsh
67198ce7b3 Revert "Run release on tag creation"
This reverts commit c21a5912b9.
2023-02-12 23:11:31 -05:00
Charlie Marsh
c21a5912b9 Run release on tag creation 2023-02-12 22:33:01 -05:00
Charlie Marsh
48a5cd1dd9 Revert "perf: Use custom allocator (#2768)" (#2841)
This is causing wheel creation to fail on some of our more exotic build targets: https://github.com/charliermarsh/ruff/actions/runs/4159524132.

Let's figure out how to gate appropriately, but for now, reverting to get the release out.
2023-02-12 22:31:34 -05:00
Charlie Marsh
63f3d5e610 Update pre-commit instructions (#2838) 2023-02-13 00:06:40 +00:00
Charlie Marsh
7dab4807d0 Allow compound statements of single ellipsis (#2837)
This allows `class C: ...`-style compound statements in stub files.

Closes #2835.
2023-02-12 18:56:43 -05:00
Charlie Marsh
83f6e52c92 Bump version to 0.0.246 (#2834) 2023-02-12 23:39:51 +00:00
Charlie Marsh
5ce7ce5bc3 Check-in updated snapshot for SIM111 (#2836) 2023-02-12 23:37:52 +00:00
Florian Best
749d197119 docs(SIM114): fix typo in python code (#2833) 2023-02-12 18:35:29 -05:00
Charlie Marsh
46c184600f Include package inference during --add-noqa command (#2832) 2023-02-12 22:45:39 +00:00
Charlie Marsh
e2051ef72f Use smarter inversion for comparison checks (#2831) 2023-02-12 22:39:29 +00:00
Charlie Marsh
1abaece9ed Fix unused multi-assignments in a single pass (#2829) 2023-02-12 22:28:03 +00:00
Charlie Marsh
8b35b052b8 Avoid duplicates in if-with-same-arms (#2827) 2023-02-12 22:22:19 +00:00
Charlie Marsh
5a34504149 Implement ComparableStmt (#2826) 2023-02-12 22:00:01 +00:00
trag1c
0e53ddc2b3 Added Tables of Contents for CONTRIBUTING.md and CODE_OF_CONDUCT.md (#2824) 2023-02-12 16:38:18 -05:00
Colin Delahunty
1f07ad6e61 [flake8-simplify]: combine-if-conditions (#2823) 2023-02-12 21:00:32 +00:00
Charlie Marsh
1666e8ba1e Add a --show-fixes flag to include applied fixes in output (#2707) 2023-02-12 20:48:01 +00:00
Charlie Marsh
c399b3e6c1 Run cargo dev generate-all (#2822) 2023-02-12 19:11:49 +00:00
Charlie Marsh
9089ef74bc Upgrade RustPython (#2821) 2023-02-12 18:45:59 +00:00
Martin Fischer
28c9263722 Automatically linkify option references in rule documentation
Previously the rule documentation referenced configuration options
via full https:// URLs, which was bad for several reasons:

* changing the website would mean you'd have to change all URLs
* the links didn't work when building mkdocs locally
* the URLs showed up in the `ruff rule` output
* broken references weren't detected by our CI

This commit solves all of these problems by post-processing the
Markdown, recognizing sections such as:

    ## Options

    * `flake8-tidy-imports.ban-relative-imports`

`cargo dev generate-all` will automatically linkify such references
and panic if the referenced option doesn't exist.
Note that the option can also be linked in the other Markdown sections
via e.g. [`flake8-tidy-imports.ban-relative-imports`] since
the post-processing code generates a CommonMark link definition.

Resolves #2766.
2023-02-12 13:19:11 -05:00
Martin Fischer
fc4c927788 refactor: Introduce ConfigurationOptions::get method 2023-02-12 13:19:11 -05:00
Zeddicus414
26f39cac2f Add PD002 use-of-inplace-argument documentation (#2799) 2023-02-12 18:10:34 +00:00
Simon Brugman
02897a141b [flake8-tidy-imports] add documentation for banned-api (#2819) 2023-02-12 18:09:39 +00:00
Nyakku Shigure
fc465cc2af [flake8-pyi]: add rules for unrecognized platform check (PYI007, PYI008) (#2805)
Add two [flake8-pyi](https://github.com/PyCQA/flake8-pyi) rules (Y007, Y008). ref: #848

The specifications are described in [PEP 484 - Version and platform checking](https://peps.python.org/pep-0484/#version-and-platform-checking)

The original implementation in flake8-pyi is shown below.

- Implemention: 66f28a4407/pyi.py (L1429-L1443)
- Tests: 66f28a4407/tests/sysplatform.pyi
2023-02-12 18:02:38 +00:00
Charlie Marsh
ca8a122889 Add flake8-django to LICENSE (#2820) 2023-02-12 17:51:40 +00:00
Karol Onyśko
6769a5bce7 Implement flake8-django plugin rules (#2586) 2023-02-12 17:47:59 +00:00
Zeddicus414
fda93c6245 Add E722 bare-except documentation (#2796) 2023-02-12 16:51:32 +00:00
Charlie Marsh
099d5414f2 Allow non-verbose raise when cause is present (#2816)
The motivating issue here is of the following form:

```py
try:
    raise Exception("We want to hide this error message")
except Exception:
    try:
        raise Exception("We want to show this")
    except Exception as exc:
        raise exc from None
```

However, I think we should avoid this if _any_ cause is present, since causes require a named exception.

Closes #2814.
2023-02-12 16:48:13 +00:00
Charlie Marsh
9ddd5e4cfe Allow private accesses on super calls (#2815) 2023-02-12 16:11:25 +00:00
trag1c
b8835c2e35 Added MkDocs section to CONTRIBUTING.md (#2803) 2023-02-12 16:07:24 +00:00
Simon Brugman
1d4422f004 [flake8-comprehensions] improve autofix for C401, C402 and C417 (#2806) 2023-02-12 16:03:37 +00:00
Simon Brugman
2dccb7611a [flake8-comprehensions] bugfix for C413 autofix (#2804) 2023-02-12 15:56:07 +00:00
Simon Brugman
f8ac6d7bf0 fix: script add_plugin.py test import (#2807) 2023-02-12 09:58:23 -05:00
Simon Brugman
0123425be1 [flake8-comprehensions] autofix C414 and C417 + bugfix (#2693)
Closes https://github.com/charliermarsh/ruff/issues/2262 and closes https://github.com/charliermarsh/ruff/issues/2423

Fixes bug where some cases generated duplicated violations (see https://github.com/charliermarsh/ruff/pull/2732#issuecomment-1426397842)
2023-02-12 05:20:42 +00:00
Charlie Marsh
c53f91d943 Remove public re-export of commands (#2801) 2023-02-12 04:59:35 +00:00
Charlie Marsh
4a12ebb9b1 Improve f-string-missing-placeholders documentation (#2800) 2023-02-12 04:58:24 +00:00
Martin Fischer
0e4d5eeea7 Implement config subcommand
The synopsis is as follows.

List all top-level config keys:

    $ ruff config
    allowed-confusables
    builtins
    cache-dir
    ... etc.

List all config keys in a specific section:

    $ ruff config mccabe
    max-complexity

Describe a specific config option:

    $ ruff config mccabe.max-complexity
    The maximum McCabe complexity to allow before triggering `C901` errors.

    Default value: 10
    Type: int
    Example usage:
    ```toml
    # Flag errors (`C901`) whenever the complexity level exceeds 5.
    max-complexity = 5
    ```
2023-02-11 23:43:09 -05:00
Martin Fischer
bbe44360e8 refactor: Move name out of OptionField & OptionGroup 2023-02-11 23:43:09 -05:00
Martin Fischer
37e80d98ab refactor: Reorder members in ruff::settings::options_base 2023-02-11 23:43:09 -05:00
Charlie Marsh
306393063d Refactor generator to use Astor-derived precedence levels (#2798) 2023-02-12 04:30:16 +00:00
Martin Fischer
f5a3c90288 Rename new ruff rule output format to "pretty"
The new `ruff rule` output format introduced in
551b810aeb doesn't print Markdown but
rather some rich text with escape sequences for colors and links,
it's actually the "text" format that prints Markdown, so naming the new
format "markdown" is very confusing. This commit therefore renames it to
"pretty".

This isn't a breaking change since there hasn't been a release yet.
2023-02-11 23:23:37 -05:00
Charlie Marsh
8289ede00f Use output-stdout pattern for linter command (#2794) 2023-02-12 03:09:03 +00:00
Charlie Marsh
77e65c9ff5 Split commands.rs into separate files (#2792) 2023-02-12 02:58:13 +00:00
Charlie Marsh
d827a9156e Add documentation on enabling autocompletion (#2791) 2023-02-12 02:51:50 +00:00
Charlie Marsh
418808895e Add docs for f-string-missing-placeholders and unused-variable (#2790) 2023-02-12 02:48:36 +00:00
Charlie Marsh
ac4e212ed2 Move Wasm clippy to its own job (#2789) 2023-02-12 02:41:28 +00:00
Nick Pope
551b810aeb Add rendering of rule markdown for terminal output (#2747)
Add rendering of rule markdown for terminal output
    
This is achieved by making use of the `mdcat` crate.
    
See the following links for details:
    
- https://crates.io/crates/mdcat
- https://github.com/swsnr/mdcat
- https://docs.rs/mdcat/latest/mdcat/
2023-02-12 02:32:45 +00:00
Charlie Marsh
1b61d4e18b Support unused variable removal in multi-assignment statements (#2786) 2023-02-12 00:53:11 +00:00
Charlie Marsh
752c0150e1 Improve unused-variable autofixes for with statements (#2785) 2023-02-12 00:38:14 +00:00
Charlie Marsh
81651a8479 Respect continuations in noqa enforcement (#2783) 2023-02-11 23:29:37 +00:00
Charlie Marsh
86d0749ed7 Use consistent formatting for lint-failure messages (#2782) 2023-02-11 22:52:18 +00:00
Charlie Marsh
19fc410683 Remove raw string from hardcoded-sql-expression (#2780) 2023-02-11 20:05:57 +00:00
Charlie Marsh
5a70a573cd Avoid treating deferred string annotations as required-at-runtime (#2779) 2023-02-11 15:00:08 -05:00
Charlie Marsh
74731a3456 Fix reference to ban-relative-imports setting (#2776) 2023-02-11 18:34:25 +00:00
Micha Reiser
863e39fe5f perf: Use custom allocator (#2768)
This PR replaces the system allocator with a custom allocator to improve performance:

* Windows: mimalloc
* Unix: tikv-jemallocator

## Performance:

* Linux
  * `cpython --no-cache`: 208.8ms -> 190.5ms
  * `cpython`: 32.8ms -> 31ms
* Mac: 
  * `cpython --no-cache`: 436.3ms -> 380ms
  * `cpython`: 40.9ms -> 39.6ms
* Windows: 
  * `cpython --no-cache`: 367ms -> 268ms
  * `cpython`: 92.5ms -> 92.3ms
  
## Size

* Linux: +5MB from 13MB -> 18MB (I need to double check this)
* Mac: +0.7MB from 8.3MB-> 9MB
* Windows: -0.16MB from 8.29MB -> 8.13MB (that's unexpected)
2023-02-11 13:26:07 -05:00
Charlie Marsh
d0f9ee33ec Remove erroneous print statements 2023-02-11 12:45:40 -05:00
Charlie Marsh
1cf3d880a7 Don't treat all future import accesses as non-runtime (#2774)
This was just an oversight and misunderstanding on my part. We had some helpful tests, but I misunderstood the "right" behavior so thought they were passing.

Closes #2761.
2023-02-11 12:44:15 -05:00
Charlie Marsh
97dcb738fa Run cargo dev generate-all 2023-02-11 12:43:48 -05:00
Charlie Marsh
ffb4e89a98 Remove multiple-statements-on-one-line-def (E704) (#2773) 2023-02-11 12:34:21 -05:00
Charlie Marsh
43b7ee215c Ignore colon-after-lambda in compound statement rules (#2771) 2023-02-11 12:22:53 -05:00
Michał Mrówka
77099dcd4d implemented option lines-between-types for isort (#2762)
Fixes #2585

Add support for the isort option [lines_between_types](https://pycqa.github.io/isort/docs/configuration/options.html#lines-between-types)
2023-02-11 12:17:37 -05:00
Martin Fischer
70ff65154d Rename function-is-too-complex to complex-structure 2023-02-11 12:05:17 -05:00
Martin Fischer
7db6a2d6d4 Rename rules containing PEP reference in name 2023-02-11 12:05:17 -05:00
Martin Fischer
42924c0d9a Rename a bunch of pydocstyle rules 2023-02-11 12:05:17 -05:00
Martin Fischer
31d00936ee Drop no- from no-unnecessary-* rule names 2023-02-11 12:05:17 -05:00
Martin Fischer
c3c5d9a852 Rename nested-if-statements to collapsible-if 2023-02-11 12:05:17 -05:00
Martin Fischer
7e5c19385c Rename return-bool-condition-directly to needless-bool 2023-02-11 12:05:17 -05:00
Simon Brugman
5b54325c81 enable navigation in footer in docs (#2760) 2023-02-11 05:08:33 -05:00
trag1c
e6538a7969 Added logo and favicon for mkdocs (#2757) 2023-02-10 23:34:47 -05:00
Charlie Marsh
24faabf1f4 Bump version to 0.0.245 2023-02-10 22:15:27 -05:00
Charlie Marsh
9b0a160239 Only update docs on release (#2755) 2023-02-10 22:14:50 -05:00
Charlie Marsh
9fd29e2c54 Mention default in relative-imports doc 2023-02-10 22:12:22 -05:00
Simon Brugman
e83ed0ecba Implement autofix for relative imports (TID252) (#2739) 2023-02-10 22:05:47 -05:00
Charlie Marsh
dadbfea497 Flag private member accesses on calls et al (#2753) 2023-02-10 19:23:22 -05:00
Nick Pope
9f84c497f9 Adjust heading level in rule documentation (#2749) 2023-02-10 19:10:42 -05:00
Martin Fischer
0ec25d1514 Rename dynamically-typed-expression to any-type (#2751) 2023-02-10 19:02:31 -05:00
Charlie Marsh
6a87c99004 Use explicit fields for implicit-namespace-package 2023-02-10 18:09:30 -05:00
Charlie Marsh
c8f60c9588 Improve implicit-namespace-package documentation 2023-02-10 18:06:48 -05:00
Charlie Marsh
113610a8d4 Improve hardcoded-sql-expression documentation 2023-02-10 18:03:01 -05:00
Charlie Marsh
6376e5915e Improve dynamically-typed-expression documentation 2023-02-10 17:55:26 -05:00
Charlie Marsh
3d8fb5be20 Rewrite documentation for yield-in-init (#2748) 2023-02-10 17:49:55 -05:00
Charlie Marsh
0040991778 Respect NO_COLOR flags in --show-source (#2750) 2023-02-10 17:27:40 -05:00
Charlie Marsh
acb70520f8 Add colored environment variables to README (#2746) 2023-02-10 17:06:02 -05:00
Charlie Marsh
6eb9268675 Allow named unicodes in bidirectional escape check (#2710) 2023-02-10 16:59:28 -05:00
Charlie Marsh
e5f5142e3e Improve yield-in-init documentation 2023-02-10 16:47:44 -05:00
Charlie Marsh
98d5ffb817 Fix __init__.py-to-__init__ in documentation 2023-02-10 16:30:36 -05:00
Charlie Marsh
3f20f73413 Use function_type::classify for yield-in-init (#2742) 2023-02-10 16:19:45 -05:00
tomecki
a5e42d2f7c pylint: E0100 yield-in-init (#2716) 2023-02-10 16:15:15 -05:00
Charlie Marsh
0bc1f68111 Only trigger compound statements after select keywords (#2737) 2023-02-10 15:21:06 -05:00
Charlie Marsh
d2b09d77c5 Only validate __all__ bindings for global scope (#2738) 2023-02-10 15:16:21 -05:00
Charlie Marsh
0377834f9f Mark __all__ members as used at end-of-scope (#2733) 2023-02-10 14:32:05 -05:00
Charlie Marsh
3d650f9dd6 Relax conditions in bad-string-format-type (#2731) 2023-02-10 14:25:59 -05:00
Charlie Marsh
a72590ecde Expand S110 and S112 ranges to include entire exception handler (#2729) 2023-02-10 13:27:18 -05:00
Charlie Marsh
812b227334 Avoid flagging typed exceptions in tuples (#2728) 2023-02-10 13:24:45 -05:00
Martin Fischer
6f58717ba4 refactor: Stop including Rule::code() in pycodestyle .snap filenames 2023-02-10 13:15:47 -05:00
Florian Best
8aab96fb9e feat(isort): Implement known-local-folder (#2657) 2023-02-10 13:15:34 -05:00
Nick Pope
9e6f7153a9 Handle more functions that never return in RET503 (#2719) 2023-02-10 12:09:05 -05:00
Peter Pentchev
cda2ff0b18 Handle functions that never return in RET503 (#2701) 2023-02-10 09:28:34 -05:00
Martin Fischer
ec63658250 Disallow rule names starting with avoid-* 2023-02-10 09:25:29 -05:00
Martin Fischer
1a97de0b01 Disallow rule names starting with uses-* 2023-02-10 09:25:29 -05:00
Martin Fischer
1cbe48522e Disallow rule names ending in *-used 2023-02-10 09:25:29 -05:00
Martin Fischer
bfbde537af Disallow rule names starting with do-not-* 2023-02-10 09:25:29 -05:00
Martin Fischer
cba91b758b Add test for rule names 2023-02-10 09:25:29 -05:00
Martin Fischer
0bab642f5a Describe rule naming convention in CONTRIBUTING.md 2023-02-10 09:25:29 -05:00
Martin Fischer
bd09a1819f Drop unused once_cell dependency from ruff_macros 2023-02-10 09:25:29 -05:00
Martin Fischer
682d206992 refactor: Reduce code duplication 2023-02-10 08:24:22 -05:00
Martin Fischer
c32441e4ab refactor: Use format! keyword arguments 2023-02-10 08:24:22 -05:00
Martin Fischer
6f16f1c39b refactor: Reduce code duplication 2023-02-10 08:24:22 -05:00
Martin Fischer
9011456aa1 refactor: Simplify attribute handling in rule_code_prefix
if_all_same(codes.values().cloned()).unwrap_or_default()

was quite unreadable because it wasn't obvious that codes.values() are
the prefixes. It's better to introduce another Map rather than having
Maps within Maps.
2023-02-10 08:24:22 -05:00
Martin Fischer
fa191cceeb refactor: Avoid implicit precondition 2023-02-10 08:24:22 -05:00
Charlie Marsh
ac6c3affdd Remove public Rust API (#2709) 2023-02-09 23:16:49 -05:00
Charlie Marsh
9a018c1650 Import AutofixKind from violation 2023-02-09 23:06:02 -05:00
Charlie Marsh
0aef5c67a3 Remove src/registry.rs 2023-02-09 23:04:28 -05:00
Charlie Marsh
a048594416 Gate Path.readlink() behind Python 3.9+ guard (#2708) 2023-02-09 22:57:31 -05:00
Charlie Marsh
5437f1299b Remove lifetimes from Printer (#2704) 2023-02-09 21:44:15 -05:00
Charlie Marsh
41c0608a69 Add test module a test-only module (#2703) 2023-02-09 21:28:10 -05:00
messense
eb0d42187f Manage LibCST and RustPython with cargo workspace dependencies (#2700) 2023-02-09 20:49:50 -05:00
Colin Delahunty
48daa0f0ca [pylint]: bad-string-format-type (#2572) 2023-02-09 20:08:56 -05:00
Charlie Marsh
417fe4355f Add colors to statistics output (#2699) 2023-02-09 19:40:29 -05:00
Florian Best
a129181407 feat(cli): let --statistics show fixable codes (#2659) 2023-02-09 19:36:31 -05:00
Matt Oberle
fc628de667 Implement bandit's 'hardcoded-sql-expressions' S608 (#2698)
This is an attempt to implement `bandit` rule `B608` (renamed here `S608`).
- https://bandit.readthedocs.io/en/latest/plugins/b608_hardcoded_sql_expressions.html

The rule inspects strings constructed via `+`, `%`, `.format`, and `f""`.

- `+` and `%` via `BinOp`
- `.format` via `Call`
- `f""` via `JoinedString`

Any SQL-ish strings that use Python string formatting are flagged.

The expressions and targeted expression types for the rule come from here:
- 7104b336d3/bandit/plugins/injection_sql.py

> Related Issue: https://github.com/charliermarsh/ruff/issues/1646
2023-02-09 19:28:17 -05:00
Charlie Marsh
9e2418097c Run cargo dev generate-all 2023-02-09 19:14:02 -05:00
Charlie Marsh
d4e5639aaf Add flake8-pyi to CONTRIBUTING.md 2023-02-09 19:04:55 -05:00
Steve Dignam
67e58a024a Add flake8-pyi with one rule (#2682)
Add basic scaffold for [flake8-pyi](https://github.com/PyCQA/flake8-pyi) and the first rule, Y001

rel: https://github.com/charliermarsh/ruff/issues/848
2023-02-09 19:03:11 -05:00
Charlie Marsh
233be0e074 Suppress parse errors with explicit # noqa: E999 directives (#2697) 2023-02-09 18:24:19 -05:00
Nick Pope
7750087f56 Remove duplicate documentation for TRY002 (#2692) 2023-02-09 12:08:00 -05:00
Charlie Marsh
7d5fb0de8a Add documentation for mccabe, isort, and flake8-annotations (#2691) 2023-02-09 11:56:18 -05:00
Charlie Marsh
8a98cfc4b8 Treat re-exported annotations as used-at-runtime (#2689) 2023-02-09 11:22:15 -05:00
Charlie Marsh
54d1719424 Hide rule configuration settings on CLI (#2687) 2023-02-09 11:13:04 -05:00
Charlie Marsh
0f622f0126 Upgrade RustPython to pull in newline-handling optimizations (#2688) 2023-02-09 11:12:43 -05:00
Charlie Marsh
739a92e99d Implement compound-statements (E701, E702, E703, E704) (#2680) 2023-02-08 22:57:39 -05:00
Charlie Marsh
5a07c9f57c Only include rule links once in README (#2678) 2023-02-08 21:48:05 -05:00
Colin Delahunty
31027497c6 [flake8-bandit]: try-except-continue (#2674) 2023-02-08 21:44:01 -05:00
Charlie Marsh
dabfdf718e Mark flake8-simplify rules as unfixable in non-fixable cases (#2676) 2023-02-08 21:28:28 -05:00
Charlie Marsh
5829bae976 Support callable decorators in classmethod_decorators et al (#2675) 2023-02-08 21:11:36 -05:00
Charlie Marsh
ff3665a24b Mark RUF005 as fixable 2023-02-08 18:02:33 -05:00
Charlie Marsh
125615af12 Bump version to 0.0.244 2023-02-08 17:28:59 -05:00
Charlie Marsh
6339f8e009 Use separate exit codes for fatal errors vs. lint errors (#2670) 2023-02-08 15:21:15 -05:00
Charlie Marsh
81abc5d7d8 Move error and warning messages into log macro (#2669) 2023-02-08 14:39:09 -05:00
Charlie Marsh
75fad989f4 Add --exit-non-zero-on-fix (#2668) 2023-02-08 14:27:54 -05:00
Charlie Marsh
cb4a221905 Treat annotated assignments in class and module scopes as runtime (#2667) 2023-02-08 13:59:25 -05:00
Charlie Marsh
286d8c18dd Remove ExprKind::Call from call path collection (#2666) 2023-02-08 13:35:18 -05:00
Florian Best
124461bddf test(UP003): let type reference be the builtin (#2664) 2023-02-08 12:44:37 -05:00
Charlie Marsh
7482a4a5b8 Avoid false-positive in chained type calls (#2663) 2023-02-08 12:18:36 -05:00
Charlie Marsh
9f9f25ff7c Accommodate multiple @pytest.mark.parametrize decorators (#2662) 2023-02-08 11:13:24 -05:00
Nuno Mendes
9cd1bf9c03 doc: add documentation for TRY002 (#2655) 2023-02-08 11:04:31 -05:00
Florian Best
3862dc2626 docs: use new command line arguments (#2658) 2023-02-08 10:36:53 -05:00
Charlie Marsh
2a0927a5ef Update Discord link 2023-02-08 04:36:59 -05:00
Charlie Marsh
824c0d2680 Implement whitespace-before-comment (E261, E262, E265, E266) (#2654) 2023-02-07 23:41:32 -05:00
Charlie Marsh
f5efdd058e Implement whitespace-around-keywords (E271, E272, E273, E274) (#2653) 2023-02-07 22:31:13 -05:00
Charlie Marsh
4c35feaa18 Add documentation for eradicate, flake8-import-conventions, and flake8-no-pep420 (#2652) 2023-02-07 22:19:21 -05:00
Charlie Marsh
8261d0656e Disable autofix for flake8-print rules (#2651) 2023-02-07 21:38:57 -05:00
Charlie Marsh
a9aa96b24f Add documentation for flake8-quotes rules (#2650) 2023-02-07 21:20:24 -05:00
Charlie Marsh
367f115d83 Add color to fixable error asterisk (#2647) 2023-02-07 19:12:18 -05:00
Charlie Marsh
56398e0002 Tweak format for rule explanations (#2645) 2023-02-07 19:02:41 -05:00
Ville Skyttä
4b49fd9494 Ignore all non-.py wrt. implicit namespace package (#2640)
It's not only `.pyi` that should be exempt for this, but also for example scripts which don't have an extension, explicitly passed in command line args.
2023-02-07 18:21:59 -05:00
Charlie Marsh
271e4fda8c Create per-rule pages and link from README (#2644) 2023-02-07 18:15:05 -05:00
Charlie Marsh
f1cdd108e6 Derive explanation method on Rule struct via rustdoc (#2642)
```console
❯ cargo run rule B017
    Finished dev [unoptimized + debuginfo] target(s) in 0.13s
     Running `target/debug/ruff rule B017`
no-assert-raises-exception

Code: B017 (flake8-bugbear)

### What it does
Checks for `self.assertRaises(Exception)`.

## Why is this bad?
`assertRaises(Exception)` can lead to your test passing even if the
code being tested is never executed due to a typo.

Either assert for a more specific exception (builtin or custom), use
`assertRaisesRegex` or the context manager form of `assertRaises`.
```
2023-02-07 17:23:29 -05:00
Charlie Marsh
8fd29b3b60 Remove dependency on "unparse" feature (#2641) 2023-02-07 17:23:09 -05:00
Charlie Marsh
e427171323 Unify imports from rustpython_parser::ast (#2639) 2023-02-07 16:54:50 -05:00
Charlie Marsh
be08384fb0 Run cargo dev generate-all 2023-02-07 16:48:06 -05:00
Charlie Marsh
2f7f4943e3 Rename some local variables 2023-02-07 16:24:53 -05:00
Charlie Marsh
67e9ff7cc8 Reorder imports (#2638) 2023-02-07 16:22:47 -05:00
Charlie Marsh
0355ba571e Skip ternary fixes for yields and awaits (#2637) 2023-02-07 15:18:52 -05:00
Charlie Marsh
38db7fd114 Avoid boolean-trap errors in __setitem__ (#2636) 2023-02-07 15:04:33 -05:00
Charlie Marsh
8ee51eb5c6 Treat @staticmethod as higher-precedence than ABC (#2635) 2023-02-07 14:57:03 -05:00
Aarni Koskela
2bc16eb4e3 flake8-annotations: add ignore-fully-untyped (#2128)
This PR adds a configuration option to inhibit ANN* violations for functions that have no other annotations either, for easier gradual typing of a large codebase.
2023-02-07 11:35:57 -05:00
Charlie Marsh
4e36225145 Avoid no-unnecessary-dict-kwargs errors with reserved keywords (#2628) 2023-02-07 11:25:09 -05:00
Charlie Marsh
850069d0aa Avoid non-recursion in nested typing function calls (#2627) 2023-02-07 11:21:49 -05:00
Charlie Marsh
9fa98ed90b Accommodate pos-only arguments when checking self name (#2626) 2023-02-07 10:50:50 -05:00
Charlie Marsh
2b4ce78830 Delete unreferenced snapshots (#2619) 2023-02-06 23:22:41 -05:00
Colin Delahunty
7647cafe12 [pylint]: bidirectional-unicode (#2589) 2023-02-06 22:49:18 -05:00
Charlie Marsh
7686179318 Remove unused src/registry.rs 2023-02-06 22:43:25 -05:00
Charlie Marsh
bf718fdf26 Bump Ruff version to 0.0.243 2023-02-06 21:22:54 -05:00
Steve Dignam
3b3466f6da Add flake8-pie single_starts_ends_with (#2616) 2023-02-06 21:22:32 -05:00
Charlie Marsh
f981f491aa Support ignore-names for all relevant pep8-naming rules (#2617) 2023-02-06 21:14:55 -05:00
Charlie Marsh
95fef43c4d Add some additional tests for relative imports 2023-02-06 21:13:23 -05:00
Charlie Marsh
097c679cf3 Support relative paths for typing-modules (#2615) 2023-02-06 19:51:37 -05:00
Charlie Marsh
3bca987665 Avoid removing quotes from runtime annotations (#2614) 2023-02-06 18:15:19 -05:00
Ville Skyttä
60ee1d2c17 fix(pep8-naming): typing.NamedTuple and typing.TypedDict treatment (#2611) 2023-02-06 17:11:37 -05:00
Charlie Marsh
2dd04dd6a3 Check in updated snapshot 2023-02-06 16:34:47 -05:00
Charlie Marsh
e59b75d31b Bump version to 0.0.242 2023-02-06 16:25:29 -05:00
Charlie Marsh
610f150dd1 Remove autofix from bad-str-strip-call; add suggestions instead (#2610) 2023-02-06 16:25:20 -05:00
Charlie Marsh
cee0d0abaa Check in updated snapshot 2023-02-06 15:48:23 -05:00
Charlie Marsh
12ed1837ee Ignore typos in snapshots (#2609) 2023-02-06 15:43:03 -05:00
Colin Delahunty
6272293180 [pylint]: bad-str-strip-call (With Autofix) (#2570) 2023-02-06 15:34:37 -05:00
Charlie Marsh
f8b8b05b80 Visit deferred assignments after deferred type annotations (#2607) 2023-02-06 14:40:41 -05:00
Charlie Marsh
79776c12e2 Allow blank line before sticky-comment functions in docstrings (#2597) 2023-02-05 18:48:29 -05:00
Charlie Marsh
7fa5ce8b63 Automatically remove empty type-checking blocks (#2598) 2023-02-05 18:46:07 -05:00
Charlie Marsh
f6864a96f6 Enable autofix for unnecessary-paren-on-raise-exception (#2596) 2023-02-05 18:19:27 -05:00
Charlie Marsh
291ef9856a Remove unnecessary super_args.rs (#2594) 2023-02-05 18:02:09 -05:00
Charlie Marsh
87d0aa5561 Move python into its own ruff_python crate (#2593) 2023-02-05 17:53:58 -05:00
Charlie Marsh
ecc9f5de99 Fix accidental setup.py changes 2023-02-05 17:18:11 -05:00
Charlie Marsh
f40b974206 Add a description of project structure (#2590) 2023-02-05 17:01:09 -05:00
Micha Reiser
cd8be8c0be refactor: Introduce crates folder (#2088)
This PR introduces a new `crates` directory and moves all "product" crates into that folder. 

Part of #2059.
2023-02-05 16:47:48 -05:00
Charlie Marsh
e3dfa2e04e Implement pycodestyle's logical line detection (#1130)
Along with the logical line detection, this adds 14 of the missing `pycodestyle` rules.

For now, this is all gated behind a `logical_lines` feature that's off-by-default, which will let us implement all rules prior to shipping, since we want to couple the release of these rules with new defaults and instructions.
2023-02-05 15:06:02 -05:00
Ville Skyttä
f03c8fff14 fix(commented-out-code): mypy and SPDX-License-Identifier false positives (#2587)
https://mypy.readthedocs.io/en/stable/inline_config.html#configuration-comment-format
https://spdx.github.io/spdx-spec/v2.3/using-SPDX-short-identifiers-in-source-files/#e2-format-for-spdx-license-identifier
2023-02-05 15:04:36 -05:00
Charlie Marsh
452b5a4b79 Propagate attribute-like macros in define_rule_mapping (#2583)
This enables us to feature-flag rules, like:

```rust
ruff_macros::define_rule_mapping!(
    #[cfg(feature = "logical_lines")]
    E111 => rules::pycodestyle::rules::IndentationWithInvalidMultiple,
    ...
)
```
2023-02-05 12:26:23 -05:00
Colin Delahunty
1e1dc3a7ed [pyupgrade]: Removes quotes from annotations (#2431) 2023-02-05 09:43:09 -05:00
Charlie Marsh
84be1df9d5 Avoid infinite renames for unused-loop-control-variable (#2581) 2023-02-05 08:01:07 -05:00
Florian Best
6b3ae1a8e1 fix: fix syntax error in Python test COM81 (#2575) 2023-02-05 07:11:46 -05:00
Colin Delahunty
5275f6c90e Allows UP030 to work better with *args and **kwargs (#2568) 2023-02-04 17:34:48 -05:00
Anders Kaseorg
6683ed49bc Portably find ruff binary path from Python (#2574)
Prefer the version from a currently active virtualenv over a version
from `pip install --user`.  Add the .exe extension on Windows, and
find the path for `pip install --user` correctly on Windows.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-02-04 17:19:27 -05:00
Chris Chan
ced55084db Implement pylint's too-many-return-statements rule (PLR0911) (#2564) 2023-02-04 16:56:36 -05:00
Chris Chan
f8f36a7ee0 Implement pylint's too-many-branches rule (PLR0912) (#2550) 2023-02-04 16:38:03 -05:00
Charlie Marsh
4190031618 Run cargo fmt 2023-02-04 08:36:57 -05:00
Matteo Vitali
5a9258327b Fix python module invocation (#2563) 2023-02-04 08:23:13 -05:00
Charlie Marsh
dd0145624b Ignore direct root-children in implicit-namespace-package (#2565) 2023-02-04 08:21:24 -05:00
3409 changed files with 182303 additions and 102780 deletions

View File

@@ -1,5 +1,6 @@
[alias]
dev = "run --package ruff_dev --bin ruff_dev"
benchmark = "bench -p ruff_benchmark --"
[target.'cfg(all())']
rustflags = [

6
.gitattributes vendored Normal file
View File

@@ -0,0 +1,6 @@
* text=auto eol=lf
crates/ruff/resources/test/fixtures/isort/line_ending_crlf.py text eol=crlf
crates/ruff/resources/test/fixtures/pycodestyle/W605_1.py text eol=crlf
ruff.schema.json linguist-generated=true text=auto eol=lf

11
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "12:00"
timezone: "America/New_York"
commit-message:
prefix: "ci(deps)"

133
.github/workflows/benchmark.yaml vendored Normal file
View File

@@ -0,0 +1,133 @@
name: Benchmark
on:
pull_request:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true
jobs:
run-benchmark:
if: github.event_name == 'pull_request'
name: "Run | ${{ matrix.os }}"
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: "PR - Checkout Branch"
uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: "PR - Install Rust toolchain"
run: rustup show
- uses: Swatinem/rust-cache@v1
- name: "PR - Build benchmarks"
uses: actions-rs/cargo@v1
with:
command: bench
args: -p ruff_benchmark --no-run
- name: "PR - Run benchmarks"
run: cargo benchmark --save-baseline=pr
- name: "Main - Checkout Branch"
uses: actions/checkout@v3
with:
clean: false
ref: main
- name: "Main - Install Rust toolchain"
run: rustup show
- name: "Main - Build benchmarks"
uses: actions-rs/cargo@v1
with:
command: bench
args: -p ruff_benchmark --no-run
- name: "Main - Run benchmarks"
run: cargo benchmark --save-baseline=main
- name: "Upload benchmark results"
uses: actions/upload-artifact@v3
with:
name: benchmark-results-${{ matrix.os }}
path: ./target/criterion
# Cleanup
- name: Remove Criterion Artifact
uses: JesseTG/rm@v1.0.3
with:
path: ./target/criterion
benchmark-compare:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
name: Compare
needs:
- run-benchmark
steps:
- name: "Install Rust toolchain"
run: rustup show
- name: "Install critcmp"
# Use debug build: Building takes much longer than the "slowness" of using the debug build.
run: cargo install --debug critcmp
- name: "Linux | Download PR benchmark results"
uses: actions/download-artifact@v3
with:
name: benchmark-results-ubuntu-latest
path: ./target/criterion
- name: "Linux | Compare benchmark results"
shell: bash
run: |
echo "### Benchmark" >> summary.md
echo "#### Linux" >> summary.md
echo "\`\`\`" >> summary.md
critcmp main pr >> summary.md
echo "\`\`\`" >> summary.md
echo "" >> summary.md
- name: "Linux | Cleanup benchmark results"
run: rm -rf ./target/criterion
- name: "Windows | Download PR benchmark results"
uses: actions/download-artifact@v3
with:
name: benchmark-results-windows-latest
path: ./target/criterion
- name: "Windows | Compare benchmark results"
shell: bash
run: |
echo "#### Windows" >> summary.md
echo "\`\`\`" >> summary.md
critcmp main pr >> summary.md
echo "\`\`\`" >> summary.md
echo "" >> summary.md
echo ${{ github.event.pull_request.number }} > pr-number
cat summary.md > $GITHUB_STEP_SUMMARY
- uses: actions/upload-artifact@v3
name: Upload PR Number
with:
name: pr-number
path: pr-number
- uses: actions/upload-artifact@v3
name: Upload Summary
with:
name: summary
path: summary.md

View File

@@ -17,20 +17,6 @@ env:
RUSTUP_MAX_RETRIES: 10
jobs:
cargo-build:
name: "cargo build"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: "Install Rust toolchain"
run: rustup show
- uses: Swatinem/rust-cache@v1
- run: cargo build --all
- run: ./target/debug/ruff_dev generate-all
- run: git diff --quiet README.md || echo "::error file=README.md::This file is outdated. Run 'cargo dev generate-all'."
- run: git diff --quiet ruff.schema.json || echo "::error file=ruff.schema.json::This file is outdated. Run 'cargo dev generate-all'."
- run: git diff --exit-code -- README.md ruff.schema.json
cargo-fmt:
name: "cargo fmt"
runs-on: ubuntu-latest
@@ -40,7 +26,7 @@ jobs:
run: rustup component add rustfmt
- run: cargo fmt --all --check
cargo_clippy:
cargo-clippy:
name: "cargo clippy"
runs-on: ubuntu-latest
steps:
@@ -48,10 +34,20 @@ jobs:
- name: "Install Rust toolchain"
run: |
rustup component add clippy
rustup target add wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v1
- uses: Swatinem/rust-cache@v2
- run: cargo clippy --workspace --all-targets --all-features -- -D warnings
- run: cargo clippy -p ruff --target wasm32-unknown-unknown --all-features -- -D warnings
cargo-clippy-wasm:
name: "cargo clippy (wasm)"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: "Install Rust toolchain"
run: |
rustup component add clippy
rustup target add wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v2
- run: cargo clippy -p ruff_wasm --target wasm32-unknown-unknown --all-features -- -D warnings
cargo-test:
strategy:
@@ -63,19 +59,19 @@ jobs:
- uses: actions/checkout@v3
- name: "Install Rust toolchain"
run: rustup show
- uses: Swatinem/rust-cache@v1
- uses: Swatinem/rust-cache@v2
- run: cargo install cargo-insta
- run: pip install black[d]==22.12.0
- run: pip install black[d]==23.1.0
- name: "Run tests (Ubuntu)"
if: ${{ matrix.os == 'ubuntu-latest' }}
run: |
cargo insta test --all --delete-unreferenced-snapshots
cargo insta test --all --all-features --delete-unreferenced-snapshots
git diff --exit-code
- name: "Run tests (Windows)"
if: ${{ matrix.os == 'windows-latest' }}
shell: bash
run: |
cargo insta test --all
cargo insta test --all --all-features
git diff --exit-code
- run: cargo test --package ruff_cli --test black_compatibility_test -- --ignored
# Check for broken links in the documentation.
@@ -83,6 +79,31 @@ jobs:
env:
# Setting RUSTDOCFLAGS because `cargo doc --check` isn't yet implemented (https://github.com/rust-lang/cargo/issues/10025).
RUSTDOCFLAGS: "-D warnings"
- uses: actions/upload-artifact@v3
if: ${{ matrix.os == 'ubuntu-latest' }}
with:
name: ruff
path: target/debug/ruff
cargo-test-wasm:
runs-on: ubuntu-latest
name: "cargo test (wasm)"
steps:
- uses: actions/checkout@v3
- name: "Install Rust toolchain"
run: rustup target add wasm32-unknown-unknown
- uses: actions/setup-node@v3
with:
node-version: 18
cache: "npm"
cache-dependency-path: playground/package-lock.json
- uses: jetli/wasm-pack-action@v0.4.0
- uses: Swatinem/rust-cache@v2
- name: "Run wasm-pack"
run: |
cd crates/ruff_wasm
wasm-pack test --node
scripts:
name: "test scripts"
@@ -91,7 +112,7 @@ jobs:
- uses: actions/checkout@v3
- name: "Install Rust toolchain"
run: rustup show
- uses: Swatinem/rust-cache@v1
- uses: Swatinem/rust-cache@v2
- run: ./scripts/add_rule.py --name DoTheThing --code PLC999 --linter pylint
- run: cargo check
- run: |
@@ -99,21 +120,6 @@ jobs:
./scripts/add_rule.py --name FirstRule --code TST001 --linter test
- run: cargo check
maturin-build:
name: "maturin build"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: "Install Rust toolchain"
run: rustup show
- uses: Swatinem/rust-cache@v1
- uses: actions/setup-python@v4
with:
python-version: "3.11"
- run: pip install maturin
- run: maturin build -b bin
- run: python scripts/transform_readme.py --target pypi
typos:
name: "spell check"
runs-on: ubuntu-latest
@@ -122,3 +128,51 @@ jobs:
- uses: crate-ci/typos@master
with:
files: .
ecosystem:
name: "ecosystem"
runs-on: ubuntu-latest
needs: cargo-test
# Only runs on pull requests, since that is the only we way we can find the base version for comparison.
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.11"
- uses: actions/download-artifact@v3
name: Download Ruff binary
id: ruff-target
with:
name: ruff
path: target/debug
- uses: dawidd6/action-download-artifact@v2
name: Download base results
with:
name: ruff
branch: ${{ github.event.pull_request.base.ref }}
check_artifacts: true
- name: Run ecosystem check
run: |
# Make executable, since artifact download doesn't preserve this
chmod +x ruff ${{ steps.ruff-target.outputs.download-path }}/ruff
scripts/check_ecosystem.py ruff ${{ steps.ruff-target.outputs.download-path }}/ruff | tee ecosystem-result
cat ecosystem-result > $GITHUB_STEP_SUMMARY
echo ${{ github.event.number }} > pr-number
- uses: actions/upload-artifact@v3
name: Upload PR Number
with:
name: pr-number
path: pr-number
- uses: actions/upload-artifact@v3
name: Upload Results
with:
name: ecosystem-result
path: ecosystem-result

View File

@@ -1,12 +1,8 @@
name: mkdocs
on:
push:
paths:
- README.md
- mkdocs.template.yml
- .github/workflows/docs.yaml
branches: [main]
release:
types: [published]
workflow_dispatch:
jobs:
@@ -17,9 +13,12 @@ jobs:
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
- name: "Install Rust toolchain"
run: rustup show
- uses: Swatinem/rust-cache@v2
- name: "Install dependencies"
run: |
pip install "mkdocs~=1.4.2" "mkdocs-material~=9.0.6"
pip install -r docs/requirements.txt
- name: "Copy README File"
run: |
python scripts/transform_readme.py --target mkdocs

View File

@@ -27,7 +27,7 @@ jobs:
- name: "Install Rust toolchain"
run: rustup show
- name: "Build wheels - x86_64"
uses: messense/maturin-action@v1
uses: PyO3/maturin-action@v1
with:
target: x86_64
args: --release --out dist --sdist -m ./${{ env.CRATE_NAME }}/Cargo.toml
@@ -50,7 +50,7 @@ jobs:
- name: "Install Rust toolchain"
run: rustup show
- name: "Build wheels - universal2"
uses: messense/maturin-action@v1
uses: PyO3/maturin-action@v1
with:
args: --release --universal2 --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
- name: "Install built wheel - universal2"
@@ -76,7 +76,7 @@ jobs:
- name: "Install Rust toolchain"
run: rustup show
- name: "Build wheels"
uses: messense/maturin-action@v1
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
args: --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
@@ -102,7 +102,7 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64
- name: "Build wheels"
uses: messense/maturin-action@v1
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
manylinux: auto
@@ -128,12 +128,12 @@ jobs:
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: "Build wheels"
uses: messense/maturin-action@v1
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
manylinux: auto
args: --no-default-features --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
- uses: uraimo/run-on-arch-action@v2.5.0
- uses: uraimo/run-on-arch-action@v2
if: matrix.target != 'ppc64'
name: Install built wheel
with:
@@ -166,7 +166,7 @@ jobs:
python-version: ${{ env.PYTHON_VERSION }}
architecture: x64
- name: "Build wheels"
uses: messense/maturin-action@v1
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
manylinux: musllinux_1_2
@@ -201,12 +201,12 @@ jobs:
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: "Build wheels"
uses: messense/maturin-action@v1
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
manylinux: musllinux_1_2
args: --release --out dist -m ./${{ env.CRATE_NAME }}/Cargo.toml
- uses: uraimo/run-on-arch-action@master
- uses: uraimo/run-on-arch-action@v2
name: Install built wheel
with:
arch: ${{ matrix.platform.arch }}
@@ -222,40 +222,6 @@ jobs:
name: wheels
path: dist
pypy:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
target: [x86_64, aarch64]
python-version:
- "3.7"
- "3.8"
- "3.9"
exclude:
- os: macos-latest
target: aarch64
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: pypy${{ matrix.python-version }}
- name: "Build wheels"
uses: messense/maturin-action@v1
with:
target: ${{ matrix.target }}
manylinux: auto
args: --release --out dist -i pypy${{ matrix.python-version }} -m ./${{ env.CRATE_NAME }}/Cargo.toml
- name: "Install built wheel"
if: matrix.target == 'x86_64'
run: |
pip install dist/${{ env.CRATE_NAME }}-*.whl --force-reinstall
- name: "Upload wheels"
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist
release:
name: Release
runs-on: ubuntu-latest
@@ -267,7 +233,6 @@ jobs:
- linux-cross
- musllinux
- musllinux-cross
- pypy
steps:
- uses: actions/download-artifact@v3
with:

View File

@@ -28,7 +28,7 @@ jobs:
- uses: jetli/wasm-pack-action@v0.4.0
- uses: jetli/wasm-bindgen-action@v0.2.0
- name: "Run wasm-pack"
run: wasm-pack build --target web --out-dir playground/src/pkg . -- -p ruff
run: wasm-pack build --target web --out-dir ../../playground/src/pkg crates/ruff_wasm
- name: "Install Node dependencies"
run: npm ci
working-directory: playground

83
.github/workflows/pr-comment.yaml vendored Normal file
View File

@@ -0,0 +1,83 @@
name: PR Check Comment
on:
workflow_run:
workflows: [CI, Benchmark]
types: [completed]
workflow_dispatch:
inputs:
workflow_run_id:
description: The ecosystem workflow that triggers the workflow run
required: true
permissions:
pull-requests: write
jobs:
comment:
runs-on: ubuntu-latest
steps:
- uses: dawidd6/action-download-artifact@v2
name: Download PR Number
with:
name: pr-number
run_id: ${{ github.event.workflow_run.id || github.event.inputs.workflow_run_id }}
if_no_artifact_found: ignore
- name: Extract PR Number
id: pr-number
run: |
if [[ -f pr-number ]]
then
echo "pr-number=$(<pr-number)" >> $GITHUB_OUTPUT
fi
- uses: dawidd6/action-download-artifact@v2
name: "Download Ecosystem Result"
id: download-ecosystem-result
if: steps.pr-number.outputs.pr-number
with:
name: ecosystem-result
workflow: ci.yaml
pr: ${{ steps.pr-number.outputs.pr-number }}
path: pr/ecosystem
if_no_artifact_found: ignore
- uses: dawidd6/action-download-artifact@v2
name: "Download Benchmark Result"
id: download-benchmark-result
if: steps.pr-number.outputs.pr-number
with:
name: summary
workflow: benchmark.yaml
pr: ${{ steps.pr-number.outputs.pr-number }}
path: pr/benchmark
if_no_artifact_found: ignore
- name: Generate Comment
id: generate-comment
if: steps.download-ecosystem-result.outputs.found_artifact == 'true' || steps.download-benchmark-result.outputs.found_artifact == 'true'
run: |
echo 'comment<<EOF' >> $GITHUB_OUTPUT
echo '## PR Check Results' >> $GITHUB_OUTPUT
if [[ -f pr/ecosystem/ecosystem-result ]]
then
echo "### Ecosystem" >> $GITHUB_OUTPUT
cat pr/ecosystem/ecosystem-result >> $GITHUB_OUTPUT
fi
if [[ -f pr/benchmark/summary.md ]]
then
cat pr/benchmark/summary.md >> $GITHUB_OUTPUT
fi
echo 'EOF' >> $GITHUB_OUTPUT
- name: Create or update comment
if: steps.generate-comment.outputs.comment
uses: thollander/actions-comment-pull-request@v2
with:
pr_number: ${{ steps.pr-number.outputs.pr-number }}
message: ${{ steps.generate-comment.outputs.comment }}
comment_tag: PR Check Results

View File

@@ -29,7 +29,7 @@ jobs:
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels - x86_64"
uses: messense/maturin-action@v1
uses: PyO3/maturin-action@v1
with:
target: x86_64
args: --release --out dist --sdist
@@ -41,6 +41,19 @@ jobs:
with:
name: wheels
path: dist
- name: "Archive binary"
run: |
ARCHIVE_FILE=ruff-x86_64-apple-darwin.tar.gz
tar czvf $ARCHIVE_FILE -C target/x86_64-apple-darwin/release ruff
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v3
with:
name: binaries
path: |
*.tar.gz
*.sha256
macos-universal:
runs-on: macos-latest
steps:
@@ -52,7 +65,7 @@ jobs:
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels - universal2"
uses: messense/maturin-action@v1
uses: PyO3/maturin-action@v1
with:
args: --release --universal2 --out dist
- name: "Install built wheel - universal2"
@@ -63,26 +76,45 @@ jobs:
with:
name: wheels
path: dist
- name: "Archive binary"
run: |
ARCHIVE_FILE=ruff-aarch64-apple-darwin.tar.gz
tar czvf $ARCHIVE_FILE -C target/aarch64-apple-darwin/release ruff
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v3
with:
name: binaries
path: |
*.tar.gz
*.sha256
windows:
runs-on: windows-latest
strategy:
matrix:
target: [x64, x86]
platform:
- target: x86_64-pc-windows-msvc
arch: x64
- target: i686-pc-windows-msvc
arch: x86
- target: aarch64-pc-windows-msvc
arch: x64
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
architecture: ${{ matrix.target }}
architecture: ${{ matrix.platform.arch }}
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels"
uses: messense/maturin-action@v1
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
target: ${{ matrix.platform.target }}
args: --release --out dist
- name: "Install built wheel"
if: ${{ !startsWith(matrix.platform.target, 'aarch64') }}
shell: bash
run: |
python -m pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
@@ -91,12 +123,27 @@ jobs:
with:
name: wheels
path: dist
- name: "Archive binary"
shell: bash
run: |
ARCHIVE_FILE=ruff-${{ matrix.platform.target }}.zip
7z a $ARCHIVE_FILE ./target/${{ matrix.platform.target }}/release/ruff.exe
sha256sum $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v3
with:
name: binaries
path: |
*.zip
*.sha256
linux:
runs-on: ubuntu-latest
strategy:
matrix:
target: [x86_64, i686]
target:
- x86_64-unknown-linux-gnu
- i686-unknown-linux-gnu
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
@@ -106,13 +153,13 @@ jobs:
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels"
uses: messense/maturin-action@v1
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
manylinux: auto
args: --release --out dist
- name: "Install built wheel"
if: matrix.target == 'x86_64'
if: ${{ startsWith(matrix.target, 'x86_64') }}
run: |
pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
- name: "Upload wheels"
@@ -120,12 +167,34 @@ jobs:
with:
name: wheels
path: dist
- name: "Archive binary"
run: |
ARCHIVE_FILE=ruff-${{ matrix.target }}.tar.gz
tar czvf $ARCHIVE_FILE -C target/${{ matrix.target }}/release ruff
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v3
with:
name: binaries
path: |
*.tar.gz
*.sha256
linux-cross:
runs-on: ubuntu-latest
strategy:
matrix:
target: [aarch64, armv7, s390x, ppc64le, ppc64]
platform:
- target: aarch64-unknown-linux-gnu
arch: aarch64
- target: armv7-unknown-linux-gnueabihf
arch: armv7
- target: s390x-unknown-linux-gnu
arch: s390x
- target: powerpc64le-unknown-linux-gnu
arch: ppc64le
- target: powerpc64-unknown-linux-gnu
arch: ppc64
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
@@ -134,16 +203,16 @@ jobs:
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels"
uses: messense/maturin-action@v1
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
target: ${{ matrix.platform.target }}
manylinux: auto
args: --release --out dist
- uses: uraimo/run-on-arch-action@v2.5.0
if: matrix.target != 'ppc64'
- uses: uraimo/run-on-arch-action@v2
if: matrix.platform.arch != 'ppc64'
name: Install built wheel
with:
arch: ${{ matrix.target }}
arch: ${{ matrix.platform.arch }}
distro: ubuntu20.04
githubToken: ${{ github.token }}
install: |
@@ -157,6 +226,18 @@ jobs:
with:
name: wheels
path: dist
- name: "Archive binary"
run: |
ARCHIVE_FILE=ruff-${{ matrix.platform.target }}.tar.gz
tar czvf $ARCHIVE_FILE -C target/${{ matrix.platform.target }}/release ruff
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v3
with:
name: binaries
path: |
*.tar.gz
*.sha256
musllinux:
runs-on: ubuntu-latest
@@ -174,7 +255,7 @@ jobs:
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels"
uses: messense/maturin-action@v1
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.target }}
manylinux: musllinux_1_2
@@ -193,6 +274,18 @@ jobs:
with:
name: wheels
path: dist
- name: "Archive binary"
run: |
ARCHIVE_FILE=ruff-${{ matrix.target }}.tar.gz
tar czvf $ARCHIVE_FILE -C target/${{ matrix.target }}/release ruff
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v3
with:
name: binaries
path: |
*.tar.gz
*.sha256
musllinux-cross:
runs-on: ubuntu-latest
@@ -211,12 +304,12 @@ jobs:
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels"
uses: messense/maturin-action@v1
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
manylinux: musllinux_1_2
args: --release --out dist
- uses: uraimo/run-on-arch-action@master
- uses: uraimo/run-on-arch-action@v2
name: Install built wheel
with:
arch: ${{ matrix.platform.arch }}
@@ -231,42 +324,18 @@ jobs:
with:
name: wheels
path: dist
pypy:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
target: [x86_64, aarch64]
python-version:
- "3.7"
- "3.8"
- "3.9"
exclude:
- os: macos-latest
target: aarch64
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: pypy${{ matrix.python-version }}
- name: "Prep README.md"
run: python scripts/transform_readme.py --target pypi
- name: "Build wheels"
uses: messense/maturin-action@v1
with:
target: ${{ matrix.target }}
manylinux: auto
args: --release --out dist -i pypy${{ matrix.python-version }}
- name: "Install built wheel"
if: matrix.target == 'x86_64'
- name: "Archive binary"
run: |
pip install dist/${{ env.PACKAGE_NAME }}-*.whl --force-reinstall
- name: "Upload wheels"
ARCHIVE_FILE=ruff-${{ matrix.platform.target }}.tar.gz
tar czvf $ARCHIVE_FILE -C target/${{ matrix.platform.target }}/release ruff
shasum -a 256 $ARCHIVE_FILE > $ARCHIVE_FILE.sha256
- name: "Upload binary"
uses: actions/upload-artifact@v3
with:
name: wheels
path: dist
name: binaries
path: |
*.tar.gz
*.sha256
release:
name: Release
@@ -279,7 +348,6 @@ jobs:
- linux-cross
- musllinux
- musllinux-cross
- pypy
if: "startsWith(github.ref, 'refs/tags/')"
steps:
- uses: actions/download-artifact@v3
@@ -296,3 +364,11 @@ jobs:
- name: "Update pre-commit mirror"
run: |
curl -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.RUFF_PRE_COMMIT_PAT }}" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/charliermarsh/ruff-pre-commit/dispatches --data '{"event_type": "pypi_release"}'
- uses: actions/download-artifact@v3
with:
name: binaries
path: binaries
- name: Release
uses: softprops/action-gh-release@v1
with:
files: binaries/*

7
.gitignore vendored
View File

@@ -1,7 +1,6 @@
# Local cache
.ruff_cache
resources/test/cpython
docs/
crates/ruff/resources/test/cpython
mkdocs.yml
.overrides
@@ -188,3 +187,7 @@ cython_debug/
# Visual Studio Code
.vscode/
# VIM
.*.sw?
.sw?

View File

@@ -1,9 +1,18 @@
fail_fast: true
repos:
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.10.1
rev: v0.12.1
hooks:
- id: validate-pyproject
- repo: https://github.com/executablebooks/mdformat
rev: 0.7.16
hooks:
- id: mdformat
additional_dependencies:
- mdformat-black
- black==23.1.0 # Must be the latest version of Black
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.33.0
hooks:
@@ -28,11 +37,15 @@ repos:
pass_filenames: false
- id: ruff
name: ruff
entry: cargo run -- --no-cache --fix
entry: cargo run -p ruff_cli -- check --no-cache --force-exclude --fix --exit-non-zero-on-fix
language: rust
types_or: [python, pyi]
require_serial: true
exclude: ^resources
exclude: |
(?x)^(
crates/ruff/resources/.*|
crates/ruff_python_formatter/resources/.*
)$
- id: dev-generate-all
name: dev-generate-all
entry: cargo dev generate-all
@@ -40,5 +53,16 @@ repos:
pass_filenames: false
exclude: target
# Black
- repo: https://github.com/psf/black
rev: 23.1.0
hooks:
- id: black
exclude: |
(?x)^(
crates/ruff/resources/.*|
crates/ruff_python_formatter/resources/.*
)$
ci:
skip: [cargo-fmt, clippy, dev-generate-all]

View File

@@ -1,12 +1,26 @@
# Breaking Changes
## 0.0.246
### `multiple-statements-on-one-line-def` (`E704`) was removed ([#2773](https://github.com/charliermarsh/ruff/pull/2773))
This rule was introduced in v0.0.245. However, it turns out that pycodestyle and Flake8 ignore this
rule by default, as it is not part of PEP 8. As such, we've removed it from Ruff.
## 0.0.245
### Ruff's public `check` method was removed ([#2709](https://github.com/charliermarsh/ruff/pull/2709))
Previously, Ruff exposed a `check` method as a public Rust API. This method was used by few,
if any clients, and was not well documented or supported. As such, it has been removed, with
the intention of adding a stable public API in the future.
## 0.0.238
### `select`, `extend-select`, `ignore`, and `extend-ignore` have new semantics ([#2312](https://github.com/charliermarsh/ruff/pull/2312))
Previously, the interplay between `select` and its related options could lead to unexpected
behavior. For example, `ruff --select E501 --ignore ALL` and `ruff --select E501 --extend-ignore
ALL` behaved differently. (See [#2312](https://github.com/charliermarsh/ruff/pull/2312) for more
behavior. For example, `ruff --select E501 --ignore ALL` and `ruff --select E501 --extend-ignore ALL` behaved differently. (See [#2312](https://github.com/charliermarsh/ruff/pull/2312) for more
examples.)
When Ruff determines the enabled rule set, it has to reconcile `select` and `ignore` from a variety
@@ -59,7 +73,7 @@ ruff rule E402 --format json # Works! (And preferred.)
This change is largely backwards compatible -- most users should experience
no change in behavior. However, please note the following exceptions:
* Subcommands will now fail when invoked with unsupported arguments, instead
- Subcommands will now fail when invoked with unsupported arguments, instead
of silently ignoring them. For example, the following will now fail:
```console
@@ -68,16 +82,16 @@ no change in behavior. However, please note the following exceptions:
(the `clean` command doesn't support `--respect-gitignore`.)
* The semantics of `ruff <arg>` have changed slightly when `<arg>` is a valid subcommand.
- The semantics of `ruff <arg>` have changed slightly when `<arg>` is a valid subcommand.
For example, prior to this release, running `ruff rule` would run `ruff` over a file or
directory called `rule`. Now, `ruff rule` would invoke the `rule` subcommand. This should
only impact projects with files or directories named `rule`, `check`, `explain`, `clean`,
or `generate-shell-completion`.
* Scripts that invoke ruff should supply `--` before any positional arguments.
- Scripts that invoke ruff should supply `--` before any positional arguments.
(The semantics of `ruff -- <arg>` have not changed.)
* `--explain` previously treated `--format grouped` as a synonym for `--format text`.
- `--explain` previously treated `--format grouped` as a synonym for `--format text`.
This is no longer supported; instead, use `--format text`.
## 0.0.226

View File

@@ -1,5 +1,17 @@
# Contributor Covenant Code of Conduct
- [Our Pledge](#our-pledge)
- [Our Standards](#our-standards)
- [Enforcement Responsibilities](#enforcement-responsibilities)
- [Scope](#scope)
- [Enforcement](#enforcement)
- [Enforcement Guidelines](#enforcement-guidelines)
- [1. Correction](#1-correction)
- [2. Warning](#2-warning)
- [3. Temporary Ban](#3-temporary-ban)
- [4. Permanent Ban](#4-permanent-ban)
- [Attribution](#attribution)
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
@@ -17,23 +29,23 @@ diverse, inclusive, and healthy community.
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
- Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
- The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
@@ -120,7 +132,7 @@ version 2.0, available [here](https://www.contributor-covenant.org/version/2/0/c
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the [FAQ](https://www.contributor-covenant.org/faq).
Translations are available [here](https://www.contributor-covenant.org/translations).
[homepage]: https://www.contributor-covenant.org

View File

@@ -2,7 +2,18 @@
Welcome! We're happy to have you here. Thank you in advance for your contribution to Ruff.
## The basics
- [The Basics](#the-basics)
- [Prerequisites](#prerequisites)
- [Development](#development)
- [Project Structure](#project-structure)
- [Example: Adding a new lint rule](#example-adding-a-new-lint-rule)
- [Rule naming convention](#rule-naming-convention)
- [Example: Adding a new configuration option](#example-adding-a-new-configuration-option)
- [MkDocs](#mkdocs)
- [Release Process](#release-process)
- [Benchmarks](#benchmarks)
## The Basics
Ruff welcomes contributions in the form of Pull Requests.
@@ -10,7 +21,7 @@ For small changes (e.g., bug fixes), feel free to submit a PR.
For larger changes (e.g., new lint rules, new functionality, new configuration options), consider
creating an [**issue**](https://github.com/charliermarsh/ruff/issues) outlining your proposed
change. You can also join us on [**Discord**](https://discord.gg/Z8KbeK24) to discuss your idea with
change. You can also join us on [**Discord**](https://discord.gg/c9MhzV8aU5) to discuss your idea with
the community.
If you're looking for a place to start, we recommend implementing a new lint rule (see:
@@ -18,10 +29,9 @@ If you're looking for a place to start, we recommend implementing a new lint rul
pattern-match against the examples in the existing codebase. Many lint rules are inspired by
existing Python plugins, which can be used as a reference implementation.
As a concrete example: consider taking on one of the rules from the [`tryceratops`](https://github.com/charliermarsh/ruff/issues/2056)
plugin, and looking to the originating [Python source](https://github.com/guilatrova/tryceratops)
for guidance. [`flake8-simplify`](https://github.com/charliermarsh/ruff/issues/998) has a few rules
left too.
As a concrete example: consider taking on one of the rules from the [`flake8-pyi`](https://github.com/charliermarsh/ruff/issues/848)
plugin, and looking to the originating [Python source](https://github.com/PyCQA/flake8-pyi)
for guidance.
### Prerequisites
@@ -39,16 +49,16 @@ cargo install cargo-insta
After cloning the repository, run Ruff locally with:
```shell
cargo run resources/test/fixtures --no-cache
cargo run -p ruff_cli -- check /path/to/file.py --no-cache
```
Prior to opening a pull request, ensure that your code has been auto-formatted,
and that it passes both the lint and test validation checks:
```shell
cargo fmt --all # Auto-formatting...
cargo fmt # Auto-formatting...
cargo clippy --fix --workspace --all-targets --all-features # Linting...
cargo test --all # Testing...
cargo test # Testing...
```
These checks will run on GitHub Actions when you open your Pull Request, but running them locally
@@ -71,58 +81,91 @@ pre-commit run --all-files
Your Pull Request will be reviewed by a maintainer, which may involve a few rounds of iteration
prior to merging.
### Project Structure
Ruff is structured as a monorepo with a [flat crate structure](https://matklad.github.io/2021/08/22/large-rust-workspaces.html),
such that all crates are contained in a flat `crates` directory.
The vast majority of the code, including all lint rules, lives in the `ruff` crate (located at
`crates/ruff`). As a contributor, that's the crate that'll be most relevant to you.
At time of writing, the repository includes the following crates:
- `crates/ruff`: library crate containing all lint rules and the core logic for running them.
- `crates/ruff_cli`: binary crate containing Ruff's command-line interface.
- `crates/ruff_dev`: binary crate containing utilities used in the development of Ruff itself (e.g., `cargo dev generate-all`).
- `crates/ruff_macros`: library crate containing macros used by Ruff.
- `crates/ruff_python`: library crate implementing Python-specific functionality (e.g., lists of standard library modules by versionb).
- `crates/flake8_to_ruff`: binary crate for generating Ruff configuration from Flake8 configuration.
### Example: Adding a new lint rule
At a high level, the steps involved in adding a new lint rule are as follows:
1. Create a file for your rule (e.g., `src/rules/flake8_bugbear/rules/abstract_base_class.rs`).
2. In that file, define a violation struct. You can grep for `define_violation!` to see examples.
3. Map the violation struct to a rule code in `src/registry.rs` (e.g., `E402`).
4. Define the logic for triggering the violation in `src/checkers/ast.rs` (for AST-based checks),
`src/checkers/tokens.rs` (for token-based checks), `src/checkers/lines.rs` (for text-based
checks), or `src/checkers/filesystem.rs` (for filesystem-based checks).
5. Add a test fixture.
6. Update the generated files (documentation and generated code).
1. Determine a name for the new rule as per our [rule naming convention](#rule-naming-convention).
1. Create a file for your rule (e.g., `crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs`).
1. In that file, define a violation struct. You can grep for `#[violation]` to see examples.
1. Map the violation struct to a rule code in `crates/ruff/src/registry.rs` (e.g., `E402`).
1. Define the logic for triggering the violation in `crates/ruff/src/checkers/ast.rs` (for AST-based
checks), `crates/ruff/src/checkers/tokens.rs` (for token-based checks), `crates/ruff/src/checkers/lines.rs`
(for text-based checks), or `crates/ruff/src/checkers/filesystem.rs` (for filesystem-based
checks).
1. Add a test fixture.
1. Update the generated files (documentation and generated code).
To define the violation, start by creating a dedicated file for your rule under the appropriate
rule linter (e.g., `src/rules/flake8_bugbear/rules/abstract_base_class.rs`). That file should
contain a struct defined via `define_violation!`, along with a function that creates the violation
based on any required inputs. (Many of the existing examples live in `src/violations.rs`, but we're
looking to place new rules in their own files.)
rule linter (e.g., `crates/ruff/src/rules/flake8_bugbear/rules/abstract_base_class.rs`). That file should
contain a struct defined via `#[violation]`, along with a function that creates the violation
based on any required inputs. (Many of the existing examples live in `crates/ruff/src/violations.rs`,
but we're looking to place new rules in their own files.)
To trigger the violation, you'll likely want to augment the logic in `src/checkers/ast.rs`, which
defines the Python AST visitor, responsible for iterating over the abstract syntax tree and
To trigger the violation, you'll likely want to augment the logic in `crates/ruff/src/checkers/ast.rs`,
which defines the Python AST visitor, responsible for iterating over the abstract syntax tree and
collecting diagnostics as it goes.
If you need to inspect the AST, you can run `cargo dev print-ast` with a Python file. Grep
for the `Check::new` invocations to understand how other, similar rules are implemented.
To add a test fixture, create a file under `resources/test/fixtures/[linter]`, named to match
the code you defined earlier (e.g., `resources/test/fixtures/pycodestyle/E402.py`). This file should
To add a test fixture, create a file under `crates/ruff/resources/test/fixtures/[linter]`, named to match
the code you defined earlier (e.g., `crates/ruff/resources/test/fixtures/pycodestyle/E402.py`). This file should
contain a variety of violations and non-violations designed to evaluate and demonstrate the behavior
of your lint rule.
Run `cargo dev generate-all` to generate the code for your new fixture. Then run Ruff
locally with (e.g.) `cargo run resources/test/fixtures/pycodestyle/E402.py --no-cache --select E402`.
locally with (e.g.) `cargo run -p ruff_cli -- check crates/ruff/resources/test/fixtures/pycodestyle/E402.py --no-cache --select E402`.
Once you're satisfied with the output, codify the behavior as a snapshot test by adding a new
`test_case` macro in the relevant `src/[linter]/mod.rs` file. Then, run `cargo test --all`.
`test_case` macro in the relevant `crates/ruff/src/[linter]/mod.rs` file. Then, run `cargo test`.
Your test will fail, but you'll be prompted to follow-up with `cargo insta review`. Accept the
generated snapshot, then commit the snapshot file alongside the rest of your changes.
Finally, regenerate the documentation and generated code with `cargo dev generate-all`.
#### Rule naming convention
The rule name should make sense when read as "allow _rule-name_" or "allow _rule-name_ items".
This implies that rule names:
- should state the bad thing being checked for
- should not contain instructions on what you what you should use instead
(these belong in the rule documentation and the `autofix_title` for rules that have autofix)
When re-implementing rules from other linters, this convention is given more importance than
preserving the original rule name.
### Example: Adding a new configuration option
Ruff's user-facing settings live in a few different places.
First, the command-line options are defined via the `Cli` struct in `src/cli.rs`.
First, the command-line options are defined via the `Cli` struct in `crates/ruff/src/cli.rs`.
Second, the `pyproject.toml` options are defined in `src/settings/options.rs` (via the `Options`
struct), `src/settings/configuration.rs` (via the `Configuration` struct), and `src/settings/mod.rs`
(via the `Settings` struct). These represent, respectively: the schema used to parse the
`pyproject.toml` file; an internal, intermediate representation; and the final, internal
representation used to power Ruff.
Second, the `pyproject.toml` options are defined in `crates/ruff/src/settings/options.rs` (via the
`Options` struct), `crates/ruff/src/settings/configuration.rs` (via the `Configuration` struct), and
`crates/ruff/src/settings/mod.rs` (via the `Settings` struct). These represent, respectively: the
schema used to parse the `pyproject.toml` file; an internal, intermediate representation; and the
final, internal representation used to power Ruff.
To add a new configuration option, you'll likely want to modify these latter few files (along with
`cli.rs`, if appropriate). If you want to pattern-match against an existing example, grep for
@@ -130,15 +173,40 @@ To add a new configuration option, you'll likely want to modify these latter few
variables (e.g., `_`).
Note that plugin-specific configuration options are defined in their own modules (e.g.,
`src/flake8_unused_arguments/settings.rs`).
`crates/ruff/src/flake8_unused_arguments/settings.rs`).
You may also want to add the new configuration option to the `flake8-to-ruff` tool, which is
responsible for converting `flake8` configuration files to Ruff's TOML format. This logic
lives in `flake8_to_ruff/src/converter.rs`.
lives in `crates/ruff/src/flake8_to_ruff/converter.rs`.
Finally, regenerate the documentation and generated code with `cargo dev generate-all`.
## Release process
## MkDocs
To preview any changes to the documentation locally:
1. Install MkDocs and Material for MkDocs with:
```shell
pip install -r docs/requirements.txt
```
1. Generate the MkDocs site with:
```shell
python scripts/generate_mkdocs.py
```
1. Run the development server with:
```shell
mkdocs serve
```
The documentation should then be available locally at
[http://127.0.0.1:8000/docs/](http://127.0.0.1:8000/docs/).
## Release Process
As of now, Ruff has an ad hoc release process: releases are cut with high frequency via GitHub
Actions, which automatically generates the appropriate wheels across architectures and publishes
@@ -153,50 +221,50 @@ First, clone [CPython](https://github.com/python/cpython). It's a large and dive
which makes it a good target for benchmarking.
```shell
git clone --branch 3.10 https://github.com/python/cpython.git resources/test/cpython
git clone --branch 3.10 https://github.com/python/cpython.git crates/ruff/resources/test/cpython
```
To benchmark the release build:
```shell
cargo build --release && hyperfine --ignore-failure --warmup 10 \
"./target/release/ruff ./resources/test/cpython/ --no-cache" \
"./target/release/ruff ./resources/test/cpython/"
"./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache" \
"./target/release/ruff ./crates/ruff/resources/test/cpython/"
Benchmark 1: ./target/release/ruff ./resources/test/cpython/ --no-cache
Benchmark 1: ./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache
Time (mean ± σ): 293.8 ms ± 3.2 ms [User: 2384.6 ms, System: 90.3 ms]
Range (min … max): 289.9 ms … 301.6 ms 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 2: ./target/release/ruff ./resources/test/cpython/
Benchmark 2: ./target/release/ruff ./crates/ruff/resources/test/cpython/
Time (mean ± σ): 48.0 ms ± 3.1 ms [User: 65.2 ms, System: 124.7 ms]
Range (min … max): 45.0 ms … 66.7 ms 62 runs
Warning: Ignoring non-zero exit code.
Summary
'./target/release/ruff ./resources/test/cpython/' ran
6.12 ± 0.41 times faster than './target/release/ruff ./resources/test/cpython/ --no-cache'
'./target/release/ruff ./crates/ruff/resources/test/cpython/' ran
6.12 ± 0.41 times faster than './target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache'
```
To benchmark against the ecosystem's existing tools:
```shell
hyperfine --ignore-failure --warmup 5 \
"./target/release/ruff ./resources/test/cpython/ --no-cache" \
"pyflakes resources/test/cpython" \
"./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache" \
"pyflakes crates/ruff/resources/test/cpython" \
"autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython" \
"pycodestyle resources/test/cpython" \
"flake8 resources/test/cpython"
"pycodestyle crates/ruff/resources/test/cpython" \
"flake8 crates/ruff/resources/test/cpython"
Benchmark 1: ./target/release/ruff ./resources/test/cpython/ --no-cache
Benchmark 1: ./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache
Time (mean ± σ): 294.3 ms ± 3.3 ms [User: 2467.5 ms, System: 89.6 ms]
Range (min … max): 291.1 ms … 302.8 ms 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 2: pyflakes resources/test/cpython
Benchmark 2: pyflakes crates/ruff/resources/test/cpython
Time (mean ± σ): 15.786 s ± 0.143 s [User: 15.560 s, System: 0.214 s]
Range (min … max): 15.640 s … 16.157 s 10 runs
@@ -206,24 +274,24 @@ Benchmark 3: autoflake --recursive --expand-star-imports --remove-all-unused-imp
Time (mean ± σ): 6.175 s ± 0.169 s [User: 54.102 s, System: 1.057 s]
Range (min … max): 5.950 s … 6.391 s 10 runs
Benchmark 4: pycodestyle resources/test/cpython
Benchmark 4: pycodestyle crates/ruff/resources/test/cpython
Time (mean ± σ): 46.921 s ± 0.508 s [User: 46.699 s, System: 0.202 s]
Range (min … max): 46.171 s … 47.863 s 10 runs
Warning: Ignoring non-zero exit code.
Benchmark 5: flake8 resources/test/cpython
Benchmark 5: flake8 crates/ruff/resources/test/cpython
Time (mean ± σ): 12.260 s ± 0.321 s [User: 102.934 s, System: 1.230 s]
Range (min … max): 11.848 s … 12.933 s 10 runs
Warning: Ignoring non-zero exit code.
Summary
'./target/release/ruff ./resources/test/cpython/ --no-cache' ran
'./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache' ran
20.98 ± 0.62 times faster than 'autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython'
41.66 ± 1.18 times faster than 'flake8 resources/test/cpython'
53.64 ± 0.77 times faster than 'pyflakes resources/test/cpython'
159.43 ± 2.48 times faster than 'pycodestyle resources/test/cpython'
41.66 ± 1.18 times faster than 'flake8 crates/ruff/resources/test/cpython'
53.64 ± 0.77 times faster than 'pyflakes crates/ruff/resources/test/cpython'
159.43 ± 2.48 times faster than 'pycodestyle crates/ruff/resources/test/cpython'
```
You can run `poetry install` from `./scripts` to create a working environment for the above. All
@@ -256,10 +324,10 @@ rm Lib/test/bad_coding.py \
Lib/test/test_typing.py
```
Then, from `resources/test/cpython`, run: `time pylint -j 0 -E $(git ls-files '*.py')`. This
Then, from `crates/ruff/resources/test/cpython`, run: `time pylint -j 0 -E $(git ls-files '*.py')`. This
will execute Pylint with maximum parallelism and only report errors.
To benchmark Pyupgrade, run the following from `resources/test/cpython`:
To benchmark Pyupgrade, run the following from `crates/ruff/resources/test/cpython`:
```shell
hyperfine --ignore-failure --warmup 5 --prepare "git reset --hard HEAD" \

828
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,88 +1,51 @@
[workspace]
members = [
"flake8_to_ruff",
"ruff_dev",
"ruff_cli",
]
default-members = [".", "ruff_cli"]
members = ["crates/*"]
[package]
name = "ruff"
version = "0.0.241"
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
[workspace.package]
edition = "2021"
rust-version = "1.65.0"
documentation = "https://github.com/charliermarsh/ruff"
homepage = "https://github.com/charliermarsh/ruff"
rust-version = "1.67"
homepage = "https://beta.ruff.rs/docs/"
documentation = "https://beta.ruff.rs/docs/"
repository = "https://github.com/charliermarsh/ruff"
readme = "README.md"
license = "MIT"
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
[lib]
name = "ruff"
crate-type = ["cdylib", "rlib"]
doctest = false
[dependencies]
anyhow = { version = "1.0.66" }
[workspace.dependencies]
anyhow = { version = "1.0.69" }
bitflags = { version = "1.3.2" }
cfg-if = { version = "1.0.0" }
chrono = { version = "0.4.21", default-features = false, features = ["clock"] }
clap = { version = "4.0.1", features = ["derive", "env"] }
chrono = { version = "0.4.23", default-features = false, features = ["clock"] }
clap = { version = "4.1.8", features = ["derive"] }
colored = { version = "2.0.0" }
dirs = { version = "4.0.0" }
fern = { version = "0.6.1" }
glob = { version = "0.3.0" }
globset = { version = "0.4.9" }
ignore = { version = "0.4.18" }
imperative = { version = "1.0.3" }
filetime = { version = "0.2.20" }
glob = { version = "0.3.1" }
globset = { version = "0.4.10" }
ignore = { version = "0.4.20" }
insta = { version = "1.28.0" }
is-macro = { version = "0.2.2" }
itertools = { version = "0.10.5" }
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "f2f0b7a487a8725d161fe8b3ed73a6758b21e177" }
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "80e4c1399f95e5beb532fdd1e209ad2dbb470438" }
log = { version = "0.4.17" }
natord = { version = "1.0.9" }
nohash-hasher = { version = "0.2.0" }
num-bigint = { version = "0.4.3" }
num-traits = "0.2.15"
once_cell = { version = "1.16.0" }
path-absolutize = { version = "3.0.14", features = ["once_cell_cache", "use_unix_paths_on_wasm"] }
regex = { version = "1.6.0" }
ruff_macros = { version = "0.0.241", path = "ruff_macros" }
once_cell = { version = "1.17.1" }
path-absolutize = { version = "3.0.14" }
proc-macro2 = { version = "1.0.51" }
quote = { version = "1.0.23" }
regex = { version = "1.7.1" }
rustc-hash = { version = "1.1.0" }
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "adc23253e4b58980b407ba2760dbe61681d752fc" }
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "adc23253e4b58980b407ba2760dbe61681d752fc" }
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "adc23253e4b58980b407ba2760dbe61681d752fc" }
schemars = { version = "0.8.11" }
semver = { version = "1.0.16" }
serde = { version = "1.0.147", features = ["derive"] }
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "c15f670f2c30cfae6b41a1874893590148c74bc4" }
rustpython-parser = { features = [
"lalrpop",
"serde",
], git = "https://github.com/RustPython/RustPython.git", rev = "c15f670f2c30cfae6b41a1874893590148c74bc4" }
schemars = { version = "0.8.12" }
serde = { version = "1.0.152", features = ["derive"] }
serde_json = { version = "1.0.93" }
shellexpand = { version = "3.0.0" }
smallvec = { version = "1.10.0" }
similar = { version = "2.2.1" }
strum = { version = "0.24.1", features = ["strum_macros"] }
strum_macros = { version = "0.24.3" }
syn = { version = "1.0.109" }
test-case = { version = "3.0.0" }
textwrap = { version = "0.16.0" }
thiserror = { version = "1.0" }
titlecase = { version = "2.2.1" }
toml = { version = "0.6.0" }
# https://docs.rs/getrandom/0.2.7/getrandom/#webassembly-support
# For (future) wasm-pack support
[target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dependencies]
getrandom = { version = "0.2.7", features = ["js"] }
console_error_panic_hook = { version = "0.1.7" }
console_log = { version = "0.2.0" }
serde-wasm-bindgen = { version = "0.4" }
js-sys = { version = "0.3.60" }
wasm-bindgen = { version = "0.2.83" }
[target.'cfg(not(target_family = "wasm"))'.dependencies]
is_executable = "1.0.1"
[dev-dependencies]
insta = { version = "1.19.0", features = ["yaml", "redactions"] }
test-case = { version = "2.2.2" }
wasm-bindgen-test = { version = "0.3.33" }
[target.'cfg(not(target_family = "wasm"))'.dev-dependencies]
criterion = { version = "0.4.0" }
toml = { version = "0.7.2" }
[profile.release]
panic = "abort"
@@ -100,3 +63,9 @@ opt-level = 3
# https://github.com/bytecodealliance/wasm-tools/blob/b5c3d98e40590512a3b12470ef358d5c7b983b15/crates/wasmparser/src/limits.rs#L29
[profile.dev.package.rustpython-parser]
opt-level = 1
# Use the `--profile release-debug` flag to show symbols in release mode.
# e.g. `cargo build --profile release-debug`
[profile.release-debug]
inherits = "release"
debug = 1

79
LICENSE
View File

@@ -245,6 +245,31 @@ are:
SOFTWARE.
"""
- flake8-pyi, licensed as follows:
"""
The MIT License (MIT)
Copyright (c) 2016 Łukasz Langa
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
- flake8-print, licensed as follows:
"""
MIT License
@@ -1035,3 +1060,57 @@ are:
"""
Freely Distributable
"""
- flake8-django, licensed under the GPL license.
- rust-analyzer/text-size, licensed under the MIT license:
"""
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
"""
- rome/tools, licensed under the MIT license:
"""
MIT License
Copyright (c) Rome Tools, Inc. and its affiliates.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""

3748
README.md

File diff suppressed because it is too large Load Diff

7
_typos.toml Normal file
View File

@@ -0,0 +1,7 @@
[files]
extend-exclude = ["snapshots", "black"]
[default.extend-words]
trivias = "trivias"
hel = "hel"
whos = "whos"

7
clippy.toml Normal file
View File

@@ -0,0 +1,7 @@
doc-valid-idents = [
"StackOverflow",
"CodeQL",
"IPython",
"NumPy",
"..",
]

View File

@@ -0,0 +1,21 @@
[package]
name = "flake8-to-ruff"
version = "0.0.256"
edition = { workspace = true }
rust-version = { workspace = true }
[dependencies]
ruff = { path = "../ruff", default-features = false }
anyhow = { workspace = true }
clap = { workspace = true }
colored = { workspace = true }
configparser = { version = "3.0.2" }
once_cell = { workspace = true }
regex = { workspace = true }
rustc-hash = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
strum = { workspace = true }
strum_macros = { workspace = true }
toml = { workspace = true }

View File

@@ -0,0 +1,98 @@
# flake8-to-ruff
Convert existing Flake8 configuration files (`setup.cfg`, `tox.ini`, or `.flake8`) for use with
[Ruff](https://github.com/charliermarsh/ruff).
Generates a Ruff-compatible `pyproject.toml` section.
## Installation and Usage
### Installation
Available as [`flake8-to-ruff`](https://pypi.org/project/flake8-to-ruff/) on PyPI:
```shell
pip install flake8-to-ruff
```
### Usage
To run `flake8-to-ruff`:
```shell
flake8-to-ruff path/to/setup.cfg
flake8-to-ruff path/to/tox.ini
flake8-to-ruff path/to/.flake8
```
`flake8-to-ruff` will print the relevant `pyproject.toml` sections to standard output, like so:
```toml
[tool.ruff]
exclude = [
'.svn',
'CVS',
'.bzr',
'.hg',
'.git',
'__pycache__',
'.tox',
'.idea',
'.mypy_cache',
'.venv',
'node_modules',
'_state_machine.py',
'test_fstring.py',
'bad_coding2.py',
'badsyntax_*.py',
]
select = [
'A',
'E',
'F',
'Q',
]
ignore = []
[tool.ruff.flake8-quotes]
inline-quotes = 'single'
[tool.ruff.pep8-naming]
ignore-names = [
'foo',
'bar',
]
```
### Plugins
`flake8-to-ruff` will attempt to infer any activated plugins based on the settings provided in your
configuration file.
For example, if your `.flake8` file includes a `docstring-convention` property, `flake8-to-ruff`
will enable the appropriate [`flake8-docstrings`](https://pypi.org/project/flake8-docstrings/)
checks.
Alternatively, you can manually specify plugins on the command-line:
```shell
flake8-to-ruff path/to/.flake8 --plugin flake8-builtins --plugin flake8-quotes
```
## Limitations
1. Ruff only supports a subset of the Flake configuration options. `flake8-to-ruff` will warn on and
ignore unsupported options in the `.flake8` file (or equivalent). (Similarly, Ruff has a few
configuration options that don't exist in Flake8.)
1. Ruff will omit any rule codes that are unimplemented or unsupported by Ruff, including rule
codes from unsupported plugins. (See the [Ruff README](https://github.com/charliermarsh/ruff#user-content-how-does-ruff-compare-to-flake8)
for the complete list of supported plugins.)
## License
MIT
## Contributing
Contributions are welcome and hugely appreciated. To get started, check out the
[contributing guidelines](https://github.com/charliermarsh/ruff/blob/main/CONTRIBUTING.md).

View File

@@ -0,0 +1,68 @@
//! Utility to generate Ruff's `pyproject.toml` section from a Flake8 INI file.
use std::path::PathBuf;
use anyhow::Result;
use clap::Parser;
use configparser::ini::Ini;
use ruff::flake8_to_ruff::{self, ExternalConfig};
use ruff::logging::{set_up_logging, LogLevel};
#[derive(Parser)]
#[command(
about = "Convert existing Flake8 configuration to Ruff.",
long_about = None
)]
struct Args {
/// Path to the Flake8 configuration file (e.g., `setup.cfg`, `tox.ini`, or
/// `.flake8`).
#[arg(required = true)]
file: PathBuf,
/// Optional path to a `pyproject.toml` file, used to ensure compatibility
/// with Black.
#[arg(long)]
pyproject: Option<PathBuf>,
/// List of plugins to enable.
#[arg(long, value_delimiter = ',')]
plugin: Option<Vec<flake8_to_ruff::Plugin>>,
}
fn main() -> Result<()> {
set_up_logging(&LogLevel::Default)?;
let args = Args::parse();
// Read the INI file.
let mut ini = Ini::new_cs();
ini.set_multiline(true);
let config = ini.load(args.file).map_err(|msg| anyhow::anyhow!(msg))?;
// Read the pyproject.toml file.
let pyproject = args.pyproject.map(flake8_to_ruff::parse).transpose()?;
let external_config = pyproject
.as_ref()
.and_then(|pyproject| pyproject.tool.as_ref())
.map(|tool| ExternalConfig {
black: tool.black.as_ref(),
isort: tool.isort.as_ref(),
..Default::default()
})
.unwrap_or_default();
let external_config = ExternalConfig {
project: pyproject
.as_ref()
.and_then(|pyproject| pyproject.project.as_ref()),
..external_config
};
// Create Ruff's pyproject.toml section.
let pyproject = flake8_to_ruff::convert(&config, &external_config, args.plugin)?;
#[allow(clippy::print_stdout)]
{
println!("{}", toml::to_string_pretty(&pyproject)?);
}
Ok(())
}

77
crates/ruff/Cargo.toml Normal file
View File

@@ -0,0 +1,77 @@
[package]
name = "ruff"
version = "0.0.256"
authors.workspace = true
edition.workspace = true
rust-version.workspace = true
documentation.workspace = true
homepage.workspace = true
repository.workspace = true
readme = "README.md"
license = "MIT"
[lib]
name = "ruff"
[dependencies]
ruff_cache = { path = "../ruff_cache" }
ruff_diagnostics = { path = "../ruff_diagnostics", features = ["serde"] }
ruff_macros = { path = "../ruff_macros" }
ruff_python_ast = { path = "../ruff_python_ast" }
ruff_python_stdlib = { path = "../ruff_python_stdlib" }
ruff_rustpython = { path = "../ruff_rustpython" }
anyhow = { workspace = true }
bisection = { version = "0.1.0" }
bitflags = { workspace = true }
chrono = { workspace = true }
clap = { workspace = true, features = ["derive", "string"], optional = true }
colored = { workspace = true }
dirs = { version = "4.0.0" }
fern = { version = "0.6.1" }
glob = { workspace = true }
globset = { workspace = true }
ignore = { workspace = true }
imperative = { version = "1.0.4" }
is-macro = { workspace = true }
itertools = { workspace = true }
libcst = { workspace = true }
log = { workspace = true }
natord = { version = "1.0.9" }
nohash-hasher = { version = "0.2.0" }
num-bigint = { version = "0.4.3" }
num-traits = { version = "0.2.15" }
once_cell = { workspace = true }
path-absolutize = { workspace = true, features = [
"once_cell_cache",
"use_unix_paths_on_wasm",
] }
pathdiff = { version = "0.2.1" }
pep440_rs = { git = "https://github.com/konstin/pep440-rs.git", features = [
"serde",
], rev = "a8fef4ec47f4c25b070b39cdbe6a0b9847e49941" }
regex = { workspace = true }
result-like = { version = "0.4.6" }
rustc-hash = { workspace = true }
rustpython-common = { workspace = true }
rustpython-parser = { workspace = true }
schemars = { workspace = true }
semver = { version = "1.0.16" }
serde = { workspace = true }
shellexpand = { workspace = true }
smallvec = { version = "1.10.0" }
strum = { workspace = true }
strum_macros = { workspace = true }
textwrap = { workspace = true }
thiserror = { version = "1.0.38" }
toml = { workspace = true }
[dev-dependencies]
criterion = { version = "0.4.0" }
insta = { workspace = true, features = ["yaml", "redactions"] }
pretty_assertions = "1.3.0"
test-case = { workspace = true }
[features]
default = []
logical_lines = []

View File

@@ -0,0 +1,4 @@
avoid-*
do-not-*
uses-*
*-used

View File

@@ -103,3 +103,11 @@ class Foo:
@classmethod
def foo(cls, a: int, b: int) -> int:
pass
# ANN101
def foo(self, /, a: int, b: int) -> int:
pass
# OK
def f(*args: *tuple[int]) -> None: ...

View File

@@ -0,0 +1,44 @@
"""Test case expected to be run with `ignore_fully_untyped = True`."""
def ok_fully_untyped_1(a, b):
pass
def ok_fully_untyped_2():
pass
def ok_fully_typed_1(a: int, b: int) -> int:
pass
def ok_fully_typed_2() -> int:
pass
def ok_fully_typed_3(a: int, *args: str, **kwargs: str) -> int:
pass
def error_partially_typed_1(a: int, b):
pass
def error_partially_typed_2(a: int, b) -> int:
pass
def error_partially_typed_3(a: int, b: int):
pass
class X:
def ok_untyped_method_with_arg(self, a):
pass
def ok_untyped_method(self):
pass
def error_typed_self(self: X):
pass

View File

@@ -53,3 +53,8 @@ def foo():
return True
else:
return
# Error (on the argument, but not the return type)
def foo(a):
a = 2 + 2

View File

@@ -19,6 +19,8 @@ token = "s3cr3t"
secrete = "s3cr3t"
safe = password = "s3cr3t"
password = safe = "s3cr3t"
PASSWORD = "s3cr3t"
PassWord = "s3cr3t"
d["password"] = "s3cr3t"
d["pass"] = "s3cr3t"
@@ -61,3 +63,15 @@ if token == "3\t4":
if token == "5\r6":
pass
# These should not be flagged
passed_msg = "You have passed!"
compassion = "Please don't match!"
impassable = "You shall not pass!"
passwords = ""
PASSWORDS = ""
passphrases = ""
PassPhrases = ""
tokens = ""
secrets = ""

View File

@@ -0,0 +1,29 @@
try:
pass
except Exception:
continue
try:
pass
except:
continue
try:
pass
except (Exception,):
continue
try:
pass
except (Exception, ValueError):
continue
try:
pass
except ValueError:
continue
try:
pass
except (ValueError,):
continue

View File

@@ -0,0 +1,95 @@
# single-line failures
query1 = "SELECT %s FROM table" % (var,) # bad
query2 = "SELECT var FROM " + table
query3 = "SELECT " + val + " FROM " + table
query4 = "SELECT {} FROM table;".format(var)
query5 = f"SELECT * FROM table WHERE var = {var}"
query6 = "DELETE FROM table WHERE var = %s" % (var,)
query7 = "DELETE FROM table WHERE VAR = " + var
query8 = "DELETE FROM " + table + "WHERE var = " + var
query9 = "DELETE FROM table WHERE var = {}".format(var)
query10 = f"DELETE FROM table WHERE var = {var}"
query11 = "INSERT INTO table VALUES (%s)" % (var,)
query12 = "INSERT INTO TABLE VALUES (" + var + ")"
query13 = "INSERT INTO {} VALUES ({})".format(table, var)
query14 = f"INSERT INTO {table} VALUES var = {var}"
query15 = "UPDATE %s SET var = %s" % (table, var)
query16 = "UPDATE " + table + " SET var = " + var
query17 = "UPDATE {} SET var = {}".format(table, var)
query18 = f"UPDATE {table} SET var = {var}"
query19 = "select %s from table" % (var,)
query20 = "select var from " + table
query21 = "select " + val + " from " + table
query22 = "select {} from table;".format(var)
query23 = f"select * from table where var = {var}"
query24 = "delete from table where var = %s" % (var,)
query25 = "delete from table where var = " + var
query26 = "delete from " + table + "where var = " + var
query27 = "delete from table where var = {}".format(var)
query28 = f"delete from table where var = {var}"
query29 = "insert into table values (%s)" % (var,)
query30 = "insert into table values (" + var + ")"
query31 = "insert into {} values ({})".format(table, var)
query32 = f"insert into {table} values var = {var}"
query33 = "update %s set var = %s" % (table, var)
query34 = "update " + table + " set var = " + var
query35 = "update {} set var = {}".format(table, var)
query36 = f"update {table} set var = {var}"
# multi-line failures
def query37():
return """
SELECT *
FROM table
WHERE var = %s
""" % var
def query38():
return """
SELECT *
FROM TABLE
WHERE var =
""" + var
def query39():
return """
SELECT *
FROM table
WHERE var = {}
""".format(var)
def query40():
return f"""
SELECT *
FROM table
WHERE var = {var}
"""
def query41():
return (
"SELECT *"
"FROM table"
f"WHERE var = {var}"
)
# # cursor-wrapped failures
query42 = cursor.execute("SELECT * FROM table WHERE var = %s" % var)
query43 = cursor.execute(f"SELECT * FROM table WHERE var = {var}")
query44 = cursor.execute("SELECT * FROM table WHERE var = {}".format(var))
query45 = cursor.executemany("SELECT * FROM table WHERE var = %s" % var, [])
# # pass
query = "SELECT * FROM table WHERE id = 1"
query = "DELETE FROM table WHERE id = 1"
query = "INSERT INTO table VALUES (1)"
query = "UPDATE table SET id = 1"
cursor.execute('SELECT * FROM table WHERE id = %s', var)
cursor.execute('SELECT * FROM table WHERE id = 1')
cursor.executemany('SELECT * FROM table WHERE id = %s', [var, var2])

View File

@@ -0,0 +1,82 @@
def function(
posonly_nohint,
posonly_nonboolhint: int,
posonly_boolhint: bool,
posonly_boolstrhint: "bool",
/,
offset,
posorkw_nonvalued_nohint,
posorkw_nonvalued_nonboolhint: int,
posorkw_nonvalued_boolhint: bool,
posorkw_nonvalued_boolstrhint: "bool",
posorkw_boolvalued_nohint=True,
posorkw_boolvalued_nonboolhint: int = True,
posorkw_boolvalued_boolhint: bool = True,
posorkw_boolvalued_boolstrhint: "bool" = True,
posorkw_nonboolvalued_nohint=1,
posorkw_nonboolvalued_nonboolhint: int = 2,
posorkw_nonboolvalued_boolhint: bool = 3,
posorkw_nonboolvalued_boolstrhint: "bool" = 4,
*,
kwonly_nonvalued_nohint,
kwonly_nonvalued_nonboolhint: int,
kwonly_nonvalued_boolhint: bool,
kwonly_nonvalued_boolstrhint: "bool",
kwonly_boolvalued_nohint=True,
kwonly_boolvalued_nonboolhint: int = False,
kwonly_boolvalued_boolhint: bool = True,
kwonly_boolvalued_boolstrhint: "bool" = True,
kwonly_nonboolvalued_nohint=5,
kwonly_nonboolvalued_nonboolhint: int = 1,
kwonly_nonboolvalued_boolhint: bool = 1,
kwonly_nonboolvalued_boolstrhint: "bool" = 1,
**kw,
):
...
def used(do):
return do
used("a", True)
used(do=True)
# Avoid FBT003 for explicitly allowed methods.
"""
FBT003 Boolean positional value on dict
"""
a = {"a": "b"}
a.get("hello", False)
{}.get("hello", False)
{}.setdefault("hello", True)
{}.pop("hello", False)
{}.pop(True, False)
dict.fromkeys(("world",), True)
{}.deploy(True, False)
getattr(someobj, attrname, False)
mylist.index(True)
int(True)
str(int(False))
cfg.get("hello", True)
cfg.getint("hello", True)
cfg.getfloat("hello", True)
cfg.getboolean("hello", True)
class Registry:
def __init__(self) -> None:
self._switches = [False] * len(Switch)
# FBT001: Boolean positional arg in function definition
def __setitem__(self, switch: Switch, value: bool) -> None:
self._switches[switch.value] = value
@foo.setter
def foo(self, value: bool) -> None:
pass
# FBT001: Boolean positional arg in function definition
def foo(self, value: bool) -> None:
pass

View File

@@ -17,6 +17,11 @@ s.rstrip(".facebook.com") # warning
s.rstrip("e") # no warning
s.rstrip("\n\t ") # no warning
s.rstrip(r"\n\t ") # warning
s.strip("a") # no warning
s.strip("") # no warning
s.strip("ああ") # warning
s.strip("\ufeff") # no warning
s.strip("\u0074\u0065\u0073\u0074") # warning
from somewhere import other_type, strip

View File

@@ -80,3 +80,9 @@ def f():
bar = 1
print(bar)
# Unfixable due to trailing underscore (`_line_` wouldn't be considered an ignorable
# variable name).
for line_ in range(self.header_lines):
fp.readline()

View File

@@ -105,3 +105,25 @@ while True:
pass
finally:
break # warning
while True:
try:
pass
finally:
match *0, 1, *2:
case 0,:
y = 0
case 0, *x:
break # warning
while True:
try:
pass
finally:
match *0, 1, *2:
case 0,:
y = 0
case 0, *x:
pass # no warning

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