Section 1: A modern Python project from the ground up
Why Python tooling changed
For years, setting up a Python project meant combining several separate tools. You might install Python with your operating system or pyenv, create an environment with venv or virtualenv, install packages with pip, pin them with pip-tools, and format and lint with black, isort and flake8. Each tool had its own configuration file and its own quirks. New team members often spent their first day just getting tests to run.
Two things improved the situation.
One file for configuration
Packaging standards settled on pyproject.toml as the place for project metadata: the name, version, dependencies and build system. Most tools now read their settings from the same file, so setup.py, setup.cfg, requirements.txt and many dotfiles are no longer needed for new projects.
Fast, integrated tools
uv, from Astral, is a package and project manager written in Rust. It installs Python versions, creates virtual environments, resolves and installs dependencies, writes a lock file and runs commands inside the environment. It is much faster than pip, which matters more than it sounds: when installs take seconds instead of minutes, people stop avoiding clean environments.
Ruff, from the same team, is a linter and formatter that replaces flake8, isort, pyupgrade and black style formatting for most projects, again with a large speed improvement.
What this course does not claim
pip, venv and other tools still work and are still maintained. Poetry, PDM and Hatch are good project managers with their own strengths, and many teams are happy with them. I teach uv because it covers the whole workflow with one tool and has become a common default in new projects, but every concept here, such as lock files and the src layout, applies to the others too.
Our project
We will modernise tidy, a small command line tool that cleans CSV files. It currently has a requirements.txt with unpinned versions, inconsistent formatting, no type hints and tests that only run on the author's machine. By the end it will be a typed, tested package installable with one command.