Skip to content

build.check_dependency ignores URL reqs with names that match an installed distribution #860

Open
@gschaffner

Description

@gschaffner

When build.check_dependency sees a URL req with a name that matches an installed distribution, it considers the URL req met. For example:

import importlib.metadata

import build


def get_version(distribution_name: str) -> str | None:
    try:
        return importlib.metadata.version(distribution_name)
    except ModuleNotFoundError:
        return None


# Some version of packaging is installed:
packaging_ver = importlib.metadata.version("packaging")
assert packaging_ver is not None and packaging_ver != "24.1"
print(
    f"{tuple(build.check_dependency("packaging @ git+https://github.com/pypa/[email protected]")) = !r}"
)

# No version of sniffio is installed:
sniffio_ver = get_version("sniffio")
assert sniffio_ver is None
print(
    f"{tuple(build.check_dependency("sniffio @ git+https://github.com/python-trio/[email protected]")) = !r}"
)

Output (in a venv with packaging==24.2 and without sniffio):

tuple(build.check_dependency("packaging @ git+https://github.com/pypa/[email protected]")) = ()
tuple(build.check_dependency("sniffio @ git+https://github.com/python-trio/[email protected]")) = (('sniffio@ git+https://github.com/python-trio/[email protected]',),)

The packaging URL req is reported as met but it is not. The sniffio URL req is correctly reported as unmet.

With check_dependency's current documentation, this seems like a bug; it should be able to verify that URL reqs are met.

Is it possible via PEP 610?

     try:
         dist = importlib.metadata.distribution(req.name)
     except importlib.metadata.PackageNotFoundError:
         # dependency is not installed in the environment.
         yield (*ancestral_req_strings, normalised_req_string)
     else:
         if req.specifier and not req.specifier.contains(dist.version, prereleases=True):
             # the installed version is incompatible.
             yield (*ancestral_req_strings, normalised_req_string)
+        elif req.url and pseudocode(dist.origin != req.url):
+            yield (*ancestral_req_strings, normalised_req_string)
         elif dist.requires:
             for other_req_string in dist.requires:
                 # yields transitive dependencies that are not satisfied.
                 yield from check_dependency(other_req_string, (*ancestral_req_strings, normalised_req_string), req.extras)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions