A comprehensive Python code quality checking tool that wraps PyFlakes, pycodestyle, and McCabe to provide unified static analysis with extensible plugin support.
—
Logging configuration and general flake8 setup functionality for controlling output verbosity, log formatting, and accessing version information.
Configure flake8's internal logging system for debugging and monitoring execution.
def configure_logging(verbosity: int, filename: str | None = None, logformat: str = LOG_FORMAT) -> None:
"""
Configure logging for flake8 execution.
Sets up logging handlers, formatters, and levels for flake8's internal
logging system. Useful for debugging flake8 behavior and plugin execution.
Parameters:
verbosity: Logging verbosity level
- 0 or less: No logging (disabled)
- 1: INFO level logging (general information)
- 2 or more: DEBUG level logging (detailed debugging)
filename: Log output destination
- None: Log to stderr (default)
- "stdout": Log to stdout
- "stderr": Log to stderr explicitly
- Any other string: Log to file with that path
logformat: Log message format string using Python logging format
Default uses LOG_FORMAT constant with process info and timestamps
Example:
# Enable debug logging to file
configure_logging(2, filename="flake8-debug.log")
# Enable info logging to stdout
configure_logging(1, filename="stdout")
"""Usage example:
import flake8
from flake8.api import legacy
# Enable debug logging for troubleshooting
flake8.configure_logging(
verbosity=2,
filename="flake8-debug.log"
)
# Now run flake8 - all debug info will be logged
style_guide = legacy.get_style_guide()
report = style_guide.check_files(['myproject/'])Access flake8 version information for compatibility checking and reporting.
__version__: str
"""
Current flake8 version string.
String containing the semantic version of the installed flake8 package
in format "MAJOR.MINOR.PATCH" (e.g., "7.3.0").
Example:
print(f"Using flake8 version: {flake8.__version__}")
"""
__version_info__: tuple[int, ...]
"""
Version information as tuple of integers.
Tuple containing version components as integers for programmatic
version comparison and compatibility checking.
Example:
if flake8.__version_info__ >= (7, 0, 0):
# Use features available in flake8 7.0+
"""
LOG_FORMAT: str
"""
Default log format string for flake8 logging.
Format string used by configure_logging() when no custom format is provided.
Includes process name, relative timestamps, log level, and message.
Default format includes:
- Logger name (25 chars)
- Process name (11 chars)
- Relative creation time (6 digits)
- Log level (8 chars)
- Log message
Example format:
"%(name)-25s %(processName)-11s %(relativeCreated)6d %(levelname)-8s %(message)s"
"""Usage example:
import flake8
# Check version compatibility
def check_flake8_compatibility():
"""Check if flake8 version meets requirements."""
required_version = (7, 0, 0)
current_version = flake8.__version_info__
if current_version >= required_version:
print(f"✅ Flake8 {flake8.__version__} meets requirements")
return True
else:
print(f"❌ Flake8 {flake8.__version__} is too old")
print(f" Required: {'.'.join(map(str, required_version))}+")
return False
# Report version info
def report_environment():
"""Report flake8 environment information."""
print(f"Flake8 Version: {flake8.__version__}")
print(f"Version Info: {flake8.__version_info__}")
print(f"Log Format: {flake8.LOG_FORMAT}")
if __name__ == "__main__":
report_environment()
check_flake8_compatibility()import flake8
from flake8.api import legacy
import tempfile
import os
def debug_flake8_execution(files_to_check):
"""Run flake8 with detailed debugging information."""
# Create temporary debug log file
with tempfile.NamedTemporaryFile(mode='w', suffix='.log', delete=False) as f:
debug_log = f.name
try:
# Enable maximum verbosity
flake8.configure_logging(
verbosity=2,
filename=debug_log,
logformat="[%(asctime)s] %(name)s - %(levelname)s - %(message)s"
)
print(f"Debug logging enabled: {debug_log}")
# Run flake8 with debugging
style_guide = legacy.get_style_guide(show_source=True)
report = style_guide.check_files(files_to_check)
print(f"Execution complete. Found {report.total_errors} violations.")
# Display debug log contents
print("\n=== Debug Log Contents ===")
with open(debug_log, 'r') as f:
print(f.read())
finally:
# Clean up debug log
if os.path.exists(debug_log):
os.unlink(debug_log)
# Usage
debug_flake8_execution(['problematic_file.py'])import flake8
from flake8.api import legacy
import logging
import io
class FlakeLogAnalyzer:
"""Capture and analyze flake8 log output."""
def __init__(self):
self.log_stream = io.StringIO()
self.handler = None
def start_capture(self):
"""Start capturing flake8 log output."""
# Configure flake8 logging to capture in memory
flake8.configure_logging(
verbosity=2,
filename=None # This will use stderr, but we'll redirect
)
# Add our custom handler to capture logs
logger = logging.getLogger('flake8')
self.handler = logging.StreamHandler(self.log_stream)
self.handler.setLevel(logging.DEBUG)
logger.addHandler(self.handler)
def stop_capture(self):
"""Stop capturing and return log contents."""
if self.handler:
logger = logging.getLogger('flake8')
logger.removeHandler(self.handler)
log_contents = self.log_stream.getvalue()
self.log_stream.close()
return log_contents
def run_with_analysis(self, files):
"""Run flake8 and analyze log output."""
self.start_capture()
try:
# Run flake8
style_guide = legacy.get_style_guide()
report = style_guide.check_files(files)
# Analyze logs
logs = self.stop_capture()
# Simple analysis
log_lines = logs.split('\n')
error_lines = [line for line in log_lines if 'ERROR' in line]
warning_lines = [line for line in log_lines if 'WARNING' in line]
print(f"Execution Results:")
print(f" Violations found: {report.total_errors}")
print(f" Log errors: {len(error_lines)}")
print(f" Log warnings: {len(warning_lines)}")
if error_lines:
print("\nLog Errors:")
for error in error_lines:
print(f" {error}")
return report, logs
except Exception as e:
self.stop_capture()
raise e
# Usage
analyzer = FlakeLogAnalyzer()
report, logs = analyzer.run_with_analysis(['myproject/'])import flake8
from flake8.api import legacy
import logging.handlers
import os
def setup_production_logging(log_dir="/var/log/flake8"):
"""Set up production-ready flake8 logging."""
# Ensure log directory exists
os.makedirs(log_dir, exist_ok=True)
# Configure rotating log files
log_file = os.path.join(log_dir, "flake8.log")
# Set up flake8 logging with custom format
custom_format = (
"[%(asctime)s] %(name)s - %(levelname)s - "
"PID:%(process)d - %(message)s"
)
flake8.configure_logging(
verbosity=1, # INFO level for production
filename=log_file,
logformat=custom_format
)
# Also add rotating handler for long-term storage
logger = logging.getLogger('flake8')
rotating_handler = logging.handlers.RotatingFileHandler(
log_file, maxBytes=10*1024*1024, backupCount=5
)
rotating_handler.setFormatter(logging.Formatter(custom_format))
logger.addHandler(rotating_handler)
print(f"Production logging configured: {log_file}")
def production_quality_check(project_paths):
"""Run flake8 with production logging."""
setup_production_logging()
try:
style_guide = legacy.get_style_guide(
show_source=False, # Reduce log noise in production
statistics=False
)
total_violations = 0
for path in project_paths:
print(f"Checking {path}...")
report = style_guide.check_files([path])
total_violations += report.total_errors
print(f"Total violations across all projects: {total_violations}")
return total_violations == 0
except Exception as e:
logging.error(f"Quality check failed: {e}")
return False
# Usage
success = production_quality_check(['project1/', 'project2/'])
if not success:
print("Quality check failed - see logs for details")Install with Tessl CLI
npx tessl i tessl/pypi-flake8