Skip to content

Latest commit

 

History

History
51 lines (39 loc) · 2.17 KB

File metadata and controls

51 lines (39 loc) · 2.17 KB

Agent guidelines

AST-based checking

Pylint is an AST-based linter built on astroid. When writing or modifying checkers, prefer isinstance against concrete astroid node types combined with domain knowledge of Python syntax, rather than duck-typing with getattr/hasattr.

The visitor pattern from BaseChecker already narrows the node type for you: a visit_call method only receives nodes.Call, a visit_assign only receives nodes.Assign, and so on. Inside such a method, the node's structure is known — its attributes follow from the grammar (e.g. a nodes.Call always has .func and .args). Walk and type-check that known structure with isinstance instead of probing for attributes defensively.

Good:

def visit_call(self, node: nodes.Call) -> None:
    if isinstance(node.func, nodes.Attribute):
        ...

Avoid:

def visit_call(self, node) -> None:
    if hasattr(node.func, "attrname"):  # don't probe — check the type
        ...

This keeps checks precise, readable, and aligned with astroid's typed node API.

Caveat: astroid proxies and Uninferable

isinstance checks the static node type. Some astroid objects — bases.Instance, Generator, BoundMethod/UnboundMethod, and util.Uninferable — resolve attributes through __getattr__, proxying to a wrapped node. So hasattr(obj, "x") can be True at runtime on an object whose class has no x, and a naive isinstance(obj, ConcreteNode) will drop cases the old hasattr caught (e.g. an exception inferred to an Instance that proxies ancestors, or an AsyncGenerator that proxies locals).

When replacing such a guard:

  • Include the proxy base in the type tuple — e.g. (nodes.ClassDef, bases.Instance), or (nodes.LocalsDictNodeNG, bases.Proxy) for anything exposing qname.
  • If the check is a behavioral capability spanning heterogeneous nodes with no common base — or the proxied node may legitimately lack the attribute (a BoundMethod can wrap a Lambda, which has no .decorators) — keep hasattr. That is honest duck-typing, not a grammar check, and isinstance cannot express it safely.