home / skills / wdm0006 / python-skills / code-quality

code-quality skill

/skills/code-quality

This skill helps you improve Python library code quality by applying ruff linting, mypy typing, and clean refactoring across projects.

npx playbooks add skill wdm0006/python-skills --skill code-quality

Review the files below or copy the command above to add this skill to your agents.

Files (4)
SKILL.md
3.0 KB
---
name: improving-python-code-quality
description: Improves Python library code quality through ruff linting, mypy type checking, Pythonic idioms, and refactoring. Use when reviewing code for quality issues, adding type hints, configuring static analysis tools, or refactoring Python library code.
---

# Python Code Quality

## Quick Reference

| Tool | Purpose | Command |
|------|---------|---------|
| ruff | Lint + format | `ruff check src && ruff format src` |
| mypy | Type check | `mypy src` |

## Ruff Configuration

Minimal config in pyproject.toml:

```toml
[tool.ruff]
line-length = 88
target-version = "py310"

[tool.ruff.lint]
select = ["E", "W", "F", "I", "B", "C4", "UP"]
```

For full configuration options, see **[RUFF_CONFIG.md](RUFF_CONFIG.md)**.

## MyPy Configuration

```toml
[tool.mypy]
python_version = "3.10"
disallow_untyped_defs = true
warn_return_any = true
```

For strict settings and overrides, see **[MYPY_CONFIG.md](MYPY_CONFIG.md)**.

## Type Hints Patterns

```python
# Basic
def process(items: list[str]) -> dict[str, int]: ...

# Optional
def fetch(url: str, timeout: int | None = None) -> bytes: ...

# Callable
def apply(func: Callable[[int], str], value: int) -> str: ...

# Generic
T = TypeVar("T")
def first(items: Sequence[T]) -> T | None: ...
```

For protocols and advanced patterns, see **[TYPE_PATTERNS.md](TYPE_PATTERNS.md)**.

## Common Anti-Patterns

```python
# Bad: Mutable default
def process(items: list = []):  # Bug!
    ...

# Good: None default
def process(items: list | None = None):
    items = items or []
    ...
```

```python
# Bad: Bare except
try:
    ...
except:
    pass

# Good: Specific exception
try:
    ...
except ValueError as e:
    logger.error(e)
```

## Pythonic Idioms

```python
# Iteration
for item in items:           # Not: for i in range(len(items))
for i, item in enumerate(items):  # When index needed

# Dictionary access
value = d.get(key, default)  # Not: if key in d: value = d[key]

# Context managers
with open(path) as f:        # Not: f = open(path); try: finally: f.close()

# Comprehensions (simple only)
squares = [x**2 for x in numbers]
```

## Module Organization

```
src/my_library/
├── __init__.py      # Public API exports
├── _internal.py     # Private (underscore prefix)
├── exceptions.py    # Custom exceptions
├── types.py         # Type definitions
└── py.typed         # Type hint marker
```

## Checklist

```
Code Quality:
- [ ] ruff check passes
- [ ] mypy passes (strict mode)
- [ ] Public API has type hints
- [ ] Public API has docstrings
- [ ] No mutable default arguments
- [ ] Specific exception handling
- [ ] py.typed marker present
```

## Learn More

This skill is based on the [Code Quality](https://mcginniscommawill.com/guides/python-library-development/#code-quality-the-foundation) section of the [Guide to Developing High-Quality Python Libraries](https://mcginniscommawill.com/guides/python-library-development/) by [Will McGinnis](https://mcginniscommawill.com/).

Overview

This skill improves Python library code quality by applying ruff linting, mypy type checking, Pythonic idioms, and targeted refactors. It focuses on making public APIs typed and documented, removing common anti-patterns, and configuring static analysis for consistent results. Use it when reviewing or hardening library code for distribution and long-term maintenance.

How this skill works

The skill runs ruff to enforce linting and formatting rules and runs mypy for static type checking. It identifies mutable-defaults, bare excepts, untyped public functions, and other common anti-patterns, then suggests idiomatic rewrites and refactors. It also recommends minimal pyproject.toml configurations and module layout changes to support a clean, typed public API.

When to use it

  • During code review of a Python library before a release
  • When adding or enforcing type hints across a public API
  • When configuring or standardizing ruff and mypy for a repo
  • When refactoring legacy modules to remove anti-patterns
  • When preparing a library for packaging with proper type markers

Best practices

  • Run ruff (check + format) and mypy in CI with the repo’s pyproject.toml settings
  • Use explicit type hints on public functions and classes; keep internal types in types.py
  • Avoid mutable default arguments; prefer None with a local fallback
  • Catch specific exceptions and log or rewrap them instead of using bare except
  • Include a py.typed marker and docstrings for all public API elements

Example use cases

  • Add type annotations and mypy config for a previously untyped library module
  • Refactor functions that use mutable defaults or bare except blocks
  • Standardize ruff rules (line length, target Python version, selected codes) across projects
  • Audit a package to ensure public API functions are typed and documented before release
  • Create a minimal pyproject.toml with ruff and mypy settings to enable CI checks

FAQ

Will this skill change application logic while refactoring?

No. The goal is to preserve behavior while improving style, types, and safety. Any behavioral changes are flagged and reviewed before applying.

What minimal configs are recommended for ruff and mypy?

Use a pyproject.toml with ruff line-length and target-version plus a select lint list. For mypy, set python_version and enable disallow_untyped_defs and warn_return_any for stricter checks.