pypa-hatch/docs/config/dependency.md

277 lines
11 KiB
Markdown

# Dependency configuration
-----
[Project dependencies](metadata.md#dependencies) are defined with [PEP 508][] strings using optional [PEP 440 version specifiers][].
## Version specifiers
A version specifier consists of a series of version clauses, separated by commas. For example:
```toml tab="pyproject.toml"
[project]
...
dependencies = [
"cryptography",
"click>=7, <9, != 8.0.0",
"python-dateutil==2.8.*",
"numpy~=1.21.4",
]
```
The comma is equivalent to a logical `AND` operator: a candidate version must match all given version clauses in order to match the specifier as a whole.
### Operators
| Operators | Function |
| :---: | --- |
| `~=` | [Compatible release](#compatible-release) |
| `==` | [Version matching](#version-matching) |
| `!=` | [Version exclusion](#version-exclusion) |
| `<=`, `>=` | [Inclusive ordered comparison](#ordered-comparison) |
| `<`, `>` | [Exclusive ordered comparison](#ordered-comparison) |
| `===` | [Arbitrary equality](#arbitrary-equality) |
### Version matching
A version matching clause includes the version matching operator `==` and a version identifier.
By default, the version matching operator is based on a strict equality comparison: the specified version must be exactly the same as the requested version.
| Clause | Allowed versions |
| --- | --- |
| `==1` | `1.0.0` |
| `==1.2` | `1.2.0` |
Prefix matching may be requested instead of strict comparison, by appending a trailing `.*` to the version identifier in the version matching clause. This means that additional trailing segments will be ignored when determining whether or not a version identifier matches the clause.
| Clause | Allowed versions |
| --- | --- |
| `==1.*` | `>=1.0.0, <2.0.0` |
| `==1.2.*` | `>=1.2.0, <1.3.0` |
### Compatible release
A compatible release clause consists of the compatible release operator `~=` and a version identifier. It matches any candidate version that is expected to be compatible with the specified version.
For a given release identifier `V.N`, the compatible release clause is approximately equivalent to the following pair of comparison clauses:
```
>= V.N, == V.*
```
This operator cannot be used with a single segment version number such as `~=1`.
| Clause | Allowed versions |
| --- | --- |
| `~=1.2` | `>=1.2.0, <2.0.0` |
| `~=1.2.3` | `>=1.2.3, <1.3.0` |
### Version exclusion
A version exclusion clause includes the version exclusion operator `!=` and a version identifier.
The allowed version identifiers and comparison semantics are the same as those of the [Version matching](#version-matching) operator, except that the sense of any match is inverted.
### Ordered comparison
Inclusive comparisons allow for the version identifier part of clauses whereas exclusive comparisons do not. For example, `>=1.2` allows for version `1.2.0` while `>1.2` does not.
Unlike the inclusive ordered comparisons `<=` and `>=`, the exclusive ordered comparisons `<` and `>` specifically exclude pre-releases, post-releases, and local versions of the specified version.
### Arbitrary equality
Though heavily discouraged, arbitrary equality comparisons allow for simple string matching without any version semantics, for example `===foobar`.
## Environment markers
[Environment markers](https://peps.python.org/pep-0508/#environment-markers) allow for dependencies to only be installed when certain conditions are met.
For example, if you need to install the latest version of `cryptography` that is available for a given Python major version you could define the following:
```
cryptography==3.3.2; python_version < "3"
cryptography>=35.0; python_version > "3"
```
Alternatively, if you only need it on Python 3 when running on Windows you could do:
```
cryptography; python_version ~= "3.0" and platform_system == "Windows"
```
The available environment markers are as follows.
| Marker | Python equivalent | Examples |
| --- | --- | --- |
| `os_name` | `#!python import os`<br>`os.name` | <ul><li>posix</li><li>java</li></ul> |
| `sys_platform` | `#!python import sys`<br>`sys.platform` | <ul><li>linux</li><li>win32</li><li>darwin</li></ul> |
| `platform_machine` | `#!python import platform`<br>`platform.machine()` | <ul><li>x86_64</li></ul> |
| `platform_python_implementation` | `#!python import platform`<br>`platform.python_implementation()` | <ul><li>CPython</li><li>Jython</li></ul> |
| `platform_release` | `#!python import platform`<br>`platform.release()` | <ul><li>1.8.0_51</li><li>3.14.1-x86_64-linode39</li></ul> |
| `platform_system` | `#!python import platform`<br>`platform.system()` | <ul><li>Linux</li><li>Windows</li><li>Darwin</li></ul> |
| `platform_version` | `#!python import platform`<br>`platform.version()` | <ul><li>10.0.19041</li><li>\#1 SMP Fri Apr 2 22:23:49 UTC 2021</li></ul> |
| `python_version` | `#!python import platform`<br>`'.'.join(platform.python_version_tuple()[:2])` | <ul><li>2.7</li><li>3.10</li></ul> |
| `python_full_version` | `#!python import platform`<br>`platform.python_version()` | <ul><li>2.7.18</li><li>3.11.0b1</li></ul> |
| `implementation_name` | `#!python import sys`<br>`sys.implementation.name` | <ul><li>cpython</li></ul> |
| `implementation_version` | See [here](https://peps.python.org/pep-0508/#environment-markers) | <ul><li>2.7.18</li><li>3.11.0b1</li></ul> |
## Features
You can select groups of [optional dependencies](metadata.md#optional) to install using the [extras](https://peps.python.org/pep-0508/#extras) syntax. For example, if a dependency named `foo` defined the following:
```toml tab="pyproject.toml"
[project.optional-dependencies]
crypto = [
"PyJWT",
"cryptography",
]
fastjson = [
"orjson",
]
cli = [
"prompt-toolkit",
"colorama; platform_system == 'Windows'",
]
```
You can select the `cli` and `crypto` features like so:
```
foo[cli,crypto]==1.*
```
Note that the features come immediately after the package name, before any [version specifiers](#version-specifiers).
### Self-referential
Feature groups can self-referentially extend others. For example, for a project called `awesome-project`, the `dev` feature group in the following `pyproject.toml` file would select everything in the `crypto` feature group, plus `black`:
```toml tab="pyproject.toml"
[project]
name = "awesome-project"
[project.optional-dependencies]
crypto = [
"PyJWT",
"cryptography",
]
dev = [
"awesome-project[crypto]",
"black",
]
```
## Direct references
Instead of using normal [version specifiers](#version-specifiers) and fetching packages from an index like PyPI, you can define exact sources using [direct references](https://peps.python.org/pep-0440/#direct-references) with an explicit [URI](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Syntax).
Direct references are usually not meant to be used for dependencies of a published project but rather are used for defining [dependencies for an environment](environment/overview.md#dependencies).
All direct reference types are prefixed by the package name like:
```
<NAME> @ <REFERENCE>
```
### Version control systems
Various version control systems (VCS) are [supported](#supported-vcs) as long as the associated executable is available along your `PATH`.
VCS direct references are defined using one of the following formats:
```
<NAME> @ <SCHEME>://<PATH>
<NAME> @ <SCHEME>://<PATH>@<REVISION>
```
You may also append a `#subdirectory=<PATH>` component for specifying the relative path to the Python package when it is not located at the root e.g. `#subdirectory=lib/foo`.
For more information, refer to [this](https://pip.pypa.io/en/stable/topics/vcs-support/).
#### Supported VCS
=== "Git"
| Executable | Schemes | Revisions | Example |
| --- | --- | --- | --- |
| `git` | <ul><li><code>git+file</code></li><li><code>git+https</code></li><li><code>git+ssh</code></li><li><code>git+http</code> :warning:</li><li><code>git+git</code> :warning:</li><li><code>git</code> :warning:</li></ul> | <ul><li>Commit hash</li><li>Tag name</li><li>Branch name</li></ul> | `proj @ git+https://github.com/org/proj.git@v1` |
=== "Mercurial"
| Executable | Schemes | Revisions | Example |
| --- | --- | --- | --- |
| `hg` | <ul><li><code>hg+file</code></li><li><code>hg+https</code></li><li><code>hg+ssh</code></li><li><code>hg+http</code> :warning:</li><li><code>hg+static-http</code> :warning:</li></ul> | <ul><li>Revision hash</li><li>Revision number</li><li>Tag name</li><li>Branch name</li></ul> | `proj @ hg+file:///path/to/proj@v1` |
=== "Subversion"
| Executable | Schemes | Revisions | Example |
| --- | --- | --- | --- |
| `svn` | <ul><li><code>svn+https</code></li><li><code>svn+ssh</code></li><li><code>svn+http</code> :warning:</li><li><code>svn+svn</code> :warning:</li><li><code>svn</code> :warning:</li></ul> | <ul><li>Revision number</li></ul> | `proj @ svn+file:///path/to/proj` |
=== "Bazaar"
| Executable | Schemes | Revisions | Example |
| --- | --- | --- | --- |
| `bzr` | <ul><li><code>bzr+https</code></li><li><code>bzr+ssh</code></li><li><code>bzr+sftp</code></li><li><code>bzr+lp</code></li><li><code>bzr+http</code> :warning:</li><li><code>bzr+ftp</code> :warning:</li></ul> | <ul><li>Revision number</li><li>Tag name</li></ul> | `proj @ bzr+lp:proj@v1` |
### Local
You can install local packages with the `file` scheme in the following format:
```
<NAME> @ file://<HOST>/<PATH>
```
The `<HOST>` is only used on Windows systems, where it can refer to a network share. If omitted it is assumed to be `localhost` and the third slash must still be present.
The `<PATH>` can refer to a source archive, a wheel, or a directory containing a Python package.
| Type | Unix | Windows |
| --- | --- | --- |
| Source archive | `proj @ file:///path/to/pkg.tar.gz` | `proj @ file:///c:/path/to/pkg.tar.gz` |
| Wheel | `proj @ file:///path/to/pkg.whl` | `proj @ file:///c:/path/to/pkg.whl` |
| Directory | `proj @ file:///path/to/pkg` | `proj @ file:///c:/path/to/pkg` |
!!! tip
You may also specify paths relative to your project's root directory on all platforms by using [context formatting](context.md#paths):
```
<NAME> @ {root:uri}/pkg_inside_project
<NAME> @ {root:parent:uri}/pkg_alongside_project
```
### Remote
You can install source archives and wheels by simply referring to a URL:
```
black @ https://github.com/psf/black/archive/refs/tags/21.10b0.zip
pytorch @ https://download.pytorch.org/whl/cu102/torch-1.10.0%2Bcu102-cp39-cp39-linux_x86_64.whl
```
An expected hash value may be specified by appending a `#<HASH_ALGORITHM>=<EXPECTED_HASH>` component:
```
requests @ https://github.com/psf/requests/archive/refs/tags/v2.26.0.zip#sha256=eb729a757f01c10546ebd179ae2aec852dd0d7f8ada2328ccf4558909d859985
```
If the hash differs from the expected hash, the installation will fail.
It is recommended that only hashes which are unconditionally provided by the latest version of the standard library's [hashlib module](https://docs.python.org/dev/library/hashlib.html) be used for hashes. As of Python 3.10, that list consists of:
- `md5`
- `sha1`
- `sha224`
- `sha256`
- `sha384`
- `sha512`
- `blake2b`
- `blake2s`
### Complex syntax
The following is an example that uses [features](#features) and [environment markers](#environment-markers):
```
pkg[feature1,feature2] @ <REFERENCE> ; python_version < "3.7"
```
Note that the space before the semicolon is required.