From ca9aaf1c48c7351d7fd6cc844dfd688667749578 Mon Sep 17 00:00:00 2001 From: Zanie Blue Date: Tue, 19 Nov 2024 13:52:12 -0600 Subject: [PATCH] Reorganize the project concept documentation (#9121) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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: Screenshot 2024-11-14 at 11 28 45 AM --- crates/uv-dev/src/generate_json_schema.rs | 4 +- crates/uv-static/src/env_vars.rs | 2 +- crates/uv-workspace/src/pyproject.rs | 2 +- docs/concepts/index.md | 4 +- docs/concepts/projects.md | 920 ------------------- docs/concepts/projects/build.md | 51 + docs/concepts/projects/config.md | 322 +++++++ docs/concepts/{ => projects}/dependencies.md | 120 ++- docs/concepts/projects/index.md | 18 + docs/concepts/projects/init.md | 240 +++++ docs/concepts/projects/layout.md | 95 ++ docs/concepts/projects/run.md | 65 ++ docs/concepts/projects/sync.md | 58 ++ docs/concepts/{ => projects}/workspaces.md | 6 +- docs/concepts/resolution.md | 2 +- docs/configuration/environment.md | 2 +- docs/guides/integration/dependency-bots.md | 8 +- docs/guides/integration/docker.md | 4 +- docs/guides/integration/fastapi.md | 4 +- docs/guides/integration/github.md | 2 +- docs/guides/integration/jupyter.md | 8 +- docs/guides/projects.md | 22 +- docs/guides/publish.md | 2 +- docs/guides/scripts.md | 2 +- docs/guides/tools.md | 2 +- docs/index.md | 4 +- docs/reference/settings.md | 2 +- docs/requirements-insiders.txt | 2 +- docs/requirements.in | 1 + docs/requirements.txt | 2 +- mkdocs.template.yml | 17 +- uv.schema.json | 2 +- 32 files changed, 1015 insertions(+), 980 deletions(-) delete mode 100644 docs/concepts/projects.md create mode 100644 docs/concepts/projects/build.md create mode 100644 docs/concepts/projects/config.md rename docs/concepts/{ => projects}/dependencies.md (84%) create mode 100644 docs/concepts/projects/index.md create mode 100644 docs/concepts/projects/init.md create mode 100644 docs/concepts/projects/layout.md create mode 100644 docs/concepts/projects/run.md create mode 100644 docs/concepts/projects/sync.md rename docs/concepts/{ => projects}/workspaces.md (98%) diff --git a/crates/uv-dev/src/generate_json_schema.rs b/crates/uv-dev/src/generate_json_schema.rs index 82c5a7bd9..e22bad901 100644 --- a/crates/uv-dev/src/generate_json_schema.rs +++ b/crates/uv-dev/src/generate_json_schema.rs @@ -82,8 +82,8 @@ pub(crate) fn main(args: &Args) -> Result<()> { const REPLACEMENTS: &[(&str, &str)] = &[ // Use the fully-resolved URL rather than the relative Markdown path. ( - "(../concepts/dependencies.md)", - "(https://docs.astral.sh/uv/concepts/dependencies/)", + "(../concepts/projects/dependencies.md)", + "(https://docs.astral.sh/uv/concepts/projects/dependencies/)", ), ]; diff --git a/crates/uv-static/src/env_vars.rs b/crates/uv-static/src/env_vars.rs index 7099e0711..c792751d0 100644 --- a/crates/uv-static/src/env_vars.rs +++ b/crates/uv-static/src/env_vars.rs @@ -196,7 +196,7 @@ impl EnvVars { pub const UV_TOOL_BIN_DIR: &'static str = "UV_TOOL_BIN_DIR"; /// Specifies the path to the directory to use for a project virtual environment. - /// See the [project documentation](../concepts/projects.md#configuring-the-project-environment-path) + /// See the [project documentation](../concepts/projects/config.md#project-environment-path) /// for more details. pub const UV_PROJECT_ENVIRONMENT: &'static str = "UV_PROJECT_ENVIRONMENT"; diff --git a/crates/uv-workspace/src/pyproject.rs b/crates/uv-workspace/src/pyproject.rs index e47a480d9..d76f3b0e9 100644 --- a/crates/uv-workspace/src/pyproject.rs +++ b/crates/uv-workspace/src/pyproject.rs @@ -248,7 +248,7 @@ pub struct ToolUv { /// during development. A dependency source can be a Git repository, a URL, a local path, or an /// alternative registry. /// - /// See [Dependencies](../concepts/dependencies.md) for more. + /// See [Dependencies](../concepts/projects/dependencies.md) for more. #[option( default = "{}", value_type = "dict", diff --git a/docs/concepts/index.md b/docs/concepts/index.md index 5e3a02a74..9a61c46a7 100644 --- a/docs/concepts/index.md +++ b/docs/concepts/index.md @@ -2,9 +2,7 @@ Read the concept documents to learn more about uv's features: -- [Projects](./projects.md) -- [Dependencies](./dependencies.md) -- [Workspaces](./workspaces.md) +- [Projects](./projects/index.md) - [Tools](./tools.md) - [Python versions](./python-versions.md) - [Resolution](./resolution.md) diff --git a/docs/concepts/projects.md b/docs/concepts/projects.md deleted file mode 100644 index bf06051db..000000000 --- a/docs/concepts/projects.md +++ /dev/null @@ -1,920 +0,0 @@ -# Projects - -Python projects help manage Python applications spanning multiple files. - -!!! tip - - Looking for an introduction to creating a project with uv? See the [projects guide](../guides/projects.md) first. - -## Project metadata - -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 - details. - -A minimal project definition includes a name, version, and description: - -```toml title="pyproject.toml" -[project] -name = "example" -version = "0.1.0" -description = "Add your description here" -``` - -It's recommended, but not required, to include a Python version requirement in the `[project]` -section: - -```toml title="pyproject.toml" -requires-python = ">=3.12" -``` - -Including a Python version requirement defines the Python syntax that is allowed in the project and -affects selection of dependency versions (they must support the same Python version range). - -The `pyproject.toml` also lists dependencies of the project in the `project.dependencies` and -`project.optional-dependencies` fields. uv supports modifying the project's dependencies from the -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 - - 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`. - -## Defining entry points - -uv uses the standard `[project.scripts]` table to define entry points for the project. - -For example, to declare a command called `hello` that invokes the `hello` function in the -`example_package_app` module: - -```toml title="pyproject.toml" -[project.scripts] -hello = "example_package_app:hello" -``` - -!!! important - - Using `[project.scripts]` requires a [build system](#build-systems) to be defined. - -## 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. By default, 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 re-installation. - -### 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 - -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**](#applications) and -[**libraries**](#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: - -```console -$ 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. - -```toml title="pyproject.toml" -[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: - -```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 - -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: - -```console -$ 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. - -```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 = [] - -[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: - -```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 --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`. - -```console -$ 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`: - -```console -$ 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: - -```console -$ 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: - -```python title="__init__.py" -def main() -> None: - print("Hello from example-packaged-app!") -``` - -And the `pyproject.toml` includes a script entrypoint: - -```toml 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] -example-packaged-app = "example_packaged_app:main" - -[build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" -``` - -Which can be executed with `uv run`: - -```console -$ 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`. - -```console -$ 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`: - -```console -$ uv run --directory example-packaged-app example-packaged-app -Hello from example-packaged-app! -``` - -## Project environments - -When working on a project with uv, uv will create a virtual environment as needed. While some uv -commands will create a temporary environment (e.g., `uv run --isolated`), uv also manages a -persistent environment with the project and its dependencies in a `.venv` directory next to the -`pyproject.toml`. It is stored inside the project to make it easy for editors to find — they need -the environment to give code completions and type hints. It is not recommended to include the -`.venv` directory in version control; it is automatically excluded from `git` with an internal -`.gitignore` file. - -To run a command in the project environment, use `uv run`. Alternatively the project environment can -be activated as normal for a virtual environment. - -When `uv run` is invoked, it will create the project environment if it does not exist yet or ensure -it is up-to-date if it exists. The project environment can also be explicitly created with -`uv sync`. - -It is _not_ recommended to modify the project environment manually, e.g., with `uv pip install`. For -project dependencies, use `uv add` to add a package to the environment. For one-off requirements, -use [`uvx`](../guides/tools.md) or -[`uv run --with`](#running-commands-with-additional-dependencies). - -!!! tip - - If you don't want uv to manage the project environment, set [`managed = false`](../reference/settings.md#managed) - to disable automatic locking and syncing of the project. For example: - - ```toml title="pyproject.toml" - [tool.uv] - managed = false - ``` - -By default, the project will be installed in editable mode, such that changes to the source code are -immediately reflected in the environment. `uv sync` and `uv run` both accept a `--no-editable` flag, -which instructs uv to install the project in non-editable mode. `--no-editable` is intended for -deployment use-cases, such as building a Docker container, in which the project should be included -in the deployed environment without a dependency on the originating source code. - -### Configuring the project environment path - -The `UV_PROJECT_ENVIRONMENT` environment variable can be used to configure the project virtual -environment path (`.venv` by default). - -If a relative path is provided, it will be resolved relative to the workspace root. If an absolute -path is provided, it will be used as-is, i.e. a child directory will not be created for the -environment. If an environment is not present at the provided path, uv will create it. - -This option can be used to write to the system Python environment, though it is not recommended. -`uv sync` will remove extraneous packages from the environment by default and, as such, may leave -the system in a broken state. - -!!! important - - If an absolute path is provided and the setting is used across multiple projects, the - environment will be overwritten by invocations in each project. This setting is only recommended - for use for a single project in CI or Docker images. - -!!! note - - uv does not read the `VIRTUAL_ENV` environment variable during project operations. A warning - will be displayed if `VIRTUAL_ENV` is set to a different path than the project's environment. - -## Project lockfile - -uv creates a `uv.lock` file next to the `pyproject.toml`. - -`uv.lock` is a _universal_ or _cross-platform_ lockfile that captures the packages that would be -installed across all possible Python markers such as operating system, architecture, and Python -version. - -Unlike the `pyproject.toml`, which is used to specify the broad requirements of your project, the -lockfile contains the exact resolved versions that are installed in the project environment. This -file should be checked into version control, allowing for consistent and reproducible installations -across machines. - -A lockfile ensures that developers working on the project are using a consistent set of package -versions. Additionally, it ensures when deploying the project as an application that the exact set -of used package versions is known. - -The lockfile is created and updated during uv invocations that use the project environment, i.e., -`uv sync` and `uv run`. The lockfile may also be explicitly updated using `uv lock`. - -`uv.lock` is a human-readable TOML file but is managed by uv and should not be edited manually. -There is no Python standard for lockfiles at this time, so the format of this file is specific to uv -and not usable by other tools. - -!!! tip - - If you need to integrate uv with other tools or workflows, you can export `uv.lock` to `requirements.txt` format - with `uv export --format requirements-txt`. The generated `requirements.txt` file can then be installed via - `uv pip install`, or with other tools like `pip`. - - In general, we recommend against using both a `uv.lock` and a `requirements.txt` file. If you find yourself - exporting a `uv.lock` file, consider opening an issue to discuss your use case. - -### Checking if the lockfile is up-to-date - -To avoid updating the lockfile during `uv sync` and `uv run` invocations, use the `--frozen` flag. - -To avoid updating the environment during `uv run` invocations, use the `--no-sync` flag. - -To assert the lockfile matches the project metadata, use the `--locked` flag. If the lockfile is not -up-to-date, an error will be raised instead of updating the lockfile. - -### Upgrading locked package versions - -By default, uv will prefer the locked versions of packages when running `uv sync` and `uv lock`. -Package versions will only change if the project's dependency constraints exclude the previous, -locked version. - -To upgrade all packages: - -```console -$ uv lock --upgrade -``` - -To upgrade a single package to the latest version, while retaining the locked versions of all other -packages: - -```console -$ uv lock --upgrade-package -``` - -To upgrade a single package to a specific version: - -```console -$ uv lock --upgrade-package == -``` - -!!! note - - In all cases, upgrades are limited to the project's dependency constraints. For example, if the - project defines an upper bound for a package then an upgrade will not go beyond that version. - -### Limited resolution environments - -If your project supports a more limited set of platforms or Python versions, you can constrain the -set of solved platforms via the `environments` setting, which accepts a list of PEP 508 environment -markers. For example, to constrain the lockfile to macOS and Linux, and exclude Windows: - -```toml title="pyproject.toml" -[tool.uv] -environments = [ - "sys_platform == 'darwin'", - "sys_platform == 'linux'", -] -``` - -Entries in the `environments` setting must be disjoint (i.e., they must not overlap). For example, -`sys_platform == 'darwin'` and `sys_platform == 'linux'` are disjoint, but -`sys_platform == 'darwin'` and `python_version >= '3.9'` are not, since both could be true at the -same time. - -### Optional dependencies - -uv requires that all optional dependencies ("extras") declared by the project are compatible with -each other and resolves all optional dependencies together when creating the lockfile. - -If optional dependencies declared in one extra are not compatible with those in another extra, uv -will fail to resolve the requirements of the project with an error. - -To work around this, uv supports declaring conflicting extras. For example, consider two sets of -optional dependencies that conflict with one another: - -```toml title="pyproject.toml" -[project.optional-dependencies] -extra1 = ["numpy==2.1.2"] -extra2 = ["numpy==2.0.0"] -``` - -If you run `uv lock` with the above dependencies, resolution will fail: - -```console -$ uv lock - x No solution found when resolving dependencies: - `-> Because myproject[extra2] depends on numpy==2.0.0 and myproject[extra1] depends on numpy==2.1.2, we can conclude that myproject[extra1] and - myproject[extra2] are incompatible. - And because your project requires myproject[extra1] and myproject[extra2], we can conclude that your projects's requirements are unsatisfiable. -``` - -But if you specify that `extra1` and `extra2` are conflicting, uv will resolve them separately. -Specify conflicts in the `tool.uv` section: - -```toml title="pyproject.toml" -[tool.uv] -conflicts = [ - [ - { extra = "extra1" }, - { extra = "extra2" }, - ], -] -``` - -Now, running `uv lock` will succeed. Note though, that now you cannot install both `extra1` and -`extra2` at the same time: - -```console -$ uv sync --extra extra1 --extra extra2 -Resolved 3 packages in 14ms -error: extra `extra1`, extra `extra2` are incompatible with the declared conflicts: {`myproject[extra1]`, `myproject[extra2]`} -``` - -This error occurs because installing both `extra1` and `extra2` would result in installing two -different versions of a package into the same environment. - -The above strategy for dealing with conflicting extras also works with dependency groups: - -```toml title="pyproject.toml" -[dependency-groups] -group1 = ["numpy==2.1.2"] -group2 = ["numpy==2.0.0"] - -[tool.uv] -conflicts = [ - [ - { group = "group1" }, - { group = "group2" }, - ], -] -``` - -The only difference with conflicting extras is that you need to use `group` instead of `extra`. - -## Managing dependencies - -uv is capable of adding, updating, and removing dependencies using the CLI. - -To add a dependency: - -```console -$ uv add httpx -``` - -uv supports adding [editable dependencies](./dependencies.md#editable-dependencies), -[development dependencies](./dependencies.md#development-dependencies), -[optional dependencies](./dependencies.md#optional-dependencies), and alternative -[dependency sources](./dependencies.md#dependency-sources). See the -[dependency specification](./dependencies.md) documentation for more details. - -uv will raise an error if the dependency cannot be resolved, e.g.: - -```console -$ uv add 'httpx>9999' -error: Because only httpx<=9999 is available and example==0.1.0 depends on httpx>9999, we can conclude that example==0.1.0 cannot be used. -And because only example==0.1.0 is available and you require example, we can conclude that the requirements are unsatisfiable. -``` - -To remove a dependency: - -```console -$ uv remove httpx -``` - -To update an existing dependency, e.g., to add a lower bound to the `httpx` version: - -```console -$ uv add 'httpx>0.1.0' -``` - -!!! note - - "Updating" a dependency refers to changing the constraints for the dependency in the - `pyproject.toml`. The locked version of the dependency will only change if necessary to - satisfy the new constraints. To force the package version to update to the latest within - the constraints, use `--upgrade-package `, e.g.: - - ```console - $ uv add 'httpx>0.1.0' --upgrade-package httpx - ``` - - See the [lockfile](#upgrading-locked-package-versions) section for more details on upgrading - package versions. - -Or, to change the bounds for `httpx`: - -```console -$ uv add 'httpx<0.2.0' -``` - -To add a dependency source, e.g., to use `httpx` from GitHub during development: - -```console -$ uv add git+https://github.com/encode/httpx -``` - -### Platform-specific dependencies - -To ensure that a dependency is only installed on a specific platform or on specific Python versions, -use Python's standardized -[environment markers](https://peps.python.org/pep-0508/#environment-markers) syntax. - -For example, to install `jax` on Linux, but not on Windows or macOS: - -```console -$ uv add 'jax; sys_platform == "linux"' -``` - -The resulting `pyproject.toml` will then include the environment marker in the dependency -definition: - -```toml title="pyproject.toml" hl_lines="6" -[project] -name = "project" -version = "0.1.0" -requires-python = ">=3.11" -dependencies = ["jax; sys_platform == 'linux'"] -``` - -Similarly, to include `numpy` on Python 3.11 and later: - -```console -$ uv add 'numpy; python_version >= "3.11"' -``` - -See Python's [environment marker](https://peps.python.org/pep-0508/#environment-markers) -documentation for a complete enumeration of the available markers and operators. - -## Running commands - -When working on a project, it is installed into virtual environment at `.venv`. This environment is -isolated from the current shell by default, so invocations that require the project, e.g., -`python -c "import example"`, will fail. Instead, use `uv run` to run commands in the project -environment: - -```console -$ uv run python -c "import example" -``` - -When using `run`, uv will ensure that the project environment is up-to-date before running the given -command. - -The given command can be provided by the project environment or exist outside of it, e.g.: - -```console -$ # Presuming the project provides `example-cli` -$ uv run example-cli foo - -$ # Running a `bash` script that requires the project to be available -$ uv run bash scripts/foo.sh -``` - -### Running commands with additional dependencies - -Additional dependencies or different versions of dependencies can be requested per invocation. - -The `--with` option is used to include a dependency for the invocation, e.g., to request a different -version of `httpx`: - -```console -$ uv run --with httpx==0.26.0 python -c "import httpx; print(httpx.__version__)" -0.26.0 -$ uv run --with httpx==0.25.0 python -c "import httpx; print(httpx.__version__)" -0.25.0 -``` - -The requested version will be respected regardless of the project's requirements. For example, even -if the project requires `httpx==0.24.0`, the output above would be the same. - -### Running scripts - -Scripts that declare inline metadata are automatically executed in environments isolated from the -project. See the [scripts guide](../guides/scripts.md#declaring-script-dependencies) for more -details. - -For example, given a script: - -```python title="example.py" -# /// script -# dependencies = [ -# "httpx", -# ] -# /// - -import httpx - -resp = httpx.get("https://peps.python.org/api/peps.json") -data = resp.json() -print([(k, v["title"]) for k, v in data.items()][:10]) -``` - -The invocation `uv run example.py` would run _isolated_ from the project with only the given -dependencies listed. - -## Projects with many packages - -If working in a project composed of many packages, see the [workspaces](./workspaces.md) -documentation. - -## Building projects - -To distribute your project to others (e.g., to upload it to an index like PyPI), you'll need to -build it into a distributable format. - -Python projects are typically distributed as both source distributions (sdists) and binary -distributions (wheels). The former is typically a `.tar.gz` or `.zip` file containing the project's -source code along with some additional metadata, while the latter is a `.whl` file containing -pre-built artifacts that can be installed directly. - -`uv build` can be used to build both source distributions and binary distributions for your project. -By default, `uv build` will build the project in the current directory, and place the built -artifacts in a `dist/` subdirectory: - -```console -$ uv build -$ ls dist/ -example-0.1.0-py3-none-any.whl -example-0.1.0.tar.gz -``` - -You can build the project in a different directory by providing a path to `uv build`, e.g., -`uv build path/to/project`. - -`uv build` will first build a source distribution, and then build a binary distribution (wheel) from -that source distribution. - -You can limit `uv build` to building a source distribution with `uv build --sdist`, a binary -distribution with `uv build --wheel`, or build both distributions from source with -`uv build --sdist --wheel`. - -`uv build` accepts `--build-constraint`, which can be used to constrain the versions of any build -requirements during the build process. When coupled with `--require-hashes`, uv will enforce that -the requirement used to build the project match specific, known hashes, for reproducibility. - -For example, given the following `constraints.txt`: - -```text -setuptools==68.2.2 --hash=sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a -``` - -Running the following would build the project with the specified version of `setuptools`, and verify -that the downloaded `setuptools` distribution matches the specified hash: - -```console -$ uv build --build-constraint constraints.txt --require-hashes -``` - -## Build isolation - -By default, uv builds all packages in isolated virtual environments, as per -[PEP 517](https://peps.python.org/pep-0517/). Some packages are incompatible with build isolation, -be it intentionally (e.g., due to the use of heavy build dependencies, mostly commonly PyTorch) or -unintentionally (e.g., due to the use of legacy packaging setups). - -To disable build isolation for a specific dependency, add it to the `no-build-isolation-package` -list in your `pyproject.toml`: - -```toml title="pyproject.toml" -[project] -name = "project" -version = "0.1.0" -description = "..." -readme = "README.md" -requires-python = ">=3.12" -dependencies = ["cchardet"] - -[tool.uv] -no-build-isolation-package = ["cchardet"] -``` - -Installing packages without build isolation requires that the package's build dependencies are -installed in the project environment _prior_ to installing the package itself. This can be achieved -by separating out the build dependencies and the packages that require them into distinct extras. -For example: - -```toml title="pyproject.toml" -[project] -name = "project" -version = "0.1.0" -description = "..." -readme = "README.md" -requires-python = ">=3.12" -dependencies = [] - -[project.optional-dependencies] -build = ["setuptools", "cython"] -compile = ["cchardet"] - -[tool.uv] -no-build-isolation-package = ["cchardet"] -``` - -Given the above, a user would first sync the `build` dependencies: - -```console -$ uv sync --extra build - + cython==3.0.11 - + foo==0.1.0 (from file:///Users/crmarsh/workspace/uv/foo) - + setuptools==73.0.1 -``` - -Followed by the `compile` dependencies: - -```console -$ uv sync --extra compile - + cchardet==2.1.7 - - cython==3.0.11 - - setuptools==73.0.1 -``` - -Note that `uv sync --extra compile` would, by default, uninstall the `cython` and `setuptools` -packages. To instead retain the build dependencies, include both extras in the second `uv sync` -invocation: - -```console -$ uv sync --extra build -$ uv sync --extra build --extra compile -``` - -Some packages, like `cchardet` above, only require build dependencies for the _installation_ phase -of `uv sync`. Others, like `flash-attn`, require their build dependencies to be present even just to -resolve the project's lockfile during the _resolution_ phase. - -In such cases, the build dependencies must be installed prior to running any `uv lock` or `uv sync` -commands, using the lower lower-level `uv pip` API. For example, given: - -```toml title="pyproject.toml" -[project] -name = "project" -version = "0.1.0" -description = "..." -readme = "README.md" -requires-python = ">=3.12" -dependencies = ["flash-attn"] - -[tool.uv] -no-build-isolation-package = ["flash-attn"] -``` - -You could run the following sequence of commands to sync `flash-attn`: - -```console -$ uv venv -$ uv pip install torch -$ uv sync -``` - -Alternatively, you can provide the `flash-attn` metadata upfront via the -[`dependency-metadata`](../reference/settings.md#dependency-metadata) setting, thereby forgoing the -need to build the package during the dependency resolution phase. For example, to provide the -`flash-attn` metadata upfront, include the following in your `pyproject.toml`: - -```toml title="pyproject.toml" -[[tool.uv.dependency-metadata]] -name = "flash-attn" -version = "2.6.3" -requires-dist = ["torch", "einops"] -``` - -!!! tip - - To determine the package metadata for a package like `flash-attn`, navigate to the appropriate Git repository, - or look it up on [PyPI](https://pypi.org/project/flash-attn) and download the package's source distribution. - The package requirements can typically be found in the `setup.py` or `setup.cfg` file. - - (If the package includes a built distribution, you can unzip it to find the `METADATA` file; however, the presence - of a built distribution would negate the need to provide the metadata upfront, since it would already be available - to uv.) - -Once included, you can again use the two-step `uv sync` process to install the build dependencies. -Given the following `pyproject.toml`: - -```toml title="pyproject.toml" -[project] -name = "project" -version = "0.1.0" -description = "..." -readme = "README.md" -requires-python = ">=3.12" -dependencies = [] - -[project.optional-dependencies] -build = ["torch", "setuptools", "packaging"] -compile = ["flash-attn"] - -[tool.uv] -no-build-isolation-package = ["flash-attn"] - -[[tool.uv.dependency-metadata]] -name = "flash-attn" -version = "2.6.3" -requires-dist = ["torch", "einops"] -``` - -You could run the following sequence of commands to sync `flash-attn`: - -```console -$ uv sync --extra build -$ uv sync --extra build --extra compile -``` - -!!! note - - The `version` field in `tool.uv.dependency-metadata` is optional for registry-based - dependencies (when omitted, uv will assume the metadata applies to all versions of the package), - but _required_ for direct URL dependencies (like Git dependencies). diff --git a/docs/concepts/projects/build.md b/docs/concepts/projects/build.md new file mode 100644 index 000000000..a073bdae5 --- /dev/null +++ b/docs/concepts/projects/build.md @@ -0,0 +1,51 @@ +# Building distributions + +To distribute your project to others (e.g., to upload it to an index like PyPI), you'll need to +build it into a distributable format. + +Python projects are typically distributed as both source distributions (sdists) and binary +distributions (wheels). The former is typically a `.tar.gz` or `.zip` file containing the project's +source code along with some additional metadata, while the latter is a `.whl` file containing +pre-built artifacts that can be installed directly. + +## Using `uv build` + +`uv build` can be used to build both source distributions and binary distributions for your project. +By default, `uv build` will build the project in the current directory, and place the built +artifacts in a `dist/` subdirectory: + +```console +$ uv build +$ ls dist/ +example-0.1.0-py3-none-any.whl +example-0.1.0.tar.gz +``` + +You can build the project in a different directory by providing a path to `uv build`, e.g., +`uv build path/to/project`. + +`uv build` will first build a source distribution, and then build a binary distribution (wheel) from +that source distribution. + +You can limit `uv build` to building a source distribution with `uv build --sdist`, a binary +distribution with `uv build --wheel`, or build both distributions from source with +`uv build --sdist --wheel`. + +## Build constraints + +`uv build` accepts `--build-constraint`, which can be used to constrain the versions of any build +requirements during the build process. When coupled with `--require-hashes`, uv will enforce that +the requirement used to build the project match specific, known hashes, for reproducibility. + +For example, given the following `constraints.txt`: + +```text +setuptools==68.2.2 --hash=sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a +``` + +Running the following would build the project with the specified version of `setuptools`, and verify +that the downloaded `setuptools` distribution matches the specified hash: + +```console +$ uv build --build-constraint constraints.txt --require-hashes +``` diff --git a/docs/concepts/projects/config.md b/docs/concepts/projects/config.md new file mode 100644 index 000000000..7cea90bfc --- /dev/null +++ b/docs/concepts/projects/config.md @@ -0,0 +1,322 @@ +# Configuring projects + +## Entry points + +uv uses the standard `[project.scripts]` table to define entry points for the project. + +For example, to declare a command called `hello` that invokes the `hello` function in the +`example_package_app` module: + +```toml title="pyproject.toml" +[project.scripts] +hello = "example_package_app:hello" +``` + +!!! important + + Using `[project.scripts]` requires a [build system](#build-systems) to be defined. + +## 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. By default, 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 re-installation. + +## Project packaging + +While uv usually uses the declaration of a [build system](#build-systems) to determine if a project +should be packaged, uv also allows overriding this behavior with 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. + +## Project environment path + +The `UV_PROJECT_ENVIRONMENT` environment variable can be used to configure the project virtual +environment path (`.venv` by default). + +If a relative path is provided, it will be resolved relative to the workspace root. If an absolute +path is provided, it will be used as-is, i.e. a child directory will not be created for the +environment. If an environment is not present at the provided path, uv will create it. + +This option can be used to write to the system Python environment, though it is not recommended. +`uv sync` will remove extraneous packages from the environment by default and, as such, may leave +the system in a broken state. + +!!! important + + If an absolute path is provided and the setting is used across multiple projects, the + environment will be overwritten by invocations in each project. This setting is only recommended + for use for a single project in CI or Docker images. + +!!! note + + uv does not read the `VIRTUAL_ENV` environment variable during project operations. A warning + will be displayed if `VIRTUAL_ENV` is set to a different path than the project's environment. + +## Limited resolution environments + +If your project supports a more limited set of platforms or Python versions, you can constrain the +set of solved platforms via the `environments` setting, which accepts a list of PEP 508 environment +markers. For example, to constrain the lockfile to macOS and Linux, and exclude Windows: + +```toml title="pyproject.toml" +[tool.uv] +environments = [ + "sys_platform == 'darwin'", + "sys_platform == 'linux'", +] +``` + +Entries in the `environments` setting must be disjoint (i.e., they must not overlap). For example, +`sys_platform == 'darwin'` and `sys_platform == 'linux'` are disjoint, but +`sys_platform == 'darwin'` and `python_version >= '3.9'` are not, since both could be true at the +same time. + +## Build isolation + +By default, uv builds all packages in isolated virtual environments, as per +[PEP 517](https://peps.python.org/pep-0517/). Some packages are incompatible with build isolation, +be it intentionally (e.g., due to the use of heavy build dependencies, mostly commonly PyTorch) or +unintentionally (e.g., due to the use of legacy packaging setups). + +To disable build isolation for a specific dependency, add it to the `no-build-isolation-package` +list in your `pyproject.toml`: + +```toml title="pyproject.toml" +[project] +name = "project" +version = "0.1.0" +description = "..." +readme = "README.md" +requires-python = ">=3.12" +dependencies = ["cchardet"] + +[tool.uv] +no-build-isolation-package = ["cchardet"] +``` + +Installing packages without build isolation requires that the package's build dependencies are +installed in the project environment _prior_ to installing the package itself. This can be achieved +by separating out the build dependencies and the packages that require them into distinct extras. +For example: + +```toml title="pyproject.toml" +[project] +name = "project" +version = "0.1.0" +description = "..." +readme = "README.md" +requires-python = ">=3.12" +dependencies = [] + +[project.optional-dependencies] +build = ["setuptools", "cython"] +compile = ["cchardet"] + +[tool.uv] +no-build-isolation-package = ["cchardet"] +``` + +Given the above, a user would first sync the `build` dependencies: + +```console +$ uv sync --extra build + + cython==3.0.11 + + foo==0.1.0 (from file:///Users/crmarsh/workspace/uv/foo) + + setuptools==73.0.1 +``` + +Followed by the `compile` dependencies: + +```console +$ uv sync --extra compile + + cchardet==2.1.7 + - cython==3.0.11 + - setuptools==73.0.1 +``` + +Note that `uv sync --extra compile` would, by default, uninstall the `cython` and `setuptools` +packages. To instead retain the build dependencies, include both extras in the second `uv sync` +invocation: + +```console +$ uv sync --extra build +$ uv sync --extra build --extra compile +``` + +Some packages, like `cchardet` above, only require build dependencies for the _installation_ phase +of `uv sync`. Others, like `flash-attn`, require their build dependencies to be present even just to +resolve the project's lockfile during the _resolution_ phase. + +In such cases, the build dependencies must be installed prior to running any `uv lock` or `uv sync` +commands, using the lower lower-level `uv pip` API. For example, given: + +```toml title="pyproject.toml" +[project] +name = "project" +version = "0.1.0" +description = "..." +readme = "README.md" +requires-python = ">=3.12" +dependencies = ["flash-attn"] + +[tool.uv] +no-build-isolation-package = ["flash-attn"] +``` + +You could run the following sequence of commands to sync `flash-attn`: + +```console +$ uv venv +$ uv pip install torch +$ uv sync +``` + +Alternatively, you can provide the `flash-attn` metadata upfront via the +[`dependency-metadata`](../../reference/settings.md#dependency-metadata) setting, thereby forgoing +the need to build the package during the dependency resolution phase. For example, to provide the +`flash-attn` metadata upfront, include the following in your `pyproject.toml`: + +```toml title="pyproject.toml" +[[tool.uv.dependency-metadata]] +name = "flash-attn" +version = "2.6.3" +requires-dist = ["torch", "einops"] +``` + +!!! tip + + To determine the package metadata for a package like `flash-attn`, navigate to the appropriate Git repository, + or look it up on [PyPI](https://pypi.org/project/flash-attn) and download the package's source distribution. + The package requirements can typically be found in the `setup.py` or `setup.cfg` file. + + (If the package includes a built distribution, you can unzip it to find the `METADATA` file; however, the presence + of a built distribution would negate the need to provide the metadata upfront, since it would already be available + to uv.) + +Once included, you can again use the two-step `uv sync` process to install the build dependencies. +Given the following `pyproject.toml`: + +```toml title="pyproject.toml" +[project] +name = "project" +version = "0.1.0" +description = "..." +readme = "README.md" +requires-python = ">=3.12" +dependencies = [] + +[project.optional-dependencies] +build = ["torch", "setuptools", "packaging"] +compile = ["flash-attn"] + +[tool.uv] +no-build-isolation-package = ["flash-attn"] + +[[tool.uv.dependency-metadata]] +name = "flash-attn" +version = "2.6.3" +requires-dist = ["torch", "einops"] +``` + +You could run the following sequence of commands to sync `flash-attn`: + +```console +$ uv sync --extra build +$ uv sync --extra build --extra compile +``` + +!!! note + + The `version` field in `tool.uv.dependency-metadata` is optional for registry-based + dependencies (when omitted, uv will assume the metadata applies to all versions of the package), + but _required_ for direct URL dependencies (like Git dependencies). + +## Editable mode + +By default, the project will be installed in editable mode, such that changes to the source code are +immediately reflected in the environment. `uv sync` and `uv run` both accept a `--no-editable` flag, +which instructs uv to install the project in non-editable mode. `--no-editable` is intended for +deployment use-cases, such as building a Docker container, in which the project should be included +in the deployed environment without a dependency on the originating source code. + +### Conflicting dependencies + +uv requires that all optional dependencies ("extras") declared by the project are compatible with +each other and resolves all optional dependencies together when creating the lockfile. + +If optional dependencies declared in one extra are not compatible with those in another extra, uv +will fail to resolve the requirements of the project with an error. + +To work around this, uv supports declaring conflicting extras. For example, consider two sets of +optional dependencies that conflict with one another: + +```toml title="pyproject.toml" +[project.optional-dependencies] +extra1 = ["numpy==2.1.2"] +extra2 = ["numpy==2.0.0"] +``` + +If you run `uv lock` with the above dependencies, resolution will fail: + +```console +$ uv lock + x No solution found when resolving dependencies: + `-> Because myproject[extra2] depends on numpy==2.0.0 and myproject[extra1] depends on numpy==2.1.2, we can conclude that myproject[extra1] and + myproject[extra2] are incompatible. + And because your project requires myproject[extra1] and myproject[extra2], we can conclude that your projects's requirements are unsatisfiable. +``` + +But if you specify that `extra1` and `extra2` are conflicting, uv will resolve them separately. +Specify conflicts in the `tool.uv` section: + +```toml title="pyproject.toml" +[tool.uv] +conflicts = [ + [ + { extra = "extra1" }, + { extra = "extra2" }, + ], +] +``` + +Now, running `uv lock` will succeed. Note though, that now you cannot install both `extra1` and +`extra2` at the same time: + +```console +$ uv sync --extra extra1 --extra extra2 +Resolved 3 packages in 14ms +error: extra `extra1`, extra `extra2` are incompatible with the declared conflicts: {`myproject[extra1]`, `myproject[extra2]`} +``` + +This error occurs because installing both `extra1` and `extra2` would result in installing two +different versions of a package into the same environment. + +The above strategy for dealing with conflicting extras also works with dependency groups: + +```toml title="pyproject.toml" +[dependency-groups] +group1 = ["numpy==2.1.2"] +group2 = ["numpy==2.0.0"] + +[tool.uv] +conflicts = [ + [ + { group = "group1" }, + { group = "group2" }, + ], +] +``` + +The only difference with conflicting extras is that you need to use `group` instead of `extra`. diff --git a/docs/concepts/dependencies.md b/docs/concepts/projects/dependencies.md similarity index 84% rename from docs/concepts/dependencies.md rename to docs/concepts/projects/dependencies.md index 278ad5f0d..750b72695 100644 --- a/docs/concepts/dependencies.md +++ b/docs/concepts/projects/dependencies.md @@ -1,4 +1,104 @@ -# Specifying dependencies +# Managing dependencies + +uv is capable of adding, updating, and removing dependencies using the CLI. + +## Adding dependencies + +To add a dependency: + +```console +$ uv add httpx +``` + +uv supports adding [editable dependencies](./dependencies.md#editable-dependencies), +[development dependencies](./dependencies.md#development-dependencies), +[optional dependencies](./dependencies.md#optional-dependencies), and alternative +[dependency sources](./dependencies.md#dependency-sources). See the +[dependency specification](./dependencies.md) documentation for more details. + +uv will raise an error if the dependency cannot be resolved, e.g.: + +```console +$ uv add 'httpx>9999' +error: Because only httpx<=9999 is available and example==0.1.0 depends on httpx>9999, we can conclude that example==0.1.0 cannot be used. +And because only example==0.1.0 is available and you require example, we can conclude that the requirements are unsatisfiable. +``` + +## Removing dependencies + +To remove a dependency: + +```console +$ uv remove httpx +``` + +## Updating dependencies + +To update an existing dependency, e.g., to add a lower bound to the `httpx` version: + +```console +$ uv add 'httpx>0.1.0' +``` + +!!! note + + "Updating" a dependency refers to changing the constraints for the dependency in the + `pyproject.toml`. The locked version of the dependency will only change if necessary to + satisfy the new constraints. To force the package version to update to the latest within + the constraints, use `--upgrade-package `, e.g.: + + ```console + $ uv add 'httpx>0.1.0' --upgrade-package httpx + ``` + + See the [lockfile](./sync.md#upgrading-locked-package-versions) section for more details on upgrading + package versions. + +Or, to change the bounds for `httpx`: + +```console +$ uv add 'httpx<0.2.0' +``` + +To add a dependency source, e.g., to use `httpx` from GitHub during development: + +```console +$ uv add git+https://github.com/encode/httpx +``` + +## Platform-specific dependencies + +To ensure that a dependency is only installed on a specific platform or on specific Python versions, +use Python's standardized +[environment markers](https://peps.python.org/pep-0508/#environment-markers) syntax. + +For example, to install `jax` on Linux, but not on Windows or macOS: + +```console +$ uv add 'jax; sys_platform == "linux"' +``` + +The resulting `pyproject.toml` will then include the environment marker in the dependency +definition: + +```toml title="pyproject.toml" hl_lines="6" +[project] +name = "project" +version = "0.1.0" +requires-python = ">=3.11" +dependencies = ["jax; sys_platform == 'linux'"] +``` + +Similarly, to include `numpy` on Python 3.11 and later: + +```console +$ uv add 'numpy; python_version >= "3.11"' +``` + +See Python's [environment marker](https://peps.python.org/pep-0508/#environment-markers) +documentation for a complete enumeration of the available markers and operators. + +## Dependency tables In uv, project dependencies are declared across two `pyproject.toml` tables: `project.dependencies` and `tool.uv.sources`. @@ -61,11 +161,6 @@ sufficient. If the project depends on packages from Git, remote URLs, or local s `tool.uv.sources` can be used to enrich the dependency metadata without ejecting from the standards-compliant `project.dependencies` table. -!!! tip - - See the [projects](./projects.md#managing-dependencies) documentation to add, remove, or update - dependencies from the `pyproject.toml` from the CLI. - ## Dependency sources During development, a project may rely on a package that isn't available on PyPI. The following @@ -190,7 +285,7 @@ A `subdirectory` may be specified if the package isn't in the repository root. To add a URL source, provide a `https://` URL to either a wheel (ending in `.whl`) or a source distribution (typically ending in `.tar.gz` or `.zip`; see -[here](../concepts/resolution.md#source-distribution) for all supported formats). +[here](../../concepts/resolution.md#source-distribution) for all supported formats). For example: @@ -217,8 +312,9 @@ archive root. ### Path To add a path source, provide the path of a wheel (ending in `.whl`), a source distribution -(typically ending in `.tar.gz` or `.zip`; see [here](../concepts/resolution.md#source-distribution) -for all supported formats), or a directory containing a `pyproject.toml`. +(typically ending in `.tar.gz` or `.zip`; see +[here](../../concepts/resolution.md#source-distribution) for all supported formats), or a directory +containing a `pyproject.toml`. For example: @@ -391,7 +487,7 @@ $ uv add httpx --optional network !!! note If you have optional dependencies that conflict with one another, resolution will fail - unless you explicitly [declare them as conflicting](./projects.md#optional-dependencies). + unless you explicitly [declare them as conflicting](./config.md#conflicting-dependencies). Sources can also be declared as applying only to a specific optional dependency. For example, to pull `torch` from different PyTorch indexes based on an optional `cpu` or `gpu` extra: @@ -490,7 +586,7 @@ to resolve the requirements of the project with an error. !!! note If you have dependency groups that conflict with one another, resolution will fail - unless you explicitly [declare them as conflicting](./projects.md#optional-dependencies). + unless you explicitly [declare them as conflicting](./config.md#conflicting-dependencies). ### Default groups @@ -528,7 +624,7 @@ Dependencies declared in this section will be combined with the contents in the ## Build dependencies -If a project is structured as [Python package](./projects.md#build-systems), it may declare +If a project is structured as [Python package](./config.md#build-systems), it may declare dependencies that are required to build the project, but not required to run it. These dependencies are specified in the `[build-system]` table under `build-system.requires`, following [PEP 518](https://peps.python.org/pep-0518/). diff --git a/docs/concepts/projects/index.md b/docs/concepts/projects/index.md new file mode 100644 index 000000000..6caa93bcc --- /dev/null +++ b/docs/concepts/projects/index.md @@ -0,0 +1,18 @@ +# Projects + +Projects help manage Python code spanning multiple files. + +!!! tip + + Looking for an introduction to creating a project with uv? See the [projects guide](../../guides/projects.md) first. + +Working on projects is a core part of the uv experience. Learn more about using projects: + +- [Understanding project structure and files](./layout.md) +- [Creating new projects](./init.md) +- [Managing project dependencies](./dependencies.md) +- [Running commands and scripts in a project](./run.md) +- [Using lockfiles and syncing the environment](./sync.md) +- [Configuring the project for advanced use cases](./config.md) +- [Building distributions to publish a project](./build.md) +- [Using workspaces to work on multiple projects at once](./workspaces.md) diff --git a/docs/concepts/projects/init.md b/docs/concepts/projects/init.md new file mode 100644 index 000000000..0aea1cc1d --- /dev/null +++ b/docs/concepts/projects/init.md @@ -0,0 +1,240 @@ +# 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**](#applications) and +[**libraries**](#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: + +```console +$ 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. + +```toml title="pyproject.toml" +[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: + +```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 + +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: + +```console +$ 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. + +```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 = [] + +[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: + +```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 --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`. + +```console +$ 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`: + +```console +$ 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: + +```console +$ 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: + +```python title="__init__.py" +def main() -> None: + print("Hello from example-packaged-app!") +``` + +And the `pyproject.toml` includes a script entrypoint: + +```toml 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] +example-packaged-app = "example_packaged_app:main" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" +``` + +Which can be executed with `uv run`: + +```console +$ 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`. + +```console +$ 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`: + +```console +$ uv run --directory example-packaged-app example-packaged-app +Hello from example-packaged-app! +``` diff --git a/docs/concepts/projects/layout.md b/docs/concepts/projects/layout.md new file mode 100644 index 000000000..c2134d462 --- /dev/null +++ b/docs/concepts/projects/layout.md @@ -0,0 +1,95 @@ +# Project structure and files + +## The `pyproject.toml` + +Python project metadata is defined in a `pyproject.toml` file. uv requires this file to identify the +root directory of a project. + +!!! tip + + `uv init` can be used to create a new project. See [Creating projects](./init.md) for + details. + +A minimal project definition includes a name, version, and description: + +```toml title="pyproject.toml" +[project] +name = "example" +version = "0.1.0" +description = "Add your description here" +``` + +It's recommended, but not required, to include a Python version requirement in the `[project]` +section: + +```toml title="pyproject.toml" +requires-python = ">=3.12" +``` + +Including a Python version requirement defines the Python syntax that is allowed in the project and +affects selection of dependency versions (they must support the same Python version range). + +The `pyproject.toml` also lists dependencies of the project in the `project.dependencies` and +`project.optional-dependencies` fields. uv supports modifying the project's dependencies from the +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 + + 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`. + +## The project environment + +When working on a project with uv, uv will create a virtual environment as needed. While some uv +commands will create a temporary environment (e.g., `uv run --isolated`), uv also manages a +persistent environment with the project and its dependencies in a `.venv` directory next to the +`pyproject.toml`. It is stored inside the project to make it easy for editors to find — they need +the environment to give code completions and type hints. It is not recommended to include the +`.venv` directory in version control; it is automatically excluded from `git` with an internal +`.gitignore` file. + +To run a command in the project environment, use `uv run`. Alternatively the project environment can +be activated as normal for a virtual environment. + +When `uv run` is invoked, it will create the project environment if it does not exist yet or ensure +it is up-to-date if it exists. The project environment can also be explicitly created with +`uv sync`. + +It is _not_ recommended to modify the project environment manually, e.g., with `uv pip install`. For +project dependencies, use `uv add` to add a package to the environment. For one-off requirements, +use [`uvx`](../../guides/tools.md) or +[`uv run --with`](./run.md#requesting-additional-dependencies). + +!!! tip + + If you don't want uv to manage the project environment, set [`managed = false`](../../reference/settings.md#managed) + to disable automatic locking and syncing of the project. For example: + + ```toml title="pyproject.toml" + [tool.uv] + managed = false + ``` + +## The lockfile + +uv creates a `uv.lock` file next to the `pyproject.toml`. + +`uv.lock` is a _universal_ or _cross-platform_ lockfile that captures the packages that would be +installed across all possible Python markers such as operating system, architecture, and Python +version. + +Unlike the `pyproject.toml`, which is used to specify the broad requirements of your project, the +lockfile contains the exact resolved versions that are installed in the project environment. This +file should be checked into version control, allowing for consistent and reproducible installations +across machines. + +A lockfile ensures that developers working on the project are using a consistent set of package +versions. Additionally, it ensures when deploying the project as an application that the exact set +of used package versions is known. + +The lockfile is created and updated during uv invocations that use the project environment, i.e., +`uv sync` and `uv run`. The lockfile may also be explicitly updated using `uv lock`. + +`uv.lock` is a human-readable TOML file but is managed by uv and should not be edited manually. +There is no Python standard for lockfiles at this time, so the format of this file is specific to uv +and not usable by other tools. diff --git a/docs/concepts/projects/run.md b/docs/concepts/projects/run.md new file mode 100644 index 000000000..7da4b4a79 --- /dev/null +++ b/docs/concepts/projects/run.md @@ -0,0 +1,65 @@ +# Running commands in projects + +When working on a project, it is installed into virtual environment at `.venv`. This environment is +isolated from the current shell by default, so invocations that require the project, e.g., +`python -c "import example"`, will fail. Instead, use `uv run` to run commands in the project +environment: + +```console +$ uv run python -c "import example" +``` + +When using `run`, uv will ensure that the project environment is up-to-date before running the given +command. + +The given command can be provided by the project environment or exist outside of it, e.g.: + +```console +$ # Presuming the project provides `example-cli` +$ uv run example-cli foo + +$ # Running a `bash` script that requires the project to be available +$ uv run bash scripts/foo.sh +``` + +## Requesting additional dependencies + +Additional dependencies or different versions of dependencies can be requested per invocation. + +The `--with` option is used to include a dependency for the invocation, e.g., to request a different +version of `httpx`: + +```console +$ uv run --with httpx==0.26.0 python -c "import httpx; print(httpx.__version__)" +0.26.0 +$ uv run --with httpx==0.25.0 python -c "import httpx; print(httpx.__version__)" +0.25.0 +``` + +The requested version will be respected regardless of the project's requirements. For example, even +if the project requires `httpx==0.24.0`, the output above would be the same. + +## Running scripts + +Scripts that declare inline metadata are automatically executed in environments isolated from the +project. See the [scripts guide](../../guides/scripts.md#declaring-script-dependencies) for more +details. + +For example, given a script: + +```python title="example.py" +# /// script +# dependencies = [ +# "httpx", +# ] +# /// + +import httpx + +resp = httpx.get("https://peps.python.org/api/peps.json") +data = resp.json() +print([(k, v["title"]) for k, v in data.items()][:10]) +``` + +The invocation `uv run example.py` would run _isolated_ from the project with only the given +dependencies listed. diff --git a/docs/concepts/projects/sync.md b/docs/concepts/projects/sync.md new file mode 100644 index 000000000..469123def --- /dev/null +++ b/docs/concepts/projects/sync.md @@ -0,0 +1,58 @@ +# Locking and syncing + +### Creating the lockfile + +The lockfile is created and updated during uv invocations that use the project environment, i.e., +`uv sync` and `uv run`. The lockfile may also be explicitly created or updated using `uv lock`: + +```console +$ uv lock +``` + +### Exporting the lockfile + +If you need to integrate uv with other tools or workflows, you can export `uv.lock` to +`requirements.txt` format with `uv export --format requirements-txt`. The generated +`requirements.txt` file can then be installed via `uv pip install`, or with other tools like `pip`. + +In general, we recommend against using both a `uv.lock` and a `requirements.txt` file. If you find +yourself exporting a `uv.lock` file, consider opening an issue to discuss your use case. + +### Checking if the lockfile is up-to-date + +To avoid updating the lockfile during `uv sync` and `uv run` invocations, use the `--frozen` flag. + +To avoid updating the environment during `uv run` invocations, use the `--no-sync` flag. + +To assert the lockfile matches the project metadata, use the `--locked` flag. If the lockfile is not +up-to-date, an error will be raised instead of updating the lockfile. + +### Upgrading locked package versions + +By default, uv will prefer the locked versions of packages when running `uv sync` and `uv lock`. +Package versions will only change if the project's dependency constraints exclude the previous, +locked version. + +To upgrade all packages: + +```console +$ uv lock --upgrade +``` + +To upgrade a single package to the latest version, while retaining the locked versions of all other +packages: + +```console +$ uv lock --upgrade-package +``` + +To upgrade a single package to a specific version: + +```console +$ uv lock --upgrade-package == +``` + +!!! note + + In all cases, upgrades are limited to the project's dependency constraints. For example, if the + project defines an upper bound for a package then an upgrade will not go beyond that version. diff --git a/docs/concepts/workspaces.md b/docs/concepts/projects/workspaces.md similarity index 98% rename from docs/concepts/workspaces.md rename to docs/concepts/projects/workspaces.md index 5731b5dcb..bf71f3610 100644 --- a/docs/concepts/workspaces.md +++ b/docs/concepts/projects/workspaces.md @@ -1,4 +1,4 @@ -# Workspaces +# Using workspaces Inspired by the [Cargo](https://doc.rust-lang.org/cargo/reference/workspaces.html) concept of the same name, a workspace is "a collection of one or more packages, called _workspace members_, that @@ -49,8 +49,8 @@ build-backend = "hatchling.build" Every directory included by the `members` globs (and not excluded by the `exclude` globs) must contain a `pyproject.toml` file. However, workspace members can be _either_ -[applications](./projects.md#applications) or [libraries](./projects.md#libraries); both are -supported in the workspace context. +[applications](./init.md#applications) or [libraries](./init.md#libraries); both are supported in +the workspace context. Every workspace needs a root, which is _also_ a workspace member. In the above example, `albatross` is the workspace root, and the workspace members include all projects under the `packages` diff --git a/docs/concepts/resolution.md b/docs/concepts/resolution.md index 89c6ea1f9..f4fad1648 100644 --- a/docs/concepts/resolution.md +++ b/docs/concepts/resolution.md @@ -86,7 +86,7 @@ uv supports both [platform-specific](#platform-specific-resolution) and uv's lockfile (`uv.lock`) is created with a universal resolution and is portable across platforms. This ensures that dependencies are locked for everyone working on the project, regardless of operating system, architecture, and Python version. The uv lockfile is created and modified by -[project](../concepts/projects.md) commands such as `uv lock`, `uv sync`, and `uv add`. +[project](../concepts/projects/index.md) commands such as `uv lock`, `uv sync`, and `uv add`. universal resolution is also available in uv's pip interface, i.e., [`uv pip compile`](../pip/compile.md), with the `--universal` flag. The resulting requirements file diff --git a/docs/configuration/environment.md b/docs/configuration/environment.md index 3d3f96d5f..c82cb9d6f 100644 --- a/docs/configuration/environment.md +++ b/docs/configuration/environment.md @@ -214,7 +214,7 @@ Equivalent to the `--preview` argument. Enables preview mode. ### `UV_PROJECT_ENVIRONMENT` Specifies the path to the directory to use for a project virtual environment. -See the [project documentation](../concepts/projects.md#configuring-the-project-environment-path) +See the [project documentation](../concepts/projects/config.md#project-environment-path) for more details. ### `UV_PUBLISH_CHECK_URL` diff --git a/docs/guides/integration/dependency-bots.md b/docs/guides/integration/dependency-bots.md index 3450e761a..63cff7910 100644 --- a/docs/guides/integration/dependency-bots.md +++ b/docs/guides/integration/dependency-bots.md @@ -19,10 +19,10 @@ uv is supported by [Renovate](https://github.com/renovatebot/renovate). Renovate uses the presence of a `uv.lock` file to determine that uv is used for managing dependencies, and will suggest upgrades to -[project dependencies](../../concepts/dependencies.md#project-dependencies), -[optional dependencies](../../concepts/dependencies.md#optional-dependencies) and -[development dependencies](../../concepts/dependencies.md#development-dependencies). Renovate will -update both the `pyproject.toml` and `uv.lock` files. +[project dependencies](../../concepts/projects/dependencies.md#project-dependencies), +[optional dependencies](../../concepts/projects/dependencies.md#optional-dependencies) and +[development dependencies](../../concepts/projects/dependencies.md#development-dependencies). +Renovate will update both the `pyproject.toml` and `uv.lock` files. The lockfile can also be refreshed on a regular basis (for instance to update transitive dependencies) by enabling the diff --git a/docs/guides/integration/docker.md b/docs/guides/integration/docker.md index 484a061b3..709362ec0 100644 --- a/docs/guides/integration/docker.md +++ b/docs/guides/integration/docker.md @@ -161,7 +161,7 @@ RUN uv run some_script.py !!! tip Alternatively, the - [`UV_PROJECT_ENVIRONMENT` setting](../../concepts/projects.md#configuring-the-project-environment-path) can + [`UV_PROJECT_ENVIRONMENT` setting](../../concepts/projects/config.md#project-environment-path) can be set before syncing to install to the system Python environment and skip environment activation entirely. @@ -366,7 +366,7 @@ _contents_ are not copied into the image until the final `uv sync` command. !!! tip - If you're using a [workspace](../../concepts/workspaces.md), then use the + If you're using a [workspace](../../concepts/projects/workspaces.md), then use the `--no-install-workspace` flag which excludes the project _and_ any workspace members. If you want to remove specific packages from the sync, use `--no-install-package `. diff --git a/docs/guides/integration/fastapi.md b/docs/guides/integration/fastapi.md index 23fe5f7ca..654b2ed14 100644 --- a/docs/guides/integration/fastapi.md +++ b/docs/guides/integration/fastapi.md @@ -35,8 +35,8 @@ To use uv with this application, inside the `project` directory run: $ uv init --app ``` -This creates an [Application project](../../concepts/projects.md#applications) with a -`pyproject.toml` file. +This creates an [project with an application layout](../../concepts/projects/init.md#applications) +and a `pyproject.toml` file. Then, add a dependency on FastAPI: diff --git a/docs/guides/integration/github.md b/docs/guides/integration/github.md index 76da2a7a1..9913bd893 100644 --- a/docs/guides/integration/github.md +++ b/docs/guides/integration/github.md @@ -181,7 +181,7 @@ jobs: !!! tip The - [`UV_PROJECT_ENVIRONMENT` setting](../../concepts/projects.md#configuring-the-project-environment-path) can + [`UV_PROJECT_ENVIRONMENT` setting](../../concepts/projects/config.md#project-environment-path) can be used to install to the system Python environment instead of creating a virtual environment. ## Caching diff --git a/docs/guides/integration/jupyter.md b/docs/guides/integration/jupyter.md index dbb5b267f..358a090d4 100644 --- a/docs/guides/integration/jupyter.md +++ b/docs/guides/integration/jupyter.md @@ -6,8 +6,8 @@ with a project, or as a standalone tool. ## Using Jupyter within a project -If you're working within a [project](../../concepts/projects.md), you can start a Jupyter server -with access to the project's virtual environment via the following: +If you're working within a [project](../../concepts/projects/index.md), you can start a Jupyter +server with access to the project's virtual environment via the following: ```console $ uv run --with jupyter jupyter lab @@ -96,8 +96,8 @@ an isolated environment. ## Using Jupyter with a non-project environment If you need to run Jupyter in a virtual environment that isn't associated with a -[project](../../concepts/projects.md) (e.g., has no `pyproject.toml` or `uv.lock`), you can do so by -adding Jupyter to the environment directly. For example: +[project](../../concepts/projects/index.md) (e.g., has no `pyproject.toml` or `uv.lock`), you can do +so by adding Jupyter to the environment directly. For example: ```console $ uv venv --seed diff --git a/docs/guides/projects.md b/docs/guides/projects.md index 3cb75509d..867a25238 100644 --- a/docs/guides/projects.md +++ b/docs/guides/projects.md @@ -93,8 +93,8 @@ Python version to use when creating the project's virtual environment. The `.venv` folder contains your project's virtual environment, a Python environment that is isolated from the rest of your system. This is where uv will install your project's dependencies. -See the [project environment](../concepts/projects.md#project-environments) documentation for more -details. +See the [project environment](../concepts/projects/layout.md#the-project-environment) documentation +for more details. ### `uv.lock` @@ -106,7 +106,7 @@ reproducible installations across machines. `uv.lock` is a human-readable TOML file but is managed by uv and should not be edited manually. -See the [lockfile](../concepts/projects.md#project-lockfile) documentation for more details. +See the [lockfile](../concepts/projects/layout.md#the-lockfile) documentation for more details. ## Managing dependencies @@ -142,8 +142,8 @@ $ uv lock --upgrade-package requests The `--upgrade-package` flag will attempt to update the specified package to the latest compatible version, while keeping the rest of the lockfile intact. -See the documentation on [managing dependencies](../concepts/projects.md#managing-dependencies) for -more details. +See the documentation on [managing dependencies](../concepts/projects/dependencies.md) for more +details. ## Running commands @@ -188,8 +188,8 @@ $ python example.py The virtual environment must be active to run scripts and commands in the project without `uv run`. Virtual environment activation differs per shell and platform. -See the documentation on [running commands](../concepts/projects.md#running-commands) and -[running scripts](../concepts/projects.md#running-scripts) in projects for more details. +See the documentation on [running commands and scripts](../concepts/projects/run.md) in projects for +more details. ## Building distributions @@ -206,12 +206,12 @@ hello-world-0.1.0-py3-none-any.whl hello-world-0.1.0.tar.gz ``` -See the documentation on [building projects](../concepts/projects.md#building-projects) for more -details. +See the documentation on [building projects](../concepts/projects/build.md) for more details. ## Next steps -To learn more about working on projects with uv, see the [Projects concept](../concepts/projects.md) -page and the [command reference](../reference/cli.md#uv). +To learn more about working on projects with uv, see the +[projects concept](../concepts/projects/index.md) page and the +[command reference](../reference/cli.md#uv). Or, read on to learn how to [publish your project as a package](./publish.md). diff --git a/docs/guides/publish.md b/docs/guides/publish.md index 042631e31..8d8888f1a 100644 --- a/docs/guides/publish.md +++ b/docs/guides/publish.md @@ -11,7 +11,7 @@ distribution. 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 the effect of declaring a build system in the -[project concept](../concepts/projects.md#build-systems) documentation. +[project concept](../concepts/projects/config.md#build-systems) documentation. !!! note diff --git a/docs/guides/scripts.md b/docs/guides/scripts.md index 50875008d..1b3379860 100644 --- a/docs/guides/scripts.md +++ b/docs/guides/scripts.md @@ -187,7 +187,7 @@ $ uv run example.py !!! important - When using inline script metadata, even if `uv run` is [used in a _project_](../concepts/projects.md#running-scripts), the project's dependencies will be ignored. The `--no-project` flag is not required. + When using inline script metadata, even if `uv run` is [used in a _project_](../concepts/projects/run.md), the project's dependencies will be ignored. The `--no-project` flag is not required. uv also respects Python version requirements: diff --git a/docs/guides/tools.md b/docs/guides/tools.md index f6022940c..8300d1d5d 100644 --- a/docs/guides/tools.md +++ b/docs/guides/tools.md @@ -43,7 +43,7 @@ Tools are installed into temporary, isolated environments when using `uvx`. !!! note - If you are running a tool in a [_project_](../concepts/projects.md) and the tool requires that + If you are running a tool in a [_project_](../concepts/projects/index.md) and the tool requires that your project is installed, e.g., when using `pytest` or `mypy`, you'll want to use [`uv run`](./projects.md#running-commands) instead of `uvx`. Otherwise, the tool will be run in a virtual environment that is isolated from your project. diff --git a/docs/index.md b/docs/index.md index 7f4e34035..acb04a59d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -24,10 +24,10 @@ An extremely fast Python package and project manager, written in Rust. - ❇️ [Runs scripts](#script-support), with support for [inline dependency metadata](./guides/scripts.md#declaring-script-dependencies). - 🗂️ Provides [comprehensive project management](#project-management), with a - [universal lockfile](./concepts/projects.md#project-lockfile). + [universal lockfile](./concepts/projects/layout.md#the-lockfile). - 🔩 Includes a [pip-compatible interface](#the-pip-interface) for a performance boost with a familiar CLI. -- 🏢 Supports Cargo-style [workspaces](./concepts/workspaces.md) for scalable projects. +- 🏢 Supports Cargo-style [workspaces](./concepts/projects/workspaces.md) for scalable projects. - 💾 Disk-space efficient, with a [global cache](./concepts/cache.md) for dependency deduplication. - ⏬ Installable without Rust or Python via `curl` or `pip`. - 🖥️ Supports macOS, Linux, and Windows. diff --git a/docs/reference/settings.md b/docs/reference/settings.md index 02d3aecbc..ef7a63ef5 100644 --- a/docs/reference/settings.md +++ b/docs/reference/settings.md @@ -281,7 +281,7 @@ The sources to use when resolving dependencies. during development. A dependency source can be a Git repository, a URL, a local path, or an alternative registry. -See [Dependencies](../concepts/dependencies.md) for more. +See [Dependencies](../concepts/projects/dependencies.md) for more. **Default value**: `{}` diff --git a/docs/requirements-insiders.txt b/docs/requirements-insiders.txt index a933ee0e7..08ba54251 100644 --- a/docs/requirements-insiders.txt +++ b/docs/requirements-insiders.txt @@ -79,7 +79,7 @@ mkdocs-material @ git+ssh://git@github.com/astral-sh/mkdocs-material-insiders.gi # -r docs/requirements.in mkdocs-material-extensions==1.3.1 # via mkdocs-material -mkdocs-redirects==1.2.1 +mkdocs-redirects==1.2.2 # via -r docs/requirements.in more-itertools==10.3.0 # via mdformat-mkdocs diff --git a/docs/requirements.in b/docs/requirements.in index 9aea93dcf..79fa08bd7 100644 --- a/docs/requirements.in +++ b/docs/requirements.in @@ -5,3 +5,4 @@ mkdocs-redirects>=1.2.1 mdformat>=0.7.17 mdformat-mkdocs>=2.0.4 mdformat-admon>=2.0.2 +mkdocs-redirects>=1.2.2 diff --git a/docs/requirements.txt b/docs/requirements.txt index 8b7a8cee9..db4298467 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -80,7 +80,7 @@ mkdocs-material==9.5.29 # via -r docs/requirements.in mkdocs-material-extensions==1.3.1 # via mkdocs-material -mkdocs-redirects==1.2.1 +mkdocs-redirects==1.2.2 # via -r docs/requirements.in more-itertools==10.3.0 # via mdformat-mkdocs diff --git a/mkdocs.template.yml b/mkdocs.template.yml index 446cf1cd6..31b813e15 100644 --- a/mkdocs.template.yml +++ b/mkdocs.template.yml @@ -61,6 +61,10 @@ markdown_extensions: alternate_style: true plugins: - search + - redirects: + redirect_maps: + "concepts/workspaces.md": "concepts/projects/workspaces.md" + "concepts/dependencies.md": "concepts/projects/dependencies.md" extra_css: - stylesheets/extra.css extra_javascript: @@ -94,9 +98,16 @@ nav: - Publishing packages: guides/publish.md - Concepts: - concepts/index.md - - Projects: concepts/projects.md - - Dependencies: concepts/dependencies.md - - Workspaces: concepts/workspaces.md + - Projects: + - concepts/projects/index.md + - Structure and files: concepts/projects/layout.md + - Creating projects: concepts/projects/init.md + - Managing dependencies: concepts/projects/dependencies.md + - Running commands: concepts/projects/run.md + - Locking and syncing: concepts/projects/sync.md + - Configuring projects: concepts/projects/config.md + - Building distributions: concepts/projects/build.md + - Using workspaces: concepts/projects/workspaces.md - Tools: concepts/tools.md - Python versions: concepts/python-versions.md - Resolution: concepts/resolution.md diff --git a/uv.schema.json b/uv.schema.json index 8c5177fb5..9995ea244 100644 --- a/uv.schema.json +++ b/uv.schema.json @@ -433,7 +433,7 @@ ] }, "sources": { - "description": "The sources to use when resolving dependencies.\n\n`tool.uv.sources` enriches the dependency metadata with additional sources, incorporated during development. A dependency source can be a Git repository, a URL, a local path, or an alternative registry.\n\nSee [Dependencies](https://docs.astral.sh/uv/concepts/dependencies/) for more.", + "description": "The sources to use when resolving dependencies.\n\n`tool.uv.sources` enriches the dependency metadata with additional sources, incorporated during development. A dependency source can be a Git repository, a URL, a local path, or an alternative registry.\n\nSee [Dependencies](https://docs.astral.sh/uv/concepts/projects/dependencies/) for more.", "anyOf": [ { "$ref": "#/definitions/ToolUvSources"