Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion pylint/checkers/base_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from astroid import nodes

from pylint.checkers.mapreduce_checker import MapReduceMixin
from pylint.config.arguments_provider import _ArgumentsProvider
from pylint.constants import _MSG_ORDER, MAIN_CHECKER_NAME, WarningScope
from pylint.exceptions import InvalidMessageError
Expand All @@ -24,7 +25,7 @@


@functools.total_ordering
class BaseChecker(_ArgumentsProvider):
class BaseChecker(_ArgumentsProvider, MapReduceMixin):

# checker name (you may reuse an existing one)
name: str = ""
Expand Down Expand Up @@ -206,6 +207,12 @@ def open(self):
def close(self):
"""Called after visiting project (i.e set of modules)."""

def get_map_data(self) -> Any:
return None

def reduce_map_data(self, linter: PyLinter, data: list[Any]) -> None:
return None


class BaseTokenChecker(BaseChecker):
"""Base class for checkers that want to have access to the token stream."""
Expand Down
10 changes: 8 additions & 2 deletions pylint/checkers/mapreduce_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@
# For details: https://github.com/PyCQA/pylint/blob/main/LICENSE
# Copyright (c) https://github.com/PyCQA/pylint/blob/main/CONTRIBUTORS.txt

from __future__ import annotations

import abc
from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
from pylint.lint import PyLinter


class MapReduceMixin(metaclass=abc.ABCMeta):
"""A mixin design to allow multiprocess/threaded runs of a Checker."""

@abc.abstractmethod
def get_map_data(self):
def get_map_data(self) -> Any:
"""Returns mergeable/reducible data that will be examined."""

@abc.abstractmethod
def reduce_map_data(self, linter, data):
def reduce_map_data(self, linter: PyLinter, data: list[Any]) -> None:
"""For a given Checker, receives data for all mapped runs."""
4 changes: 2 additions & 2 deletions pylint/checkers/similar.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
import astroid
from astroid import nodes

from pylint.checkers import BaseChecker, MapReduceMixin, table_lines_from_stats
from pylint.checkers import BaseChecker, table_lines_from_stats
from pylint.interfaces import IRawChecker
from pylint.reporters.ureports.nodes import Table
from pylint.typing import Options
Expand Down Expand Up @@ -727,7 +727,7 @@ def report_similarities(


# wrapper to get a pylint checker from the similar class
class SimilarChecker(BaseChecker, Similar, MapReduceMixin):
class SimilarChecker(BaseChecker, Similar):
"""Checks for similarities and duplicated code.

This computation may be memory / CPU intensive, so you
Expand Down
13 changes: 5 additions & 8 deletions pylint/lint/parallel.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,9 @@ def _worker_check_single_file(
_worker_linter.check_single_file_item(file_item)
mapreduce_data = defaultdict(list)
for checker in _worker_linter.get_checkers():
try:
data = checker.get_map_data()
except AttributeError:
continue
mapreduce_data[checker.name].append(data)
data = checker.get_map_data()
if data is not None:
mapreduce_data[checker.name].append(data)
Comment thread
jacobtylerwalls marked this conversation as resolved.
msgs = _worker_linter.reporter.messages
assert isinstance(_worker_linter.reporter, reporters.CollectingReporter)
_worker_linter.reporter.reset()
Expand Down Expand Up @@ -108,7 +106,7 @@ def _merge_mapreduce_data(
# validation. The intent here is to collect all the mapreduce data for all checker-
# runs across processes - that will then be passed to a static method on the
# checkers to be reduced and further processed.
collated_map_reduce_data = defaultdict(list)
collated_map_reduce_data: defaultdict[str, list[Any]] = defaultdict(list)
for linter_data in all_mapreduce_data.values():
for run_data in linter_data:
for checker_name, data in run_data.items():
Expand All @@ -132,8 +130,7 @@ def check_parallel(
"""Use the given linter to lint the files with given amount of workers (jobs).

This splits the work filestream-by-filestream. If you need to do work across
multiple files, as in the similarity-checker, then inherit from MapReduceMixin and
implement the map/reduce mixin functionality.
multiple files, as in the similarity-checker, then implement the map/reduce mixin functionality.
"""
# The linter is inherited by all the pool's workers, i.e. the linter
# is identical to the linter object here. This is required so that
Expand Down
3 changes: 1 addition & 2 deletions tests/test_check_parallel.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import pylint.interfaces
import pylint.lint.parallel
from pylint.checkers.base_checker import BaseChecker
from pylint.checkers.mapreduce_checker import MapReduceMixin
from pylint.lint import PyLinter
from pylint.lint.parallel import _worker_check_single_file as worker_check_single_file
from pylint.lint.parallel import _worker_initialize as worker_initialize
Expand Down Expand Up @@ -73,7 +72,7 @@ def process_module(self, _node: nodes.Module) -> None:
self.data.append(record)


class ParallelTestChecker(BaseChecker, MapReduceMixin):
class ParallelTestChecker(BaseChecker):
"""A checker that does need to consolidate data.

To simulate the need to consolidate data, this checker only
Expand Down