Pyproject
Description
The pyproject crawler looks recursively for all pyproject.toml files from a specific root directory.
Then for each of them, it tries to update the Python dependencies declared in the [project] table.
Dependencies are read from:
[project.dependencies][project.optional-dependencies](one manifest per package, per group)
Directories named .venv, pycache, .git, node_modules, .tox, .nox, and .eggs are never walked.
This crawler is enabled by default, so it can be used either automatically by running updatecli diff from a directory containing the files to update, or by providing a manifest.
The automatic discovery behavior can be tuned by providing a YAML manifest with a pyproject crawler in top-level directive autodiscovery as explained in the "Autodiscovery" page.
Requirements
The crawler detects the package manager from the lock file sitting next to pyproject.toml.
Only uv is supported today, via uv.lock.
The result depends on what Updatecli finds next to each pyproject.toml:
uv.lock | uv command on PATH | Result |
|---|---|---|
present | yes | Full manifests: a |
present | no | The |
absent | - | Source-only manifests. Updatecli reports the latest published version but generates no target, so nothing is modified. |
Tip | If a project produces no manifest at all, check that uv is installed and reachable from the environment running Updatecli. |
Generated manifests
One manifest is generated per dependency, using the pypi resource as a source and a shell target:
name: 'deps(pypi): bump "requests" for "myproject" project'
sources:
requests:
name: 'Get latest "requests" package version'
kind: 'pypi'
spec:
name: 'requests'
versionfilter:
kind: 'pep440'
pattern: '>=2.28'
targets:
requests:
name: 'deps(pypi): bump "requests" to {{ source "requests" }}'
kind: 'shell'
spec:
command: 'uv lock --upgrade-package requests=={{ source "requests" }}'
changedif:
kind: file/checksum
spec:
files:
- "uv.lock"
environments:
- name: PATH
workdir: '.'
disablesourceinput: trueworkdir points at the directory holding the pyproject.toml, so nested projects are updated in place.
Important | uv lock --upgrade-package only updates uv.lock. The version constraints declared in pyproject.toml are deliberately left untouched, so a dependency is only bumped as far as its own constraint allows. Widening a constraint such as requests>=2.28,<3 remains a manual change. |
The shell target only exposes the PATH environment variable to uv. Variables such as UV_INDEX_URL, NETRC, or HOME are not inherited.
Version filtering
If no versionfilter is specified, the crawler falls back to kind: pep440 and reuses each dependency’s own constraint as the pattern, for example >=2.28 for requests>=2.28.
Dependencies declared without a constraint get the pattern *.
If a versionfilter is specified, its kind is used for every generated source, and relative semver patterns are resolved against the version currently declared by each dependency.
For example kind: semver with pattern: minor generates pattern: '2.x' for requests>=2.28.
Explicit constraint patterns such as >=1.0.0 are used as-is.
More details on the "Version Filtering" page.
Limitations
Only the
[project]table is read.[dependency-groups](PEP 735),[tool.poetry],[tool.uv], and[build-system].requiresare ignored, so Poetry and PDM projects yield no manifest.PEP 508 direct references such as
mypkg @ https://…;ormypkg @ git+https://…, and local path dependencies, are skipped with a warning.Extras are dropped from the tracked name:
black[jupyter]>=24.0is tracked asblack.Environment markers are stripped, not evaluated.
pywin32>=300; sys_platform == 'win32'is updated unconditionally.
Manifest
Parameters
| Name | Type | Description | Required |
|---|---|---|---|
| ignore | array | Ignore specifies rules to exclude pyproject.toml dependencies from autodiscovery. | |
| packages | object | Packages specifies the list of Python packages to match, keyed by package name. The value is a PEP 440 version specifier (e.g. “>=2.0,<3.0”) or empty to match any version. | |
| path | string | Path specifies a pyproject.toml path pattern. The pattern must match the full path, not just a substring. Wildcards accepted by filepath.Match are supported. | |
| indexurl | string | IndexURL specifies a custom PyPI index URL propagated to all generated source specs.
It carries no credentials: authenticating against a private registry requires setting the
pypi resource token field on the generated manifests. | |
| only | array | Only specifies rules to restrict autodiscovery to matching pyproject.toml dependencies. | |
| packages | object | Packages specifies the list of Python packages to match, keyed by package name. The value is a PEP 440 version specifier (e.g. “>=2.0,<3.0”) or empty to match any version. | |
| path | string | Path specifies a pyproject.toml path pattern. The pattern must match the full path, not just a substring. Wildcards accepted by filepath.Match are supported. | |
| rootdir | string | RootDir defines the root directory used to recursively search for pyproject.toml files. | |
| versionfilter | object |
If unspecified, Updatecli falls back to kind kind - pep440 (default)
versionfilter of kind kind - semver
versionfilter of kind kind - regex
versionfilter of kind example: More examples can be found at https://www.updatecli.io/docs/core/versionfilter/ | |
| kind | string | specifies the version kind such as semver, regex, or latest | |
| pattern | string | specifies the version pattern according the version kind for semver, it is a semver constraint for regex, it is a regex pattern for time, it is a date format | |
| regex | string | specifies the regex pattern, used for regex/semver and regex/time. Output of the first capture group will be used. | |
| replaceall | object | replaceAll applies a regex replacement to version strings before filtering. This is useful for transforming versions (e.g., curl-8_15_0 to curl-8.15.0) before regex extraction. | |
| pattern | string | Pattern specifies the regex pattern to match for replacement | |
| replacement | string | Replacement specifies the replacement string (supports $1, $2, etc. for captured groups) | |
| strict | boolean | strict enforce strict versioning rule. Only used for semantic versioning at this time |
Note | Within a single only/ignore rule, path and packages must both match (AND); separate rules are combined with OR. A package version in a rule is a PEP 440 specifier evaluated against the version number extracted from the dependency’s constraint, for example 2.28 for requests>=2.28. An empty value matches any version. |
Example
Basic Example
# updatecli.d/pyproject.yaml
autodiscovery:
crawlers:
pyproject:
rootdir: "."
versionfilter:
kind: semver
pattern: minorFilter to Specific Packages
# updatecli.d/pyproject-only.yaml
autodiscovery:
crawlers:
pyproject:
only:
- packages:
"requests": ""
"flask": ""Private PyPI Registry
# updatecli.d/pyproject-private.yaml
autodiscovery:
crawlers:
pyproject:
rootdir: "."
# Custom PyPI index URL propagated to all generated pypi source specs
indexurl: "https://pypi.example.com/"Note | The indexurl parameter is propagated as the url field of every generated pypi source, allowing consistent registry configuration across all discovered dependencies. It does not carry credentials: the crawler has no token parameter, so an authenticated registry requires adding the pypi resource token field to the generated manifests by hand. The uv lock target relies on `uv’s own index configuration. |
Note | The alias python/uv can also be used instead of pyproject. |