Skip to content

Implement Pylint #970

Description

@charliermarsh

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: #970 (comment) 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
  • assigning-non-slot / E0237 (PLE0237)
  • assignment-from-no-return / E1111
  • assignment-from-none / E1128
  • await-outside-async / E1142 (PLE1142)
  • bad-configuration-section / E0014
  • bad-except-order / E0701
  • bad-exception-cause / E0705
  • bad-format-character / E1300 (PLE1300)
  • bad-plugin-value / E0013
  • bad-reversed-sequence / E0111
  • bad-str-strip-call / E1310 (PLE1310)
  • bad-string-format-type / E1307 (PLE1307)
  • bad-super-call / E1003 (mainly targets Python 2)
  • bidirectional-unicode / E2502 (PLE2502)
  • broken-collections-callable / E6005
  • broken-noreturn / E6004
  • catching-non-exception / E0712
  • class-variable-slots-conflict / E0242
  • continue-in-finally / E0116 (PLE0116)
  • dict-iter-missing-items / E1141
  • duplicate-argument-name / E0108
  • duplicate-bases / E0241 (PLE0241)
  • format-needs-mapping / E1303 (F502)
  • function-redefined / E0102 (F811)
  • import-error / E0401
  • inconsistent-mro / E0240
  • inherit-non-class / E0239
  • init-is-generator / E0100 (PLE0100)
  • invalid-all-format / E0605 (PLE0605)
  • invalid-all-object / E0604 (PLE0604)
  • invalid-bool-returned / E0304 (PLE0304)
  • invalid-bytes-returned / E0308 (PLE0308)
  • invalid-character-backspace / E2510 (PLE2510)
  • invalid-character-carriage-return / E2511
  • invalid-character-esc / E2513 (PLE2513)
  • invalid-character-nul / E2514 (PLE2514)
  • invalid-character-sub / E2512 (PLE2512)
  • 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
  • invalid-hash-returned / E0309 (PLE0309)
  • invalid-index-returned / E0305 (PLE0305)
  • invalid-length-hint-returned / E0310
  • invalid-length-returned / E0303 (PLE0303)
  • 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
  • logging-too-few-args / E1206 (PLE1206)
  • logging-too-many-args / E1205 (PLE1205)
  • logging-unsupported-format / E1200
  • method-hidden / E0202
  • misplaced-bare-raise / E0704 (PLE0704)
  • misplaced-format-function / E0119
  • missing-format-string-key / E1304 (F524)
  • missing-kwoa / E1125
  • mixed-format-string / E1302 (F506)
  • modified-iterating-dict / E4702
  • modified-iterating-set / E4703 (PLE4703)
  • no-member / E1101
  • no-method-argument / E0211
  • no-name-in-module / E0611
  • no-self-argument / E0213 (N805)
  • no-value-for-parameter / E1120
  • non-iterator-returned / E0301
  • nonexistent-operator / E0107 (B002)
  • nonlocal-and-global / E0115 (PLE0115)
  • 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
  • not-in-loop / E0103 (F701, F702)
  • notimplemented-raised / E0711 (F901)
  • potential-index-error / E0643 (PLE0643)
  • raising-bad-type / E0702
  • raising-non-exception / E0710
  • redundant-keyword-arg / E1124
  • relative-beyond-top-level / E0402 (TID252)
  • repeated-keyword / E1132 (PLE1132)
  • return-arg-in-generator / E0106
  • return-in-init / E0101 (PLE0101)
  • return-outside-function / E0104 (F706)
  • singledispatch-method / E1519 (PLE1519)
  • singledispatchmethod-function / E1520 (PLE1520)
  • star-needs-assignment-target / E0114 (syntax error in preview)
  • syntax-error / E0001 (always enabled)
  • too-few-format-args / E1306 (F524)
  • too-many-format-args / E1305 (F522)
  • too-many-function-args / E1121
  • too-many-star-expressions / E0112 (F622)
  • truncated-format-string / E1301 (F501)
  • undefined-all-variable / E0603 (F822)
  • undefined-variable / E0602 (F821)
  • unexpected-keyword-arg / E1123
  • 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 (F821)
  • used-prior-global-declaration / E0118 (PLE0118)
  • yield-inside-async-function / E1700 (PLE1700)
  • yield-outside-function / E0105 (F704)

Warning

  • abstract-method / W0223
  • anomalous-backslash-in-string / W1401 (W605)
  • anomalous-unicode-escape-in-string / W1402
  • arguments-differ / W0221
  • arguments-out-of-order / W1114
  • arguments-renamed / W0237
  • assert-on-string-literal / W0129 (PLW0129)
  • assert-on-tuple / W0199 (F631)
  • attribute-defined-outside-init / W0201
  • bad-builtin / W0141
  • bad-chained-comparison / W3601
  • bad-dunder-name / W3201 (PLW3201)
  • bad-format-string / W1302 (F521)
  • bad-format-string-key / W1300
  • bad-indentation / W0311 (E111)
  • bad-open-mode / W1501 (PLW1501)
  • bad-staticmethod-argument / W0211 (PLW0211)
  • bad-thread-instantiation / W1506
  • bare-except / W0702 (E722)
  • binary-op-exception / W0711 (PLW0711)
  • boolean-datetime / W1502
  • broad-exception-caught / W0718 (BLE001)
  • broad-exception-raised / W0719 (TRY002)
  • cell-var-from-loop / W0640 (B023)
  • comparison-with-callable / W0143
  • confusing-with-statement / W0124
  • consider-ternary-expression / W0160 (SIM108)
  • 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
  • duplicate-except / W0705 (B014)
  • duplicate-key / W0109 (F601)
  • duplicate-string-formatting-argument / W1308
  • duplicate-value / W0130 (B033)
  • eq-without-hash / W1641 (PLW1641)
  • eval-used / W0123 (S307)
  • exec-used / W0122 (S102)
  • expression-not-assigned / W0106 (B018)
  • f-string-without-interpolation / W1309 (F541)
  • fixme / W0511 (FIX001, FIX002, FIX003, FIX004)
  • forgotten-debug-statement / W1515 (T100 )
  • format-combined-specification / W1305 (F525)
  • format-string-without-interpolation / W1310 (F541)
  • global-at-module-level / W0604 (PLW0604)
  • global-statement / W0603 (PLW0603)
  • global-variable-not-assigned / W0602 (PLW0602)
  • global-variable-undefined / W0601
  • implicit-str-concat / W1404 (ISC001)
  • import-self / W0406 (PLW0406)
  • inconsistent-quotes / W1405 (Q000)
  • invalid-envvar-default / W1508 (PLW1508)
  • invalid-format-index / W1307
  • invalid-overridden-method / W0236
  • isinstance-second-argument-not-valid-type / W1116
  • keyword-arg-before-vararg / W1113 (B026)
  • logging-format-interpolation / W1202 (G001)
  • logging-fstring-interpolation / W1203 (G004)
  • logging-not-lazy / W1201 (G002)
  • lost-exception / W0150 (B012)
  • method-cache-max-size-none / W1518 (B019)
  • misplaced-future / W0410 (F404)
  • missing-any-param-doc / W9021
  • 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
  • named-expr-without-context / W0131 (PLW0131)
  • nan-comparison / W0177 (PLW0177)
  • nested-min-max / W3301 (PLW3301)
  • 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
  • pointless-exception-statement / W0133 (PLW0133)
  • pointless-statement / W0104 (B018)
  • pointless-string-statement / W0105
  • possibly-unused-variable / W0641
  • preferred-module / W0407
  • protected-access / W0212 (SLF001)
  • raise-missing-from / W0707 (B904)
  • raising-format-tuple / W0715
  • redeclared-assigned-name / W0128
  • redefined-builtin / W0622 (A001)
  • redefined-loop-name / W2901 (PLW2901)
  • redefined-outer-name / W0621
  • redefined-slots-in-subclass / W0244
  • redundant-returns-doc / W9008
  • redundant-u-string-prefix / W1406 (UP025)
  • redundant-unittest-assert / W1503
  • redundant-yields-doc / W9010
  • reimported / W0404 (F811)
  • self-assigning-variable / W0127 (PLW0127)
  • self-cls-assignment / W0642
  • shallow-copy-environ / W1507
  • signature-differs / W0222
  • subclassed-final-class / W0240
  • subprocess-popen-preexec-fn / W1509 (PLW1509)
  • subprocess-run-check / W1510 (PLW1510)
  • super-init-not-called / W0231
  • super-without-brackets / W0245 (PLW0245)
  • too-many-try-statements / W0717
  • try-except-raise / W0706 (TRY302)
  • unbalanced-dict-unpacking / W0644
  • unbalanced-tuple-unpacking / W0632
  • undefined-loop-variable / W0631
  • unknown-option-value / W0012
  • unnecessary-ellipsis / W2301 (`PIE790)
  • unnecessary-lambda / W0108 (PLW0108)
  • unnecessary-pass / W0107 (PIE790)
  • unnecessary-semicolon / W0301 (E703)
  • unreachable / W0101
  • unspecified-encoding / W1514 (PLW1514)
  • unused-argument / W0613 (ARG001)
  • unused-format-string-argument / W1304 (F507)
  • unused-format-string-key / W1301 (F504)
  • unused-import / W0611 (F401)
  • unused-private-member / W0238
  • unused-variable / W0612 (F841)
  • unused-wildcard-import / W0614
  • useless-else-on-loop / W0120 (PLW0120)
  • useless-param-doc / W9019
  • useless-parent-delegation / W0246
  • useless-type-doc / W9020
  • useless-with-lock / W2101 (PLW2101)
  • using-constant-test / W0125
  • using-f-string-in-unsupported-version / W2601
  • using-final-decorator-in-unsupported-version / W2602
  • while-used / W0149
  • wildcard-import / W0401 (F403)
  • wrong-exception-operation / W0716

Convention

  • bad-classmethod-argument / C0202 (N804)
  • bad-docstring-quotes / C0198 (Q002)
  • bad-file-encoding / C2503
  • bad-mcs-classmethod-argument / C0204
  • bad-mcs-method-argument / C0203
  • compare-to-empty-string / C1901 (PLC1901)
  • compare-to-zero / C2001
  • consider-iterating-dictionary / C0201 (SIM118)
  • consider-using-any-or-all / C0501 (SIM110, SIM111)
  • consider-using-dict-items / C0206 (PLC0206)
  • consider-using-enumerate / C0200
  • consider-using-f-string / C0209
  • dict-init-mutate / C3401
  • disallowed-name / C0104
  • docstring-first-line-empty / C0199 (D210)
  • empty-docstring / C0112 (D419)
  • import-outside-toplevel / C0415 (PLC0415)
  • import-private-name / C2701 (PLC2701)
  • invalid-characters-in-docstring / C0403
  • invalid-name / C0103 (N815)
  • line-too-long / C0301 (E501)
  • misplaced-comparison-constant / C2201 (SIM300)
  • missing-class-docstring / C0115 (D101)
  • missing-final-newline / C0304 (W292)
  • missing-function-docstring / C0116 (D103)
  • missing-module-docstring / C0114 (D100)
  • mixed-line-endings / C0327
  • multiple-imports / C0410 (E401)
  • multiple-statements / C0321 (E701, E702)
  • non-ascii-module-import / C2403 (PLC2403)
  • non-ascii-name / C2401 (PLC2401)
  • single-string-used-for-slots / C0205 (PLC0205)
  • singleton-comparison / C0121 (E711 , E712)
  • superfluous-parens / C0325
  • too-many-lines / C0302 (not compatible with the formatter)
  • trailing-newlines / C0305 (W391)
  • trailing-whitespace / C0303 (W291)
  • typevar-double-variance / C0131 (PLC0131)
  • typevar-name-incorrect-variance / C0105 (PLC0105)
  • typevar-name-mismatch / C0132 (PLC0132)
  • unexpected-line-ending-format / C0328
  • ungrouped-imports / C0412 (I001)
  • unidiomatic-typecheck / C0123 (E721)
  • unnecessary-direct-lambda-call / C3002 (PLC3002)
  • unnecessary-dunder-call / C2801 (PLC2801)
  • unnecessary-lambda-assignment / C3001 (E731)
  • unneeded-not / C0113 (SIM208)
  • use-implicit-booleaness-not-comparison / C1803
  • use-implicit-booleaness-not-len / C1802 (PLC1802)
  • use-maxsplit-arg / C0207 (PLC0207)
  • use-sequence-for-iteration / C0208 (PLC0208)
  • useless-import-alias / C0414 (PLC0414)
  • wrong-import-order / C0411 (I001)
  • wrong-import-position / C0413 (E402 )
  • wrong-spelling-in-comment / C0401
  • wrong-spelling-in-docstring / C0402

Refactor

  • chained-comparison / R1716
  • comparison-of-constants / R0133 (PLR0133)
  • comparison-with-itself / R0124 (PLR0124)
  • condition-evals-to-constant / R1727
  • confusing-consecutive-elif / R5601
  • consider-alternative-union-syntax / R6003 (UP007)
  • consider-merging-isinstance / R1701 (SIM101)
  • consider-swap-variables / R1712 (PLR1712)
  • consider-using-alias / R6002 (UP006)
  • consider-using-assignment-expr / R6103
  • consider-using-augmented-assign / R6104 (PLR6104)
  • consider-using-dict-comprehension / R1717 (C402)
  • consider-using-from-import / R0402 (PLR0402)
  • consider-using-generator / R1728 (C417)
  • consider-using-get / R1715 (SIM401)
  • consider-using-in / R1714 (PLR1714)
  • consider-using-join / R1713
  • consider-using-min-builtin / R1730 (PLR1730)
  • consider-using-max-builtin / R1731 (PLR1730)
  • consider-using-namedtuple-or-dataclass / R6101
  • consider-using-set-comprehension / R1718 (C401)
  • consider-using-sys-exit / R1722 (PLR1722)
  • consider-using-ternary / R1706 (PLR1706 )
  • consider-using-tuple / R6102
  • consider-using-with / R1732 (SIM115)
  • cyclic-import / R0401
  • duplicate-code / R0801
  • else-if-used / R5501 (PLR5501)
  • empty-comment / R2044 (PLR2044)
  • inconsistent-return-statements / R1710 (RET501, RET502)
  • literal-comparison / R0123 (F632)
  • magic-value-comparison / R2004 (PLR2004)
  • no-classmethod-decorator / R0202 (PLR0202)
  • no-else-break / R1723 (RET508)
  • no-else-continue / R1724 (RET507)
  • no-else-raise / R1720 (RET506)
  • no-else-return / R1705 (RET505)
  • no-self-use / R6301 (PLR6301)
  • no-staticmethod-decorator / R0203 (PLR0203)
  • property-with-parameters / R0206 (PLR0206)
  • redefined-argument-from-local / R1704 (PLR1704)
  • redefined-variable-type / R0204
  • simplifiable-condition / R1726
  • simplifiable-if-expression / R1719 (SIM210, SIM211)
  • simplifiable-if-statement / R1703 (SIM108)
  • simplify-boolean-expression / R1709
  • stop-iteration-return / R1708
  • super-with-arguments / R1725 (UP008)
  • too-complex / R1260 (C901)
  • too-few-public-methods / R0903
  • too-many-ancestors / R0901 (requires multifile analysis)
  • too-many-arguments / R0913 (PLR0913)
  • too-many-boolean-expressions / R0916 (PLR0916)
  • too-many-positional-arguments / R0917 (PLR0917)
  • too-many-branches / R0912 (PLR0912)
  • too-many-instance-attributes / R0902 (requires Rule categorization #1774)
  • too-many-locals / R0914 (PLR0914)
  • too-many-nested-blocks / R1702 (PLR1702)
  • too-many-public-methods / R0904 (PLR0904)
  • too-many-return-statements / R0911 (PLR0911)
  • too-many-statements / R0915 (PLR0915)
  • trailing-comma-tuple / R1707 (COM818)
  • unnecessary-comprehension / R1721 (C416)
  • use-a-generator / R1729 (C419)
  • unnecessary-dict-index-lookup / R1733 (PLR1733)
  • use-list-literal / R1734 (C405)
  • use-dict-literal / R1735 (C406)
  • unnecessary-list-index-lookup / R1736 (PLR1736)
  • use-yield-from / R1737 (UP028)
  • use-set-for-membership / R6201 (PLR6201)
  • useless-object-inheritance / R0205 (UP004)
  • useless-option-value / R0022
  • useless-return / R1711 (PLR1711)

Activity

  1. charliermarsh commented on Nov 30, 2022

    @charliermarsh
    MemberAuthor

    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.

  2. JonathanPlasse commented on Nov 30, 2022

    @JonathanPlasse
    Contributor

    I vote for PYE as it would keep the same categories and the migration would be easier.

  3. harupy commented on Dec 1, 2022

    @harupy
    Contributor

    I'll work on unneeded-not this weekend.

  4. relsunkaev commented on Dec 1, 2022

    @relsunkaev
    Contributor

    I would suggest PL as the pylint prefix (PLE -> PyLint Error). I think PYE might be a bit ambiguous with PYflakes, PYdocstyle, etc.

  5. MartinBernstorff commented on Dec 1, 2022

    @MartinBernstorff
    Contributor

    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.

  6. charliermarsh commented on Dec 1, 2022

    @charliermarsh
    MemberAuthor

    @relsunkaev 👍 Went with PLE! The first code is checked in as PLE1142 (matching E1142 from Pylint).

  7. charliermarsh commented on Dec 1, 2022

    @charliermarsh
    MemberAuthor

    @MartinBernstorff - Definitely. The multi-file stuff will come, just not as quickly.

  8. hmc-cs-mdrissi commented on Dec 8, 2022

    @hmc-cs-mdrissi

    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.

  9. added
    pluginImplementing a known but unsupported Ruff plugin
    and removed
    ruleImplementing or modifying a lint rule
    on Dec 31, 2022
  10. charliermarsh commented on Jan 5, 2023

    @charliermarsh
    MemberAuthor

    I'd like to get pointless-statement, unnecessary-ellipsis, and unnecessary-pass in.

  11. charliermarsh commented on Jan 5, 2023

    @charliermarsh
    MemberAuthor
  12. thejcannon commented on Jan 12, 2023

    @thejcannon
    Contributor

    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

  13. thejcannon commented on Jan 12, 2023

    @thejcannon
    Contributor

    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:

    1. 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
    2. Having the type information be seeded to ruff. Aside from the overhead and protocol, this actually seems feasible.
  14. 441 remaining items

  15. seroperson commented on Mar 30, 2026

    @seroperson
    Contributor

    @charliermarsh What do you think about bad-except-order (https://pylint.readthedocs.io/en/latest/user_guide/messages/error/bad-except-order.html)? Can I give it a try on implementing it?

    Checked the code, seems like there is nothing like this yet.

    And maybe you can also suggest what else (besides this) can be freely implemented?

    I'm thinking about using-constant-test (https://pylint.readthedocs.io/en/latest/user_guide/messages/warning/using-constant-test.html), consider-using-enumerate (https://pylint.readthedocs.io/en/latest/user_guide/messages/convention/consider-using-enumerate.html), bad-chained-comparison (https://pylint.readthedocs.io/en/latest/user_guide/messages/warning/bad-chained-comparison.html) and maybe dict-init-mutate (https://pylint.readthedocs.io/en/latest/user_guide/messages/convention/dict-init-mutate.html)

  16. NeilGirdhar commented on May 23, 2026

    @NeilGirdhar

    Now that Ty is very usable, it might be worth it to check off everything that Ty does. Also, this issue is so long that it might be worth starting a new one with an updated list of Pylint codes.

  17. oehlschl commented on Jul 28, 2026

    @oehlschl

    PR for W0105 (pointless-string-statement): #27253

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    pluginImplementing a known but unsupported Ruff plugin

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions