| name | python-validation |
| description | Validate Python code quality using ruff, mypy, and best practices. Use when reviewing Python code, running linting/type checking, or ensuring code follows PEP 8 and type hint standards. |
| metadata | [object Object] |
What I do
- Guide agents to run ruff for linting and code style checking
- Guide agents to run mypy for type checking and type hints validation
- Ensure code follows PEP 257 docstring conventions
- Teach how to add and improve type hints (PEP 484)
- Check for Python best practices (PEP 8, naming conventions)
- Help interpret and fix linter warnings and errors
- Verify code is well-structured and maintainable
When to use me
Use this when you need to:
- Validate Python code quality with automated tools
- Run ruff to check code style and find issues
- Run mypy to verify type hints
- Add missing type annotations to functions and variables
- Improve code documentation (docstrings, comments)
- Fix linting warnings and type errors
- Ensure code follows Python best practices and conventions
Ask clarifying questions if:
- Code has complex type annotations that need clarification
- User wants to balance strictness with development speed
- Multiple files need validation with different standards
- Legacy code needs gradual migration to typed code
Sources
This skill synthesizes best practices from:
- Ruff documentation - Fast Python linter and formatter (astral.sh/ruff)
- Mypy documentation - Static type checker for Python (mypy.readthedocs.io)
- PEP 8 - Style Guide for Python Code (peps.python.org/pep-0008)
- PEP 257 - Docstring Conventions (peps.python.org/pep-0257)
- PEP 484 - Type Hints (peps.python.org/pep-0484)
- python-standards skill - Python development standards for production code
Quick Start
Full validation workflow:
- Run ruff for linting:
ruff check <file_or_dir> - Run ruff with auto-fix:
ruff check --fix <file_or_dir> - Run mypy for type checking:
mypy <file_or_dir> - Add missing type hints based on mypy output
- Add or improve docstrings following PEP 257
- Re-run tools to verify all issues resolved
Example: Validate a Python file
# Check for linting issues
ruff check myscript.py
# Auto-fix issues where possible
ruff check --fix myscript.py
# Check for type errors
mypy myscript.py
Validation Tools
1. Ruff - Linting and Style
Basic usage:
# Check all Python files in current directory
ruff check .
# Check specific file
ruff check mymodule.py
# Auto-fix issues
ruff check --fix .
Common ruff rules:
E- PEP 8 errors (indentation, line length, spacing)W- PEP 8 warnings (unused imports, unused variables)F- Pyflakes (undefined names, redefinition)I- Import sorting and organizationN- Naming conventions
Fixing common ruff issues:
# F401: Unused import
# Before
import os
import sys # Unused
# After
import os
# E501: Line too long
# Before
very_long_variable_name = some_function_that_has_a_really_long_name(argument1, argument2, argument3)
# After
very_long_variable_name = some_function_that_has_a_really_long_name(
argument1, argument2, argument3
)
# E501: Or break long strings
long_string = (
"This is a very long string that exceeds the "
"maximum line length limit"
)
# I001: Import sort order
# Before
from typing import List
import os
import sys
from mymodule import helper
# After
import os
import sys
from typing import List
from mymodule import helper
2. Mypy - Type Checking
Basic usage:
# Check all Python files
mypy .
# Check specific file
mypy mymodule.py
# Show error codes
mypy --show-error-codes mymodule.py
# Strict mode
mypy --strict mymodule.py
Common mypy errors and fixes:
Missing return annotation:
# Before (error: missing return annotation)
def calculate(x, y):
return x + y
# After
def calculate(x: int, y: int) -> int:
return x + y
Missing type for variable:
# Before (error: need type annotation)
result = some_function()
# After
result: str = some_function()
# Or let mypy infer (mypy will still complain without --no-strict-optional)
result = some_function() # mypy infers type
Incompatible types:
# Before (error: incompatible types)
def process(value: int) -> None:
print(value)
process("string") # Error: incompatible type
# After
def process(value: int) -> None:
print(value)
process(42) # OK
# Or change function signature to accept Union types
def process(value: int | str) -> None:
print(value)
Optional types:
from typing import Optional
# Before (error: None not compatible with int)
def get_value() -> int:
if some_condition:
return 42
return None # Error
# After
def get_value() -> Optional[int]:
if some_condition:
return 42
return None # OK
Type Hint Best Practices
Function Signatures
from typing import List, Dict, Optional, Union
def simple_function(x: int, y: int) -> int:
"""Add two numbers."""
return x + y
def with_defaults(name: str, count: int = 1) -> str:
"""Return name repeated count times."""
return name * count
def optional_return(value: Optional[int] = None) -> int:
"""Return value or default."""
return value if value is not None else 0
def complex_return() -> Dict[str, List[int]]:
"""Return dictionary with list values."""
return {"numbers": [1, 2, 3]}
def union_type(value: int | str) -> str:
"""Accept int or str, return str."""
return str(value)
Type Aliases
from typing import Dict, List, Tuple
# Define type aliases for complex types
DataPoint = Tuple[int, int, int] # x, y, z coordinates
TimeSeries = Dict[str, List[float]]
def process_points(points: List[DataPoint]) -> TimeSeries:
"""Process 3D points."""
return {"x": [p[0] for p in points],
"y": [p[1] for p in points],
"z": [p[2] for p in points]}
Documentation Standards
PEP 257 Docstring Conventions
One-line docstrings:
def add(x: int, y: int) -> int:
"""Return the sum of two integers."""
return x + y
Multi-line docstrings:
def process_data(data: List[str], threshold: int) -> Dict[str, int]:
"""
Process data and count items above threshold.
Args:
data: List of strings representing numbers.
threshold: Minimum value to count.
Returns:
Dictionary with 'above' and 'below' counts.
Raises:
ValueError: If data contains non-numeric strings.
"""
# Implementation
Module docstrings:
"""
Data processing utilities for financial analysis.
This module provides functions for parsing, validating, and processing
financial data from various sources.
Example:
>>> data = load_financial_data("report.csv")
>>> result = process_data(data)
"""
Code Quality Checklist
Before considering code validated:
- Ruff passes with no errors
- Mypy passes with no errors (or acceptable strictness level)
- All functions have type hints for parameters and return values
- All functions have docstrings following PEP 257
- Module has a docstring explaining its purpose
- Imports are sorted and organized correctly
- No unused imports or variables
- Lines are within reasonable length (79-88 characters)
- Naming follows conventions (snake_case, PascalCase, UPPER_CASE)
- Code is logically consistent and error-free
- Complex logic is explained with comments
Related Skills
This skill works well with:
python-standards: When you need Python best practices for production codepython-coder: When validation issues require code modifications
Use these skills together:
- python-validation provides validation workflows and tooling
- python-standards provides production-quality standards
- python-coder applies minimal fixes for validation issues
For advanced validation patterns and troubleshooting, see advanced.md.
Troubleshooting
If validation is overwhelming:
Too many ruff errors? Start with
ruff check --fixto auto-fix, then manually address remaining issues.Too many mypy errors? Start with less strict settings (
--no-strict-optional) and gradually increase strictness.Legacy code with no types? Add type hints incrementally, starting with function signatures and critical paths.
Conflicting ruff/mypy rules? Configure tool-specific settings in
pyproject.tomlor.mypy.ini.Large codebase? Validate one module at a time, establish patterns, then scale.
For comprehensive troubleshooting and edge cases, see advanced.md.