Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix metadata cache instability #6332

Merged
merged 1 commit into from
Aug 21, 2024
Merged

Commits on Aug 21, 2024

  1. Fix metadata cache instability

    For a path dep such as the root project, uv can read metadata statically from `pyproject.toml` or dynamically from the build backend.
    
    Python's `packaging` [sorts](https://github.com/pypa/packaging/blob/cc938f984bbbe43c5734b9656c9837ab3a28191f/src/packaging/specifiers.py#L777) specifiers before emitting them, so all build backends built on top of it - such as hatchling - will change the specifier order compared to pyproject.toml. The core metadata spec does say "If a field is not marked as Dynamic, then the value of the field in any wheel built from the sdist MUST match the value in the sdist", but it doesn't specify if "match" means string equivalent or semantically equivalent, so it's arguable if that spec conformant. This change means that the specifiers have a different ordering when coming from the build backend than when read statically from pyproject.toml.
    
    Previously, we tried to read path dep metadata in order:
    * From the (built wheel) cache (`packaging` order)
    * From pyproject.toml (verbatim specifier)
    * From a fresh build (`packaging` order)
    
    This behaviour is unstable: On the first run, we cache is cold, so we read the verbatim specifier from `pyproject.toml`, then we build and store the metadata in the cache. On the second run, we read the `packaging` sorted specifier from the cache.
    
    Reproducer:
    
    ```shell
    rm -rf newproj
    uv init -q --no-config newproj
    cd newproj/
    uv add -q "anyio>=4,<5"
    cat uv.lock | grep "requires-dist"
    uv sync -q
    cat uv.lock | grep "requires-dist"
    cd ..
    ```
    
    ```
    requires-dist = [{ name = "anyio", specifier = ">=4,<5" }]
    requires-dist = [{ name = "anyio", specifier = "<5,>=4" }]
    ```
    
    A project either has static metadata, so we can read from pyproject.toml, or it doesn't, and we always read from the build through `packaging`. We can use this to stabilize the behavior by slightly switching the order.
    
    * From pyproject.toml (verbatim specifier)
    * From the (built wheel) cache (`packaging` order)
    * From a fresh build (`packaging` order)
    
    Potentially, we still want to sort the specifiers we get anyway, after all, the is no guarantee that the specifiers from a build backend are deterministic. But our metadata reading behavior should be independent of the cache state, hence changing the order in the PR.
    
    Fixes #6316
    konstin committed Aug 21, 2024
    Configuration menu
    Copy the full SHA
    c45f658 View commit details
    Browse the repository at this point in the history