Section 1: A modern Python project from the ground up
Python versions and environments with uv
Install uv following the official instructions for your system, then check it:
uv --version
Installing Python itself
uv can download and manage Python versions for you, independent of the system Python:
uv python install 3.13
uv python list
You no longer need the system Python for development, which avoids breaking tools your operating system relies on. A .python-version file in a project tells uv which version that project uses:
uv python pin 3.13
Creating a project
Inside the old tidy folder, run:
uv init --package
This creates a pyproject.toml, a src/tidy package folder and a .python-version file. The --package flag means the project is meant to be installed and distributed, not just run as a script.
Adding dependencies
Instead of editing requirements.txt, add packages with uv:
uv add typer rich
uv add --dev pytest ruff mypy
uv updates pyproject.toml, resolves compatible versions, writes uv.lock and installs everything into a .venv folder in the project. Development dependencies go into a separate group so they are not required by people who install your package.
The lock file
pyproject.toml lists what your project needs, usually with flexible version ranges. uv.lock records the exact versions that were resolved, for every platform. Commit both files. When a teammate runs uv sync, they get exactly the same versions as you, which removes the classic "works on my machine" problem.
Running commands
You rarely need to activate the environment manually. Prefix commands with uv run:
uv run pytest
uv run tidy --help
uv run checks that the environment matches the lock file, syncs it if needed and then runs the command. If you prefer activating, source .venv/bin/activate (or .venv\Scripts\activate on Windows) still works.
Delete the old requirements.txt once everything runs through uv, and commit.