
- Adds a collapsible section for the project concept - Splits the project concept document into several child documents. - Moves the workspace and dependencies documents to under the project section - Adds a mkdocs plugin for redirects, so links to the moved documents still work I attempted to make the minimum required changes to the contents of the documents here. There is a lot of room for improvement on the content of each new child document. For review purposes, I want to do that work separately. I'd prefer if the review focused on this structure and idea rather than the content of the files. I expect to do this to other documentation pages that would otherwise be very nested. The project concept landing page and nav (collapsed by default) looks like this now: <img width="1507" alt="Screenshot 2024-11-14 at 11 28 45 AM" src="https://github.com/user-attachments/assets/88288b09-8463-49d4-84ba-ee27144b62a5">
6.6 KiB
Creating projects
uv supports creating a project with uv init
.
uv will create a project in the working directory, or, in a target directory by providing a name,
e.g., uv init foo
. If there's already a project in the target directory, i.e., there's a
pyproject.toml
, uv will exit with an error.
When creating projects, uv distinguishes between two types: applications and libraries.
By default, uv will create a project for an application. The --lib
flag can be used to create a
project for a library instead.
Applications
Application projects are suitable for web servers, scripts, and command-line interfaces.
Applications are the default target for uv init
, but can also be specified with the --app
flag:
$ uv init --app example-app
$ tree example-app
example-app
├── .python-version
├── README.md
├── hello.py
└── pyproject.toml
When creating an application, uv will generate a minimal pyproject.toml
. A build system is not
defined and the source code is in the top-level directory, e.g., hello.py
. The project does not
contain a package that will be built and installed into the project environment.
[project]
name = "example-app"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
The created script defines a main
function with some standard boilerplate:
def main():
print("Hello from example-app!")
if __name__ == "__main__":
main()
And can be executed with uv run
:
$ uv run hello.py
Hello from example-project!
Libraries
A library is a project that is intended to be built and distributed as a Python package, for example, by uploading it to PyPI. A library provides functions and objects for other projects to consume.
Libraries can be created by using the --lib
flag:
$ uv init --lib example-lib
$ tree example-lib
example-lib
├── .python-version
├── README.md
├── pyproject.toml
└── src
└── example_lib
├── py.typed
└── __init__.py
When creating a library, uv defines a build system and places the source code in a src
directory.
These changes ensure that the library is isolated from any python
invocations in the project root
and that distributed library code is well separated from the rest of the project source code. The
project includes a package at src/example_lib
that will be built and installed into the project
environment.
[project]
name = "example-lib"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
!!! note
uv does not provide a build backend yet. `hatchling` is used by default, but there are other
options. You may need to use the [hatch build](https://hatch.pypa.io/1.9/config/build/) options
to configure `hatchling` for your project structure.
Progress towards a uv build backend can be tracked in [astral-sh/uv#3957](https://github.com/astral-sh/uv/issues/3957).
The created module defines a simple API function:
def hello() -> str:
return "Hello from example-lib!"
And you can import and execute it using uv run
:
$ uv run --directory example-lib python -c "import example_lib; print(example_lib.hello())"
Hello from example-lib!
You can select a different build backend template by using --build-backend
with hatchling
,
flit-core
, pdm-backend
, setuptools
, maturin
, or scikit-build-core
.
$ uv init --lib --build-backend maturin example-lib
$ tree example-lib
example-lib
├── .python-version
├── Cargo.toml
├── README.md
├── pyproject.toml
└── src
├── lib.rs
└── example_lib
├── py.typed
├── __init__.py
└── _core.pyi
And you can import and execute it using uv run
:
$ uv run --directory example-lib python -c "import example_lib; print(example_lib.hello())"
Hello from example-lib!
!!! tip
Changes to `lib.rs` or `main.cpp` will require running `--reinstall` when using binary build
backends such as `maturin` and `scikit-build-core`.
Packaged applications
The --package
flag can be passed to uv init
to create a distributable application, e.g., if you
want to publish a command-line interface via PyPI. uv will define a build backend for the project,
include a [project.scripts]
entrypoint, and install the project package into the project
environment.
The project structure looks the same as a library:
$ uv init --app --package example-packaged-app
$ tree example-packaged-app
example-packaged-app
├── .python-version
├── README.md
├── pyproject.toml
└── src
└── example_packaged_app
└── __init__.py
But the module defines a CLI function:
def main() -> None:
print("Hello from example-packaged-app!")
And the pyproject.toml
includes a script entrypoint:
[project]
name = "example-packaged-app"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
[project.scripts]
example-packaged-app = "example_packaged_app:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
Which can be executed with uv run
:
$ uv run --directory example-packaged-app example-packaged-app
Hello from example-packaged-app!
!!! tip
An existing application can be redefined as a distributable package by adding a build system.
However, this may require changes to the project directory structure, depending on the build
backend.
In addition, you can further customize the build backend of a packaged application by specifying
--build-backend
including binary build backends such as maturin
.
$ uv init --app --package --build-backend maturin example-packaged-app
$ tree example-packaged-app
example-packaged-app
├── .python-version
├── Cargo.toml
├── README.md
├── pyproject.toml
└── src
├── lib.rs
└── example_packaged_app
├── __init__.py
└── _core.pyi
Which can also be executed with uv run
:
$ uv run --directory example-packaged-app example-packaged-app
Hello from example-packaged-app!