extract pipfile: reset PythonBuildPack
MODIFY
repo2docker/buildpacks/python/__init__.py
repo2docker/buildpacks/python/__init__.py
"""Generates Dockerfiles based on an input matrix based on Python."""
import os
-import re
from ..conda import CondaBuildPack
+
class PythonBuildPack(CondaBuildPack):
"""Setup Python for use with a repository."""
@property
def python_version(self):
- """
- Detect the Python version declared in a `Pipfile.lock`, `Pipfile`, or
- `runtime.txt`. Will return 'x.y' if version is found (e.g '3.6'), or a
- Falsy empty string '' if not found.
- """
-
if hasattr(self, '_python_version'):
return self._python_version
- files_to_search_in_order = [
- {
- 'path': self.binder_path('Pipfile.lock'),
- 'pattern': r'\s*\"python_(?:full_)?version\": \"?([0-9a-z\.]*)\"?', # ' "python_version": "3.6"'
- },
- {
- 'path': self.binder_path('Pipfile'),
- 'pattern': r'python_(?:full_)?version\s*=+\s*\"?([0-9a-z\.]*)\"?', # 'python_version = "3.6"'
- },
- {
- 'path': self.binder_path('runtime.txt'),
- 'pattern': r'\s*python-([0-9a-z\.]*)\s*', # 'python-3.6'
- },
- ]
-
- py_version = None
- for file in files_to_search_in_order:
try:
- with open(file['path']) as f:
- for line in f:
- match = re.match(file['pattern'], line)
- if not match:
- continue
- py_version = match.group(1)
- break
+ with open(self.binder_path('runtime.txt')) as f:
+ runtime = f.read().strip()
except FileNotFoundError:
- pass
- if py_version:
- break
+ runtime = ''
- # extract major.minor
- if py_version:
- if len(py_version) == 1:
- self._python_version = self.major_pythons.get(py_version[0])
- else:
- # return major.minor
- self._python_version = '.'.join(py_version.split('.')[:2])
- return self._python_version
- else:
+ if not runtime.startswith('python-'):
+ # not a Python runtime (e.g. R, which subclasses this)
# use the default Python
self._python_version = self.major_pythons['3']
return self._python_version
+ py_version_info = runtime.split('-', 1)[1].split('.')
+ py_version = ''
+ if len(py_version_info) == 1:
+ py_version = self.major_pythons[py_version_info[0]]
+ else:
+ # get major.minor
+ py_version = '.'.join(py_version_info[:2])
+ self._python_version = py_version
+ return self._python_version
+
def get_assemble_scripts(self):
"""Return series of build-steps specific to this repository.
"""
@@ -69,7 +42,10 @@ class PythonBuildPack(CondaBuildPack):
# and requirements3.txt (if it exists)
# will be installed in the python 3 notebook server env.
assemble_scripts = super().get_assemble_scripts()
-
+ setup_py = 'setup.py'
+ # KERNEL_PYTHON_PREFIX is the env with the kernel,
+ # whether it's distinct from the notebook or the same.
+ pip = '${KERNEL_PYTHON_PREFIX}/bin/pip'
if self.py2:
# using python 2 kernel,
# requirements3.txt allows installation in the notebook server env
@@ -82,51 +58,25 @@ class PythonBuildPack(CondaBuildPack):
'${{NB_PYTHON_PREFIX}}/bin/pip install --no-cache-dir -r "{}"'.format(nb_requirements_file)
))
- # install Pipfile.lock, Pipfile, or requirements.txt in the kernel env
- pipenv = '${KERNEL_PYTHON_PREFIX}/bin/pipenv'
- pipfile = self.binder_path('Pipfile')
- pipfile_lock = self.binder_path('Pipfile.lock')
- if os.path.exists(pipfile_lock) or os.path.exists(pipfile):
- working_directory = 'binder' if os.path.exists('binder') else '.'
- assemble_scripts.append((
- '${NB_USER}',
- 'pip install pipenv'
- ))
- if not os.path.exists(pipfile_lock):
- assemble_scripts.append((
- '${NB_USER}',
- '(cd {} && {} lock --python {})'.format(working_directory, pipenv, '${KERNEL_PYTHON_PREFIX}/bin/python')
- ))
- assemble_scripts.append((
- '${NB_USER}',
- '(cd {} && {} install --ignore-pipfile --deploy --system --dev --python {})'.format(working_directory, pipenv, '${KERNEL_PYTHON_PREFIX}/bin/python')
- ))
- else:
- # KERNEL_PYTHON_PREFIX is the env with the kernel,
- # whether it's distinct from the notebook or the same.
- pip = '${KERNEL_PYTHON_PREFIX}/bin/pip'
+ # install requirements.txt in the kernel env
requirements_file = self.binder_path('requirements.txt')
- setup_py = 'setup.py'
if os.path.exists(requirements_file):
assemble_scripts.append((
'${NB_USER}',
- 'pip install "pip<19" && ' + \
'{} install --no-cache-dir -r "{}"'.format(pip, requirements_file)
))
+
# setup.py exists *and* binder dir is not used
- if not os.path.exists('binder') and os.path.exists(setup_py):
+ if not self.binder_dir and os.path.exists(setup_py):
assemble_scripts.append((
'${NB_USER}',
'{} install --no-cache-dir .'.format(pip)
))
-
return assemble_scripts
def detect(self):
"""Check if current repo should be built with the Python buildpack.
"""
- pipfile = self.binder_path('Pipfile')
- pipfile_lock = self.binder_path('Pipfile.lock')
requirements_txt = self.binder_path('requirements.txt')
runtime_txt = self.binder_path('runtime.txt')
setup_py = 'setup.py'
@@ -138,6 +88,6 @@ class PythonBuildPack(CondaBuildPack):
return True
else:
return False
- if not os.path.exists('binder') and os.path.exists(setup_py):
+ if not self.binder_dir and os.path.exists(setup_py):
return True
- return os.path.exists(pipfile) or os.path.exists(pipfile_lock) or os.path.exists(requirements_txt)
+ return os.path.exists(requirements_txt)

extract pipfile: reset PythonBuildPack