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

messages.mddocs/

Message System

Structured message definitions with categories, confidence levels, and detailed location information for precise error reporting and filtering. Pylint's message system provides comprehensive information about code issues with standardized formatting and metadata.

Capabilities

Message Representation

Core classes for representing individual messages and their metadata.

class Message:
    """
    Individual message/warning representation.
    
    Attributes:
        msg_id (str): Message identifier (e.g., 'C0111')
        symbol (str): Message symbol (e.g., 'missing-docstring')
        msg (str): Formatted message text
        C (str): Message category letter (C/R/W/E/F/I)
        category (str): Full category name
        confidence (str): Confidence level
        abspath (str): Absolute file path
        path (str): Relative file path
        module (str): Module name
        obj (str): Object name (function, class, etc.)
        line (int): Line number
        column (int): Column number
        end_line (int): End line number (optional)
        end_column (int): End column number (optional)
    """
    
    def __init__(self, msg_id, line=None, node=None, args=None, 
                 confidence=None, col_offset=None, end_lineno=None, 
                 end_col_offset=None):
        """
        Initialize message instance.
        
        Args:
            msg_id (str): Message identifier
            line (int): Line number
            node: AST node
            args (tuple): Message arguments
            confidence (str): Confidence level
            col_offset (int): Column offset
            end_lineno (int): End line number
            end_col_offset (int): End column offset
        """
    
    def format(self, template=None):
        """
        Format message according to template.
        
        Args:
            template (str): Format template
            
        Returns:
            str: Formatted message
        """

Message Definitions

Classes for defining and managing message types and their properties.

class MessageDefinition:
    """
    Message type definition.
    
    Defines the structure and properties of a specific message type
    including its identifier, description, and formatting template.
    """
    
    def __init__(self, checker, msgid, msg, description, symbol=None, 
                 scope=None, minversion=None, maxversion=None, 
                 old_names=None):
        """
        Initialize message definition.
        
        Args:
            checker: Checker that defines this message
            msgid (str): Unique message identifier (e.g., 'C0111')
            msg (str): Message template with placeholders
            description (str): Detailed description
            symbol (str): Symbolic name (e.g., 'missing-docstring') 
            scope (str): Scope where message applies
            minversion (tuple): Minimum Python version
            maxversion (tuple): Maximum Python version
            old_names (list): Previous names for this message
        """
    
    @property
    def msgid(self):
        """Message identifier."""
        return self._msgid
    
    @property
    def symbol(self):
        """Message symbol."""
        return self._symbol
    
    def format_help(self, checkerref=False):
        """
        Format help text for this message.
        
        Args:
            checkerref (bool): Include checker reference
            
        Returns:
            str: Formatted help text
        """

class MessageDefinitionStore:
    """
    Storage for message definitions.
    
    Manages the collection of all message definitions from
    all checkers, providing lookup and validation capabilities.
    """
    
    def __init__(self):
        """Initialize empty message definition store."""
        self._messages_definitions = {}
        self._msgs_by_category = {}
    
    def register_message(self, message_definition):
        """
        Register a message definition.
        
        Args:
            message_definition: MessageDefinition instance
        """
    
    def get_message_definitions(self, msgid_or_symbol):
        """
        Get message definition by ID or symbol.
        
        Args:
            msgid_or_symbol (str): Message ID or symbol
            
        Returns:
            MessageDefinition: Message definition if found
        """
    
    def get_msg_display_string(self, msgid):
        """
        Get display string for message.
        
        Args:
            msgid (str): Message identifier
            
        Returns:
            str: Display string combining ID and symbol
        """

Message ID Management

Classes for managing message identifiers and symbolic names.

class MessageIdStore:
    """
    Message ID management and lookup.
    
    Provides mapping between message IDs, symbols, and their
    definitions, including support for deprecated message names.
    """
    
    def __init__(self):
        """Initialize message ID store."""
        self._msgid_to_symbol = {}
        self._symbol_to_msgid = {}
        self._old_names = {}
    
    def register_message_definition(self, msgid, symbol, old_names=None):
        """
        Register message ID and symbol mapping.
        
        Args:
            msgid (str): Message identifier
            symbol (str): Message symbol
            old_names (list): List of deprecated names
        """
    
    def get_active_msgids(self, msgid_or_symbol):
        """
        Get active message IDs for given ID or symbol.
        
        Args:
            msgid_or_symbol (str): Message ID or symbol
            
        Returns:
            list: Active message IDs
        """
    
    def get_msgid(self, symbol):
        """
        Get message ID from symbol.
        
        Args:
            symbol (str): Message symbol
            
        Returns:
            str: Message ID
        """
    
    def get_symbol(self, msgid):
        """
        Get symbol from message ID.
        
        Args:
            msgid (str): Message ID
            
        Returns:
            str: Message symbol
        """

Message Categories

Category Definitions

# Message category mappings
MSG_TYPES = {
    'I': 'info',        # Informational messages
    'C': 'convention',  # Coding standard violations  
    'R': 'refactor',    # Refactoring suggestions
    'W': 'warning',     # Potential issues
    'E': 'error',       # Probable bugs
    'F': 'fatal'        # Errors preventing further processing
}

# Category status codes for exit codes
MSG_TYPES_STATUS = {
    'I': 0,  # Info - no impact on exit code
    'C': 2,  # Convention violation
    'R': 4,  # Refactor suggestion
    'W': 8,  # Warning
    'E': 16, # Error
    'F': 32  # Fatal error
}

Confidence Levels

# Confidence level constants
HIGH = "HIGH"                    # High confidence in the issue
CONTROL_FLOW = "CONTROL_FLOW"    # Based on control flow analysis
INFERENCE = "INFERENCE"          # Based on type inference
INFERENCE_FAILURE = "INFERENCE_FAILURE"  # Failed type inference
UNDEFINED = "UNDEFINED"          # No confidence level specified

Usage Examples

Creating Custom Messages

from pylint.checkers import BaseChecker
from pylint.interfaces import HIGH, INFERENCE

class CustomChecker(BaseChecker):
    """Example checker with custom messages."""
    
    name = 'custom'
    msgs = {
        'W9001': (
            'Function "%s" has too many parameters (%d > %d)',
            'too-many-params-custom',
            'Function should have fewer parameters for better maintainability',
        ),
        'C9001': (
            'Variable name "%s" should use snake_case',
            'invalid-variable-name-custom', 
            'Variable names should follow snake_case convention',
        ),
        'E9001': (
            'Undefined variable "%s" used in function "%s"',
            'undefined-variable-custom',
            'Variable must be defined before use',
        )
    }
    
    def visit_functiondef(self, node):
        """Check function parameters."""
        max_params = 5
        param_count = len(node.args.args)
        
        if param_count > max_params:
            self.add_message(
                'too-many-params-custom',
                node=node,
                args=(node.name, param_count, max_params),
                confidence=HIGH
            )
    
    def visit_name(self, node):
        """Check variable naming."""
        import re
        if not re.match(r'^[a-z_][a-z0-9_]*$', node.name):
            self.add_message(
                'invalid-variable-name-custom',
                node=node,
                args=(node.name,),
                confidence=INFERENCE
            )

Message Processing and Filtering

from pylint.lint import PyLinter
from pylint.reporters import CollectingReporter

# Collect messages for processing
collector = CollectingReporter()
linter = PyLinter()
linter.set_reporter(collector)
linter.check(['mymodule.py'])

messages = collector.finalize()

# Filter messages by category
errors = [msg for msg in messages if msg.category == 'error']
warnings = [msg for msg in messages if msg.category == 'warning']

# Filter by confidence level
high_confidence = [msg for msg in messages if msg.confidence == 'HIGH']

# Filter by message type
missing_docstrings = [msg for msg in messages 
                     if msg.symbol == 'missing-docstring']

# Group messages by file
from collections import defaultdict
by_file = defaultdict(list)
for msg in messages:
    by_file[msg.path].append(msg)

# Process each message
for msg in messages:
    print(f"{msg.path}:{msg.line}:{msg.column} - {msg.msg_id}: {msg.msg}")
    print(f"  Category: {msg.category}")
    print(f"  Confidence: {msg.confidence}")
    print(f"  Symbol: {msg.symbol}")

Custom Message Formatting

def format_message_custom(msg):
    """Custom message formatting function."""
    severity_map = {
        'error': '❌',
        'warning': '⚠️ ',
        'convention': '📋',
        'refactor': '♻️ ',
        'info': 'ℹ️ '
    }
    
    icon = severity_map.get(msg.category, '?')
    return f"{icon} {msg.path}:{msg.line} - {msg.msg} ({msg.symbol})"

# Apply custom formatting
for msg in messages:
    formatted = format_message_custom(msg)
    print(formatted)

Message Template Configuration

# Configure message template
linter = PyLinter()

# Standard templates
linter.config.msg_template = '{path}:{line}: [{msg_id}({symbol}), {obj}] {msg}'
linter.config.msg_template = '{path}:{line}:{column}: {category}: {msg} ({symbol})'

# Custom template with all fields
template = (
    '{path}:{line}:{column}: {msg_id}: {msg}\n'
    '  Category: {category} | Confidence: {confidence}\n'
    '  Object: {obj} | Symbol: {symbol}'
)
linter.config.msg_template = template

Built-in Message Examples

Convention Messages (C)

# C0103: invalid-name
# "Name doesn't conform to naming convention"

# C0111: missing-docstring  
# "Missing module/class/function docstring"

# C0301: line-too-long
# "Line too long (%d/%d characters)"

# C0326: bad-whitespace
# "Wrong hanging indentation"

Refactor Messages (R)

# R0201: no-self-use
# "Method could be a function"

# R0903: too-few-public-methods
# "Too few public methods (%d/%d)"

# R0913: too-many-arguments
# "Too many arguments (%d/%d)"

# R1705: no-else-return
# "Unnecessary else after return statement"

Warning Messages (W)

# W0613: unused-argument
# "Unused argument '%s'"

# W0622: redefined-builtin
# "Redefining built-in '%s'"

# W0703: broad-except
# "Catching too general exception %s"

# W1203: logging-fstring-interpolation
# "Use lazy % formatting in logging functions"

Error Messages (E)

# E0601: used-before-assignment
# "Using variable '%s' before assignment"

# E1101: no-member
# "%s %r has no %r member"

# E1120: no-value-for-parameter
# "No value provided for parameter %s in function call"

# E1136: unsubscriptable-object
# "Value '%s' is unsubscriptable"

Fatal Messages (F)

# F0001: fatal
# "Error occurred preventing further processing: %s"

# F0010: error
# "Error while code parsing: %s"

# F0202: method-check-failed
# "Unable to check methods signature (%s / %s)"

Message State Management

Disabling Messages

# Disable globally in configuration
linter.config.disable = ['missing-docstring', 'invalid-name']

# Disable via command line
# pylint --disable=missing-docstring,invalid-name mymodule.py

# Disable in code with comments
def my_function():  # pylint: disable=missing-docstring
    pass

class MyClass:  # pylint: disable=too-few-public-methods
    pass

# Disable for entire file
# pylint: disable=missing-docstring

# Disable for code block
# pylint: disable-next=unused-variable
x = get_value()

Enabling Messages

# Enable specific messages
linter.config.enable = ['unused-variable']

# Enable message categories
linter.config.enable = ['warning', 'error']

# Enable all messages then disable specific ones
linter.config.disable = 'all'
linter.config.enable = ['error', 'fatal']

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