Claude Code Plugins

Community-maintained marketplace

Feedback

python-dev-practices

@tbhb/rig
0
0

Python development best practices for modern Python projects. Activated when working with Python files, pyproject.toml, or discussing Python patterns, testing, linting, type hints.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name python-dev-practices
description Python development best practices for modern Python projects. Activated when working with Python files, pyproject.toml, or discussing Python patterns, testing, linting, type hints.

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

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:

# 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:

# 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:

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

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

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

# 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)

[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

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.