A template repository for developing Python packages using uv in a VSCode devcontainer. Comes pre-configured with uv and Quarto for package documentation.
- Devcontainer configuration for VSCode
- uv for dependency, virtual environment and Python version management (replaces pip, pipx, pyenv and Poetry)
- Quarto for documentation
- Pre-configured development environment
Pre-requisites: Ensure you have the following installed on your system: Visual Studio Code (VSCode) and Docker Desktop
- Click "Use this template" to create a new repository
- Clone your new repository
- Open in VSCode with devcontainer extension
- VSCode will prompt to reopen in container - accept this (will take a few minutes)
Alternatively, click 'Use this template' in this repository, then select 'Open in a codespace' to try it out directly in your browser.
This section and the Example Project section below are two alternative walkthroughs — a generic one here and a concrete "hellopy" worked example further down. Pick one; running both in sequence will fail because the project can only be initialized once.
Open a terminal in your container workspace and run the following:
-
Initialize a uv project as a library (creates
pyproject.tomlwith PEP 621 metadata and a.python-version):uv init --lib
Important: run
uv initbefore anyuv add. If you runuv addin an uninitialized directory, uv will silently create an application project (not a library) using the folder name — and thenuv init --libwill refuse to run because the project already exists. -
Add development-only dependencies (recorded under the
devdependency group inpyproject.toml, not shipped to end users):uv add --dev pytest quartodoc
uv also supports arbitrary named groups — for example, docs-only dependencies:
uv add --group docs quartodoc
-
Add runtime dependencies your package needs:
uv add requests
-
Sync the environment (creates
.venv/in the project and writesuv.lock):uv sync
Documentation is handled through Quarto. To build the documentation:
uv run quarto renderThis is a concrete worked example. It is an alternative to Project Setup above — don't run both in the same project directory.
After creating a new repository from this template:
Alternatively, replace steps 1 and 2 by clicking 'Use this template' in this repository, then select 'Open in a codespace' to try it out directly in your browser.
-
Clone your repository and open in VSCode
git clone <your-repo-url> code <repo-directory>
-
When prompted, reopen in container (or use Command Palette: "Reopen in Container")
-
Initialize your uv project as a library (update with your details):
uv init --lib \ --name hellopy \ --description "Your package description" \ --author-from none \ --python 3.11With
--author-from noneuv deliberately omits theauthorsfield. To add it, openpyproject.tomland insert the following inside the[project]table (adjust the name and email):authors = [ {name = "Your Name", email = "your.email@example.com"}, ]
If you'd rather have uv auto-detect from your git config, drop
--author-from nonefrom the init command — uv's default is--author-from auto, which populates this field fromgit config user.name/user.email. -
uv init --libalready createdsrc/hellopy/__init__.py(with a samplehello()function) andsrc/hellopy/py.typed. Add a separatehello.pymodule alongside them:touch src/hellopy/hello.py
Then replace the contents of
src/hellopy/__init__.pywith a single re-export sofrom hellopy import helloworks from callers:from hellopy.hello import hello
Keep
src/hellopy/py.typed— it's an empty marker file that tells type checkers your package ships with type hints (PEP 561). -
Populate
hello.pywith the followingdef hello(): """ Print a greeting message. Example usage: ```{python} from hellopy.hello import hello hello() ``` """ print("Hello!")
-
Install your package in editable mode and add IPython / Jupyter as dev-only dependencies:
uv sync && \ uv add --dev ipython jupyter -
Activate the virtual environment
source .venv/bin/activateOr, skip activation and prefix commands with
uv run, e.g.uv run ipython. -
Start IPython (or an interactive Jupyter window)
ipython
-
In IPython, import
hello()from hellopy.hello import hello
-
Enjoy developing your package!
# Try editing `hello.py` and re-running the `hello()` command hello()
If you're coming from the previous Poetry-based template:
| Task | Poetry | uv |
|---|---|---|
| Create a project | poetry init |
uv init / uv init --lib |
| Add a runtime dependency | poetry add requests |
uv add requests |
| Add a dev-only dependency | poetry add --group dev pytest |
uv add --dev pytest |
| Add to a named group | poetry add --group docs quartodoc |
uv add --group docs quartodoc |
| Install all deps from lockfile | poetry install |
uv sync |
| Run a command in the venv | poetry run pytest |
uv run pytest |
| Update the lockfile | poetry lock |
uv lock |
| Build a distribution | poetry build |
uv build |
| Publish | poetry publish |
uv publish |
| Pin a Python version | poetry env use 3.11 |
uv python pin 3.11 |