From ff223597f32661bb694c3bb6b27744214aace6c7 Mon Sep 17 00:00:00 2001
From: Kenneth Reitz <me@kennethreitz.org>
Date: Tue, 26 Sep 2017 11:42:14 -0400
Subject: [PATCH] =?UTF-8?q?Upgrades=20=F0=9F=94=9D=20(#475)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fixed the bug for pypy-5.8.0

* changelog

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* python 2.7.14

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* pipfile > requirements.txt

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* check for python_full_version too

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* 2.7.14

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* warn when using an older version of python

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* requirements for anaconda buildpack

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* remove hashes for conda buildpack

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* improvements to pipenv python version detection

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* oops

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* oops

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* oops

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* echo not puts

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* try this

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* learn more

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* there we go

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* cleanups

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* cleanups

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* cleanups

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* unsupported

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* consistiency

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* be more specific

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* capitalize Pipfile.lock

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* attempt to force color

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* try this

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* try this

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* interactive

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* interactive

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* diagnose

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* try without -l

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* confirmed env working

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* just -c

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* use latest, to debug

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* no more bash

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* try …

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* don't use the git version of pipenv

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* oops

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* next version

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* 2.7.14

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* comment out force color bits

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* readme

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* more tests

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* more tests

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>

* ellipsis

Signed-off-by: Kenneth Reitz <me@kennethreitz.org>
---
 CHANGELOG.md                                  | 11 ++++
 Pipfile                                       |  9 ++++
 Pipfile.lock                                  | 52 ++++++++++++++++++
 README.md                                     | 20 +++++--
 bin/compile                                   |  5 +-
 bin/steps/nltk                                |  2 +-
 bin/steps/pipenv                              |  5 +-
 bin/steps/pipenv-python-version               | 22 +++++---
 bin/steps/python                              | 15 ++++++
 builds/libraries/sqlite                       |  2 +-
 builds/libraries/vendor/gdal                  |  2 +-
 builds/libraries/vendor/geos                  |  2 +-
 builds/libraries/vendor/libffi                |  2 +-
 builds/libraries/vendor/libmemcache           |  4 +-
 builds/libraries/vendor/proj                  |  2 +-
 builds/runtimes/pypy-5.3.1                    |  2 +-
 builds/runtimes/pypy-5.6.0                    |  2 +-
 builds/runtimes/pypy-5.7.0                    |  2 +-
 builds/runtimes/pypy-5.7.1                    |  2 +-
 builds/runtimes/pypy-5.8.0                    |  2 +-
 builds/runtimes/pypy3-2.4.0                   |  2 +-
 builds/runtimes/pypy3-5.5.0                   |  2 +-
 builds/runtimes/pypy3-5.7.1                   |  2 +-
 builds/runtimes/pypy3-5.8.0                   |  2 +-
 builds/runtimes/python-2.7.10                 |  2 +-
 builds/runtimes/python-2.7.11                 |  2 +-
 builds/runtimes/python-2.7.12                 |  2 +-
 builds/runtimes/python-2.7.13                 |  2 +-
 builds/runtimes/python-2.7.14                 | 19 +++++++
 builds/runtimes/python-2.7.9                  |  2 +-
 builds/runtimes/python-3.5.2                  |  2 +-
 builds/runtimes/python-3.5.3                  |  2 +-
 builds/runtimes/python-3.6.0                  |  2 +-
 builds/runtimes/python-3.6.1                  |  2 +-
 builds/runtimes/python-3.6.2                  |  2 +-
 requirements.txt                              |  2 +
 test/fixtures/pipenv-full-version/Pipfile     |  9 ++++
 .../fixtures/pipenv-full-version/Pipfile.lock | 23 ++++++++
 test/fixtures/pipenv-lock/Pipfile             |  2 +
 test/fixtures/pipenv-lock/Pipfile.lock        | 53 +++++++++++++++++++
 test/fixtures/python2/runtime.txt             |  2 +-
 test/run                                      | 13 ++++-
 42 files changed, 273 insertions(+), 43 deletions(-)
 create mode 100644 Pipfile
 create mode 100644 Pipfile.lock
 create mode 100755 builds/runtimes/python-2.7.14
 create mode 100644 test/fixtures/pipenv-full-version/Pipfile
 create mode 100644 test/fixtures/pipenv-full-version/Pipfile.lock
 create mode 100644 test/fixtures/pipenv-lock/Pipfile
 create mode 100644 test/fixtures/pipenv-lock/Pipfile.lock

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3301ea3b..88e1610b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,16 @@
 # Python Buildpack Changelog
 
+# 119
+
+Improvements to Pipenv support, warning on unsupported Python versions.
+
+- We now warn when a user is not using latest 2.x or 3.x Python.
+- Heroku now supports `[requires]` `python_full_version` in addition to `python_version`.
+
+# 118
+
+Improvements to Pipenv support.
+
 # 117
 
 Bug fix.
diff --git a/Pipfile b/Pipfile
new file mode 100644
index 00000000..061134c9
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,9 @@
+[[source]]
+url = "https://pypi.python.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[dev-packages]
+
+[packages]
+"bob-builder" = "==0.0.13"
\ No newline at end of file
diff --git a/Pipfile.lock b/Pipfile.lock
new file mode 100644
index 00000000..b3d436d8
--- /dev/null
+++ b/Pipfile.lock
@@ -0,0 +1,52 @@
+{
+    "_meta": {
+        "hash": {
+            "sha256": "36d17c46a8b1b844b3cae475f6f42d6c0a9e59b2a9685cbcdc0985656a7a129f"
+        },
+        "host-environment-markers": {
+            "implementation_name": "cpython",
+            "implementation_version": "3.6.2",
+            "os_name": "posix",
+            "platform_machine": "x86_64",
+            "platform_python_implementation": "CPython",
+            "platform_release": "16.7.0",
+            "platform_system": "Darwin",
+            "platform_version": "Darwin Kernel Version 16.7.0: Thu Jun 15 17:36:27 PDT 2017; root:xnu-3789.70.16~2/RELEASE_X86_64",
+            "python_full_version": "3.6.2",
+            "python_version": "3.6",
+            "sys_platform": "darwin"
+        },
+        "pipfile-spec": 6,
+        "requires": {},
+        "sources": [
+            {
+                "name": "pypi",
+                "url": "https://pypi.python.org/simple",
+                "verify_ssl": true
+            }
+        ]
+    },
+    "default": {
+        "bob-builder": {
+            "hashes": [
+                "sha256:b4de49a8e436fcaf82236ea43f78413b4a4c92100726e382ab57b6bdfb38fe64",
+                "sha256:288e3e765c4890fe9a63ae52ac6b4a963c13fe508482c70ff701a5ae21b9a673"
+            ],
+            "version": "==0.0.13"
+        },
+        "boto": {
+            "hashes": [
+                "sha256:13be844158d1bd80a94c972c806ec8381b9ea72035aa06123c5db6bc6a6f3ead",
+                "sha256:deb8925b734b109679e3de65856018996338758f4b916ff4fe7bb62b6d7000d1"
+            ],
+            "version": "==2.48.0"
+        },
+        "docopt": {
+            "hashes": [
+                "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"
+            ],
+            "version": "==0.6.2"
+        }
+    },
+    "develop": {}
+}
diff --git a/README.md b/README.md
index b35a0a95..4e1bb6fc 100644
--- a/README.md
+++ b/README.md
@@ -21,13 +21,13 @@ Deploying a Python application couldn't be easier:
     $ heroku create --buildpack heroku/python
 
     $ git push heroku master
-    ...
+    …
     -----> Python app detected
     -----> Installing python-3.6.2
     -----> Installing pip
-    -----> Installing requirements with latest pipenv...
+    -----> Installing requirements with latest pipenv…
            ...
-           Installing dependencies from Pipfile...
+           Installing dependencies from Pipfile…
     -----> Discovering process types
            Procfile declares types -> (none)
 
@@ -44,11 +44,21 @@ Specify a Python Runtime
 Specific versions of the Python runtime can be specified with a `runtime.txt` file:
 
     $ cat runtime.txt
-    python-2.7.13
+    python-2.7.14
+
+Or, with a `Pipfile.lock` (generated from the following `Pipfile`):
+
+    [requires]
+    python_version = "2.7"
+
+Or, more specifically:
+
+    [requires]
+    python_full_version = "2.7.14"
 
 Runtime options include:
 
 - `python-3.6.2`
-- `python-2.7.13`
+- `python-2.7.14`
 - `pypy-5.7.1` (unsupported, experimental)
 - `pypy3-5.5.1` (unsupported, experimental)
diff --git a/bin/compile b/bin/compile
index c2885214..4b7682d4 100755
--- a/bin/compile
+++ b/bin/compile
@@ -35,10 +35,13 @@ export BUILD_DIR CACHE_DIR ENV_DIR
 
 # Python defaults
 DEFAULT_PYTHON_VERSION="python-3.6.2"
+LATEST_3="python-3.6.2"
+LATEST_2="python-2.7.14"
+
 DEFAULT_PYTHON_STACK="cedar-14"
 PIP_UPDATE="9.0.1"
 
-export DEFAULT_PYTHON_VERSION DEFAULT_PYTHON_STACK PIP_UPDATE
+export DEFAULT_PYTHON_VERSION DEFAULT_PYTHON_STACK PIP_UPDATE LATEST_2 LATEST_3
 
 # Common Problem Warnings
 WARNINGS_LOG=$(mktemp)
diff --git a/bin/steps/nltk b/bin/steps/nltk
index b2ded512..a930a72f 100755
--- a/bin/steps/nltk
+++ b/bin/steps/nltk
@@ -15,7 +15,7 @@ source "$BIN_DIR/utils"
 
 # Check that nltk was installed by pip, otherwise obviously not needed
 if sp-grep -s nltk; then
-    puts-step "Downloading NLTK corpora..."
+    puts-step "Downloading NLTK corpora…"
 
     nltk_packages_definition="$BUILD_DIR/nltk.txt"
 
diff --git a/bin/steps/pipenv b/bin/steps/pipenv
index ad7c78ed..927183b4 100644
--- a/bin/steps/pipenv
+++ b/bin/steps/pipenv
@@ -1,9 +1,12 @@
 #!/usr/bin/env bash
 
+# export CLINT_FORCE_COLOR=1
+# export PIPENV_FORCE_COLOR=1
+
 # Pipenv support (Generate requriements.txt with pipenv).
 if [[ -f Pipfile ]]; then
     if [[ ! -f requirements.txt ]]; then
-        puts-step "Installing requirements with latest Pipenv..."
+        puts-step "Installing requirements with latest Pipenv…"
 
         # Install pipenv.
         /app/.heroku/python/bin/pip install pipenv --upgrade &> /dev/null
diff --git a/bin/steps/pipenv-python-version b/bin/steps/pipenv-python-version
index 23aa12a3..361668f2 100755
--- a/bin/steps/pipenv-python-version
+++ b/bin/steps/pipenv-python-version
@@ -6,19 +6,27 @@ if [[ -f $BUILD_DIR/Pipfile ]]; then
 
     if [[ ! -f $BUILD_DIR/runtime.txt ]]; then
         if [[ ! -f $BUILD_DIR/Pipfile.lock ]]; then
-            puts-warn "No 'pipfile.lock' found! We recommend you commit this into your repository."
+            puts-warn "No 'Pipfile.lock' found! We recommend you commit this into your repository."
         fi
         if [[ -f $BUILD_DIR/Pipfile.lock ]]; then
             set +e
-            PYTHON=$(jq -r '._meta.requires.python_version' "$BUILD_DIR/Pipfile.lock")
+            PYTHON=$(jq -r '._meta.requires.python_full_version' "$BUILD_DIR/Pipfile.lock")
+            if [[ "$PYTHON" != "null" ]]; then
+                echo "python-$PYTHON" > "$BUILD_DIR/runtime.txt"
+            fi
             set -e
 
-            if [ "$PYTHON" = 2.7 ]; then
-                echo "python-2.7.13" > "$BUILD_DIR/runtime.txt"
-            fi
-            if [ "$PYTHON" = 3.6 ]; then
-                echo "python-3.6.2" > "$BUILD_DIR/runtime.txt"
+            if [[ "$PYTHON" == "null" ]]; then
+                PYTHON=$(jq -r '._meta.requires.python_version' "$BUILD_DIR/Pipfile.lock")
+                if [ "$PYTHON" = 2.7 ]; then
+                    echo "python-2.7.14" > "$BUILD_DIR/runtime.txt"
+                fi
+                if [ "$PYTHON" = 3.6 ]; then
+                    echo "python-3.6.2" > "$BUILD_DIR/runtime.txt"
+                fi
             fi
+
+
         fi
     fi
 fi
diff --git a/bin/steps/python b/bin/steps/python
index 908d1b27..798d4b19 100755
--- a/bin/steps/python
+++ b/bin/steps/python
@@ -4,6 +4,21 @@ set +e
 runtime-fixer runtime.txt
 PYTHON_VERSION=$(cat runtime.txt)
 
+if [[ $PYTHON_VERSION =~ ^python-2 ]]; then
+  if [[ "$PYTHON_VERSION" != "$LATEST_2" ]]; then
+    puts-warn "The latest version of Python 2 is $LATEST_2 (you are using $PYTHON_VERSION, which is unsupported)."
+    puts-warn "We recommend upgrading by specifying the latest version ($LATEST_2)."
+    echo "       Learn More: https://devcenter.heroku.com/articles/python-runtimes"
+  fi
+else
+  if [[ "$PYTHON_VERSION" != "$LATEST_3" ]]; then
+    puts-warn "The latest version of Python 3 is $LATEST_3 (you are using $PYTHON_VERSION, which is unsupported)."
+    puts-warn "We recommend upgrading by specifying the latest version ($LATEST_3)."
+    echo "       Learn More: https://devcenter.heroku.com/articles/python-runtimes"
+  fi
+
+fi
+
 if [[ "$STACK" != "$CACHED_PYTHON_STACK" ]]; then
     puts-step "Stack has changed from $CACHED_PYTHON_STACK to $STACK, clearing cache"
     rm -fr .heroku/python-stack .heroku/python-version .heroku/python .heroku/vendor
diff --git a/builds/libraries/sqlite b/builds/libraries/sqlite
index 8ed1720d..e24484ed 100755
--- a/builds/libraries/sqlite
+++ b/builds/libraries/sqlite
@@ -3,7 +3,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building SQLite..."
+echo "Building SQLite…"
 
 
 SOURCE_TARBALL='https://www.sqlite.org/sqlite-autoconf-3070900.tar.gz'
diff --git a/builds/libraries/vendor/gdal b/builds/libraries/vendor/gdal
index 21b331a5..7cb110ea 100755
--- a/builds/libraries/vendor/gdal
+++ b/builds/libraries/vendor/gdal
@@ -8,7 +8,7 @@ export PATH="/app/.heroku/python/bin/:$PATH"
 hash -r
 
 
-echo "Building gdal..."
+echo "Building gdal…"
 
 VERSION="2.2.1"
 SOURCE_TARBALL="http://download.osgeo.org/gdal/${VERSION}/gdal-${VERSION}.tar.gz"
diff --git a/builds/libraries/vendor/geos b/builds/libraries/vendor/geos
index 69966b1c..3c7bcab2 100755
--- a/builds/libraries/vendor/geos
+++ b/builds/libraries/vendor/geos
@@ -8,7 +8,7 @@ export PATH="/app/.heroku/python/bin/:$PATH"
 hash -r
 
 
-echo "Building geos..."
+echo "Building geos…"
 
 VERSION=3.6.2
 
diff --git a/builds/libraries/vendor/libffi b/builds/libraries/vendor/libffi
index bfe7e38a..5955371b 100755
--- a/builds/libraries/vendor/libffi
+++ b/builds/libraries/vendor/libffi
@@ -13,7 +13,7 @@ export PATH="/app/.heroku/python/bin/:$PATH"
 hash -r
 
 
-echo "Building libffi..."
+echo "Building libffi…"
 
 SOURCE_TARBALL='ftp://sourceware.org/pub/libffi/libffi-3.1.tar.gz'
 
diff --git a/builds/libraries/vendor/libmemcache b/builds/libraries/vendor/libmemcache
index 05c31318..3d01ce5a 100755
--- a/builds/libraries/vendor/libmemcache
+++ b/builds/libraries/vendor/libmemcache
@@ -20,7 +20,7 @@ dep_archive_name=${dep_dirname}.tar.gz
 dep_url=https://launchpad.net/libmemcached/1.0/${dep_version}/+download/${dep_archive_name}
 
 # SASL Support.
-echo "-----> Building cyrus-sasl 2.1.26..."
+echo "-----> Building cyrus-sasl 2.1.26…"
 
 curl -LO ftp://ftp.cyrusimap.org/cyrus-sasl/cyrus-sasl-2.1.26.tar.gz
 # FTP doesn't play well with piping into tar xz
@@ -33,7 +33,7 @@ make -s -j 9
 make install -s
 popd
 
-echo "-----> Building libmemcached ${dep_version}..."
+echo "-----> Building libmemcached ${dep_version}…"
 
 curl -L ${dep_url} | tar xz
 pushd ${dep_dirname}
diff --git a/builds/libraries/vendor/proj b/builds/libraries/vendor/proj
index a22e779b..7f11578b 100755
--- a/builds/libraries/vendor/proj
+++ b/builds/libraries/vendor/proj
@@ -8,7 +8,7 @@ export PATH="/app/.heroku/python/bin/:$PATH"
 hash -r
 
 
-echo "Building gdal..."
+echo "Building gdal…"
 
 VERSION=4.9.3
 SOURCE_TARBALL="http://download.osgeo.org/proj/proj-${VERSION}.tar.gz"
diff --git a/builds/runtimes/pypy-5.3.1 b/builds/runtimes/pypy-5.3.1
index d4fc13b3..cc1be00e 100755
--- a/builds/runtimes/pypy-5.3.1
+++ b/builds/runtimes/pypy-5.3.1
@@ -6,7 +6,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building PyPy..."
+echo "Building PyPy…"
 SOURCE_TARBALL='https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.3.1-linux64.tar.bz2'
 curl -L $SOURCE_TARBALL | tar jx
 cp -R pypy2-v5.3.1-linux64/* $OUT_PREFIX
diff --git a/builds/runtimes/pypy-5.6.0 b/builds/runtimes/pypy-5.6.0
index 2aee7539..685fa1da 100755
--- a/builds/runtimes/pypy-5.6.0
+++ b/builds/runtimes/pypy-5.6.0
@@ -6,7 +6,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building PyPy..."
+echo "Building PyPy…"
 SOURCE_TARBALL='https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.6.0-linux64.tar.bz2'
 curl -L $SOURCE_TARBALL | tar jx
 cp -R pypy2-v5.6.0-linux64/* $OUT_PREFIX
diff --git a/builds/runtimes/pypy-5.7.0 b/builds/runtimes/pypy-5.7.0
index de074edf..c16d5e36 100755
--- a/builds/runtimes/pypy-5.7.0
+++ b/builds/runtimes/pypy-5.7.0
@@ -6,7 +6,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building PyPy..."
+echo "Building PyPy…"
 SOURCE_TARBALL='https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.0-linux64.tar.bz2'
 curl -L $SOURCE_TARBALL | tar jx
 cp -R pypy2-v5.7.0-linux64/* $OUT_PREFIX
diff --git a/builds/runtimes/pypy-5.7.1 b/builds/runtimes/pypy-5.7.1
index ee93ba1f..86e34c6a 100755
--- a/builds/runtimes/pypy-5.7.1
+++ b/builds/runtimes/pypy-5.7.1
@@ -6,7 +6,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building PyPy..."
+echo "Building PyPy…"
 SOURCE_TARBALL='https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.7.1-linux64.tar.bz2'
 curl -L $SOURCE_TARBALL | tar jx
 cp -R pypy2-v5.7.1-linux64/* $OUT_PREFIX
diff --git a/builds/runtimes/pypy-5.8.0 b/builds/runtimes/pypy-5.8.0
index 1e06e711..6e8b6ac3 100755
--- a/builds/runtimes/pypy-5.8.0
+++ b/builds/runtimes/pypy-5.8.0
@@ -4,7 +4,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building PyPy..."
+echo "Building PyPy…"
 SOURCE_TARBALL='https://bitbucket.org/pypy/pypy/downloads/pypy2-v5.8.0-linux64.tar.bz2'
 curl -L $SOURCE_TARBALL | tar jx
 cp -R pypy2-v5.8.0-linux64/* $OUT_PREFIX
diff --git a/builds/runtimes/pypy3-2.4.0 b/builds/runtimes/pypy3-2.4.0
index ca010199..61b16381 100755
--- a/builds/runtimes/pypy3-2.4.0
+++ b/builds/runtimes/pypy3-2.4.0
@@ -6,7 +6,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building PyPy..."
+echo "Building PyPy…"
 SOURCE_TARBALL='https://bitbucket.org/pypy/pypy/downloads/pypy3-2.4.0-linux64.tar.bz2'
 curl -L $SOURCE_TARBALL | tar jx
 cp -R pypy3-2.4.0-linux64/* $OUT_PREFIX
diff --git a/builds/runtimes/pypy3-5.5.0 b/builds/runtimes/pypy3-5.5.0
index 567e96ef..fde9ffe2 100755
--- a/builds/runtimes/pypy3-5.5.0
+++ b/builds/runtimes/pypy3-5.5.0
@@ -6,7 +6,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building PyPy..."
+echo "Building PyPy…"
 SOURCE_TARBALL='https://bitbucket.org/pypy/pypy/downloads/pypy3.3-v5.5.0-alpha-linux64.tar.bz2'
 curl -L $SOURCE_TARBALL | tar jx
 cp -R pypy3-v5.5.0-linux64/* $OUT_PREFIX
diff --git a/builds/runtimes/pypy3-5.7.1 b/builds/runtimes/pypy3-5.7.1
index fad7d222..fb0e7180 100755
--- a/builds/runtimes/pypy3-5.7.1
+++ b/builds/runtimes/pypy3-5.7.1
@@ -4,7 +4,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building PyPy..."
+echo "Building PyPy…"
 SOURCE_TARBALL='https://bitbucket.org/pypy/pypy/downloads/pypy3-v5.7.1-linux64.tar.bz2'
 curl -L $SOURCE_TARBALL | tar jx
 cp -R pypy3-v5.7.1-linux64/* $OUT_PREFIX
diff --git a/builds/runtimes/pypy3-5.8.0 b/builds/runtimes/pypy3-5.8.0
index 87844a56..df08b9fc 100755
--- a/builds/runtimes/pypy3-5.8.0
+++ b/builds/runtimes/pypy3-5.8.0
@@ -4,7 +4,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building PyPy..."
+echo "Building PyPy…"
 SOURCE_TARBALL='https://bitbucket.org/pypy/pypy/downloads/pypy3-v5.8.0-linux64.tar.bz2'
 curl -L $SOURCE_TARBALL | tar jx
 cp -R pypy3-v5.8.0-linux64/* $OUT_PREFIX
diff --git a/builds/runtimes/python-2.7.10 b/builds/runtimes/python-2.7.10
index ba72340f..4ab82dc3 100755
--- a/builds/runtimes/python-2.7.10
+++ b/builds/runtimes/python-2.7.10
@@ -4,7 +4,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building Python..."
+echo "Building Python…"
 SOURCE_TARBALL='https://python.org/ftp/python/2.7.10/Python-2.7.10.tgz'
 curl -L $SOURCE_TARBALL | tar xz
 mv Python-2.7.10 src
diff --git a/builds/runtimes/python-2.7.11 b/builds/runtimes/python-2.7.11
index 4e60fed2..903a4a29 100755
--- a/builds/runtimes/python-2.7.11
+++ b/builds/runtimes/python-2.7.11
@@ -4,7 +4,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building Python..."
+echo "Building Python…"
 SOURCE_TARBALL='https://python.org/ftp/python/2.7.11/Python-2.7.11.tgz'
 curl -L $SOURCE_TARBALL | tar xz
 mv Python-2.7.11 src
diff --git a/builds/runtimes/python-2.7.12 b/builds/runtimes/python-2.7.12
index 6c1b38ce..3a721c31 100755
--- a/builds/runtimes/python-2.7.12
+++ b/builds/runtimes/python-2.7.12
@@ -4,7 +4,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building Python..."
+echo "Building Python…"
 SOURCE_TARBALL='https://python.org/ftp/python/2.7.12/Python-2.7.12.tgz'
 curl -L $SOURCE_TARBALL | tar xz
 mv Python-2.7.12 src
diff --git a/builds/runtimes/python-2.7.13 b/builds/runtimes/python-2.7.13
index 3f34aad6..4379d2ed 100755
--- a/builds/runtimes/python-2.7.13
+++ b/builds/runtimes/python-2.7.13
@@ -4,7 +4,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building Python..."
+echo "Building Python…"
 SOURCE_TARBALL='https://python.org/ftp/python/2.7.13/Python-2.7.13.tgz'
 curl -L $SOURCE_TARBALL | tar xz
 mv Python-2.7.13 src
diff --git a/builds/runtimes/python-2.7.14 b/builds/runtimes/python-2.7.14
new file mode 100755
index 00000000..fa16fd5f
--- /dev/null
+++ b/builds/runtimes/python-2.7.14
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+# Build Path: /app/.heroku/python/
+# Build Deps: libraries/sqlite
+
+OUT_PREFIX=$1
+
+echo "Building Python…"
+SOURCE_TARBALL='https://python.org/ftp/python/2.7.14/Python-2.7.14.tgz'
+curl -L $SOURCE_TARBALL | tar xz
+mv Python-2.7.14 src
+cd src
+
+./configure --prefix=$OUT_PREFIX  --enable-unicode=ucs4 --with-ensurepip=no
+make
+make install
+
+# Remove unneeded test directories, similar to the official Docker Python images:
+# https://github.com/docker-library/python
+find "${OUT_PREFIX}" \( -type d -a \( -name test -o -name tests \) \) -exec rm -rf '{}' +
diff --git a/builds/runtimes/python-2.7.9 b/builds/runtimes/python-2.7.9
index e94dedeb..1ab0085e 100755
--- a/builds/runtimes/python-2.7.9
+++ b/builds/runtimes/python-2.7.9
@@ -4,7 +4,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building Python..."
+echo "Building Python…"
 SOURCE_TARBALL='https://python.org/ftp/python/2.7.9/Python-2.7.9.tgz'
 curl -L $SOURCE_TARBALL | tar xz
 mv Python-2.7.9 src
diff --git a/builds/runtimes/python-3.5.2 b/builds/runtimes/python-3.5.2
index 760293d4..49806e64 100755
--- a/builds/runtimes/python-3.5.2
+++ b/builds/runtimes/python-3.5.2
@@ -4,7 +4,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building Python..."
+echo "Building Python…"
 SOURCE_TARBALL='https://python.org/ftp/python/3.5.2/Python-3.5.2.tgz'
 curl -L $SOURCE_TARBALL | tar xz
 mv Python-3.5.2 src
diff --git a/builds/runtimes/python-3.5.3 b/builds/runtimes/python-3.5.3
index a6f6ca49..6e54f88b 100755
--- a/builds/runtimes/python-3.5.3
+++ b/builds/runtimes/python-3.5.3
@@ -4,7 +4,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building Python..."
+echo "Building Python…"
 SOURCE_TARBALL='https://python.org/ftp/python/3.5.3/Python-3.5.3.tgz'
 curl -L $SOURCE_TARBALL | tar xz
 mv Python-3.5.3 src
diff --git a/builds/runtimes/python-3.6.0 b/builds/runtimes/python-3.6.0
index 2d420821..9c31d24f 100755
--- a/builds/runtimes/python-3.6.0
+++ b/builds/runtimes/python-3.6.0
@@ -4,7 +4,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building Python..."
+echo "Building Python…"
 SOURCE_TARBALL='https://python.org/ftp/python/3.6.0/Python-3.6.0.tgz'
 curl -L $SOURCE_TARBALL | tar xz
 mv Python-3.6.0 src
diff --git a/builds/runtimes/python-3.6.1 b/builds/runtimes/python-3.6.1
index 2611342c..263fc082 100755
--- a/builds/runtimes/python-3.6.1
+++ b/builds/runtimes/python-3.6.1
@@ -4,7 +4,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building Python..."
+echo "Building Python…"
 SOURCE_TARBALL='https://python.org/ftp/python/3.6.1/Python-3.6.1.tgz'
 curl -L $SOURCE_TARBALL | tar xz
 mv Python-3.6.1 src
diff --git a/builds/runtimes/python-3.6.2 b/builds/runtimes/python-3.6.2
index d23d4913..9b23a902 100755
--- a/builds/runtimes/python-3.6.2
+++ b/builds/runtimes/python-3.6.2
@@ -4,7 +4,7 @@
 
 OUT_PREFIX=$1
 
-echo "Building Python..."
+echo "Building Python…"
 SOURCE_TARBALL='https://python.org/ftp/python/3.6.2/Python-3.6.2.tgz'
 curl -L $SOURCE_TARBALL | tar xz
 mv Python-3.6.2 src
diff --git a/requirements.txt b/requirements.txt
index 1d64dbd0..35bd1665 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1 +1,3 @@
+docopt==0.6.2
 bob-builder==0.0.13
+boto==2.48.0
diff --git a/test/fixtures/pipenv-full-version/Pipfile b/test/fixtures/pipenv-full-version/Pipfile
new file mode 100644
index 00000000..56194d02
--- /dev/null
+++ b/test/fixtures/pipenv-full-version/Pipfile
@@ -0,0 +1,9 @@
+[[source]]
+url = "https://pypi.python.org/simple"
+verify_ssl = true
+
+[packages]
+requests = "*"
+
+[requires]
+python_full_version = "3.6.2"
\ No newline at end of file
diff --git a/test/fixtures/pipenv-full-version/Pipfile.lock b/test/fixtures/pipenv-full-version/Pipfile.lock
new file mode 100644
index 00000000..15f40775
--- /dev/null
+++ b/test/fixtures/pipenv-full-version/Pipfile.lock
@@ -0,0 +1,23 @@
+{
+    "default": {
+        "requests": {
+            "version": "==2.13.0",
+            "hash": "sha256:1a720e8862a41aa22e339373b526f508ef0c8988baf48b84d3fc891a8e237efb"
+        }
+    },
+    "develop": {},
+    "_meta": {
+        "sources": [
+            {
+                "url": "https://pypi.python.org/simple",
+                "verify_ssl": true
+            }
+        ],
+        "requires": {
+            "python_version": "3.6"
+        },
+        "hash": {
+            "sha256": "5866990104fc8f27d13cdf01abc2a32c553129e03f666316cacc5b42d3e0884e"
+        }
+    }
+}
\ No newline at end of file
diff --git a/test/fixtures/pipenv-lock/Pipfile b/test/fixtures/pipenv-lock/Pipfile
new file mode 100644
index 00000000..317d2ddd
--- /dev/null
+++ b/test/fixtures/pipenv-lock/Pipfile
@@ -0,0 +1,2 @@
+[packages]
+"delegator.py" = "*"
diff --git a/test/fixtures/pipenv-lock/Pipfile.lock b/test/fixtures/pipenv-lock/Pipfile.lock
new file mode 100644
index 00000000..f5414a8e
--- /dev/null
+++ b/test/fixtures/pipenv-lock/Pipfile.lock
@@ -0,0 +1,53 @@
+{
+    "_meta": {
+        "hash": {
+            "sha256": "397f2c55e3558ea57d292e3fc19b34e483770e5ec02cdedfb1f330680cd26635"
+        },
+        "host-environment-markers": {
+            "implementation_name": "cpython",
+            "implementation_version": "3.6.2",
+            "os_name": "posix",
+            "platform_machine": "x86_64",
+            "platform_python_implementation": "CPython",
+            "platform_release": "16.7.0",
+            "platform_system": "Darwin",
+            "platform_version": "Darwin Kernel Version 16.7.0: Thu Jun 15 17:36:27 PDT 2017; root:xnu-3789.70.16~2/RELEASE_X86_64",
+            "python_full_version": "3.6.2",
+            "python_version": "3.6",
+            "sys_platform": "darwin"
+        },
+        "pipfile-spec": 6,
+        "requires": {},
+        "sources": [
+            {
+                "name": "pypi",
+                "url": "https://pypi.python.org/simple",
+                "verify_ssl": true
+            }
+        ]
+    },
+    "default": {
+        "delegator.py": {
+            "hashes": [
+                "sha256:2575c4adc923ad0b8fdaa433f862b2b7cf21982717fb23cc895fd8f249ea820c",
+                "sha256:495e11ada66648650171a6c9a188df4eb050b235abff8771f41ee8a064eb9ded"
+            ],
+            "version": "==0.0.13"
+        },
+        "pexpect": {
+            "hashes": [
+                "sha256:f853b52afaf3b064d29854771e2db509ef80392509bde2dd7a6ecf2dfc3f0018",
+                "sha256:3d132465a75b57aa818341c6521392a06cc660feb3988d7f1074f39bd23c9a92"
+            ],
+            "version": "==4.2.1"
+        },
+        "ptyprocess": {
+            "hashes": [
+                "sha256:e8c43b5eee76b2083a9badde89fd1bbce6c8942d1045146e100b7b5e014f4f1a",
+                "sha256:e64193f0047ad603b71f202332ab5527c5e52aa7c8b609704fc28c0dc20c4365"
+            ],
+            "version": "==0.5.2"
+        }
+    },
+    "develop": {}
+}
diff --git a/test/fixtures/python2/runtime.txt b/test/fixtures/python2/runtime.txt
index ba85ab97..2ce112e3 100644
--- a/test/fixtures/python2/runtime.txt
+++ b/test/fixtures/python2/runtime.txt
@@ -1 +1 @@
-python-2.7.13
\ No newline at end of file
+python-2.7.14
\ No newline at end of file
diff --git a/test/run b/test/run
index faec5755..51db41fc 100755
--- a/test/run
+++ b/test/run
@@ -5,12 +5,23 @@ testPipenv() {
   assertCapturedSuccess
 }
 
+testPipenvLock() {
+  compile "pipenv-lock"
+  assertCapturedSuccess
+}
+
 testPipenvVersion() {
   compile "pipenv-version"
   assertCaptured "3.6.2"
   assertCapturedSuccess
 }
 
+testPipenvFullVersion() {
+  compile "pipenv-full-version"
+  assertCaptured "3.6.2"
+  assertCapturedSuccess
+}
+
 testNoRequirements() {
   compile "no-requirements"
   assertCapturedError
@@ -61,7 +72,7 @@ testPylibmc() {
 
 testPython2() {
   compile "python2"
-  assertCaptured "python-2.7.13"
+  assertCaptured "python-2.7.14"
   assertCapturedSuccess
 }
 
-- 
GitLab