Agent skill
python-dev-practices
Python development best practices for modern Python projects. Activated when working with Python files, pyproject.toml, or discussing Python patterns, testing, linting, type hints.
Stars
163
Forks
31
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/testing/python-dev-practices
SKILL.md
Python development practices
Purpose
Comprehensive guide for Python development covering modern Python practices, type safety, testing strategies, and coding conventions.
When to use
This skill activates when:
- Creating or modifying Python files
- Working with pyproject.toml configuration
- Writing property-based or fuzz tests
- Handling type hints and type safety
- Setting up development environment
- Configuring linting, formatting, or type checking
Core principles
Minimal dependencies philosophy
CRITICAL: Standard library first, dependencies last.
- ALWAYS prefer standard library solutions
- Evaluate stdlib before considering third-party code
- Implementation over dependencies
Type safety requirements
MANDATORY: Comprehensive type hints for ALL code
python
from typing import Protocol
from typing_extensions import TypeIs, ReadOnly, TypedDict
class Config(TypedDict):
"""Configuration with immutable fields."""
name: ReadOnly[str]
options: ReadOnly[list[str]]
def is_valid_config(value: object) -> TypeIs[Config]:
"""Type narrowing with TypeIs."""
return isinstance(value, dict) and 'name' in value
Modern Python features
Leverage Python 3.10+ capabilities:
python
# Pattern matching (3.10+)
match argument:
case {"type": "option", "name": str(name)}:
return process_option(name)
case {"type": "value", "data": list(data)}:
return process_value(data)
case _:
raise ValueError(f"Unknown argument: {argument}")
# Dataclasses with slots and frozen
from dataclasses import dataclass
@dataclass(slots=True, frozen=True)
class Result:
"""Immutable result with memory efficiency."""
success: bool
data: dict[str, Any]
errors: list[str]
Import organization
Follow project conventions with isort/Ruff:
python
# Standard library imports first
import sys
from collections.abc import Sequence
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any, Protocol
# Third-party (minimal)
from typing_extensions import Doc, ReadOnly, TypeIs
# Local imports
from yourpackage._module import Module
from yourpackage.validation import Validator
Class organization standards
MANDATORY class member ordering:
python
class Processor:
# 1. Class State: Constants and class attributes
DEFAULT_CONFIG = "default"
RESERVED_NAMES = frozenset(["__init__", "__new__"])
# 2. Lifecycle: __init__ and __new__
def __init__(self, config: Config) -> None:
self._config = config
self._state = ProcessorState()
# 3. Magic Methods: __repr__, __str__, __len__
def __repr__(self) -> str:
return f"Processor(config={self._config!r})"
# 4. Public Interface: Properties, then public methods
@property
def name(self) -> str:
return self._config.get("name", self.DEFAULT_CONFIG)
def process(self, data: Sequence[str]) -> Result:
"""Process data."""
return self._process_impl(list(data))
# 5. Internals: Private/protected methods at bottom
def _process_impl(self, data: list[str]) -> Result:
pass
Testing strategy
Domain-centric test organization
text
tests/
├── unit/
│ ├── processing/
│ │ ├── test_data_processing.py
│ │ └── test_transformations.py
│ └── validation/
│ └── test_input_validation.py
├── properties/
│ └── test_invariants.py
└── fuzz/
└── test_fuzzing.py
Error handling patterns
python
class AppError(Exception):
"""Base exception for application."""
pass
class ValidationError(AppError):
"""Raised when validation fails."""
def __init__(self, message: str, field: str | None = None) -> None:
super().__init__(message)
self.field = field
def process_data(data: Sequence[str]) -> Result:
"""Process with clear error messages."""
if not data:
raise ValidationError("No data provided")
try:
return _process_impl(data)
except ValueError as e:
raise ValidationError(f"Invalid data format: {e}") from e
Package management with uv
Essential commands
bash
# CRITICAL: ALWAYS use 'uv run python' for script execution
uv run python scripts/analyze.py
uv run python -m yourpackage
# Install dependencies
uv sync
# Run tools
uv run pytest
uv run ruff check .
uv run basedpyright
Code quality tools
Configuration (pyproject.toml)
toml
[project]
requires-python = ">=3.14"
dependencies = ["typing-extensions>=4.8"]
[tool.basedpyright]
typeCheckingMode = "strict"
pythonVersion = "3.14"
[tool.ruff]
line-length = 88
target-version = "py314"
[tool.ruff.lint]
select = ["ALL"]
ignore = ["D", "ANN101", "ANN102"]
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "--strict-markers --cov=src --cov-report=term-missing"
Security practices
python
import shlex
from pathlib import Path
def validate_input(user_input: str) -> str:
"""Validate and sanitize user input."""
# Prevent command injection
if any(char in user_input for char in [';', '|', '&', '`', '$']):
raise ValueError("Invalid characters in input")
return shlex.quote(user_input)
def safe_path_resolution(user_path: str, base: Path) -> Path:
"""Safely resolve paths to prevent traversal."""
path = (base / user_path).resolve()
if not path.is_relative_to(base):
raise ValueError("Path traversal detected")
return path
Quick reference
Testing checklist
- Unit tests with >95% coverage
- Property-based tests for invariants
- Fuzz tests for robustness
- Benchmarks for critical paths
- Type checking passes (basedpyright)
- Linting passes (ruff)
- Domain-centric test organization
Remember: Prioritize type safety, comprehensive testing, and standard library usage in all development.
Didn't find tool you were looking for?