Project Setup

Getting a reproducible development environment off the ground

Concepts

Create the project with uv

Add dependencies

Automate tasks with taskipy

Lay out project

Check for Understanding

Why does pinning exact package versions in a lock file matter for reproducibility?

A package like litestar may release a new version that changes behavior or breaks an API. If you only record litestar>=0.1, anyone who installs the project later may get a different version than you tested with, and the code may fail in ways that are hard to diagnose. A lock file records the exact version such as litestar==2.14.0 so every installation is identical.

What is the difference between uv add and uv add --dev?

uv add installs a package as a runtime dependency: something the application needs to run. uv add --dev installs a package as a development dependency: something only needed during development, such as linters, test frameworks, type checkers. Development dependencies are not installed when someone deploys or imports the package in another project.

If you delete your .venv directory, what command recreates it with the same package versions?

uv sync reads pyproject.toml and uv.lock and recreates the environment with exactly the same versions that were pinned. You do not need to remember which packages to install or which versions to use.

Why use taskipy rather than just writing the commands down in a README?

Taskipy makes commands executable with a single short name like task test or task run rather than requiring the user to copy-paste from the README, remember flags, or navigate to the right directory. It also serves as living documentation that is always up to date, because if the command changes, pyproject.toml changes too.

Exercises

Extend the tasks

Add two new tasks to the [tool.taskipy.tasks] section of pyproject.toml: one that opens a Python REPL inside the virtual environment, and one that prints the exact Python version in use. Run both to confirm they work. Ask the LLM to help, then read the generated task definitions and make sure you understand what each one does before accepting it.

Explore dependency trees

Run uv tree and examine the output. Identify which of your runtime dependencies pulls in the most transitive packages. Ask the LLM to explain why that dependency has so many sub-dependencies and evaluate whether the explanation makes sense given what you know about the package.

Reproduce from scratch

Clone the repository into a fresh directory on your machine (or ask a classmate to do it on theirs). Prompt an LLM to set up an environment using the instructions in pyproject.toml and the README, then check that the "hello world" script runs.

Pin a specific version

Prompt the LLM to change the snailz dependency to a specific older version. Observe what changes in pyproject.toml and uv.lock, then restore the original constraint and explain the difference between a version constraint and a pinned version in one sentence.