A Pytest Plugin for Mypy static type checking integration
—
Runtime configuration capabilities for customizing mypy integration behavior through conftest.py and global variables. Provides programmatic control over mypy execution, error formatting, and test naming.
Direct access to plugin configuration through global variables that can be modified at runtime.
# Global mypy command line arguments
mypy_argv: List[str]
"""
Global list of mypy command line arguments.
Automatically populated from pytest command line options and can be
extended programmatically in conftest.py for additional mypy configuration.
Example modifications:
- mypy_argv.append('--check-untyped-defs')
- mypy_argv.extend(['--strict', '--warn-redundant-casts'])
"""
# Test name formatting function
test_name_formatter: Callable[[MypyFileItem], str]
"""
Function used to format test names in pytest reports.
Default implementation shows "[mypy] relative/path/to/file.py".
Can be replaced with custom formatter for different naming schemes.
Parameters:
- item: MypyFileItem being formatted
Returns:
Formatted test name string for display in reports
"""
# File error formatting function
file_error_formatter: Callable[[MypyItem, MypyResults, List[str]], str]
"""
Function used to format mypy error messages for display.
Default implementation respects --mypy-report-style setting.
Can be replaced with custom formatter for specialized error display.
Parameters:
- item: MypyItem that encountered errors
- results: Complete MypyResults from execution
- lines: List of error lines for this item
Returns:
Formatted error message string for display
"""Built-in formatter functions that can be used or replaced.
def default_test_name_formatter(*, item: MypyFileItem) -> str:
"""
Default formatter for mypy test names.
Creates test names in the format "[mypy] relative/path/to/file.py"
using the file path relative to the pytest invocation directory.
Parameters:
- item: MypyFileItem to generate name for
Returns:
Formatted test name with [mypy] prefix and relative path
"""
def default_file_error_formatter(
item: MypyItem,
results: MypyResults,
lines: List[str]
) -> str:
"""
Default formatter for mypy error messages.
Formats error lines according to --mypy-report-style setting:
- 'mypy': Preserves original mypy output format
- 'no-path': Strips path prefixes for cleaner display
Parameters:
- item: MypyItem that encountered the errors
- results: Complete mypy execution results
- lines: Error lines to format
Returns:
Formatted error message string
"""Standard pattern for accessing and configuring the mypy plugin.
def pytest_configure(config: pytest.Config) -> None:
"""
Standard hook for configuring the mypy plugin.
The plugin module can be imported directly to access
global configuration variables and functions.
Parameters:
- config: Pytest configuration object
"""
import pytest_mypy
# Direct access to global configuration variables
pytest_mypy.mypy_argv.extend(['--strict', '--check-untyped-defs'])
pytest_mypy.test_name_formatter = custom_formatter
pytest_mypy.file_error_formatter = custom_error_formatterPlugin constants that define behavior and can be referenced for customization.
item_marker: str = "mypy"
"""Marker name applied to all mypy test items for filtering."""
nodeid_name: str = "mypy"
"""Base node ID name used for mypy test items."""
terminal_summary_title: str = "mypy"
"""Title used in pytest terminal summary section."""# conftest.py
def pytest_configure(config):
"""Add additional mypy checking options."""
import pytest_mypy
# Enable strict type checking
pytest_mypy.mypy_argv.extend([
'--strict',
'--check-untyped-defs',
'--warn-redundant-casts',
'--warn-unused-ignores'
])# conftest.py
def pytest_configure(config):
"""Customize mypy test names for better readability."""
import pytest_mypy
def custom_test_name(*, item):
"""Show just filename instead of full path."""
return f"[mypy] {item.path.name}"
pytest_mypy.test_name_formatter = custom_test_name# conftest.py
def pytest_configure(config):
"""Customize mypy error display format."""
import pytest_mypy
def detailed_error_formatter(item, results, lines):
"""Add context and statistics to error messages."""
error_count = len(lines)
header = f"Found {error_count} type issues in {item.path.name}:"
formatted_lines = []
for line in lines:
# Add severity highlighting
if "error:" in line:
formatted_lines.append(f"❌ {line}")
elif "warning:" in line:
formatted_lines.append(f"⚠️ {line}")
else:
formatted_lines.append(f"ℹ️ {line}")
return header + "\n" + "\n".join(formatted_lines)
pytest_mypy.file_error_formatter = detailed_error_formatter# conftest.py
import os
def pytest_configure(config):
"""Configure mypy based on environment."""
import pytest_mypy
# Strict checking in CI environment
if os.getenv('CI'):
pytest_mypy.mypy_argv.extend([
'--strict',
'--warn-unreachable',
'--disallow-any-generics'
])
else:
# More lenient for local development
pytest_mypy.mypy_argv.extend([
'--ignore-missing-imports',
'--allow-redefinition'
])# conftest.py
def pytest_configure(config):
"""Integrate mypy configuration with project settings."""
import pytest_mypy
# Use project-specific mypy configuration
project_mypy_config = config.rootpath / "tools" / "mypy.ini"
if project_mypy_config.exists():
pytest_mypy.mypy_argv.append(f"--config-file={project_mypy_config}")
# Custom exclusions based on pytest collection
if hasattr(config.option, 'ignore_paths'):
for ignore_path in config.option.ignore_paths:
pytest_mypy.mypy_argv.append(f"--exclude={ignore_path}")# conftest.py
def pytest_configure(config):
"""Add custom error handling and reporting."""
import pytest_mypy
# Store original error formatter
original_formatter = pytest_mypy.file_error_formatter
def logging_error_formatter(item, results, lines):
"""Log errors to external system before displaying."""
# Log to external monitoring system
import logging
logger = logging.getLogger('mypy_errors')
logger.error(f"Type errors in {item.path}: {len(lines)} issues")
# Use original formatting for display
return original_formatter(item, results, lines)
pytest_mypy.file_error_formatter = logging_error_formatterInstall with Tessl CLI
npx tessl i tessl/pypi-pytest-mypy