Skip to content

Commit

Permalink
Improve package manager tests (#1754)
Browse files Browse the repository at this point in the history
Backports a number of updates/improvements to the pip/Poetry/Pipenv
package manager integration tests found while working on the tests for uv.
  • Loading branch information
edmorley authored Feb 20, 2025
1 parent ee0a9eb commit f2d2bc7
Show file tree
Hide file tree
Showing 12 changed files with 98 additions and 52 deletions.
2 changes: 2 additions & 0 deletions spec/fixtures/pipenv_editable/.python-version
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
# Note: This test has to use Python 3.12 until we work around the
# Pipenv editable VCS dependency cache invalidation bug.
3.12
3 changes: 2 additions & 1 deletion spec/fixtures/pipenv_editable/Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ verify_ssl = true
name = "pypi"

[packages]
gunicorn = {git = "git+https://github.com/benoitc/gunicorn", ref = "20.1.0", editable = true}
local-package-pyproject-toml = {file = "packages/local_package_pyproject_toml", editable = true}
local-package-setup-py = {file = "packages/local_package_setup_py", editable = true}
gunicorn = {git = "git+https://github.com/benoitc/gunicorn", ref = "20.1.0", editable = true}
pipenv-editable = {file = ".", editable = true}
12 changes: 8 additions & 4 deletions spec/fixtures/pipenv_editable/Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file.
8 changes: 8 additions & 0 deletions spec/fixtures/pipenv_editable/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
name = "pipenv-editable"
version = "0.0.0"
requires-python = ">=3.12"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
2 changes: 1 addition & 1 deletion spec/fixtures/poetry_editable/bin/test-entrypoints.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set -euo pipefail

cd .heroku/python/lib/python*/site-packages/

# List any path like strings in .pth, and finder files in site-packages.
# List any path like strings in the .pth and finder files in site-packages.
grep --extended-regexp --only-matching -- '/\S+' *.pth __editable___*_finder.py | sort
echo

Expand Down
46 changes: 21 additions & 25 deletions spec/fixtures/poetry_editable/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion spec/fixtures/poetry_editable/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ authors = []

[tool.poetry.dependencies]
python = "^3.13"
gunicorn = { git = "https://github.com/benoitc/gunicorn.git", tag = "20.1.0", develop = true }
gunicorn = { git = "https://github.com/benoitc/gunicorn.git", develop = true }
local-package-pyproject-toml = { path = "packages/local_package_pyproject_toml", develop = true }
local-package-setup-py = { path = "packages/local_package_setup_py", develop = true }

Expand Down
12 changes: 6 additions & 6 deletions spec/hatchet/ci_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

it 'installs both normal and test dependencies and uses cache on subsequent runs' do
app.run_ci do |test_run|
expect(test_run.output).to match(Regexp.new(<<~REGEX, Regexp::MULTILINE))
expect(clean_output(test_run.output)).to match(Regexp.new(<<~REGEX, Regexp::MULTILINE))
-----> Python app detected
-----> Using Python #{DEFAULT_PYTHON_MAJOR_VERSION} specified in .python-version
-----> Installing Python #{DEFAULT_PYTHON_FULL_VERSION}
Expand Down Expand Up @@ -62,7 +62,7 @@
REGEX

test_run.run_again
expect(test_run.output).to include(<<~OUTPUT)
expect(clean_output(test_run.output)).to include(<<~OUTPUT)
-----> Python app detected
-----> Using Python #{DEFAULT_PYTHON_MAJOR_VERSION} specified in .python-version
-----> Restoring cache
Expand All @@ -81,7 +81,7 @@

it 'installs both normal and test dependencies and uses cache on subsequent runs' do
app.run_ci do |test_run|
expect(test_run.output).to match(Regexp.new(<<~REGEX))
expect(clean_output(test_run.output)).to match(Regexp.new(<<~REGEX))
-----> Python app detected
-----> Using Python #{DEFAULT_PYTHON_MAJOR_VERSION} specified in .python-version
-----> Installing Python #{DEFAULT_PYTHON_FULL_VERSION}
Expand Down Expand Up @@ -134,7 +134,7 @@
REGEX

test_run.run_again
expect(test_run.output).to match(Regexp.new(<<~REGEX))
expect(clean_output(test_run.output)).to match(Regexp.new(<<~REGEX))
-----> Python app detected
-----> Using Python #{DEFAULT_PYTHON_MAJOR_VERSION} specified in .python-version
-----> Restoring cache
Expand All @@ -156,7 +156,7 @@

it 'installs both normal and test dependencies and uses cache on subsequent runs' do
app.run_ci do |test_run|
expect(test_run.output).to match(Regexp.new(<<~REGEX))
expect(clean_output(test_run.output)).to match(Regexp.new(<<~REGEX))
-----> Python app detected
-----> Using Python #{DEFAULT_PYTHON_MAJOR_VERSION} specified in .python-version
-----> Installing Python #{DEFAULT_PYTHON_FULL_VERSION}
Expand Down Expand Up @@ -217,7 +217,7 @@
REGEX

test_run.run_again
expect(test_run.output).to include(<<~OUTPUT)
expect(clean_output(test_run.output)).to include(<<~OUTPUT)
-----> Python app detected
-----> Using Python #{DEFAULT_PYTHON_MAJOR_VERSION} specified in .python-version
-----> Restoring cache
Expand Down
5 changes: 4 additions & 1 deletion spec/hatchet/pip_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@
end

# This test intentionally uses Python 3.12, so that we test rewriting using older globally installed
# setuptools. The Poetry equivalent of this test covers the PEP-517/518 setuptools case.
# setuptools (which causes .egg-link files to be created too). The Pipenv and Poetry equivalents of
# this test covers the PEP-517/518 setuptools case.
context 'when requirements.txt contains editable requirements (both VCS and local package)' do
let(:buildpacks) { [:default, 'heroku-community/inline'] }
let(:app) { Hatchet::Runner.new('spec/fixtures/pip_editable', buildpacks:) }
Expand Down Expand Up @@ -159,6 +160,8 @@
remote: Running entrypoint for the setup.py-based local package: Hello setup.py!
remote: Running entrypoint for the VCS package: gunicorn \\(version 20.1.0\\)
REGEX
# Test that the VCS repo checkout was cached correctly.
expect(app.output).to include('Updating /app/.heroku/python/src/gunicorn clone (to revision 20.1.0)')
end
end
end
Expand Down
13 changes: 12 additions & 1 deletion spec/hatchet/pipenv_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
remote: typing_extensions 4.12.2
remote: virtualenv .+
remote:
remote: \\<module 'typing_extensions' from '/app/.heroku/python/lib/python3.13/site-packages/typing_extensions.py'\\>
remote: <module 'typing_extensions' from '/app/.heroku/python/lib/python3.13/site-packages/typing_extensions.py'>
REGEX
app.commit!
app.push!
Expand Down Expand Up @@ -348,19 +348,24 @@
end
end

# This test has to use Python 3.12 until we work around the Pipenv editable VCS dependency
# cache invalidation bug when using pyproject.toml / PEP517 based installs.
context 'when Pipfile contains editable requirements' do
let(:buildpacks) { [:default, 'heroku-community/inline'] }
let(:app) { Hatchet::Runner.new('spec/fixtures/pipenv_editable', buildpacks:) }

it 'rewrites .pth, .egg-link and finder paths correctly for hooks, later buildpacks, runtime and cached builds' do
app.deploy do |app|
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX))
remote: -----> Installing dependencies using 'pipenv install --deploy'
remote: Installing dependencies from Pipfile.lock \\(.+\\)...
remote: -----> Running bin/post_compile hook
remote: easy-install.pth:/tmp/build_.+/.heroku/python/src/gunicorn
remote: easy-install.pth:/tmp/build_.+/packages/local_package_setup_py
remote: __editable___local_package_pyproject_toml_0_0_1_finder.py:/tmp/build_.+/packages/local_package_pyproject_toml/local_package_pyproject_toml'}
remote: gunicorn.egg-link:/tmp/build_.+/.heroku/python/src/gunicorn
remote: local-package-setup-py.egg-link:/tmp/build_.+/packages/local_package_setup_py
remote: _pipenv_editable.pth:/tmp/build_.+
remote:
remote: Running entrypoint for the pyproject.toml-based local package: Hello pyproject.toml!
remote: Running entrypoint for the setup.py-based local package: Hello setup.py!
Expand All @@ -371,6 +376,7 @@
remote: __editable___local_package_pyproject_toml_0_0_1_finder.py:/tmp/build_.+/packages/local_package_pyproject_toml/local_package_pyproject_toml'}
remote: gunicorn.egg-link:/tmp/build_.+/.heroku/python/src/gunicorn
remote: local-package-setup-py.egg-link:/tmp/build_.+/packages/local_package_setup_py
remote: _pipenv_editable.pth:/tmp/build_.+
remote:
remote: Running entrypoint for the pyproject.toml-based local package: Hello pyproject.toml!
remote: Running entrypoint for the setup.py-based local package: Hello setup.py!
Expand All @@ -384,6 +390,7 @@
__editable___local_package_pyproject_toml_0_0_1_finder.py:/app/packages/local_package_pyproject_toml/local_package_pyproject_toml'}
gunicorn.egg-link:/app/.heroku/python/src/gunicorn
local-package-setup-py.egg-link:/app/packages/local_package_setup_py
_pipenv_editable.pth:/app
Running entrypoint for the pyproject.toml-based local package: Hello pyproject.toml!
Running entrypoint for the setup.py-based local package: Hello setup.py!
Expand All @@ -394,12 +401,15 @@
app.commit!
app.push!
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX))
remote: -----> Installing dependencies using 'pipenv install --deploy'
remote: Installing dependencies from Pipfile.lock \\(.+\\)...
remote: -----> Running bin/post_compile hook
remote: easy-install.pth:/tmp/build_.+/.heroku/python/src/gunicorn
remote: easy-install.pth:/tmp/build_.+/packages/local_package_setup_py
remote: __editable___local_package_pyproject_toml_0_0_1_finder.py:/tmp/build_.+/packages/local_package_pyproject_toml/local_package_pyproject_toml'}
remote: gunicorn.egg-link:/tmp/build_.+/.heroku/python/src/gunicorn
remote: local-package-setup-py.egg-link:/tmp/build_.+/packages/local_package_setup_py
remote: _pipenv_editable.pth:/tmp/build_.+
remote:
remote: Running entrypoint for the pyproject.toml-based local package: Hello pyproject.toml!
remote: Running entrypoint for the setup.py-based local package: Hello setup.py!
Expand All @@ -410,6 +420,7 @@
remote: __editable___local_package_pyproject_toml_0_0_1_finder.py:/tmp/build_.+/packages/local_package_pyproject_toml/local_package_pyproject_toml'}
remote: gunicorn.egg-link:/tmp/build_.+/.heroku/python/src/gunicorn
remote: local-package-setup-py.egg-link:/tmp/build_.+/packages/local_package_setup_py
remote: _pipenv_editable.pth:/tmp/build_.+
remote:
remote: Running entrypoint for the pyproject.toml-based local package: Hello pyproject.toml!
remote: Running entrypoint for the setup.py-based local package: Hello setup.py!
Expand Down
Loading

0 comments on commit f2d2bc7

Please sign in to comment.