Skip to content

Restore pylint: ruff is not a drop-in replacement #289

Closed

Description

@farhan

Context

During the Python tooling modernization, pylint was replaced with ruff in xblocks-core.

Confusion was perhaps we are replacing ruff with pylint

After further discussion, the team has decided not to replace pylint with ruff.

Ruff will not catch issues like type mis-matches, attribute-undefined, etc.

For repos which are fully type annotated and checked with mypy we can ignore pylint

See the Slack thread for the full discussion: https://openedx.slack.com/archives/C05P7KQURL0/p1786133265985139

Summary of decision (from Feanil Patel):

People are welcome to add ruff, but it's not a replacement for pylint. To replace pylint we'll need to replace some custom pylint plugins + all its type checking.

Decision

  • Restore pylint to xblocks-core

Activity

  1. moved this to 🔖 Ready in Aximprovements Teamon Aug 11, 2026
  2. self-assigned this
    on Aug 21, 2026
  3. moved this from 🔖 Ready to 🏗 In progress in Aximprovements Teamon Aug 21, 2026
  4. moved this from 🏗 In progress to 👀 In review in Aximprovements Teamon Aug 21, 2026
  5. farhan commented on Aug 31, 2026

    @farhan
    ContributorAuthor

    Note

    Generated with help of Claude after thorough brainstorming & spelunking

    @feanil @kdmccormick @openedx/axim-aximprovements

    While working on this story I started shaping a strategy for running ruff and pylint together across our Python repos, so they complement each other instead of overlapping. This is an agentically brainstormed plan; feedback is appreciated.

    Use ruff as the first-class tool

    Ruff is the default linter and formatter. It is fast, auto-fixes most findings, and owns everything mechanical: style, imports, modern syntax, comprehensions, bugbear, Django checks, and unused imports. When ruff and pylint cover the same check, ruff wins and pylint's version is disabled.

    Use pylint where it shines

    Keep pylint for the checks ruff cannot do, because they need whole-program or type-aware analysis:

    Give ruff preference on overlap

    Where both tools cover a check, keep it in ruff and disable pylint's version:

    • Unused imports: ruff F401 is auto-fixable, so pylint unused-import is disabled. Package re-exports declare __all__, which ruff recognizes.

    Carry the shared config in edx-lint

    edx-lint ships the canonical pylintrc for Open edX repos. Encode the ruff and pylint split there so every repo inherits the same setup instead of re-deriving it.

    Example: edx-platform

    edx-platform runs both tools this way, with ruff as the primary gate and pylint for its semantic and plugin checks. It is migrating toward ruff as the first-class tool across staged PRs. Some of its choices are scale-driven and are not part of this baseline:

    • It suppressed thousands of existing findings with # noqa instead of fixing them, because a mass fix was infeasible. A smaller repo should fix them.
    • It ignores E722, E731, E741, and E721 to keep the migration an equivalent swap. A smaller repo should keep these on.

    Where this repo deviates

    • Line length stays with pylint (C0301) rather than ruff (E501), against the ruff-wins rule, because pylint ignores trailing comments and URLs while ruff does not.

    Deviating is fine with a solid reason

    Treat this as a default, not a rule:

    • A fully type-annotated repo checked by mypy can drop pylint's type checks.
    • A repo may hand line length to ruff (E501) when it does not need pylint's trailing-comment handling.
    • Move a check to ruff once ruff gains an equivalent that only pylint provides today.
    • Keep a scale-driven suppression, like edx-platform's, when fixing every existing finding is not yet practical.
  6. moved this from 👀 In review to 🛑 Blocked in Aximprovements Teamon Sep 2, 2026
  7. feanil commented on Sep 3, 2026

    @feanil
    Contributor

    This generally makes sense to me and seems like a good approach.

  8. moved this from 🛑 Blocked to ✅ Done in Aximprovements Teamon Sep 11, 2026
  9. kdmccormick commented on Sep 14, 2026

    @kdmccormick
    Member

    @farhan Great writeup 🚀

    edx-lint ships the canonical pylintrc for Open edX repos. Encode the ruff and pylint split there so every repo inherits the same setup instead of re-deriving it.

    That sounds great. When you encode this into edx-lint, I would mark it as a BREAKING CHANGE with a major version bump, because repos which don't use ruff yet will not be ready for the slimmed-out pylint rules.

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions