Python Codebase Modernization
Upgrade Python projects to use modern tooling, syntax, and patterns following Engineering Charter principles.
Objectives
- Migrate from pip to uv for faster dependency management
- Upgrade Python syntax to 3.13+ modern patterns
- Replace deprecated APIs and patterns
- Update tooling to current best practices
- Ensure pyproject.toml is the single source of configuration
Required Tools
Install uv globally (via package manager): sudo zypper install uv or pip install --user uv
Add to [dependency-groups] dev: "pyupgrade", "ruff"
- uv: Fast package installer (pip replacement)
- pyupgrade: Auto-upgrade syntax to newer Python
- ruff: Modern linter with UP rules
Permissions: Run py-quality-setup first to configure .claude/settings.local.json with all needed tool permissions.
Package Manager: pip → uv
Why uv?
- 10-100x faster than pip
- Better dependency resolution
- Improved caching
- Compatible with pip (drop-in replacement)
- Actively developed by Astral (same team as ruff)
Migration Workflow
# 1. Verify current setup
cat requirements.txt setup.py setup.cfg pyproject.toml
# 2. Install uv globally (not recommended, ask user to install via package manager)
# curl -LsSf https://astral.sh/uv/install.sh | sh
# 3. Replace venv creation
# OLD: python -m venv venv
uv venv
# 4. Replace pip install
# OLD: pip install -e ".[dev]"
uv pip install -e ".[dev]"
# 5. Replace pip install from requirements.txt
# OLD: pip install -r requirements.txt
uv pip install -r requirements.txt
# 6. Compile requirements (faster dependency resolution)
uv pip compile pyproject.toml -o requirements.txt
# 7. Sync environment (install exactly what's in requirements.txt)
uv pip sync requirements.txt
Update CI/CD
# .github/workflows/test.yml
# BEFORE
- name: Install dependencies
run: |
python -m venv venv
source venv/bin/activate
pip install -e ".[dev]"
# AFTER
- name: Install uv
uses: astral-sh/setup-uv@v1
- name: Install dependencies
run: |
uv venv
source .venv/bin/activate
uv pip install -e ".[dev]"
Update Documentation
Update README.md:
<!-- BEFORE -->
## Development Setup
python -m venv venv
source venv/bin/activate
pip install -e ".[dev]"
<!-- AFTER -->
## Development Setup
# Install uv if not already installed (via package manager preferred)
# sudo zypper install uv # openSUSE
# or: pip install --user uv
uv venv
source .venv/bin/activate
uv pip install -e ".[dev]"
Python Syntax Modernization
Target Version
Set target in pyproject.toml:
[project]
requires-python = ">=3.13"
[tool.pyupgrade]
target-version = "py313"
[tool.ruff]
target-version = "py313"
[tool.ruff.lint]
select = ["UP"] # Enable pyupgrade rules
Run Syntax Upgrades
# Using pyupgrade directly (modifies files in-place)
pyupgrade --py313-plus **/*.py
# Using ruff (shows what would change)
ruff check . --select UP
ruff check . --select UP --fix # Apply fixes
# Verify changes
git diff
# Run tests to ensure functionality preserved
pytest
Common Modernizations
Run pyupgrade --py313-plus . or ruff check . --select UP to auto-upgrade:
- Type hints:
List[str]→list[str],Optional[int]→int | None - Remove
__future__: imports (built-in 3.11+) - String formatting:
%or.format()→ f-strings - Type unions:
Union[int, str]→int | str - Walrus operator:
if x := func():(reduce temp variables) - Match statements: Replace long if/elif chains (3.10+)
- Pathlib: Replace
os.pathwithPathobjects - Dataclasses: Replace manual
__init__with@dataclass
Configuration Modernization
Consolidate setup.py/setup.cfg/requirements.txt → pyproject.toml.
Note: For complete pyproject.toml configuration including ruff, mypy, and basedpyright, see py-quality-setup.
Basic structure:
[project]
name = "myproject"
version = "1.0.0"
requires-python = ">=3.13"
dependencies = ["requests", "pydantic"]
[build-system]
requires = ["setuptools>=68.0"]
build-backend = "setuptools.build_meta"
After: rm setup.py setup.cfg; uv pip install -e .; pytest
Deprecated Pattern Updates
Common deprecations to fix:
collections.Iterable→collections.abc.Iterable(deprecated 3.3, removed 3.10)datetime.utcnow()→datetime.now(UTC)(deprecated 3.12)datetime.utcfromtimestamp()→datetime.fromtimestamp(ts, UTC)(deprecated 3.12)impmodule →importlib(removed 3.12)typing.List,typing.Dict→list,dict(3.9+)typing.Optional[X]→X | None(3.10+)typing.Union[X, Y]→X | Y(3.10+)
Search for deprecated patterns:
# Find deprecated datetime usage
grep -rn "datetime.utcnow\|datetime.utcfromtimestamp" --include="*.py" .
# Find old typing imports
grep -rn "from typing import.*List\|from typing import.*Dict\|from typing import.*Optional" --include="*.py" .
# Find old collections imports
grep -rn "from collections import.*Callable\|from collections import.*Iterable" --include="*.py" .
Verification Checklist
-
uvis used for venv creation and package installation -
pyproject.tomlis the single configuration source (no setup.py/setup.cfg) -
requires-python = ">=3.13"is set in pyproject.toml -
ruff check . --select UPreports no issues (or only accepted exceptions) - No deprecated
datetime.utcnow()ordatetime.utcfromtimestamp()usage - No old-style typing imports (
List,Dict,Optional,Union) - CI/CD updated to use uv
- README.md reflects uv-based setup instructions
- All tests pass after modernization
Examples
Example: Migrate pip to uv
1. Check current setup:
- ls -la | grep -E "setup.py|requirements.txt|pyproject.toml"
- cat pyproject.toml
2. Install uv (if not already installed):
- Via package manager: sudo zypper install uv # openSUSE
- Or as user package: pip install --user uv
3. Test uv with current project:
- uv venv
- source .venv/bin/activate
- uv pip install -e ".[dev]"
- pytest (verify all tests pass)
4. Update CI/CD:
- Edit .github/workflows/test.yml
- Replace pip commands with uv
5. Update README:
- Replace pip instructions with uv
6. Commit: "Migrate from pip to uv for dependency management"
Example: Modernize syntax to Python 3.13
1. Update pyproject.toml:
[project]
requires-python = ">=3.13"
2. Run pyupgrade:
pyupgrade --py313-plus **/*.py
3. Review changes:
git diff
# Check: List[X] → list[X], Union[X, Y] → X | Y, etc.
4. Run ruff for additional upgrades:
ruff check . --select UP --fix
5. Verify type checking still works:
mypy .
basedpyright .
6. Run tests:
pytest
7. Commit: "Modernize syntax to Python 3.13+"
Example: Complete modernization
1. Migrate to uv (see Example 1)
2. Consolidate configuration:
- Read setup.py and setup.cfg
- Migrate all config to pyproject.toml
- Remove setup.py and setup.cfg
- Verify: uv pip install -e ".[dev]"
3. Modernize syntax (see Example 2)
4. Update deprecated APIs:
- grep -r "from collections import.*Iterable" .
- Replace with collections.abc
- grep -r "datetime.utcnow" .
- Replace with datetime.now(UTC)
5. Final validation:
- ruff check . --select UP (clean)
- pytest (all pass)
- mypy . && basedpyright . (no errors)
6. Update documentation:
- README reflects uv usage
- CONTRIBUTING.md updated
7. Commit: "Modernize codebase: uv, Python 3.13 syntax, pyproject.toml"
Related Skills
- Prerequisites: py-quality-setup (tool configuration), py-test-quality (safety net before syntax changes)
- Enforcement: py-git-hooks (enforce modern syntax via ruff UP rules)
- See also: py-complexity (modernization often enables simplification)