Compare commits
760 Commits
nextest
...
confusable
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
292bf7fd15 | ||
|
|
25bccf0555 | ||
|
|
e8879d5eda | ||
|
|
f16505d885 | ||
|
|
d04d964ace | ||
|
|
f64c389654 | ||
|
|
2ff1afb15c | ||
|
|
7fa6ac976a | ||
|
|
7dd5137913 | ||
|
|
0d93fbb4a2 | ||
|
|
d350ede992 | ||
|
|
a8a72306f0 | ||
|
|
c8122563a6 | ||
|
|
f8f507cfc8 | ||
|
|
ab6bf50a2d | ||
|
|
df4dc040de | ||
|
|
3a889f4686 | ||
|
|
edc75dc5d6 | ||
|
|
ebad36da06 | ||
|
|
2f7e2a8de3 | ||
|
|
4d23c1fc83 | ||
|
|
29573daef5 | ||
|
|
9558bac64a | ||
|
|
d5abe55b03 | ||
|
|
3fc920cd12 | ||
|
|
e9acb99f7d | ||
|
|
1642f4dbd9 | ||
|
|
38358980f1 | ||
|
|
43691f97d0 | ||
|
|
3076d76b0a | ||
|
|
23ed4e9616 | ||
|
|
97ae617fac | ||
|
|
a8d04cbd88 | ||
|
|
230c93459f | ||
|
|
8977b6ae11 | ||
|
|
982ae6ff08 | ||
|
|
c674db6e51 | ||
|
|
7323c12eee | ||
|
|
161c093c06 | ||
|
|
daea870c3c | ||
|
|
b6c4074836 | ||
|
|
cf74debf42 | ||
|
|
f483ed4240 | ||
|
|
98b3d716c6 | ||
|
|
03df6fa105 | ||
|
|
8cc97f70b4 | ||
|
|
951c59c6ad | ||
|
|
d177df226d | ||
|
|
703e2a9da3 | ||
|
|
bdad5e9a5f | ||
|
|
b21eb1f689 | ||
|
|
b0dc5a86a1 | ||
|
|
b5a4a9a356 | ||
|
|
230c9ce236 | ||
|
|
78bbf6d403 | ||
|
|
ee7d445ef5 | ||
|
|
5776ec1079 | ||
|
|
1f2d4f3ee1 | ||
|
|
221f7cd932 | ||
|
|
c7aa816f17 | ||
|
|
3ccca332bd | ||
|
|
2c84f911c4 | ||
|
|
e799f90782 | ||
|
|
9b89bf7d8a | ||
|
|
d7b966d6cd | ||
|
|
44e21cfada | ||
|
|
cda1c5dd35 | ||
|
|
86cdaea743 | ||
|
|
af4cb34ce2 | ||
|
|
4afff436ff | ||
|
|
f2f2e759c7 | ||
|
|
317b6e8682 | ||
|
|
2f5734d1ac | ||
|
|
c39ea6ef05 | ||
|
|
10a50bf1e2 | ||
|
|
a151e50ad3 | ||
|
|
854f5d09fa | ||
|
|
c2f6c79b3d | ||
|
|
87772c2884 | ||
|
|
aa90a425e0 | ||
|
|
81a2e74fe2 | ||
|
|
3af890f32f | ||
|
|
223873c8c7 | ||
|
|
7b4b004506 | ||
|
|
9f5102d536 | ||
|
|
af95cbaeef | ||
|
|
fc94857a20 | ||
|
|
5f26411577 | ||
|
|
40c886c3bc | ||
|
|
097e703071 | ||
|
|
cd8e1bad64 | ||
|
|
e2b5c6ac5f | ||
|
|
c36efe254e | ||
|
|
3e7b92991b | ||
|
|
25d4ddaa60 | ||
|
|
63a5a12a41 | ||
|
|
c32f943d86 | ||
|
|
d211074f59 | ||
|
|
4ffd4ed61f | ||
|
|
a4dd1e5fad | ||
|
|
be3307e9a6 | ||
|
|
317d3dd612 | ||
|
|
f5e850745c | ||
|
|
a7d1f7e1ec | ||
|
|
88c8b47326 | ||
|
|
133a745de1 | ||
|
|
6983d96d27 | ||
|
|
3c3d9ab173 | ||
|
|
ff9fb0da54 | ||
|
|
9792b1551b | ||
|
|
d1c67f91bd | ||
|
|
dbd84c947b | ||
|
|
c2ec5f0bc9 | ||
|
|
31032f4f70 | ||
|
|
f55b724254 | ||
|
|
fd07a12a52 | ||
|
|
1ee73bdedf | ||
|
|
23b55aea30 | ||
|
|
e36afc3324 | ||
|
|
8304c41714 | ||
|
|
6f31e9c00e | ||
|
|
a6cc56fd98 | ||
|
|
0236e0751c | ||
|
|
2d0769e324 | ||
|
|
80473c3f5c | ||
|
|
4d7f90e045 | ||
|
|
75bd95e58c | ||
|
|
3bbdfee69f | ||
|
|
3127c79b29 | ||
|
|
c91cc29d6d | ||
|
|
8b665f40c8 | ||
|
|
84979f9673 | ||
|
|
c3dabc1933 | ||
|
|
2e81b9c391 | ||
|
|
9feb86caa4 | ||
|
|
2587aef1ea | ||
|
|
7f4ea6690d | ||
|
|
2f32a57cf4 | ||
|
|
802616aac0 | ||
|
|
7100e12cc3 | ||
|
|
5a95b25aa8 | ||
|
|
833814384a | ||
|
|
39e45aa06f | ||
|
|
92baa3591d | ||
|
|
0e96482085 | ||
|
|
b9bff6f5d1 | ||
|
|
2401e91ab9 | ||
|
|
6199590072 | ||
|
|
08519e22e4 | ||
|
|
c704674190 | ||
|
|
2db96067aa | ||
|
|
8cd09c88d3 | ||
|
|
ce9bd19885 | ||
|
|
764304faf1 | ||
|
|
6fc35dd075 | ||
|
|
c0710a1dd4 | ||
|
|
2c2ebf952a | ||
|
|
d6a4283003 | ||
|
|
95702e408f | ||
|
|
bcaac9693b | ||
|
|
d6f59e4131 | ||
|
|
66e6388776 | ||
|
|
8472a7e50f | ||
|
|
7586091437 | ||
|
|
4e07a65c15 | ||
|
|
00fd324c6f | ||
|
|
2414f23abb | ||
|
|
e0f9dbcd10 | ||
|
|
6ddb0fa950 | ||
|
|
df807ff912 | ||
|
|
f6d6200aae | ||
|
|
fa556d1c74 | ||
|
|
860ffb9549 | ||
|
|
90ebea86a4 | ||
|
|
7a5f98835a | ||
|
|
348b649b5c | ||
|
|
ae41d6f30a | ||
|
|
b1072049bf | ||
|
|
bc49492085 | ||
|
|
c8464c3a90 | ||
|
|
f158536fbb | ||
|
|
1dd264b019 | ||
|
|
a525f09008 | ||
|
|
256b98ab9a | ||
|
|
962472da96 | ||
|
|
a00c445580 | ||
|
|
0e58433715 | ||
|
|
22cf451d51 | ||
|
|
ec1be60dcb | ||
|
|
a327b4da87 | ||
|
|
cdc5e2fb58 | ||
|
|
b5d3caf033 | ||
|
|
8f9753f58e | ||
|
|
67b043482a | ||
|
|
693f957b90 | ||
|
|
a85ed309ea | ||
|
|
2e225d7538 | ||
|
|
4786abac7a | ||
|
|
46d5db56cc | ||
|
|
2729c4cacd | ||
|
|
b2d1fcf7b2 | ||
|
|
78d172aad7 | ||
|
|
13d6c8237a | ||
|
|
51aa73f405 | ||
|
|
0c3123e07e | ||
|
|
dda4ceda71 | ||
|
|
195c000f5a | ||
|
|
a62c735f9e | ||
|
|
94b4bb0f57 | ||
|
|
fe485d791c | ||
|
|
d685107638 | ||
|
|
d85950ce5a | ||
|
|
88c0106421 | ||
|
|
f60aa85471 | ||
|
|
d942a777d7 | ||
|
|
8a529925b3 | ||
|
|
dc6b4ad2b4 | ||
|
|
21ea290d6a | ||
|
|
5da0f9111e | ||
|
|
cb6d74c27b | ||
|
|
73049df3ed | ||
|
|
bf0e5788ef | ||
|
|
4113d65836 | ||
|
|
4c2c9bf7e0 | ||
|
|
172ac2c9a2 | ||
|
|
cac9754455 | ||
|
|
134def0119 | ||
|
|
1fabaca5de | ||
|
|
523f542dbd | ||
|
|
ee7575eb5a | ||
|
|
84f7391cc5 | ||
|
|
7da4e28a98 | ||
|
|
5718df638f | ||
|
|
4bb4cd3b37 | ||
|
|
620426de7a | ||
|
|
84ec66a22c | ||
|
|
e58ffa9a7a | ||
|
|
aa6846c78c | ||
|
|
3d03e75a9d | ||
|
|
b6e75e58c9 | ||
|
|
8061894af6 | ||
|
|
e261eb7461 | ||
|
|
bd06cbe0c5 | ||
|
|
ddffadb4b0 | ||
|
|
8255e4ed6c | ||
|
|
60ca6885b1 | ||
|
|
889117ea87 | ||
|
|
c03a693ebc | ||
|
|
6f9c317aa5 | ||
|
|
66179af4f1 | ||
|
|
1e184e69f3 | ||
|
|
f08a5f67eb | ||
|
|
cd564c4200 | ||
|
|
c1fdb9c46d | ||
|
|
48b256bd94 | ||
|
|
3944c42d4c | ||
|
|
cb06b7956c | ||
|
|
4454fbf7e5 | ||
|
|
b243840e4b | ||
|
|
23bbe7336a | ||
|
|
a71c4dfabb | ||
|
|
81275d12e9 | ||
|
|
40cad44f4a | ||
|
|
c38617fa27 | ||
|
|
1835d7bb45 | ||
|
|
f670f9b22c | ||
|
|
7a072cc2ea | ||
|
|
8c4b5d3c90 | ||
|
|
ec9d5cddd6 | ||
|
|
0f759af3cf | ||
|
|
644011fb14 | ||
|
|
a1ee6d28ce | ||
|
|
826868da5b | ||
|
|
5986ff748a | ||
|
|
739a8aa10e | ||
|
|
090c1a4a19 | ||
|
|
2b95d3832b | ||
|
|
d412e8ef74 | ||
|
|
46e45bdf19 | ||
|
|
a3e8e77172 | ||
|
|
ec7395ba69 | ||
|
|
d8c0360fc7 | ||
|
|
097b654ba7 | ||
|
|
d54cabd276 | ||
|
|
7faa43108f | ||
|
|
74b00c9b91 | ||
|
|
97e944003b | ||
|
|
016e16254a | ||
|
|
61a41334a3 | ||
|
|
74971617a1 | ||
|
|
5c68c89566 | ||
|
|
8923eb19e0 | ||
|
|
dad70fff99 | ||
|
|
b72c94b3d1 | ||
|
|
b4b296dca3 | ||
|
|
43883b7a15 | ||
|
|
38f512d588 | ||
|
|
2d6557a51b | ||
|
|
2ba5677700 | ||
|
|
62f1ee08e7 | ||
|
|
bdd925c0f2 | ||
|
|
dd36a2516e | ||
|
|
b6c9cf1c5b | ||
|
|
805fd1bc93 | ||
|
|
0fc76ba276 | ||
|
|
4b537d1297 | ||
|
|
3c25d261fe | ||
|
|
4f95df1b6d | ||
|
|
22e18741bd | ||
|
|
e8d2cbc3f6 | ||
|
|
1dd5deb53d | ||
|
|
b64f403dc2 | ||
|
|
7dc9887ab9 | ||
|
|
709abd534a | ||
|
|
27def479bd | ||
|
|
1eac457c1b | ||
|
|
609a78b13e | ||
|
|
17fba99ed4 | ||
|
|
adb6580270 | ||
|
|
76fcf63052 | ||
|
|
90de108bfa | ||
|
|
ad265fa6bc | ||
|
|
59c00b5298 | ||
|
|
a0c846f9bd | ||
|
|
bb87f75b0c | ||
|
|
e674e87d1b | ||
|
|
600471e45f | ||
|
|
a1509dfc7c | ||
|
|
7b4fb4fb5d | ||
|
|
5d49d268a0 | ||
|
|
f71c80af68 | ||
|
|
90c259beb9 | ||
|
|
37d21c0d54 | ||
|
|
69b8136463 | ||
|
|
c040fac12f | ||
|
|
a6ebbf21c3 | ||
|
|
e129f77bcf | ||
|
|
3ccd1d580d | ||
|
|
f872c3bf0f | ||
|
|
55fa887099 | ||
|
|
c6d0bdd572 | ||
|
|
75f759ed55 | ||
|
|
6b99f5e3e6 | ||
|
|
97c092a102 | ||
|
|
bdf285225d | ||
|
|
0961f008b8 | ||
|
|
ebdfcee87f | ||
|
|
c71ff7eae1 | ||
|
|
0df27375ba | ||
|
|
c82d0503a8 | ||
|
|
7d7e0824af | ||
|
|
8d1d5b8d80 | ||
|
|
9ba5bc26f6 | ||
|
|
13748dd27c | ||
|
|
f70e8a7524 | ||
|
|
1df8101b9e | ||
|
|
6a4437ea81 | ||
|
|
4d2de898e3 | ||
|
|
d8a6279fe5 | ||
|
|
2838f7af98 | ||
|
|
1cf3b5676f | ||
|
|
e91ffe3e93 | ||
|
|
e72d617f4b | ||
|
|
488ec54d21 | ||
|
|
c782770e90 | ||
|
|
1646939383 | ||
|
|
b519b56e81 | ||
|
|
8c8988ea40 | ||
|
|
e9f8b91eb5 | ||
|
|
b5280061f8 | ||
|
|
b42a8972bf | ||
|
|
bb65fb8486 | ||
|
|
253fbb665f | ||
|
|
974262ad2c | ||
|
|
dc51d03866 | ||
|
|
614a19cb4e | ||
|
|
e2ec42539b | ||
|
|
e62e245c61 | ||
|
|
78b8741352 | ||
|
|
246d93ec37 | ||
|
|
3347524164 | ||
|
|
598974545b | ||
|
|
c2a9cf8ae5 | ||
|
|
cfbebcf354 | ||
|
|
5e75467757 | ||
|
|
9611f8134f | ||
|
|
f45281345d | ||
|
|
316f75987d | ||
|
|
695dbbc539 | ||
|
|
f62b4c801f | ||
|
|
46b85ab0a9 | ||
|
|
1c02fcd7ce | ||
|
|
f53c410ff8 | ||
|
|
1e173f7909 | ||
|
|
8028de8956 | ||
|
|
a6d79c03b3 | ||
|
|
58b50a6290 | ||
|
|
c8360a1333 | ||
|
|
34480c0e4d | ||
|
|
70ab4b8b59 | ||
|
|
e863fa55cb | ||
|
|
0c65d0c8a6 | ||
|
|
15f3d8c8e0 | ||
|
|
0a8cad2550 | ||
|
|
fbbc982c29 | ||
|
|
2aef46cb6f | ||
|
|
528f386131 | ||
|
|
ee533332ed | ||
|
|
8165925e01 | ||
|
|
0a737843b5 | ||
|
|
4d16e2308d | ||
|
|
2cb5e43dd7 | ||
|
|
26f9b4a8e6 | ||
|
|
93b5d8a0fb | ||
|
|
65aebf127a | ||
|
|
17ceb5dcb3 | ||
|
|
8ce138760a | ||
|
|
10e35e38d7 | ||
|
|
f169cb5d92 | ||
|
|
39ddad7454 | ||
|
|
f32b0eef9c | ||
|
|
15813a65f3 | ||
|
|
604cf521b5 | ||
|
|
865c89800e | ||
|
|
1a22eae98c | ||
|
|
8ba8896a7f | ||
|
|
b194f59aab | ||
|
|
e41b08f1d0 | ||
|
|
1a4f2a9baf | ||
|
|
19010f276e | ||
|
|
5174e8c926 | ||
|
|
8bfe9bda41 | ||
|
|
01843af21a | ||
|
|
2ecf59726f | ||
|
|
f137819536 | ||
|
|
9d16e46129 | ||
|
|
82978ac9b5 | ||
|
|
814403cdf7 | ||
|
|
f254aaa847 | ||
|
|
a51b0b02f0 | ||
|
|
74dbd871f8 | ||
|
|
d7508af48d | ||
|
|
c3774e1255 | ||
|
|
887455c498 | ||
|
|
4d6f5ff0a7 | ||
|
|
6c3378edb1 | ||
|
|
7f1456a2c9 | ||
|
|
2759db6604 | ||
|
|
124d95d246 | ||
|
|
ab643017f9 | ||
|
|
6eb9a9a633 | ||
|
|
288c07d911 | ||
|
|
f8f1cd5016 | ||
|
|
87a0cd219f | ||
|
|
b685ee4749 | ||
|
|
ad893f8295 | ||
|
|
621bed55c0 | ||
|
|
86faee1522 | ||
|
|
a0917ec658 | ||
|
|
ee9ee005c5 | ||
|
|
5df0326bc8 | ||
|
|
6540321966 | ||
|
|
b34278e0cd | ||
|
|
222f1c37b8 | ||
|
|
8f41eab0c7 | ||
|
|
83daddbeb7 | ||
|
|
b19eec9b2a | ||
|
|
ca3c15858d | ||
|
|
bb4f7c681a | ||
|
|
0a167dd20b | ||
|
|
c43542896f | ||
|
|
192463c2fb | ||
|
|
5849a75223 | ||
|
|
dcbd8eacd8 | ||
|
|
297ec2c2d2 | ||
|
|
511cc25fc4 | ||
|
|
4c4eceee36 | ||
|
|
e07670ad97 | ||
|
|
b792140579 | ||
|
|
36a60bd50e | ||
|
|
4ae463d04b | ||
|
|
6dade5b9ab | ||
|
|
97510c888b | ||
|
|
94b68f201b | ||
|
|
ef34c5cbec | ||
|
|
fdbefd777c | ||
|
|
078547adbb | ||
|
|
42a0bec146 | ||
|
|
37b7d0f921 | ||
|
|
6a4dbd622b | ||
|
|
28b48ab902 | ||
|
|
4123d074bd | ||
|
|
c6ba7dfbc6 | ||
|
|
40f6456add | ||
|
|
3e1dffab20 | ||
|
|
3336d23f48 | ||
|
|
2421805033 | ||
|
|
359f50e6dc | ||
|
|
bccba5d73f | ||
|
|
0bfdb15ecf | ||
|
|
a902d14c31 | ||
|
|
728539291f | ||
|
|
c2bd8af59a | ||
|
|
c946bf157e | ||
|
|
8ab2519717 | ||
|
|
c4d85d6fb6 | ||
|
|
70ea49bf72 | ||
|
|
8e255974bc | ||
|
|
d358604464 | ||
|
|
8243db74fe | ||
|
|
0346e781d4 | ||
|
|
b66bfa6570 | ||
|
|
28273eb00b | ||
|
|
12acd191e1 | ||
|
|
64b929bc29 | ||
|
|
26ae0a6e8d | ||
|
|
959338d39d | ||
|
|
422ff82f4a | ||
|
|
8d0a5e01bd | ||
|
|
aae02cf275 | ||
|
|
7e2eba2592 | ||
|
|
22770fb4be | ||
|
|
1880cceac1 | ||
|
|
0d1fb823d6 | ||
|
|
c907317199 | ||
|
|
916dd5b7fa | ||
|
|
2cbe1733c8 | ||
|
|
1f6e1485f9 | ||
|
|
9b43162cc4 | ||
|
|
cc9e84c144 | ||
|
|
f4d50a2aec | ||
|
|
0c030b5bf3 | ||
|
|
1b082ce67e | ||
|
|
f936d319cc | ||
|
|
85d8b6228f | ||
|
|
7594dadc1d | ||
|
|
de37fbfac9 | ||
|
|
4e2769a16c | ||
|
|
75b5c314e3 | ||
|
|
450fb9b99a | ||
|
|
6163c99551 | ||
|
|
3112202a5b | ||
|
|
64ea00048b | ||
|
|
067a4acd54 | ||
|
|
c88376f468 | ||
|
|
9b7c29853d | ||
|
|
3e21d32b79 | ||
|
|
f9e3ea23ba | ||
|
|
6856d0b44b | ||
|
|
21539f1663 | ||
|
|
b9bb6bf780 | ||
|
|
d39eae2713 | ||
|
|
5d21b9c22e | ||
|
|
ec2f229a45 | ||
|
|
34c1cb7d11 | ||
|
|
2ddea7c657 | ||
|
|
45eabdd2c3 | ||
|
|
675c86c175 | ||
|
|
1f8e2b8f14 | ||
|
|
58b3040342 | ||
|
|
6a9b8aede1 | ||
|
|
f48126ad00 | ||
|
|
11287f944f | ||
|
|
a65efcf459 | ||
|
|
04183b0299 | ||
|
|
36fa1fe359 | ||
|
|
6e625bd93d | ||
|
|
ebd1b296fd | ||
|
|
1373e1c395 | ||
|
|
4bff397318 | ||
|
|
5347df4728 | ||
|
|
ebe9c03545 | ||
|
|
b0cbcd3dfa | ||
|
|
4df9e07a79 | ||
|
|
f0f7ea7502 | ||
|
|
4f26002dd5 | ||
|
|
d1a9c198e3 | ||
|
|
7a4f699fba | ||
|
|
3fb5418c2c | ||
|
|
9fcc009a0c | ||
|
|
bf8e5a167b | ||
|
|
8a001dfc3d | ||
|
|
0823394525 | ||
|
|
e15047815c | ||
|
|
7531bb3b21 | ||
|
|
2d9b39871f | ||
|
|
e122a96d27 | ||
|
|
f4c7bff36b | ||
|
|
56440ad835 | ||
|
|
179128dc54 | ||
|
|
e7a2779402 | ||
|
|
008da95b29 | ||
|
|
5d4dd3e38e | ||
|
|
e561f5783b | ||
|
|
ee0f1270cf | ||
|
|
e7b7e4a18d | ||
|
|
b4419c34ea | ||
|
|
08f19226b9 | ||
|
|
1e6df19a35 | ||
|
|
c21b960fc7 | ||
|
|
73ad2affa1 | ||
|
|
40c936922e | ||
|
|
874db4fb86 | ||
|
|
a41bb2733f | ||
|
|
24b848a4ea | ||
|
|
773ba5f816 | ||
|
|
f5701fcc63 | ||
|
|
ff0feb191c | ||
|
|
6566d00295 | ||
|
|
7c9bbcf4e2 | ||
|
|
babf8d718e | ||
|
|
878813f277 | ||
|
|
71c8a02ebd | ||
|
|
3a2c3a7398 | ||
|
|
7440e54ec6 | ||
|
|
0357e801ed | ||
|
|
69d0caabe7 | ||
|
|
9cb5ce750e | ||
|
|
0a07a2ca62 | ||
|
|
47a253fb62 | ||
|
|
d9544a2d37 | ||
|
|
41f0aad7b3 | ||
|
|
05951dd338 | ||
|
|
c260762900 | ||
|
|
1d5c4b0a14 | ||
|
|
a352f2f092 | ||
|
|
e376c3ff7e | ||
|
|
9671922e40 | ||
|
|
45f9fca228 | ||
|
|
6661be2c30 | ||
|
|
97f945651d | ||
|
|
5cea43731e | ||
|
|
7971e0b0ee | ||
|
|
842ff0212e | ||
|
|
f1a4eb9c28 | ||
|
|
041cdb95e0 | ||
|
|
fda48afc23 | ||
|
|
c1af1c291d | ||
|
|
171b66cb43 | ||
|
|
fa0b6f4813 | ||
|
|
eab85aea1a | ||
|
|
5b31524920 | ||
|
|
6d0469638c | ||
|
|
29ba2bb943 | ||
|
|
f0ea40a68d | ||
|
|
a3a531e0d4 | ||
|
|
b3e8eca871 | ||
|
|
447b7cb0e2 | ||
|
|
e3114a144c | ||
|
|
2e58ad437e | ||
|
|
04f2842e4f | ||
|
|
31990b8d3f | ||
|
|
5f59101811 | ||
|
|
fa6bff0078 | ||
|
|
ea7c394817 | ||
|
|
264d9159f8 | ||
|
|
37dfb205b1 | ||
|
|
f8e4e1d562 | ||
|
|
89be850b73 | ||
|
|
d68041ba24 | ||
|
|
b60b37e866 | ||
|
|
5a95edab45 | ||
|
|
1adde24133 | ||
|
|
e02d76f070 | ||
|
|
7ead2c17b1 | ||
|
|
e428099e4c | ||
|
|
7a83fd9926 | ||
|
|
e8f78fa2cf | ||
|
|
955501f267 | ||
|
|
175b3702c3 | ||
|
|
40ee4909b5 | ||
|
|
10a8e4a225 | ||
|
|
0465b03282 | ||
|
|
154fe7bdcc | ||
|
|
ece30e7c69 | ||
|
|
7be28a38c5 | ||
|
|
5ec73a6137 | ||
|
|
1067261a55 | ||
|
|
93ca8ebbc0 | ||
|
|
834566f34f | ||
|
|
a56121672c | ||
|
|
32f4a96c64 | ||
|
|
c004e03395 | ||
|
|
b57ddd54d2 | ||
|
|
af189db5eb | ||
|
|
c7217e34d7 | ||
|
|
d70247959c | ||
|
|
911d4f2918 | ||
|
|
d9cf31f355 | ||
|
|
7da99cc756 | ||
|
|
9c3b2c3c3c | ||
|
|
37d244d178 | ||
|
|
dbb34804a4 | ||
|
|
3c7486817b | ||
|
|
3c3c5b5c57 | ||
|
|
b0d171ac19 | ||
|
|
b70dde4a77 | ||
|
|
4eaa412370 | ||
|
|
577280c8be | ||
|
|
45680bbb44 | ||
|
|
71ff6f911d | ||
|
|
c05e4628b1 | ||
|
|
2f3a950f6f | ||
|
|
dea65536e9 | ||
|
|
fbc9b5a604 | ||
|
|
253a241f5d | ||
|
|
33806b8b7c | ||
|
|
afcd00da56 | ||
|
|
08e246764f | ||
|
|
0489bbc54c | ||
|
|
60132da7bb | ||
|
|
17a44c0078 | ||
|
|
376d3caf47 | ||
|
|
51d69b448c | ||
|
|
f7dca3d958 | ||
|
|
7c1aa98f43 | ||
|
|
68f605e80a | ||
|
|
96a9717c1a | ||
|
|
f4ba0ea144 | ||
|
|
92143afeee | ||
|
|
eb552da8a9 | ||
|
|
e2b2b1759f | ||
|
|
a3f4d7745a | ||
|
|
edfd888bd6 | ||
|
|
9c382e8291 | ||
|
|
eb2b226142 | ||
|
|
31947af6a3 | ||
|
|
b404e54f33 | ||
|
|
34e8de738e | ||
|
|
1550a6bfe7 | ||
|
|
dc4db39f78 | ||
|
|
f3aaf84a28 | ||
|
|
5de95d7054 | ||
|
|
8d1610d960 | ||
|
|
fad23bbe60 | ||
|
|
25c374856a | ||
|
|
34221346c1 | ||
|
|
924f10186f | ||
|
|
b7634b6ede | ||
|
|
4d49d5e845 | ||
|
|
715d86dae9 | ||
|
|
adb48692d6 | ||
|
|
19ccf1d073 | ||
|
|
e3c36465ec | ||
|
|
7e36284684 | ||
|
|
c448b4086a | ||
|
|
3200015c06 | ||
|
|
26d53c56a2 | ||
|
|
1439bb592e | ||
|
|
fc47e0dab2 | ||
|
|
87aa5d6b66 | ||
|
|
d1ad20c9ea | ||
|
|
ecca125f9a | ||
|
|
005e21a139 | ||
|
|
e1db036f90 | ||
|
|
9ad67b0758 | ||
|
|
af61abc747 | ||
|
|
ec575188c4 | ||
|
|
aea7500c1e | ||
|
|
58f5f27dc3 |
@@ -10,7 +10,7 @@ indent_style = space
|
||||
insert_final_newline = true
|
||||
indent_size = 2
|
||||
|
||||
[*.{rs,py}]
|
||||
[*.{rs,py,pyi}]
|
||||
indent_size = 4
|
||||
|
||||
[*.snap]
|
||||
|
||||
4
.gitattributes
vendored
4
.gitattributes
vendored
@@ -1,7 +1,7 @@
|
||||
* 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
|
||||
crates/ruff_linter/resources/test/fixtures/isort/line_ending_crlf.py text eol=crlf
|
||||
crates/ruff_linter/resources/test/fixtures/pycodestyle/W605_1.py text eol=crlf
|
||||
|
||||
ruff.schema.json linguist-generated=true text=auto eol=lf
|
||||
*.md.snap linguist-language=Markdown
|
||||
|
||||
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -6,4 +6,4 @@
|
||||
# - Order is important. The last matching pattern has the most precedence.
|
||||
|
||||
# Jupyter
|
||||
/crates/ruff/src/jupyter/ @dhruvmanila
|
||||
/crates/ruff_linter/src/jupyter/ @dhruvmanila
|
||||
|
||||
12
.github/dependabot.yml
vendored
12
.github/dependabot.yml
vendored
@@ -4,8 +4,10 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "monday"
|
||||
time: "12:00"
|
||||
timezone: "America/New_York"
|
||||
commit-message:
|
||||
prefix: "ci(deps)"
|
||||
labels: ["internal"]
|
||||
|
||||
- package-ecosystem: "cargo"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
labels: ["internal"]
|
||||
|
||||
8
.github/release.yml
vendored
8
.github/release.yml
vendored
@@ -4,7 +4,6 @@ changelog:
|
||||
labels:
|
||||
- internal
|
||||
- documentation
|
||||
- formatter
|
||||
categories:
|
||||
- title: Breaking Changes
|
||||
labels:
|
||||
@@ -12,7 +11,6 @@ changelog:
|
||||
- title: Rules
|
||||
labels:
|
||||
- rule
|
||||
- autofix
|
||||
- title: Settings
|
||||
labels:
|
||||
- configuration
|
||||
@@ -20,6 +18,12 @@ changelog:
|
||||
- title: Bug Fixes
|
||||
labels:
|
||||
- bug
|
||||
- title: Formatter
|
||||
labels:
|
||||
- formatter
|
||||
- title: Preview
|
||||
labels:
|
||||
- preview
|
||||
- title: Other Changes
|
||||
labels:
|
||||
- "*"
|
||||
|
||||
217
.github/workflows/ci.yaml
vendored
217
.github/workflows/ci.yaml
vendored
@@ -26,11 +26,11 @@ jobs:
|
||||
linter: ${{ steps.changed.outputs.linter_any_changed }}
|
||||
formatter: ${{ steps.changed.outputs.formatter_any_changed }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: tj-actions/changed-files@v37
|
||||
- uses: tj-actions/changed-files@v40
|
||||
id: changed
|
||||
with:
|
||||
files_yaml: |
|
||||
@@ -43,6 +43,7 @@ jobs:
|
||||
- "!crates/ruff_dev/**"
|
||||
- "!crates/ruff_shrinking/**"
|
||||
- scripts/*
|
||||
- .github/workflows/ci.yaml
|
||||
|
||||
formatter:
|
||||
- Cargo.toml
|
||||
@@ -57,12 +58,13 @@ jobs:
|
||||
- crates/ruff_python_parser/**
|
||||
- crates/ruff_dev/**
|
||||
- scripts/*
|
||||
- .github/workflows/ci.yaml
|
||||
|
||||
cargo-fmt:
|
||||
name: "cargo fmt"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup component add rustfmt
|
||||
- run: cargo fmt --all --check
|
||||
@@ -71,7 +73,7 @@ jobs:
|
||||
name: "cargo clippy"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: "Install Rust toolchain"
|
||||
run: |
|
||||
rustup component add clippy
|
||||
@@ -82,69 +84,55 @@ jobs:
|
||||
- name: "Clippy (wasm)"
|
||||
run: cargo clippy -p ruff_wasm --target wasm32-unknown-unknown --all-features -- -D warnings
|
||||
|
||||
cargo-test:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: "cargo test | ${{ matrix.os }}"
|
||||
cargo-test-linux:
|
||||
runs-on: ubuntu-latest
|
||||
name: "cargo test (linux)"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- name: "Install cargo insta"
|
||||
uses: taiki-e/install-action@v2
|
||||
with:
|
||||
tool: cargo-insta
|
||||
- run: pip install black[d]==23.1.0
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- name: "Run tests (Ubuntu)"
|
||||
if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||
- name: "Run tests"
|
||||
run: cargo insta test --all --all-features --unreferenced reject
|
||||
- name: "Run tests (Windows)"
|
||||
if: ${{ matrix.os == 'windows-latest' }}
|
||||
shell: bash
|
||||
# We can't reject unreferenced snapshots on windows because flake8_executable can't run on windows
|
||||
run: cargo insta test --all --all-features
|
||||
- run: cargo test --package ruff_cli --test black_compatibility_test -- --ignored
|
||||
# TODO: Skipped as it's currently broken. The resource were moved from the
|
||||
# ruff_cli to ruff crate, but this test was not updated.
|
||||
if: false
|
||||
# Check for broken links in the documentation.
|
||||
- run: cargo doc --all --no-deps
|
||||
env:
|
||||
# Setting RUSTDOCFLAGS because `cargo doc --check` isn't yet implemented (https://github.com/rust-lang/cargo/issues/10025).
|
||||
RUSTDOCFLAGS: "-D warnings"
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||
with:
|
||||
name: ruff
|
||||
path: target/debug/ruff
|
||||
|
||||
cargo-fuzz:
|
||||
runs-on: ubuntu-latest
|
||||
name: "cargo fuzz"
|
||||
cargo-test-windows:
|
||||
runs-on: windows-latest
|
||||
name: "cargo test (windows)"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: "fuzz -> target"
|
||||
- name: "Install cargo-fuzz"
|
||||
- name: "Install cargo insta"
|
||||
uses: taiki-e/install-action@v2
|
||||
with:
|
||||
tool: cargo-fuzz@0.11
|
||||
- run: cargo fuzz build -s none
|
||||
tool: cargo-insta
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- name: "Run tests"
|
||||
shell: bash
|
||||
# We can't reject unreferenced snapshots on windows because flake8_executable can't run on windows
|
||||
run: cargo insta test --all --all-features
|
||||
|
||||
cargo-test-wasm:
|
||||
runs-on: ubuntu-latest
|
||||
name: "cargo test (wasm)"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup target add wasm32-unknown-unknown
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: "npm"
|
||||
@@ -156,11 +144,27 @@ jobs:
|
||||
cd crates/ruff_wasm
|
||||
wasm-pack test --node
|
||||
|
||||
cargo-fuzz:
|
||||
runs-on: ubuntu-latest
|
||||
name: "cargo fuzz"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: "fuzz -> target"
|
||||
- name: "Install cargo-fuzz"
|
||||
uses: taiki-e/install-action@v2
|
||||
with:
|
||||
tool: cargo-fuzz@0.11
|
||||
- run: cargo fuzz build -s none
|
||||
|
||||
scripts:
|
||||
name: "test scripts"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup component add rustfmt
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
@@ -177,38 +181,100 @@ jobs:
|
||||
name: "ecosystem"
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- cargo-test
|
||||
- cargo-test-linux
|
||||
- determine_changes
|
||||
# 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' && needs.determine_changes.outputs.linter == 'true'
|
||||
if: github.event_name == 'pull_request'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
name: Download Ruff binary
|
||||
name: Download comparison Ruff binary
|
||||
id: ruff-target
|
||||
with:
|
||||
name: ruff
|
||||
path: target/debug
|
||||
|
||||
- uses: dawidd6/action-download-artifact@v2
|
||||
name: Download base results
|
||||
name: Download baseline Ruff binary
|
||||
with:
|
||||
name: ruff
|
||||
branch: ${{ github.event.pull_request.base.ref }}
|
||||
check_artifacts: true
|
||||
|
||||
- name: Run ecosystem check
|
||||
- name: Install ruff-ecosystem
|
||||
run: |
|
||||
pip install ./python/ruff-ecosystem
|
||||
|
||||
- name: Run `ruff check` stable ecosystem check
|
||||
if: ${{ needs.determine_changes.outputs.linter == 'true' }}
|
||||
run: |
|
||||
# Make executable, since artifact download doesn't preserve this
|
||||
chmod +x ruff ${{ steps.ruff-target.outputs.download-path }}/ruff
|
||||
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
|
||||
# Set pipefail to avoid hiding errors with tee
|
||||
set -eo pipefail
|
||||
|
||||
ruff-ecosystem check ./ruff ${{ steps.ruff-target.outputs.download-path }}/ruff --cache ./checkouts --output-format markdown | tee ecosystem-result-check-stable
|
||||
|
||||
cat ecosystem-result-check-stable > $GITHUB_STEP_SUMMARY
|
||||
echo "### Linter (stable)" > ecosystem-result
|
||||
cat ecosystem-result-check-stable >> ecosystem-result
|
||||
echo "" >> ecosystem-result
|
||||
|
||||
- name: Run `ruff check` preview ecosystem check
|
||||
if: ${{ needs.determine_changes.outputs.linter == 'true' }}
|
||||
run: |
|
||||
# Make executable, since artifact download doesn't preserve this
|
||||
chmod +x ./ruff ${{ steps.ruff-target.outputs.download-path }}/ruff
|
||||
|
||||
# Set pipefail to avoid hiding errors with tee
|
||||
set -eo pipefail
|
||||
|
||||
ruff-ecosystem check ./ruff ${{ steps.ruff-target.outputs.download-path }}/ruff --cache ./checkouts --output-format markdown --force-preview | tee ecosystem-result-check-preview
|
||||
|
||||
cat ecosystem-result-check-preview > $GITHUB_STEP_SUMMARY
|
||||
echo "### Linter (preview)" >> ecosystem-result
|
||||
cat ecosystem-result-check-preview >> ecosystem-result
|
||||
echo "" >> ecosystem-result
|
||||
|
||||
- name: Run `ruff format` stable ecosystem check
|
||||
if: ${{ needs.determine_changes.outputs.formatter == 'true' }}
|
||||
run: |
|
||||
# Make executable, since artifact download doesn't preserve this
|
||||
chmod +x ./ruff ${{ steps.ruff-target.outputs.download-path }}/ruff
|
||||
|
||||
# Set pipefail to avoid hiding errors with tee
|
||||
set -eo pipefail
|
||||
|
||||
ruff-ecosystem format ./ruff ${{ steps.ruff-target.outputs.download-path }}/ruff --cache ./checkouts --output-format markdown | tee ecosystem-result-format-stable
|
||||
|
||||
cat ecosystem-result-format-stable > $GITHUB_STEP_SUMMARY
|
||||
echo "### Formatter (stable)" >> ecosystem-result
|
||||
cat ecosystem-result-format-stable >> ecosystem-result
|
||||
echo "" >> ecosystem-result
|
||||
|
||||
- name: Run `ruff format` preview ecosystem check
|
||||
if: ${{ needs.determine_changes.outputs.formatter == 'true' }}
|
||||
run: |
|
||||
# Make executable, since artifact download doesn't preserve this
|
||||
chmod +x ./ruff ${{ steps.ruff-target.outputs.download-path }}/ruff
|
||||
|
||||
# Set pipefail to avoid hiding errors with tee
|
||||
set -eo pipefail
|
||||
|
||||
ruff-ecosystem format ./ruff ${{ steps.ruff-target.outputs.download-path }}/ruff --cache ./checkouts --output-format markdown --force-preview | tee ecosystem-result-format-preview
|
||||
|
||||
cat ecosystem-result-format-preview > $GITHUB_STEP_SUMMARY
|
||||
echo "### Formatter (preview)" >> ecosystem-result
|
||||
cat ecosystem-result-format-preview >> ecosystem-result
|
||||
echo "" >> ecosystem-result
|
||||
|
||||
- name: Export pull request number
|
||||
run: |
|
||||
echo ${{ github.event.number }} > pr-number
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
@@ -227,21 +293,21 @@ jobs:
|
||||
name: "cargo udeps"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: "Install nightly Rust toolchain"
|
||||
# Only pinned to make caching work, update freely
|
||||
run: rustup toolchain install nightly-2023-06-08
|
||||
run: rustup toolchain install nightly-2023-10-15
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- name: "Install cargo-udeps"
|
||||
uses: taiki-e/install-action@cargo-udeps
|
||||
- name: "Run cargo-udeps"
|
||||
run: cargo +nightly-2023-06-08 udeps
|
||||
run: cargo +nightly-2023-10-15 udeps
|
||||
|
||||
python-package:
|
||||
name: "python package"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
@@ -265,7 +331,7 @@ jobs:
|
||||
name: "pre-commit"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
@@ -295,7 +361,7 @@ jobs:
|
||||
env:
|
||||
MKDOCS_INSIDERS_SSH_KEY_EXISTS: ${{ secrets.MKDOCS_INSIDERS_SSH_KEY != '' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
- name: "Add SSH key"
|
||||
if: ${{ env.MKDOCS_INSIDERS_SSH_KEY_EXISTS == 'true' }}
|
||||
@@ -324,13 +390,13 @@ jobs:
|
||||
if: ${{ env.MKDOCS_INSIDERS_SSH_KEY_EXISTS != 'true' }}
|
||||
run: mkdocs build --strict -f mkdocs.generated.yml
|
||||
|
||||
check-formatter-ecosystem:
|
||||
name: "Formatter ecosystem and progress checks"
|
||||
check-formatter-instability-and-black-similarity:
|
||||
name: "formatter instabilities and black similarity"
|
||||
runs-on: ubuntu-latest
|
||||
needs: determine_changes
|
||||
if: needs.determine_changes.outputs.formatter == 'true' || github.ref == 'refs/heads/main'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
- name: "Cache rust"
|
||||
@@ -342,11 +408,50 @@ jobs:
|
||||
- name: "Remove checkouts from cache"
|
||||
run: rm -r target/progress_projects
|
||||
|
||||
check-ruff-lsp:
|
||||
name: "test ruff-lsp"
|
||||
runs-on: ubuntu-latest
|
||||
needs: cargo-test-linux
|
||||
steps:
|
||||
- uses: extractions/setup-just@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
name: "Download ruff-lsp source"
|
||||
with:
|
||||
repository: "astral-sh/ruff-lsp"
|
||||
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
name: Download development ruff binary
|
||||
id: ruff-target
|
||||
with:
|
||||
name: ruff
|
||||
path: target/debug
|
||||
|
||||
- name: Install ruff-lsp dependencies
|
||||
run: |
|
||||
just install
|
||||
|
||||
- name: Run ruff-lsp tests
|
||||
run: |
|
||||
# Setup development binary
|
||||
pip uninstall --yes ruff
|
||||
chmod +x ${{ steps.ruff-target.outputs.download-path }}/ruff
|
||||
export PATH=${{ steps.ruff-target.outputs.download-path }}:$PATH
|
||||
ruff version
|
||||
|
||||
just test
|
||||
|
||||
benchmarks:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Checkout Branch"
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup show
|
||||
|
||||
14
.github/workflows/docs.yaml
vendored
14
.github/workflows/docs.yaml
vendored
@@ -2,6 +2,11 @@ name: mkdocs
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
description: "The commit SHA, tag, or branch to publish. Uses the default branch if not specified."
|
||||
default: ""
|
||||
type: string
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
@@ -12,7 +17,9 @@ jobs:
|
||||
CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
|
||||
MKDOCS_INSIDERS_SSH_KEY_EXISTS: ${{ secrets.MKDOCS_INSIDERS_SSH_KEY != '' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.ref }}
|
||||
- uses: actions/setup-python@v4
|
||||
- name: "Add SSH key"
|
||||
if: ${{ env.MKDOCS_INSIDERS_SSH_KEY_EXISTS == 'true' }}
|
||||
@@ -40,8 +47,9 @@ jobs:
|
||||
run: mkdocs build --strict -f mkdocs.generated.yml
|
||||
- name: "Deploy to Cloudflare Pages"
|
||||
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
|
||||
uses: cloudflare/wrangler-action@v3.1.0
|
||||
uses: cloudflare/wrangler-action@v3.3.2
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
accountId: ${{ secrets.CF_ACCOUNT_ID }}
|
||||
command: pages publish site --project-name=ruff-docs --branch ${GITHUB_HEAD_REF} --commit-hash ${GITHUB_SHA}
|
||||
# `github.head_ref` is only set during pull requests and for manual runs or tags we use `main` to deploy to production
|
||||
command: pages deploy site --project-name=astral-docs --branch ${{ github.head_ref || 'main' }} --commit-hash ${GITHUB_SHA}
|
||||
|
||||
14
.github/workflows/flake8-to-ruff.yaml
vendored
14
.github/workflows/flake8-to-ruff.yaml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
macos-x86_64:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
macos-universal:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
@@ -68,7 +68,7 @@ jobs:
|
||||
matrix:
|
||||
target: [x64, x86]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
@@ -96,7 +96,7 @@ jobs:
|
||||
matrix:
|
||||
target: [x86_64, i686]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
@@ -123,7 +123,7 @@ jobs:
|
||||
matrix:
|
||||
target: [aarch64, armv7, s390x, ppc64le, ppc64]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
@@ -160,7 +160,7 @@ jobs:
|
||||
- x86_64-unknown-linux-musl
|
||||
- i686-unknown-linux-musl
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
@@ -196,7 +196,7 @@ jobs:
|
||||
- target: armv7-unknown-linux-musleabihf
|
||||
arch: armv7
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
|
||||
9
.github/workflows/playground.yaml
vendored
9
.github/workflows/playground.yaml
vendored
@@ -17,10 +17,10 @@ jobs:
|
||||
env:
|
||||
CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: "Install Rust toolchain"
|
||||
run: rustup target add wasm32-unknown-unknown
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: "npm"
|
||||
@@ -40,8 +40,9 @@ jobs:
|
||||
working-directory: playground
|
||||
- name: "Deploy to Cloudflare Pages"
|
||||
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
|
||||
uses: cloudflare/wrangler-action@v3.1.0
|
||||
uses: cloudflare/wrangler-action@v3.3.2
|
||||
with:
|
||||
apiToken: ${{ secrets.CF_API_TOKEN }}
|
||||
accountId: ${{ secrets.CF_ACCOUNT_ID }}
|
||||
command: pages publish playground/dist --project-name=ruff --branch ${GITHUB_HEAD_REF} --commit-hash ${GITHUB_SHA}
|
||||
# `github.head_ref` is only set during pull requests and for manual runs or tags we use `main` to deploy to production
|
||||
command: pages deploy playground/dist --project-name=ruff-playground --branch ${{ github.head_ref || 'main' }} --commit-hash ${GITHUB_SHA}
|
||||
|
||||
21
.github/workflows/pr-comment.yaml
vendored
21
.github/workflows/pr-comment.yaml
vendored
@@ -1,4 +1,4 @@
|
||||
name: PR Check Comment
|
||||
name: Ecosystem check comment
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
@@ -18,13 +18,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dawidd6/action-download-artifact@v2
|
||||
name: Download PR Number
|
||||
name: Download pull request 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
|
||||
- name: Parse pull request number
|
||||
id: pr-number
|
||||
run: |
|
||||
if [[ -f pr-number ]]
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- uses: dawidd6/action-download-artifact@v2
|
||||
name: "Download Ecosystem Result"
|
||||
name: "Download ecosystem results"
|
||||
id: download-ecosystem-result
|
||||
if: steps.pr-number.outputs.pr-number
|
||||
with:
|
||||
@@ -41,15 +41,18 @@ jobs:
|
||||
workflow: ci.yaml
|
||||
pr: ${{ steps.pr-number.outputs.pr-number }}
|
||||
path: pr/ecosystem
|
||||
workflow_conclusion: completed
|
||||
if_no_artifact_found: ignore
|
||||
|
||||
- name: Generate Comment
|
||||
- name: Generate comment content
|
||||
id: generate-comment
|
||||
if: steps.download-ecosystem-result.outputs.found_artifact == 'true'
|
||||
run: |
|
||||
echo '## PR Check Results' >> comment.txt
|
||||
# Note this identifier is used to find the comment to update on
|
||||
# subsequent runs
|
||||
echo '<!-- generated-comment ecosystem -->' >> comment.txt
|
||||
|
||||
echo "### Ecosystem" >> comment.txt
|
||||
echo '## `ruff-ecosystem` results' >> comment.txt
|
||||
cat pr/ecosystem/ecosystem-result >> comment.txt
|
||||
echo "" >> comment.txt
|
||||
|
||||
@@ -57,14 +60,14 @@ jobs:
|
||||
cat comment.txt >> $GITHUB_OUTPUT
|
||||
echo 'EOF' >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Find Comment
|
||||
- name: Find existing comment
|
||||
uses: peter-evans/find-comment@v2
|
||||
if: steps.generate-comment.outcome == 'success'
|
||||
id: find-comment
|
||||
with:
|
||||
issue-number: ${{ steps.pr-number.outputs.pr-number }}
|
||||
comment-author: "github-actions[bot]"
|
||||
body-includes: PR Check Results
|
||||
body-includes: "<!-- generated-comment ecosystem -->"
|
||||
|
||||
- name: Create or update comment
|
||||
if: steps.find-comment.outcome == 'success'
|
||||
|
||||
69
.github/workflows/release.yaml
vendored
69
.github/workflows/release.yaml
vendored
@@ -7,12 +7,15 @@ on:
|
||||
description: "The version to tag, without the leading 'v'. If omitted, will initiate a dry run (no uploads)."
|
||||
type: string
|
||||
sha:
|
||||
description: "Optionally, the full sha of the commit to be released"
|
||||
description: "The full sha of the commit to be released. If omitted, the latest commit on the default branch will be used."
|
||||
default: ""
|
||||
type: string
|
||||
pull_request:
|
||||
paths:
|
||||
# When we change pyproject.toml, we want to ensure that the maturin builds still work
|
||||
- pyproject.toml
|
||||
# And when we change this workflow itself...
|
||||
- .github/workflows/release.yaml
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -30,7 +33,9 @@ jobs:
|
||||
sdist:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.sha }}
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
@@ -43,7 +48,6 @@ jobs:
|
||||
args: --out dist
|
||||
- name: "Test sdist"
|
||||
run: |
|
||||
rustup default $(cat rust-toolchain)
|
||||
pip install dist/${{ env.PACKAGE_NAME }}-*.tar.gz --force-reinstall
|
||||
ruff --help
|
||||
python -m ruff --help
|
||||
@@ -56,7 +60,9 @@ jobs:
|
||||
macos-x86_64:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.sha }}
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
@@ -94,7 +100,9 @@ jobs:
|
||||
macos-universal:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.sha }}
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
@@ -140,7 +148,9 @@ jobs:
|
||||
- target: aarch64-pc-windows-msvc
|
||||
arch: x64
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.sha }}
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
@@ -186,7 +196,9 @@ jobs:
|
||||
- x86_64-unknown-linux-gnu
|
||||
- i686-unknown-linux-gnu
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.sha }}
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
@@ -243,7 +255,9 @@ jobs:
|
||||
arch: ppc64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.sha }}
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
@@ -296,7 +310,9 @@ jobs:
|
||||
- x86_64-unknown-linux-musl
|
||||
- i686-unknown-linux-musl
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.sha }}
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
@@ -350,7 +366,9 @@ jobs:
|
||||
arch: armv7
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.sha }}
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ env.PYTHON_VERSION }}
|
||||
@@ -398,9 +416,22 @@ jobs:
|
||||
# If you don't set an input tag, it's a dry run (no uploads).
|
||||
if: ${{ inputs.tag }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: main # We checkout the main branch to check for the commit
|
||||
- name: Check main branch
|
||||
if: ${{ inputs.sha }}
|
||||
run: |
|
||||
# Fetch the main branch since a shallow checkout is used by default
|
||||
git fetch origin main --unshallow
|
||||
if ! git branch --contains ${{ inputs.sha }} | grep -E '(^|\s)main$'; then
|
||||
echo "The specified sha is not on the main branch" >&2
|
||||
exit 1
|
||||
fi
|
||||
- name: Check tag consistency
|
||||
run: |
|
||||
# Switch to the commit we want to release
|
||||
git checkout ${{ inputs.sha }}
|
||||
version=$(grep "version = " pyproject.toml | sed -e 's/version = "\(.*\)"/\1/g')
|
||||
if [ "${{ inputs.tag }}" != "${version}" ]; then
|
||||
echo "The input tag does not match the version from pyproject.toml:" >&2
|
||||
@@ -410,18 +441,6 @@ jobs:
|
||||
else
|
||||
echo "Releasing ${version}"
|
||||
fi
|
||||
- name: Check SHA consistency
|
||||
if: ${{ inputs.sha }}
|
||||
run: |
|
||||
git_sha=$(git rev-parse HEAD)
|
||||
if [ "${{ inputs.sha }}" != "${git_sha}" ]; then
|
||||
echo "The specified sha does not match the git checkout" >&2
|
||||
echo "${{ inputs.sha }}" >&2
|
||||
echo "${git_sha}" >&2
|
||||
exit 1
|
||||
else
|
||||
echo "Releasing ${git_sha}"
|
||||
fi
|
||||
|
||||
upload-release:
|
||||
name: Upload to PyPI
|
||||
@@ -464,7 +483,9 @@ jobs:
|
||||
# For git tag
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.sha }}
|
||||
- name: git tag
|
||||
run: |
|
||||
git config user.email "hey@astral.sh"
|
||||
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -1,5 +1,5 @@
|
||||
# Benchmarking cpython (CONTRIBUTING.md)
|
||||
crates/ruff/resources/test/cpython
|
||||
crates/ruff_linter/resources/test/cpython
|
||||
# generate_mkdocs.py
|
||||
mkdocs.generated.yml
|
||||
# check_ecosystem.py
|
||||
@@ -208,3 +208,9 @@ cython_debug/
|
||||
# VIM
|
||||
.*.sw?
|
||||
.sw?
|
||||
|
||||
# Custom re-inclusions for the resolver test cases
|
||||
!crates/ruff_python_resolver/resources/test/airflow/venv/
|
||||
!crates/ruff_python_resolver/resources/test/airflow/venv/lib
|
||||
!crates/ruff_python_resolver/resources/test/airflow/venv/lib/python3.11/site-packages/_watchdog_fsevents.cpython-311-darwin.so
|
||||
!crates/ruff_python_resolver/resources/test/airflow/venv/lib/python3.11/site-packages/orjson/orjson.cpython-311-darwin.so
|
||||
|
||||
@@ -13,3 +13,8 @@ MD041: false
|
||||
|
||||
# MD013/line-length
|
||||
MD013: false
|
||||
|
||||
# MD024/no-duplicate-heading
|
||||
MD024:
|
||||
# Allow when nested under different parents e.g. CHANGELOG.md
|
||||
allow_different_nesting: true
|
||||
|
||||
@@ -2,8 +2,8 @@ fail_fast: true
|
||||
|
||||
exclude: |
|
||||
(?x)^(
|
||||
crates/ruff/resources/.*|
|
||||
crates/ruff/src/rules/.*/snapshots/.*|
|
||||
crates/ruff_linter/resources/.*|
|
||||
crates/ruff_linter/src/rules/.*/snapshots/.*|
|
||||
crates/ruff_cli/resources/.*|
|
||||
crates/ruff_python_formatter/resources/.*|
|
||||
crates/ruff_python_formatter/tests/snapshots/.*|
|
||||
@@ -23,8 +23,11 @@ repos:
|
||||
- id: mdformat
|
||||
additional_dependencies:
|
||||
- mdformat-mkdocs
|
||||
- mdformat-black
|
||||
- black==23.1.0 # Must be the latest version of Black
|
||||
- mdformat-admon
|
||||
exclude: |
|
||||
(?x)^(
|
||||
docs/formatter/black.md
|
||||
)$
|
||||
|
||||
- repo: https://github.com/igorshubovych/markdownlint-cli
|
||||
rev: v0.33.0
|
||||
@@ -44,24 +47,21 @@ repos:
|
||||
language: system
|
||||
types: [rust]
|
||||
pass_filenames: false # This makes it a lot faster
|
||||
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.1.3
|
||||
hooks:
|
||||
- id: ruff-format
|
||||
- id: ruff
|
||||
name: ruff
|
||||
entry: cargo run --bin ruff -- check --no-cache --force-exclude --fix --exit-non-zero-on-fix
|
||||
language: system
|
||||
args: [--fix, --exit-non-zero-on-fix]
|
||||
types_or: [python, pyi]
|
||||
require_serial: true
|
||||
exclude: |
|
||||
(?x)^(
|
||||
crates/ruff/resources/.*|
|
||||
crates/ruff_linter/resources/.*|
|
||||
crates/ruff_python_formatter/resources/.*
|
||||
)$
|
||||
|
||||
# Black
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.1.0
|
||||
hooks:
|
||||
- id: black
|
||||
|
||||
# Prettier
|
||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||
rev: v3.0.0
|
||||
|
||||
@@ -1,5 +1,50 @@
|
||||
# Breaking Changes
|
||||
|
||||
## 0.1.0
|
||||
|
||||
### The deprecated `format` setting has been removed
|
||||
|
||||
Ruff previously used the `format` setting, `--format` CLI option, and `RUFF_FORMAT` environment variable to
|
||||
configure the output format of the CLI. This usage was deprecated in `v0.0.291` — the `format` setting is now used
|
||||
to control Ruff's code formatting. As of this release:
|
||||
|
||||
- The `format` setting cannot be used to configure the output format, use `output-format` instead
|
||||
- The `RUFF_FORMAT` environment variable is ignored, use `RUFF_OUTPUT_FORMAT` instead
|
||||
- The `--format` option has been removed from `ruff check`, use `--output-format` instead
|
||||
|
||||
### Unsafe fixes are not applied by default ([#7769](https://github.com/astral-sh/ruff/pull/7769))
|
||||
|
||||
Ruff labels fixes as "safe" and "unsafe". The meaning and intent of your code will be retained when applying safe
|
||||
fixes, but the meaning could be changed when applying unsafe fixes. Previously, unsafe fixes were always displayed
|
||||
and applied when fixing was enabled. Now, unsafe fixes are hidden by default and not applied. The `--unsafe-fixes`
|
||||
flag or `unsafe-fixes` configuration option can be used to enable unsafe fixes.
|
||||
|
||||
See the [docs](https://docs.astral.sh/ruff/configuration/#fix-safety) for details.
|
||||
|
||||
### Remove formatter-conflicting rules from the default rule set ([#7900](https://github.com/astral-sh/ruff/pull/7900))
|
||||
|
||||
Previously, Ruff enabled all implemented rules in Pycodestyle (`E`) by default. Ruff now only includes the
|
||||
Pycodestyle prefixes `E4`, `E7`, and `E9` to exclude rules that conflict with automatic formatters. Consequently,
|
||||
the stable rule set no longer includes `line-too-long` (`E501`) and `mixed-spaces-and-tabs` (`E101`). Other
|
||||
excluded Pycodestyle rules include whitespace enforcement in `E1` and `E2`; these rules are currently in preview, and are already omitted by default.
|
||||
|
||||
This change only affects those using Ruff under its default rule set. Users that include `E` in their `select` will experience no change in behavior.
|
||||
|
||||
## 0.0.288
|
||||
|
||||
### Remove support for emoji identifiers ([#7212](https://github.com/astral-sh/ruff/pull/7212))
|
||||
|
||||
Previously, Ruff supported the non-standard compliant emoji identifiers e.g. `📦 = 1`.
|
||||
We decided to remove this non-standard language extension, and Ruff now reports syntax errors for emoji identifiers in your code, the same as CPython.
|
||||
|
||||
### Improved GitLab fingerprints ([#7203](https://github.com/astral-sh/ruff/pull/7203))
|
||||
|
||||
GitLab uses fingerprints to identify new, existing, or fixed violations. Previously, Ruff included the violation's position in the fingerprint. Using the location has the downside that changing any code before the violation causes the fingerprint to change, resulting in GitLab reporting one fixed and one new violation even though it is a pre-existing violation.
|
||||
|
||||
Ruff now uses a more stable location-agnostic fingerprint to minimize that existing violations incorrectly get marked as fixed and re-reported as new violations.
|
||||
|
||||
Expect GitLab to report each pre-existing violation in your project as fixed and a new violation in your Ruff upgrade PR.
|
||||
|
||||
## 0.0.283 / 0.284
|
||||
|
||||
### The target Python version now defaults to 3.8 instead of 3.10 ([#6397](https://github.com/astral-sh/ruff/pull/6397))
|
||||
@@ -284,4 +329,4 @@ default.
|
||||
`pyproject.toml` files are now resolved hierarchically, such that for each Python file, we find
|
||||
the first `pyproject.toml` file in its path, and use that to determine its lint settings.
|
||||
|
||||
See the [documentation](https://beta.ruff.rs/docs/configuration/#python-file-discovery) for more.
|
||||
See the [documentation](https://docs.astral.sh/ruff/configuration/#python-file-discovery) for more.
|
||||
|
||||
274
CHANGELOG.md
Normal file
274
CHANGELOG.md
Normal file
@@ -0,0 +1,274 @@
|
||||
# Changelog
|
||||
|
||||
## 0.1.3
|
||||
|
||||
This release includes a variety of improvements to the Ruff formatter, removing several known and
|
||||
unintentional deviations from Black.
|
||||
|
||||
### Formatter
|
||||
|
||||
- Avoid space around pow for `None`, `True` and `False` ([#8189](https://github.com/astral-sh/ruff/pull/8189))
|
||||
- Avoid sorting all paths in the format command ([#8181](https://github.com/astral-sh/ruff/pull/8181))
|
||||
- Insert necessary blank line between class and leading comments ([#8224](https://github.com/astral-sh/ruff/pull/8224))
|
||||
- Avoid introducing new parentheses in annotated assignments ([#8233](https://github.com/astral-sh/ruff/pull/8233))
|
||||
- Refine the warnings about incompatible linter options ([#8196](https://github.com/astral-sh/ruff/pull/8196))
|
||||
- Add test and basic implementation for formatter preview mode ([#8044](https://github.com/astral-sh/ruff/pull/8044))
|
||||
- Refine warning about incompatible `isort` settings ([#8192](https://github.com/astral-sh/ruff/pull/8192))
|
||||
- Only omit optional parentheses for starting or ending with parentheses ([#8238](https://github.com/astral-sh/ruff/pull/8238))
|
||||
- Use source type to determine parser mode for formatting ([#8205](https://github.com/astral-sh/ruff/pull/8205))
|
||||
- Don't warn about magic trailing comma when `isort.force-single-line` is true ([#8244](https://github.com/astral-sh/ruff/pull/8244))
|
||||
- Use `SourceKind::diff` for formatter ([#8240](https://github.com/astral-sh/ruff/pull/8240))
|
||||
- Fix `fmt:off` with trailing child comment ([#8234](https://github.com/astral-sh/ruff/pull/8234))
|
||||
- Formatter parentheses support for `IpyEscapeCommand` ([#8207](https://github.com/astral-sh/ruff/pull/8207))
|
||||
|
||||
### Linter
|
||||
|
||||
- \[`pylint`\] Add buffer methods to `bad-dunder-method-name` (`PLW3201`) exclusions ([#8190](https://github.com/astral-sh/ruff/pull/8190))
|
||||
- Match rule prefixes from `external` codes setting in `unused-noqa` ([#8177](https://github.com/astral-sh/ruff/pull/8177))
|
||||
- Use `line-length` setting for isort in lieu of `pycodestyle.max-line-length` ([#8235](https://github.com/astral-sh/ruff/pull/8235))
|
||||
- Update fix for `unnecessary-paren-on-raise-exception` to unsafe for unknown types ([#8231](https://github.com/astral-sh/ruff/pull/8231))
|
||||
- Correct quick fix message for `W605` ([#8255](https://github.com/astral-sh/ruff/pull/8255))
|
||||
|
||||
### Documentation
|
||||
|
||||
- Fix typo in max-doc-length documentation ([#8201](https://github.com/astral-sh/ruff/pull/8201))
|
||||
- Improve documentation around linter-formatter conflicts ([#8257](https://github.com/astral-sh/ruff/pull/8257))
|
||||
- Fix link to error suppression documentation in `unused-noqa` ([#8172](https://github.com/astral-sh/ruff/pull/8172))
|
||||
- Add `external` option to `unused-noqa` documentation ([#8171](https://github.com/astral-sh/ruff/pull/8171))
|
||||
- Add title attribute to icons ([#8060](https://github.com/astral-sh/ruff/pull/8060))
|
||||
- Clarify unsafe case in RSE102 ([#8256](https://github.com/astral-sh/ruff/pull/8256))
|
||||
- Fix skipping formatting examples ([#8210](https://github.com/astral-sh/ruff/pull/8210))
|
||||
- docs: fix name of `magic-trailing-comma` option in README ([#8200](https://github.com/astral-sh/ruff/pull/8200))
|
||||
- Add note about scope of rule changing in versioning policy ([#8169](https://github.com/astral-sh/ruff/pull/8169))
|
||||
- Document: Fix default lint rules ([#8218](https://github.com/astral-sh/ruff/pull/8218))
|
||||
- Fix a wrong setting in configuration.md ([#8186](https://github.com/astral-sh/ruff/pull/8186))
|
||||
- Fix misspelled TOML headers in the tutorial ([#8209](https://github.com/astral-sh/ruff/pull/8209))
|
||||
|
||||
## 0.1.2
|
||||
|
||||
This release includes the Beta version of the Ruff formatter — an extremely fast, Black-compatible Python formatter.
|
||||
Try it today with `ruff format`! [Check out the blog post](https://astral.sh/blog/the-ruff-formatter) and [read the docs](https://docs.astral.sh/ruff/formatter/).
|
||||
|
||||
### Preview features
|
||||
|
||||
- \[`pylint`\] Implement `non-ascii-module-import` (`C2403`) ([#8056](https://github.com/astral-sh/ruff/pull/8056))
|
||||
- \[`pylint`\] implement `non-ascii-name` (`C2401`) ([#8038](https://github.com/astral-sh/ruff/pull/8038))
|
||||
- \[`pylint`\] Implement unnecessary-lambda (W0108) ([#7953](https://github.com/astral-sh/ruff/pull/7953))
|
||||
- \[`refurb`\] Implement `read-whole-file` (`FURB101`) ([#7682](https://github.com/astral-sh/ruff/pull/7682))
|
||||
- Add fix for `E223`, `E224`, and `E242` ([#8143](https://github.com/astral-sh/ruff/pull/8143))
|
||||
- Add fix for `E225`, `E226`, `E227`, and `E228` ([#8136](https://github.com/astral-sh/ruff/pull/8136))
|
||||
- Add fix for `E252` ([#8142](https://github.com/astral-sh/ruff/pull/8142))
|
||||
- Add fix for `E261` ([#8114](https://github.com/astral-sh/ruff/pull/8114))
|
||||
- Add fix for `E273` and `E274` ([#8144](https://github.com/astral-sh/ruff/pull/8144))
|
||||
- Add fix for `E275` ([#8133](https://github.com/astral-sh/ruff/pull/8133))
|
||||
- Update `SIM401` to catch ternary operations ([#7415](https://github.com/astral-sh/ruff/pull/7415))
|
||||
- Update `E721` to allow `is` and `is` not for direct type comparisons ([#7905](https://github.com/astral-sh/ruff/pull/7905))
|
||||
|
||||
### Rule changes
|
||||
|
||||
- Add `backports.strenum` to `deprecated-imports` ([#8113](https://github.com/astral-sh/ruff/pull/8113))
|
||||
- Update `SIM112` to ignore `https_proxy`, `http_proxy`, and `no_proxy` ([#8140](https://github.com/astral-sh/ruff/pull/8140))
|
||||
- Update fix for `literal-membership` (`PLR6201`) to be unsafe ([#8097](https://github.com/astral-sh/ruff/pull/8097))
|
||||
- Update fix for `mutable-argument-defaults` (`B006`) to be unsafe ([#8108](https://github.com/astral-sh/ruff/pull/8108))
|
||||
|
||||
### Formatter
|
||||
|
||||
- Change `line-ending` default to `auto` ([#8057](https://github.com/astral-sh/ruff/pull/8057))
|
||||
- Respect parenthesized generators in `has_own_parentheses` ([#8100](https://github.com/astral-sh/ruff/pull/8100))
|
||||
- Add caching to formatter ([#8089](https://github.com/astral-sh/ruff/pull/8089))
|
||||
- Remove `--line-length` option from `format` command ([#8131](https://github.com/astral-sh/ruff/pull/8131))
|
||||
- Add formatter to `line-length` documentation ([#8150](https://github.com/astral-sh/ruff/pull/8150))
|
||||
- Warn about incompatible formatter options ([#8088](https://github.com/astral-sh/ruff/pull/8088))
|
||||
- Fix range of unparenthesized tuple subject in match statement ([#8101](https://github.com/astral-sh/ruff/pull/8101))
|
||||
- Remove experimental formatter warning ([#8148](https://github.com/astral-sh/ruff/pull/8148))
|
||||
- Don't move type param opening parenthesis comment ([#8163](https://github.com/astral-sh/ruff/pull/8163))
|
||||
- Update versions in format benchmark script ([#8110](https://github.com/astral-sh/ruff/pull/8110))
|
||||
- Avoid loading files for cached format results ([#8134](https://github.com/astral-sh/ruff/pull/8134))
|
||||
|
||||
### CLI
|
||||
|
||||
- Show the `ruff format` command in help menus ([#8167](https://github.com/astral-sh/ruff/pull/8167))
|
||||
- Add `ruff version` command with long version display ([#8034](https://github.com/astral-sh/ruff/pull/8034))
|
||||
|
||||
### Configuration
|
||||
|
||||
- New `pycodestyle.max-line-length` option ([#8039](https://github.com/astral-sh/ruff/pull/8039))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- Detect `sys.version_info` slices in `outdated-version-block` ([#8112](https://github.com/astral-sh/ruff/pull/8112))
|
||||
- Avoid if-else simplification for `TYPE_CHECKING` blocks ([#8072](https://github.com/astral-sh/ruff/pull/8072))
|
||||
- Avoid false-positive print separator diagnostic with starred argument ([#8079](https://github.com/astral-sh/ruff/pull/8079))
|
||||
|
||||
### Documentation
|
||||
|
||||
- Fix message for `too-many-arguments` lint ([#8092](https://github.com/astral-sh/ruff/pull/8092))
|
||||
- Fix `extend-unsafe-fixes` and `extend-safe-fixes` example ([#8139](https://github.com/astral-sh/ruff/pull/8139))
|
||||
- Add links to `flake8-import-conventions` options ([#8115](https://github.com/astral-sh/ruff/pull/8115))
|
||||
- Rework the documentation to incorporate the Ruff formatter ([#7732](https://github.com/astral-sh/ruff/pull/7732))
|
||||
- Fix `Options` JSON schema description ([#8081](https://github.com/astral-sh/ruff/pull/8081))
|
||||
- Fix typo (`pytext` -> `pytest`) ([#8117](https://github.com/astral-sh/ruff/pull/8117))
|
||||
- Improve `magic-value-comparison` example in docs ([#8111](https://github.com/astral-sh/ruff/pull/8111))
|
||||
|
||||
## 0.1.1
|
||||
|
||||
### Rule changes
|
||||
|
||||
- Add unsafe fix for `escape-sequence-in-docstring` (`D301`) ([#7970](https://github.com/astral-sh/ruff/pull/7970))
|
||||
|
||||
### Configuration
|
||||
|
||||
- Respect `#(deprecated)` attribute in configuration options ([#8035](https://github.com/astral-sh/ruff/pull/8035))
|
||||
- Add `[format|lint].exclude` options ([#8000](https://github.com/astral-sh/ruff/pull/8000))
|
||||
- Respect `tab-size` setting in formatter ([#8006](https://github.com/astral-sh/ruff/pull/8006))
|
||||
- Add `lint.preview` ([#8002](https://github.com/astral-sh/ruff/pull/8002))
|
||||
|
||||
### Preview features
|
||||
|
||||
- \[`pylint`\] Implement `literal-membership` (`PLR6201`) ([#7973](https://github.com/astral-sh/ruff/pull/7973))
|
||||
- \[`pylint`\] Implement `too-many-boolean-expressions` (`PLR0916`) ([#7975](https://github.com/astral-sh/ruff/pull/7975))
|
||||
- \[`pylint`\] Implement `misplaced-bare-raise` (`E0704`) ([#7961](https://github.com/astral-sh/ruff/pull/7961))
|
||||
- \[`pylint`\] Implement `global-at-module-level` (`W0604`) ([#8058](https://github.com/astral-sh/ruff/pull/8058))
|
||||
- \[`pylint`\] Implement `unspecified-encoding` (`PLW1514`) ([#7939](https://github.com/astral-sh/ruff/pull/7939))
|
||||
- Add fix for `triple-single-quotes` (`D300`) ([#7967](https://github.com/astral-sh/ruff/pull/7967))
|
||||
|
||||
### Formatter
|
||||
|
||||
- New code style badge for `ruff format` ([#7878](https://github.com/astral-sh/ruff/pull/7878))
|
||||
- Fix comments outside expression parentheses ([#7873](https://github.com/astral-sh/ruff/pull/7873))
|
||||
- Add `--target-version` to `ruff format` ([#8055](https://github.com/astral-sh/ruff/pull/8055))
|
||||
- Skip over parentheses when detecting `in` keyword ([#8054](https://github.com/astral-sh/ruff/pull/8054))
|
||||
- Add `--diff` option to `ruff format` ([#7937](https://github.com/astral-sh/ruff/pull/7937))
|
||||
- Insert newline after nested function or class statements ([#7946](https://github.com/astral-sh/ruff/pull/7946))
|
||||
- Use `pass` over ellipsis in non-function/class contexts ([#8049](https://github.com/astral-sh/ruff/pull/8049))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- Lazily evaluate all PEP 695 type alias values ([#8033](https://github.com/astral-sh/ruff/pull/8033))
|
||||
- Avoid failed assertion when showing fixes from stdin ([#8029](https://github.com/astral-sh/ruff/pull/8029))
|
||||
- Avoid flagging HTTP and HTTPS literals in urllib-open ([#8046](https://github.com/astral-sh/ruff/pull/8046))
|
||||
- Avoid flagging `bad-dunder-method-name` for `_` ([#8015](https://github.com/astral-sh/ruff/pull/8015))
|
||||
- Remove Python 2-only methods from `URLOpen` audit ([#8047](https://github.com/astral-sh/ruff/pull/8047))
|
||||
- Use set bracket replacement for `iteration-over-set` to preserve whitespace and comments ([#8001](https://github.com/astral-sh/ruff/pull/8001))
|
||||
|
||||
### Documentation
|
||||
|
||||
- Update tutorial to match revised Ruff defaults ([#8066](https://github.com/astral-sh/ruff/pull/8066))
|
||||
- Update rule `B005` docs ([#8028](https://github.com/astral-sh/ruff/pull/8028))
|
||||
- Update GitHub actions example in docs to use `--output-format` ([#8014](https://github.com/astral-sh/ruff/pull/8014))
|
||||
- Document `lint.preview` and `format.preview` ([#8032](https://github.com/astral-sh/ruff/pull/8032))
|
||||
- Clarify that new rules should be added to `RuleGroup::Preview`. ([#7989](https://github.com/astral-sh/ruff/pull/7989))
|
||||
|
||||
## 0.1.0
|
||||
|
||||
This is the first release which uses the `CHANGELOG` file. See [GitHub Releases](https://github.com/astral-sh/ruff/releases) for prior changelog entries.
|
||||
|
||||
Read Ruff's new [versioning policy](https://docs.astral.sh/ruff/versioning/).
|
||||
|
||||
### Breaking changes
|
||||
|
||||
- Unsafe fixes are no longer displayed or applied without opt-in ([#7769](https://github.com/astral-sh/ruff/pull/7769))
|
||||
- Drop formatting specific rules from the default set ([#7900](https://github.com/astral-sh/ruff/pull/7900))
|
||||
- The deprecated `format` setting has been removed ([#7984](https://github.com/astral-sh/ruff/pull/7984))
|
||||
- The `format` setting cannot be used to configure the output format, use `output-format` instead
|
||||
- The `RUFF_FORMAT` environment variable is ignored, use `RUFF_OUTPUT_FORMAT` instead
|
||||
- The `--format` option has been removed from `ruff check`, use `--output-format` instead
|
||||
|
||||
### Rule changes
|
||||
|
||||
- Extend `reimplemented-starmap` (`FURB140`) to catch calls with a single and starred argument ([#7768](https://github.com/astral-sh/ruff/pull/7768))
|
||||
- Improve cases covered by `RUF015` ([#7848](https://github.com/astral-sh/ruff/pull/7848))
|
||||
- Update `SIM15` to allow `open` followed by `close` ([#7916](https://github.com/astral-sh/ruff/pull/7916))
|
||||
- Respect `msgspec.Struct` default-copy semantics in `RUF012` ([#7786](https://github.com/astral-sh/ruff/pull/7786))
|
||||
- Add `sqlalchemy` methods to \`flake8-boolean-trap\`\` exclusion list ([#7874](https://github.com/astral-sh/ruff/pull/7874))
|
||||
- Add fix for `PLR1714` ([#7910](https://github.com/astral-sh/ruff/pull/7910))
|
||||
- Add fix for `PIE804` ([#7884](https://github.com/astral-sh/ruff/pull/7884))
|
||||
- Add fix for `PLC0208` ([#7887](https://github.com/astral-sh/ruff/pull/7887))
|
||||
- Add fix for `PYI055` ([#7886](https://github.com/astral-sh/ruff/pull/7886))
|
||||
- Update `non-pep695-type-alias` to require `--unsafe-fixes` outside of stub files ([#7836](https://github.com/astral-sh/ruff/pull/7836))
|
||||
- Improve fix message for `UP018` ([#7913](https://github.com/astral-sh/ruff/pull/7913))
|
||||
- Update `PLW3201` to support `Enum` [sunder names](https://docs.python.org/3/library/enum.html#supported-sunder-names) ([#7987](https://github.com/astral-sh/ruff/pull/7987))
|
||||
|
||||
### Preview features
|
||||
|
||||
- Only show warnings for empty preview selectors when enabling rules ([#7842](https://github.com/astral-sh/ruff/pull/7842))
|
||||
- Add `unnecessary-key-check` to simplify `key in dct and dct[key]` to `dct.get(key)` ([#7895](https://github.com/astral-sh/ruff/pull/7895))
|
||||
- Add `assignment-in-assert` to prevent walrus expressions in assert statements ([#7856](https://github.com/astral-sh/ruff/pull/7856))
|
||||
- \[`refurb`\] Add `single-item-membership-test` (`FURB171`) ([#7815](https://github.com/astral-sh/ruff/pull/7815))
|
||||
- \[`pylint`\] Add `and-or-ternary` (`R1706`) ([#7811](https://github.com/astral-sh/ruff/pull/7811))
|
||||
|
||||
_New rules are added in [preview](https://docs.astral.sh/ruff/preview/)._
|
||||
|
||||
### Configuration
|
||||
|
||||
- Add `unsafe-fixes` setting ([#7769](https://github.com/astral-sh/ruff/pull/7769))
|
||||
- Add `extend-safe-fixes` and `extend-unsafe-fixes` for promoting and demoting fixes ([#7841](https://github.com/astral-sh/ruff/pull/7841))
|
||||
|
||||
### CLI
|
||||
|
||||
- Added `--unsafe-fixes` option for opt-in to display and apply unsafe fixes ([#7769](https://github.com/astral-sh/ruff/pull/7769))
|
||||
- Fix use of deprecated `--format` option in warning ([#7837](https://github.com/astral-sh/ruff/pull/7837))
|
||||
- Show changed files when running under `--check` ([#7788](https://github.com/astral-sh/ruff/pull/7788))
|
||||
- Write summary messages to stderr when fixing via stdin instead of omitting them ([#7838](https://github.com/astral-sh/ruff/pull/7838))
|
||||
- Update fix summary message in `check --diff` to include unsafe fix hints ([#7790](https://github.com/astral-sh/ruff/pull/7790))
|
||||
- Add notebook `cell` field to JSON output format ([#7664](https://github.com/astral-sh/ruff/pull/7664))
|
||||
- Rename applicability levels to `Safe`, `Unsafe`, and `Display` ([#7843](https://github.com/astral-sh/ruff/pull/7843))
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- Fix bug where f-strings were allowed in match pattern literal ([#7857](https://github.com/astral-sh/ruff/pull/7857))
|
||||
- Fix `SIM110` with a yield in the condition ([#7801](https://github.com/astral-sh/ruff/pull/7801))
|
||||
- Preserve trailing comments in `C414` fixes ([#7775](https://github.com/astral-sh/ruff/pull/7775))
|
||||
- Check sequence type before triggering `unnecessary-enumerate` `len` suggestion ([#7781](https://github.com/astral-sh/ruff/pull/7781))
|
||||
- Use correct start location for class/function clause header ([#7802](https://github.com/astral-sh/ruff/pull/7802))
|
||||
- Fix incorrect fixes for `SIM101` ([#7798](https://github.com/astral-sh/ruff/pull/7798))
|
||||
- Format comment before parameter default correctly ([#7870](https://github.com/astral-sh/ruff/pull/7870))
|
||||
- Fix `E251` false positive inside f-strings ([#7894](https://github.com/astral-sh/ruff/pull/7894))
|
||||
- Allow bindings to be created and referenced within annotations ([#7885](https://github.com/astral-sh/ruff/pull/7885))
|
||||
- Show per-cell diffs when analyzing notebooks over `stdin` ([#7789](https://github.com/astral-sh/ruff/pull/7789))
|
||||
- Avoid curly brace escape in f-string format spec ([#7780](https://github.com/astral-sh/ruff/pull/7780))
|
||||
- Fix lexing single-quoted f-string with multi-line format spec ([#7787](https://github.com/astral-sh/ruff/pull/7787))
|
||||
- Consider nursery rules to be in-preview for `ruff rule` ([#7812](https://github.com/astral-sh/ruff/pull/7812))
|
||||
- Report precise location for invalid conversion flag ([#7809](https://github.com/astral-sh/ruff/pull/7809))
|
||||
- Visit pattern match guard as a boolean test ([#7911](https://github.com/astral-sh/ruff/pull/7911))
|
||||
- Respect `--unfixable` in `ISC` rules ([#7917](https://github.com/astral-sh/ruff/pull/7917))
|
||||
- Fix edge case with `PIE804` ([#7922](https://github.com/astral-sh/ruff/pull/7922))
|
||||
- Show custom message in `PTH118` for `Path.joinpath` with starred arguments ([#7852](https://github.com/astral-sh/ruff/pull/7852))
|
||||
- Fix false negative in `outdated-version-block` when using greater than comparisons ([#7920](https://github.com/astral-sh/ruff/pull/7920))
|
||||
- Avoid converting f-strings within Django `gettext` calls ([#7898](https://github.com/astral-sh/ruff/pull/7898))
|
||||
- Fix false positive in `PLR6301` ([#7933](https://github.com/astral-sh/ruff/pull/7933))
|
||||
- Treat type aliases as typing-only expressions e.g. resolves false positive in `TCH004` ([#7968](https://github.com/astral-sh/ruff/pull/7968))
|
||||
- Resolve `cache-dir` relative to project root ([#7962](https://github.com/astral-sh/ruff/pull/7962))
|
||||
- Respect subscripted base classes in type-checking rules e.g. resolves false positive in `TCH003` ([#7954](https://github.com/astral-sh/ruff/pull/7954))
|
||||
- Fix JSON schema limit for `line-length` ([#7883](https://github.com/astral-sh/ruff/pull/7883))
|
||||
- Fix commented-out `coalesce` keyword ([#7876](https://github.com/astral-sh/ruff/pull/7876))
|
||||
|
||||
### Documentation
|
||||
|
||||
- Document `reimplemented-starmap` performance effects ([#7846](https://github.com/astral-sh/ruff/pull/7846))
|
||||
- Default to following the system dark/light mode ([#7888](https://github.com/astral-sh/ruff/pull/7888))
|
||||
- Add documentation for fixes ([#7901](https://github.com/astral-sh/ruff/pull/7901))
|
||||
- Fix typo in docs of `PLR6301` ([#7831](https://github.com/astral-sh/ruff/pull/7831))
|
||||
- Update `UP038` docs to note that it results in slower code ([#7872](https://github.com/astral-sh/ruff/pull/7872))
|
||||
- crlf -> cr-lf ([#7766](https://github.com/astral-sh/ruff/pull/7766))
|
||||
- Add an example of an unsafe fix ([#7924](https://github.com/astral-sh/ruff/pull/7924))
|
||||
- Fix documented examples for `unnecessary-subscript-reversal` ([#7774](https://github.com/astral-sh/ruff/pull/7774))
|
||||
- Correct error in tuple example in ruff formatter docs ([#7822](https://github.com/astral-sh/ruff/pull/7822))
|
||||
- Add versioning policy to documentation ([#7923](https://github.com/astral-sh/ruff/pull/7923))
|
||||
- Fix invalid code in `FURB177` example ([#7832](https://github.com/astral-sh/ruff/pull/7832))
|
||||
|
||||
### Formatter
|
||||
|
||||
- Less scary `ruff format` message ([#7867](https://github.com/astral-sh/ruff/pull/7867))
|
||||
- Remove spaces from import statements ([#7859](https://github.com/astral-sh/ruff/pull/7859))
|
||||
- Formatter quoting for f-strings with triple quotes ([#7826](https://github.com/astral-sh/ruff/pull/7826))
|
||||
- Update `ruff_python_formatter` generate.py comment ([#7850](https://github.com/astral-sh/ruff/pull/7850))
|
||||
- Document one-call chaining deviation ([#7767](https://github.com/astral-sh/ruff/pull/7767))
|
||||
- Allow f-string modifications in line-shrinking cases ([#7818](https://github.com/astral-sh/ruff/pull/7818))
|
||||
- Add trailing comment deviation to README ([#7827](https://github.com/astral-sh/ruff/pull/7827))
|
||||
- Add trailing zero between dot and exponential ([#7956](https://github.com/astral-sh/ruff/pull/7956))
|
||||
- Force parentheses for power operations in unary expressions ([#7955](https://github.com/astral-sh/ruff/pull/7955))
|
||||
|
||||
### Playground
|
||||
|
||||
- Fix playground `Quick Fix` action ([#7824](https://github.com/astral-sh/ruff/pull/7824))
|
||||
120
CONTRIBUTING.md
120
CONTRIBUTING.md
@@ -112,11 +112,11 @@ Ruff is structured as a monorepo with a [flat crate structure](https://matklad.g
|
||||
such that all crates are contained in a flat `crates` directory.
|
||||
|
||||
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.
|
||||
`crates/ruff_linter`). As a contributor, that's the crate that'll be most relevant to you.
|
||||
|
||||
At time of writing, the repository includes the following crates:
|
||||
At the 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_linter`: library crate containing all lint rules and the core logic for running them.
|
||||
If you're working on a rule, this is the crate for you.
|
||||
- `crates/ruff_benchmark`: binary crate for running micro-benchmarks.
|
||||
- `crates/ruff_cache`: library crate for caching lint results.
|
||||
@@ -129,6 +129,7 @@ At time of writing, the repository includes the following crates:
|
||||
intermediate representation. The backend for `ruff_python_formatter`.
|
||||
- `crates/ruff_index`: library crate inspired by `rustc_index`.
|
||||
- `crates/ruff_macros`: proc macro crate containing macros used by Ruff.
|
||||
- `crates/ruff_notebook`: library crate for parsing and manipulating Jupyter notebooks.
|
||||
- `crates/ruff_python_ast`: library crate containing Python-specific AST types and utilities.
|
||||
- `crates/ruff_python_codegen`: library crate containing utilities for generating Python source code.
|
||||
- `crates/ruff_python_formatter`: library crate implementing the Python formatter. Emits an
|
||||
@@ -152,7 +153,7 @@ At a high level, the steps involved in adding a new lint rule are as follows:
|
||||
1. Determine a name for the new rule as per our [rule naming convention](#rule-naming-convention)
|
||||
(e.g., `AssertFalse`, as in, "allow `assert False`").
|
||||
|
||||
1. Create a file for your rule (e.g., `crates/ruff/src/rules/flake8_bugbear/rules/assert_false.rs`).
|
||||
1. Create a file for your rule (e.g., `crates/ruff_linter/src/rules/flake8_bugbear/rules/assert_false.rs`).
|
||||
|
||||
1. In that file, define a violation struct (e.g., `pub struct AssertFalse`). You can grep for
|
||||
`#[violation]` to see examples.
|
||||
@@ -161,21 +162,22 @@ At a high level, the steps involved in adding a new lint rule are as follows:
|
||||
(e.g., `pub(crate) fn assert_false`) based on whatever inputs are required for the rule (e.g.,
|
||||
an `ast::StmtAssert` node).
|
||||
|
||||
1. Define the logic for invoking the diagnostic in `crates/ruff/src/checkers/ast/analyze` (for
|
||||
AST-based rules), `crates/ruff/src/checkers/tokens.rs` (for token-based rules),
|
||||
`crates/ruff/src/checkers/physical_lines.rs` (for text-based rules),
|
||||
`crates/ruff/src/checkers/filesystem.rs` (for filesystem-based rules), etc. For AST-based rules,
|
||||
1. Define the logic for invoking the diagnostic in `crates/ruff_linter/src/checkers/ast/analyze` (for
|
||||
AST-based rules), `crates/ruff_linter/src/checkers/tokens.rs` (for token-based rules),
|
||||
`crates/ruff_linter/src/checkers/physical_lines.rs` (for text-based rules),
|
||||
`crates/ruff_linter/src/checkers/filesystem.rs` (for filesystem-based rules), etc. For AST-based rules,
|
||||
you'll likely want to modify `analyze/statement.rs` (if your rule is based on analyzing
|
||||
statements, like imports) or `analyze/expression.rs` (if your rule is based on analyzing
|
||||
expressions, like function calls).
|
||||
|
||||
1. Map the violation struct to a rule code in `crates/ruff/src/codes.rs` (e.g., `B011`).
|
||||
1. Map the violation struct to a rule code in `crates/ruff_linter/src/codes.rs` (e.g., `B011`). New rules
|
||||
should be added in `RuleGroup::Preview`.
|
||||
|
||||
1. Add proper [testing](#rule-testing-fixtures-and-snapshots) for your rule.
|
||||
|
||||
1. Update the generated files (documentation and generated code).
|
||||
|
||||
To trigger the violation, you'll likely want to augment the logic in `crates/ruff/src/checkers/ast.rs`
|
||||
To trigger the violation, you'll likely want to augment the logic in `crates/ruff_linter/src/checkers/ast.rs`
|
||||
to call your new function at the appropriate time and with the appropriate inputs. The `Checker`
|
||||
defined therein is a Python AST visitor, which iterates over the AST, building up a semantic model,
|
||||
and calling out to lint rule analyzer functions as it goes.
|
||||
@@ -203,7 +205,7 @@ As such, rule names should...
|
||||
For example, `AssertFalse` guards against `assert False` statements.
|
||||
|
||||
- _Not_ contain instructions on how to fix the violation, which instead belong in the rule
|
||||
documentation and the `autofix_title`.
|
||||
documentation and the `fix_title`.
|
||||
|
||||
- _Not_ contain a redundant prefix, like `Disallow` or `Banned`, which are already implied by the
|
||||
convention.
|
||||
@@ -220,7 +222,7 @@ Ruff's output for each fixture, which you can then commit alongside your changes
|
||||
|
||||
Once you've completed the code for the rule itself, you can define tests with the following steps:
|
||||
|
||||
1. Add a Python file to `crates/ruff/resources/test/fixtures/[linter]` that contains the code you
|
||||
1. Add a Python file to `crates/ruff_linter/resources/test/fixtures/[linter]` that contains the code you
|
||||
want to test. The file name should match the rule name (e.g., `E402.py`), and it should include
|
||||
examples of both violations and non-violations.
|
||||
|
||||
@@ -229,16 +231,16 @@ Once you've completed the code for the rule itself, you can define tests with th
|
||||
For example, if you're adding a new rule named `E402`, you would run:
|
||||
|
||||
```shell
|
||||
cargo run -p ruff_cli -- check crates/ruff/resources/test/fixtures/pycodestyle/E402.py --no-cache --select E402
|
||||
cargo run -p ruff_cli -- check crates/ruff_linter/resources/test/fixtures/pycodestyle/E402.py --no-cache --select E402
|
||||
```
|
||||
|
||||
**Note:** Only a subset of rules are enabled by default. When testing a new rule, ensure that
|
||||
you activate it by adding `--select ${rule_code}` to the command.
|
||||
|
||||
1. Add the test to the relevant `crates/ruff/src/rules/[linter]/mod.rs` file. If you're contributing
|
||||
1. Add the test to the relevant `crates/ruff_linter/src/rules/[linter]/mod.rs` file. If you're contributing
|
||||
a rule to a pre-existing set, you should be able to find a similar example to pattern-match
|
||||
against. If you're adding a new linter, you'll need to create a new `mod.rs` file (see,
|
||||
e.g., `crates/ruff/src/rules/flake8_bugbear/mod.rs`)
|
||||
e.g., `crates/ruff_linter/src/rules/flake8_bugbear/mod.rs`)
|
||||
|
||||
1. Run `cargo test`. Your test will fail, but you'll be prompted to follow-up
|
||||
with `cargo insta review`. Run `cargo insta review`, review and accept the generated snapshot,
|
||||
@@ -250,25 +252,24 @@ Once you've completed the code for the rule itself, you can define tests with th
|
||||
|
||||
Ruff's user-facing settings live in a few different places.
|
||||
|
||||
First, the command-line options are defined via the `Cli` struct in `crates/ruff/src/cli.rs`.
|
||||
First, the command-line options are defined via the `Args` struct in `crates/ruff_cli/src/args.rs`.
|
||||
|
||||
Second, the `pyproject.toml` options are defined in `crates/ruff/src/settings/options.rs` (via the
|
||||
`Options` struct), `crates/ruff/src/settings/configuration.rs` (via the `Configuration` struct), and
|
||||
`crates/ruff/src/settings/mod.rs` (via the `Settings` struct). These represent, respectively: the
|
||||
schema used to parse the `pyproject.toml` file; an internal, intermediate representation; and the
|
||||
final, internal representation used to power Ruff.
|
||||
Second, the `pyproject.toml` options are defined in `crates/ruff_workspace/src/options.rs` (via the
|
||||
`Options` struct), `crates/ruff_workspace/src/configuration.rs` (via the `Configuration` struct),
|
||||
and `crates/ruff_workspace/src/settings.rs` (via the `Settings` struct), which then includes
|
||||
the `LinterSettings` struct as a field.
|
||||
|
||||
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
|
||||
`arg.rs`, if appropriate). If you want to pattern-match against an existing example, grep for
|
||||
`dummy_variable_rgx`, which defines a regular expression to match against acceptable unused
|
||||
variables (e.g., `_`).
|
||||
|
||||
Note that plugin-specific configuration options are defined in their own modules (e.g.,
|
||||
`crates/ruff/src/flake8_unused_arguments/settings.rs`).
|
||||
|
||||
You may also want to add the new configuration option to the `flake8-to-ruff` tool, which is
|
||||
responsible for converting `flake8` configuration files to Ruff's TOML format. This logic
|
||||
lives in `crates/ruff/src/flake8_to_ruff/converter.rs`.
|
||||
`Settings` in `crates/ruff_linter/src/flake8_unused_arguments/settings.rs` coupled with
|
||||
`Flake8UnusedArgumentsOptions` in `crates/ruff_workspace/src/options.rs`).
|
||||
|
||||
Finally, regenerate the documentation and generated code with `cargo dev generate-all`.
|
||||
|
||||
@@ -336,16 +337,15 @@ even patch releases may contain [non-backwards-compatible changes](https://semve
|
||||
## Ecosystem CI
|
||||
|
||||
GitHub Actions will run your changes against a number of real-world projects from GitHub and
|
||||
report on any diagnostic differences. You can also run those checks locally via:
|
||||
report on any linter or formatter differences. You can also run those checks locally via:
|
||||
|
||||
```shell
|
||||
python scripts/check_ecosystem.py path/to/your/ruff path/to/older/ruff
|
||||
pip install -e ./python/ruff-ecosystem
|
||||
ruff-ecosystem check ruff "./target/debug/ruff"
|
||||
ruff-ecosystem format ruff "./target/debug/ruff"
|
||||
```
|
||||
|
||||
You can also run the Ecosystem CI check in a Docker container across a larger set of projects by
|
||||
downloading the [`known-github-tomls.json`](https://github.com/akx/ruff-usage-aggregate/blob/master/data/known-github-tomls.jsonl)
|
||||
as `github_search.jsonl` and following the instructions in [scripts/Dockerfile.ecosystem](https://github.com/astral-sh/ruff/blob/main/scripts/Dockerfile.ecosystem).
|
||||
Note that this check will take a while to run.
|
||||
See the [ruff-ecosystem package](https://github.com/astral-sh/ruff/tree/main/python/ruff-ecosystem) for more details.
|
||||
|
||||
## Benchmarking and Profiling
|
||||
|
||||
@@ -361,46 +361,46 @@ 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 crates/ruff/resources/test/cpython
|
||||
git clone --branch 3.10 https://github.com/python/cpython.git crates/ruff_linter/resources/test/cpython
|
||||
```
|
||||
|
||||
To benchmark the release build:
|
||||
|
||||
```shell
|
||||
cargo build --release && hyperfine --warmup 10 \
|
||||
"./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache -e" \
|
||||
"./target/release/ruff ./crates/ruff/resources/test/cpython/ -e"
|
||||
"./target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache -e" \
|
||||
"./target/release/ruff ./crates/ruff_linter/resources/test/cpython/ -e"
|
||||
|
||||
Benchmark 1: ./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache
|
||||
Benchmark 1: ./target/release/ruff ./crates/ruff_linter/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
|
||||
|
||||
Benchmark 2: ./target/release/ruff ./crates/ruff/resources/test/cpython/
|
||||
Benchmark 2: ./target/release/ruff ./crates/ruff_linter/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
|
||||
|
||||
Summary
|
||||
'./target/release/ruff ./crates/ruff/resources/test/cpython/' ran
|
||||
6.12 ± 0.41 times faster than './target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache'
|
||||
'./target/release/ruff ./crates/ruff_linter/resources/test/cpython/' ran
|
||||
6.12 ± 0.41 times faster than './target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache'
|
||||
```
|
||||
|
||||
To benchmark against the ecosystem's existing tools:
|
||||
|
||||
```shell
|
||||
hyperfine --ignore-failure --warmup 5 \
|
||||
"./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache" \
|
||||
"pyflakes crates/ruff/resources/test/cpython" \
|
||||
"./target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache" \
|
||||
"pyflakes crates/ruff_linter/resources/test/cpython" \
|
||||
"autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython" \
|
||||
"pycodestyle crates/ruff/resources/test/cpython" \
|
||||
"flake8 crates/ruff/resources/test/cpython"
|
||||
"pycodestyle crates/ruff_linter/resources/test/cpython" \
|
||||
"flake8 crates/ruff_linter/resources/test/cpython"
|
||||
|
||||
Benchmark 1: ./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache
|
||||
Benchmark 1: ./target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache
|
||||
Time (mean ± σ): 294.3 ms ± 3.3 ms [User: 2467.5 ms, System: 89.6 ms]
|
||||
Range (min … max): 291.1 ms … 302.8 ms 10 runs
|
||||
|
||||
Warning: Ignoring non-zero exit code.
|
||||
|
||||
Benchmark 2: pyflakes crates/ruff/resources/test/cpython
|
||||
Benchmark 2: pyflakes crates/ruff_linter/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
|
||||
|
||||
@@ -410,31 +410,31 @@ Benchmark 3: autoflake --recursive --expand-star-imports --remove-all-unused-imp
|
||||
Time (mean ± σ): 6.175 s ± 0.169 s [User: 54.102 s, System: 1.057 s]
|
||||
Range (min … max): 5.950 s … 6.391 s 10 runs
|
||||
|
||||
Benchmark 4: pycodestyle crates/ruff/resources/test/cpython
|
||||
Benchmark 4: pycodestyle crates/ruff_linter/resources/test/cpython
|
||||
Time (mean ± σ): 46.921 s ± 0.508 s [User: 46.699 s, System: 0.202 s]
|
||||
Range (min … max): 46.171 s … 47.863 s 10 runs
|
||||
|
||||
Warning: Ignoring non-zero exit code.
|
||||
|
||||
Benchmark 5: flake8 crates/ruff/resources/test/cpython
|
||||
Benchmark 5: flake8 crates/ruff_linter/resources/test/cpython
|
||||
Time (mean ± σ): 12.260 s ± 0.321 s [User: 102.934 s, System: 1.230 s]
|
||||
Range (min … max): 11.848 s … 12.933 s 10 runs
|
||||
|
||||
Warning: Ignoring non-zero exit code.
|
||||
|
||||
Summary
|
||||
'./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache' ran
|
||||
'./target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache' ran
|
||||
20.98 ± 0.62 times faster than 'autoflake --recursive --expand-star-imports --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys resources/test/cpython'
|
||||
41.66 ± 1.18 times faster than 'flake8 crates/ruff/resources/test/cpython'
|
||||
53.64 ± 0.77 times faster than 'pyflakes crates/ruff/resources/test/cpython'
|
||||
159.43 ± 2.48 times faster than 'pycodestyle crates/ruff/resources/test/cpython'
|
||||
41.66 ± 1.18 times faster than 'flake8 crates/ruff_linter/resources/test/cpython'
|
||||
53.64 ± 0.77 times faster than 'pyflakes crates/ruff_linter/resources/test/cpython'
|
||||
159.43 ± 2.48 times faster than 'pycodestyle crates/ruff_linter/resources/test/cpython'
|
||||
```
|
||||
|
||||
To benchmark a subset of rules, e.g. `LineTooLong` and `DocLineTooLong`:
|
||||
|
||||
```shell
|
||||
cargo build --release && hyperfine --warmup 10 \
|
||||
"./target/release/ruff ./crates/ruff/resources/test/cpython/ --no-cache -e --select W505,E501"
|
||||
"./target/release/ruff ./crates/ruff_linter/resources/test/cpython/ --no-cache -e --select W505,E501"
|
||||
```
|
||||
|
||||
You can run `poetry install` from `./scripts/benchmarks` to create a working environment for the
|
||||
@@ -467,10 +467,10 @@ rm Lib/test/bad_coding.py \
|
||||
Lib/test/test_typing.py
|
||||
```
|
||||
|
||||
Then, from `crates/ruff/resources/test/cpython`, run: `time pylint -j 0 -E $(git ls-files '*.py')`. This
|
||||
Then, from `crates/ruff_linter/resources/test/cpython`, run: `time pylint -j 0 -E $(git ls-files '*.py')`. This
|
||||
will execute Pylint with maximum parallelism and only report errors.
|
||||
|
||||
To benchmark Pyupgrade, run the following from `crates/ruff/resources/test/cpython`:
|
||||
To benchmark Pyupgrade, run the following from `crates/ruff_linter/resources/test/cpython`:
|
||||
|
||||
```shell
|
||||
hyperfine --ignore-failure --warmup 5 --prepare "git reset --hard HEAD" \
|
||||
@@ -718,8 +718,8 @@ Module {
|
||||
- `cargo dev generate-cli-help`, `cargo dev generate-docs` and `cargo dev generate-json-schema`:
|
||||
Update just `docs/configuration.md`, `docs/rules` and `ruff.schema.json` respectively.
|
||||
- `cargo dev generate-options`: Generate a markdown-compatible table of all `pyproject.toml`
|
||||
options. Used for <https://beta.ruff.rs/docs/settings/>
|
||||
- `cargo dev generate-rules-table`: Generate a markdown-compatible table of all rules. Used for <https://beta.ruff.rs/docs/rules/>
|
||||
options. Used for <https://docs.astral.sh/ruff/settings/>.
|
||||
- `cargo dev generate-rules-table`: Generate a markdown-compatible table of all rules. Used for <https://docs.astral.sh/ruff/rules/>.
|
||||
- `cargo dev round-trip <python file or jupyter notebook>`: Read a Python file or Jupyter Notebook,
|
||||
parse it, serialize the parsed representation and write it back. Used to check how good our
|
||||
representation is so that fixes don't rewrite irrelevant parts of a file.
|
||||
@@ -777,7 +777,7 @@ To understand Ruff's import categorization system, we first need to define two c
|
||||
- "Package root": The top-most directory defining the Python package that includes a given Python
|
||||
file. To find the package root for a given Python file, traverse up its parent directories until
|
||||
you reach a parent directory that doesn't contain an `__init__.py` file (and isn't marked as
|
||||
a [namespace package](https://beta.ruff.rs/docs/settings/#namespace-packages)); take the directory
|
||||
a [namespace package](https://docs.astral.sh/ruff/settings/#namespace-packages)); take the directory
|
||||
just before that, i.e., the first directory in the package.
|
||||
|
||||
For example, given:
|
||||
@@ -866,7 +866,7 @@ There are three ways in which an import can be categorized as "first-party":
|
||||
package (e.g., `from foo import bar` or `import foo.bar`), they'll be classified as first-party
|
||||
automatically. This check is as simple as comparing the first segment of the current file's
|
||||
module path to the first segment of the import.
|
||||
1. **Source roots**: Ruff supports a `[src](https://beta.ruff.rs/docs/settings/#src)` setting, which
|
||||
1. **Source roots**: Ruff supports a `[src](https://docs.astral.sh/ruff/settings/#src)` setting, which
|
||||
sets the directories to scan when identifying first-party imports. The algorithm is
|
||||
straightforward: given an import, like `import foo`, iterate over the directories enumerated in
|
||||
the `src` setting and, for each directory, check for the existence of a subdirectory `foo` or a
|
||||
@@ -876,5 +876,5 @@ By default, `src` is set to the project root. In the above example, we'd want to
|
||||
`src = ["./src"]` to ensure that we locate `./my_project/src/foo` and thus categorize `import foo`
|
||||
as first-party in `baz.py`. In practice, for this limited example, setting `src = ["./src"]` is
|
||||
unnecessary, as all imports within `./my_project/src/foo` would be categorized as first-party via
|
||||
the same-package heuristic; but your project contains multiple packages, you'll want to set `src`
|
||||
the same-package heuristic; but if your project contains multiple packages, you'll want to set `src`
|
||||
explicitly.
|
||||
|
||||
1165
Cargo.lock
generated
1165
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
61
Cargo.toml
61
Cargo.toml
@@ -5,8 +5,8 @@ resolver = "2"
|
||||
[workspace.package]
|
||||
edition = "2021"
|
||||
rust-version = "1.71"
|
||||
homepage = "https://beta.ruff.rs/docs"
|
||||
documentation = "https://beta.ruff.rs/docs"
|
||||
homepage = "https://docs.astral.sh/ruff"
|
||||
documentation = "https://docs.astral.sh/ruff"
|
||||
repository = "https://github.com/astral-sh/ruff"
|
||||
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
|
||||
license = "MIT"
|
||||
@@ -14,48 +14,47 @@ license = "MIT"
|
||||
[workspace.dependencies]
|
||||
anyhow = { version = "1.0.69" }
|
||||
bitflags = { version = "2.3.1" }
|
||||
chrono = { version = "0.4.23", default-features = false, features = ["clock"] }
|
||||
clap = { version = "4.1.8", features = ["derive"] }
|
||||
chrono = { version = "0.4.31", default-features = false, features = ["clock"] }
|
||||
clap = { version = "4.4.7", features = ["derive"] }
|
||||
colored = { version = "2.0.0" }
|
||||
filetime = { version = "0.2.20" }
|
||||
glob = { version = "0.3.1" }
|
||||
globset = { version = "0.4.10" }
|
||||
ignore = { version = "0.4.20" }
|
||||
insta = { version = "1.31.0", feature = ["filters", "glob"] }
|
||||
is-macro = { version = "0.2.2" }
|
||||
itertools = { version = "0.10.5" }
|
||||
insta = { version = "1.34.0", feature = ["filters", "glob"] }
|
||||
is-macro = { version = "0.3.0" }
|
||||
itertools = { version = "0.11.0" }
|
||||
libcst = { version = "1.1.0", default-features = false }
|
||||
log = { version = "0.4.17" }
|
||||
memchr = "2.5.0"
|
||||
num-bigint = { version = "0.4.3" }
|
||||
num-traits = { version = "0.2.15" }
|
||||
memchr = { version = "2.6.4" }
|
||||
once_cell = { version = "1.17.1" }
|
||||
path-absolutize = { version = "3.0.14" }
|
||||
proc-macro2 = { version = "1.0.51" }
|
||||
path-absolutize = { version = "3.1.1" }
|
||||
proc-macro2 = { version = "1.0.69" }
|
||||
quote = { version = "1.0.23" }
|
||||
regex = { version = "1.7.1" }
|
||||
regex = { version = "1.10.2" }
|
||||
rustc-hash = { version = "1.1.0" }
|
||||
schemars = { version = "0.8.12" }
|
||||
serde = { version = "1.0.152", features = ["derive"] }
|
||||
serde_json = { version = "1.0.93" }
|
||||
schemars = { version = "0.8.15" }
|
||||
serde = { version = "1.0.190", features = ["derive"] }
|
||||
serde_json = { version = "1.0.107" }
|
||||
shellexpand = { version = "3.0.0" }
|
||||
similar = { version = "2.2.1", features = ["inline"] }
|
||||
smallvec = { version = "1.10.0" }
|
||||
strum = { version = "0.24.1", features = ["strum_macros"] }
|
||||
strum_macros = { version = "0.24.3" }
|
||||
syn = { version = "2.0.15" }
|
||||
test-case = { version = "3.0.0" }
|
||||
thiserror = { version = "1.0.43" }
|
||||
toml = { version = "0.7.2" }
|
||||
tracing = "0.1.37"
|
||||
tracing-indicatif = "0.3.4"
|
||||
similar = { version = "2.3.0", features = ["inline"] }
|
||||
smallvec = { version = "1.11.1" }
|
||||
static_assertions = "1.1.0"
|
||||
strum = { version = "0.25.0", features = ["strum_macros"] }
|
||||
strum_macros = { version = "0.25.3" }
|
||||
syn = { version = "2.0.38" }
|
||||
test-case = { version = "3.2.1" }
|
||||
thiserror = { version = "1.0.50" }
|
||||
toml = { version = "0.7.8" }
|
||||
tracing = { version = "0.1.40" }
|
||||
tracing-indicatif = { version = "0.3.4" }
|
||||
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
|
||||
unicode-width = "0.1.10"
|
||||
uuid = { version = "1.4.1", features = ["v4", "fast-rng", "macro-diagnostics", "js"] }
|
||||
unicode-ident = { version = "1.0.12" }
|
||||
unicode_names2 = { version = "1.2.0" }
|
||||
unicode-width = { version = "0.1.11" }
|
||||
uuid = { version = "1.5.0", features = ["v4", "fast-rng", "macro-diagnostics", "js"] }
|
||||
wsl = { version = "0.1.0" }
|
||||
|
||||
# v1.0.1
|
||||
libcst = { git = "https://github.com/Instagram/LibCST.git", rev = "3cacca1a1029f05707e50703b49fe3dd860aa839", default-features = false }
|
||||
|
||||
[profile.release]
|
||||
lto = "fat"
|
||||
codegen-units = 1
|
||||
|
||||
72
LICENSE
72
LICENSE
@@ -1194,7 +1194,27 @@ are:
|
||||
|
||||
- flake8-self, licensed as follows:
|
||||
"""
|
||||
Freely Distributable
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Korijn van Golen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"""
|
||||
|
||||
- flake8-django, licensed under the GPL license.
|
||||
@@ -1224,6 +1244,56 @@ are:
|
||||
SOFTWARE.
|
||||
"""
|
||||
|
||||
- flake8-logging, licensed as follows:
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Adam Johnson
|
||||
|
||||
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-trio, licensed as follows:
|
||||
"""
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Zac Hatfield-Dodds
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"""
|
||||
|
||||
- Pyright, licensed as follows:
|
||||
"""
|
||||
MIT License
|
||||
|
||||
130
README.md
130
README.md
@@ -8,9 +8,9 @@
|
||||
[](https://pypi.python.org/pypi/ruff)
|
||||
[](https://github.com/astral-sh/ruff/actions)
|
||||
|
||||
[**Discord**](https://discord.gg/c9MhzV8aU5) | [**Docs**](https://beta.ruff.rs/docs/) | [**Playground**](https://play.ruff.rs/)
|
||||
[**Discord**](https://discord.gg/c9MhzV8aU5) | [**Docs**](https://docs.astral.sh/ruff/) | [**Playground**](https://play.ruff.rs/)
|
||||
|
||||
An extremely fast Python linter, written in Rust.
|
||||
An extremely fast Python linter and code formatter, written in Rust.
|
||||
|
||||
<p align="center">
|
||||
<picture align="center">
|
||||
@@ -24,28 +24,27 @@ An extremely fast Python linter, written in Rust.
|
||||
<i>Linting the CPython codebase from scratch.</i>
|
||||
</p>
|
||||
|
||||
- ⚡️ 10-100x faster than existing linters
|
||||
- ⚡️ 10-100x faster than existing linters (like Flake8) and formatters (like Black)
|
||||
- 🐍 Installable via `pip`
|
||||
- 🛠️ `pyproject.toml` support
|
||||
- 🤝 Python 3.11 compatibility
|
||||
- 🤝 Python 3.12 compatibility
|
||||
- ⚖️ Drop-in parity with [Flake8](https://docs.astral.sh/ruff/faq/#how-does-ruff-compare-to-flake8), isort, and Black
|
||||
- 📦 Built-in caching, to avoid re-analyzing unchanged files
|
||||
- 🔧 Autofix support, for automatic error correction (e.g., automatically remove unused imports)
|
||||
- 📏 Over [600 built-in rules](https://beta.ruff.rs/docs/rules/)
|
||||
- ⚖️ [Near-parity](https://beta.ruff.rs/docs/faq/#how-does-ruff-compare-to-flake8) with the
|
||||
built-in Flake8 rule set
|
||||
- 🔌 Native re-implementations of dozens of Flake8 plugins, like flake8-bugbear
|
||||
- ⌨️ First-party [editor integrations](https://beta.ruff.rs/docs/editor-integrations/) for
|
||||
- 🔧 Fix support, for automatic error correction (e.g., automatically remove unused imports)
|
||||
- 📏 Over [700 built-in rules](https://docs.astral.sh/ruff/rules/), with native re-implementations
|
||||
of popular Flake8 plugins, like flake8-bugbear
|
||||
- ⌨️ First-party [editor integrations](https://docs.astral.sh/ruff/integrations/) for
|
||||
[VS Code](https://github.com/astral-sh/ruff-vscode) and [more](https://github.com/astral-sh/ruff-lsp)
|
||||
- 🌎 Monorepo-friendly, with [hierarchical and cascading configuration](https://beta.ruff.rs/docs/configuration/#pyprojecttoml-discovery)
|
||||
- 🌎 Monorepo-friendly, with [hierarchical and cascading configuration](https://docs.astral.sh/ruff/configuration/#pyprojecttoml-discovery)
|
||||
|
||||
Ruff aims to be orders of magnitude faster than alternative tools while integrating more
|
||||
functionality behind a single, common interface.
|
||||
|
||||
Ruff can be used to replace [Flake8](https://pypi.org/project/flake8/) (plus dozens of plugins),
|
||||
[isort](https://pypi.org/project/isort/), [pydocstyle](https://pypi.org/project/pydocstyle/),
|
||||
[yesqa](https://github.com/asottile/yesqa), [eradicate](https://pypi.org/project/eradicate/),
|
||||
[pyupgrade](https://pypi.org/project/pyupgrade/), and [autoflake](https://pypi.org/project/autoflake/),
|
||||
all while executing tens or hundreds of times faster than any individual tool.
|
||||
[Black](https://github.com/psf/black), [isort](https://pypi.org/project/isort/),
|
||||
[pydocstyle](https://pypi.org/project/pydocstyle/), [pyupgrade](https://pypi.org/project/pyupgrade/),
|
||||
[autoflake](https://pypi.org/project/autoflake/), and more, all while executing tens or hundreds of
|
||||
times faster than any individual tool.
|
||||
|
||||
Ruff is extremely actively developed and used in major open-source projects like:
|
||||
|
||||
@@ -98,7 +97,7 @@ developer of [Zulip](https://github.com/zulip/zulip):
|
||||
|
||||
## Table of Contents
|
||||
|
||||
For more, see the [documentation](https://beta.ruff.rs/docs/).
|
||||
For more, see the [documentation](https://docs.astral.sh/ruff/).
|
||||
|
||||
1. [Getting Started](#getting-started)
|
||||
1. [Configuration](#configuration)
|
||||
@@ -111,7 +110,7 @@ For more, see the [documentation](https://beta.ruff.rs/docs/).
|
||||
|
||||
## Getting Started
|
||||
|
||||
For more, see the [documentation](https://beta.ruff.rs/docs/).
|
||||
For more, see the [documentation](https://docs.astral.sh/ruff/).
|
||||
|
||||
### Installation
|
||||
|
||||
@@ -122,27 +121,42 @@ pip install ruff
|
||||
```
|
||||
|
||||
You can also install Ruff via [Homebrew](https://formulae.brew.sh/formula/ruff), [Conda](https://anaconda.org/conda-forge/ruff),
|
||||
and with [a variety of other package managers](https://beta.ruff.rs/docs/installation/).
|
||||
and with [a variety of other package managers](https://docs.astral.sh/ruff/installation/).
|
||||
|
||||
### Usage
|
||||
|
||||
To run Ruff, try any of the following:
|
||||
To run Ruff as a linter, try any of the following:
|
||||
|
||||
```shell
|
||||
ruff check . # Lint all files in the current directory (and any subdirectories)
|
||||
ruff check path/to/code/ # Lint all files in `/path/to/code` (and any subdirectories)
|
||||
ruff check path/to/code/*.py # Lint all `.py` files in `/path/to/code`
|
||||
ruff check path/to/code/to/file.py # Lint `file.py`
|
||||
ruff check . # Lint all files in the current directory (and any subdirectories).
|
||||
ruff check path/to/code/ # Lint all files in `/path/to/code` (and any subdirectories).
|
||||
ruff check path/to/code/*.py # Lint all `.py` files in `/path/to/code`.
|
||||
ruff check path/to/code/to/file.py # Lint `file.py`.
|
||||
ruff check @arguments.txt # Lint using an input file, treating its contents as newline-delimited command-line arguments.
|
||||
```
|
||||
|
||||
Ruff can also be used as a [pre-commit](https://pre-commit.com) hook:
|
||||
Or, to run Ruff as a formatter:
|
||||
|
||||
```shell
|
||||
ruff format . # Format all files in the current directory (and any subdirectories).
|
||||
ruff format path/to/code/ # Format all files in `/path/to/code` (and any subdirectories).
|
||||
ruff format path/to/code/*.py # Format all `.py` files in `/path/to/code`.
|
||||
ruff format path/to/code/to/file.py # Format `file.py`.
|
||||
ruff format @arguments.txt # Format using an input file, treating its contents as newline-delimited command-line arguments.
|
||||
```
|
||||
|
||||
Ruff can also be used as a [pre-commit](https://pre-commit.com/) hook via [`ruff-pre-commit`](https://github.com/astral-sh/ruff-pre-commit):
|
||||
|
||||
```yaml
|
||||
# Run the Ruff linter.
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.0.286
|
||||
rev: v0.1.3
|
||||
hooks:
|
||||
# Run the Ruff linter.
|
||||
- id: ruff
|
||||
# Run the Ruff formatter.
|
||||
- id: ruff-format
|
||||
```
|
||||
|
||||
Ruff can also be used as a [VS Code extension](https://github.com/astral-sh/ruff-vscode) or
|
||||
@@ -165,21 +179,13 @@ jobs:
|
||||
### Configuration
|
||||
|
||||
Ruff can be configured through a `pyproject.toml`, `ruff.toml`, or `.ruff.toml` file (see:
|
||||
[_Configuration_](https://beta.ruff.rs/docs/configuration/), or [_Settings_](https://beta.ruff.rs/docs/settings/)
|
||||
[_Configuration_](https://docs.astral.sh/ruff/configuration/), or [_Settings_](https://docs.astral.sh/ruff/settings/)
|
||||
for a complete list of all configuration options).
|
||||
|
||||
If left unspecified, the default configuration is equivalent to:
|
||||
If left unspecified, Ruff's default configuration is equivalent to:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
# Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default.
|
||||
select = ["E", "F"]
|
||||
ignore = []
|
||||
|
||||
# Allow autofix for all enabled rules (when `--fix`) is provided.
|
||||
fixable = ["A", "B", "C", "D", "E", "F", "G", "I", "N", "Q", "S", "T", "W", "ANN", "ARG", "BLE", "COM", "DJ", "DTZ", "EM", "ERA", "EXE", "FBT", "ICN", "INP", "ISC", "NPY", "PD", "PGH", "PIE", "PL", "PT", "PTH", "PYI", "RET", "RSE", "RUF", "SIM", "SLF", "TCH", "TID", "TRY", "UP", "YTT"]
|
||||
unfixable = []
|
||||
|
||||
# Exclude a variety of commonly ignored directories.
|
||||
exclude = [
|
||||
".bzr",
|
||||
@@ -207,39 +213,57 @@ exclude = [
|
||||
|
||||
# Same as Black.
|
||||
line-length = 88
|
||||
|
||||
# Allow unused variables when underscore-prefixed.
|
||||
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
||||
indent-width = 4
|
||||
|
||||
# Assume Python 3.8
|
||||
target-version = "py38"
|
||||
|
||||
[tool.ruff.mccabe]
|
||||
# Unlike Flake8, default to a complexity level of 10.
|
||||
max-complexity = 10
|
||||
[tool.ruff.lint]
|
||||
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
|
||||
select = ["E4", "E7", "E9", "F"]
|
||||
ignore = []
|
||||
|
||||
# Allow fix for all enabled rules (when `--fix`) is provided.
|
||||
fixable = ["ALL"]
|
||||
unfixable = []
|
||||
|
||||
# Allow unused variables when underscore-prefixed.
|
||||
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
||||
|
||||
[tool.ruff.format]
|
||||
# Like Black, use double quotes for strings.
|
||||
quote-style = "double"
|
||||
|
||||
# Like Black, indent with spaces, rather than tabs.
|
||||
indent-style = "space"
|
||||
|
||||
# Like Black, respect magic trailing commas.
|
||||
skip-magic-trailing-comma = false
|
||||
|
||||
# Like Black, automatically detect the appropriate line ending.
|
||||
line-ending = "auto"
|
||||
```
|
||||
|
||||
Some configuration options can be provided via the command-line, such as those related to
|
||||
rule enablement and disablement, file discovery, logging level, and more:
|
||||
rule enablement and disablement, file discovery, and logging level:
|
||||
|
||||
```shell
|
||||
ruff check path/to/code/ --select F401 --select F403 --quiet
|
||||
```
|
||||
|
||||
See `ruff help` for more on Ruff's top-level commands, or `ruff help check` for more on the
|
||||
linting command.
|
||||
See `ruff help` for more on Ruff's top-level commands, or `ruff help check` and `ruff help format`
|
||||
for more on the linting and formatting commands, respectively.
|
||||
|
||||
## Rules
|
||||
|
||||
<!-- Begin section: Rules -->
|
||||
|
||||
**Ruff supports over 600 lint rules**, many of which are inspired by popular tools like Flake8,
|
||||
**Ruff supports over 700 lint rules**, many of which are inspired by popular tools like Flake8,
|
||||
isort, pyupgrade, and others. Regardless of the rule's origin, Ruff re-implements every rule in
|
||||
Rust as a first-party feature.
|
||||
|
||||
By default, Ruff enables Flake8's `E` and `F` rules. Ruff supports all rules from the `F` category,
|
||||
and a [subset](https://beta.ruff.rs/docs/rules/#error-e) of the `E` category, omitting those
|
||||
stylistic rules made obsolete by the use of an autoformatter, like
|
||||
By default, Ruff enables Flake8's `F` rules, along with a subset of the `E` rules, omitting any
|
||||
stylistic rules that overlap with the use of a formatter, like `ruff format` or
|
||||
[Black](https://github.com/psf/black).
|
||||
|
||||
If you're just getting started with Ruff, **the default rule set is a great place to start**: it
|
||||
@@ -274,6 +298,7 @@ quality tools, including:
|
||||
- [flake8-gettext](https://pypi.org/project/flake8-gettext/)
|
||||
- [flake8-implicit-str-concat](https://pypi.org/project/flake8-implicit-str-concat/)
|
||||
- [flake8-import-conventions](https://github.com/joaopalmeiro/flake8-import-conventions)
|
||||
- [flake8-logging](https://pypi.org/project/flake8-logging/)
|
||||
- [flake8-logging-format](https://pypi.org/project/flake8-logging-format/)
|
||||
- [flake8-no-pep420](https://pypi.org/project/flake8-no-pep420)
|
||||
- [flake8-pie](https://pypi.org/project/flake8-pie/)
|
||||
@@ -289,6 +314,7 @@ quality tools, including:
|
||||
- [flake8-super](https://pypi.org/project/flake8-super/)
|
||||
- [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
|
||||
- [flake8-todos](https://pypi.org/project/flake8-todos/)
|
||||
- [flake8-trio](https://pypi.org/project/flake8-trio/)
|
||||
- [flake8-type-checking](https://pypi.org/project/flake8-type-checking/)
|
||||
- [flake8-use-pathlib](https://pypi.org/project/flake8-use-pathlib/)
|
||||
- [flynt](https://pypi.org/project/flynt/) ([#2102](https://github.com/astral-sh/ruff/issues/2102))
|
||||
@@ -303,12 +329,12 @@ quality tools, including:
|
||||
- [tryceratops](https://pypi.org/project/tryceratops/)
|
||||
- [yesqa](https://pypi.org/project/yesqa/)
|
||||
|
||||
For a complete enumeration of the supported rules, see [_Rules_](https://beta.ruff.rs/docs/rules/).
|
||||
For a complete enumeration of the supported rules, see [_Rules_](https://docs.astral.sh/ruff/rules/).
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome and highly appreciated. To get started, check out the
|
||||
[**contributing guidelines**](https://beta.ruff.rs/docs/contributing/).
|
||||
[**contributing guidelines**](https://docs.astral.sh/ruff/contributing/).
|
||||
|
||||
You can also join us on [**Discord**](https://discord.gg/c9MhzV8aU5).
|
||||
|
||||
@@ -330,7 +356,7 @@ In some cases, Ruff includes a "direct" Rust port of the corresponding tool.
|
||||
We're grateful to the maintainers of these tools for their work, and for all
|
||||
the value they've provided to the Python community.
|
||||
|
||||
Ruff's autoformatter is built on a fork of Rome's [`rome_formatter`](https://github.com/rome/tools/tree/main/crates/rome_formatter),
|
||||
Ruff's formatter is built on a fork of Rome's [`rome_formatter`](https://github.com/rome/tools/tree/main/crates/rome_formatter),
|
||||
and again draws on both API and implementation details from [Rome](https://github.com/rome/tools),
|
||||
[Prettier](https://github.com/prettier/prettier), and [Black](https://github.com/psf/black).
|
||||
|
||||
@@ -384,6 +410,7 @@ Ruff is used by a number of major open-source projects and companies, including:
|
||||
- [Mypy](https://github.com/python/mypy)
|
||||
- Netflix ([Dispatch](https://github.com/Netflix/dispatch))
|
||||
- [Neon](https://github.com/neondatabase/neon)
|
||||
- [NoneBot](https://github.com/nonebot/nonebot2)
|
||||
- [ONNX](https://github.com/onnx/onnx)
|
||||
- [OpenBB](https://github.com/OpenBB-finance/OpenBBTerminal)
|
||||
- [PDM](https://github.com/pdm-project/pdm)
|
||||
@@ -398,6 +425,7 @@ Ruff is used by a number of major open-source projects and companies, including:
|
||||
- [Pydantic](https://github.com/pydantic/pydantic)
|
||||
- [Pylint](https://github.com/PyCQA/pylint)
|
||||
- [Reflex](https://github.com/reflex-dev/reflex)
|
||||
- [Rippling](https://rippling.com)
|
||||
- [Robyn](https://github.com/sansyrox/robyn)
|
||||
- Scale AI ([Launch SDK](https://github.com/scaleapi/launch-python-client))
|
||||
- Snowflake ([SnowCLI](https://github.com/Snowflake-Labs/snowcli))
|
||||
|
||||
8
assets/badge/format.json
Normal file
8
assets/badge/format.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"label": "code style",
|
||||
"message": "Ruff",
|
||||
"logoSvg": "<svg width=\"510\" height=\"622\" viewBox=\"0 0 510 622\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M206.701 0C200.964 0 196.314 4.64131 196.314 10.3667V41.4667C196.314 47.192 191.663 51.8333 185.927 51.8333H156.843C151.107 51.8333 146.456 56.4746 146.456 62.2V145.133C146.456 150.859 141.806 155.5 136.069 155.5H106.986C101.249 155.5 96.5988 160.141 96.5988 165.867V222.883C96.5988 228.609 91.9484 233.25 86.2118 233.25H57.1283C51.3917 233.25 46.7413 237.891 46.7413 243.617V300.633C46.7413 306.359 42.0909 311 36.3544 311H10.387C4.6504 311 0 315.641 0 321.367V352.467C0 358.192 4.6504 362.833 10.387 362.833H145.418C151.154 362.833 155.804 367.475 155.804 373.2V430.217C155.804 435.942 151.154 440.583 145.418 440.583H116.334C110.597 440.583 105.947 445.225 105.947 450.95V507.967C105.947 513.692 101.297 518.333 95.5601 518.333H66.4766C60.74 518.333 56.0896 522.975 56.0896 528.7V611.633C56.0896 617.359 60.74 622 66.4766 622H149.572C155.309 622 159.959 617.359 159.959 611.633V570.167H201.507C207.244 570.167 211.894 565.525 211.894 559.8V528.7C211.894 522.975 216.544 518.333 222.281 518.333H251.365C257.101 518.333 261.752 513.692 261.752 507.967V476.867C261.752 471.141 266.402 466.5 272.138 466.5H301.222C306.959 466.5 311.609 461.859 311.609 456.133V425.033C311.609 419.308 316.259 414.667 321.996 414.667H351.079C356.816 414.667 361.466 410.025 361.466 404.3V373.2C361.466 367.475 366.117 362.833 371.853 362.833H400.937C406.673 362.833 411.324 358.192 411.324 352.467V321.367C411.324 315.641 415.974 311 421.711 311H450.794C456.531 311 461.181 306.359 461.181 300.633V217.7C461.181 211.975 456.531 207.333 450.794 207.333H420.672C414.936 207.333 410.285 202.692 410.285 196.967V165.867C410.285 160.141 414.936 155.5 420.672 155.5H449.756C455.492 155.5 460.143 150.859 460.143 145.133V114.033C460.143 108.308 464.793 103.667 470.53 103.667H499.613C505.35 103.667 510 99.0253 510 93.3V10.3667C510 4.64132 505.35 0 499.613 0H206.701ZM168.269 440.583C162.532 440.583 157.882 445.225 157.882 450.95V507.967C157.882 513.692 153.231 518.333 147.495 518.333H118.411C112.675 518.333 108.024 522.975 108.024 528.7V559.8C108.024 565.525 112.675 570.167 118.411 570.167H159.959V528.7C159.959 522.975 164.61 518.333 170.346 518.333H199.43C205.166 518.333 209.817 513.692 209.817 507.967V476.867C209.817 471.141 214.467 466.5 220.204 466.5H249.287C255.024 466.5 259.674 461.859 259.674 456.133V425.033C259.674 419.308 264.325 414.667 270.061 414.667H299.145C304.881 414.667 309.532 410.025 309.532 404.3V373.2C309.532 367.475 314.182 362.833 319.919 362.833H349.002C354.739 362.833 359.389 358.192 359.389 352.467V321.367C359.389 315.641 364.039 311 369.776 311H398.859C404.596 311 409.246 306.359 409.246 300.633V269.533C409.246 263.808 404.596 259.167 398.859 259.167H318.88C313.143 259.167 308.493 254.525 308.493 248.8V217.7C308.493 211.975 313.143 207.333 318.88 207.333H347.963C353.7 207.333 358.35 202.692 358.35 196.967V165.867C358.35 160.141 363.001 155.5 368.737 155.5H397.821C403.557 155.5 408.208 150.859 408.208 145.133V114.033C408.208 108.308 412.858 103.667 418.595 103.667H447.678C453.415 103.667 458.065 99.0253 458.065 93.3V62.2C458.065 56.4746 453.415 51.8333 447.678 51.8333H208.778C203.041 51.8333 198.391 56.4746 198.391 62.2V145.133C198.391 150.859 193.741 155.5 188.004 155.5H158.921C153.184 155.5 148.534 160.141 148.534 165.867V222.883C148.534 228.609 143.883 233.25 138.147 233.25H109.063C103.327 233.25 98.6762 237.891 98.6762 243.617V300.633C98.6762 306.359 103.327 311 109.063 311H197.352C203.089 311 207.739 315.641 207.739 321.367V430.217C207.739 435.942 203.089 440.583 197.352 440.583H168.269Z\" fill=\"#D7FF64\"/></svg>",
|
||||
"logoWidth": 10,
|
||||
"labelColor": "grey",
|
||||
"color": "#261230"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "flake8-to-ruff"
|
||||
version = "0.0.286"
|
||||
version = "0.1.3"
|
||||
description = """
|
||||
Convert Flake8 configuration files to Ruff configuration files.
|
||||
"""
|
||||
@@ -13,7 +13,7 @@ repository = { workspace = true }
|
||||
license = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
ruff = { path = "../ruff", default-features = false }
|
||||
ruff_linter = { path = "../ruff_linter", default-features = false }
|
||||
ruff_workspace = { path = "../ruff_workspace" }
|
||||
|
||||
anyhow = { workspace = true }
|
||||
@@ -23,7 +23,7 @@ configparser = { version = "3.0.2" }
|
||||
itertools = { workspace = true }
|
||||
log = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
pep440_rs = { version = "0.3.1", features = ["serde"] }
|
||||
pep440_rs = { version = "0.3.12", features = ["serde"] }
|
||||
regex = { workspace = true }
|
||||
rustc-hash = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
|
||||
@@ -86,7 +86,7 @@ flake8-to-ruff path/to/.flake8 --plugin flake8-builtins --plugin flake8-quotes
|
||||
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
|
||||
[documentation](https://beta.ruff.rs/docs/faq/#how-does-ruff-compare-to-flake8) for the complete
|
||||
[documentation](https://docs.astral.sh/ruff/faq/#how-does-ruff-compare-to-flake8) for the complete
|
||||
list of supported plugins.)
|
||||
|
||||
## License
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! Extract Black configuration settings from a pyproject.toml.
|
||||
|
||||
use ruff::line_width::LineLength;
|
||||
use ruff::settings::types::PythonVersion;
|
||||
use ruff_linter::line_width::LineLength;
|
||||
use ruff_linter::settings::types::PythonVersion;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
|
||||
|
||||
@@ -3,21 +3,22 @@ use std::str::FromStr;
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
use ruff::line_width::LineLength;
|
||||
use ruff::registry::Linter;
|
||||
use ruff::rule_selector::RuleSelector;
|
||||
use ruff::rules::flake8_pytest_style::types::{
|
||||
use ruff_linter::line_width::LineLength;
|
||||
use ruff_linter::registry::Linter;
|
||||
use ruff_linter::rule_selector::RuleSelector;
|
||||
use ruff_linter::rules::flake8_pytest_style::types::{
|
||||
ParametrizeNameType, ParametrizeValuesRowType, ParametrizeValuesType,
|
||||
};
|
||||
use ruff::rules::flake8_quotes::settings::Quote;
|
||||
use ruff::rules::flake8_tidy_imports::settings::Strictness;
|
||||
use ruff::rules::pydocstyle::settings::Convention;
|
||||
use ruff::settings::types::PythonVersion;
|
||||
use ruff::warn_user;
|
||||
use ruff_linter::rules::flake8_quotes::settings::Quote;
|
||||
use ruff_linter::rules::flake8_tidy_imports::settings::Strictness;
|
||||
use ruff_linter::rules::pydocstyle::settings::Convention;
|
||||
use ruff_linter::settings::types::PythonVersion;
|
||||
use ruff_linter::settings::DEFAULT_SELECTORS;
|
||||
use ruff_linter::warn_user;
|
||||
use ruff_workspace::options::{
|
||||
Flake8AnnotationsOptions, Flake8BugbearOptions, Flake8BuiltinsOptions, Flake8ErrMsgOptions,
|
||||
Flake8PytestStyleOptions, Flake8QuotesOptions, Flake8TidyImportsOptions, McCabeOptions,
|
||||
Options, Pep8NamingOptions, PydocstyleOptions,
|
||||
Flake8PytestStyleOptions, Flake8QuotesOptions, Flake8TidyImportsOptions, LintCommonOptions,
|
||||
LintOptions, McCabeOptions, Options, Pep8NamingOptions, PydocstyleOptions,
|
||||
};
|
||||
use ruff_workspace::pyproject::Pyproject;
|
||||
|
||||
@@ -25,11 +26,6 @@ use super::external_config::ExternalConfig;
|
||||
use super::plugin::Plugin;
|
||||
use super::{parser, plugin};
|
||||
|
||||
const DEFAULT_SELECTORS: &[RuleSelector] = &[
|
||||
RuleSelector::Linter(Linter::Pyflakes),
|
||||
RuleSelector::Linter(Linter::Pycodestyle),
|
||||
];
|
||||
|
||||
pub(crate) fn convert(
|
||||
config: &HashMap<String, HashMap<String, Option<String>>>,
|
||||
external_config: &ExternalConfig,
|
||||
@@ -103,6 +99,7 @@ pub(crate) fn convert(
|
||||
|
||||
// Parse each supported option.
|
||||
let mut options = Options::default();
|
||||
let mut lint_options = LintCommonOptions::default();
|
||||
let mut flake8_annotations = Flake8AnnotationsOptions::default();
|
||||
let mut flake8_bugbear = Flake8BugbearOptions::default();
|
||||
let mut flake8_builtins = Flake8BuiltinsOptions::default();
|
||||
@@ -150,7 +147,7 @@ pub(crate) fn convert(
|
||||
"per-file-ignores" | "per_file_ignores" => {
|
||||
match parser::parse_files_to_codes_mapping(value.as_ref()) {
|
||||
Ok(per_file_ignores) => {
|
||||
options.per_file_ignores =
|
||||
lint_options.per_file_ignores =
|
||||
Some(parser::collect_per_file_ignores(per_file_ignores));
|
||||
}
|
||||
Err(e) => {
|
||||
@@ -358,47 +355,47 @@ pub(crate) fn convert(
|
||||
}
|
||||
|
||||
// Deduplicate and sort.
|
||||
options.select = Some(
|
||||
lint_options.select = Some(
|
||||
select
|
||||
.into_iter()
|
||||
.sorted_by_key(RuleSelector::prefix_and_code)
|
||||
.collect(),
|
||||
);
|
||||
options.ignore = Some(
|
||||
lint_options.ignore = Some(
|
||||
ignore
|
||||
.into_iter()
|
||||
.sorted_by_key(RuleSelector::prefix_and_code)
|
||||
.collect(),
|
||||
);
|
||||
if flake8_annotations != Flake8AnnotationsOptions::default() {
|
||||
options.flake8_annotations = Some(flake8_annotations);
|
||||
lint_options.flake8_annotations = Some(flake8_annotations);
|
||||
}
|
||||
if flake8_bugbear != Flake8BugbearOptions::default() {
|
||||
options.flake8_bugbear = Some(flake8_bugbear);
|
||||
lint_options.flake8_bugbear = Some(flake8_bugbear);
|
||||
}
|
||||
if flake8_builtins != Flake8BuiltinsOptions::default() {
|
||||
options.flake8_builtins = Some(flake8_builtins);
|
||||
lint_options.flake8_builtins = Some(flake8_builtins);
|
||||
}
|
||||
if flake8_errmsg != Flake8ErrMsgOptions::default() {
|
||||
options.flake8_errmsg = Some(flake8_errmsg);
|
||||
lint_options.flake8_errmsg = Some(flake8_errmsg);
|
||||
}
|
||||
if flake8_pytest_style != Flake8PytestStyleOptions::default() {
|
||||
options.flake8_pytest_style = Some(flake8_pytest_style);
|
||||
lint_options.flake8_pytest_style = Some(flake8_pytest_style);
|
||||
}
|
||||
if flake8_quotes != Flake8QuotesOptions::default() {
|
||||
options.flake8_quotes = Some(flake8_quotes);
|
||||
lint_options.flake8_quotes = Some(flake8_quotes);
|
||||
}
|
||||
if flake8_tidy_imports != Flake8TidyImportsOptions::default() {
|
||||
options.flake8_tidy_imports = Some(flake8_tidy_imports);
|
||||
lint_options.flake8_tidy_imports = Some(flake8_tidy_imports);
|
||||
}
|
||||
if mccabe != McCabeOptions::default() {
|
||||
options.mccabe = Some(mccabe);
|
||||
lint_options.mccabe = Some(mccabe);
|
||||
}
|
||||
if pep8_naming != Pep8NamingOptions::default() {
|
||||
options.pep8_naming = Some(pep8_naming);
|
||||
lint_options.pep8_naming = Some(pep8_naming);
|
||||
}
|
||||
if pydocstyle != PydocstyleOptions::default() {
|
||||
options.pydocstyle = Some(pydocstyle);
|
||||
lint_options.pydocstyle = Some(pydocstyle);
|
||||
}
|
||||
|
||||
// Extract any settings from the existing `pyproject.toml`.
|
||||
@@ -436,6 +433,13 @@ pub(crate) fn convert(
|
||||
}
|
||||
}
|
||||
|
||||
if lint_options != LintCommonOptions::default() {
|
||||
options.lint = Some(LintOptions {
|
||||
common: lint_options,
|
||||
..LintOptions::default()
|
||||
});
|
||||
}
|
||||
|
||||
// Create the pyproject.toml.
|
||||
Pyproject::new(options)
|
||||
}
|
||||
@@ -458,13 +462,15 @@ mod tests {
|
||||
use pep440_rs::VersionSpecifiers;
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
use ruff::line_width::LineLength;
|
||||
use ruff::registry::Linter;
|
||||
use ruff::rule_selector::RuleSelector;
|
||||
use ruff::rules::flake8_quotes;
|
||||
use ruff::rules::pydocstyle::settings::Convention;
|
||||
use ruff::settings::types::PythonVersion;
|
||||
use ruff_workspace::options::{Flake8QuotesOptions, Options, PydocstyleOptions};
|
||||
use ruff_linter::line_width::LineLength;
|
||||
use ruff_linter::registry::Linter;
|
||||
use ruff_linter::rule_selector::RuleSelector;
|
||||
use ruff_linter::rules::flake8_quotes;
|
||||
use ruff_linter::rules::pydocstyle::settings::Convention;
|
||||
use ruff_linter::settings::types::PythonVersion;
|
||||
use ruff_workspace::options::{
|
||||
Flake8QuotesOptions, LintCommonOptions, LintOptions, Options, PydocstyleOptions,
|
||||
};
|
||||
use ruff_workspace::pyproject::Pyproject;
|
||||
|
||||
use crate::converter::DEFAULT_SELECTORS;
|
||||
@@ -474,8 +480,8 @@ mod tests {
|
||||
use super::super::plugin::Plugin;
|
||||
use super::convert;
|
||||
|
||||
fn default_options(plugins: impl IntoIterator<Item = RuleSelector>) -> Options {
|
||||
Options {
|
||||
fn lint_default_options(plugins: impl IntoIterator<Item = RuleSelector>) -> LintCommonOptions {
|
||||
LintCommonOptions {
|
||||
ignore: Some(vec![]),
|
||||
select: Some(
|
||||
DEFAULT_SELECTORS
|
||||
@@ -485,7 +491,7 @@ mod tests {
|
||||
.sorted_by_key(RuleSelector::prefix_and_code)
|
||||
.collect(),
|
||||
),
|
||||
..Options::default()
|
||||
..LintCommonOptions::default()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -496,7 +502,13 @@ mod tests {
|
||||
&ExternalConfig::default(),
|
||||
None,
|
||||
);
|
||||
let expected = Pyproject::new(default_options([]));
|
||||
let expected = Pyproject::new(Options {
|
||||
lint: Some(LintOptions {
|
||||
common: lint_default_options([]),
|
||||
..LintOptions::default()
|
||||
}),
|
||||
..Options::default()
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@@ -512,7 +524,11 @@ mod tests {
|
||||
);
|
||||
let expected = Pyproject::new(Options {
|
||||
line_length: Some(LineLength::try_from(100).unwrap()),
|
||||
..default_options([])
|
||||
lint: Some(LintOptions {
|
||||
common: lint_default_options([]),
|
||||
..LintOptions::default()
|
||||
}),
|
||||
..Options::default()
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
@@ -529,7 +545,11 @@ mod tests {
|
||||
);
|
||||
let expected = Pyproject::new(Options {
|
||||
line_length: Some(LineLength::try_from(100).unwrap()),
|
||||
..default_options([])
|
||||
lint: Some(LintOptions {
|
||||
common: lint_default_options([]),
|
||||
..LintOptions::default()
|
||||
}),
|
||||
..Options::default()
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
@@ -544,7 +564,13 @@ mod tests {
|
||||
&ExternalConfig::default(),
|
||||
Some(vec![]),
|
||||
);
|
||||
let expected = Pyproject::new(default_options([]));
|
||||
let expected = Pyproject::new(Options {
|
||||
lint: Some(LintOptions {
|
||||
common: lint_default_options([]),
|
||||
..LintOptions::default()
|
||||
}),
|
||||
..Options::default()
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
@@ -559,13 +585,19 @@ mod tests {
|
||||
Some(vec![]),
|
||||
);
|
||||
let expected = Pyproject::new(Options {
|
||||
flake8_quotes: Some(Flake8QuotesOptions {
|
||||
inline_quotes: Some(flake8_quotes::settings::Quote::Single),
|
||||
multiline_quotes: None,
|
||||
docstring_quotes: None,
|
||||
avoid_escape: None,
|
||||
lint: Some(LintOptions {
|
||||
common: LintCommonOptions {
|
||||
flake8_quotes: Some(Flake8QuotesOptions {
|
||||
inline_quotes: Some(flake8_quotes::settings::Quote::Single),
|
||||
multiline_quotes: None,
|
||||
docstring_quotes: None,
|
||||
avoid_escape: None,
|
||||
}),
|
||||
..lint_default_options([])
|
||||
},
|
||||
..LintOptions::default()
|
||||
}),
|
||||
..default_options([])
|
||||
..Options::default()
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
@@ -584,12 +616,18 @@ mod tests {
|
||||
Some(vec![Plugin::Flake8Docstrings]),
|
||||
);
|
||||
let expected = Pyproject::new(Options {
|
||||
pydocstyle: Some(PydocstyleOptions {
|
||||
convention: Some(Convention::Numpy),
|
||||
ignore_decorators: None,
|
||||
property_decorators: None,
|
||||
lint: Some(LintOptions {
|
||||
common: LintCommonOptions {
|
||||
pydocstyle: Some(PydocstyleOptions {
|
||||
convention: Some(Convention::Numpy),
|
||||
ignore_decorators: None,
|
||||
property_decorators: None,
|
||||
}),
|
||||
..lint_default_options([Linter::Pydocstyle.into()])
|
||||
},
|
||||
..LintOptions::default()
|
||||
}),
|
||||
..default_options([Linter::Pydocstyle.into()])
|
||||
..Options::default()
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
@@ -605,13 +643,19 @@ mod tests {
|
||||
None,
|
||||
);
|
||||
let expected = Pyproject::new(Options {
|
||||
flake8_quotes: Some(Flake8QuotesOptions {
|
||||
inline_quotes: Some(flake8_quotes::settings::Quote::Single),
|
||||
multiline_quotes: None,
|
||||
docstring_quotes: None,
|
||||
avoid_escape: None,
|
||||
lint: Some(LintOptions {
|
||||
common: LintCommonOptions {
|
||||
flake8_quotes: Some(Flake8QuotesOptions {
|
||||
inline_quotes: Some(flake8_quotes::settings::Quote::Single),
|
||||
multiline_quotes: None,
|
||||
docstring_quotes: None,
|
||||
avoid_escape: None,
|
||||
}),
|
||||
..lint_default_options([Linter::Flake8Quotes.into()])
|
||||
},
|
||||
..LintOptions::default()
|
||||
}),
|
||||
..default_options([Linter::Flake8Quotes.into()])
|
||||
..Options::default()
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
@@ -630,7 +674,11 @@ mod tests {
|
||||
);
|
||||
let expected = Pyproject::new(Options {
|
||||
target_version: Some(PythonVersion::Py38),
|
||||
..default_options([])
|
||||
lint: Some(LintOptions {
|
||||
common: lint_default_options([]),
|
||||
..LintOptions::default()
|
||||
}),
|
||||
..Options::default()
|
||||
});
|
||||
assert_eq!(actual, expected);
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ use crate::converter::convert;
|
||||
use crate::external_config::ExternalConfig;
|
||||
use crate::plugin::Plugin;
|
||||
use crate::pyproject::parse;
|
||||
use ruff::logging::{set_up_logging, LogLevel};
|
||||
use ruff_linter::logging::{set_up_logging, LogLevel};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(
|
||||
|
||||
@@ -3,10 +3,11 @@ use std::str::FromStr;
|
||||
use anyhow::{bail, Result};
|
||||
use once_cell::sync::Lazy;
|
||||
use regex::Regex;
|
||||
use ruff::settings::types::PatternPrefixPair;
|
||||
use ruff::{warn_user, RuleSelector};
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use ruff_linter::settings::types::PatternPrefixPair;
|
||||
use ruff_linter::{warn_user, RuleSelector};
|
||||
|
||||
static COMMA_SEPARATED_LIST_RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"[,\s]").unwrap());
|
||||
|
||||
/// Parse a comma-separated list of `RuleSelector` values (e.g.,
|
||||
@@ -183,7 +184,7 @@ pub(crate) fn collect_per_file_ignores(
|
||||
for pair in pairs {
|
||||
per_file_ignores
|
||||
.entry(pair.pattern)
|
||||
.or_insert_with(Vec::new)
|
||||
.or_default()
|
||||
.push(pair.prefix);
|
||||
}
|
||||
per_file_ignores
|
||||
@@ -192,11 +193,11 @@ pub(crate) fn collect_per_file_ignores(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use anyhow::Result;
|
||||
use ruff::RuleSelector;
|
||||
|
||||
use ruff::codes;
|
||||
use ruff::registry::Linter;
|
||||
use ruff::settings::types::PatternPrefixPair;
|
||||
use ruff_linter::codes;
|
||||
use ruff_linter::registry::Linter;
|
||||
use ruff_linter::settings::types::PatternPrefixPair;
|
||||
use ruff_linter::RuleSelector;
|
||||
|
||||
use super::{parse_files_to_codes_mapping, parse_prefix_codes, parse_strings};
|
||||
|
||||
|
||||
@@ -3,8 +3,9 @@ use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use ruff::registry::Linter;
|
||||
use ruff::RuleSelector;
|
||||
use ruff_linter::registry::Linter;
|
||||
use ruff_linter::rule_selector::PreviewOptions;
|
||||
use ruff_linter::RuleSelector;
|
||||
|
||||
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
|
||||
pub enum Plugin {
|
||||
@@ -331,7 +332,7 @@ pub(crate) fn infer_plugins_from_codes(selectors: &HashSet<RuleSelector>) -> Vec
|
||||
.filter(|plugin| {
|
||||
for selector in selectors {
|
||||
if selector
|
||||
.into_iter()
|
||||
.rules(&PreviewOptions::default())
|
||||
.any(|rule| Linter::from(plugin).rules().any(|r| r == rule))
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
[package]
|
||||
name = "ruff"
|
||||
version = "0.0.286"
|
||||
publish = false
|
||||
authors = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
rust-version = { workspace = true }
|
||||
homepage = { workspace = true }
|
||||
documentation = { workspace = true }
|
||||
repository = { workspace = true }
|
||||
license = { workspace = true }
|
||||
readme = "README.md"
|
||||
|
||||
[lib]
|
||||
name = "ruff"
|
||||
|
||||
[dependencies]
|
||||
ruff_cache = { path = "../ruff_cache" }
|
||||
ruff_diagnostics = { path = "../ruff_diagnostics", features = ["serde"] }
|
||||
ruff_index = { path = "../ruff_index" }
|
||||
ruff_macros = { path = "../ruff_macros" }
|
||||
ruff_python_ast = { path = "../ruff_python_ast", features = ["serde"] }
|
||||
ruff_python_codegen = { path = "../ruff_python_codegen" }
|
||||
ruff_python_index = { path = "../ruff_python_index" }
|
||||
ruff_python_literal = { path = "../ruff_python_literal" }
|
||||
ruff_python_semantic = { path = "../ruff_python_semantic" }
|
||||
ruff_python_stdlib = { path = "../ruff_python_stdlib" }
|
||||
ruff_python_trivia = { path = "../ruff_python_trivia" }
|
||||
ruff_python_parser = { path = "../ruff_python_parser" }
|
||||
ruff_source_file = { path = "../ruff_source_file", features = ["serde"] }
|
||||
ruff_text_size = { path = "../ruff_text_size" }
|
||||
|
||||
annotate-snippets = { version = "0.9.1", features = ["color"] }
|
||||
anyhow = { workspace = true }
|
||||
bitflags = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
clap = { workspace = true, features = ["derive", "string"], optional = true }
|
||||
colored = { workspace = true }
|
||||
fern = { version = "0.6.1" }
|
||||
glob = { workspace = true }
|
||||
globset = { workspace = true }
|
||||
imperative = { version = "1.0.4" }
|
||||
is-macro = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
libcst = { workspace = true }
|
||||
log = { workspace = true }
|
||||
memchr = { workspace = true }
|
||||
natord = { version = "1.0.9" }
|
||||
num-bigint = { workspace = true }
|
||||
num-traits = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
path-absolutize = { workspace = true, features = [
|
||||
"once_cell_cache",
|
||||
"use_unix_paths_on_wasm",
|
||||
] }
|
||||
pathdiff = { version = "0.2.1" }
|
||||
pep440_rs = { version = "0.3.1", features = ["serde"] }
|
||||
pyproject-toml = { version = "0.6.0" }
|
||||
quick-junit = { version = "0.3.2" }
|
||||
regex = { workspace = true }
|
||||
result-like = { version = "0.4.6" }
|
||||
rustc-hash = { workspace = true }
|
||||
schemars = { workspace = true, optional = true }
|
||||
semver = { version = "1.0.16" }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
serde_with = { version = "3.0.0" }
|
||||
similar = { workspace = true }
|
||||
smallvec = { workspace = true }
|
||||
strum = { workspace = true }
|
||||
strum_macros = { workspace = true }
|
||||
thiserror = { version = "1.0.43" }
|
||||
toml = { workspace = true }
|
||||
typed-arena = { version = "2.0.2" }
|
||||
unicode-width = { workspace = true }
|
||||
unicode_names2 = { version = "0.6.0", git = "https://github.com/youknowone/unicode_names2.git", rev = "4ce16aa85cbcdd9cc830410f1a72ef9a235f2fde" }
|
||||
uuid = { workspace = true, features = ["v4", "fast-rng", "macro-diagnostics", "js"] }
|
||||
wsl = { version = "0.1.0" }
|
||||
|
||||
[dev-dependencies]
|
||||
insta = { workspace = true }
|
||||
pretty_assertions = "1.3.0"
|
||||
test-case = { workspace = true }
|
||||
# Disable colored output in tests
|
||||
colored = { workspace = true, features = ["no-color"] }
|
||||
tempfile = "3.6.0"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
schemars = ["dep:schemars"]
|
||||
# Enables the UnreachableCode rule
|
||||
unreachable-code = []
|
||||
@@ -1,45 +0,0 @@
|
||||
"""
|
||||
Should emit:
|
||||
B009 - Line 19, 20, 21, 22, 23, 24
|
||||
B010 - Line 40, 41, 42, 43, 44, 45
|
||||
"""
|
||||
|
||||
# Valid getattr usage
|
||||
getattr(foo, bar)
|
||||
getattr(foo, "bar", None)
|
||||
getattr(foo, "bar{foo}".format(foo="a"), None)
|
||||
getattr(foo, "bar{foo}".format(foo="a"))
|
||||
getattr(foo, bar, None)
|
||||
getattr(foo, "123abc")
|
||||
getattr(foo, r"123\abc")
|
||||
getattr(foo, "except")
|
||||
getattr(foo, "__123abc")
|
||||
|
||||
# Invalid usage
|
||||
getattr(foo, "bar")
|
||||
getattr(foo, "_123abc")
|
||||
getattr(foo, "__123abc__")
|
||||
getattr(foo, "abc123")
|
||||
getattr(foo, r"abc123")
|
||||
_ = lambda x: getattr(x, "bar")
|
||||
if getattr(x, "bar"):
|
||||
pass
|
||||
|
||||
# Valid setattr usage
|
||||
setattr(foo, bar, None)
|
||||
setattr(foo, "bar{foo}".format(foo="a"), None)
|
||||
setattr(foo, "123abc", None)
|
||||
setattr(foo, "__123abc", None)
|
||||
setattr(foo, r"123\abc", None)
|
||||
setattr(foo, "except", None)
|
||||
_ = lambda x: setattr(x, "bar", 1)
|
||||
if setattr(x, "bar", 1):
|
||||
pass
|
||||
|
||||
# Invalid usage
|
||||
setattr(foo, "bar", None)
|
||||
setattr(foo, "_123abc", None)
|
||||
setattr(foo, "__123abc__", None)
|
||||
setattr(foo, "abc123", None)
|
||||
setattr(foo, r"abc123", None)
|
||||
setattr(foo.bar, r"baz", None)
|
||||
@@ -1,8 +0,0 @@
|
||||
try:
|
||||
pass
|
||||
except (ValueError,):
|
||||
pass
|
||||
except AttributeError:
|
||||
pass
|
||||
except (ImportError, TypeError):
|
||||
pass
|
||||
@@ -1,18 +0,0 @@
|
||||
dict((x, x) for x in range(3))
|
||||
dict(
|
||||
(x, x) for x in range(3)
|
||||
)
|
||||
dict(((x, x) for x in range(3)), z=3)
|
||||
y = f'{dict((x, x) for x in range(3))}'
|
||||
print(f'Hello {dict((x, x) for x in range(3))} World')
|
||||
print(f"Hello {dict((x, x) for x in 'abc')} World")
|
||||
print(f'Hello {dict((x, x) for x in "abc")} World')
|
||||
print(f'Hello {dict((x,x) for x in "abc")} World')
|
||||
|
||||
f'{dict((x, x) for x in range(3)) | dict((x, x) for x in range(3))}'
|
||||
f'{ dict((x, x) for x in range(3)) | dict((x, x) for x in range(3)) }'
|
||||
|
||||
def f(x):
|
||||
return x
|
||||
|
||||
print(f'Hello {dict((x,f(x)) for x in "abc")} World')
|
||||
@@ -1,13 +0,0 @@
|
||||
dict([(i, i) for i in range(3)])
|
||||
dict([(i, i) for i in range(3)], z=4)
|
||||
|
||||
def f(x):
|
||||
return x
|
||||
|
||||
f'{dict([(s,s) for s in "ab"])}'
|
||||
f"{dict([(s,s) for s in 'ab'])}"
|
||||
f"{dict([(s, s) for s in 'ab'])}"
|
||||
f"{dict([(s,f(s)) for s in 'ab'])}"
|
||||
|
||||
f'{dict([(s,s) for s in "ab"]) | dict([(s,s) for s in "ab"])}'
|
||||
f'{ dict([(s,s) for s in "ab"]) | dict([(s,s) for s in "ab"]) }'
|
||||
@@ -1,15 +0,0 @@
|
||||
x = [2, 3, 1]
|
||||
list(x)
|
||||
list(sorted(x))
|
||||
reversed(sorted(x))
|
||||
reversed(sorted(x, key=lambda e: e))
|
||||
reversed(sorted(x, reverse=True))
|
||||
reversed(sorted(x, key=lambda e: e, reverse=True))
|
||||
reversed(sorted(x, reverse=True, key=lambda e: e))
|
||||
reversed(sorted(x, reverse=False))
|
||||
|
||||
def reversed(*args, **kwargs):
|
||||
return None
|
||||
|
||||
|
||||
reversed(sorted(x, reverse=True))
|
||||
@@ -1,34 +0,0 @@
|
||||
x = [1, 2, 3]
|
||||
list(list(x))
|
||||
list(tuple(x))
|
||||
tuple(list(x))
|
||||
tuple(tuple(x))
|
||||
set(set(x))
|
||||
set(list(x))
|
||||
set(tuple(x))
|
||||
set(sorted(x))
|
||||
set(sorted(x, key=lambda y: y))
|
||||
set(reversed(x))
|
||||
sorted(list(x))
|
||||
sorted(tuple(x))
|
||||
sorted(sorted(x))
|
||||
sorted(sorted(x, key=foo, reverse=False), reverse=False, key=foo)
|
||||
sorted(sorted(x, reverse=True), reverse=True)
|
||||
sorted(reversed(x))
|
||||
sorted(list(x), key=lambda y: y)
|
||||
tuple(
|
||||
list(
|
||||
[x, 3, "hell"\
|
||||
"o"]
|
||||
)
|
||||
)
|
||||
set(set())
|
||||
set(list())
|
||||
set(tuple())
|
||||
sorted(reversed())
|
||||
|
||||
# Nested sorts with differing keyword arguments. Not flagged.
|
||||
sorted(sorted(x, key=lambda y: y))
|
||||
sorted(sorted(x, key=lambda y: y), key=lambda x: x)
|
||||
sorted(sorted(x), reverse=True)
|
||||
sorted(sorted(x, reverse=False), reverse=True)
|
||||
@@ -1,19 +0,0 @@
|
||||
x = [1, 2, 3]
|
||||
y = [("a", 1), ("b", 2), ("c", 3)]
|
||||
z = [(1,), (2,), (3,)]
|
||||
d = {"a": 1, "b": 2, "c": 3}
|
||||
|
||||
[i for i in x]
|
||||
{i for i in x}
|
||||
{k: v for k, v in y}
|
||||
{k: v for k, v in d.items()}
|
||||
|
||||
[i for i, in z]
|
||||
[i for i, j in y]
|
||||
[i for i in x if i > 1]
|
||||
[i for i in x for j in x]
|
||||
|
||||
{v: k for k, v in y}
|
||||
{k.foo: k for k in y}
|
||||
{k["foo"]: k for k in y}
|
||||
{k: v if v else None for k, v in y}
|
||||
@@ -1,61 +0,0 @@
|
||||
_ = "a" "b" "c"
|
||||
|
||||
_ = "abc" + "def"
|
||||
|
||||
_ = "abc" \
|
||||
"def"
|
||||
|
||||
_ = (
|
||||
"abc" +
|
||||
"def"
|
||||
)
|
||||
|
||||
_ = (
|
||||
f"abc" +
|
||||
"def"
|
||||
)
|
||||
|
||||
_ = (
|
||||
b"abc" +
|
||||
b"def"
|
||||
)
|
||||
|
||||
_ = (
|
||||
"abc"
|
||||
"def"
|
||||
)
|
||||
|
||||
_ = (
|
||||
f"abc"
|
||||
"def"
|
||||
)
|
||||
|
||||
_ = (
|
||||
b"abc"
|
||||
b"def"
|
||||
)
|
||||
|
||||
_ = """a""" """b"""
|
||||
|
||||
_ = """a
|
||||
b""" """c
|
||||
d"""
|
||||
|
||||
_ = f"""a""" f"""b"""
|
||||
|
||||
_ = f"a" "b"
|
||||
|
||||
_ = """a""" "b"
|
||||
|
||||
_ = 'a' "b"
|
||||
|
||||
_ = rf"a" rf"b"
|
||||
|
||||
# Single-line explicit concatenation should be ignored.
|
||||
_ = "abc" + "def" + "ghi"
|
||||
_ = foo + "abc" + "def"
|
||||
_ = "abc" + foo + "def"
|
||||
_ = "abc" + "def" + foo
|
||||
_ = foo + bar + "abc"
|
||||
_ = "abc" + foo + bar
|
||||
_ = foo + "abc" + bar
|
||||
@@ -1,18 +0,0 @@
|
||||
import logging
|
||||
import logging as foo
|
||||
|
||||
logging.info("Hello {}".format("World!"))
|
||||
logging.log(logging.INFO, "Hello {}".format("World!"))
|
||||
foo.info("Hello {}".format("World!"))
|
||||
logging.log(logging.INFO, msg="Hello {}".format("World!"))
|
||||
logging.log(level=logging.INFO, msg="Hello {}".format("World!"))
|
||||
logging.log(msg="Hello {}".format("World!"), level=logging.INFO)
|
||||
|
||||
# Flask support
|
||||
import flask
|
||||
from flask import current_app
|
||||
from flask import current_app as app
|
||||
|
||||
flask.current_app.logger.info("Hello {}".format("World!"))
|
||||
current_app.logger.info("Hello {}".format("World!"))
|
||||
app.logger.log(logging.INFO, "Hello {}".format("World!"))
|
||||
@@ -1,4 +0,0 @@
|
||||
import logging
|
||||
|
||||
logging.info("Hello %s" % "World!")
|
||||
logging.log(logging.INFO, "Hello %s" % "World!")
|
||||
@@ -1,4 +0,0 @@
|
||||
import logging
|
||||
|
||||
logging.info("Hello" + " " + "World!")
|
||||
logging.log(logging.INFO, "Hello" + " " + "World!")
|
||||
@@ -1,8 +0,0 @@
|
||||
import logging
|
||||
|
||||
name = "world"
|
||||
logging.info(f"Hello {name}")
|
||||
logging.log(logging.INFO, f"Hello {name}")
|
||||
|
||||
_LOGGER = logging.getLogger()
|
||||
_LOGGER.info(f"{__name__}")
|
||||
@@ -1,10 +0,0 @@
|
||||
import logging
|
||||
from distutils import log
|
||||
|
||||
from logging_setup import logger
|
||||
|
||||
logging.warn("Hello World!")
|
||||
log.warn("Hello world!") # This shouldn't be considered as a logger candidate
|
||||
logger.warn("Hello world!")
|
||||
|
||||
logging . warn("Hello World!")
|
||||
@@ -1,8 +0,0 @@
|
||||
import logging
|
||||
|
||||
logging.info(
|
||||
"Hello world!",
|
||||
extra={
|
||||
"name": "foobar",
|
||||
},
|
||||
)
|
||||
@@ -1,8 +0,0 @@
|
||||
import logging
|
||||
|
||||
logging.info(
|
||||
"Hello world!",
|
||||
extra=dict(
|
||||
name="foobar",
|
||||
),
|
||||
)
|
||||
@@ -1,21 +0,0 @@
|
||||
import logging
|
||||
import sys
|
||||
|
||||
# G201
|
||||
try:
|
||||
pass
|
||||
except:
|
||||
logging.error("Hello World", exc_info=True)
|
||||
|
||||
try:
|
||||
pass
|
||||
except:
|
||||
logging.error("Hello World", exc_info=sys.exc_info())
|
||||
|
||||
# OK
|
||||
try:
|
||||
pass
|
||||
except:
|
||||
logging.error("Hello World", exc_info=False)
|
||||
|
||||
logging.error("Hello World", exc_info=sys.exc_info())
|
||||
@@ -1,21 +0,0 @@
|
||||
import logging
|
||||
import sys
|
||||
|
||||
# G202
|
||||
try:
|
||||
pass
|
||||
except:
|
||||
logging.exception("Hello World", exc_info=True)
|
||||
|
||||
try:
|
||||
pass
|
||||
except:
|
||||
logging.exception("Hello World", exc_info=sys.exc_info())
|
||||
|
||||
# OK
|
||||
try:
|
||||
pass
|
||||
except:
|
||||
logging.exception("Hello World", exc_info=False)
|
||||
|
||||
logging.exception("Hello World", exc_info=True)
|
||||
@@ -1,18 +0,0 @@
|
||||
def bar():
|
||||
... # OK
|
||||
|
||||
|
||||
def foo():
|
||||
"""foo""" # OK
|
||||
|
||||
|
||||
def buzz():
|
||||
print("buzz") # OK, not in stub file
|
||||
|
||||
|
||||
def foo2():
|
||||
123 # OK, not in a stub file
|
||||
|
||||
|
||||
def bizz():
|
||||
x = 123 # OK, not in a stub file
|
||||
@@ -1,12 +0,0 @@
|
||||
def bar(): ... # OK
|
||||
def foo():
|
||||
"""foo""" # OK, strings are handled by another rule
|
||||
|
||||
def buzz():
|
||||
print("buzz") # ERROR PYI010
|
||||
|
||||
def foo2():
|
||||
123 # ERROR PYI010
|
||||
|
||||
def bizz():
|
||||
x = 123 # ERROR PYI010
|
||||
@@ -1,19 +0,0 @@
|
||||
def bar(): # OK
|
||||
...
|
||||
|
||||
|
||||
def oof(): # OK, docstrings are handled by another rule
|
||||
"""oof"""
|
||||
print("foo")
|
||||
|
||||
|
||||
def foo(): # Ok not in Stub file
|
||||
"""foo"""
|
||||
print("foo")
|
||||
print("foo")
|
||||
|
||||
|
||||
def buzz(): # Ok not in Stub file
|
||||
print("fizz")
|
||||
print("buzz")
|
||||
print("test")
|
||||
@@ -1,20 +0,0 @@
|
||||
def bar():
|
||||
... # OK
|
||||
|
||||
|
||||
def oof(): # OK, docstrings are handled by another rule
|
||||
"""oof"""
|
||||
print("foo")
|
||||
|
||||
|
||||
|
||||
def foo(): # ERROR PYI048
|
||||
"""foo"""
|
||||
print("foo")
|
||||
print("foo")
|
||||
|
||||
|
||||
def buzz(): # ERROR PYI048
|
||||
print("fizz")
|
||||
print("buzz")
|
||||
print("test")
|
||||
@@ -1,31 +0,0 @@
|
||||
import builtins
|
||||
from typing import Union
|
||||
|
||||
w: builtins.type[int] | builtins.type[str] | builtins.type[complex]
|
||||
x: type[int] | type[str] | type[float]
|
||||
y: builtins.type[int] | type[str] | builtins.type[complex]
|
||||
z: Union[type[float], type[complex]]
|
||||
z: Union[type[float, int], type[complex]]
|
||||
|
||||
|
||||
def func(arg: type[int] | str | type[float]) -> None:
|
||||
...
|
||||
|
||||
|
||||
# OK
|
||||
x: type[int, str, float]
|
||||
y: builtins.type[int, str, complex]
|
||||
z: Union[float, complex]
|
||||
|
||||
|
||||
def func(arg: type[int, float] | str) -> None:
|
||||
...
|
||||
|
||||
|
||||
# OK
|
||||
item: type[requests_mock.Mocker] | type[httpretty] = requests_mock.Mocker
|
||||
|
||||
|
||||
def func():
|
||||
# PYI055
|
||||
item: type[requests_mock.Mocker] | type[httpretty] = requests_mock.Mocker
|
||||
@@ -1,54 +0,0 @@
|
||||
import pytest
|
||||
|
||||
|
||||
def test_ok():
|
||||
assert something
|
||||
assert something or something_else
|
||||
assert something or something_else and something_third
|
||||
assert not (something and something_else)
|
||||
assert something, "something message"
|
||||
assert something or something_else and something_third, "another message"
|
||||
|
||||
|
||||
def test_error():
|
||||
assert something and something_else
|
||||
assert something and something_else and something_third
|
||||
assert something and not something_else
|
||||
assert something and (something_else or something_third)
|
||||
assert not something and something_else
|
||||
assert not (something or something_else)
|
||||
assert not (something or something_else or something_third)
|
||||
assert something and something_else == """error
|
||||
message
|
||||
"""
|
||||
assert (
|
||||
something
|
||||
and something_else
|
||||
== """error
|
||||
message
|
||||
"""
|
||||
)
|
||||
|
||||
# recursive case
|
||||
assert not (a or not (b or c))
|
||||
assert not (a or not (b and c))
|
||||
|
||||
# detected, but no autofix for messages
|
||||
assert something and something_else, "error message"
|
||||
assert not (something or something_else and something_third), "with message"
|
||||
# detected, but no autofix for mixed conditions (e.g. `a or b and c`)
|
||||
assert not (something or something_else and something_third)
|
||||
|
||||
|
||||
assert something # OK
|
||||
assert something and something_else # Error
|
||||
assert something and something_else and something_third # Error
|
||||
|
||||
|
||||
def test_multiline():
|
||||
assert something and something_else; x = 1
|
||||
|
||||
x = 1; assert something and something_else
|
||||
|
||||
x = 1; \
|
||||
assert something and something_else
|
||||
@@ -1,17 +0,0 @@
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def ok_complex_logic():
|
||||
if some_condition:
|
||||
resource = acquire_resource()
|
||||
yield resource
|
||||
resource.release()
|
||||
return
|
||||
yield None
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def error():
|
||||
resource = acquire_resource()
|
||||
yield resource
|
||||
@@ -1,11 +0,0 @@
|
||||
this_should_raise_Q003 = 'This is a \'string\''
|
||||
this_should_raise_Q003 = 'This is \\ a \\\'string\''
|
||||
this_is_fine = '"This" is a \'string\''
|
||||
this_is_fine = "This is a 'string'"
|
||||
this_is_fine = "\"This\" is a 'string'"
|
||||
this_is_fine = r'This is a \'string\''
|
||||
this_is_fine = R'This is a \'string\''
|
||||
this_should_raise = (
|
||||
'This is a'
|
||||
'\'string\''
|
||||
)
|
||||
@@ -1,10 +0,0 @@
|
||||
this_should_raise_Q003 = "This is a \"string\""
|
||||
this_is_fine = "'This' is a \"string\""
|
||||
this_is_fine = 'This is a "string"'
|
||||
this_is_fine = '\'This\' is a "string"'
|
||||
this_is_fine = r"This is a \"string\""
|
||||
this_is_fine = R"This is a \"string\""
|
||||
this_should_raise = (
|
||||
"This is a"
|
||||
"\"string\""
|
||||
)
|
||||
@@ -1,44 +0,0 @@
|
||||
key in obj.keys() # SIM118
|
||||
|
||||
key not in obj.keys() # SIM118
|
||||
|
||||
foo["bar"] in obj.keys() # SIM118
|
||||
|
||||
foo["bar"] not in obj.keys() # SIM118
|
||||
|
||||
foo['bar'] in obj.keys() # SIM118
|
||||
|
||||
foo['bar'] not in obj.keys() # SIM118
|
||||
|
||||
foo() in obj.keys() # SIM118
|
||||
|
||||
foo() not in obj.keys() # SIM118
|
||||
|
||||
for key in obj.keys(): # SIM118
|
||||
pass
|
||||
|
||||
for key in list(obj.keys()):
|
||||
if some_property(key):
|
||||
del obj[key]
|
||||
|
||||
[k for k in obj.keys()] # SIM118
|
||||
|
||||
{k for k in obj.keys()} # SIM118
|
||||
|
||||
{k: k for k in obj.keys()} # SIM118
|
||||
|
||||
(k for k in obj.keys()) # SIM118
|
||||
|
||||
key in (obj or {}).keys() # SIM118
|
||||
|
||||
(key) in (obj or {}).keys() # SIM118
|
||||
|
||||
from typing import KeysView
|
||||
|
||||
|
||||
class Foo:
|
||||
def keys(self) -> KeysView[object]:
|
||||
...
|
||||
|
||||
def __contains__(self, key: object) -> bool:
|
||||
return key in self.keys() # OK
|
||||
@@ -1,15 +0,0 @@
|
||||
a = True if b else False # SIM210
|
||||
|
||||
a = True if b != c else False # SIM210
|
||||
|
||||
a = True if b + c else False # SIM210
|
||||
|
||||
a = False if b else True # OK
|
||||
|
||||
|
||||
def f():
|
||||
# OK
|
||||
def bool():
|
||||
return False
|
||||
|
||||
a = True if b else False
|
||||
@@ -1,35 +0,0 @@
|
||||
import os
|
||||
import os.path
|
||||
|
||||
p = "/foo"
|
||||
q = "bar"
|
||||
|
||||
a = os.path.abspath(p)
|
||||
aa = os.chmod(p)
|
||||
aaa = os.mkdir(p)
|
||||
os.makedirs(p)
|
||||
os.rename(p)
|
||||
os.replace(p)
|
||||
os.rmdir(p)
|
||||
os.remove(p)
|
||||
os.unlink(p)
|
||||
os.getcwd(p)
|
||||
b = os.path.exists(p)
|
||||
bb = os.path.expanduser(p)
|
||||
bbb = os.path.isdir(p)
|
||||
bbbb = os.path.isfile(p)
|
||||
bbbbb = os.path.islink(p)
|
||||
os.readlink(p)
|
||||
os.stat(p)
|
||||
os.path.isabs(p)
|
||||
os.path.join(p, q)
|
||||
os.sep.join([p, q])
|
||||
os.sep.join((p, q))
|
||||
os.path.basename(p)
|
||||
os.path.dirname(p)
|
||||
os.path.samefile(p)
|
||||
os.path.splitext(p)
|
||||
with open(p) as fp:
|
||||
fp.read()
|
||||
open(p).close()
|
||||
os.getcwdb(p)
|
||||
@@ -1,8 +0,0 @@
|
||||
[tool.ruff]
|
||||
line-length = 88
|
||||
|
||||
[tool.ruff.isort]
|
||||
lines-after-imports = 3
|
||||
lines-between-types = 2
|
||||
known-local-folder = ["ruff"]
|
||||
force-to-top = ["lib1", "lib3", "lib5", "lib3.lib4", "z"]
|
||||
@@ -1,15 +0,0 @@
|
||||
import numpy as np
|
||||
|
||||
np.round_(np.random.rand(5, 5), 2)
|
||||
np.product(np.random.rand(5, 5))
|
||||
np.cumproduct(np.random.rand(5, 5))
|
||||
np.sometrue(np.random.rand(5, 5))
|
||||
np.alltrue(np.random.rand(5, 5))
|
||||
|
||||
from numpy import round_, product, cumproduct, sometrue, alltrue
|
||||
|
||||
round_(np.random.rand(5, 5), 2)
|
||||
product(np.random.rand(5, 5))
|
||||
cumproduct(np.random.rand(5, 5))
|
||||
sometrue(np.random.rand(5, 5))
|
||||
alltrue(np.random.rand(5, 5))
|
||||
@@ -1,40 +0,0 @@
|
||||
import collections
|
||||
from collections import namedtuple
|
||||
from typing import TypeVar
|
||||
from typing import NewType
|
||||
from typing import NamedTuple, TypedDict
|
||||
|
||||
GLOBAL: str = "foo"
|
||||
|
||||
|
||||
def assign():
|
||||
global GLOBAL
|
||||
GLOBAL = "bar"
|
||||
lower = 0
|
||||
Camel = 0
|
||||
CONSTANT = 0
|
||||
_ = 0
|
||||
|
||||
MyObj1 = collections.namedtuple("MyObj1", ["a", "b"])
|
||||
MyObj2 = namedtuple("MyObj12", ["a", "b"])
|
||||
|
||||
T = TypeVar("T")
|
||||
UserId = NewType("UserId", int)
|
||||
|
||||
Employee = NamedTuple('Employee', [('name', str), ('id', int)])
|
||||
|
||||
Point2D = TypedDict('Point2D', {'in': int, 'x-y': int})
|
||||
|
||||
|
||||
def aug_assign(rank, world_size):
|
||||
global CURRENT_PORT
|
||||
|
||||
CURRENT_PORT += 1
|
||||
if CURRENT_PORT > MAX_PORT:
|
||||
CURRENT_PORT = START_PORT
|
||||
|
||||
|
||||
def loop_assign():
|
||||
global CURRENT_PORT
|
||||
for CURRENT_PORT in range(5):
|
||||
pass
|
||||
@@ -1,26 +0,0 @@
|
||||
def f():
|
||||
items = [1, 2, 3, 4]
|
||||
result = []
|
||||
for i in items:
|
||||
result.append(i) # PERF402
|
||||
|
||||
|
||||
def f():
|
||||
items = [1, 2, 3, 4]
|
||||
result = []
|
||||
for i in items:
|
||||
result.insert(0, i) # PERF402
|
||||
|
||||
|
||||
def f():
|
||||
items = [1, 2, 3, 4]
|
||||
result = []
|
||||
for i in items:
|
||||
result.append(i * i) # OK
|
||||
|
||||
|
||||
def f():
|
||||
items = [1, 2, 3, 4]
|
||||
result = {}
|
||||
for i in items:
|
||||
result[i].append(i * i) # OK
|
||||
@@ -1,14 +0,0 @@
|
||||
#: E211
|
||||
spam (1)
|
||||
#: E211 E211
|
||||
dict ['key'] = list [index]
|
||||
#: E211
|
||||
dict['key'] ['subkey'] = list[index]
|
||||
#: Okay
|
||||
spam(1)
|
||||
dict['key'] = list[index]
|
||||
|
||||
|
||||
# This is not prohibited by PEP8, but avoid it.
|
||||
class Foo (Bar, Baz):
|
||||
pass
|
||||
@@ -1,33 +0,0 @@
|
||||
#: E231
|
||||
a = (1,2)
|
||||
#: E231
|
||||
a[b1,:]
|
||||
#: E231
|
||||
a = [{'a':''}]
|
||||
#: Okay
|
||||
a = (4,)
|
||||
b = (5, )
|
||||
c = {'text': text[5:]}
|
||||
|
||||
result = {
|
||||
'key1': 'value',
|
||||
'key2': 'value',
|
||||
}
|
||||
|
||||
def foo() -> None:
|
||||
#: E231
|
||||
if (1,2):
|
||||
pass
|
||||
|
||||
#: Okay
|
||||
a = (1,\
|
||||
2)
|
||||
|
||||
#: E231:2:20
|
||||
mdtypes_template = {
|
||||
'tag_full': [('mdtype', 'u4'), ('byte_count', 'u4')],
|
||||
'tag_smalldata':[('byte_count_mdtype', 'u4'), ('data', 'S4')],
|
||||
}
|
||||
|
||||
#: Okay
|
||||
a = (1,
|
||||
@@ -1,6 +0,0 @@
|
||||
# TODO: comments starting with one of the configured task-tags sometimes are longer than line-length so that you can easily find them with `git grep`
|
||||
# TODO comments starting with one of the configured task-tags sometimes are longer than line-length so that you can easily find them with `git grep`
|
||||
# TODO comments starting with one of the configured task-tags sometimes are longer than line-length so that you can easily find them with `git grep`
|
||||
# FIXME: comments starting with one of the configured task-tags sometimes are longer than line-length so that you can easily find them with `git grep`
|
||||
# FIXME comments starting with one of the configured task-tags sometimes are longer than line-length so that you can easily find them with `git grep`
|
||||
# FIXME comments starting with one of the configured task-tags sometimes are longer than line-length so that you can easily find them with `git grep`
|
||||
@@ -1,90 +0,0 @@
|
||||
#: E721
|
||||
if type(res) == type(42):
|
||||
pass
|
||||
#: E721
|
||||
if type(res) != type(""):
|
||||
pass
|
||||
#: E721
|
||||
import types
|
||||
|
||||
if res == types.IntType:
|
||||
pass
|
||||
#: E721
|
||||
import types
|
||||
|
||||
if type(res) is not types.ListType:
|
||||
pass
|
||||
#: E721
|
||||
assert type(res) == type(False)
|
||||
#: E721
|
||||
assert type(res) == type([])
|
||||
#: E721
|
||||
assert type(res) == type(())
|
||||
#: E721
|
||||
assert type(res) == type((0,))
|
||||
#: E721
|
||||
assert type(res) == type((0))
|
||||
#: E721
|
||||
assert type(res) != type((1,))
|
||||
#: E721
|
||||
assert type(res) is type((1,))
|
||||
#: E721
|
||||
assert type(res) is not type((1,))
|
||||
#: E211 E721
|
||||
assert type(res) == type(
|
||||
[
|
||||
2,
|
||||
]
|
||||
)
|
||||
#: E201 E201 E202 E721
|
||||
assert type(res) == type(())
|
||||
#: E201 E202 E721
|
||||
assert type(res) == type((0,))
|
||||
|
||||
#: Okay
|
||||
import types
|
||||
|
||||
if isinstance(res, int):
|
||||
pass
|
||||
if isinstance(res, str):
|
||||
pass
|
||||
if isinstance(res, types.MethodType):
|
||||
pass
|
||||
if type(a) != type(b) or type(a) == type(ccc):
|
||||
pass
|
||||
|
||||
assert type(res) == type(None)
|
||||
|
||||
types = StrEnum
|
||||
if x == types.X:
|
||||
pass
|
||||
|
||||
#: E721
|
||||
assert type(res) is int
|
||||
|
||||
|
||||
class Foo:
|
||||
def asdf(self, value: str | None):
|
||||
#: E721
|
||||
if type(value) is str:
|
||||
...
|
||||
|
||||
|
||||
class Foo:
|
||||
def type(self):
|
||||
pass
|
||||
|
||||
def asdf(self, value: str | None):
|
||||
#: E721
|
||||
if type(value) is str:
|
||||
...
|
||||
|
||||
|
||||
class Foo:
|
||||
def asdf(self, value: str | None):
|
||||
def type():
|
||||
pass
|
||||
|
||||
# Okay
|
||||
if type(value) is str:
|
||||
...
|
||||
@@ -1,7 +0,0 @@
|
||||
import logging
|
||||
import warnings
|
||||
from warnings import warn
|
||||
|
||||
warnings.warn("this is ok")
|
||||
warn("by itself is also ok")
|
||||
logging.warning("this is fine")
|
||||
@@ -1,5 +0,0 @@
|
||||
import logging
|
||||
from logging import warn
|
||||
|
||||
logging.warn("this is not ok")
|
||||
warn("not ok")
|
||||
@@ -1,46 +0,0 @@
|
||||
class Apples:
|
||||
def _init_(self): # [bad-dunder-name]
|
||||
pass
|
||||
|
||||
def __hello__(self): # [bad-dunder-name]
|
||||
print("hello")
|
||||
|
||||
def __init_(self): # [bad-dunder-name]
|
||||
# author likely unintentionally misspelled the correct init dunder.
|
||||
pass
|
||||
|
||||
def _init_(self): # [bad-dunder-name]
|
||||
# author likely unintentionally misspelled the correct init dunder.
|
||||
pass
|
||||
|
||||
def ___neg__(self): # [bad-dunder-name]
|
||||
# author likely accidentally added an additional `_`
|
||||
pass
|
||||
|
||||
def __inv__(self): # [bad-dunder-name]
|
||||
# author likely meant to call the invert dunder method
|
||||
pass
|
||||
|
||||
def hello(self):
|
||||
print("hello")
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def init(self):
|
||||
# valid name even though someone could accidentally mean __init__
|
||||
pass
|
||||
|
||||
def _protected_method(self):
|
||||
print("Protected")
|
||||
|
||||
def __private_method(self):
|
||||
print("Private")
|
||||
|
||||
@property
|
||||
def __doc__(self):
|
||||
return "Docstring"
|
||||
|
||||
|
||||
def __foo_bar__(): # this is not checked by the [bad-dunder-name] rule
|
||||
...
|
||||
Binary file not shown.
@@ -1,28 +0,0 @@
|
||||
import logging
|
||||
|
||||
logging.warning("Hello %s %s", "World!") # [logging-too-few-args]
|
||||
|
||||
# do not handle calls with kwargs (like pylint)
|
||||
logging.warning("Hello %s", "World!", "again", something="else")
|
||||
|
||||
logging.warning("Hello %s", "World!")
|
||||
|
||||
# do not handle calls without any args
|
||||
logging.info("100% dynamic")
|
||||
|
||||
# do not handle calls with *args
|
||||
logging.error("Example log %s, %s", "foo", "bar", "baz", *args)
|
||||
|
||||
# do not handle calls with **kwargs
|
||||
logging.error("Example log %s, %s", "foo", "bar", "baz", **kwargs)
|
||||
|
||||
# do not handle keyword arguments
|
||||
logging.error("%(objects)d modifications: %(modifications)d errors: %(errors)d")
|
||||
|
||||
logging.info(msg="Hello %s")
|
||||
|
||||
logging.info(msg="Hello %s %s")
|
||||
|
||||
import warning
|
||||
|
||||
warning.warning("Hello %s %s", "World!")
|
||||
@@ -1,24 +0,0 @@
|
||||
import logging
|
||||
|
||||
logging.warning("Hello %s", "World!", "again") # [logging-too-many-args]
|
||||
|
||||
logging.warning("Hello %s", "World!", "again", something="else")
|
||||
|
||||
logging.warning("Hello %s", "World!")
|
||||
|
||||
# do not handle calls with *args
|
||||
logging.error("Example log %s, %s", "foo", "bar", "baz", *args)
|
||||
|
||||
# do not handle calls with **kwargs
|
||||
logging.error("Example log %s, %s", "foo", "bar", "baz", **kwargs)
|
||||
|
||||
# do not handle keyword arguments
|
||||
logging.error("%(objects)d modifications: %(modifications)d errors: %(errors)d", {"objects": 1, "modifications": 1, "errors": 1})
|
||||
|
||||
logging.info(msg="Hello")
|
||||
|
||||
logging.info(msg="Hello", something="else")
|
||||
|
||||
import warning
|
||||
|
||||
warning.warning("Hello %s", "World!", "again")
|
||||
@@ -1,8 +0,0 @@
|
||||
[tool.ruff]
|
||||
line-length = 88
|
||||
extend-exclude = [
|
||||
"excluded_file.py",
|
||||
"migrations",
|
||||
"with_excluded_file/other_excluded_file.py",
|
||||
]
|
||||
per-file-ignores = { "__init__.py" = ["F401"] }
|
||||
@@ -1,15 +0,0 @@
|
||||
type("")
|
||||
type(b"")
|
||||
type(0)
|
||||
type(0.0)
|
||||
type(0j)
|
||||
|
||||
# OK
|
||||
type(arg)(" ")
|
||||
|
||||
# OK
|
||||
y = x.dtype.type(0.0)
|
||||
|
||||
# OK
|
||||
type = lambda *args, **kwargs: None
|
||||
type("")
|
||||
@@ -1,93 +0,0 @@
|
||||
import typing
|
||||
from typing import Optional
|
||||
from typing import Union
|
||||
|
||||
|
||||
def f(x: Optional[str]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: typing.Optional[str]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: Union[str, int, Union[float, bytes]]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: typing.Union[str, int]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: typing.Union[(str, int)]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: typing.Union[(str, int), float]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: typing.Union[(int,)]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: typing.Union[()]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: "Union[str, int, Union[float, bytes]]") -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: "typing.Union[str, int]") -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: Union["str", int]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: Union[("str", "int"), float]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f() -> None:
|
||||
x: Optional[str]
|
||||
x = Optional[str]
|
||||
|
||||
x = Union[str, int]
|
||||
x = Union["str", "int"]
|
||||
x: Union[str, int]
|
||||
x: Union["str", "int"]
|
||||
|
||||
|
||||
def f(x: Union[int : float]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: Union[str, int : float]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: Union[x := int]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: Union[str, x := int]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: Union[lambda: int]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: Union[str, lambda: int]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: Optional[int : float]) -> None:
|
||||
...
|
||||
|
||||
|
||||
def f(x: Optional[str, int : float]) -> None:
|
||||
...
|
||||
@@ -1,24 +0,0 @@
|
||||
from typing import NamedTuple
|
||||
import typing
|
||||
|
||||
# with complex annotations
|
||||
MyType = NamedTuple("MyType", [("a", int), ("b", tuple[str, ...])])
|
||||
|
||||
# with namespace
|
||||
MyType = typing.NamedTuple("MyType", [("a", int), ("b", str)])
|
||||
|
||||
# invalid identifiers (OK)
|
||||
MyType = NamedTuple("MyType", [("x-y", int), ("b", tuple[str, ...])])
|
||||
|
||||
# no fields
|
||||
MyType = typing.NamedTuple("MyType")
|
||||
|
||||
# empty fields
|
||||
MyType = typing.NamedTuple("MyType", [])
|
||||
|
||||
# keywords
|
||||
MyType = typing.NamedTuple("MyType", a=int, b=tuple[str, ...])
|
||||
|
||||
# unfixable
|
||||
MyType = typing.NamedTuple("MyType", [("a", int)], [("b", str)])
|
||||
MyType = typing.NamedTuple("MyType", [("a", int)], b=str)
|
||||
@@ -1,80 +0,0 @@
|
||||
open("foo", "U")
|
||||
open("foo", "Ur")
|
||||
open("foo", "Ub")
|
||||
open("foo", "rUb")
|
||||
open("foo", "r")
|
||||
open("foo", "rt")
|
||||
open("f", "r", encoding="UTF-8")
|
||||
open("f", "wt")
|
||||
|
||||
with open("foo", "U") as f:
|
||||
pass
|
||||
with open("foo", "Ur") as f:
|
||||
pass
|
||||
with open("foo", "Ub") as f:
|
||||
pass
|
||||
with open("foo", "rUb") as f:
|
||||
pass
|
||||
with open("foo", "r") as f:
|
||||
pass
|
||||
with open("foo", "rt") as f:
|
||||
pass
|
||||
with open("foo", "r", encoding="UTF-8") as f:
|
||||
pass
|
||||
with open("foo", "wt") as f:
|
||||
pass
|
||||
|
||||
open(f("a", "b", "c"), "U")
|
||||
open(f("a", "b", "c"), "Ub")
|
||||
|
||||
with open(f("a", "b", "c"), "U") as f:
|
||||
pass
|
||||
with open(f("a", "b", "c"), "Ub") as f:
|
||||
pass
|
||||
|
||||
with open("foo", "U") as fa, open("bar", "U") as fb:
|
||||
pass
|
||||
with open("foo", "Ub") as fa, open("bar", "Ub") as fb:
|
||||
pass
|
||||
|
||||
open("foo", mode="U")
|
||||
open(name="foo", mode="U")
|
||||
open(mode="U", name="foo")
|
||||
|
||||
with open("foo", mode="U") as f:
|
||||
pass
|
||||
with open(name="foo", mode="U") as f:
|
||||
pass
|
||||
with open(mode="U", name="foo") as f:
|
||||
pass
|
||||
|
||||
open("foo", mode="Ub")
|
||||
open(name="foo", mode="Ub")
|
||||
open(mode="Ub", name="foo")
|
||||
|
||||
with open("foo", mode="Ub") as f:
|
||||
pass
|
||||
with open(name="foo", mode="Ub") as f:
|
||||
pass
|
||||
with open(mode="Ub", name="foo") as f:
|
||||
pass
|
||||
|
||||
open(file="foo", mode='U', buffering=- 1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
|
||||
open(file="foo", buffering=- 1, encoding=None, errors=None, newline=None, closefd=True, opener=None, mode='U')
|
||||
open(file="foo", buffering=- 1, encoding=None, errors=None, mode='U', newline=None, closefd=True, opener=None)
|
||||
open(mode='U', file="foo", buffering=- 1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
|
||||
|
||||
open(file="foo", mode='Ub', buffering=- 1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
|
||||
open(file="foo", buffering=- 1, encoding=None, errors=None, newline=None, closefd=True, opener=None, mode='Ub')
|
||||
open(file="foo", buffering=- 1, encoding=None, errors=None, mode='Ub', newline=None, closefd=True, opener=None)
|
||||
open(mode='Ub', file="foo", buffering=- 1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
|
||||
|
||||
open = 1
|
||||
open("foo", "U")
|
||||
open("foo", "Ur")
|
||||
open("foo", "Ub")
|
||||
open("foo", "rUb")
|
||||
open("foo", "r")
|
||||
open("foo", "rt")
|
||||
open("f", "r", encoding="UTF-8")
|
||||
open("f", "wt")
|
||||
@@ -1,12 +0,0 @@
|
||||
import subprocess
|
||||
import subprocess as somename
|
||||
from subprocess import run
|
||||
from subprocess import run as anothername
|
||||
|
||||
subprocess.run(["foo"], universal_newlines=True, check=True)
|
||||
somename.run(["foo"], universal_newlines=True)
|
||||
|
||||
run(["foo"], universal_newlines=True, check=False)
|
||||
anothername(["foo"], universal_newlines=True)
|
||||
|
||||
subprocess.run(["foo"], check=True)
|
||||
@@ -1,42 +0,0 @@
|
||||
from subprocess import run
|
||||
import subprocess
|
||||
|
||||
output = run(["foo"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
output = subprocess.run(["foo"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
|
||||
output = subprocess.run(stdout=subprocess.PIPE, args=["foo"], stderr=subprocess.PIPE)
|
||||
|
||||
output = subprocess.run(
|
||||
["foo"], stdout=subprocess.PIPE, check=True, stderr=subprocess.PIPE
|
||||
)
|
||||
|
||||
output = subprocess.run(
|
||||
["foo"], stderr=subprocess.PIPE, check=True, stdout=subprocess.PIPE
|
||||
)
|
||||
|
||||
output = subprocess.run(
|
||||
["foo"],
|
||||
stdout=subprocess.PIPE,
|
||||
check=True,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
close_fds=True,
|
||||
)
|
||||
|
||||
if output:
|
||||
output = subprocess.run(
|
||||
["foo"],
|
||||
stdout=subprocess.PIPE,
|
||||
check=True,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
|
||||
# Examples that should NOT trigger the rule
|
||||
from foo import PIPE
|
||||
subprocess.run(["foo"], stdout=PIPE, stderr=PIPE)
|
||||
run(["foo"], stdout=None, stderr=PIPE)
|
||||
@@ -1,98 +0,0 @@
|
||||
import mmap, select, socket
|
||||
from mmap import error
|
||||
# These should be fixed
|
||||
try:
|
||||
pass
|
||||
except EnvironmentError:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except WindowsError:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except mmap.error:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except select.error:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except socket.error:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except error:
|
||||
pass
|
||||
|
||||
# Should NOT be in parentheses when replaced
|
||||
|
||||
try:
|
||||
pass
|
||||
except (IOError,):
|
||||
pass
|
||||
try:
|
||||
pass
|
||||
except (mmap.error,):
|
||||
pass
|
||||
try:
|
||||
pass
|
||||
except (EnvironmentError, IOError, OSError, select.error):
|
||||
pass
|
||||
|
||||
# Should be kept in parentheses (because multiple)
|
||||
|
||||
try:
|
||||
pass
|
||||
except (IOError, KeyError, OSError):
|
||||
pass
|
||||
|
||||
# First should change, second should not
|
||||
from .mmap import error
|
||||
try:
|
||||
pass
|
||||
except (IOError, error):
|
||||
pass
|
||||
# These should not change
|
||||
|
||||
from foo import error
|
||||
|
||||
try:
|
||||
pass
|
||||
except (OSError, error):
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except AssertionError:
|
||||
pass
|
||||
try:
|
||||
pass
|
||||
except (mmap).error:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
try:
|
||||
pass
|
||||
except (OSError, KeyError):
|
||||
pass
|
||||
@@ -1,14 +0,0 @@
|
||||
x = [1, 2, 3]
|
||||
y = [4, 5, 6]
|
||||
|
||||
# RUF017
|
||||
sum([x, y], start=[])
|
||||
sum([x, y], [])
|
||||
sum([[1, 2, 3], [4, 5, 6]], start=[])
|
||||
sum([[1, 2, 3], [4, 5, 6]], [])
|
||||
sum([[1, 2, 3], [4, 5, 6]],
|
||||
[])
|
||||
|
||||
# OK
|
||||
sum([x, y])
|
||||
sum([[1, 2, 3], [4, 5, 6]])
|
||||
@@ -1,31 +0,0 @@
|
||||
x = "𝐁ad string"
|
||||
y = "−"
|
||||
|
||||
|
||||
def f():
|
||||
"""Here's a docstring with an unusual parenthesis: )"""
|
||||
# And here's a comment with an unusual punctuation mark: ᜵
|
||||
...
|
||||
|
||||
|
||||
def f():
|
||||
"""Here's a docstring with a greek rho: ρ"""
|
||||
# And here's a comment with a greek alpha: ∗
|
||||
...
|
||||
|
||||
|
||||
x = "𝐁ad string"
|
||||
x = "−"
|
||||
|
||||
# This should be ignored, since it contains an unambiguous unicode character, and no
|
||||
# ASCII.
|
||||
x = "Русский"
|
||||
|
||||
# The first word should be ignored, while the second should be included, since it
|
||||
# contains ASCII.
|
||||
x = "βα Bαd"
|
||||
|
||||
# The two characters should be flagged here. The first character is a "word"
|
||||
# consisting of a single ambiguous character, while the second character is a "word
|
||||
# boundary" (whitespace) that it itself ambiguous.
|
||||
x = "Р усский"
|
||||
@@ -1,77 +0,0 @@
|
||||
"""
|
||||
Violation:
|
||||
Use '.exception' over '.error' inside except blocks
|
||||
"""
|
||||
|
||||
import logging
|
||||
import sys
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def bad():
|
||||
try:
|
||||
a = 1
|
||||
except Exception:
|
||||
logging.error("Context message here")
|
||||
|
||||
if True:
|
||||
logging.error("Context message here")
|
||||
|
||||
|
||||
def bad():
|
||||
try:
|
||||
a = 1
|
||||
except Exception:
|
||||
logger.error("Context message here")
|
||||
|
||||
if True:
|
||||
logger.error("Context message here")
|
||||
|
||||
|
||||
def bad():
|
||||
try:
|
||||
a = 1
|
||||
except Exception:
|
||||
log.error("Context message here")
|
||||
|
||||
if True:
|
||||
log.error("Context message here")
|
||||
|
||||
|
||||
def bad():
|
||||
try:
|
||||
a = 1
|
||||
except Exception:
|
||||
self.logger.error("Context message here")
|
||||
|
||||
if True:
|
||||
self.logger.error("Context message here")
|
||||
|
||||
|
||||
def good():
|
||||
try:
|
||||
a = 1
|
||||
except Exception:
|
||||
logger.exception("Context message here")
|
||||
|
||||
|
||||
def good():
|
||||
try:
|
||||
a = 1
|
||||
except Exception:
|
||||
foo.exception("Context message here")
|
||||
|
||||
|
||||
def fine():
|
||||
try:
|
||||
a = 1
|
||||
except Exception:
|
||||
logger.error("Context message here", exc_info=True)
|
||||
|
||||
|
||||
def fine():
|
||||
try:
|
||||
a = 1
|
||||
except Exception:
|
||||
logger.error("Context message here", exc_info=sys.exc_info())
|
||||
@@ -1,64 +0,0 @@
|
||||
# Errors
|
||||
def main_function():
|
||||
try:
|
||||
process()
|
||||
handle()
|
||||
finish()
|
||||
except Exception as ex:
|
||||
logger.exception(f"Found an error: {ex}") # TRY401
|
||||
|
||||
|
||||
def main_function():
|
||||
try:
|
||||
process()
|
||||
handle()
|
||||
finish()
|
||||
except ValueError as bad:
|
||||
if True is False:
|
||||
for i in range(10):
|
||||
logger.exception(f"Found an error: {bad} {good}") # TRY401
|
||||
except IndexError as bad:
|
||||
logger.exception(f"Found an error: {bad} {bad}") # TRY401
|
||||
except Exception as bad:
|
||||
logger.exception(f"Found an error: {bad}") # TRY401
|
||||
logger.exception(f"Found an error: {bad}") # TRY401
|
||||
|
||||
if True:
|
||||
logger.exception(f"Found an error: {bad}") # TRY401
|
||||
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def func_fstr():
|
||||
try:
|
||||
...
|
||||
except Exception as ex:
|
||||
logger.exception(f"Logging an error: {ex}") # TRY401
|
||||
|
||||
|
||||
def func_concat():
|
||||
try:
|
||||
...
|
||||
except Exception as ex:
|
||||
logger.exception("Logging an error: " + str(ex)) # TRY401
|
||||
|
||||
|
||||
def func_comma():
|
||||
try:
|
||||
...
|
||||
except Exception as ex:
|
||||
logger.exception("Logging an error:", ex) # TRY401
|
||||
|
||||
|
||||
# OK
|
||||
def main_function():
|
||||
try:
|
||||
process()
|
||||
handle()
|
||||
finish()
|
||||
except Exception as ex:
|
||||
logger.exception(f"Found an error: {er}")
|
||||
logger.exception(f"Found an error: {ex.field}")
|
||||
@@ -1,96 +0,0 @@
|
||||
# project
|
||||
|
||||
An example multi-package Python project used to test setting resolution and other complex
|
||||
behaviors.
|
||||
|
||||
## Expected behavior
|
||||
|
||||
Running from the repo root should pick up and enforce the appropriate settings for each package:
|
||||
|
||||
```console
|
||||
∴ cargo run -p ruff_cli -- check crates/ruff/resources/test/project/
|
||||
crates/ruff/resources/test/project/examples/.dotfiles/script.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
crates/ruff/resources/test/project/examples/.dotfiles/script.py:1:8: F401 [*] `numpy` imported but unused
|
||||
crates/ruff/resources/test/project/examples/.dotfiles/script.py:2:17: F401 [*] `app.app_file` imported but unused
|
||||
crates/ruff/resources/test/project/examples/docs/docs/file.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
crates/ruff/resources/test/project/examples/docs/docs/file.py:8:5: F841 [*] Local variable `x` is assigned to but never used
|
||||
crates/ruff/resources/test/project/project/file.py:1:8: F401 [*] `os` imported but unused
|
||||
crates/ruff/resources/test/project/project/import_file.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
Found 7 errors.
|
||||
[*] 7 potentially fixable with the --fix option.
|
||||
```
|
||||
|
||||
Running from the project directory itself should exhibit the same behavior:
|
||||
|
||||
```console
|
||||
∴ (cd crates/ruff/resources/test/project/ && cargo run -p ruff_cli -- check .)
|
||||
examples/.dotfiles/script.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
examples/.dotfiles/script.py:1:8: F401 [*] `numpy` imported but unused
|
||||
examples/.dotfiles/script.py:2:17: F401 [*] `app.app_file` imported but unused
|
||||
examples/docs/docs/file.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
examples/docs/docs/file.py:8:5: F841 [*] Local variable `x` is assigned to but never used
|
||||
project/file.py:1:8: F401 [*] `os` imported but unused
|
||||
project/import_file.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
Found 7 errors.
|
||||
[*] 7 potentially fixable with the --fix option.
|
||||
```
|
||||
|
||||
Running from the sub-package directory should exhibit the same behavior, but omit the top-level
|
||||
files:
|
||||
|
||||
```console
|
||||
∴ (cd crates/ruff/resources/test/project/examples/docs && cargo run -p ruff_cli -- check .)
|
||||
docs/file.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
docs/file.py:8:5: F841 [*] Local variable `x` is assigned to but never used
|
||||
Found 2 errors.
|
||||
[*] 2 potentially fixable with the --fix option.
|
||||
```
|
||||
|
||||
`--config` should force Ruff to use the specified `pyproject.toml` for all files, and resolve
|
||||
file paths from the current working directory:
|
||||
|
||||
```console
|
||||
∴ (cargo run -p ruff_cli -- check --config=crates/ruff/resources/test/project/pyproject.toml crates/ruff/resources/test/project/)
|
||||
crates/ruff/resources/test/project/examples/.dotfiles/script.py:1:8: F401 [*] `numpy` imported but unused
|
||||
crates/ruff/resources/test/project/examples/.dotfiles/script.py:2:17: F401 [*] `app.app_file` imported but unused
|
||||
crates/ruff/resources/test/project/examples/docs/docs/concepts/file.py:1:8: F401 [*] `os` imported but unused
|
||||
crates/ruff/resources/test/project/examples/docs/docs/file.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
crates/ruff/resources/test/project/examples/docs/docs/file.py:1:8: F401 [*] `os` imported but unused
|
||||
crates/ruff/resources/test/project/examples/docs/docs/file.py:3:8: F401 [*] `numpy` imported but unused
|
||||
crates/ruff/resources/test/project/examples/docs/docs/file.py:4:27: F401 [*] `docs.concepts.file` imported but unused
|
||||
crates/ruff/resources/test/project/examples/excluded/script.py:1:8: F401 [*] `os` imported but unused
|
||||
crates/ruff/resources/test/project/project/file.py:1:8: F401 [*] `os` imported but unused
|
||||
Found 9 errors.
|
||||
[*] 9 potentially fixable with the --fix option.
|
||||
```
|
||||
|
||||
Running from a parent directory should "ignore" the `exclude` (hence, `concepts/file.py` gets
|
||||
included in the output):
|
||||
|
||||
```console
|
||||
∴ (cd crates/ruff/resources/test/project/examples && cargo run -p ruff_cli -- check --config=docs/ruff.toml .)
|
||||
docs/docs/concepts/file.py:5:5: F841 [*] Local variable `x` is assigned to but never used
|
||||
docs/docs/file.py:1:1: I001 [*] Import block is un-sorted or un-formatted
|
||||
docs/docs/file.py:8:5: F841 [*] Local variable `x` is assigned to but never used
|
||||
excluded/script.py:5:5: F841 [*] Local variable `x` is assigned to but never used
|
||||
Found 4 errors.
|
||||
[*] 4 potentially fixable with the --fix option.
|
||||
```
|
||||
|
||||
Passing an excluded directory directly should report errors in the contained files:
|
||||
|
||||
```console
|
||||
∴ cargo run -p ruff_cli -- check crates/ruff/resources/test/project/examples/excluded/
|
||||
crates/ruff/resources/test/project/examples/excluded/script.py:1:8: F401 [*] `os` imported but unused
|
||||
Found 1 error.
|
||||
[*] 1 potentially fixable with the --fix option.
|
||||
```
|
||||
|
||||
Unless we `--force-exclude`:
|
||||
|
||||
```console
|
||||
∴ cargo run -p ruff_cli -- check crates/ruff/resources/test/project/examples/excluded/ --force-exclude
|
||||
warning: No Python files found under the given path(s)
|
||||
∴ cargo run -p ruff_cli -- check crates/ruff/resources/test/project/examples/excluded/script.py --force-exclude
|
||||
warning: No Python files found under the given path(s)
|
||||
```
|
||||
@@ -1,5 +0,0 @@
|
||||
[tool.ruff]
|
||||
src = [".", "python_modules/*"]
|
||||
exclude = ["examples/excluded"]
|
||||
extend-select = ["I001"]
|
||||
extend-ignore = ["F841"]
|
||||
@@ -1,331 +0,0 @@
|
||||
//! Interface for generating autofix edits from higher-level actions (e.g., "remove an argument").
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
|
||||
use ruff_diagnostics::Edit;
|
||||
use ruff_python_ast::{self as ast, Arguments, ExceptHandler, Expr, Keyword, Stmt};
|
||||
use ruff_python_codegen::Stylist;
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_python_trivia::{
|
||||
has_leading_content, is_python_whitespace, PythonWhitespace, SimpleTokenKind, SimpleTokenizer,
|
||||
};
|
||||
use ruff_source_file::{Locator, NewlineWithTrailingNewline};
|
||||
use ruff_text_size::{Ranged, TextLen, TextSize};
|
||||
|
||||
use crate::autofix::codemods;
|
||||
|
||||
/// Return the `Fix` to use when deleting a `Stmt`.
|
||||
///
|
||||
/// In some cases, this is as simple as deleting the `Range` of the `Stmt`
|
||||
/// itself. However, there are a few exceptions:
|
||||
/// - If the `Stmt` is _not_ the terminal statement in a multi-statement line,
|
||||
/// we need to delete up to the start of the next statement (and avoid
|
||||
/// deleting any content that precedes the statement).
|
||||
/// - If the `Stmt` is the terminal statement in a multi-statement line, we need
|
||||
/// to avoid deleting any content that precedes the statement.
|
||||
/// - If the `Stmt` has no trailing and leading content, then it's convenient to
|
||||
/// remove the entire start and end lines.
|
||||
/// - If the `Stmt` is the last statement in its parent body, replace it with a
|
||||
/// `pass` instead.
|
||||
pub(crate) fn delete_stmt(
|
||||
stmt: &Stmt,
|
||||
parent: Option<&Stmt>,
|
||||
locator: &Locator,
|
||||
indexer: &Indexer,
|
||||
) -> Edit {
|
||||
if parent
|
||||
.map(|parent| is_lone_child(stmt, parent))
|
||||
.unwrap_or_default()
|
||||
{
|
||||
// If removing this node would lead to an invalid syntax tree, replace
|
||||
// it with a `pass`.
|
||||
Edit::range_replacement("pass".to_string(), stmt.range())
|
||||
} else {
|
||||
if let Some(semicolon) = trailing_semicolon(stmt.end(), locator) {
|
||||
let next = next_stmt_break(semicolon, locator);
|
||||
Edit::deletion(stmt.start(), next)
|
||||
} else if has_leading_content(stmt.start(), locator) {
|
||||
Edit::range_deletion(stmt.range())
|
||||
} else if let Some(start) = indexer.preceded_by_continuations(stmt.start(), locator) {
|
||||
Edit::deletion(start, stmt.end())
|
||||
} else {
|
||||
let range = locator.full_lines_range(stmt.range());
|
||||
Edit::range_deletion(range)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a `Fix` to remove the specified imports from an `import` statement.
|
||||
pub(crate) fn remove_unused_imports<'a>(
|
||||
member_names: impl Iterator<Item = &'a str>,
|
||||
stmt: &Stmt,
|
||||
parent: Option<&Stmt>,
|
||||
locator: &Locator,
|
||||
stylist: &Stylist,
|
||||
indexer: &Indexer,
|
||||
) -> Result<Edit> {
|
||||
match codemods::remove_imports(member_names, stmt, locator, stylist)? {
|
||||
None => Ok(delete_stmt(stmt, parent, locator, indexer)),
|
||||
Some(content) => Ok(Edit::range_replacement(content, stmt.range())),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(crate) enum Parentheses {
|
||||
/// Remove parentheses, if the removed argument is the only argument left.
|
||||
Remove,
|
||||
/// Preserve parentheses, even if the removed argument is the only argument
|
||||
Preserve,
|
||||
}
|
||||
|
||||
/// Generic function to remove arguments or keyword arguments in function
|
||||
/// calls and class definitions. (For classes `args` should be considered
|
||||
/// `bases`)
|
||||
///
|
||||
/// Supports the removal of parentheses when this is the only (kw)arg left.
|
||||
/// For this behavior, set `remove_parentheses` to `true`.
|
||||
pub(crate) fn remove_argument<T: Ranged>(
|
||||
argument: &T,
|
||||
arguments: &Arguments,
|
||||
parentheses: Parentheses,
|
||||
source: &str,
|
||||
) -> Result<Edit> {
|
||||
// Partition into arguments before and after the argument to remove.
|
||||
let (before, after): (Vec<_>, Vec<_>) = arguments
|
||||
.args
|
||||
.iter()
|
||||
.map(Expr::range)
|
||||
.chain(arguments.keywords.iter().map(Keyword::range))
|
||||
.filter(|range| argument.range() != *range)
|
||||
.partition(|range| range.start() < argument.start());
|
||||
|
||||
if !after.is_empty() {
|
||||
// Case 1: argument or keyword is _not_ the last node, so delete from the start of the
|
||||
// argument to the end of the subsequent comma.
|
||||
let mut tokenizer = SimpleTokenizer::starts_at(argument.end(), source);
|
||||
|
||||
// Find the trailing comma.
|
||||
tokenizer
|
||||
.find(|token| token.kind == SimpleTokenKind::Comma)
|
||||
.context("Unable to find trailing comma")?;
|
||||
|
||||
// Find the next non-whitespace token.
|
||||
let next = tokenizer
|
||||
.find(|token| {
|
||||
token.kind != SimpleTokenKind::Whitespace && token.kind != SimpleTokenKind::Newline
|
||||
})
|
||||
.context("Unable to find next token")?;
|
||||
|
||||
Ok(Edit::deletion(argument.start(), next.start()))
|
||||
} else if let Some(previous) = before.iter().map(Ranged::end).max() {
|
||||
// Case 2: argument or keyword is the last node, so delete from the start of the
|
||||
// previous comma to the end of the argument.
|
||||
let mut tokenizer = SimpleTokenizer::starts_at(previous, source);
|
||||
|
||||
// Find the trailing comma.
|
||||
let comma = tokenizer
|
||||
.find(|token| token.kind == SimpleTokenKind::Comma)
|
||||
.context("Unable to find trailing comma")?;
|
||||
|
||||
Ok(Edit::deletion(comma.start(), argument.end()))
|
||||
} else {
|
||||
// Case 3: argument or keyword is the only node, so delete the arguments (but preserve
|
||||
// parentheses, if needed).
|
||||
Ok(match parentheses {
|
||||
Parentheses::Remove => Edit::range_deletion(arguments.range()),
|
||||
Parentheses::Preserve => Edit::range_replacement("()".to_string(), arguments.range()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Determine if a vector contains only one, specific element.
|
||||
fn is_only<T: PartialEq>(vec: &[T], value: &T) -> bool {
|
||||
vec.len() == 1 && vec[0] == *value
|
||||
}
|
||||
|
||||
/// Determine if a child is the only statement in its body.
|
||||
fn is_lone_child(child: &Stmt, parent: &Stmt) -> bool {
|
||||
match parent {
|
||||
Stmt::FunctionDef(ast::StmtFunctionDef { body, .. })
|
||||
| Stmt::ClassDef(ast::StmtClassDef { body, .. })
|
||||
| Stmt::With(ast::StmtWith { body, .. }) => {
|
||||
if is_only(body, child) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Stmt::For(ast::StmtFor { body, orelse, .. })
|
||||
| Stmt::While(ast::StmtWhile { body, orelse, .. }) => {
|
||||
if is_only(body, child) || is_only(orelse, child) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Stmt::If(ast::StmtIf {
|
||||
body,
|
||||
elif_else_clauses,
|
||||
..
|
||||
}) => {
|
||||
if is_only(body, child)
|
||||
|| elif_else_clauses
|
||||
.iter()
|
||||
.any(|ast::ElifElseClause { body, .. }| is_only(body, child))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Stmt::Try(ast::StmtTry {
|
||||
body,
|
||||
handlers,
|
||||
orelse,
|
||||
finalbody,
|
||||
..
|
||||
}) => {
|
||||
if is_only(body, child)
|
||||
|| is_only(orelse, child)
|
||||
|| is_only(finalbody, child)
|
||||
|| handlers.iter().any(|handler| match handler {
|
||||
ExceptHandler::ExceptHandler(ast::ExceptHandlerExceptHandler {
|
||||
body, ..
|
||||
}) => is_only(body, child),
|
||||
})
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Stmt::Match(ast::StmtMatch { cases, .. }) => {
|
||||
if cases.iter().any(|case| is_only(&case.body, child)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Return the location of a trailing semicolon following a `Stmt`, if it's part
|
||||
/// of a multi-statement line.
|
||||
fn trailing_semicolon(offset: TextSize, locator: &Locator) -> Option<TextSize> {
|
||||
let contents = locator.after(offset);
|
||||
|
||||
for line in NewlineWithTrailingNewline::from(contents) {
|
||||
let trimmed = line.trim_whitespace_start();
|
||||
|
||||
if trimmed.starts_with(';') {
|
||||
let colon_offset = line.text_len() - trimmed.text_len();
|
||||
return Some(offset + line.start() + colon_offset);
|
||||
}
|
||||
|
||||
if !trimmed.starts_with('\\') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Find the next valid break for a `Stmt` after a semicolon.
|
||||
fn next_stmt_break(semicolon: TextSize, locator: &Locator) -> TextSize {
|
||||
let start_location = semicolon + TextSize::from(1);
|
||||
|
||||
for line in
|
||||
NewlineWithTrailingNewline::with_offset(locator.after(start_location), start_location)
|
||||
{
|
||||
let trimmed = line.trim_whitespace();
|
||||
// Skip past any continuations.
|
||||
if trimmed.starts_with('\\') {
|
||||
continue;
|
||||
}
|
||||
|
||||
return if trimmed.is_empty() {
|
||||
// If the line is empty, then despite the previous statement ending in a
|
||||
// semicolon, we know that it's not a multi-statement line.
|
||||
line.start()
|
||||
} else {
|
||||
// Otherwise, find the start of the next statement. (Or, anything that isn't
|
||||
// whitespace.)
|
||||
let relative_offset = line.find(|c: char| !is_python_whitespace(c)).unwrap();
|
||||
line.start() + TextSize::try_from(relative_offset).unwrap()
|
||||
};
|
||||
}
|
||||
|
||||
locator.line_end(start_location)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use anyhow::Result;
|
||||
|
||||
use ruff_python_parser::parse_suite;
|
||||
use ruff_source_file::Locator;
|
||||
use ruff_text_size::{Ranged, TextSize};
|
||||
|
||||
use crate::autofix::edits::{next_stmt_break, trailing_semicolon};
|
||||
|
||||
#[test]
|
||||
fn find_semicolon() -> Result<()> {
|
||||
let contents = "x = 1";
|
||||
let program = parse_suite(contents, "<filename>")?;
|
||||
let stmt = program.first().unwrap();
|
||||
let locator = Locator::new(contents);
|
||||
assert_eq!(trailing_semicolon(stmt.end(), &locator), None);
|
||||
|
||||
let contents = "x = 1; y = 1";
|
||||
let program = parse_suite(contents, "<filename>")?;
|
||||
let stmt = program.first().unwrap();
|
||||
let locator = Locator::new(contents);
|
||||
assert_eq!(
|
||||
trailing_semicolon(stmt.end(), &locator),
|
||||
Some(TextSize::from(5))
|
||||
);
|
||||
|
||||
let contents = "x = 1 ; y = 1";
|
||||
let program = parse_suite(contents, "<filename>")?;
|
||||
let stmt = program.first().unwrap();
|
||||
let locator = Locator::new(contents);
|
||||
assert_eq!(
|
||||
trailing_semicolon(stmt.end(), &locator),
|
||||
Some(TextSize::from(6))
|
||||
);
|
||||
|
||||
let contents = r"
|
||||
x = 1 \
|
||||
; y = 1
|
||||
"
|
||||
.trim();
|
||||
let program = parse_suite(contents, "<filename>")?;
|
||||
let stmt = program.first().unwrap();
|
||||
let locator = Locator::new(contents);
|
||||
assert_eq!(
|
||||
trailing_semicolon(stmt.end(), &locator),
|
||||
Some(TextSize::from(10))
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn find_next_stmt_break() {
|
||||
let contents = "x = 1; y = 1";
|
||||
let locator = Locator::new(contents);
|
||||
assert_eq!(
|
||||
next_stmt_break(TextSize::from(4), &locator),
|
||||
TextSize::from(5)
|
||||
);
|
||||
|
||||
let contents = "x = 1 ; y = 1";
|
||||
let locator = Locator::new(contents);
|
||||
assert_eq!(
|
||||
next_stmt_break(TextSize::from(5), &locator),
|
||||
TextSize::from(6)
|
||||
);
|
||||
|
||||
let contents = r"
|
||||
x = 1 \
|
||||
; y = 1
|
||||
"
|
||||
.trim();
|
||||
let locator = Locator::new(contents);
|
||||
assert_eq!(
|
||||
next_stmt_break(TextSize::from(10), &locator),
|
||||
TextSize::from(12)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,396 +0,0 @@
|
||||
use itertools::Itertools;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Edit, Fix, IsolationLevel};
|
||||
use ruff_source_file::Locator;
|
||||
|
||||
use crate::autofix::source_map::SourceMap;
|
||||
use crate::linter::FixTable;
|
||||
use crate::registry::{AsRule, Rule};
|
||||
|
||||
pub(crate) mod codemods;
|
||||
pub(crate) mod edits;
|
||||
pub(crate) mod snippet;
|
||||
pub(crate) mod source_map;
|
||||
|
||||
pub(crate) struct FixResult {
|
||||
/// The resulting source code, after applying all fixes.
|
||||
pub(crate) code: String,
|
||||
/// The number of fixes applied for each [`Rule`].
|
||||
pub(crate) fixes: FixTable,
|
||||
/// Source map for the fixed source code.
|
||||
pub(crate) source_map: SourceMap,
|
||||
}
|
||||
|
||||
/// Auto-fix errors in a file, and write the fixed source code to disk.
|
||||
pub(crate) fn fix_file(diagnostics: &[Diagnostic], locator: &Locator) -> Option<FixResult> {
|
||||
let mut with_fixes = diagnostics
|
||||
.iter()
|
||||
.filter(|diag| diag.fix.is_some())
|
||||
.peekable();
|
||||
|
||||
if with_fixes.peek().is_none() {
|
||||
None
|
||||
} else {
|
||||
Some(apply_fixes(with_fixes, locator))
|
||||
}
|
||||
}
|
||||
|
||||
/// Apply a series of fixes.
|
||||
fn apply_fixes<'a>(
|
||||
diagnostics: impl Iterator<Item = &'a Diagnostic>,
|
||||
locator: &'a Locator<'a>,
|
||||
) -> FixResult {
|
||||
let mut output = String::with_capacity(locator.len());
|
||||
let mut last_pos: Option<TextSize> = None;
|
||||
let mut applied: BTreeSet<&Edit> = BTreeSet::default();
|
||||
let mut isolated: FxHashSet<u32> = FxHashSet::default();
|
||||
let mut fixed = FxHashMap::default();
|
||||
let mut source_map = SourceMap::default();
|
||||
|
||||
for (rule, fix) in diagnostics
|
||||
.filter_map(|diagnostic| {
|
||||
diagnostic
|
||||
.fix
|
||||
.as_ref()
|
||||
.map(|fix| (diagnostic.kind.rule(), fix))
|
||||
})
|
||||
.sorted_by(|(rule1, fix1), (rule2, fix2)| cmp_fix(*rule1, *rule2, fix1, fix2))
|
||||
{
|
||||
let mut edits = fix
|
||||
.edits()
|
||||
.iter()
|
||||
.filter(|edit| !applied.contains(edit))
|
||||
.peekable();
|
||||
|
||||
// If the fix contains at least one new edit, enforce isolation and positional requirements.
|
||||
if let Some(first) = edits.peek() {
|
||||
// If this fix requires isolation, and we've already applied another fix in the
|
||||
// same isolation group, skip it.
|
||||
if let IsolationLevel::Group(id) = fix.isolation() {
|
||||
if !isolated.insert(id) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// If this fix overlaps with a fix we've already applied, skip it.
|
||||
if last_pos.is_some_and(|last_pos| last_pos >= first.start()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let mut applied_edits = Vec::with_capacity(fix.edits().len());
|
||||
for edit in edits {
|
||||
// Add all contents from `last_pos` to `fix.location`.
|
||||
let slice = locator.slice(TextRange::new(last_pos.unwrap_or_default(), edit.start()));
|
||||
output.push_str(slice);
|
||||
|
||||
// Add the start source marker for the patch.
|
||||
source_map.push_start_marker(edit, output.text_len());
|
||||
|
||||
// Add the patch itself.
|
||||
output.push_str(edit.content().unwrap_or_default());
|
||||
|
||||
// Add the end source marker for the added patch.
|
||||
source_map.push_end_marker(edit, output.text_len());
|
||||
|
||||
// Track that the edit was applied.
|
||||
last_pos = Some(edit.end());
|
||||
applied_edits.push(edit);
|
||||
}
|
||||
|
||||
applied.extend(applied_edits.drain(..));
|
||||
*fixed.entry(rule).or_default() += 1;
|
||||
}
|
||||
|
||||
// Add the remaining content.
|
||||
let slice = locator.after(last_pos.unwrap_or_default());
|
||||
output.push_str(slice);
|
||||
|
||||
FixResult {
|
||||
code: output,
|
||||
fixes: fixed,
|
||||
source_map,
|
||||
}
|
||||
}
|
||||
|
||||
/// Compare two fixes.
|
||||
fn cmp_fix(rule1: Rule, rule2: Rule, fix1: &Fix, fix2: &Fix) -> std::cmp::Ordering {
|
||||
fix1.min_start()
|
||||
.cmp(&fix2.min_start())
|
||||
.then_with(|| match (&rule1, &rule2) {
|
||||
// Apply `EndsInPeriod` fixes before `NewLineAfterLastParagraph` fixes.
|
||||
(Rule::EndsInPeriod, Rule::NewLineAfterLastParagraph) => std::cmp::Ordering::Less,
|
||||
(Rule::NewLineAfterLastParagraph, Rule::EndsInPeriod) => std::cmp::Ordering::Greater,
|
||||
// Apply `IfElseBlockInsteadOfDictGet` fixes before `IfElseBlockInsteadOfIfExp` fixes.
|
||||
(Rule::IfElseBlockInsteadOfDictGet, Rule::IfElseBlockInsteadOfIfExp) => {
|
||||
std::cmp::Ordering::Less
|
||||
}
|
||||
(Rule::IfElseBlockInsteadOfIfExp, Rule::IfElseBlockInsteadOfDictGet) => {
|
||||
std::cmp::Ordering::Greater
|
||||
}
|
||||
_ => std::cmp::Ordering::Equal,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ruff_text_size::{Ranged, TextSize};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Edit, Fix};
|
||||
use ruff_source_file::Locator;
|
||||
|
||||
use crate::autofix::source_map::SourceMarker;
|
||||
use crate::autofix::{apply_fixes, FixResult};
|
||||
use crate::rules::pycodestyle::rules::MissingNewlineAtEndOfFile;
|
||||
|
||||
#[allow(deprecated)]
|
||||
fn create_diagnostics(edit: impl IntoIterator<Item = Edit>) -> Vec<Diagnostic> {
|
||||
edit.into_iter()
|
||||
.map(|edit| Diagnostic {
|
||||
// The choice of rule here is arbitrary.
|
||||
kind: MissingNewlineAtEndOfFile.into(),
|
||||
range: edit.range(),
|
||||
fix: Some(Fix::unspecified(edit)),
|
||||
parent: None,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_file() {
|
||||
let locator = Locator::new(r#""#);
|
||||
let diagnostics = create_diagnostics([]);
|
||||
let FixResult {
|
||||
code,
|
||||
fixes,
|
||||
source_map,
|
||||
} = apply_fixes(diagnostics.iter(), &locator);
|
||||
assert_eq!(code, "");
|
||||
assert_eq!(fixes.values().sum::<usize>(), 0);
|
||||
assert!(source_map.markers().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn apply_one_insertion() {
|
||||
let locator = Locator::new(
|
||||
r#"
|
||||
import os
|
||||
|
||||
print("hello world")
|
||||
"#
|
||||
.trim(),
|
||||
);
|
||||
let diagnostics = create_diagnostics([Edit::insertion(
|
||||
"import sys\n".to_string(),
|
||||
TextSize::new(10),
|
||||
)]);
|
||||
let FixResult {
|
||||
code,
|
||||
fixes,
|
||||
source_map,
|
||||
} = apply_fixes(diagnostics.iter(), &locator);
|
||||
assert_eq!(
|
||||
code,
|
||||
r#"
|
||||
import os
|
||||
import sys
|
||||
|
||||
print("hello world")
|
||||
"#
|
||||
.trim()
|
||||
);
|
||||
assert_eq!(fixes.values().sum::<usize>(), 1);
|
||||
assert_eq!(
|
||||
source_map.markers(),
|
||||
&[
|
||||
SourceMarker {
|
||||
source: 10.into(),
|
||||
dest: 10.into(),
|
||||
},
|
||||
SourceMarker {
|
||||
source: 10.into(),
|
||||
dest: 21.into(),
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn apply_one_replacement() {
|
||||
let locator = Locator::new(
|
||||
r#"
|
||||
class A(object):
|
||||
...
|
||||
"#
|
||||
.trim(),
|
||||
);
|
||||
let diagnostics = create_diagnostics([Edit::replacement(
|
||||
"Bar".to_string(),
|
||||
TextSize::new(8),
|
||||
TextSize::new(14),
|
||||
)]);
|
||||
let FixResult {
|
||||
code,
|
||||
fixes,
|
||||
source_map,
|
||||
} = apply_fixes(diagnostics.iter(), &locator);
|
||||
assert_eq!(
|
||||
code,
|
||||
r#"
|
||||
class A(Bar):
|
||||
...
|
||||
"#
|
||||
.trim(),
|
||||
);
|
||||
assert_eq!(fixes.values().sum::<usize>(), 1);
|
||||
assert_eq!(
|
||||
source_map.markers(),
|
||||
&[
|
||||
SourceMarker {
|
||||
source: 8.into(),
|
||||
dest: 8.into(),
|
||||
},
|
||||
SourceMarker {
|
||||
source: 14.into(),
|
||||
dest: 11.into(),
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn apply_one_removal() {
|
||||
let locator = Locator::new(
|
||||
r#"
|
||||
class A(object):
|
||||
...
|
||||
"#
|
||||
.trim(),
|
||||
);
|
||||
let diagnostics = create_diagnostics([Edit::deletion(TextSize::new(7), TextSize::new(15))]);
|
||||
let FixResult {
|
||||
code,
|
||||
fixes,
|
||||
source_map,
|
||||
} = apply_fixes(diagnostics.iter(), &locator);
|
||||
assert_eq!(
|
||||
code,
|
||||
r#"
|
||||
class A:
|
||||
...
|
||||
"#
|
||||
.trim()
|
||||
);
|
||||
assert_eq!(fixes.values().sum::<usize>(), 1);
|
||||
assert_eq!(
|
||||
source_map.markers(),
|
||||
&[
|
||||
SourceMarker {
|
||||
source: 7.into(),
|
||||
dest: 7.into()
|
||||
},
|
||||
SourceMarker {
|
||||
source: 15.into(),
|
||||
dest: 7.into()
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn apply_two_removals() {
|
||||
let locator = Locator::new(
|
||||
r#"
|
||||
class A(object, object, object):
|
||||
...
|
||||
"#
|
||||
.trim(),
|
||||
);
|
||||
let diagnostics = create_diagnostics([
|
||||
Edit::deletion(TextSize::from(8), TextSize::from(16)),
|
||||
Edit::deletion(TextSize::from(22), TextSize::from(30)),
|
||||
]);
|
||||
let FixResult {
|
||||
code,
|
||||
fixes,
|
||||
source_map,
|
||||
} = apply_fixes(diagnostics.iter(), &locator);
|
||||
|
||||
assert_eq!(
|
||||
code,
|
||||
r#"
|
||||
class A(object):
|
||||
...
|
||||
"#
|
||||
.trim()
|
||||
);
|
||||
assert_eq!(fixes.values().sum::<usize>(), 2);
|
||||
assert_eq!(
|
||||
source_map.markers(),
|
||||
&[
|
||||
SourceMarker {
|
||||
source: 8.into(),
|
||||
dest: 8.into()
|
||||
},
|
||||
SourceMarker {
|
||||
source: 16.into(),
|
||||
dest: 8.into()
|
||||
},
|
||||
SourceMarker {
|
||||
source: 22.into(),
|
||||
dest: 14.into(),
|
||||
},
|
||||
SourceMarker {
|
||||
source: 30.into(),
|
||||
dest: 14.into(),
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ignore_overlapping_fixes() {
|
||||
let locator = Locator::new(
|
||||
r#"
|
||||
class A(object):
|
||||
...
|
||||
"#
|
||||
.trim(),
|
||||
);
|
||||
let diagnostics = create_diagnostics([
|
||||
Edit::deletion(TextSize::from(7), TextSize::from(15)),
|
||||
Edit::replacement("ignored".to_string(), TextSize::from(9), TextSize::from(11)),
|
||||
]);
|
||||
let FixResult {
|
||||
code,
|
||||
fixes,
|
||||
source_map,
|
||||
} = apply_fixes(diagnostics.iter(), &locator);
|
||||
assert_eq!(
|
||||
code,
|
||||
r#"
|
||||
class A:
|
||||
...
|
||||
"#
|
||||
.trim(),
|
||||
);
|
||||
assert_eq!(fixes.values().sum::<usize>(), 1);
|
||||
assert_eq!(
|
||||
source_map.markers(),
|
||||
&[
|
||||
SourceMarker {
|
||||
source: 7.into(),
|
||||
dest: 7.into(),
|
||||
},
|
||||
SourceMarker {
|
||||
source: 15.into(),
|
||||
dest: 7.into(),
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
use ruff_text_size::{Ranged, TextSize};
|
||||
|
||||
use ruff_diagnostics::Edit;
|
||||
|
||||
/// Lightweight sourcemap marker representing the source and destination
|
||||
/// position for an [`Edit`].
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub(crate) struct SourceMarker {
|
||||
/// Position of the marker in the original source.
|
||||
pub(crate) source: TextSize,
|
||||
/// Position of the marker in the transformed code.
|
||||
pub(crate) dest: TextSize,
|
||||
}
|
||||
|
||||
/// A collection of [`SourceMarker`].
|
||||
///
|
||||
/// Sourcemaps are used to map positions in the original source to positions in
|
||||
/// the transformed code. Here, only the boundaries of edits are tracked instead
|
||||
/// of every single character.
|
||||
#[derive(Default, PartialEq, Eq)]
|
||||
pub(crate) struct SourceMap(Vec<SourceMarker>);
|
||||
|
||||
impl SourceMap {
|
||||
/// Returns a slice of all the markers in the sourcemap in the order they
|
||||
/// were added.
|
||||
pub(crate) fn markers(&self) -> &[SourceMarker] {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// Push the start marker for an [`Edit`].
|
||||
///
|
||||
/// The `output_length` is the length of the transformed string before the
|
||||
/// edit is applied.
|
||||
pub(crate) fn push_start_marker(&mut self, edit: &Edit, output_length: TextSize) {
|
||||
self.0.push(SourceMarker {
|
||||
source: edit.start(),
|
||||
dest: output_length,
|
||||
});
|
||||
}
|
||||
|
||||
/// Push the end marker for an [`Edit`].
|
||||
///
|
||||
/// The `output_length` is the length of the transformed string after the
|
||||
/// edit has been applied.
|
||||
pub(crate) fn push_end_marker(&mut self, edit: &Edit, output_length: TextSize) {
|
||||
if edit.is_insertion() {
|
||||
self.0.push(SourceMarker {
|
||||
source: edit.start(),
|
||||
dest: output_length,
|
||||
});
|
||||
} else {
|
||||
// Deletion or replacement
|
||||
self.0.push(SourceMarker {
|
||||
source: edit.end(),
|
||||
dest: output_length,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
pub(super) use bindings::bindings;
|
||||
pub(super) use comprehension::comprehension;
|
||||
pub(super) use deferred_for_loops::deferred_for_loops;
|
||||
pub(super) use deferred_scopes::deferred_scopes;
|
||||
pub(super) use definitions::definitions;
|
||||
pub(super) use except_handler::except_handler;
|
||||
pub(super) use expression::expression;
|
||||
pub(super) use module::module;
|
||||
pub(super) use parameter::parameter;
|
||||
pub(super) use parameters::parameters;
|
||||
pub(super) use statement::statement;
|
||||
pub(super) use suite::suite;
|
||||
pub(super) use unresolved_references::unresolved_references;
|
||||
|
||||
mod bindings;
|
||||
mod comprehension;
|
||||
mod deferred_for_loops;
|
||||
mod deferred_scopes;
|
||||
mod definitions;
|
||||
mod except_handler;
|
||||
mod expression;
|
||||
mod module;
|
||||
mod parameter;
|
||||
mod parameters;
|
||||
mod statement;
|
||||
mod suite;
|
||||
mod unresolved_references;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,242 +0,0 @@
|
||||
//! `NoQA` enforcement and validation.
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use itertools::Itertools;
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
|
||||
use ruff_diagnostics::{Diagnostic, Edit, Fix};
|
||||
use ruff_source_file::Locator;
|
||||
|
||||
use crate::noqa;
|
||||
use crate::noqa::{Directive, FileExemption, NoqaDirectives, NoqaMapping};
|
||||
use crate::registry::{AsRule, Rule};
|
||||
use crate::rule_redirects::get_redirect_target;
|
||||
use crate::rules::ruff::rules::{UnusedCodes, UnusedNOQA};
|
||||
use crate::settings::Settings;
|
||||
|
||||
pub(crate) fn check_noqa(
|
||||
diagnostics: &mut Vec<Diagnostic>,
|
||||
path: &Path,
|
||||
locator: &Locator,
|
||||
comment_ranges: &[TextRange],
|
||||
noqa_line_for: &NoqaMapping,
|
||||
analyze_directives: bool,
|
||||
settings: &Settings,
|
||||
) -> Vec<usize> {
|
||||
// Identify any codes that are globally exempted (within the current file).
|
||||
let exemption = FileExemption::try_extract(locator.contents(), comment_ranges, path, locator);
|
||||
|
||||
// Extract all `noqa` directives.
|
||||
let mut noqa_directives = NoqaDirectives::from_commented_ranges(comment_ranges, path, locator);
|
||||
|
||||
// Indices of diagnostics that were ignored by a `noqa` directive.
|
||||
let mut ignored_diagnostics = vec![];
|
||||
|
||||
// Remove any ignored diagnostics.
|
||||
'outer: for (index, diagnostic) in diagnostics.iter().enumerate() {
|
||||
if matches!(diagnostic.kind.rule(), Rule::BlanketNOQA) {
|
||||
continue;
|
||||
}
|
||||
|
||||
match &exemption {
|
||||
Some(FileExemption::All) => {
|
||||
// If the file is exempted, ignore all diagnostics.
|
||||
ignored_diagnostics.push(index);
|
||||
continue;
|
||||
}
|
||||
Some(FileExemption::Codes(codes)) => {
|
||||
// If the diagnostic is ignored by a global exemption, ignore it.
|
||||
if codes.contains(&diagnostic.kind.rule().noqa_code()) {
|
||||
ignored_diagnostics.push(index);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
let noqa_offsets = diagnostic
|
||||
.parent
|
||||
.into_iter()
|
||||
.chain(std::iter::once(diagnostic.start()))
|
||||
.map(|position| noqa_line_for.resolve(position))
|
||||
.unique();
|
||||
|
||||
for noqa_offset in noqa_offsets {
|
||||
if let Some(directive_line) = noqa_directives.find_line_with_directive_mut(noqa_offset)
|
||||
{
|
||||
let suppressed = match &directive_line.directive {
|
||||
Directive::All(_) => {
|
||||
directive_line
|
||||
.matches
|
||||
.push(diagnostic.kind.rule().noqa_code());
|
||||
ignored_diagnostics.push(index);
|
||||
true
|
||||
}
|
||||
Directive::Codes(directive) => {
|
||||
if noqa::includes(diagnostic.kind.rule(), directive.codes()) {
|
||||
directive_line
|
||||
.matches
|
||||
.push(diagnostic.kind.rule().noqa_code());
|
||||
ignored_diagnostics.push(index);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if suppressed {
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Enforce that the noqa directive was actually used (RUF100), unless RUF100 was itself
|
||||
// suppressed.
|
||||
if settings.rules.enabled(Rule::UnusedNOQA)
|
||||
&& analyze_directives
|
||||
&& !exemption.is_some_and(|exemption| match exemption {
|
||||
FileExemption::All => true,
|
||||
FileExemption::Codes(codes) => codes.contains(&Rule::UnusedNOQA.noqa_code()),
|
||||
})
|
||||
{
|
||||
for line in noqa_directives.lines() {
|
||||
match &line.directive {
|
||||
Directive::All(directive) => {
|
||||
if line.matches.is_empty() {
|
||||
let mut diagnostic =
|
||||
Diagnostic::new(UnusedNOQA { codes: None }, directive.range());
|
||||
if settings.rules.should_fix(diagnostic.kind.rule()) {
|
||||
diagnostic
|
||||
.set_fix(Fix::automatic(delete_noqa(directive.range(), locator)));
|
||||
}
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
Directive::Codes(directive) => {
|
||||
let mut disabled_codes = vec![];
|
||||
let mut unknown_codes = vec![];
|
||||
let mut unmatched_codes = vec![];
|
||||
let mut valid_codes = vec![];
|
||||
let mut self_ignore = false;
|
||||
for code in directive.codes() {
|
||||
let code = get_redirect_target(code).unwrap_or(code);
|
||||
if Rule::UnusedNOQA.noqa_code() == code {
|
||||
self_ignore = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if line.matches.iter().any(|match_| *match_ == code)
|
||||
|| settings.external.contains(code)
|
||||
{
|
||||
valid_codes.push(code);
|
||||
} else {
|
||||
if let Ok(rule) = Rule::from_code(code) {
|
||||
if settings.rules.enabled(rule) {
|
||||
unmatched_codes.push(code);
|
||||
} else {
|
||||
disabled_codes.push(code);
|
||||
}
|
||||
} else {
|
||||
unknown_codes.push(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self_ignore {
|
||||
continue;
|
||||
}
|
||||
|
||||
if !(disabled_codes.is_empty()
|
||||
&& unknown_codes.is_empty()
|
||||
&& unmatched_codes.is_empty())
|
||||
{
|
||||
let mut diagnostic = Diagnostic::new(
|
||||
UnusedNOQA {
|
||||
codes: Some(UnusedCodes {
|
||||
disabled: disabled_codes
|
||||
.iter()
|
||||
.map(|code| (*code).to_string())
|
||||
.collect(),
|
||||
unknown: unknown_codes
|
||||
.iter()
|
||||
.map(|code| (*code).to_string())
|
||||
.collect(),
|
||||
unmatched: unmatched_codes
|
||||
.iter()
|
||||
.map(|code| (*code).to_string())
|
||||
.collect(),
|
||||
}),
|
||||
},
|
||||
directive.range(),
|
||||
);
|
||||
if settings.rules.should_fix(diagnostic.kind.rule()) {
|
||||
if valid_codes.is_empty() {
|
||||
diagnostic.set_fix(Fix::automatic(delete_noqa(
|
||||
directive.range(),
|
||||
locator,
|
||||
)));
|
||||
} else {
|
||||
diagnostic.set_fix(Fix::automatic(Edit::range_replacement(
|
||||
format!("# noqa: {}", valid_codes.join(", ")),
|
||||
directive.range(),
|
||||
)));
|
||||
}
|
||||
}
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ignored_diagnostics.sort_unstable();
|
||||
ignored_diagnostics
|
||||
}
|
||||
|
||||
/// Generate a [`Edit`] to delete a `noqa` directive.
|
||||
fn delete_noqa(range: TextRange, locator: &Locator) -> Edit {
|
||||
let line_range = locator.line_range(range.start());
|
||||
|
||||
// Compute the leading space.
|
||||
let prefix = locator.slice(TextRange::new(line_range.start(), range.start()));
|
||||
let leading_space = prefix
|
||||
.rfind(|c: char| !c.is_whitespace())
|
||||
.map_or(prefix.len(), |i| prefix.len() - i - 1);
|
||||
let leading_space_len = TextSize::try_from(leading_space).unwrap();
|
||||
|
||||
// Compute the trailing space.
|
||||
let suffix = locator.slice(TextRange::new(range.end(), line_range.end()));
|
||||
let trailing_space = suffix
|
||||
.find(|c: char| !c.is_whitespace())
|
||||
.map_or(suffix.len(), |i| i);
|
||||
let trailing_space_len = TextSize::try_from(trailing_space).unwrap();
|
||||
|
||||
// Ex) `# noqa`
|
||||
if line_range
|
||||
== TextRange::new(
|
||||
range.start() - leading_space_len,
|
||||
range.end() + trailing_space_len,
|
||||
)
|
||||
{
|
||||
let full_line_end = locator.full_line_end(line_range.end());
|
||||
Edit::deletion(line_range.start(), full_line_end)
|
||||
}
|
||||
// Ex) `x = 1 # noqa`
|
||||
else if range.end() + trailing_space_len == line_range.end() {
|
||||
Edit::deletion(range.start() - leading_space_len, line_range.end())
|
||||
}
|
||||
// Ex) `x = 1 # noqa # type: ignore`
|
||||
else if locator.contents()[usize::from(range.end() + trailing_space_len)..].starts_with('#') {
|
||||
Edit::deletion(range.start(), range.end() + trailing_space_len)
|
||||
}
|
||||
// Ex) `x = 1 # noqa here`
|
||||
else {
|
||||
Edit::deletion(
|
||||
range.start() + "# ".text_len(),
|
||||
range.end() + trailing_space_len,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,193 +0,0 @@
|
||||
//! Lint rules based on token traversal.
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use ruff_python_parser::lexer::LexResult;
|
||||
use ruff_python_parser::Tok;
|
||||
|
||||
use ruff_diagnostics::Diagnostic;
|
||||
use ruff_python_index::Indexer;
|
||||
use ruff_source_file::Locator;
|
||||
|
||||
use crate::directives::TodoComment;
|
||||
use crate::lex::docstring_detection::StateMachine;
|
||||
use crate::registry::{AsRule, Rule};
|
||||
use crate::rules::ruff::rules::Context;
|
||||
use crate::rules::{
|
||||
eradicate, flake8_commas, flake8_executable, flake8_fixme, flake8_implicit_str_concat,
|
||||
flake8_pyi, flake8_quotes, flake8_todos, pycodestyle, pygrep_hooks, pylint, pyupgrade, ruff,
|
||||
};
|
||||
use crate::settings::Settings;
|
||||
|
||||
pub(crate) fn check_tokens(
|
||||
tokens: &[LexResult],
|
||||
path: &Path,
|
||||
locator: &Locator,
|
||||
indexer: &Indexer,
|
||||
settings: &Settings,
|
||||
is_stub: bool,
|
||||
) -> Vec<Diagnostic> {
|
||||
let mut diagnostics: Vec<Diagnostic> = vec![];
|
||||
|
||||
if settings.rules.enabled(Rule::BlanketNOQA) {
|
||||
pygrep_hooks::rules::blanket_noqa(&mut diagnostics, indexer, locator);
|
||||
}
|
||||
|
||||
if settings.rules.enabled(Rule::BlanketTypeIgnore) {
|
||||
pygrep_hooks::rules::blanket_type_ignore(&mut diagnostics, indexer, locator);
|
||||
}
|
||||
|
||||
if settings.rules.any_enabled(&[
|
||||
Rule::AmbiguousUnicodeCharacterString,
|
||||
Rule::AmbiguousUnicodeCharacterDocstring,
|
||||
Rule::AmbiguousUnicodeCharacterComment,
|
||||
]) {
|
||||
let mut state_machine = StateMachine::default();
|
||||
for &(ref tok, range) in tokens.iter().flatten() {
|
||||
let is_docstring = state_machine.consume(tok);
|
||||
if matches!(tok, Tok::String { .. } | Tok::Comment(_)) {
|
||||
ruff::rules::ambiguous_unicode_character(
|
||||
&mut diagnostics,
|
||||
locator,
|
||||
range,
|
||||
if tok.is_string() {
|
||||
if is_docstring {
|
||||
Context::Docstring
|
||||
} else {
|
||||
Context::String
|
||||
}
|
||||
} else {
|
||||
Context::Comment
|
||||
},
|
||||
settings,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if settings.rules.enabled(Rule::CommentedOutCode) {
|
||||
eradicate::rules::commented_out_code(&mut diagnostics, locator, indexer, settings);
|
||||
}
|
||||
|
||||
if settings.rules.enabled(Rule::UTF8EncodingDeclaration) {
|
||||
pyupgrade::rules::unnecessary_coding_comment(&mut diagnostics, locator, indexer, settings);
|
||||
}
|
||||
|
||||
if settings.rules.enabled(Rule::InvalidEscapeSequence) {
|
||||
for (tok, range) in tokens.iter().flatten() {
|
||||
if tok.is_string() {
|
||||
pycodestyle::rules::invalid_escape_sequence(
|
||||
&mut diagnostics,
|
||||
locator,
|
||||
*range,
|
||||
settings.rules.should_fix(Rule::InvalidEscapeSequence),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if settings.rules.any_enabled(&[
|
||||
Rule::InvalidCharacterBackspace,
|
||||
Rule::InvalidCharacterSub,
|
||||
Rule::InvalidCharacterEsc,
|
||||
Rule::InvalidCharacterNul,
|
||||
Rule::InvalidCharacterZeroWidthSpace,
|
||||
]) {
|
||||
for (tok, range) in tokens.iter().flatten() {
|
||||
if tok.is_string() {
|
||||
pylint::rules::invalid_string_characters(&mut diagnostics, *range, locator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if settings.rules.any_enabled(&[
|
||||
Rule::MultipleStatementsOnOneLineColon,
|
||||
Rule::MultipleStatementsOnOneLineSemicolon,
|
||||
Rule::UselessSemicolon,
|
||||
]) {
|
||||
pycodestyle::rules::compound_statements(
|
||||
&mut diagnostics,
|
||||
tokens,
|
||||
locator,
|
||||
indexer,
|
||||
settings,
|
||||
);
|
||||
}
|
||||
|
||||
if settings.rules.any_enabled(&[
|
||||
Rule::BadQuotesInlineString,
|
||||
Rule::BadQuotesMultilineString,
|
||||
Rule::BadQuotesDocstring,
|
||||
Rule::AvoidableEscapedQuote,
|
||||
]) {
|
||||
flake8_quotes::rules::from_tokens(&mut diagnostics, tokens, locator, settings);
|
||||
}
|
||||
|
||||
if settings.rules.any_enabled(&[
|
||||
Rule::SingleLineImplicitStringConcatenation,
|
||||
Rule::MultiLineImplicitStringConcatenation,
|
||||
]) {
|
||||
flake8_implicit_str_concat::rules::implicit(
|
||||
&mut diagnostics,
|
||||
tokens,
|
||||
&settings.flake8_implicit_str_concat,
|
||||
locator,
|
||||
);
|
||||
}
|
||||
|
||||
if settings.rules.any_enabled(&[
|
||||
Rule::MissingTrailingComma,
|
||||
Rule::TrailingCommaOnBareTuple,
|
||||
Rule::ProhibitedTrailingComma,
|
||||
]) {
|
||||
flake8_commas::rules::trailing_commas(&mut diagnostics, tokens, locator, settings);
|
||||
}
|
||||
|
||||
if settings.rules.enabled(Rule::ExtraneousParentheses) {
|
||||
pyupgrade::rules::extraneous_parentheses(&mut diagnostics, tokens, locator, settings);
|
||||
}
|
||||
|
||||
if is_stub && settings.rules.enabled(Rule::TypeCommentInStub) {
|
||||
flake8_pyi::rules::type_comment_in_stub(&mut diagnostics, locator, indexer);
|
||||
}
|
||||
|
||||
if settings.rules.any_enabled(&[
|
||||
Rule::ShebangNotExecutable,
|
||||
Rule::ShebangMissingExecutableFile,
|
||||
Rule::ShebangLeadingWhitespace,
|
||||
Rule::ShebangNotFirstLine,
|
||||
Rule::ShebangMissingPython,
|
||||
]) {
|
||||
flake8_executable::rules::from_tokens(tokens, path, locator, settings, &mut diagnostics);
|
||||
}
|
||||
|
||||
if settings.rules.any_enabled(&[
|
||||
Rule::InvalidTodoTag,
|
||||
Rule::MissingTodoAuthor,
|
||||
Rule::MissingTodoLink,
|
||||
Rule::MissingTodoColon,
|
||||
Rule::MissingTodoDescription,
|
||||
Rule::InvalidTodoCapitalization,
|
||||
Rule::MissingSpaceAfterTodoColon,
|
||||
Rule::LineContainsFixme,
|
||||
Rule::LineContainsXxx,
|
||||
Rule::LineContainsTodo,
|
||||
Rule::LineContainsHack,
|
||||
]) {
|
||||
let todo_comments: Vec<TodoComment> = indexer
|
||||
.comment_ranges()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(i, comment_range)| {
|
||||
let comment = locator.slice(*comment_range);
|
||||
TodoComment::from_comment(comment, *comment_range, i)
|
||||
})
|
||||
.collect();
|
||||
flake8_todos::rules::todos(&mut diagnostics, &todo_comments, locator, indexer, settings);
|
||||
flake8_fixme::rules::todos(&mut diagnostics, &todo_comments);
|
||||
}
|
||||
|
||||
diagnostics.retain(|diagnostic| settings.rules.enabled(diagnostic.kind.rule()));
|
||||
|
||||
diagnostics
|
||||
}
|
||||
@@ -1,870 +0,0 @@
|
||||
/// In this module we generate [`Rule`], an enum of all rules, and [`RuleCodePrefix`], an enum of
|
||||
/// all rules categories. A rule category is something like pyflakes or flake8-todos. Each rule
|
||||
/// category contains all rules and their common prefixes, i.e. everything you can specify in
|
||||
/// `--select`. For pylint this is e.g. C0414 and E0118 but also C and E01.
|
||||
use std::fmt::Formatter;
|
||||
|
||||
use strum_macros::{AsRefStr, EnumIter};
|
||||
|
||||
use ruff_diagnostics::Violation;
|
||||
|
||||
use crate::registry::{AsRule, Linter};
|
||||
use crate::rules;
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct NoqaCode(&'static str, &'static str);
|
||||
|
||||
impl NoqaCode {
|
||||
/// Return the prefix for the [`NoqaCode`], e.g., `SIM` for `SIM101`.
|
||||
pub fn prefix(&self) -> &str {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Return the suffix for the [`NoqaCode`], e.g., `101` for `SIM101`.
|
||||
pub fn suffix(&self) -> &str {
|
||||
self.1
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for NoqaCode {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for NoqaCode {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
write!(f, "{}{}", self.0, self.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<&str> for NoqaCode {
|
||||
fn eq(&self, other: &&str) -> bool {
|
||||
match other.strip_prefix(self.0) {
|
||||
Some(suffix) => suffix == self.1,
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum RuleGroup {
|
||||
/// The rule has not been assigned to any specific group.
|
||||
Unspecified,
|
||||
/// The rule is still under development, and must be enabled explicitly.
|
||||
Nursery,
|
||||
}
|
||||
|
||||
#[ruff_macros::map_codes]
|
||||
pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
|
||||
#[allow(clippy::enum_glob_use)]
|
||||
use Linter::*;
|
||||
|
||||
#[rustfmt::skip]
|
||||
Some(match (linter, code) {
|
||||
// pycodestyle errors
|
||||
(Pycodestyle, "E101") => (RuleGroup::Unspecified, rules::pycodestyle::rules::MixedSpacesAndTabs),
|
||||
(Pycodestyle, "E111") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::IndentationWithInvalidMultiple),
|
||||
(Pycodestyle, "E112") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::NoIndentedBlock),
|
||||
(Pycodestyle, "E113") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::UnexpectedIndentation),
|
||||
(Pycodestyle, "E114") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::IndentationWithInvalidMultipleComment),
|
||||
(Pycodestyle, "E115") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::NoIndentedBlockComment),
|
||||
(Pycodestyle, "E116") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::UnexpectedIndentationComment),
|
||||
(Pycodestyle, "E117") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::OverIndented),
|
||||
(Pycodestyle, "E201") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::WhitespaceAfterOpenBracket),
|
||||
(Pycodestyle, "E202") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::WhitespaceBeforeCloseBracket),
|
||||
(Pycodestyle, "E203") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::WhitespaceBeforePunctuation),
|
||||
(Pycodestyle, "E211") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::WhitespaceBeforeParameters),
|
||||
(Pycodestyle, "E221") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::MultipleSpacesBeforeOperator),
|
||||
(Pycodestyle, "E222") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::MultipleSpacesAfterOperator),
|
||||
(Pycodestyle, "E223") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::TabBeforeOperator),
|
||||
(Pycodestyle, "E224") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::TabAfterOperator),
|
||||
(Pycodestyle, "E225") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::MissingWhitespaceAroundOperator),
|
||||
(Pycodestyle, "E226") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::MissingWhitespaceAroundArithmeticOperator),
|
||||
(Pycodestyle, "E227") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::MissingWhitespaceAroundBitwiseOrShiftOperator),
|
||||
(Pycodestyle, "E228") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::MissingWhitespaceAroundModuloOperator),
|
||||
(Pycodestyle, "E231") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::MissingWhitespace),
|
||||
(Pycodestyle, "E241") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::MultipleSpacesAfterComma),
|
||||
(Pycodestyle, "E242") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::TabAfterComma),
|
||||
(Pycodestyle, "E251") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::UnexpectedSpacesAroundKeywordParameterEquals),
|
||||
(Pycodestyle, "E252") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::MissingWhitespaceAroundParameterEquals),
|
||||
(Pycodestyle, "E261") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::TooFewSpacesBeforeInlineComment),
|
||||
(Pycodestyle, "E262") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::NoSpaceAfterInlineComment),
|
||||
(Pycodestyle, "E265") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::NoSpaceAfterBlockComment),
|
||||
(Pycodestyle, "E266") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::MultipleLeadingHashesForBlockComment),
|
||||
(Pycodestyle, "E271") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::MultipleSpacesAfterKeyword),
|
||||
(Pycodestyle, "E272") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::MultipleSpacesBeforeKeyword),
|
||||
(Pycodestyle, "E273") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::TabAfterKeyword),
|
||||
(Pycodestyle, "E274") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::TabBeforeKeyword),
|
||||
(Pycodestyle, "E275") => (RuleGroup::Nursery, rules::pycodestyle::rules::logical_lines::MissingWhitespaceAfterKeyword),
|
||||
(Pycodestyle, "E401") => (RuleGroup::Unspecified, rules::pycodestyle::rules::MultipleImportsOnOneLine),
|
||||
(Pycodestyle, "E402") => (RuleGroup::Unspecified, rules::pycodestyle::rules::ModuleImportNotAtTopOfFile),
|
||||
(Pycodestyle, "E501") => (RuleGroup::Unspecified, rules::pycodestyle::rules::LineTooLong),
|
||||
(Pycodestyle, "E701") => (RuleGroup::Unspecified, rules::pycodestyle::rules::MultipleStatementsOnOneLineColon),
|
||||
(Pycodestyle, "E702") => (RuleGroup::Unspecified, rules::pycodestyle::rules::MultipleStatementsOnOneLineSemicolon),
|
||||
(Pycodestyle, "E703") => (RuleGroup::Unspecified, rules::pycodestyle::rules::UselessSemicolon),
|
||||
(Pycodestyle, "E711") => (RuleGroup::Unspecified, rules::pycodestyle::rules::NoneComparison),
|
||||
(Pycodestyle, "E712") => (RuleGroup::Unspecified, rules::pycodestyle::rules::TrueFalseComparison),
|
||||
(Pycodestyle, "E713") => (RuleGroup::Unspecified, rules::pycodestyle::rules::NotInTest),
|
||||
(Pycodestyle, "E714") => (RuleGroup::Unspecified, rules::pycodestyle::rules::NotIsTest),
|
||||
(Pycodestyle, "E721") => (RuleGroup::Unspecified, rules::pycodestyle::rules::TypeComparison),
|
||||
(Pycodestyle, "E722") => (RuleGroup::Unspecified, rules::pycodestyle::rules::BareExcept),
|
||||
(Pycodestyle, "E731") => (RuleGroup::Unspecified, rules::pycodestyle::rules::LambdaAssignment),
|
||||
(Pycodestyle, "E741") => (RuleGroup::Unspecified, rules::pycodestyle::rules::AmbiguousVariableName),
|
||||
(Pycodestyle, "E742") => (RuleGroup::Unspecified, rules::pycodestyle::rules::AmbiguousClassName),
|
||||
(Pycodestyle, "E743") => (RuleGroup::Unspecified, rules::pycodestyle::rules::AmbiguousFunctionName),
|
||||
(Pycodestyle, "E902") => (RuleGroup::Unspecified, rules::pycodestyle::rules::IOError),
|
||||
(Pycodestyle, "E999") => (RuleGroup::Unspecified, rules::pycodestyle::rules::SyntaxError),
|
||||
|
||||
// pycodestyle warnings
|
||||
(Pycodestyle, "W191") => (RuleGroup::Unspecified, rules::pycodestyle::rules::TabIndentation),
|
||||
(Pycodestyle, "W291") => (RuleGroup::Unspecified, rules::pycodestyle::rules::TrailingWhitespace),
|
||||
(Pycodestyle, "W292") => (RuleGroup::Unspecified, rules::pycodestyle::rules::MissingNewlineAtEndOfFile),
|
||||
(Pycodestyle, "W293") => (RuleGroup::Unspecified, rules::pycodestyle::rules::BlankLineWithWhitespace),
|
||||
(Pycodestyle, "W505") => (RuleGroup::Unspecified, rules::pycodestyle::rules::DocLineTooLong),
|
||||
(Pycodestyle, "W605") => (RuleGroup::Unspecified, rules::pycodestyle::rules::InvalidEscapeSequence),
|
||||
|
||||
// pyflakes
|
||||
(Pyflakes, "401") => (RuleGroup::Unspecified, rules::pyflakes::rules::UnusedImport),
|
||||
(Pyflakes, "402") => (RuleGroup::Unspecified, rules::pyflakes::rules::ImportShadowedByLoopVar),
|
||||
(Pyflakes, "403") => (RuleGroup::Unspecified, rules::pyflakes::rules::UndefinedLocalWithImportStar),
|
||||
(Pyflakes, "404") => (RuleGroup::Unspecified, rules::pyflakes::rules::LateFutureImport),
|
||||
(Pyflakes, "405") => (RuleGroup::Unspecified, rules::pyflakes::rules::UndefinedLocalWithImportStarUsage),
|
||||
(Pyflakes, "406") => (RuleGroup::Unspecified, rules::pyflakes::rules::UndefinedLocalWithNestedImportStarUsage),
|
||||
(Pyflakes, "407") => (RuleGroup::Unspecified, rules::pyflakes::rules::FutureFeatureNotDefined),
|
||||
(Pyflakes, "501") => (RuleGroup::Unspecified, rules::pyflakes::rules::PercentFormatInvalidFormat),
|
||||
(Pyflakes, "502") => (RuleGroup::Unspecified, rules::pyflakes::rules::PercentFormatExpectedMapping),
|
||||
(Pyflakes, "503") => (RuleGroup::Unspecified, rules::pyflakes::rules::PercentFormatExpectedSequence),
|
||||
(Pyflakes, "504") => (RuleGroup::Unspecified, rules::pyflakes::rules::PercentFormatExtraNamedArguments),
|
||||
(Pyflakes, "505") => (RuleGroup::Unspecified, rules::pyflakes::rules::PercentFormatMissingArgument),
|
||||
(Pyflakes, "506") => (RuleGroup::Unspecified, rules::pyflakes::rules::PercentFormatMixedPositionalAndNamed),
|
||||
(Pyflakes, "507") => (RuleGroup::Unspecified, rules::pyflakes::rules::PercentFormatPositionalCountMismatch),
|
||||
(Pyflakes, "508") => (RuleGroup::Unspecified, rules::pyflakes::rules::PercentFormatStarRequiresSequence),
|
||||
(Pyflakes, "509") => (RuleGroup::Unspecified, rules::pyflakes::rules::PercentFormatUnsupportedFormatCharacter),
|
||||
(Pyflakes, "521") => (RuleGroup::Unspecified, rules::pyflakes::rules::StringDotFormatInvalidFormat),
|
||||
(Pyflakes, "522") => (RuleGroup::Unspecified, rules::pyflakes::rules::StringDotFormatExtraNamedArguments),
|
||||
(Pyflakes, "523") => (RuleGroup::Unspecified, rules::pyflakes::rules::StringDotFormatExtraPositionalArguments),
|
||||
(Pyflakes, "524") => (RuleGroup::Unspecified, rules::pyflakes::rules::StringDotFormatMissingArguments),
|
||||
(Pyflakes, "525") => (RuleGroup::Unspecified, rules::pyflakes::rules::StringDotFormatMixingAutomatic),
|
||||
(Pyflakes, "541") => (RuleGroup::Unspecified, rules::pyflakes::rules::FStringMissingPlaceholders),
|
||||
(Pyflakes, "601") => (RuleGroup::Unspecified, rules::pyflakes::rules::MultiValueRepeatedKeyLiteral),
|
||||
(Pyflakes, "602") => (RuleGroup::Unspecified, rules::pyflakes::rules::MultiValueRepeatedKeyVariable),
|
||||
(Pyflakes, "621") => (RuleGroup::Unspecified, rules::pyflakes::rules::ExpressionsInStarAssignment),
|
||||
(Pyflakes, "622") => (RuleGroup::Unspecified, rules::pyflakes::rules::MultipleStarredExpressions),
|
||||
(Pyflakes, "631") => (RuleGroup::Unspecified, rules::pyflakes::rules::AssertTuple),
|
||||
(Pyflakes, "632") => (RuleGroup::Unspecified, rules::pyflakes::rules::IsLiteral),
|
||||
(Pyflakes, "633") => (RuleGroup::Unspecified, rules::pyflakes::rules::InvalidPrintSyntax),
|
||||
(Pyflakes, "634") => (RuleGroup::Unspecified, rules::pyflakes::rules::IfTuple),
|
||||
(Pyflakes, "701") => (RuleGroup::Unspecified, rules::pyflakes::rules::BreakOutsideLoop),
|
||||
(Pyflakes, "702") => (RuleGroup::Unspecified, rules::pyflakes::rules::ContinueOutsideLoop),
|
||||
(Pyflakes, "704") => (RuleGroup::Unspecified, rules::pyflakes::rules::YieldOutsideFunction),
|
||||
(Pyflakes, "706") => (RuleGroup::Unspecified, rules::pyflakes::rules::ReturnOutsideFunction),
|
||||
(Pyflakes, "707") => (RuleGroup::Unspecified, rules::pyflakes::rules::DefaultExceptNotLast),
|
||||
(Pyflakes, "722") => (RuleGroup::Unspecified, rules::pyflakes::rules::ForwardAnnotationSyntaxError),
|
||||
(Pyflakes, "811") => (RuleGroup::Unspecified, rules::pyflakes::rules::RedefinedWhileUnused),
|
||||
(Pyflakes, "821") => (RuleGroup::Unspecified, rules::pyflakes::rules::UndefinedName),
|
||||
(Pyflakes, "822") => (RuleGroup::Unspecified, rules::pyflakes::rules::UndefinedExport),
|
||||
(Pyflakes, "823") => (RuleGroup::Unspecified, rules::pyflakes::rules::UndefinedLocal),
|
||||
(Pyflakes, "841") => (RuleGroup::Unspecified, rules::pyflakes::rules::UnusedVariable),
|
||||
(Pyflakes, "842") => (RuleGroup::Unspecified, rules::pyflakes::rules::UnusedAnnotation),
|
||||
(Pyflakes, "901") => (RuleGroup::Unspecified, rules::pyflakes::rules::RaiseNotImplemented),
|
||||
|
||||
// pylint
|
||||
(Pylint, "C0105") => (RuleGroup::Unspecified, rules::pylint::rules::TypeNameIncorrectVariance),
|
||||
(Pylint, "C0131") => (RuleGroup::Unspecified, rules::pylint::rules::TypeBivariance),
|
||||
(Pylint, "C0132") => (RuleGroup::Unspecified, rules::pylint::rules::TypeParamNameMismatch),
|
||||
(Pylint, "C0205") => (RuleGroup::Unspecified, rules::pylint::rules::SingleStringSlots),
|
||||
(Pylint, "C0208") => (RuleGroup::Unspecified, rules::pylint::rules::IterationOverSet),
|
||||
(Pylint, "C0414") => (RuleGroup::Unspecified, rules::pylint::rules::UselessImportAlias),
|
||||
(Pylint, "C1901") => (RuleGroup::Nursery, rules::pylint::rules::CompareToEmptyString),
|
||||
(Pylint, "C3002") => (RuleGroup::Unspecified, rules::pylint::rules::UnnecessaryDirectLambdaCall),
|
||||
(Pylint, "E0100") => (RuleGroup::Unspecified, rules::pylint::rules::YieldInInit),
|
||||
(Pylint, "E0101") => (RuleGroup::Unspecified, rules::pylint::rules::ReturnInInit),
|
||||
(Pylint, "E0116") => (RuleGroup::Unspecified, rules::pylint::rules::ContinueInFinally),
|
||||
(Pylint, "E0117") => (RuleGroup::Unspecified, rules::pylint::rules::NonlocalWithoutBinding),
|
||||
(Pylint, "E0118") => (RuleGroup::Unspecified, rules::pylint::rules::LoadBeforeGlobalDeclaration),
|
||||
(Pylint, "E0241") => (RuleGroup::Unspecified, rules::pylint::rules::DuplicateBases),
|
||||
(Pylint, "E0302") => (RuleGroup::Unspecified, rules::pylint::rules::UnexpectedSpecialMethodSignature),
|
||||
(Pylint, "E0307") => (RuleGroup::Unspecified, rules::pylint::rules::InvalidStrReturnType),
|
||||
(Pylint, "E0604") => (RuleGroup::Unspecified, rules::pylint::rules::InvalidAllObject),
|
||||
(Pylint, "E0605") => (RuleGroup::Unspecified, rules::pylint::rules::InvalidAllFormat),
|
||||
(Pylint, "E1142") => (RuleGroup::Unspecified, rules::pylint::rules::AwaitOutsideAsync),
|
||||
(Pylint, "E1205") => (RuleGroup::Unspecified, rules::pylint::rules::LoggingTooManyArgs),
|
||||
(Pylint, "E1206") => (RuleGroup::Unspecified, rules::pylint::rules::LoggingTooFewArgs),
|
||||
(Pylint, "E1300") => (RuleGroup::Unspecified, rules::pylint::rules::BadStringFormatCharacter),
|
||||
(Pylint, "E1307") => (RuleGroup::Unspecified, rules::pylint::rules::BadStringFormatType),
|
||||
(Pylint, "E1310") => (RuleGroup::Unspecified, rules::pylint::rules::BadStrStripCall),
|
||||
(Pylint, "E1507") => (RuleGroup::Unspecified, rules::pylint::rules::InvalidEnvvarValue),
|
||||
(Pylint, "E1700") => (RuleGroup::Unspecified, rules::pylint::rules::YieldFromInAsyncFunction),
|
||||
(Pylint, "E2502") => (RuleGroup::Unspecified, rules::pylint::rules::BidirectionalUnicode),
|
||||
(Pylint, "E2510") => (RuleGroup::Unspecified, rules::pylint::rules::InvalidCharacterBackspace),
|
||||
(Pylint, "E2512") => (RuleGroup::Unspecified, rules::pylint::rules::InvalidCharacterSub),
|
||||
(Pylint, "E2513") => (RuleGroup::Unspecified, rules::pylint::rules::InvalidCharacterEsc),
|
||||
(Pylint, "E2514") => (RuleGroup::Unspecified, rules::pylint::rules::InvalidCharacterNul),
|
||||
(Pylint, "E2515") => (RuleGroup::Unspecified, rules::pylint::rules::InvalidCharacterZeroWidthSpace),
|
||||
(Pylint, "R0124") => (RuleGroup::Unspecified, rules::pylint::rules::ComparisonWithItself),
|
||||
(Pylint, "R0133") => (RuleGroup::Unspecified, rules::pylint::rules::ComparisonOfConstant),
|
||||
(Pylint, "R0206") => (RuleGroup::Unspecified, rules::pylint::rules::PropertyWithParameters),
|
||||
(Pylint, "R0402") => (RuleGroup::Unspecified, rules::pylint::rules::ManualFromImport),
|
||||
(Pylint, "R0911") => (RuleGroup::Unspecified, rules::pylint::rules::TooManyReturnStatements),
|
||||
(Pylint, "R0912") => (RuleGroup::Unspecified, rules::pylint::rules::TooManyBranches),
|
||||
(Pylint, "R0913") => (RuleGroup::Unspecified, rules::pylint::rules::TooManyArguments),
|
||||
(Pylint, "R0915") => (RuleGroup::Unspecified, rules::pylint::rules::TooManyStatements),
|
||||
(Pylint, "R1701") => (RuleGroup::Unspecified, rules::pylint::rules::RepeatedIsinstanceCalls),
|
||||
(Pylint, "R1711") => (RuleGroup::Unspecified, rules::pylint::rules::UselessReturn),
|
||||
(Pylint, "R1714") => (RuleGroup::Unspecified, rules::pylint::rules::RepeatedEqualityComparisonTarget),
|
||||
(Pylint, "R1722") => (RuleGroup::Unspecified, rules::pylint::rules::SysExitAlias),
|
||||
(Pylint, "R2004") => (RuleGroup::Unspecified, rules::pylint::rules::MagicValueComparison),
|
||||
(Pylint, "R5501") => (RuleGroup::Unspecified, rules::pylint::rules::CollapsibleElseIf),
|
||||
(Pylint, "R6301") => (RuleGroup::Nursery, rules::pylint::rules::NoSelfUse),
|
||||
(Pylint, "W0120") => (RuleGroup::Unspecified, rules::pylint::rules::UselessElseOnLoop),
|
||||
(Pylint, "W0127") => (RuleGroup::Unspecified, rules::pylint::rules::SelfAssigningVariable),
|
||||
(Pylint, "W0129") => (RuleGroup::Unspecified, rules::pylint::rules::AssertOnStringLiteral),
|
||||
(Pylint, "W0131") => (RuleGroup::Unspecified, rules::pylint::rules::NamedExprWithoutContext),
|
||||
(Pylint, "W0406") => (RuleGroup::Unspecified, rules::pylint::rules::ImportSelf),
|
||||
(Pylint, "W0602") => (RuleGroup::Unspecified, rules::pylint::rules::GlobalVariableNotAssigned),
|
||||
(Pylint, "W0603") => (RuleGroup::Unspecified, rules::pylint::rules::GlobalStatement),
|
||||
(Pylint, "W0711") => (RuleGroup::Unspecified, rules::pylint::rules::BinaryOpException),
|
||||
(Pylint, "W1508") => (RuleGroup::Unspecified, rules::pylint::rules::InvalidEnvvarDefault),
|
||||
(Pylint, "W1509") => (RuleGroup::Unspecified, rules::pylint::rules::SubprocessPopenPreexecFn),
|
||||
(Pylint, "W1510") => (RuleGroup::Unspecified, rules::pylint::rules::SubprocessRunWithoutCheck),
|
||||
(Pylint, "W1641") => (RuleGroup::Nursery, rules::pylint::rules::EqWithoutHash),
|
||||
(Pylint, "W2901") => (RuleGroup::Unspecified, rules::pylint::rules::RedefinedLoopName),
|
||||
(Pylint, "W3201") => (RuleGroup::Nursery, rules::pylint::rules::BadDunderMethodName),
|
||||
(Pylint, "W3301") => (RuleGroup::Unspecified, rules::pylint::rules::NestedMinMax),
|
||||
|
||||
// flake8-async
|
||||
(Flake8Async, "100") => (RuleGroup::Unspecified, rules::flake8_async::rules::BlockingHttpCallInAsyncFunction),
|
||||
(Flake8Async, "101") => (RuleGroup::Unspecified, rules::flake8_async::rules::OpenSleepOrSubprocessInAsyncFunction),
|
||||
(Flake8Async, "102") => (RuleGroup::Unspecified, rules::flake8_async::rules::BlockingOsCallInAsyncFunction),
|
||||
|
||||
// flake8-builtins
|
||||
(Flake8Builtins, "001") => (RuleGroup::Unspecified, rules::flake8_builtins::rules::BuiltinVariableShadowing),
|
||||
(Flake8Builtins, "002") => (RuleGroup::Unspecified, rules::flake8_builtins::rules::BuiltinArgumentShadowing),
|
||||
(Flake8Builtins, "003") => (RuleGroup::Unspecified, rules::flake8_builtins::rules::BuiltinAttributeShadowing),
|
||||
|
||||
// flake8-bugbear
|
||||
(Flake8Bugbear, "002") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::UnaryPrefixIncrementDecrement),
|
||||
(Flake8Bugbear, "003") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::AssignmentToOsEnviron),
|
||||
(Flake8Bugbear, "004") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::UnreliableCallableCheck),
|
||||
(Flake8Bugbear, "005") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::StripWithMultiCharacters),
|
||||
(Flake8Bugbear, "006") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::MutableArgumentDefault),
|
||||
(Flake8Bugbear, "007") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::UnusedLoopControlVariable),
|
||||
(Flake8Bugbear, "008") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::FunctionCallInDefaultArgument),
|
||||
(Flake8Bugbear, "009") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::GetAttrWithConstant),
|
||||
(Flake8Bugbear, "010") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::SetAttrWithConstant),
|
||||
(Flake8Bugbear, "011") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::AssertFalse),
|
||||
(Flake8Bugbear, "012") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::JumpStatementInFinally),
|
||||
(Flake8Bugbear, "013") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::RedundantTupleInExceptionHandler),
|
||||
(Flake8Bugbear, "014") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::DuplicateHandlerException),
|
||||
(Flake8Bugbear, "015") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::UselessComparison),
|
||||
(Flake8Bugbear, "016") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::RaiseLiteral),
|
||||
(Flake8Bugbear, "017") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::AssertRaisesException),
|
||||
(Flake8Bugbear, "018") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::UselessExpression),
|
||||
(Flake8Bugbear, "019") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::CachedInstanceMethod),
|
||||
(Flake8Bugbear, "020") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::LoopVariableOverridesIterator),
|
||||
(Flake8Bugbear, "021") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::FStringDocstring),
|
||||
(Flake8Bugbear, "022") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::UselessContextlibSuppress),
|
||||
(Flake8Bugbear, "023") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::FunctionUsesLoopVariable),
|
||||
(Flake8Bugbear, "024") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::AbstractBaseClassWithoutAbstractMethod),
|
||||
(Flake8Bugbear, "025") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::DuplicateTryBlockException),
|
||||
(Flake8Bugbear, "026") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::StarArgUnpackingAfterKeywordArg),
|
||||
(Flake8Bugbear, "027") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::EmptyMethodWithoutAbstractDecorator),
|
||||
(Flake8Bugbear, "028") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::NoExplicitStacklevel),
|
||||
(Flake8Bugbear, "029") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::ExceptWithEmptyTuple),
|
||||
(Flake8Bugbear, "030") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::ExceptWithNonExceptionClasses),
|
||||
(Flake8Bugbear, "031") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::ReuseOfGroupbyGenerator),
|
||||
(Flake8Bugbear, "032") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::UnintentionalTypeAnnotation),
|
||||
(Flake8Bugbear, "033") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::DuplicateValue),
|
||||
(Flake8Bugbear, "034") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::ReSubPositionalArgs),
|
||||
(Flake8Bugbear, "904") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::RaiseWithoutFromInsideExcept),
|
||||
(Flake8Bugbear, "905") => (RuleGroup::Unspecified, rules::flake8_bugbear::rules::ZipWithoutExplicitStrict),
|
||||
|
||||
// flake8-blind-except
|
||||
(Flake8BlindExcept, "001") => (RuleGroup::Unspecified, rules::flake8_blind_except::rules::BlindExcept),
|
||||
|
||||
// flake8-comprehensions
|
||||
(Flake8Comprehensions, "00") => (RuleGroup::Unspecified, rules::flake8_comprehensions::rules::UnnecessaryGeneratorList),
|
||||
(Flake8Comprehensions, "01") => (RuleGroup::Unspecified, rules::flake8_comprehensions::rules::UnnecessaryGeneratorSet),
|
||||
(Flake8Comprehensions, "02") => (RuleGroup::Unspecified, rules::flake8_comprehensions::rules::UnnecessaryGeneratorDict),
|
||||
(Flake8Comprehensions, "03") => (RuleGroup::Unspecified, rules::flake8_comprehensions::rules::UnnecessaryListComprehensionSet),
|
||||
(Flake8Comprehensions, "04") => (RuleGroup::Unspecified, rules::flake8_comprehensions::rules::UnnecessaryListComprehensionDict),
|
||||
(Flake8Comprehensions, "05") => (RuleGroup::Unspecified, rules::flake8_comprehensions::rules::UnnecessaryLiteralSet),
|
||||
(Flake8Comprehensions, "06") => (RuleGroup::Unspecified, rules::flake8_comprehensions::rules::UnnecessaryLiteralDict),
|
||||
(Flake8Comprehensions, "08") => (RuleGroup::Unspecified, rules::flake8_comprehensions::rules::UnnecessaryCollectionCall),
|
||||
(Flake8Comprehensions, "09") => (RuleGroup::Unspecified, rules::flake8_comprehensions::rules::UnnecessaryLiteralWithinTupleCall),
|
||||
(Flake8Comprehensions, "10") => (RuleGroup::Unspecified, rules::flake8_comprehensions::rules::UnnecessaryLiteralWithinListCall),
|
||||
(Flake8Comprehensions, "11") => (RuleGroup::Unspecified, rules::flake8_comprehensions::rules::UnnecessaryListCall),
|
||||
(Flake8Comprehensions, "13") => (RuleGroup::Unspecified, rules::flake8_comprehensions::rules::UnnecessaryCallAroundSorted),
|
||||
(Flake8Comprehensions, "14") => (RuleGroup::Unspecified, rules::flake8_comprehensions::rules::UnnecessaryDoubleCastOrProcess),
|
||||
(Flake8Comprehensions, "15") => (RuleGroup::Unspecified, rules::flake8_comprehensions::rules::UnnecessarySubscriptReversal),
|
||||
(Flake8Comprehensions, "16") => (RuleGroup::Unspecified, rules::flake8_comprehensions::rules::UnnecessaryComprehension),
|
||||
(Flake8Comprehensions, "17") => (RuleGroup::Unspecified, rules::flake8_comprehensions::rules::UnnecessaryMap),
|
||||
(Flake8Comprehensions, "18") => (RuleGroup::Unspecified, rules::flake8_comprehensions::rules::UnnecessaryLiteralWithinDictCall),
|
||||
(Flake8Comprehensions, "19") => (RuleGroup::Unspecified, rules::flake8_comprehensions::rules::UnnecessaryComprehensionAnyAll),
|
||||
|
||||
// flake8-debugger
|
||||
(Flake8Debugger, "0") => (RuleGroup::Unspecified, rules::flake8_debugger::rules::Debugger),
|
||||
|
||||
// mccabe
|
||||
(McCabe, "1") => (RuleGroup::Unspecified, rules::mccabe::rules::ComplexStructure),
|
||||
|
||||
// flake8-tidy-imports
|
||||
(Flake8TidyImports, "251") => (RuleGroup::Unspecified, rules::flake8_tidy_imports::rules::BannedApi),
|
||||
(Flake8TidyImports, "252") => (RuleGroup::Unspecified, rules::flake8_tidy_imports::rules::RelativeImports),
|
||||
(Flake8TidyImports, "253") => (RuleGroup::Unspecified, rules::flake8_tidy_imports::rules::BannedModuleLevelImports),
|
||||
|
||||
// flake8-return
|
||||
(Flake8Return, "501") => (RuleGroup::Unspecified, rules::flake8_return::rules::UnnecessaryReturnNone),
|
||||
(Flake8Return, "502") => (RuleGroup::Unspecified, rules::flake8_return::rules::ImplicitReturnValue),
|
||||
(Flake8Return, "503") => (RuleGroup::Unspecified, rules::flake8_return::rules::ImplicitReturn),
|
||||
(Flake8Return, "504") => (RuleGroup::Unspecified, rules::flake8_return::rules::UnnecessaryAssign),
|
||||
(Flake8Return, "505") => (RuleGroup::Unspecified, rules::flake8_return::rules::SuperfluousElseReturn),
|
||||
(Flake8Return, "506") => (RuleGroup::Unspecified, rules::flake8_return::rules::SuperfluousElseRaise),
|
||||
(Flake8Return, "507") => (RuleGroup::Unspecified, rules::flake8_return::rules::SuperfluousElseContinue),
|
||||
(Flake8Return, "508") => (RuleGroup::Unspecified, rules::flake8_return::rules::SuperfluousElseBreak),
|
||||
|
||||
// flake8-gettext
|
||||
(Flake8GetText, "001") => (RuleGroup::Unspecified, rules::flake8_gettext::rules::FStringInGetTextFuncCall),
|
||||
(Flake8GetText, "002") => (RuleGroup::Unspecified, rules::flake8_gettext::rules::FormatInGetTextFuncCall),
|
||||
(Flake8GetText, "003") => (RuleGroup::Unspecified, rules::flake8_gettext::rules::PrintfInGetTextFuncCall),
|
||||
|
||||
// flake8-implicit-str-concat
|
||||
(Flake8ImplicitStrConcat, "001") => (RuleGroup::Unspecified, rules::flake8_implicit_str_concat::rules::SingleLineImplicitStringConcatenation),
|
||||
(Flake8ImplicitStrConcat, "002") => (RuleGroup::Unspecified, rules::flake8_implicit_str_concat::rules::MultiLineImplicitStringConcatenation),
|
||||
(Flake8ImplicitStrConcat, "003") => (RuleGroup::Unspecified, rules::flake8_implicit_str_concat::rules::ExplicitStringConcatenation),
|
||||
|
||||
// flake8-print
|
||||
(Flake8Print, "1") => (RuleGroup::Unspecified, rules::flake8_print::rules::Print),
|
||||
(Flake8Print, "3") => (RuleGroup::Unspecified, rules::flake8_print::rules::PPrint),
|
||||
|
||||
// flake8-quotes
|
||||
(Flake8Quotes, "000") => (RuleGroup::Unspecified, rules::flake8_quotes::rules::BadQuotesInlineString),
|
||||
(Flake8Quotes, "001") => (RuleGroup::Unspecified, rules::flake8_quotes::rules::BadQuotesMultilineString),
|
||||
(Flake8Quotes, "002") => (RuleGroup::Unspecified, rules::flake8_quotes::rules::BadQuotesDocstring),
|
||||
(Flake8Quotes, "003") => (RuleGroup::Unspecified, rules::flake8_quotes::rules::AvoidableEscapedQuote),
|
||||
|
||||
// flake8-annotations
|
||||
(Flake8Annotations, "001") => (RuleGroup::Unspecified, rules::flake8_annotations::rules::MissingTypeFunctionArgument),
|
||||
(Flake8Annotations, "002") => (RuleGroup::Unspecified, rules::flake8_annotations::rules::MissingTypeArgs),
|
||||
(Flake8Annotations, "003") => (RuleGroup::Unspecified, rules::flake8_annotations::rules::MissingTypeKwargs),
|
||||
(Flake8Annotations, "101") => (RuleGroup::Unspecified, rules::flake8_annotations::rules::MissingTypeSelf),
|
||||
(Flake8Annotations, "102") => (RuleGroup::Unspecified, rules::flake8_annotations::rules::MissingTypeCls),
|
||||
(Flake8Annotations, "201") => (RuleGroup::Unspecified, rules::flake8_annotations::rules::MissingReturnTypeUndocumentedPublicFunction),
|
||||
(Flake8Annotations, "202") => (RuleGroup::Unspecified, rules::flake8_annotations::rules::MissingReturnTypePrivateFunction),
|
||||
(Flake8Annotations, "204") => (RuleGroup::Unspecified, rules::flake8_annotations::rules::MissingReturnTypeSpecialMethod),
|
||||
(Flake8Annotations, "205") => (RuleGroup::Unspecified, rules::flake8_annotations::rules::MissingReturnTypeStaticMethod),
|
||||
(Flake8Annotations, "206") => (RuleGroup::Unspecified, rules::flake8_annotations::rules::MissingReturnTypeClassMethod),
|
||||
(Flake8Annotations, "401") => (RuleGroup::Unspecified, rules::flake8_annotations::rules::AnyType),
|
||||
|
||||
// flake8-future-annotations
|
||||
(Flake8FutureAnnotations, "100") => (RuleGroup::Unspecified, rules::flake8_future_annotations::rules::FutureRewritableTypeAnnotation),
|
||||
(Flake8FutureAnnotations, "102") => (RuleGroup::Unspecified, rules::flake8_future_annotations::rules::FutureRequiredTypeAnnotation),
|
||||
|
||||
// flake8-2020
|
||||
(Flake82020, "101") => (RuleGroup::Unspecified, rules::flake8_2020::rules::SysVersionSlice3),
|
||||
(Flake82020, "102") => (RuleGroup::Unspecified, rules::flake8_2020::rules::SysVersion2),
|
||||
(Flake82020, "103") => (RuleGroup::Unspecified, rules::flake8_2020::rules::SysVersionCmpStr3),
|
||||
(Flake82020, "201") => (RuleGroup::Unspecified, rules::flake8_2020::rules::SysVersionInfo0Eq3),
|
||||
(Flake82020, "202") => (RuleGroup::Unspecified, rules::flake8_2020::rules::SixPY3),
|
||||
(Flake82020, "203") => (RuleGroup::Unspecified, rules::flake8_2020::rules::SysVersionInfo1CmpInt),
|
||||
(Flake82020, "204") => (RuleGroup::Unspecified, rules::flake8_2020::rules::SysVersionInfoMinorCmpInt),
|
||||
(Flake82020, "301") => (RuleGroup::Unspecified, rules::flake8_2020::rules::SysVersion0),
|
||||
(Flake82020, "302") => (RuleGroup::Unspecified, rules::flake8_2020::rules::SysVersionCmpStr10),
|
||||
(Flake82020, "303") => (RuleGroup::Unspecified, rules::flake8_2020::rules::SysVersionSlice1),
|
||||
|
||||
// flake8-simplify
|
||||
(Flake8Simplify, "101") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::DuplicateIsinstanceCall),
|
||||
(Flake8Simplify, "102") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::CollapsibleIf),
|
||||
(Flake8Simplify, "103") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::NeedlessBool),
|
||||
(Flake8Simplify, "105") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::SuppressibleException),
|
||||
(Flake8Simplify, "107") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::ReturnInTryExceptFinally),
|
||||
(Flake8Simplify, "108") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::IfElseBlockInsteadOfIfExp),
|
||||
(Flake8Simplify, "109") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::CompareWithTuple),
|
||||
(Flake8Simplify, "110") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::ReimplementedBuiltin),
|
||||
(Flake8Simplify, "112") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::UncapitalizedEnvironmentVariables),
|
||||
(Flake8Simplify, "114") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::IfWithSameArms),
|
||||
(Flake8Simplify, "115") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::OpenFileWithContextHandler),
|
||||
(Flake8Simplify, "116") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::IfElseBlockInsteadOfDictLookup),
|
||||
(Flake8Simplify, "117") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::MultipleWithStatements),
|
||||
(Flake8Simplify, "118") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::InDictKeys),
|
||||
(Flake8Simplify, "201") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::NegateEqualOp),
|
||||
(Flake8Simplify, "202") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::NegateNotEqualOp),
|
||||
(Flake8Simplify, "208") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::DoubleNegation),
|
||||
(Flake8Simplify, "210") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::IfExprWithTrueFalse),
|
||||
(Flake8Simplify, "211") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::IfExprWithFalseTrue),
|
||||
(Flake8Simplify, "212") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::IfExprWithTwistedArms),
|
||||
(Flake8Simplify, "220") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::ExprAndNotExpr),
|
||||
(Flake8Simplify, "221") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::ExprOrNotExpr),
|
||||
(Flake8Simplify, "222") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::ExprOrTrue),
|
||||
(Flake8Simplify, "223") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::ExprAndFalse),
|
||||
(Flake8Simplify, "300") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::YodaConditions),
|
||||
(Flake8Simplify, "401") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::IfElseBlockInsteadOfDictGet),
|
||||
(Flake8Simplify, "910") => (RuleGroup::Unspecified, rules::flake8_simplify::rules::DictGetWithNoneDefault),
|
||||
|
||||
// flake8-copyright
|
||||
(Flake8Copyright, "001") => (RuleGroup::Nursery, rules::flake8_copyright::rules::MissingCopyrightNotice),
|
||||
|
||||
// pyupgrade
|
||||
(Pyupgrade, "001") => (RuleGroup::Unspecified, rules::pyupgrade::rules::UselessMetaclassType),
|
||||
(Pyupgrade, "003") => (RuleGroup::Unspecified, rules::pyupgrade::rules::TypeOfPrimitive),
|
||||
(Pyupgrade, "004") => (RuleGroup::Unspecified, rules::pyupgrade::rules::UselessObjectInheritance),
|
||||
(Pyupgrade, "005") => (RuleGroup::Unspecified, rules::pyupgrade::rules::DeprecatedUnittestAlias),
|
||||
(Pyupgrade, "006") => (RuleGroup::Unspecified, rules::pyupgrade::rules::NonPEP585Annotation),
|
||||
(Pyupgrade, "007") => (RuleGroup::Unspecified, rules::pyupgrade::rules::NonPEP604Annotation),
|
||||
(Pyupgrade, "008") => (RuleGroup::Unspecified, rules::pyupgrade::rules::SuperCallWithParameters),
|
||||
(Pyupgrade, "009") => (RuleGroup::Unspecified, rules::pyupgrade::rules::UTF8EncodingDeclaration),
|
||||
(Pyupgrade, "010") => (RuleGroup::Unspecified, rules::pyupgrade::rules::UnnecessaryFutureImport),
|
||||
(Pyupgrade, "011") => (RuleGroup::Unspecified, rules::pyupgrade::rules::LRUCacheWithoutParameters),
|
||||
(Pyupgrade, "012") => (RuleGroup::Unspecified, rules::pyupgrade::rules::UnnecessaryEncodeUTF8),
|
||||
(Pyupgrade, "013") => (RuleGroup::Unspecified, rules::pyupgrade::rules::ConvertTypedDictFunctionalToClass),
|
||||
(Pyupgrade, "014") => (RuleGroup::Unspecified, rules::pyupgrade::rules::ConvertNamedTupleFunctionalToClass),
|
||||
(Pyupgrade, "015") => (RuleGroup::Unspecified, rules::pyupgrade::rules::RedundantOpenModes),
|
||||
(Pyupgrade, "017") => (RuleGroup::Unspecified, rules::pyupgrade::rules::DatetimeTimezoneUTC),
|
||||
(Pyupgrade, "018") => (RuleGroup::Unspecified, rules::pyupgrade::rules::NativeLiterals),
|
||||
(Pyupgrade, "019") => (RuleGroup::Unspecified, rules::pyupgrade::rules::TypingTextStrAlias),
|
||||
(Pyupgrade, "020") => (RuleGroup::Unspecified, rules::pyupgrade::rules::OpenAlias),
|
||||
(Pyupgrade, "021") => (RuleGroup::Unspecified, rules::pyupgrade::rules::ReplaceUniversalNewlines),
|
||||
(Pyupgrade, "022") => (RuleGroup::Unspecified, rules::pyupgrade::rules::ReplaceStdoutStderr),
|
||||
(Pyupgrade, "023") => (RuleGroup::Unspecified, rules::pyupgrade::rules::DeprecatedCElementTree),
|
||||
(Pyupgrade, "024") => (RuleGroup::Unspecified, rules::pyupgrade::rules::OSErrorAlias),
|
||||
(Pyupgrade, "025") => (RuleGroup::Unspecified, rules::pyupgrade::rules::UnicodeKindPrefix),
|
||||
(Pyupgrade, "026") => (RuleGroup::Unspecified, rules::pyupgrade::rules::DeprecatedMockImport),
|
||||
(Pyupgrade, "027") => (RuleGroup::Unspecified, rules::pyupgrade::rules::UnpackedListComprehension),
|
||||
(Pyupgrade, "028") => (RuleGroup::Unspecified, rules::pyupgrade::rules::YieldInForLoop),
|
||||
(Pyupgrade, "029") => (RuleGroup::Unspecified, rules::pyupgrade::rules::UnnecessaryBuiltinImport),
|
||||
(Pyupgrade, "030") => (RuleGroup::Unspecified, rules::pyupgrade::rules::FormatLiterals),
|
||||
(Pyupgrade, "031") => (RuleGroup::Unspecified, rules::pyupgrade::rules::PrintfStringFormatting),
|
||||
(Pyupgrade, "032") => (RuleGroup::Unspecified, rules::pyupgrade::rules::FString),
|
||||
(Pyupgrade, "033") => (RuleGroup::Unspecified, rules::pyupgrade::rules::LRUCacheWithMaxsizeNone),
|
||||
(Pyupgrade, "034") => (RuleGroup::Unspecified, rules::pyupgrade::rules::ExtraneousParentheses),
|
||||
(Pyupgrade, "035") => (RuleGroup::Unspecified, rules::pyupgrade::rules::DeprecatedImport),
|
||||
(Pyupgrade, "036") => (RuleGroup::Unspecified, rules::pyupgrade::rules::OutdatedVersionBlock),
|
||||
(Pyupgrade, "037") => (RuleGroup::Unspecified, rules::pyupgrade::rules::QuotedAnnotation),
|
||||
(Pyupgrade, "038") => (RuleGroup::Unspecified, rules::pyupgrade::rules::NonPEP604Isinstance),
|
||||
(Pyupgrade, "039") => (RuleGroup::Unspecified, rules::pyupgrade::rules::UnnecessaryClassParentheses),
|
||||
(Pyupgrade, "040") => (RuleGroup::Unspecified, rules::pyupgrade::rules::NonPEP695TypeAlias),
|
||||
|
||||
// pydocstyle
|
||||
(Pydocstyle, "100") => (RuleGroup::Unspecified, rules::pydocstyle::rules::UndocumentedPublicModule),
|
||||
(Pydocstyle, "101") => (RuleGroup::Unspecified, rules::pydocstyle::rules::UndocumentedPublicClass),
|
||||
(Pydocstyle, "102") => (RuleGroup::Unspecified, rules::pydocstyle::rules::UndocumentedPublicMethod),
|
||||
(Pydocstyle, "103") => (RuleGroup::Unspecified, rules::pydocstyle::rules::UndocumentedPublicFunction),
|
||||
(Pydocstyle, "104") => (RuleGroup::Unspecified, rules::pydocstyle::rules::UndocumentedPublicPackage),
|
||||
(Pydocstyle, "105") => (RuleGroup::Unspecified, rules::pydocstyle::rules::UndocumentedMagicMethod),
|
||||
(Pydocstyle, "106") => (RuleGroup::Unspecified, rules::pydocstyle::rules::UndocumentedPublicNestedClass),
|
||||
(Pydocstyle, "107") => (RuleGroup::Unspecified, rules::pydocstyle::rules::UndocumentedPublicInit),
|
||||
(Pydocstyle, "200") => (RuleGroup::Unspecified, rules::pydocstyle::rules::FitsOnOneLine),
|
||||
(Pydocstyle, "201") => (RuleGroup::Unspecified, rules::pydocstyle::rules::NoBlankLineBeforeFunction),
|
||||
(Pydocstyle, "202") => (RuleGroup::Unspecified, rules::pydocstyle::rules::NoBlankLineAfterFunction),
|
||||
(Pydocstyle, "203") => (RuleGroup::Unspecified, rules::pydocstyle::rules::OneBlankLineBeforeClass),
|
||||
(Pydocstyle, "204") => (RuleGroup::Unspecified, rules::pydocstyle::rules::OneBlankLineAfterClass),
|
||||
(Pydocstyle, "205") => (RuleGroup::Unspecified, rules::pydocstyle::rules::BlankLineAfterSummary),
|
||||
(Pydocstyle, "206") => (RuleGroup::Unspecified, rules::pydocstyle::rules::IndentWithSpaces),
|
||||
(Pydocstyle, "207") => (RuleGroup::Unspecified, rules::pydocstyle::rules::UnderIndentation),
|
||||
(Pydocstyle, "208") => (RuleGroup::Unspecified, rules::pydocstyle::rules::OverIndentation),
|
||||
(Pydocstyle, "209") => (RuleGroup::Unspecified, rules::pydocstyle::rules::NewLineAfterLastParagraph),
|
||||
(Pydocstyle, "210") => (RuleGroup::Unspecified, rules::pydocstyle::rules::SurroundingWhitespace),
|
||||
(Pydocstyle, "211") => (RuleGroup::Unspecified, rules::pydocstyle::rules::BlankLineBeforeClass),
|
||||
(Pydocstyle, "212") => (RuleGroup::Unspecified, rules::pydocstyle::rules::MultiLineSummaryFirstLine),
|
||||
(Pydocstyle, "213") => (RuleGroup::Unspecified, rules::pydocstyle::rules::MultiLineSummarySecondLine),
|
||||
(Pydocstyle, "214") => (RuleGroup::Unspecified, rules::pydocstyle::rules::SectionNotOverIndented),
|
||||
(Pydocstyle, "215") => (RuleGroup::Unspecified, rules::pydocstyle::rules::SectionUnderlineNotOverIndented),
|
||||
(Pydocstyle, "300") => (RuleGroup::Unspecified, rules::pydocstyle::rules::TripleSingleQuotes),
|
||||
(Pydocstyle, "301") => (RuleGroup::Unspecified, rules::pydocstyle::rules::EscapeSequenceInDocstring),
|
||||
(Pydocstyle, "400") => (RuleGroup::Unspecified, rules::pydocstyle::rules::EndsInPeriod),
|
||||
(Pydocstyle, "401") => (RuleGroup::Unspecified, rules::pydocstyle::rules::NonImperativeMood),
|
||||
(Pydocstyle, "402") => (RuleGroup::Unspecified, rules::pydocstyle::rules::NoSignature),
|
||||
(Pydocstyle, "403") => (RuleGroup::Unspecified, rules::pydocstyle::rules::FirstLineCapitalized),
|
||||
(Pydocstyle, "404") => (RuleGroup::Unspecified, rules::pydocstyle::rules::DocstringStartsWithThis),
|
||||
(Pydocstyle, "405") => (RuleGroup::Unspecified, rules::pydocstyle::rules::CapitalizeSectionName),
|
||||
(Pydocstyle, "406") => (RuleGroup::Unspecified, rules::pydocstyle::rules::NewLineAfterSectionName),
|
||||
(Pydocstyle, "407") => (RuleGroup::Unspecified, rules::pydocstyle::rules::DashedUnderlineAfterSection),
|
||||
(Pydocstyle, "408") => (RuleGroup::Unspecified, rules::pydocstyle::rules::SectionUnderlineAfterName),
|
||||
(Pydocstyle, "409") => (RuleGroup::Unspecified, rules::pydocstyle::rules::SectionUnderlineMatchesSectionLength),
|
||||
(Pydocstyle, "410") => (RuleGroup::Unspecified, rules::pydocstyle::rules::NoBlankLineAfterSection),
|
||||
(Pydocstyle, "411") => (RuleGroup::Unspecified, rules::pydocstyle::rules::NoBlankLineBeforeSection),
|
||||
(Pydocstyle, "412") => (RuleGroup::Unspecified, rules::pydocstyle::rules::BlankLinesBetweenHeaderAndContent),
|
||||
(Pydocstyle, "413") => (RuleGroup::Unspecified, rules::pydocstyle::rules::BlankLineAfterLastSection),
|
||||
(Pydocstyle, "414") => (RuleGroup::Unspecified, rules::pydocstyle::rules::EmptyDocstringSection),
|
||||
(Pydocstyle, "415") => (RuleGroup::Unspecified, rules::pydocstyle::rules::EndsInPunctuation),
|
||||
(Pydocstyle, "416") => (RuleGroup::Unspecified, rules::pydocstyle::rules::SectionNameEndsInColon),
|
||||
(Pydocstyle, "417") => (RuleGroup::Unspecified, rules::pydocstyle::rules::UndocumentedParam),
|
||||
(Pydocstyle, "418") => (RuleGroup::Unspecified, rules::pydocstyle::rules::OverloadWithDocstring),
|
||||
(Pydocstyle, "419") => (RuleGroup::Unspecified, rules::pydocstyle::rules::EmptyDocstring),
|
||||
|
||||
// pep8-naming
|
||||
(PEP8Naming, "801") => (RuleGroup::Unspecified, rules::pep8_naming::rules::InvalidClassName),
|
||||
(PEP8Naming, "802") => (RuleGroup::Unspecified, rules::pep8_naming::rules::InvalidFunctionName),
|
||||
(PEP8Naming, "803") => (RuleGroup::Unspecified, rules::pep8_naming::rules::InvalidArgumentName),
|
||||
(PEP8Naming, "804") => (RuleGroup::Unspecified, rules::pep8_naming::rules::InvalidFirstArgumentNameForClassMethod),
|
||||
(PEP8Naming, "805") => (RuleGroup::Unspecified, rules::pep8_naming::rules::InvalidFirstArgumentNameForMethod),
|
||||
(PEP8Naming, "806") => (RuleGroup::Unspecified, rules::pep8_naming::rules::NonLowercaseVariableInFunction),
|
||||
(PEP8Naming, "807") => (RuleGroup::Unspecified, rules::pep8_naming::rules::DunderFunctionName),
|
||||
(PEP8Naming, "811") => (RuleGroup::Unspecified, rules::pep8_naming::rules::ConstantImportedAsNonConstant),
|
||||
(PEP8Naming, "812") => (RuleGroup::Unspecified, rules::pep8_naming::rules::LowercaseImportedAsNonLowercase),
|
||||
(PEP8Naming, "813") => (RuleGroup::Unspecified, rules::pep8_naming::rules::CamelcaseImportedAsLowercase),
|
||||
(PEP8Naming, "814") => (RuleGroup::Unspecified, rules::pep8_naming::rules::CamelcaseImportedAsConstant),
|
||||
(PEP8Naming, "815") => (RuleGroup::Unspecified, rules::pep8_naming::rules::MixedCaseVariableInClassScope),
|
||||
(PEP8Naming, "816") => (RuleGroup::Unspecified, rules::pep8_naming::rules::MixedCaseVariableInGlobalScope),
|
||||
(PEP8Naming, "817") => (RuleGroup::Unspecified, rules::pep8_naming::rules::CamelcaseImportedAsAcronym),
|
||||
(PEP8Naming, "818") => (RuleGroup::Unspecified, rules::pep8_naming::rules::ErrorSuffixOnExceptionName),
|
||||
(PEP8Naming, "999") => (RuleGroup::Unspecified, rules::pep8_naming::rules::InvalidModuleName),
|
||||
|
||||
// isort
|
||||
(Isort, "001") => (RuleGroup::Unspecified, rules::isort::rules::UnsortedImports),
|
||||
(Isort, "002") => (RuleGroup::Unspecified, rules::isort::rules::MissingRequiredImport),
|
||||
|
||||
// eradicate
|
||||
(Eradicate, "001") => (RuleGroup::Unspecified, rules::eradicate::rules::CommentedOutCode),
|
||||
|
||||
// flake8-bandit
|
||||
(Flake8Bandit, "101") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::Assert),
|
||||
(Flake8Bandit, "102") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::ExecBuiltin),
|
||||
(Flake8Bandit, "103") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::BadFilePermissions),
|
||||
(Flake8Bandit, "104") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::HardcodedBindAllInterfaces),
|
||||
(Flake8Bandit, "105") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::HardcodedPasswordString),
|
||||
(Flake8Bandit, "106") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::HardcodedPasswordFuncArg),
|
||||
(Flake8Bandit, "107") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::HardcodedPasswordDefault),
|
||||
(Flake8Bandit, "108") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::HardcodedTempFile),
|
||||
(Flake8Bandit, "110") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::TryExceptPass),
|
||||
(Flake8Bandit, "112") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::TryExceptContinue),
|
||||
(Flake8Bandit, "113") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::RequestWithoutTimeout),
|
||||
(Flake8Bandit, "301") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousPickleUsage),
|
||||
(Flake8Bandit, "302") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousMarshalUsage),
|
||||
(Flake8Bandit, "303") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousInsecureHashUsage),
|
||||
(Flake8Bandit, "304") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousInsecureCipherUsage),
|
||||
(Flake8Bandit, "305") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousInsecureCipherModeUsage),
|
||||
(Flake8Bandit, "306") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousMktempUsage),
|
||||
(Flake8Bandit, "307") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousEvalUsage),
|
||||
(Flake8Bandit, "308") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousMarkSafeUsage),
|
||||
(Flake8Bandit, "310") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousURLOpenUsage),
|
||||
(Flake8Bandit, "311") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousNonCryptographicRandomUsage),
|
||||
(Flake8Bandit, "312") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousTelnetUsage),
|
||||
(Flake8Bandit, "313") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousXMLCElementTreeUsage),
|
||||
(Flake8Bandit, "314") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousXMLElementTreeUsage),
|
||||
(Flake8Bandit, "315") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousXMLExpatReaderUsage),
|
||||
(Flake8Bandit, "316") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousXMLExpatBuilderUsage),
|
||||
(Flake8Bandit, "317") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousXMLSaxUsage),
|
||||
(Flake8Bandit, "318") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousXMLMiniDOMUsage),
|
||||
(Flake8Bandit, "319") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousXMLPullDOMUsage),
|
||||
(Flake8Bandit, "320") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousXMLETreeUsage),
|
||||
(Flake8Bandit, "321") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousFTPLibUsage),
|
||||
(Flake8Bandit, "323") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SuspiciousUnverifiedContextUsage),
|
||||
(Flake8Bandit, "324") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::HashlibInsecureHashFunction),
|
||||
(Flake8Bandit, "501") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::RequestWithNoCertValidation),
|
||||
(Flake8Bandit, "506") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::UnsafeYAMLLoad),
|
||||
(Flake8Bandit, "508") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SnmpInsecureVersion),
|
||||
(Flake8Bandit, "509") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SnmpWeakCryptography),
|
||||
(Flake8Bandit, "601") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::ParamikoCall),
|
||||
(Flake8Bandit, "602") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SubprocessPopenWithShellEqualsTrue),
|
||||
(Flake8Bandit, "603") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::SubprocessWithoutShellEqualsTrue),
|
||||
(Flake8Bandit, "604") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::CallWithShellEqualsTrue),
|
||||
(Flake8Bandit, "605") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::StartProcessWithAShell),
|
||||
(Flake8Bandit, "606") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::StartProcessWithNoShell),
|
||||
(Flake8Bandit, "607") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::StartProcessWithPartialPath),
|
||||
(Flake8Bandit, "608") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::HardcodedSQLExpression),
|
||||
(Flake8Bandit, "609") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::UnixCommandWildcardInjection),
|
||||
(Flake8Bandit, "612") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::LoggingConfigInsecureListen),
|
||||
(Flake8Bandit, "701") => (RuleGroup::Unspecified, rules::flake8_bandit::rules::Jinja2AutoescapeFalse),
|
||||
|
||||
// flake8-boolean-trap
|
||||
(Flake8BooleanTrap, "001") => (RuleGroup::Unspecified, rules::flake8_boolean_trap::rules::BooleanTypeHintPositionalArgument),
|
||||
(Flake8BooleanTrap, "002") => (RuleGroup::Unspecified, rules::flake8_boolean_trap::rules::BooleanDefaultValuePositionalArgument),
|
||||
(Flake8BooleanTrap, "003") => (RuleGroup::Unspecified, rules::flake8_boolean_trap::rules::BooleanPositionalValueInCall),
|
||||
|
||||
// flake8-unused-arguments
|
||||
(Flake8UnusedArguments, "001") => (RuleGroup::Unspecified, rules::flake8_unused_arguments::rules::UnusedFunctionArgument),
|
||||
(Flake8UnusedArguments, "002") => (RuleGroup::Unspecified, rules::flake8_unused_arguments::rules::UnusedMethodArgument),
|
||||
(Flake8UnusedArguments, "003") => (RuleGroup::Unspecified, rules::flake8_unused_arguments::rules::UnusedClassMethodArgument),
|
||||
(Flake8UnusedArguments, "004") => (RuleGroup::Unspecified, rules::flake8_unused_arguments::rules::UnusedStaticMethodArgument),
|
||||
(Flake8UnusedArguments, "005") => (RuleGroup::Unspecified, rules::flake8_unused_arguments::rules::UnusedLambdaArgument),
|
||||
|
||||
// flake8-import-conventions
|
||||
(Flake8ImportConventions, "001") => (RuleGroup::Unspecified, rules::flake8_import_conventions::rules::UnconventionalImportAlias),
|
||||
(Flake8ImportConventions, "002") => (RuleGroup::Unspecified, rules::flake8_import_conventions::rules::BannedImportAlias),
|
||||
(Flake8ImportConventions, "003") => (RuleGroup::Unspecified, rules::flake8_import_conventions::rules::BannedImportFrom),
|
||||
|
||||
// flake8-datetimez
|
||||
(Flake8Datetimez, "001") => (RuleGroup::Unspecified, rules::flake8_datetimez::rules::CallDatetimeWithoutTzinfo),
|
||||
(Flake8Datetimez, "002") => (RuleGroup::Unspecified, rules::flake8_datetimez::rules::CallDatetimeToday),
|
||||
(Flake8Datetimez, "003") => (RuleGroup::Unspecified, rules::flake8_datetimez::rules::CallDatetimeUtcnow),
|
||||
(Flake8Datetimez, "004") => (RuleGroup::Unspecified, rules::flake8_datetimez::rules::CallDatetimeUtcfromtimestamp),
|
||||
(Flake8Datetimez, "005") => (RuleGroup::Unspecified, rules::flake8_datetimez::rules::CallDatetimeNowWithoutTzinfo),
|
||||
(Flake8Datetimez, "006") => (RuleGroup::Unspecified, rules::flake8_datetimez::rules::CallDatetimeFromtimestamp),
|
||||
(Flake8Datetimez, "007") => (RuleGroup::Unspecified, rules::flake8_datetimez::rules::CallDatetimeStrptimeWithoutZone),
|
||||
(Flake8Datetimez, "011") => (RuleGroup::Unspecified, rules::flake8_datetimez::rules::CallDateToday),
|
||||
(Flake8Datetimez, "012") => (RuleGroup::Unspecified, rules::flake8_datetimez::rules::CallDateFromtimestamp),
|
||||
|
||||
// pygrep-hooks
|
||||
(PygrepHooks, "001") => (RuleGroup::Unspecified, rules::pygrep_hooks::rules::Eval),
|
||||
(PygrepHooks, "002") => (RuleGroup::Unspecified, rules::pygrep_hooks::rules::DeprecatedLogWarn),
|
||||
(PygrepHooks, "003") => (RuleGroup::Unspecified, rules::pygrep_hooks::rules::BlanketTypeIgnore),
|
||||
(PygrepHooks, "004") => (RuleGroup::Unspecified, rules::pygrep_hooks::rules::BlanketNOQA),
|
||||
(PygrepHooks, "005") => (RuleGroup::Unspecified, rules::pygrep_hooks::rules::InvalidMockAccess),
|
||||
|
||||
// pandas-vet
|
||||
(PandasVet, "002") => (RuleGroup::Unspecified, rules::pandas_vet::rules::PandasUseOfInplaceArgument),
|
||||
(PandasVet, "003") => (RuleGroup::Unspecified, rules::pandas_vet::rules::PandasUseOfDotIsNull),
|
||||
(PandasVet, "004") => (RuleGroup::Unspecified, rules::pandas_vet::rules::PandasUseOfDotNotNull),
|
||||
(PandasVet, "007") => (RuleGroup::Unspecified, rules::pandas_vet::rules::PandasUseOfDotIx),
|
||||
(PandasVet, "008") => (RuleGroup::Unspecified, rules::pandas_vet::rules::PandasUseOfDotAt),
|
||||
(PandasVet, "009") => (RuleGroup::Unspecified, rules::pandas_vet::rules::PandasUseOfDotIat),
|
||||
(PandasVet, "010") => (RuleGroup::Unspecified, rules::pandas_vet::rules::PandasUseOfDotPivotOrUnstack),
|
||||
(PandasVet, "011") => (RuleGroup::Unspecified, rules::pandas_vet::rules::PandasUseOfDotValues),
|
||||
(PandasVet, "012") => (RuleGroup::Unspecified, rules::pandas_vet::rules::PandasUseOfDotReadTable),
|
||||
(PandasVet, "013") => (RuleGroup::Unspecified, rules::pandas_vet::rules::PandasUseOfDotStack),
|
||||
(PandasVet, "015") => (RuleGroup::Unspecified, rules::pandas_vet::rules::PandasUseOfPdMerge),
|
||||
(PandasVet, "101") => (RuleGroup::Unspecified, rules::pandas_vet::rules::PandasNuniqueConstantSeriesCheck),
|
||||
(PandasVet, "901") => (RuleGroup::Unspecified, rules::pandas_vet::rules::PandasDfVariableName),
|
||||
|
||||
// flake8-errmsg
|
||||
(Flake8ErrMsg, "101") => (RuleGroup::Unspecified, rules::flake8_errmsg::rules::RawStringInException),
|
||||
(Flake8ErrMsg, "102") => (RuleGroup::Unspecified, rules::flake8_errmsg::rules::FStringInException),
|
||||
(Flake8ErrMsg, "103") => (RuleGroup::Unspecified, rules::flake8_errmsg::rules::DotFormatInException),
|
||||
|
||||
// flake8-pyi
|
||||
(Flake8Pyi, "001") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnprefixedTypeParam),
|
||||
(Flake8Pyi, "002") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::ComplexIfStatementInStub),
|
||||
(Flake8Pyi, "003") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnrecognizedVersionInfoCheck),
|
||||
(Flake8Pyi, "004") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::PatchVersionComparison),
|
||||
(Flake8Pyi, "005") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::WrongTupleLengthVersionComparison),
|
||||
(Flake8Pyi, "006") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::BadVersionInfoComparison),
|
||||
(Flake8Pyi, "007") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnrecognizedPlatformCheck),
|
||||
(Flake8Pyi, "008") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnrecognizedPlatformName),
|
||||
(Flake8Pyi, "009") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::PassStatementStubBody),
|
||||
(Flake8Pyi, "010") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::NonEmptyStubBody),
|
||||
(Flake8Pyi, "011") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::TypedArgumentDefaultInStub),
|
||||
(Flake8Pyi, "012") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::PassInClassBody),
|
||||
(Flake8Pyi, "013") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::EllipsisInNonEmptyClassBody),
|
||||
(Flake8Pyi, "014") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::ArgumentDefaultInStub),
|
||||
(Flake8Pyi, "015") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::AssignmentDefaultInStub),
|
||||
(Flake8Pyi, "016") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::DuplicateUnionMember),
|
||||
(Flake8Pyi, "017") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::ComplexAssignmentInStub),
|
||||
(Flake8Pyi, "018") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnusedPrivateTypeVar),
|
||||
(Flake8Pyi, "019") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::CustomTypeVarReturnType),
|
||||
(Flake8Pyi, "020") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::QuotedAnnotationInStub),
|
||||
(Flake8Pyi, "021") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::DocstringInStub),
|
||||
(Flake8Pyi, "024") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::CollectionsNamedTuple),
|
||||
(Flake8Pyi, "025") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnaliasedCollectionsAbcSetImport),
|
||||
(Flake8Pyi, "026") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::TypeAliasWithoutAnnotation),
|
||||
(Flake8Pyi, "029") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::StrOrReprDefinedInStub),
|
||||
(Flake8Pyi, "030") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnnecessaryLiteralUnion),
|
||||
(Flake8Pyi, "032") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::AnyEqNeAnnotation),
|
||||
(Flake8Pyi, "033") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::TypeCommentInStub),
|
||||
(Flake8Pyi, "034") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::NonSelfReturnType),
|
||||
(Flake8Pyi, "035") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnassignedSpecialVariableInStub),
|
||||
(Flake8Pyi, "036") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::BadExitAnnotation),
|
||||
(Flake8Pyi, "041") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::RedundantNumericUnion),
|
||||
(Flake8Pyi, "042") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::SnakeCaseTypeAlias),
|
||||
(Flake8Pyi, "043") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::TSuffixedTypeAlias),
|
||||
(Flake8Pyi, "044") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::FutureAnnotationsInStub),
|
||||
(Flake8Pyi, "045") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::IterMethodReturnIterable),
|
||||
(Flake8Pyi, "046") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnusedPrivateProtocol),
|
||||
(Flake8Pyi, "047") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnusedPrivateTypeAlias),
|
||||
(Flake8Pyi, "048") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::StubBodyMultipleStatements),
|
||||
(Flake8Pyi, "049") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnusedPrivateTypedDict),
|
||||
(Flake8Pyi, "050") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::NoReturnArgumentAnnotationInStub),
|
||||
(Flake8Pyi, "051") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::RedundantLiteralUnion),
|
||||
(Flake8Pyi, "052") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnannotatedAssignmentInStub),
|
||||
(Flake8Pyi, "054") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::NumericLiteralTooLong),
|
||||
(Flake8Pyi, "053") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::StringOrBytesTooLong),
|
||||
(Flake8Pyi, "055") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnnecessaryTypeUnion),
|
||||
(Flake8Pyi, "056") => (RuleGroup::Unspecified, rules::flake8_pyi::rules::UnsupportedMethodCallOnAll),
|
||||
|
||||
// flake8-pytest-style
|
||||
(Flake8PytestStyle, "001") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestFixtureIncorrectParenthesesStyle),
|
||||
(Flake8PytestStyle, "002") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestFixturePositionalArgs),
|
||||
(Flake8PytestStyle, "003") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestExtraneousScopeFunction),
|
||||
(Flake8PytestStyle, "004") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestMissingFixtureNameUnderscore),
|
||||
(Flake8PytestStyle, "005") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestIncorrectFixtureNameUnderscore),
|
||||
(Flake8PytestStyle, "006") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestParametrizeNamesWrongType),
|
||||
(Flake8PytestStyle, "007") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestParametrizeValuesWrongType),
|
||||
(Flake8PytestStyle, "008") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestPatchWithLambda),
|
||||
(Flake8PytestStyle, "009") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestUnittestAssertion),
|
||||
(Flake8PytestStyle, "010") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestRaisesWithoutException),
|
||||
(Flake8PytestStyle, "011") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestRaisesTooBroad),
|
||||
(Flake8PytestStyle, "012") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestRaisesWithMultipleStatements),
|
||||
(Flake8PytestStyle, "013") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestIncorrectPytestImport),
|
||||
(Flake8PytestStyle, "014") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestDuplicateParametrizeTestCases),
|
||||
(Flake8PytestStyle, "015") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestAssertAlwaysFalse),
|
||||
(Flake8PytestStyle, "016") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestFailWithoutMessage),
|
||||
(Flake8PytestStyle, "017") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestAssertInExcept),
|
||||
(Flake8PytestStyle, "018") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestCompositeAssertion),
|
||||
(Flake8PytestStyle, "019") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestFixtureParamWithoutValue),
|
||||
(Flake8PytestStyle, "020") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestDeprecatedYieldFixture),
|
||||
(Flake8PytestStyle, "021") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestFixtureFinalizerCallback),
|
||||
(Flake8PytestStyle, "022") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestUselessYieldFixture),
|
||||
(Flake8PytestStyle, "023") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestIncorrectMarkParenthesesStyle),
|
||||
(Flake8PytestStyle, "024") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestUnnecessaryAsyncioMarkOnFixture),
|
||||
(Flake8PytestStyle, "025") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestErroneousUseFixturesOnFixture),
|
||||
(Flake8PytestStyle, "026") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestUseFixturesWithoutParameters),
|
||||
(Flake8PytestStyle, "027") => (RuleGroup::Unspecified, rules::flake8_pytest_style::rules::PytestUnittestRaisesAssertion),
|
||||
|
||||
// flake8-pie
|
||||
(Flake8Pie, "790") => (RuleGroup::Unspecified, rules::flake8_pie::rules::UnnecessaryPass),
|
||||
(Flake8Pie, "794") => (RuleGroup::Unspecified, rules::flake8_pie::rules::DuplicateClassFieldDefinition),
|
||||
(Flake8Pie, "796") => (RuleGroup::Unspecified, rules::flake8_pie::rules::NonUniqueEnums),
|
||||
(Flake8Pie, "800") => (RuleGroup::Unspecified, rules::flake8_pie::rules::UnnecessarySpread),
|
||||
(Flake8Pie, "804") => (RuleGroup::Unspecified, rules::flake8_pie::rules::UnnecessaryDictKwargs),
|
||||
(Flake8Pie, "807") => (RuleGroup::Unspecified, rules::flake8_pie::rules::ReimplementedListBuiltin),
|
||||
(Flake8Pie, "808") => (RuleGroup::Unspecified, rules::flake8_pie::rules::UnnecessaryRangeStart),
|
||||
(Flake8Pie, "810") => (RuleGroup::Unspecified, rules::flake8_pie::rules::MultipleStartsEndsWith),
|
||||
|
||||
// flake8-commas
|
||||
(Flake8Commas, "812") => (RuleGroup::Unspecified, rules::flake8_commas::rules::MissingTrailingComma),
|
||||
(Flake8Commas, "818") => (RuleGroup::Unspecified, rules::flake8_commas::rules::TrailingCommaOnBareTuple),
|
||||
(Flake8Commas, "819") => (RuleGroup::Unspecified, rules::flake8_commas::rules::ProhibitedTrailingComma),
|
||||
|
||||
// flake8-no-pep420
|
||||
(Flake8NoPep420, "001") => (RuleGroup::Unspecified, rules::flake8_no_pep420::rules::ImplicitNamespacePackage),
|
||||
|
||||
// flake8-executable
|
||||
(Flake8Executable, "001") => (RuleGroup::Unspecified, rules::flake8_executable::rules::ShebangNotExecutable),
|
||||
(Flake8Executable, "002") => (RuleGroup::Unspecified, rules::flake8_executable::rules::ShebangMissingExecutableFile),
|
||||
(Flake8Executable, "003") => (RuleGroup::Unspecified, rules::flake8_executable::rules::ShebangMissingPython),
|
||||
(Flake8Executable, "004") => (RuleGroup::Unspecified, rules::flake8_executable::rules::ShebangLeadingWhitespace),
|
||||
(Flake8Executable, "005") => (RuleGroup::Unspecified, rules::flake8_executable::rules::ShebangNotFirstLine),
|
||||
|
||||
// flake8-type-checking
|
||||
(Flake8TypeChecking, "001") => (RuleGroup::Unspecified, rules::flake8_type_checking::rules::TypingOnlyFirstPartyImport),
|
||||
(Flake8TypeChecking, "002") => (RuleGroup::Unspecified, rules::flake8_type_checking::rules::TypingOnlyThirdPartyImport),
|
||||
(Flake8TypeChecking, "003") => (RuleGroup::Unspecified, rules::flake8_type_checking::rules::TypingOnlyStandardLibraryImport),
|
||||
(Flake8TypeChecking, "004") => (RuleGroup::Unspecified, rules::flake8_type_checking::rules::RuntimeImportInTypeCheckingBlock),
|
||||
(Flake8TypeChecking, "005") => (RuleGroup::Unspecified, rules::flake8_type_checking::rules::EmptyTypeCheckingBlock),
|
||||
|
||||
// tryceratops
|
||||
(Tryceratops, "002") => (RuleGroup::Unspecified, rules::tryceratops::rules::RaiseVanillaClass),
|
||||
(Tryceratops, "003") => (RuleGroup::Unspecified, rules::tryceratops::rules::RaiseVanillaArgs),
|
||||
(Tryceratops, "004") => (RuleGroup::Unspecified, rules::tryceratops::rules::TypeCheckWithoutTypeError),
|
||||
(Tryceratops, "200") => (RuleGroup::Unspecified, rules::tryceratops::rules::ReraiseNoCause),
|
||||
(Tryceratops, "201") => (RuleGroup::Unspecified, rules::tryceratops::rules::VerboseRaise),
|
||||
(Tryceratops, "300") => (RuleGroup::Unspecified, rules::tryceratops::rules::TryConsiderElse),
|
||||
(Tryceratops, "301") => (RuleGroup::Unspecified, rules::tryceratops::rules::RaiseWithinTry),
|
||||
(Tryceratops, "302") => (RuleGroup::Unspecified, rules::tryceratops::rules::UselessTryExcept),
|
||||
(Tryceratops, "400") => (RuleGroup::Unspecified, rules::tryceratops::rules::ErrorInsteadOfException),
|
||||
(Tryceratops, "401") => (RuleGroup::Unspecified, rules::tryceratops::rules::VerboseLogMessage),
|
||||
|
||||
// flake8-use-pathlib
|
||||
(Flake8UsePathlib, "100") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsPathAbspath),
|
||||
(Flake8UsePathlib, "101") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsChmod),
|
||||
(Flake8UsePathlib, "102") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsMkdir),
|
||||
(Flake8UsePathlib, "103") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsMakedirs),
|
||||
(Flake8UsePathlib, "104") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsRename),
|
||||
(Flake8UsePathlib, "105") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsReplace),
|
||||
(Flake8UsePathlib, "106") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsRmdir),
|
||||
(Flake8UsePathlib, "107") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsRemove),
|
||||
(Flake8UsePathlib, "108") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsUnlink),
|
||||
(Flake8UsePathlib, "109") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsGetcwd),
|
||||
(Flake8UsePathlib, "110") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsPathExists),
|
||||
(Flake8UsePathlib, "111") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsPathExpanduser),
|
||||
(Flake8UsePathlib, "112") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsPathIsdir),
|
||||
(Flake8UsePathlib, "113") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsPathIsfile),
|
||||
(Flake8UsePathlib, "114") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsPathIslink),
|
||||
(Flake8UsePathlib, "115") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsReadlink),
|
||||
(Flake8UsePathlib, "116") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsStat),
|
||||
(Flake8UsePathlib, "117") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsPathIsabs),
|
||||
(Flake8UsePathlib, "118") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsPathJoin),
|
||||
(Flake8UsePathlib, "119") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsPathBasename),
|
||||
(Flake8UsePathlib, "120") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsPathDirname),
|
||||
(Flake8UsePathlib, "121") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsPathSamefile),
|
||||
(Flake8UsePathlib, "122") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::OsPathSplitext),
|
||||
(Flake8UsePathlib, "123") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::BuiltinOpen),
|
||||
(Flake8UsePathlib, "124") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::violations::PyPath),
|
||||
(Flake8UsePathlib, "201") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::rules::PathConstructorCurrentDirectory),
|
||||
(Flake8UsePathlib, "202") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::rules::OsPathGetsize),
|
||||
(Flake8UsePathlib, "202") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::rules::OsPathGetsize),
|
||||
(Flake8UsePathlib, "203") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::rules::OsPathGetatime),
|
||||
(Flake8UsePathlib, "204") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::rules::OsPathGetmtime),
|
||||
(Flake8UsePathlib, "205") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::rules::OsPathGetctime),
|
||||
(Flake8UsePathlib, "206") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::rules::OsSepSplit),
|
||||
(Flake8UsePathlib, "207") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::rules::Glob),
|
||||
|
||||
// flake8-logging-format
|
||||
(Flake8LoggingFormat, "001") => (RuleGroup::Unspecified, rules::flake8_logging_format::violations::LoggingStringFormat),
|
||||
(Flake8LoggingFormat, "002") => (RuleGroup::Unspecified, rules::flake8_logging_format::violations::LoggingPercentFormat),
|
||||
(Flake8LoggingFormat, "003") => (RuleGroup::Unspecified, rules::flake8_logging_format::violations::LoggingStringConcat),
|
||||
(Flake8LoggingFormat, "004") => (RuleGroup::Unspecified, rules::flake8_logging_format::violations::LoggingFString),
|
||||
(Flake8LoggingFormat, "010") => (RuleGroup::Unspecified, rules::flake8_logging_format::violations::LoggingWarn),
|
||||
(Flake8LoggingFormat, "101") => (RuleGroup::Unspecified, rules::flake8_logging_format::violations::LoggingExtraAttrClash),
|
||||
(Flake8LoggingFormat, "201") => (RuleGroup::Unspecified, rules::flake8_logging_format::violations::LoggingExcInfo),
|
||||
(Flake8LoggingFormat, "202") => (RuleGroup::Unspecified, rules::flake8_logging_format::violations::LoggingRedundantExcInfo),
|
||||
|
||||
// flake8-raise
|
||||
(Flake8Raise, "102") => (RuleGroup::Unspecified, rules::flake8_raise::rules::UnnecessaryParenOnRaiseException),
|
||||
|
||||
// flake8-self
|
||||
(Flake8Self, "001") => (RuleGroup::Unspecified, rules::flake8_self::rules::PrivateMemberAccess),
|
||||
|
||||
// numpy
|
||||
(Numpy, "001") => (RuleGroup::Unspecified, rules::numpy::rules::NumpyDeprecatedTypeAlias),
|
||||
(Numpy, "002") => (RuleGroup::Unspecified, rules::numpy::rules::NumpyLegacyRandom),
|
||||
(Numpy, "003") => (RuleGroup::Unspecified, rules::numpy::rules::NumpyDeprecatedFunction),
|
||||
|
||||
// ruff
|
||||
(Ruff, "001") => (RuleGroup::Unspecified, rules::ruff::rules::AmbiguousUnicodeCharacterString),
|
||||
(Ruff, "002") => (RuleGroup::Unspecified, rules::ruff::rules::AmbiguousUnicodeCharacterDocstring),
|
||||
(Ruff, "003") => (RuleGroup::Unspecified, rules::ruff::rules::AmbiguousUnicodeCharacterComment),
|
||||
(Ruff, "005") => (RuleGroup::Unspecified, rules::ruff::rules::CollectionLiteralConcatenation),
|
||||
(Ruff, "006") => (RuleGroup::Unspecified, rules::ruff::rules::AsyncioDanglingTask),
|
||||
(Ruff, "007") => (RuleGroup::Unspecified, rules::ruff::rules::PairwiseOverZipped),
|
||||
(Ruff, "008") => (RuleGroup::Unspecified, rules::ruff::rules::MutableDataclassDefault),
|
||||
(Ruff, "009") => (RuleGroup::Unspecified, rules::ruff::rules::FunctionCallInDataclassDefaultArgument),
|
||||
(Ruff, "010") => (RuleGroup::Unspecified, rules::ruff::rules::ExplicitFStringTypeConversion),
|
||||
(Ruff, "011") => (RuleGroup::Unspecified, rules::ruff::rules::StaticKeyDictComprehension),
|
||||
(Ruff, "012") => (RuleGroup::Unspecified, rules::ruff::rules::MutableClassDefault),
|
||||
(Ruff, "013") => (RuleGroup::Unspecified, rules::ruff::rules::ImplicitOptional),
|
||||
#[cfg(feature = "unreachable-code")] // When removing this feature gate, also update rules_selector.rs
|
||||
(Ruff, "014") => (RuleGroup::Nursery, rules::ruff::rules::UnreachableCode),
|
||||
(Ruff, "015") => (RuleGroup::Unspecified, rules::ruff::rules::UnnecessaryIterableAllocationForFirstElement),
|
||||
(Ruff, "016") => (RuleGroup::Unspecified, rules::ruff::rules::InvalidIndexType),
|
||||
(Ruff, "017") => (RuleGroup::Nursery, rules::ruff::rules::QuadraticListSummation),
|
||||
(Ruff, "100") => (RuleGroup::Unspecified, rules::ruff::rules::UnusedNOQA),
|
||||
(Ruff, "200") => (RuleGroup::Unspecified, rules::ruff::rules::InvalidPyprojectToml),
|
||||
|
||||
// flake8-django
|
||||
(Flake8Django, "001") => (RuleGroup::Unspecified, rules::flake8_django::rules::DjangoNullableModelStringField),
|
||||
(Flake8Django, "003") => (RuleGroup::Unspecified, rules::flake8_django::rules::DjangoLocalsInRenderFunction),
|
||||
(Flake8Django, "006") => (RuleGroup::Unspecified, rules::flake8_django::rules::DjangoExcludeWithModelForm),
|
||||
(Flake8Django, "007") => (RuleGroup::Unspecified, rules::flake8_django::rules::DjangoAllWithModelForm),
|
||||
(Flake8Django, "008") => (RuleGroup::Unspecified, rules::flake8_django::rules::DjangoModelWithoutDunderStr),
|
||||
(Flake8Django, "012") => (RuleGroup::Unspecified, rules::flake8_django::rules::DjangoUnorderedBodyContentInModel),
|
||||
(Flake8Django, "013") => (RuleGroup::Unspecified, rules::flake8_django::rules::DjangoNonLeadingReceiverDecorator),
|
||||
|
||||
// flynt
|
||||
// Reserved: (Flynt, "001") => (RuleGroup::Unspecified, Rule: :StringConcatenationToFString),
|
||||
(Flynt, "002") => (RuleGroup::Unspecified, rules::flynt::rules::StaticJoinToFString),
|
||||
|
||||
// flake8-todos
|
||||
(Flake8Todos, "001") => (RuleGroup::Unspecified, rules::flake8_todos::rules::InvalidTodoTag),
|
||||
(Flake8Todos, "002") => (RuleGroup::Unspecified, rules::flake8_todos::rules::MissingTodoAuthor),
|
||||
(Flake8Todos, "003") => (RuleGroup::Unspecified, rules::flake8_todos::rules::MissingTodoLink),
|
||||
(Flake8Todos, "004") => (RuleGroup::Unspecified, rules::flake8_todos::rules::MissingTodoColon),
|
||||
(Flake8Todos, "005") => (RuleGroup::Unspecified, rules::flake8_todos::rules::MissingTodoDescription),
|
||||
(Flake8Todos, "006") => (RuleGroup::Unspecified, rules::flake8_todos::rules::InvalidTodoCapitalization),
|
||||
(Flake8Todos, "007") => (RuleGroup::Unspecified, rules::flake8_todos::rules::MissingSpaceAfterTodoColon),
|
||||
|
||||
// airflow
|
||||
(Airflow, "001") => (RuleGroup::Unspecified, rules::airflow::rules::AirflowVariableNameTaskIdMismatch),
|
||||
|
||||
// perflint
|
||||
(Perflint, "101") => (RuleGroup::Unspecified, rules::perflint::rules::UnnecessaryListCast),
|
||||
(Perflint, "102") => (RuleGroup::Unspecified, rules::perflint::rules::IncorrectDictIterator),
|
||||
(Perflint, "203") => (RuleGroup::Unspecified, rules::perflint::rules::TryExceptInLoop),
|
||||
(Perflint, "401") => (RuleGroup::Unspecified, rules::perflint::rules::ManualListComprehension),
|
||||
(Perflint, "402") => (RuleGroup::Unspecified, rules::perflint::rules::ManualListCopy),
|
||||
|
||||
// flake8-fixme
|
||||
(Flake8Fixme, "001") => (RuleGroup::Unspecified, rules::flake8_fixme::rules::LineContainsFixme),
|
||||
(Flake8Fixme, "002") => (RuleGroup::Unspecified, rules::flake8_fixme::rules::LineContainsTodo),
|
||||
(Flake8Fixme, "003") => (RuleGroup::Unspecified, rules::flake8_fixme::rules::LineContainsXxx),
|
||||
(Flake8Fixme, "004") => (RuleGroup::Unspecified, rules::flake8_fixme::rules::LineContainsHack),
|
||||
|
||||
// flake8-slots
|
||||
(Flake8Slots, "000") => (RuleGroup::Unspecified, rules::flake8_slots::rules::NoSlotsInStrSubclass),
|
||||
(Flake8Slots, "001") => (RuleGroup::Unspecified, rules::flake8_slots::rules::NoSlotsInTupleSubclass),
|
||||
(Flake8Slots, "002") => (RuleGroup::Unspecified, rules::flake8_slots::rules::NoSlotsInNamedtupleSubclass),
|
||||
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/src/comments/shebang.rs
|
||||
expression: "ShebangDirective::try_extract(source)"
|
||||
---
|
||||
None
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/src/comments/shebang.rs
|
||||
expression: "ShebangDirective::try_extract(source)"
|
||||
---
|
||||
None
|
||||
@@ -1,9 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/src/comments/shebang.rs
|
||||
expression: "ShebangDirective::try_extract(source)"
|
||||
---
|
||||
Some(
|
||||
ShebangDirective(
|
||||
"/usr/bin/env python",
|
||||
),
|
||||
)
|
||||
@@ -1,9 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/src/comments/shebang.rs
|
||||
expression: "ShebangDirective::try_extract(source)"
|
||||
---
|
||||
Some(
|
||||
ShebangDirective(
|
||||
"/usr/bin/env python # trailing comment",
|
||||
),
|
||||
)
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
source: crates/ruff/src/comments/shebang.rs
|
||||
expression: "ShebangDirective::try_extract(source)"
|
||||
---
|
||||
None
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user