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

PEP660 editable VCS dependencies not reinstalled correctly #6348

Open
edmorley opened this issue Feb 21, 2025 · 0 comments
Open

PEP660 editable VCS dependencies not reinstalled correctly #6348

edmorley opened this issue Feb 21, 2025 · 0 comments

Comments

@edmorley
Copy link
Contributor

edmorley commented Feb 21, 2025

Issue description

For editable VCS (eg Git) dependencies, re-running pipenv install does not reinstall the dependency if the linked source repository checkout is missing (eg if it has been moved to a different path, or otherwise removed).

This appears to only affect PEP 660 style editable installs.

Expected result

For pipenv install to reinstall an editable VCS dependency, if the src/ directory containing the repository checkout has been removed since the last time pipenv install was run.

For example, this works with pip:

FROM python:3.13
WORKDIR /testcase
RUN pip install -e git+https://github.com/benoitc/[email protected]#egg=gunicorn
RUN python -c 'import gunicorn'
RUN rm -rf src/
RUN pip install -e git+https://github.com/benoitc/[email protected]#egg=gunicorn
RUN python -c 'import gunicorn'

Actual result

Pipenv doesn't reinstall the editable VCS dependency - the pipenv install is a no-op:

#14 [ 9/10] RUN pipenv install --system --verbose
#14 0.282 Installing dependencies from Pipfile.lock (13dee2)...
#14 DONE 0.3s

Which then results in a ModuleNotFoundError:

#15 [10/10] RUN python -c 'import gunicorn'
#15 0.130 Traceback (most recent call last):
#15 0.132   File "<string>", line 1, in <module>
#15 0.132     import gunicorn
#15 0.132 ModuleNotFoundError: No module named 'gunicorn'

Steps to replicate

Create a Dockerfile, with contents:

FROM python:3.13
WORKDIR /testcase

COPY <<EOF Pipfile
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
gunicorn = {git = "git+https://github.com/benoitc/gunicorn", ref = "23.0.0", editable = true}
EOF

COPY <<EOF Pipfile.lock
{
    "_meta": {
        "hash": {
            "sha256": "0979fd8702b00f90e3e2e93d14919cf23f76b992c80662d6e610dc850d13dee2"
        },
        "pipfile-spec": 6,
        "requires": {},
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.org/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {
        "gunicorn": {
            "editable": true,
            "git": "git+https://github.com/benoitc/gunicorn",
            "markers": "python_version >= '3.7'",
            "ref": "411986d6191114dd1d1bbb9c72c948dbf0ef0425"
        },
        "packaging": {
            "hashes": [
                "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759",
                "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"
            ],
            "markers": "python_version >= '3.8'",
            "version": "==24.2"
        }
    },
    "develop": {}
}
EOF

RUN pip install pipenv==v2024.4.1
RUN pipenv install --system --verbose

# This works
RUN python -c 'import gunicorn'

# Remove the gunicorn source checkout
RUN rm -rf src/

# Reinstall
RUN pipenv install --system --verbose

# The src dir is missing here since pipenv didn't reinstall the editable VCS dependency
RUN ls -al

# And so this fails with a `ModuleNotFoundError`
RUN python -c 'import gunicorn'

Then run it with: docker build . --progress plain --no-cache

Additional findings

If I downgrade the gunicorn version, to one that uses setup.py instead of pyproject.toml (by changing ref = "23.0.0" to ref = "21.2.0") and set ENV PIP_USE_PEP517=0 to force a legacy setup.py develop editable install then this issue no longer reproduces.

With the legacy editable install, site-packages contains:

easy-install.pth
gunicorn.egg-link

Whereas when using the PEP517 / PEP660 install (as per the Dockerfile above), site-packages instead contains:

gunicorn-23.0.0.dist-info/
__editable__.gunicorn-23.0.0.pth
__editable___gunicorn_23_0_0_finder.py

As such, I've presuming this might be an issue with how Pipenv handles editable VCS dependencies specifically when they use the new PEP660 editable interface?

Is the issue somewhere here?

def is_satisfied(self, req: InstallRequirement):
match = next(
iter(
d
for d in self.get_distributions()
if req.name
and canonicalize_name(normalized_name(d)) == canonicalize_name(req.name)
),
None,
)
if match is not None:
if req.specifier is not None:
return SpecifierSet(str(req.specifier)).contains(
match.version, prereleases=True
)
if req.link is None:
return True
elif req.editable and req.link.is_file:
requested_path = req.link.file_path
if os.path.exists(requested_path):
local_path = requested_path
else:
parsed_url = urlparse(requested_path)
local_path = parsed_url.path
return requested_path and os.path.samefile(local_path, match.location)
elif match.has_metadata("direct_url.json") or (req.link and req.link.is_vcs):
# Direct URL installs and VCS installs we assume are not satisfied
# since due to skip-lock we may be installing from Pipfile we have insufficient
# information to determine if a branch or ref has actually changed.
return False
return True
return False

edmorley added a commit to heroku/heroku-buildpack-python that referenced this issue Feb 21, 2025
Heroku builds occur at a different path to which the app will be run
at run-time. As such, we have to perform path rewriting for editable
dependencies, so that they work after relocation.

The existing rewriting is performed at app boot (see code comment for
more details), and works fine with pip and Poetry.

However, I discovered that Pipenv doesn't correctly reinstall editable
VCS dependencies if they use the new PEP660 style editable interface,
which I've reported upstream here:
pypa/pipenv#6348

This issue has affected apps using editable VCS dependencies with Pipenv
for some time, but until now only at build-time for cached builds.

However, after #1753 (which thankfully isn't yet released, due to me
catching this as part of updating the tests to exercise the new PEP660
style editable interface) would otherwise affect apps at run-time too.

As a workaround, we can perform build time rewriting of paths too, but
must do so only for VCS dependencies (see code comment for why).

Lastly, the Pipenv bug also requires that we perform explicit cache
invalidation for Pipenv apps after the src dir move in #1753.
edmorley added a commit to heroku/heroku-buildpack-python that referenced this issue Feb 21, 2025
Heroku builds occur at a different path to which the app will be run
at run-time. As such, we have to perform path rewriting for editable
dependencies, so that they work after relocation.

The existing rewriting is performed at app boot (see code comment for
more details), and works fine with pip and Poetry.

However, I discovered that Pipenv doesn't correctly reinstall editable
VCS dependencies if they use the new PEP660 style editable interface,
which I've reported upstream here:
pypa/pipenv#6348

This issue has affected apps using editable VCS dependencies with Pipenv
for some time, but until now only at build-time for cached builds.

However, after #1753 (which thankfully isn't yet released, due to me
catching this as part of updating the tests to exercise the new PEP660
style editable interface) would otherwise affect apps at run-time too.

As a workaround, we can perform build time rewriting of paths too, but
must do so only for VCS dependencies (see code comment for why).

Lastly, the Pipenv bug also requires that we perform explicit cache
invalidation for Pipenv apps after the src dir move in #1753.
edmorley added a commit to heroku/heroku-buildpack-python that referenced this issue Feb 21, 2025
Heroku builds occur at a different path to which the app will be run
at run-time. As such, we have to perform path rewriting for editable
dependencies, so that they work after relocation.

The existing rewriting is performed at app boot (see code comment for
more details), and works fine with pip and Poetry.

However, I discovered that Pipenv doesn't correctly reinstall editable
VCS dependencies if they use the new PEP660 style editable interface,
which I've reported upstream here:
pypa/pipenv#6348

This issue has affected apps using editable VCS dependencies with Pipenv
for some time, but until now only at build-time for cached builds.

However, after #1753 (which thankfully isn't yet released, due to me
catching this as part of updating the tests to exercise the new PEP660
style editable interface) would otherwise affect apps at run-time too.

As a workaround, we can perform build time rewriting of paths too, but
must do so only for VCS dependencies (see code comment for why).

Lastly, the Pipenv bug also requires that we perform explicit cache
invalidation for Pipenv apps after the src dir move in #1753.

GUS-W-17884520.
edmorley added a commit to heroku/heroku-buildpack-python that referenced this issue Feb 22, 2025
Heroku builds occur at a different path to which the app will be run
at run-time. As such, we have to perform path rewriting for editable
dependencies, so that they work after relocation.

The existing rewriting is performed at app boot (see code comment for
more details), and works fine with pip and Poetry.

However, I discovered that Pipenv doesn't correctly reinstall editable
VCS dependencies if they use the new PEP660 style editable interface,
which I've reported upstream here:
pypa/pipenv#6348

This issue has affected apps using editable VCS dependencies with Pipenv
for some time, but until now only at build-time for cached builds.

However, after #1753 (which thankfully isn't yet released, due to me
catching this as part of updating the tests to exercise the new PEP660
style editable interface) would otherwise affect apps at run-time too.

As a workaround, we can perform build time rewriting of paths too, but
must do so only for VCS dependencies (see code comment for why).

Lastly, the Pipenv bug also requires that we perform explicit cache
invalidation for Pipenv apps after the src dir move in #1753.

GUS-W-17884520.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant