Skip to content

Commit

Permalink
Install pinned dependencies from poetry.lock
Browse files Browse the repository at this point in the history
If a poetry.lock file is present, use the Poetry CLI to export the
pinned requirements to a requirements.txt file. If the project already
contains a requirements.txt, use that and ignore poetry.lock.

Poetry is not used to install the project because it does not clean up
stale requirements. This means that requirements need to be exported
anyway, for the `pip-uninstall` step.

Since we only use Poetry to export a requirements.txt file, ignore the
Poetry version specified in pyproject.toml. Install a pre-release of
1.0.0 because the export command is not available before 1.0.0a0.

Note that supporting pyproject.toml-based installations is not enough to
handle pinned requirements: When pip installs a pyproject.toml-style
project using the process described in PEP 517, it only uses Poetry to
build a wheel. The wheel contains the version constraints from
pyproject.toml, not the pinned versions from poetry.lock.
  • Loading branch information
cjolowicz committed Oct 3, 2019
1 parent e6fdadd commit ae5b3cd
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 0 deletions.
4 changes: 4 additions & 0 deletions bin/compile
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,10 @@ mtime "python.install.time" "${start}"
# shellcheck source=bin/steps/pipenv
source "$BIN_DIR/steps/pipenv"

# Export requirements.txt from poetry.lock, if present.
# shellcheck source=bin/steps/poetry
source "$BIN_DIR/steps/poetry"

# Uninstall removed dependencies with Pip.
# The buildpack will automatically remove any declared dependencies (in requirements.txt)
# that were explicitly removed. This machinery is a bit complex, but it is not complicated.
Expand Down
63 changes: 63 additions & 0 deletions bin/steps/poetry
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env bash

set -e

# shellcheck source=bin/utils
source "$BIN_DIR/utils"

if [ ! -f requirements.txt ] && [ -f pyproject.toml ] && [ -f poetry.lock ]; then
# Measure that we're using Poetry.
mcount "tool.poetry"

# Hash poetry.lock to detect changes.
POETRY_LOCK_SHA=$(openssl dgst -sha256 poetry.lock)

# Use cached requirements.txt if poetry.lock is unchanged.
CACHED_REQUIREMENTS=$CACHE_DIR/requirements.txt
CACHED_POETRY_LOCK_SHA=$CACHE_DIR/poetry.lock.sha256

if [ -f "$CACHED_REQUIREMENTS" ] && [ -f "$CACHED_POETRY_LOCK_SHA" ] &&
[ "$POETRY_LOCK_SHA" == "$(cat "$CACHED_POETRY_LOCK_SHA")" ]; then
echo "Skipping requirements export, as poetry.lock hasn't changed since last deploy." | indent
cp "$CACHED_REQUIREMENTS" requirements.txt
else
# Set environment variables for pip
# This reads certain environment variables set on the Heroku app config
# and makes them accessible to the pip install process.
#
# PIP_EXTRA_INDEX_URL allows for an alternate pypi URL to be used.
if [[ -r "$ENV_DIR/PIP_EXTRA_INDEX_URL" ]]; then
PIP_EXTRA_INDEX_URL="$(cat "$ENV_DIR/PIP_EXTRA_INDEX_URL")"
export PIP_EXTRA_INDEX_URL
mcount "buildvar.PIP_EXTRA_INDEX_URL"
fi

# Set SLUGIFY_USES_TEXT_UNIDECODE, required for Airflow versions >=1.10
if [[ -r "$ENV_DIR/SLUGIFY_USES_TEXT_UNIDECODE" ]]; then
SLUGIFY_USES_TEXT_UNIDECODE="$(cat "$ENV_DIR/SLUGIFY_USES_TEXT_UNIDECODE")"
export SLUGIFY_USES_TEXT_UNIDECODE
mcount "buildvar.SLUGIFY_USES_TEXT_UNIDECODE"
fi

# Install Poetry.
#
# Poetry is not used to install the project because it does not clean up
# stale requirements (see sdispater/poetry#648), so we need to export
# requirements.txt anyway for the pip-uninstall step.
#
# Since we only use Poetry to export a requirements.txt file, ignore the
# Poetry version specified in pyproject.toml. Install a pre-release of
# 1.0.0 because the export command is not available before 1.0.0a0.
export POETRY_VERSION="1.0.0b1"
puts-step "Exporting requirements with Poetry $POETRY_VERSION"
/app/.heroku/python/bin/pip install "poetry==$POETRY_VERSION" \
--disable-pip-version-check &> /dev/null

# Export requirements.
/app/.heroku/python/bin/poetry export -f requirements.txt > requirements.txt

# Write SHA and requirements.txt to cache dir.
echo "$POETRY_LOCK_SHA" > "$CACHED_POETRY_LOCK_SHA"
cp requirements.txt "$CACHED_REQUIREMENTS"
fi
fi

0 comments on commit ae5b3cd

Please sign in to comment.