pyright icon indicating copy to clipboard operation
pyright copied to clipboard

Relax reportSelfClsParameterName to allow mcs , mcls, and metacls when inheriting from type.

Open DylanLukes opened this issue 6 months ago • 1 comments

When implementing metaclasses, it is relatively commonplace in methods such as __new__ and @classmethod's such as __prepare__ to name the first positional argument mcs, mcls or metacls.

This has a few benefits. In particular, it allows for the name cls to be used for an actual class, such as in:

def __new__(metacls, cls_name: str, cls_bases: tuple[type, ...], cls_attrs: dict[str. Any], **kwargs):
    cls = super().__new__(metacls, cls_name, cls_bases, cls_attrs)
    # do things with cls
    return cls

This is a good bit clearer than naming the first parameter cls and requiring a different name to be used in the body. The current inspection, I think, forces either:

  • A sub-optimally readable naming choice.
  • Disabling inspections with too coarse a granularity (project, file, or class).
  • Disabling inspections per line is unnecessarily noisy.

This seems like such a common naming pattern that it

Usage in the Wild

While not ubiquitous, these naming choices are certainly common in many large and old projects, and besides that the intent behind them are immediately clear (except perhaps mcs).

  • Python documentation uses mcls in the descriptor guide.
  • Python uses metacls in Lib/enum.py.
  • Typeshed stubs use metacls in type.prepare as well as EnumMeta.__new__ and EnumMeta.__prepare__. Additionally, mcls and __mcls are used in ABCMeta.__new__.
  • Django uses mcs in django.forms.{forms, widgets, models} as well as one usage of metacls in django.db.models.enums.
  • Pydantic liberally uses mcs.

Related to a Problem?

Not really, just an inconvenience. Disabling this inspection project-wide is a sledgehammer for a nail. Ditto for an entire (meta)class. Disabling it per method or per line adds unnecessary noise, especially if there are @overloads in play.

Proposed Solution

Relax reportSelfClsParameterName when the containing class inherits from type, both for @classmethod's in general as well as for __new__ to allow for mcs, mcls and metacls.

DylanLukes avatar Aug 09 '24 17:08 DylanLukes