Module rulebook_pylint.checkers.member_order

Functions

def register(linter: PyLinter)
Expand source code
def register(linter: 'PyLinter') -> None:
    linter.register_checker(MemberOrderChecker(linter))

Classes

class MemberOrderChecker (linter: PyLinter)
Expand source code
class MemberOrderChecker(RulebookChecker):
    """See detail: https://hanggrian.github.io/rulebook/rules/#member-order"""
    MSG: str = 'member-order'

    name: str = 'member-order'
    msgs: dict[str, MessageDefinitionTuple] = _Messages.of(MSG)
    options: Options = (
        (
            'rulebook-member-order',
            {
                'default': ('property', 'constructor', 'function', 'static'),
                'type': 'csv',
                'metavar': '<comma-separated values>',
                'help': 'The structure of a class body.',
            },
        ),
    )

    _member_order: list[str]
    _property_position: int
    _constructor_position: int
    _function_position: int
    _static_position: int

    def open(self) -> None:
        self._member_order = self.linter.config.rulebook_member_order
        self._property_position: int = self._member_order.index('property')
        self._constructor_position: int = self._member_order.index('constructor')
        self._function_position: int = self._member_order.index('function')
        self._static_position: int = self._member_order.index('static')

    def _get_member_position(self, node: NodeNG) -> int:
        if isinstance(node, Assign):
            if _has_decorator(node, 'staticmethod'):
                return self._static_position
            return self._property_position
        if isinstance(node, AssignName):
            return self._property_position
        if _has_decorator(node, 'staticmethod'):
            return self._static_position
        return self._constructor_position \
            if cast(FunctionDef, node).name == '__init__' \
            else self._function_position

    def _get_member_argument(self, node: NodeNG) -> str:
        if isinstance(node, Assign):
            if _has_decorator(node, 'staticmethod'):
                return 'static member'
            return 'property'
        if isinstance(node, AssignName):
            return 'property'
        if _has_decorator(node, 'staticmethod'):
            return 'static member'
        return 'constructor' \
            if cast(FunctionDef, node).name == '__init__' \
            else 'function'

    def visit_classdef(self, node: ClassDef) -> None:
        # in Python, static members have are annotated
        last_child: FunctionDef | None = None
        for child in [
            n for n in node.values()
            if isinstance(n, (Assign, AssignName, FunctionDef))
        ]:
            # checks for violation
            if last_child and \
                self._get_member_position(last_child) > self._get_member_position(child):
                self.add_message(
                    self.MSG,
                    node=child,
                    args=(
                        self._get_member_argument(child),
                        self._get_member_argument(last_child),
                    ),
                )

            last_child = child

See detail: https://hanggrian.github.io/rulebook/rules/#member-order

Checker instances should have the linter as argument.

Ancestors

  • RulebookChecker
  • pylint.checkers.base_checker.BaseChecker
  • pylint.config.arguments_provider._ArgumentsProvider

Class variables

var MSG : str

The type of the None singleton.

var msgs : dict[str, tuple[str, str, str] | tuple[str, str, str, pylint.typing.ExtraMessageOptions]]

The type of the None singleton.

var name : str

The type of the None singleton.

var options : tuple[tuple[str, dict[str, None | str | bool | int | re.Pattern[str] | collections.abc.Iterable[str | int | re.Pattern[str]] | type['_CallbackAction'] | collections.abc.Callable[[typing.Any], typing.Any] | collections.abc.Callable[[typing.Any, typing.Any, typing.Any, typing.Any], typing.Any]]], ...]

The type of the None singleton.

Methods

def open(self) ‑> None
Expand source code
def open(self) -> None:
    self._member_order = self.linter.config.rulebook_member_order
    self._property_position: int = self._member_order.index('property')
    self._constructor_position: int = self._member_order.index('constructor')
    self._function_position: int = self._member_order.index('function')
    self._static_position: int = self._member_order.index('static')

Called before visiting project (i.e. set of modules).

def visit_classdef(self, node: astroid.nodes.scoped_nodes.scoped_nodes.ClassDef) ‑> None
Expand source code
def visit_classdef(self, node: ClassDef) -> None:
    # in Python, static members have are annotated
    last_child: FunctionDef | None = None
    for child in [
        n for n in node.values()
        if isinstance(n, (Assign, AssignName, FunctionDef))
    ]:
        # checks for violation
        if last_child and \
            self._get_member_position(last_child) > self._get_member_position(child):
            self.add_message(
                self.MSG,
                node=child,
                args=(
                    self._get_member_argument(child),
                    self._get_member_argument(last_child),
                ),
            )

        last_child = child