ruff
ruff copied to clipboard
Implement Pylint
This is the parent issue for tracking parity with Pylint. Below, we've enumerated all Pylint rules.
Rules that are checked off have been implemented in Ruff already (either as a Pylint rule, e.g., PLE0237, or by way of overlap with another linter like Pyflakes, as with missing-format-string-key).
Rules that are crossed out have been removed some consideration. (In most cases, crossed-out rules represent Pylint specific rules, e.g., rules related to Pylint configuration.)
At time of writing, many of the remaining rules require type inference and/or multi-file analysis, and aren't ready to be implemented in Ruff. (See: https://github.com/astral-sh/ruff/issues/970#issuecomment-1565594417 for an enumeration.) If you're looking to start work on a specific rule, I'd suggest commenting in the issue, to get some input on whether Ruff is capable of supporting it at present.
For guidance on getting started, see the Contributing documentation.
Note: Don't implement rules that are part of Pylint extension until #1774 is completed. Don't implement rules that mainly target Python 2.
Error
- [ ]
abstract-class-instantiated/E0110 - [ ]
access-member-before-definition/E0203 - [x]
assigning-non-slot/E0237(PLE0237) - [ ]
assignment-from-no-return/E1111 - [ ]
assignment-from-none/E1128 - [x]
await-outside-async/E1142(PLE1142) - [x] ~
bad-configuration-section/E0014~ - [ ]
bad-except-order/E0701 - [ ]
bad-exception-cause/E0705 - [x]
bad-format-character/E1300(PLE1300) - [x] ~
bad-plugin-value/E0013~ - [ ]
bad-reversed-sequence/E0111 - [x]
bad-str-strip-call/E1310(PLE1310) - [x]
bad-string-format-type/E1307(PLE1307) - [ ] ~
bad-super-call/E1003~ (mainly targets Python 2) - [x]
bidirectional-unicode/E2502(PLE2502) - [x] ~
broken-collections-callable/E6005~ - [x] ~
broken-noreturn/E6004~ - [ ]
catching-non-exception/E0712 - [ ]
class-variable-slots-conflict/E0242 - [x]
continue-in-finally/E0116(PLE0116) - [ ]
dict-iter-missing-items/E1141 - [x] ~
duplicate-argument-name/E0108~ - [x]
duplicate-bases/E0241(PLE0241) - [x]
format-needs-mapping/E1303(F502) - [x]
function-redefined/E0102(F811) - [ ]
import-error/E0401 - [ ]
inconsistent-mro/E0240 - [ ]
inherit-non-class/E0239 - [x]
init-is-generator/E0100(PLE0100) - [x]
invalid-all-format/E0605(PLE0605) - [x]
invalid-all-object/E0604(PLE0604) - [x]
invalid-bool-returned/E0304 - [x]
invalid-bytes-returned/E0308 - [x]
invalid-character-backspace/E2510(PLE2510) - [ ]
invalid-character-carriage-return/E2511 - [x]
invalid-character-esc/E2513(PLE2513) - [x]
invalid-character-nul/E2514(PLE2514) - [x]
invalid-character-sub/E2512(PLE2512) - [x]
invalid-character-zero-width-space/E2515(PLE2515) - [ ]
invalid-class-object/E0243 - [ ]
invalid-enum-extension/E0244 - [ ]
invalid-envvar-value/E1507 - [ ]
invalid-format-returned/E0311 - [ ]
invalid-getnewargs-ex-returned/E0313 - [ ]
invalid-getnewargs-returned/E0312 - [x]
invalid-hash-returned/E0309 - [x]
invalid-index-returned/E0305 - [ ]
invalid-length-hint-returned/E0310 - [x]
invalid-length-returned/E0303 - [ ]
invalid-metaclass/E1139 - [ ]
invalid-repr-returned/E0306 - [ ]
invalid-sequence-index/E1126 - [ ]
invalid-slice-index/E1127 - [ ]
invalid-slice-step/E1144 - [ ]
invalid-slots/E0238 - [ ]
invalid-slots-object/E0236 - [ ]
invalid-star-assignment-target/E0113 - [ ]
invalid-str-returned/E0307 - [ ]
invalid-unary-operand-type/E1130 - [ ]
invalid-unicode-codec/E2501 - [ ]
logging-format-truncated/E1201 - [x]
logging-too-few-args/E1206(PLE1206) - [x]
logging-too-many-args/E1205(PLE1205) - [ ]
logging-unsupported-format/E1200 - [ ]
method-hidden/E0202 - [x]
misplaced-bare-raise/E0704(PLE0704) - [ ]
misplaced-format-function/E0119 - [x]
missing-format-string-key/E1304(F524) - [ ]
missing-kwoa/E1125 - [x]
mixed-format-string/E1302(F506) - [ ]
modified-iterating-dict/E4702 - [x]
modified-iterating-set/E4703(PLE4703) - [ ]
no-member/E1101 - [ ]
no-method-argument/E0211 - [ ]
no-name-in-module/E0611 - [x]
no-self-argument/E0213(N805) - [ ]
no-value-for-parameter/E1120 - [ ]
non-iterator-returned/E0301 - [x]
nonexistent-operator/E0107(B002) - [x]
nonlocal-and-global/E0115(PLE0115) - [x]
nonlocal-without-binding/E0117(PLE0117) - [ ]
not-a-mapping/E1134 - [ ]
not-an-iterable/E1133 - [ ]
not-async-context-manager/E1701 - [ ]
not-callable/E1102 - [ ]
not-context-manager/E1129 - [x]
not-in-loop/E0103(F701,F702) - [x]
notimplemented-raised/E0711(F901) - [x]
potential-index-error/E0643(PLE0643) - [ ]
raising-bad-type/E0702 - [ ]
raising-non-exception/E0710 - [ ]
redundant-keyword-arg/E1124 - [x]
relative-beyond-top-level/E0402(TID252) - [x]
repeated-keyword/E1132(PLE1132) - [x] ~
return-arg-in-generator/E0106~ - [x]
return-in-init/E0101(PLE0101) - [x]
return-outside-function/E0104(F706) - [x]
singledispatch-method/E1519(PLE1519) - [x]
singledispatchmethod-function/E1520(PLE5120) - [ ]
star-needs-assignment-target/E0114 - [x]
syntax-error/E0001(E999) - [x]
too-few-format-args/E1306(F524) - [x]
too-many-format-args/E1305(F522) - [ ]
too-many-function-args/E1121 - [x]
too-many-star-expressions/E0112(F622) - [x]
truncated-format-string/E1301(F501) - [x]
undefined-all-variable/E0603(F822) - [x]
undefined-variable/E0602(F821) - [ ]
unexpected-keyword-arg/E1123 - [x]
unexpected-special-method-signature/E0302(PLE0302) - [ ]
unhashable-member/E1143 - [ ]
unpacking-non-sequence/E0633 - [ ]
unsubscriptable-object/E1136 - [ ]
unsupported-assignment-operation/E1137 - [ ]
unsupported-binary-operation/E1131 - [ ]
unsupported-delete-operation/E1138 - [ ]
unsupported-membership-test/E1135 - [ ]
used-before-assignment/E0601 - [x]
used-prior-global-declaration/E0118(PLE0118) - [x]
yield-inside-async-function/E1700(PLE1700) - [x]
yield-outside-function/E0105(F704)
Warning
- [ ]
abstract-method/W0223 - [x]
anomalous-backslash-in-string/W1401(W605) - [ ]
anomalous-unicode-escape-in-string/W1402 - [ ]
arguments-differ/W0221 - [ ]
arguments-out-of-order/W1114 - [ ]
arguments-renamed/W0237 - [x]
assert-on-string-literal/W0129(PLW0129) - [x]
assert-on-tuple/W0199(F631) - [ ]
attribute-defined-outside-init/W0201 - [ ]
bad-builtin/W0141 - [x]
bad-dunder-name/W3201(PLW3201) - [x]
bad-format-string/W1302 - [x]
bad-format-string-key/W1300 - [ ]
bad-indentation/W0311 - [x]
bad-open-mode/W1501(PLW1501) - [x]
bad-staticmethod-argument/W0211(PLW0211) - [ ]
bad-thread-instantiation/W1506 - [x]
bare-except/W0702(E722) - [x]
binary-op-exception/W0711(PLW0711) - [x] ~
boolean-datetime/W1502~ - [x]
broad-exception-caught/W0718 - [x]
broad-exception-raised/W0719(TRY002) - [x]
cell-var-from-loop/W0640(B023) - [ ]
comparison-with-callable/W0143 - [ ]
confusing-with-statement/W0124 - [x]
consider-ternary-expression/W0160(SIM108) - [x]
dangerous-default-value/W0102(B006) - [ ]
deprecated-argument/W4903 - [ ]
deprecated-class/W4904 - [ ]
deprecated-decorator/W4905 - [ ]
deprecated-method/W4902 - [ ]
deprecated-module/W4901 - [ ]
deprecated-typing-alias/W6001 - [ ]
differing-param-doc/W9017 - [ ]
differing-type-doc/W9018 - [x]
duplicate-except/W0705(B014) - [x]
duplicate-key/W0109(F601) - [x]
duplicate-string-formatting-argument/W1308 - [x]
duplicate-value/W0130(B033) - [x]
eq-without-hash/W1641(PLW1641) - [x]
eval-used/W0123(PGH001) - [x]
exec-used/W0122(S102) - [x]
expression-not-assigned/W0106(B018) - [x]
f-string-without-interpolation/W1309(F541) - [x]
fixme/W0511(FIX001,FIX002,FIX003,FIX004) - [x]
forgotten-debug-statement/W1515(T100) - [x]
format-combined-specification/W1305(F525) - [x]
format-string-without-interpolation/W1310(F541) - [x]
global-at-module-level/W0604(PLW0604) - [x]
global-statement/W0603(PLW0603) - [x]
global-variable-not-assigned/W0602(PLW0602) - [ ]
global-variable-undefined/W0601 - [x]
implicit-str-concat/W1404(ISC001) - [x]
import-self/W0406(PLW0406) - [x]
inconsistent-quotes/W1405(Q000) - [x]
invalid-envvar-default/W1508(PLW1508) - [ ]
invalid-format-index/W1307 - [ ]
invalid-overridden-method/W0236 - [ ]
isinstance-second-argument-not-valid-type/W1116 - [x]
keyword-arg-before-vararg/W1113(B026) - [x]
logging-format-interpolation/W1202(G) - [x]
logging-fstring-interpolation/W1203(G) - [x]
logging-not-lazy/W1201(G) - [x]
lost-exception/W0150(B012) - [x]
method-cache-max-size-none/W1518(B019) - [x]
misplaced-future/W0410(F404) - [ ]
missing-any-param-doc/W9021 - [x]
missing-format-argument-key/W1303(F524) - [ ]
missing-format-attribute/W1306 - [ ]
missing-param-doc/W9015 - [ ]
missing-parentheses-for-call-in-test/W0126 - [ ]
missing-raises-doc/W9006 - [ ] ~
missing-return-doc/W9011~ (Pylint extension) - [ ]
missing-return-type-doc/W9012 - [ ]
missing-timeout/W3101 - [ ]
missing-type-doc/W9016 - [ ]
missing-yield-doc/W9013 - [ ]
missing-yield-type-doc/W9014 - [ ]
modified-iterating-list/W4701 - [ ]
multiple-constructor-doc/W9005 - [x]
named-expr-without-context/W0131(PLW0131) - [x]
nan-comparison/W0177(PLW0117) - [x]
nested-min-max/W3301(PLW3301) - [x]
non-ascii-file-name/W2402(N999) - [ ]
non-parent-init-called/W0233 - [ ]
non-str-assignment-to-dunder-name/W1115 - [ ]
overlapping-except/W0714 - [ ]
overridden-final-method/W0239 - [x]
pointless-exception-statement/W0133(PLW0133) - [x]
pointless-statement/W0104(B018) - [ ]
pointless-string-statement/W0105 - [ ]
possibly-unused-variable/W0641 - [ ]
preferred-module/W0407 - [x]
protected-access/W0212(SLF001) - [x]
raise-missing-from/W0707(TRY200) - [ ]
raising-format-tuple/W0715 - [ ]
redeclared-assigned-name/W0128 - [x]
redefined-builtin/W0622(A001) - [x]
redefined-loop-name/W2901(PLW2901) - [ ]
redefined-outer-name/W0621 - [ ]
redefined-slots-in-subclass/W0244 - [ ]
redundant-returns-doc/W9008 - [x]
redundant-u-string-prefix/W1406(UP025) - [ ]
redundant-unittest-assert/W1503 - [ ]
redundant-yields-doc/W9010 - [x]
reimported/W0404(F811) - [x]
self-assigning-variable/W0127(PLW0127) - [ ]
self-cls-assignment/W0642 - [ ]
shallow-copy-environ/W1507 - [ ]
signature-differs/W0222 - [ ]
subclassed-final-class/W0240 - [x]
subprocess-popen-preexec-fn/W1509(PLW1509) - [x]
subprocess-run-check/W1510(PLW1510) - [ ]
super-init-not-called/W0231 - [x]
super-without-brackets/W0245(PLW0245) - [ ]
too-many-try-statements/W0717 - [x]
try-except-raise/W0706(TRY302) - [ ]
unbalanced-dict-unpacking/W0644 - [ ]
unbalanced-tuple-unpacking/W0632 - [ ]
undefined-loop-variable/W0631 - [x] ~
unknown-option-value/W0012~ - [ ]
unnecessary-ellipsis/W2301 - [x]
unnecessary-lambda/W0108(PLW0108) - [x]
unnecessary-pass/W0107(PIE790) - [x]
unnecessary-semicolon/W0301(E703) - [ ]
unreachable/W0101 - [x]
unspecified-encoding/W1514(PLW1514) - [x]
unused-argument/W0613(ARG001) - [x]
unused-format-string-argument/W1304(F507) - [x]
unused-format-string-key/W1301(F504) - [x]
unused-import/W0611(F401) - [ ]
unused-private-member/W0238 - [x]
unused-variable/W0612(F841) - [ ]
unused-wildcard-import/W0614 - [x]
useless-else-on-loop/W0120(PLW0120) - [ ]
useless-param-doc/W9019 - [ ]
useless-parent-delegation/W0246 - [ ]
useless-type-doc/W9020 - [x]
useless-with-lock/W2101(PLW2101) - [ ]
using-constant-test/W0125 - [x] ~
using-f-string-in-unsupported-version/W2601~ - [ ]
using-final-decorator-in-unsupported-version/W2602 - [ ]
while-used/W0149 - [x]
wildcard-import/W0401(F403) - [ ]
wrong-exception-operation/W0716
Convention
- [x]
bad-classmethod-argument/C0202(`N804) - [x]
bad-docstring-quotes/C0198(Q002) - [ ]
bad-file-encoding/C2503 - [ ]
bad-mcs-classmethod-argument/C0204 - [ ]
bad-mcs-method-argument/C0203 - [x]
compare-to-empty-string/C1901(PLC1901) - [ ]
compare-to-zero/C2001 - [x]
consider-iterating-dictionary/C0201(SIM118) - [x]
consider-using-any-or-all/C0501(SIM110,SIM111) - [x]
consider-using-dict-items/C0206(PLC0206) - [ ]
consider-using-enumerate/C0200 - [ ]
consider-using-f-string/C0209 - [ ]
dict-init-mutate/C3401 - [ ]
disallowed-name/C0104 - [x]
docstring-first-line-empty/C0199(D210) - [x]
empty-docstring/C0112(D419) - [x]
import-outside-toplevel/C0415(PLC0415) - [x]
import-private-name/C2701(PLC2701) - [ ]
invalid-characters-in-docstring/C0403 - [x]
invalid-name/C0103(N815) - [x]
line-too-long/C0301(E501) - [x]
misplaced-comparison-constant/C2201(SIM300) - [x]
missing-class-docstring/C0115(D101) - [x]
missing-final-newline/C0304(W292) - [x]
missing-function-docstring/C0116(D103) - [x]
missing-module-docstring/C0114(D100) - [ ]
mixed-line-endings/C0327 - [x]
multiple-imports/C0410(E401) - [x]
multiple-statements/C0321(E701,E702) - [x]
non-ascii-module-import/C2403(PLC2403) - [x]
non-ascii-name/C2401(PLC2401) - [x]
single-string-used-for-slots/C0205(PLC0205) - [x]
singleton-comparison/C0121(E711,E712) - [ ]
superfluous-parens/C0325 - [ ] ~
too-many-lines/C0302~ (not compatible with the formatter) - [ ]
trailing-newlines/C0305 - [x]
trailing-whitespace/C0303(W291) - [x]
typevar-double-variance/C0131(PLC0131) - [x]
typevar-name-incorrect-variance/C0105(PLC0105) - [x]
typevar-name-mismatch/C0132(PLC0132) - [ ]
unexpected-line-ending-format/C0328 - [x]
ungrouped-imports/C0412(I001) - [x]
unidiomatic-typecheck/C0123(E721) - [x]
unnecessary-direct-lambda-call/C3002(PLC3002) - [x]
unnecessary-dunder-call/C2801(PLC2801) - [x]
unnecessary-lambda-assignment/C3001(E731) - [x]
unneeded-not/C0113(SIM208) - [ ]
use-implicit-booleaness-not-comparison/C1803 - [ ]
use-implicit-booleaness-not-len/C1802 - [ ]
use-maxsplit-arg/C0207 - [x]
use-sequence-for-iteration/C0208(PLC0208) - [x]
useless-import-alias/C0414(PLC0414) - [x]
wrong-import-order/C0411(I001) - [x]
wrong-import-position/C0413(E402) - [ ]
wrong-spelling-in-comment/C0401 - [ ]
wrong-spelling-in-docstring/C0402
Refactor
- [ ]
chained-comparison/R1716 - [x]
comparison-of-constants/R0133(PLR0133) - [x]
comparison-with-itself/R0124(PLR0124) - [ ]
condition-evals-to-constant/R1727 - [ ] ~
confusing-consecutive-elif~ /R5601 - [x]
consider-alternative-union-syntax/R6003(UP007) - [x]
consider-merging-isinstance/R1701(PLR1701) - [ ]
consider-swap-variables/R1712 - [x]
consider-using-alias/R6002(UP006) - [ ]
consider-using-assignment-expr/R6103 - [x]
consider-using-augmented-assign/R6104 - [x]
consider-using-dict-comprehension/R1717(C402) - [ ]
consider-using-from-import/R0402 - [x]
consider-using-generator/R1728(C417) - [x]
consider-using-get/R1715(SIM401) - [x]
consider-using-in/R1714 - [ ]
consider-using-join/R1713 - [x]
consider-using-min-builtin/R1730(PLR1730) - [x]
consider-using-max-builtin/R1731(PLR1730) - [ ]
consider-using-namedtuple-or-dataclass/R6101 - [x]
consider-using-set-comprehension/R1718(C401) - [x]
consider-using-sys-exit/R1722(PLR1722) - [x]
consider-using-ternary/R1706(PLR1706) - [ ]
consider-using-tuple/R6102 - [x]
consider-using-with/R1732(SIM115) - [ ]
cyclic-import/R0401 - [ ]
duplicate-code/R0801 - [x]
else-if-used/R5501(PLR5501) - [x]
empty-comment/R2044(PLR2044) - [x]
inconsistent-return-statements/R1710(RET501,RET502) - [x]
literal-comparison/R0123(F632) - [x]
magic-value-comparison/R2004(PLR2004) - [x]
no-classmethod-decorator/R0202(PLR0202) - [x]
no-else-break/R1723(RET508) - [x]
no-else-continue/R1724(RET507) - [x]
no-else-raise/R1720(RET506) - [x]
no-else-return/R1705(RET505) - [x]
no-self-use/R6301(PLR6301) - [x]
no-staticmethod-decorator/R0203(PLR0203) - [x]
property-with-parameters/R0206(PLR0206) - [x]
redefined-argument-from-local/R1704(PLR1704) - [ ]
redefined-variable-type/R0204 - [ ]
simplifiable-condition/R1726 - [x]
simplifiable-if-expression/R1719(SIM210,SIM211) - [x]
simplifiable-if-statement/R1703(SIM108) - [ ]
simplify-boolean-expression/R1709 - [ ]
stop-iteration-return/R1708 - [x]
super-with-arguments/R1725(UP008) - [x]
too-complex/R1260(C901) - [ ]
too-few-public-methods/R0903 - [ ]
too-many-ancestors/R0901(requires multifile analysis) - [x]
too-many-arguments/R0913(PLR0913) - [x]
too-many-boolean-expressions/R0916(PLR0916) - [x]
too-many-branches/R0912(PLR0912) - [ ] ~
too-many-instance-attributes/R0902~ (requires #1774) - [x]
too-many-locals/R0914(PLR0914) - [x]
too-many-nested-blocks/R1702(PLR1702) - [x]
too-many-public-methods/R0904(PLR0904) - [x]
too-many-return-statements/R0911(PLR0911) - [x]
too-many-statements/R0915(PLR0915) - [x]
trailing-comma-tuple/R1707(COM818) - [x]
unnecessary-comprehension/R1721(C416) - [x]
unnecessary-dict-index-lookup/R1733(PLR1733) - [x]
unnecessary-list-index-lookup/R1736(PLR1736) - [x]
use-a-generator/R1729(C419) - [x]
use-dict-literal/R1735(C406) - [x]
use-list-literal/R1734(C405) - [x]
use-set-for-membership/R6201(PLR6201) - [x]
useless-object-inheritance/R0205(UP004) - [x] ~
useless-option-value/R0022~ - [x]
useless-return/R1711(PLR1711)
Need to figure out what the right "check code" approach is here. We could just start to put these under RUF. Or we could do PYE for "Pylint Error", and so on. Or we could use PYL for all of them. In either case, though, we have to allow four-digit codes, as opposed to our current three-digit codes.
I vote for PYE as it would keep the same categories and the migration would be easier.
I'll work on unneeded-not this weekend.
I would suggest PL as the pylint prefix (PLE -> PyLint Error). I think PYE might be a bit ambiguous with PYflakes, PYdocstyle, etc.
Would absolutely love to see this happen. I know flake8 intentionally decided not to implement e.g. unexpected-keyword-arg because it required looking outside of the current file for imported functions.
I expect you've already considered this, and really hope this won't stop ruff from implementing it, but just wanted to raise it.
@relsunkaev :+1: Went with PLE! The first code is checked in as PLE1142 (matching E1142 from Pylint).
@MartinBernstorff - Definitely. The multi-file stuff will come, just not as quickly.
Not sure if it should be separate issue, but looking at missing-function-docstring rule (C0116), pylint's version of it is different. It only requires that a function has docstring some in class hierarchy and does not require over-ridden methods to have a docstring. As an example,
class Foo:
def validate(self):
"""Doc."""
...
class Bar(Foo):
def validate(self):
...
gives no errors in pylint even though second validate is missing docstring being pylint allows inheriting one. This is very useful when implementing interface and the docstring would really be same for all things that subclass.
I'd like to get pointless-statement, unnecessary-ellipsis, and unnecessary-pass in.
Relevant source for defining a pointless-statement: https://github.com/PyCQA/pylint/blob/56121344f6c9c223d8e4477c0cdb58c46c840b4b/pylint/checkers/base/basic_checker.py#L447
A while ago I set out to find all the pylint codes make redundant by type checking.
Unfortunately that code got lost to the sands of time.
You might consider skipping those as type checking tools are very sophisticated, if you can do the effort of compiling that list
I've also thought very long and hard about the fact that pylint appears very sophisticated when it comes to types because it builds on astroid which works very hard to infer types based on code (pre-type-annotations)
Ideally ruff (or any modern linter) is type-aware to be as helpful as possible, but that requires either:
- A Rust-implemented type checkers for Python. Short of a large company writing and maintaining this I doubt it'll keep up with the other big dogs
- Having the type information be seeded to ruff. Aside from the overhead and protocol, this actually seems feasible.
For what it's worth, the type awareness of pylint is the killer feature that keeps us using it in our project despite how painfully slow it is. Our first-party code is almost fully typed, and mypy is generally good at catching typing issues. We've found multiple instances where pylint caught an issue that mypy missed however - usually in third-party code with missing or incomplete type definitions, but occasionally also in our own code when mypy doesn't notice (eg due to the presence of __getattr__: https://github.com/python/mypy/issues/6251).
Out of curiosity, have you tried pyright? It claims to have inference support for codebases that aren't fully typed.
Mypy has a check_untyped_defs which sounds equivalent, and we use that. We currently rely on mypy's no_strict_optional which pyright has no equivalent to, so pyright is not currently usable on our codebase.
Started to look at import-error / E0401,
From what i can tell - ruff doesn't currently use any "context" about the python environment, right?
In order to add this rule - we need to use something like pkgutil - which can be slow, or implement import resolution in ruff.
@charliermarsh Is the project open to any of these options currently?
We have some support for import resolution, but not enough to power import-error right now.
What we do support is (1) a src list, which is used for first-party resolution, similar to isort and reorder-python-imports (so it detects module-level first-party imports, but doesn't do "full" resolution), (2) a namespace-packages list, for namespace packages, and (3) we do crawl the filesystem to find all __init__.py files to power some checks.
Does import-error need to be able to lookup third-party packages?
Does
import-errorneed to be able to lookup third-party packages?
FWIW this is one of the biggest reasons we use pylint at all, despite obviously being much slower to do than just first party code.
Any plans on when and how to implement more import resolution features?
WDYT about creating an issue to gather rules that will need these capabilities?
I just went through and mapped all the checked-off rules to the relevant codes within Ruff. I'm guessing we implement more than the 86 that are checked off (at time of writing), but it's my best guess based on a single pass through the list.
It’d be really nice if ruff can understand the inline pylint ignores to make migration very easy.
It’d be really nice if ruff can understand the inline pylint ignores to make migration very easy.
this is covered in https://github.com/charliermarsh/ruff/issues/1203
We can probbably mark bad-configuration-section as complete, it has to do with a pylint refactor
useless-option-value too, it's a warning for an issue in the pylint configuration.
bad-plugin-value is also for pylint plugins that cannot be loaded, which we do not need.
Thank you! Going to strike them out.
What's the policy with duplicate logic being checked by multiple linters? E.g. too-many-format-args seems functionally equivalent to F524 which is already implemented:
https://github.com/charliermarsh/ruff/blob/41900316186ae65b588ec0fda64c21bfee4b9956/src/rules/pyflakes/rules/strings.rs#L191
We tend towards including the Flake8 variant over the Pylint variant. We're working on enabling rule aliasing, so that we'll be able to map multiple codes to the same underlying rule (details TBD).
@charliermarsh do we have anyway of knowing the minor version of python we are on? broken-collections-callable should only be run on python 3.9.0 and 3.9.1, and I don't know of a way to detect only those two sub-versions.
@colin99d - Hmm -- not really. I think we should just skip that rule.