CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-flake8

A comprehensive Python code quality checking tool that wraps PyFlakes, pycodestyle, and McCabe to provide unified static analysis with extensible plugin support.

Pending
Overview
Eval results
Files

exceptions.mddocs/

Exception Handling

Comprehensive exception hierarchy for handling errors during flake8 execution, including plugin loading failures, execution errors, and early termination scenarios.

Capabilities

Base Exception Class

Base exception class for all flake8-specific errors.

class Flake8Exception(Exception):
    """
    Base exception class for all flake8-specific errors.
    
    All flake8-related exceptions inherit from this class, allowing
    for easy exception handling of flake8-specific issues.
    
    Example:
    try:
        # flake8 operations
    except Flake8Exception as e:
        # Handle any flake8-specific error
    """

Execution Control Exceptions

Exceptions related to execution flow and early termination.

class EarlyQuit(Flake8Exception):
    """
    Exception raised when flake8 encounters a KeyboardInterrupt.
    
    This exception is raised when the user interrupts flake8 execution
    (typically with Ctrl+C) to provide clean termination handling.
    
    Example:
    try:
        style_guide.check_files(large_file_list)
    except EarlyQuit:
        print("Flake8 execution was interrupted by user")
    """

class ExecutionError(Flake8Exception):
    """
    Exception raised during general execution of flake8.
    
    This exception covers various execution errors that can occur
    during flake8's operation that are not covered by more specific
    exception types.
    
    Example:
    try:
        app.run(invalid_args)
    except ExecutionError as e:
        print(f"Execution failed: {e}")
    """

Plugin-Related Exceptions

Exceptions specifically related to plugin loading and execution failures.

class FailedToLoadPlugin(Flake8Exception):
    """
    Exception raised when a plugin fails to load.
    
    This exception occurs when flake8 cannot load a configured plugin,
    typically due to import errors, missing dependencies, or plugin
    code issues.
    """
    
    def __init__(self, plugin_name: str, exception: Exception) -> None:
        """
        Initialize plugin loading failure exception.
        
        Parameters:
        plugin_name: Name of the plugin that failed to load
        exception: The underlying exception that caused the failure
        """
    
    @property
    def plugin_name(self) -> str:
        """Name of the plugin that failed to load."""
    
    @property  
    def original_exception(self) -> Exception:
        """The underlying exception that caused the plugin loading failure."""

class PluginRequestedUnknownParameters(Flake8Exception):
    """
    Exception raised when a plugin requests unknown parameters.
    
    This exception occurs when a plugin tries to access configuration
    parameters or options that are not recognized by flake8.
    """
    
    def __init__(self, plugin_name: str, exception: Exception) -> None:
        """
        Initialize unknown parameters exception.
        
        Parameters:
        plugin_name: Name of the plugin requesting unknown parameters
        exception: The underlying exception from the parameter request
        """
    
    @property
    def plugin_name(self) -> str:
        """Name of the plugin that requested unknown parameters."""
    
    @property
    def original_exception(self) -> Exception:
        """The underlying exception from the parameter request."""

class PluginExecutionFailed(Flake8Exception):
    """
    Exception raised when a plugin fails during execution.
    
    This exception occurs when a plugin encounters an error while
    processing a file or performing its checking operations.
    """
    
    def __init__(self, filename: str, plugin_name: str, exception: Exception) -> None:
        """
        Initialize plugin execution failure exception.
        
        Parameters:
        filename: Path to the file being processed when the failure occurred
        plugin_name: Name of the plugin that failed during execution
        exception: The underlying exception that caused the execution failure
        """
    
    @property
    def filename(self) -> str:
        """Path to the file being processed when the plugin failed."""
    
    @property
    def plugin_name(self) -> str:
        """Name of the plugin that failed during execution."""
    
    @property
    def original_exception(self) -> Exception:
        """The underlying exception that caused the execution failure."""

Exception Handling Examples

Basic Exception Handling

from flake8.api import legacy
from flake8 import exceptions

def safe_flake8_check(files):
    """Run flake8 with comprehensive exception handling."""
    
    try:
        style_guide = legacy.get_style_guide()
        report = style_guide.check_files(files)
        return report.total_errors
        
    except exceptions.EarlyQuit:
        print("⚠️  Flake8 execution was interrupted by user")
        return -1
        
    except exceptions.ExecutionError as e:
        print(f"❌ Flake8 execution failed: {e}")
        return -1
        
    except exceptions.FailedToLoadPlugin as e:
        print(f"❌ Plugin loading failed: {e.plugin_name}")
        print(f"   Reason: {e.original_exception}")
        return -1
        
    except exceptions.PluginExecutionFailed as e:
        print(f"❌ Plugin execution failed: {e.plugin_name}")
        print(f"   File: {e.filename}")
        print(f"   Error: {e.original_exception}")
        return -1
        
    except exceptions.PluginRequestedUnknownParameters as e:
        print(f"❌ Plugin configuration error: {e.plugin_name}")
        print(f"   Reason: {e.original_exception}")
        return -1
        
    except exceptions.Flake8Exception as e:
        print(f"❌ General flake8 error: {e}")
        return -1
        
    except Exception as e:
        print(f"💥 Unexpected error: {e}")
        return -1

# Usage
result = safe_flake8_check(['myproject/'])
if result >= 0:
    print(f"Found {result} violations")
else:
    print("Check failed due to errors")

Plugin Error Recovery

from flake8.api import legacy
from flake8 import exceptions
import logging

class RobustFlake8Runner:
    """Flake8 runner with plugin error recovery."""
    
    def __init__(self):
        self.failed_plugins = set()
        self.logger = logging.getLogger(__name__)
    
    def run_with_fallback(self, files, plugins=None):
        """Run flake8 with automatic plugin fallback."""
        
        plugins = plugins or []
        working_plugins = [p for p in plugins if p not in self.failed_plugins]
        
        try:
            # Try with current working plugins
            style_guide = legacy.get_style_guide(
                enable_extensions=working_plugins
            )
            report = style_guide.check_files(files)
            return report.total_errors
            
        except exceptions.FailedToLoadPlugin as e:
            self.logger.warning(f"Plugin {e.plugin_name} failed to load: {e.original_exception}")
            self.failed_plugins.add(e.plugin_name)
            
            # Retry without the failed plugin
            if e.plugin_name in working_plugins:
                working_plugins.remove(e.plugin_name)
                return self.run_with_fallback(files, working_plugins)
            
            # If no plugins left, try with defaults
            return self._run_default(files)
            
        except exceptions.PluginExecutionFailed as e:
            self.logger.error(f"Plugin {e.plugin_name} failed on {e.filename}: {e.original_exception}")
            self.failed_plugins.add(e.plugin_name)
            
            # Retry without the failed plugin
            if e.plugin_name in working_plugins:
                working_plugins.remove(e.plugin_name)
                return self.run_with_fallback(files, working_plugins)
            
            return self._run_default(files)
            
        except exceptions.PluginRequestedUnknownParameters as e:
            self.logger.warning(f"Plugin {e.plugin_name} has configuration issues: {e.original_exception}")
            self.failed_plugins.add(e.plugin_name)
            
            # Retry without the problematic plugin
            if e.plugin_name in working_plugins:
                working_plugins.remove(e.plugin_name)
                return self.run_with_fallback(files, working_plugins)
            
            return self._run_default(files)
    
    def _run_default(self, files):
        """Run flake8 with only default built-in checkers."""
        
        try:
            self.logger.info("Running with default checkers only")
            style_guide = legacy.get_style_guide()
            report = style_guide.check_files(files)
            return report.total_errors
            
        except exceptions.Flake8Exception as e:
            self.logger.error(f"Even default flake8 failed: {e}")
            raise

# Usage
runner = RobustFlake8Runner()
try:
    violations = runner.run_with_fallback(
        ['myproject/'],
        plugins=['flake8-bugbear', 'flake8-import-order', 'flake8-docstrings']
    )
    print(f"Found {violations} violations")
except Exception as e:
    print(f"Complete failure: {e}")

Detailed Error Reporting

from flake8.api import legacy
from flake8 import exceptions
import traceback
import sys

def detailed_flake8_check(files, report_file=None):
    """Run flake8 with detailed error reporting."""
    
    error_report = {
        'success': False,
        'violations': 0,
        'errors': [],
        'warnings': []
    }
    
    try:
        style_guide = legacy.get_style_guide(show_source=True)
        report = style_guide.check_files(files)
        
        error_report['success'] = True
        error_report['violations'] = report.total_errors
        
        return error_report
        
    except exceptions.EarlyQuit:
        error_report['errors'].append({
            'type': 'EarlyQuit',
            'message': 'User interrupted execution',
            'fatal': False
        })
        
    except exceptions.FailedToLoadPlugin as e:
        error_report['errors'].append({
            'type': 'PluginLoadError',
            'plugin': e.plugin_name,
            'message': str(e.original_exception),
            'fatal': True,
            'traceback': traceback.format_exc()
        })
        
    except exceptions.PluginExecutionFailed as e:
        error_report['errors'].append({
            'type': 'PluginExecutionError',
            'plugin': e.plugin_name,
            'file': e.filename,
            'message': str(e.original_exception),
            'fatal': False,
            'traceback': traceback.format_exc()
        })
        
    except exceptions.PluginRequestedUnknownParameters as e:
        error_report['warnings'].append({
            'type': 'PluginConfigurationWarning',
            'plugin': e.plugin_name,
            'message': str(e.original_exception),
            'suggestion': 'Check plugin documentation and configuration'
        })
        
    except exceptions.ExecutionError as e:
        error_report['errors'].append({
            'type': 'ExecutionError',
            'message': str(e),
            'fatal': True,
            'traceback': traceback.format_exc()
        })
        
    except exceptions.Flake8Exception as e:
        error_report['errors'].append({
            'type': 'GeneralFlake8Error',
            'message': str(e),
            'fatal': True,
            'traceback': traceback.format_exc()
        })
        
    except Exception as e:
        error_report['errors'].append({
            'type': 'UnexpectedError',
            'message': str(e),
            'fatal': True,
            'traceback': traceback.format_exc()
        })
    
    # Save detailed report if requested
    if report_file:
        import json
        with open(report_file, 'w') as f:
            json.dump(error_report, f, indent=2)
    
    return error_report

def print_error_report(error_report):
    """Print formatted error report."""
    
    if error_report['success']:
        print(f"✅ Success! Found {error_report['violations']} violations")
        return
    
    print("❌ Flake8 execution encountered errors:")
    
    for error in error_report['errors']:
        print(f"\n🔥 {error['type']}: {error['message']}")
        if 'plugin' in error:
            print(f"   Plugin: {error['plugin']}")
        if 'file' in error:
            print(f"   File: {error['file']}")
        if error.get('fatal'):
            print("   ⚠️  This is a fatal error")
    
    for warning in error_report['warnings']:
        print(f"\n⚠️  {warning['type']}: {warning['message']}")
        if 'plugin' in warning:
            print(f"   Plugin: {warning['plugin']}")
        if 'suggestion' in warning:
            print(f"   💡 {warning['suggestion']}")

# Usage
if __name__ == "__main__":
    files_to_check = sys.argv[1:] or ['.']
    
    report = detailed_flake8_check(files_to_check, 'flake8-error-report.json')
    print_error_report(report)
    
    # Exit with appropriate code
    if report['success']:
        sys.exit(0 if report['violations'] == 0 else 1)
    else:
        sys.exit(2)  # Error during execution

Install with Tessl CLI

npx tessl i tessl/pypi-flake8

docs

cli.md

config-logging.md

exceptions.md

formatting.md

index.md

programmatic-api.md

tile.json