Improvements to the application and library documentation (#6726)

This commit is contained in:
Zanie Blue 2024-08-27 18:15:12 -05:00 committed by GitHub
parent 3ee6ca31f4
commit 75a5066e10
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 184 additions and 46 deletions

View File

@ -10,7 +10,7 @@ Python projects help manage Python applications spanning multiple files.
Python project metadata is defined in a `pyproject.toml` file. Python project metadata is defined in a `pyproject.toml` file.
!!! !!! tip
`uv init` can be used to create a new project. See [Creating projects](#creating-projects) for `uv init` can be used to create a new project. See [Creating projects](#creating-projects) for
details. details.
@ -24,58 +24,107 @@ version = "0.1.0"
description = "Add your description here" description = "Add your description here"
``` ```
It's recommended, but not required, to include a Python version requirement: It's recommended, but not required, to include a Python version requirement in the `[project]`
section:
```toml title="pyproject.toml" ```toml title="pyproject.toml"
[project]
requires-python = ">=3.12" requires-python = ">=3.12"
``` ```
This Python version requirement determines what syntax is valid in the project and affects the Including a Python version requirement defines the Python syntax that is allowed in the project and
versions of dependencies which can be used (they must support the same Python range). affects selection of dependency versions (they must support the same Python version range).
The `pyproject.toml` also lists dependencies of the project. uv supports modifying the standard The `pyproject.toml` also lists dependencies of the project in the `project.dependencies` and
dependency list from the command line with `uv add` and `uv remove`. uv also supports `project.optional-dependencies` fields. uv supports modifying the project's dependencies from the
[extended package sources](./dependencies.md) for advanced users. command line with `uv add` and `uv remove`. uv also supports extending the standard dependency
definitions with [package sources](./dependencies.md) in `tool.uv.sources`.
!!! tip !!! tip
See the official [`pyproject.toml` guide](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/) for more details on getting started with a `pyproject.toml`. See the official [`pyproject.toml` guide](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/) for more details on getting started with a `pyproject.toml`.
## Build systems
Projects _may_ define a `[build-system]` in the `pyproject.toml`. The build system defines how the
project should be packaged and installed.
uv uses the presence of a build system to determine if a project contains a package that should be
installed in the project virtual environment. If a build system is not defined, uv will not attempt
to build or install the project itself, just its dependencies. If a build system is defined, uv will
build and install the project into the project environment. Projects are installed in
[editable mode](https://setuptools.pypa.io/en/latest/userguide/development_mode.html) so changes to
the source code are reflected immediately, without reinstallation.
### Configuring project packaging
uv also allows manually declaring if a project should be packaged using the
[`tool.uv.package`](../reference/settings.md#package) setting.
Setting `tool.uv.package = true` will force a project to be built and installed into the project
environment. If no build system is defined, uv will use the setuptools legacy backend.
Setting `tool.uv.package = false` will force a project package _not_ to be built and installed into
the project environment. uv will ignore a declared build system when interacting with the project.
## Creating projects ## Creating projects
uv supports initializing a project with `uv init`. By default, uv will create a project in the uv supports creating a project with `uv init`.
working directory. Projects can be created 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 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. `pyproject.toml`, uv will exit with an error.
By default, uv will create a project for an [application](#applications). However, the `--lib` flag When creating projects, uv distinguishes between two types: [**applications**](#applications) and
can be used to create a project for a [library](#libraries). [**libraries**](#libraries).
## Project types By default, uv will create a project for an application. The `--lib` flag can be used to create a
project for a library instead.
uv groups projects into two types: **applications** and **libraries**.
### Applications ### Applications
Application projects are suitable for web servers, scripts, and command-line interfaces. Application projects are suitable for web servers, scripts, and command-line interfaces.
Application projects have the following traits: Applications are the default target for `uv init`, but can also be specified with the `--app` flag:
- A build backend is not defined. ```console
- Source code is often in the top-level directory, e.g., `hello.py`. $ uv init --app example-app
- The project package is not installed in the project environment. $ tree example-app
example-app
├── README.md
├── hello.py
└── pyproject.toml
```
!!! note 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.
The `--package` flag can be passed to `uv init` to create a distributable application, ```toml title="pyproject.toml"
e.g., if you want to publish a command-line interface via PyPI. uv will define a build [project]
backend for the project, include a `[project.scripts]` entrypoint, and install the project name = "example-app"
package into the project environment. version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
```
Similarly, a build backend can be manually defined to treat any application as a distributable The created script defines a `main` function with some standard boilerplate:
package. This may require changes to the project directory structure, depending on the build
backend. ```python title="hello.py"
def main():
print("Hello from example-app!")
if __name__ == "__main__":
main()
```
And can be executed with `uv run`:
```console
$ uv run hello.py
Hello from example-project!
```
### Libraries ### Libraries
@ -83,30 +132,119 @@ A library is a project that is intended to be built and distributed as a Python
example, by uploading it to PyPI. A library provides functions and objects for other projects to example, by uploading it to PyPI. A library provides functions and objects for other projects to
consume. consume.
Library projects have the following traits: Libraries can be created by using the `--lib` flag:
- A build backend is required. ```console
- Source code is typically in a `src/{package}` directory. $ uv init --lib example-lib
- The project package is installed in the project environment. $ tree example-lib
example-lib
├── README.md
├── pyproject.toml
└── src
└── example_lib
└── __init__.py
```
Libraries can be created with `uv init` by providing the `--lib` flag. uv will assume that any When creating a library, uv defines a build system and places the source code in placed in a `src`
project that defines a `[build-system]` is a library. 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.
### Other types ```toml title="pyproject.toml"
[project]
name = "example-lib"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
By default, uv uses the presence of a `[build-system]` in the `pyproject.toml` to determine if a [build-system]
project is an application or a library. However, uv also allows manually declaring if a project requires = ["hatchling"]
should be treated as a package. build-backend = "hatchling.build"
```
To enable or disable build and installation of the project package regardless of the presence of a !!! note
`[build-system]` definition, use the [`tool.uv.package`](../reference/settings.md#package) setting.
Setting `tool.uv.package = true` will force a project package to be built and installed into the uv does not provide a build backend yet. `hatchling` is used by default, but there are other
project environment. If no build system is defined, uv will use the setuptools legacy backend. 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.
Setting `tool.uv.package = false` will force a project package _not_ to be built and installed into Progress towards a uv build backend can be tracked in [astral-sh/uv#3957](https://github.com/astral-sh/uv/issues/3957).
the project environment. uv will ignore the declared build system, if any, when interacting with the
project. The created module defines a simple API function:
```python title="__init__.py"
def hello() -> str:
return "Hello from example-lib!"
```
And you can import and execute it using `uv run`:
```console
$ uv run python -c "import example_lib; print(example_lib.hello())"
Hello from example-lib!
```
### 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:
```console
$ uv init --app --package example-packaged-app
$ tree example-packaged-app
example-packaged-app
├── README.md
├── pyproject.toml
└── src
└── example_packaged-app
└── __init__.py
```
But the module defines a CLI function:
```python title="__init__.py"
def hello():
print("Hello from example-packaged-app!")
```
And the `pyproject.toml` includes a script entrypoint:
```python title="pyproject.toml" hl_lines="9 10"
[project]
name = "example-packaged-app"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
[project.scripts]
hello = "example_packaged_app:hello"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
```
Which can be executed with `uv run`:
```console
$ uv run hello
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.
## Project environments ## Project environments

View File

@ -12,7 +12,7 @@ distribution.
If your project does not include a `[build-system]` definition in the `pyproject.toml`, uv will not If your project does not include a `[build-system]` definition in the `pyproject.toml`, uv will not
build it by default. This means that your project may not be ready for distribution. Read more about build it by default. This means that your project may not be ready for distribution. Read more about
the effect of declaring a build system in the the effect of declaring a build system in the
[project concept](../concepts/projects.md#project-types) documentation. [project concept](../concepts/projects.md#build-systems) documentation.
## Building your package ## Building your package