CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pylint

Comprehensive static code analysis tool for Python that performs deep code inspection without executing the program

Pending
Overview
Eval results
Files

reporters.mddocs/

Reporters and Output

Flexible reporting system supporting multiple output formats and custom reporter development. Pylint's reporter architecture allows integration with different tools, IDEs, and continuous integration systems through standardized and custom output formats.

Capabilities

Base Reporter System

Foundation classes for all reporters providing the interface and common functionality.

class BaseReporter:
    """
    Abstract base class for all reporters.
    
    Attributes:
        out: Output stream for writing results
        messages: List of collected messages
        path_strip_prefix: Prefix to strip from file paths
    """
    
    def __init__(self, output=None):
        """
        Initialize the reporter.
        
        Args:
            output: Output stream (default: sys.stdout)
        """
    
    def handle_message(self, msg):
        """
        Handle a single message.
        
        Args:
            msg: Message instance to process
        """
    
    def display_messages(self, layout):
        """
        Display messages after collection.
        
        Args:
            layout: Layout object for organizing output (can be None)
        """
    
    def writeln(self, string=''):
        """
        Write a line to output.
        
        Args:
            string: String to write (default: empty line)
        """
    
    def display_reports(self, layout):
        """
        Display analysis reports.
        
        Args:
            layout: Report layout object
        """
    
    def on_set_current_module(self, module, filepath):
        """
        Called when switching to a new module.
        
        Args:
            module: Module name
            filepath: Path to the module file
        """

Built-in Reporters

Standard reporters for common output formats and use cases.

class TextReporter(BaseReporter):
    """
    Default text output reporter.
    
    Outputs messages in human-readable format with file paths,
    line numbers, message types, and descriptions.
    """
    
    name = 'text'
    extension = 'txt'

class ColorizedTextReporter(TextReporter):
    """
    Text reporter with color output for terminals.
    
    Adds ANSI color codes to highlight different message types
    and improve readability in terminal environments.
    """
    
    name = 'colorized'

class JSONReporter(BaseReporter):
    """
    JSON format reporter for programmatic consumption.
    
    Outputs messages as JSON array with structured data
    suitable for parsing by other tools and scripts.
    """
    
    name = 'json'
    extension = 'json'

class JSON2Reporter(BaseReporter):
    """
    Enhanced JSON reporter with additional metadata.
    
    Includes extended message information, statistics,
    and analysis metadata in JSON format.
    """
    
    name = 'json2'
    extension = 'json'

Specialized Reporters

Reporters for specific use cases and integrations.

class CollectingReporter(BaseReporter):
    """
    Reporter that collects messages in memory.
    
    Useful for programmatic access to analysis results
    without writing to files or streams.
    """
    
    name = 'collector'
    
    def finalize(self):
        """
        Finalize collection and return messages.
        
        Returns:
            list: Collected messages
        """

class MultiReporter(BaseReporter):
    """
    Reporter that delegates to multiple sub-reporters.
    
    Allows simultaneous output to multiple formats
    (e.g., console display and file logging).
    """
    
    def __init__(self, reporters):
        """
        Initialize with multiple reporters.
        
        Args:
            reporters: List of reporter instances
        """
    
    def add_reporter(self, reporter):
        """
        Add a new reporter to the collection.
        
        Args:
            reporter: Reporter instance to add
        """

Report Generation System

Mixin class providing report generation capabilities.

class ReportsHandlerMixIn:
    """
    Mixin providing report generation utilities.
    
    Handles statistics collection, report formatting,
    and output generation for analysis results.
    """
    
    def add_stats(self, **kwargs):
        """
        Add statistics to the report.
        
        Args:
            **kwargs: Statistics key-value pairs
        """
    
    def make_reports(self, stats, old_stats):
        """
        Generate analysis reports.
        
        Args:
            stats: Current analysis statistics
            old_stats: Previous analysis statistics for comparison
        """
    
    def generate_reports(self):
        """Generate and display all reports."""

Custom Reporter Development

Framework for creating custom reporters for specific output formats or integrations.

# Custom reporter pattern
class CustomReporter(BaseReporter):
    """Template for custom reporter implementation."""
    
    name = 'custom'  # Unique name for the reporter
    extension = 'ext'  # File extension for output
    
    def __init__(self, output=None):
        """Initialize custom reporter."""
        super().__init__(output)
        self.custom_data = {}
    
    def handle_message(self, msg):
        """Process each message according to custom format."""
        # Custom message processing logic
        formatted_msg = self.format_message(msg)
        self.writeln(formatted_msg)
    
    def format_message(self, msg):
        """Format message according to custom requirements."""
        return f"Custom: {msg.path}:{msg.line} - {msg.msg}"
    
    def display_reports(self, layout):
        """Generate custom report format."""
        # Custom report generation logic
        pass

Usage Examples

Using Built-in Reporters

from pylint.lint import PyLinter
from pylint.reporters import TextReporter, JSONReporter
import sys

# Text reporter to stdout
linter = PyLinter()
text_reporter = TextReporter(sys.stdout)
linter.set_reporter(text_reporter)
linter.check(['mymodule.py'])

# JSON reporter to file
with open('pylint_results.json', 'w') as f:
    json_reporter = JSONReporter(f)
    linter.set_reporter(json_reporter)
    linter.check(['mymodule.py'])

# Collecting reporter for programmatic access
from pylint.reporters import CollectingReporter
collector = CollectingReporter()
linter.set_reporter(collector)
linter.check(['mymodule.py'])
messages = collector.finalize()
for msg in messages:
    print(f"{msg.msg_id}: {msg.msg}")

Multiple Output Formats

from pylint.reporters import MultiReporter, TextReporter, JSONReporter
import sys

# Output to both console and JSON file
text_reporter = TextReporter(sys.stdout)
with open('results.json', 'w') as f:
    json_reporter = JSONReporter(f)
    multi_reporter = MultiReporter([text_reporter, json_reporter])
    
    linter = PyLinter()
    linter.set_reporter(multi_reporter)
    linter.check(['mymodule.py'])

Custom Reporter Implementation

from pylint.reporters import BaseReporter
import xml.etree.ElementTree as ET

class XMLReporter(BaseReporter):
    """Custom XML reporter for test result integration."""
    
    name = 'xml'
    extension = 'xml'
    
    def __init__(self, output=None):
        super().__init__(output)
        self.root = ET.Element('pylint-results')
        self.current_file = None
    
    def on_set_current_module(self, module, filepath):
        """Create XML element for new module."""
        self.current_file = ET.SubElement(self.root, 'file')
        self.current_file.set('name', filepath)
    
    def handle_message(self, msg):
        """Add message as XML element."""
        if self.current_file is not None:
            issue = ET.SubElement(self.current_file, 'issue')
            issue.set('line', str(msg.line))
            issue.set('column', str(msg.column))
            issue.set('severity', msg.category)
            issue.set('message', msg.msg)
            issue.set('message-id', msg.msg_id)
    
    def display_reports(self, layout):
        """Output final XML."""
        tree = ET.ElementTree(self.root)
        tree.write(self.out, encoding='unicode', xml_declaration=True)

# Register and use custom reporter
def register_reporter(reporter_class):
    """Register custom reporter with pylint."""
    # Registration logic would go here
    pass

register_reporter(XMLReporter)

IDE Integration Reporter

class IDEReporter(BaseReporter):
    """Reporter optimized for IDE integration."""
    
    name = 'ide'
    
    def __init__(self, output=None):
        super().__init__(output)
        self.messages_by_file = {}
    
    def handle_message(self, msg):
        """Group messages by file for IDE consumption."""
        if msg.path not in self.messages_by_file:
            self.messages_by_file[msg.path] = []
        
        self.messages_by_file[msg.path].append({
            'line': msg.line,
            'column': msg.column,
            'severity': self.map_severity(msg.category),
            'message': msg.msg,
            'rule': msg.msg_id
        })
    
    def map_severity(self, category):
        """Map pylint categories to IDE severity levels."""
        mapping = {
            'E': 'error',
            'F': 'error', 
            'W': 'warning',
            'C': 'info',
            'R': 'info',
            'I': 'info'
        }
        return mapping.get(category, 'info')
    
    def display_reports(self, layout):
        """Output IDE-friendly format."""
        import json
        result = {
            'files': self.messages_by_file,
            'summary': {
                'total_files': len(self.messages_by_file),
                'total_issues': sum(len(msgs) for msgs in self.messages_by_file.values())
            }
        }
        json.dump(result, self.out, indent=2)

Output Format Examples

Text Reporter Output

************* Module mymodule
mymodule.py:10:0: C0111: Missing module docstring (missing-docstring)
mymodule.py:15:4: W0613: Unused argument 'param' (unused-argument)
mymodule.py:20:0: R0903: Too few public methods (1/2) (too-few-public-methods)

JSON Reporter Output

[
    {
        "type": "convention",
        "module": "mymodule",
        "obj": "",
        "line": 10,
        "column": 0,
        "path": "mymodule.py",
        "symbol": "missing-docstring",
        "message": "Missing module docstring",
        "message-id": "C0111"
    },
    {
        "type": "warning", 
        "module": "mymodule",
        "obj": "function_name",
        "line": 15,
        "column": 4,
        "path": "mymodule.py",
        "symbol": "unused-argument",
        "message": "Unused argument 'param'",
        "message-id": "W0613"
    }
]

Colorized Output

Terminal output with ANSI color codes for different message types:

  • Red: Errors and fatal messages
  • Yellow: Warnings
  • Blue: Conventions and refactoring suggestions
  • Green: Informational messages

Reporter Configuration

Command Line Reporter Selection

# Use specific reporter
pylint --output-format=json mymodule.py
pylint --output-format=colorized mymodule.py

# Output to file
pylint --output-format=json --output=results.json mymodule.py

# Use multiple reporters (with custom script)
pylint --load-plugins=custom_reporters --output-format=multi mymodule.py

Programmatic Reporter Configuration

from pylint.lint import PyLinter
from pylint.reporters import TextReporter

linter = PyLinter()

# Configure reporter options
reporter = TextReporter()
reporter.path_strip_prefix = '/project/root/'

linter.set_reporter(reporter)

# Configure report generation
linter.config.reports = True
linter.config.score = True
linter.config.msg_template = '{path}:{line}: {msg_id}: {msg}'

Install with Tessl CLI

npx tessl i tessl/pypi-pylint

docs

built-in-checkers.md

checker-development.md

configuration.md

core-linting.md

extensions.md

index.md

messages.md

pyreverse.md

reporters.md

test-utilities.md

tile.json