`RUST_LOG` influences returned directory in `prepare_metadata_for_build_wheel`
### Bug Description
We are investigating build failures in our software stack we're currently building up.
After installing Rust v1.94.1 and maturin v1.13.1, we tried to build a Python package (tibs) with our standard install procedure:
```
$ python -m pip install --prefix=[...]/software/tibs/0.6.0-GCCcore-15.2.0 --no-deps --ignore-installed --no-index --no-build-isolation .
```
In earlier `maturin` versions, this worked perfectly fine. However, with version v1.13.0 and later, we're getting the following build failure from `pip`:
<details>
<summary>Click to open</summary>
```
ERROR: Exception:
Traceback (most recent call last):
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_internal/cli/base_command.py", line 107, in _run_wrapper
status = _inner_run()
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_internal/cli/base_command.py", line 98, in _inner_run
return self.run(options, args)
~~~~~~~~^^^^^^^^^^^^^^^
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_internal/cli/req_command.py", line 85, in wrapper
return func(self, options, args)
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_internal/commands/install.py", line 389, in run
requirement_set = resolver.resolve(
reqs, check_supported_wheels=not options.target_dir
)
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_internal/resolution/resolvelib/resolver.py", line 79, in resolve
collected = self.factory.collect_root_requirements(root_reqs)
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 538, in collect_root_requirements
reqs = list(
self._make_requirements_from_install_req(
...<2 lines>...
)
)
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 494, in _make_requirements_from_install_req
cand = self._make_base_candidate_from_link(
ireq.link,
...<2 lines>...
version=None,
)
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_internal/resolution/resolvelib/factory.py", line 226, in _make_base_candidate_from_link
self._link_candidate_cache[link] = LinkCandidate(
~~~~~~~~~~~~~^
link,
^^^^^
...<3 lines>...
version=version,
^^^^^^^^^^^^^^^^
)
^
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 318, in __init__
super().__init__(
~~~~~~~~~~~~~~~~^
link=link,
^^^^^^^^^^
...<4 lines>...
version=version,
^^^^^^^^^^^^^^^^
)
^
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 161, in __init__
self.dist = self._prepare()
~~~~~~~~~~~~~^^
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 238, in _prepare
dist = self._prepare_distribution()
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_internal/resolution/resolvelib/candidates.py", line 329, in _prepare_distribution
return preparer.prepare_linked_requirement(self._ireq, parallel_builds=True)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_internal/operations/prepare.py", line 543, in prepare_linked_requirement
return self._prepare_linked_requirement(req, parallel_builds)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_internal/operations/prepare.py", line 658, in _prepare_linked_requirement
dist = _get_prepared_distribution(
req,
...<3 lines>...
self.check_build_deps,
)
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_internal/operations/prepare.py", line 77, in _get_prepared_distribution
abstract_dist.prepare_distribution_metadata(
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
build_env_installer, build_isolation, check_build_deps
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_internal/distributions/sdist.py", line 71, in prepare_distribution_metadata
self.req.prepare_metadata()
~~~~~~~~~~~~~~~~~~~~~~~~~^^
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_internal/req/req_install.py", line 538, in prepare_metadata
self._set_requirement()
~~~~~~~~~~~~~~~~~~~~~^^
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_internal/req/req_install.py", line 373, in _set_requirement
if isinstance(parse_version(self.metadata["Version"]), Version):
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_vendor/packaging/version.py", line 56, in parse
return Version(version)
File "/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/lib/python3.14/site-packages/pip/_vendor/packaging/version.py", line 200, in __init__
match = self._regex.search(version)
TypeError: expected string or bytes-like object, got 'NoneType'
```
</details>
After digging a bit deeper, I suspect that the following things happen:
1. `pip` calls into `generate_metadata -> prepare_metadata -> prepare_metadata_for_build_wheel`. This leads to [`prepare_metadata_for_build_wheel`](https://github.com/PyO3/maturin/blob/2582ab3763cf7b9d4b9dce25bc4c4299f074d914/maturin/__init__.py#L190) in `maturin`.
2. `maturin` calls `maturin pep517 write-dist-info --metadata-directory [...] --interpreter [...]`
3. `maturin` returns the _last_ line of the output, _not_ containing the expected output
Checking `self.metadata_directory` in `pip` via some `print` debugging after `maturin` has finished (i.e. adding a print [here](https://github.com/pypa/pip/blob/2cb24160e92ba9e99b52fbc817c2500ec88da81a/src/pip/_internal/req/req_install.py#L530), I saw:
```
/tmp/eb-2gkjwrv2/pip-modern-metadata-8_54kgcy/2026-04-16T15:07:48.084403Z INFO pep517: maturin::commands::pep517: close time.busy=367ms time.idle=11.3µs
```
Here, we can see some `INFO` output instead of the directory name.
Running `maturin pep517 write-dist-info --metadata-directory [...] --interpreter [...]` manually verifies that this is indeed the last line:
```
eb-shell> maturin pep517 write-dist-info --metadata-directory /tmp/eb-37jjd3ve/pip-modern-metadata-9rw9krgm --interpreter /p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/bin/python
2026-04-17T07:37:16.252630Z INFO pep517:into_build_context: maturin::build_options: close time.busy=1.44µs time.idle=810ns
2026-04-17T07:37:16.252805Z DEBUG pep517:build: maturin::project_layout: Found pyproject.toml in working directory at "/dev/shm/reuter1/easybuild/build/tibs/0.6.0/GCCcore-15.2.0/tibs-0.6.0/pyproject.toml"
2026-04-17T07:37:16.253378Z DEBUG pep517:build: maturin::project_layout: Using cargo manifest path from working directory: "/dev/shm/reuter1/easybuild/build/tibs/0.6.0/GCCcore-15.2.0/tibs-0.6.0/Cargo.toml"
2026-04-17T07:37:16.253585Z DEBUG pep517:build:resolve_cargo_metadata: maturin::project_layout: Resolving cargo metadata from "/dev/shm/reuter1/easybuild/build/tibs/0.6.0/GCCcore-15.2.0/tibs-0.6.0/Cargo.toml"
2026-04-17T07:37:16.318621Z INFO pep517:build:resolve_cargo_metadata: maturin::project_layout: close time.busy=65.0ms time.idle=3.50µs
📦 Including license file `LICENSE`
2026-04-17T07:37:16.319311Z DEBUG pep517:build: maturin::project_layout: Project layout resolved project_root=/dev/shm/reuter1/easybuild/build/tibs/0.6.0/GCCcore-15.2.0/tibs-0.6.0 python_dir=/dev/shm/reuter1/easybuild/build/tibs/0.6.0/GCCcore-15.2.0/tibs-0.6.0 rust_module=/dev/shm/reuter1/easybuild/build/tibs/0.6.0/GCCcore-15.2.0/tibs-0.6.0/tibs python_module=Some("/dev/shm/reuter1/easybuild/build/tibs/0.6.0/GCCcore-15.2.0/tibs-0.6.0/tibs") extension_name=tibs module_name=tibs
🔗 Found pyo3 bindings with abi3 support
2026-04-17T07:37:16.319501Z DEBUG pep517:build: maturin::build_context::builder: Resolved bridge model: PyO3(PyO3 { crate_name: pyo3, version: Version { major: 0, minor: 28, patch: 2 }, stable_abi: Some(StableAbi { kind: Abi3, version: Version(3, 8) }), metadata: Some(PyO3Metadata { cpython: PyO3VersionMetadata { min_minor: 7, max_minor: 15 }, pypy: PyO3VersionMetadata { min_minor: 11, max_minor: 11 } }) })
2026-04-17T07:37:16.479623Z DEBUG pep517:build:check_executable: maturin::python_interpreter::discovery: Found CPython interpreter at /p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/bin/python executable=/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/bin/python
2026-04-17T07:37:16.479676Z INFO pep517:build:check_executable: maturin::python_interpreter::discovery: close time.busy=51.0ms time.idle=2.62µs executable=/p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/bin/python
🐍 Found CPython 3.14 at /p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/bin/python
📡 Using build options features from pyproject.toml
2026-04-17T07:37:16.479796Z INFO pep517:build: maturin::build_context::builder: close time.busy=227ms time.idle=4.22µs
2026-04-17T07:37:16.482808Z DEBUG pep517: maturin::module_writer::virtual_writer: Tracked entry "tibs-0.6.0.dist-info/METADATA"
2026-04-17T07:37:16.482840Z DEBUG pep517: maturin::module_writer::virtual_writer: Tracked entry "tibs-0.6.0.dist-info/WHEEL"
2026-04-17T07:37:16.482851Z DEBUG pep517: maturin::module_writer::virtual_writer: Tracked entry "tibs-0.6.0.dist-info/licenses/LICENSE"
tibs-0.6.0.dist-info
2026-04-17T07:37:16.483749Z INFO pep517: maturin::commands::pep517: close time.busy=231ms time.idle=13.0µs
```
Some more debugging and searching later, it looks like this boils down to `RUST_LOG=debug` being set in our environment. Changing this to e.g. `RUST_LOG=warn` is sufficient enough to fix the issues we've seen.
```
eb-shell> RUST_LOG=warn maturin pep517 write-dist-info --metadata-directory /tmp/eb-37jjd3ve/pip-modern-metadata-9rw9krgm --interpreter /p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/bin/python
📦 Including license file `LICENSE`
🔗 Found pyo3 bindings with abi3 support
🐍 Found CPython 3.14 at /p/project1/cswmanage/reuter1/EasyBuild/apps/software/Python/3.14.2-GCCcore-15.2.0/bin/python
📡 Using build options features from pyproject.toml
tibs-0.6.0.dist-info
```
----
`maturin` should probably handle the case where an environment might set `RUST_LOG=[...]`, especially as the output is being parsed in `prepare_metadata_for_build_wheel`.
Options might include to override / unset `RUST_LOG` for this particular call only, or to add a more robust handling for the returned directory name.
### Your maturin version (`maturin --version`)
1.13.0, 1.13.1
### Your Python version (`python -V`)
3.14.2
### Your pip version (`pip -V`)
25.3
### What bindings you're using
None
### Does `cargo build` work?
- [x] Yes, it works
### If on windows, have you checked that you aren't accidentally using unix path (those with the forward slash `/`)?
- [ ] Yes
The issues were encountered on different Linux systems (Arch Linux, Rocky Linux 9, RHEL, ...)
### Steps to Reproduce
1. Install `maturin` in a virtual environment:
```console
$ python3 -m venv venv
$ source venv/bin/activate
$ pip install maturin==1.13.1
```
2. Try to install a package with `RUST_LOG=debug` set:
```console
$ RUST_LOG=debug pip install --no-deps --ignore-installed --no-index --no-build-isolation https://github.com/scott-griffiths/tibs/archive/refs/tags/v0.6.0.tar.gz
```
This should yield the same error reported above:
```
File "/home/jreuter/venv/lib/python3.14/site-packages/pip/_internal/distributions/sdist.py", line 71, in prepare_distribution_metadata
self.req.prepare_metadata()
~~~~~~~~~~~~~~~~~~~~~~~~~^^
File "/home/jreuter/venv/lib/python3.14/site-packages/pip/_internal/req/req_install.py", line 538, in prepare_metadata
self._set_requirement()
~~~~~~~~~~~~~~~~~~~~~^^
File "/home/jreuter/venv/lib/python3.14/site-packages/pip/_internal/req/req_install.py", line 373, in _set_requirement
if isinstance(parse_version(self.metadata["Version"]), Version):
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/jreuter/venv/lib/python3.14/site-packages/pip/_vendor/packaging/version.py", line 103, in parse
return Version(version)
File "/home/jreuter/venv/lib/python3.14/site-packages/pip/_vendor/packaging/version.py", line 359, in __init__
match = self._regex.fullmatch(version)
TypeError: expected string or bytes-like object, got 'NoneType'
```
关闭于 2026-04-17 1 条评论