with one click
linting
// Expert in maintaining code quality standards using flake8, black, isort, and mypy. Use when fixing linting errors or enforcing code style. Use when this capability is needed.
// Expert in maintaining code quality standards using flake8, black, isort, and mypy. Use when fixing linting errors or enforcing code style. Use when this capability is needed.
| name | linting |
| description | Expert in maintaining code quality standards using flake8, black, isort, and mypy. Use when fixing linting errors or enforcing code style. Use when this capability is needed. |
| metadata | {"author":"jarosser06"} |
Learn how to maintain code quality using flake8, black, isort, and mypy for the Drift project.
# Check all linting (recommended before commits)
./lint.sh
# Auto-fix formatting issues
./lint.sh --fix
# flake8 (code quality checks)
flake8 src/drift/ tests/ --max-line-length=100
# black (code formatting)
black src/drift/ tests/ --line-length=100 --check
black src/drift/ tests/ --line-length=100 # Apply fixes
# isort (import sorting)
isort src/drift/ tests/ --profile=black --check
isort src/drift/ tests/ --profile=black # Apply fixes
# mypy (type checking)
mypy src/drift/
When flake8 reports lines over 100 characters, break them logically:
# Before - line too long
result = very_long_function_call_with_many_arguments(arg1, arg2, arg3, arg4, arg5, arg6, arg7)
# After - properly formatted
result = very_long_function_call_with_many_arguments(
arg1, arg2, arg3, arg4,
arg5, arg6, arg7
)
For long strings:
# Before
message = "This is a very long error message that exceeds the 100 character limit and needs to be broken up"
# After
message = (
"This is a very long error message that exceeds the 100 character "
"limit and needs to be broken up"
)
When isort or flake8 flags import order problems:
# Auto-fix with isort
isort src/drift/core/parser.py --profile=black
# Or fix all files
isort . --profile=black
Expected order:
# Standard library
import json
import os
from pathlib import Path
# Third-party
import boto3
import click
from botocore.exceptions import ClientError
# Local
from drift.core.parser import parse_conversation
from drift.core.detector import detect_drift
When mypy reports missing type hints, add them:
# Before - mypy error: Function is missing a return type annotation
def analyze_conversation(log_path, drift_types):
return {"results": []}
# After - properly typed
def analyze_conversation(
log_path: str,
drift_types: list[str]
) -> dict[str, list[str]]:
"""Analyze conversation log for drift."""
return {"results": []}
For optional parameters:
from typing import Optional
def detect_drift(
conversation: dict,
config: Optional[dict] = None
) -> list[str]:
"""Detect drift in conversation."""
pass
When flake8 reports unused imports:
# Before - flake8: 'json' imported but unused
import json
import os
def get_path():
return os.getcwd()
# After - removed unused import
import os
def get_path():
return os.getcwd()
Automated tools can help:
# autoflake removes unused imports
autoflake --remove-all-unused-imports --in-place src/drift/core/parser.py
# Auto-fix with black
black src/drift/
# Or manually in your editor (most editors can trim on save)
# Before - flake8: expected 2 blank lines, found 1
class DriftDetector:
pass
class Parser:
pass
# After - proper spacing
class DriftDetector:
pass
class Parser:
pass
Black auto-fixes these:
black src/drift/
./lint.sh
./lint.sh --fix
This automatically fixes:
After auto-fix, check what's left:
./lint.sh
Manually fix:
./lint.sh
Should see no errors before committing.
Add to .vscode/settings.json:
{
"python.linting.enabled": true,
"python.linting.flake8Enabled": true,
"python.linting.flake8Args": ["--max-line-length=100"],
"python.formatting.provider": "black",
"python.formatting.blackArgs": ["--line-length=100"],
"[python]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
}
}
src/drift/core/parser.py:45:80: E501 line too long (103 > 100 characters)
Format: file:line:column: code description
src/drift/core/parser.py:23: error: Function is missing a return type annotation
would reformat src/drift/core/parser.py
--diff to see exact changes before applyingfrom typing import Union
def get_config(as_dict: bool = False) -> Union[Config, dict]:
"""Get configuration."""
if as_dict:
return {"key": "value"}
return Config()
from typing import Iterator
def iter_messages(log_path: str) -> Iterator[dict]:
"""Iterate messages in log file."""
with open(log_path) as f:
for line in f:
yield json.loads(line)
from typing import TypeAlias
DriftResults: TypeAlias = dict[str, list[str]]
def analyze(log: str) -> DriftResults:
"""Analyze log for drift."""
return {"incomplete_work": ["instance1"]}
When mypy complains about missing stubs for third-party libraries:
pip install types-boto3 types-click
In pyproject.toml:
[tool.mypy]
ignore_missing_imports = true
Or per-import:
import some_untyped_library # type: ignore
Before creating a commit:
./lint.sh --fix to auto-fix what's possible./lint.sh to check for remaining issues./lint.sh should show no errorsThis ensures code quality and prevents failed CI checks.
Some conflicts (like E203) are configured to be ignored in flake8 config. Check pyproject.toml for ignored rules.
Use --profile=black to ensure isort is compatible with black:
isort . --profile=black
Sometimes mypy gets confused. Use # type: ignore sparingly:
result = complex_function() # type: ignore[return-value]
Better: Fix the type hint to be accurate.
Run on specific files during development:
black src/drift/core/parser.py
flake8 src/drift/core/parser.py
mypy src/drift/core/parser.py
Run full suite before committing.
Converted and distributed by TomeVault — claim your Tome and manage your conversions.