Free — no signup required

Writing a Pylint Plugin

2 min read

Integrating with the Ecosystem

A standalone script is useful for one-off checks, but production teams need rules that run automatically alongside standard linting, produce consistent output formats, and integrate with editors and CI pipelines. This is where Pylint plugins come in.

Pylint is one of the most widely used Python linters. It supports a plugin system where you can register custom Checkers — classes that hook into Pylint's AST walk and fire when specific node types are visited. Your custom rules then appear in Pylint's output alongside its built-in checks, with the same message format, severity levels, and suppression mechanisms (# pylint: disable=...).

Pylint uses a library called Astroid to build its AST. Astroid is a superset of the standard ast module — it adds type inference, scope analysis, and other semantic information. The node types are similar but not identical. For example, function calls are still Call nodes, but you access the function name via node.func.name (for simple names) rather than node.func.id.

Anatomy of a Pylint Checker:

┌─────────────────────────────────────────────┐
│              NoPrintChecker                 │
│                                             │
│  name      → unique identifier string       │
│  msgs       → dict of error codes + text    │
│  visit_call → called for every Call node    │
│  register() → entry point Pylint calls      │
└─────────────────────────────────────────────┘

The message code format is important: Pylint uses a letter prefix to indicate severity:

Prefix Severity
C Convention (style)
R Refactor (design smell)
W Warning (potential bug)
E Error (definite bug)
F Fatal (prevents further analysis)

Custom plugins should use codes in the W9000–W9999 or E9000–E9999 range to avoid colliding with Pylint's built-in codes.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free