fixing conflict

pull/300/head
J. Forde 2018-06-26 15:54:31 -07:00
commit e1d47df30e
28 zmienionych plików z 251 dodań i 465 usunięć

Wyświetl plik

@ -16,7 +16,11 @@ install:
script:
# cd into tests so CWD being repo2docker does not hide
# possible issues with MANIFEST.in
- cd tests && travis_retry pytest --cov repo2docker -v ${REPO_TYPE}
- if [ ${REPO_TYPE} == "r" ];
then cd tests && travis_wait pytest --cov repo2docker -v ${REPO_TYPE};
else cd tests && travis_retry pytest --cov repo2docker -v ${REPO_TYPE};
fi
after_success:
- pip install codecov
- codecov

Wyświetl plik

@ -9,6 +9,19 @@ If you have a question & have found an answer, send a PR to add it here!
Currently the best way to do this is by using a conda ``environment.yml``
file and setting the language to whichever version of Python you like.
## Can I add executable files to the user's PATH?
Yes! Using a ``postBuild`` file, you can place any files that should be called
from the command line in the folder ``~/.local/``. This folder will be
available in a user's PATH, and can be run from the command line (or as
a subsequent build step.)
## How do I set environment variables?
Use the `-e` or `--env` flag for each variable that you want to define.
For example `jupyter-repo2docker -e VAR1=val1 -e VAR2=val2 ...`
## Can I use repo2docker to bootstrap my own Dockerfile?
No, you can't.
@ -24,9 +37,3 @@ or similar traditional docker command.
Check out the [binder-examples](http://github.com/binder-examples/) github
organization for example Dockerfiles you can copy & modify for your own use!
## How do I set environment variables?
Use the `-e` or `--env` flag for each variable that you want to define.
For example `jupyter-repo2docker -e VAR1=val1 -e VAR2=val2 ...`

Wyświetl plik

@ -5,6 +5,11 @@ jupyter-repo2docker
images from source code repositories. See the list below for various
ways in which you can use ``repo2docker``.
Please report `Bugs <https://github.com/jupyter/repo2docker/issues>`_,
`ask questions <https://gitter.im/jupyterhub/binder>`_ or
`contribute to the project <https://github.com/jupyter/repo2docker/blob/master/CONTRIBUTING.md>`_.
Site Contents
-------------
.. toctree::
@ -17,4 +22,3 @@ Site Contents
design
architecture
dev_newbuildpack

Wyświetl plik

@ -29,7 +29,7 @@ from traitlets.config import Application
from . import __version__
from .buildpacks import (
PythonBuildPack, DockerBuildPack, LegacyBinderDockerBuildPack,
CondaBuildPack, JuliaBuildPack, Python2BuildPack, BaseImage,
CondaBuildPack, JuliaBuildPack, BaseImage,
RBuildPack
)
from .utils import (
@ -66,9 +66,8 @@ class Repo2Docker(Application):
LegacyBinderDockerBuildPack,
DockerBuildPack,
JuliaBuildPack,
CondaBuildPack,
Python2BuildPack,
RBuildPack,
CondaBuildPack,
PythonBuildPack,
],
config=True,

Wyświetl plik

@ -1,5 +1,5 @@
from .base import BuildPack, BaseImage
from .python import Python2BuildPack, PythonBuildPack
from .python import PythonBuildPack
from .conda import CondaBuildPack
from .julia import JuliaBuildPack
from .docker import DockerBuildPack

Wyświetl plik

@ -9,7 +9,10 @@ import docker
import sys
TEMPLATE = r"""
FROM buildpack-deps:artful
FROM buildpack-deps:bionic
# avoid prompts from apt
ENV DEBIAN_FRONTEND=noninteractive
# Set up locales properly
RUN apt-get update && \
@ -198,7 +201,10 @@ class BuildPack:
Just sets the PATH environment variable. Separated out since
it is very commonly set by various buildpacks.
"""
return []
# Allow local user installs into ~/.local, which is where the
# XDG desktop standard suggests these should be
# See https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
return ['$HOME/.local/bin']
def get_labels(self):
"""

Wyświetl plik

@ -25,17 +25,26 @@ class CondaBuildPack(BaseImage):
the `NB_PYTHON_PREFIX` to the location of the jupyter binary.
"""
return super().get_env() + [
env = super().get_env() + [
('CONDA_DIR', '${APP_BASE}/conda'),
('NB_PYTHON_PREFIX', '${CONDA_DIR}'),
]
if self.py2:
env.append(('KERNEL_PYTHON_PREFIX', '${CONDA_DIR}/envs/kernel'))
else:
env.append(('KERNEL_PYTHON_PREFIX', '${NB_PYTHON_PREFIX}'))
return env
def get_path(self):
"""Return paths (including conda environment path) to be added to
the PATH environment variable.
"""
return super().get_path() + ['${CONDA_DIR}/bin']
path = super().get_path()
if self.py2:
path.insert(0, '${KERNEL_PYTHON_PREFIX}/bin')
path.insert(0, '${CONDA_DIR}/bin')
return path
def get_build_scripts(self):
"""
@ -127,6 +136,12 @@ class CondaBuildPack(BaseImage):
py_version = None
with open(environment_yml) as f:
env = YAML().load(f)
# check if the env file is empty, if so instantiate an empty dictionary.
if env is None:
env = {}
# check if the env file has a dictionary not a list or other data structure.
if not isinstance(env, dict):
raise TypeError("environment.yml should contain a dictionary. Got %r" % type(env))
for dep in env.get('dependencies', []):
if not isinstance(dep, str):
continue

Wyświetl plik

@ -1,23 +1,24 @@
# AUTO GENERATED FROM environment.py-3.6.yml, DO NOT MANUALLY MODIFY
# Frozen on 2018-04-02 07:27:43 UTC
# Frozen on 2018-05-08 20:22:20 UTC
name: r2d
channels:
- conda-forge
- defaults
- conda-forge/label/broken
dependencies:
- backcall=0.1.0=py_0
- bleach=2.1.3=py_0
- ca-certificates=2018.1.18=0
- certifi=2018.1.18=py36_0
- decorator=4.2.1=py36_0
- ca-certificates=2018.4.16=0
- certifi=2018.4.16=py36_0
- decorator=4.3.0=py_0
- entrypoints=0.2.3=py36_1
- gmp=6.1.2=0
- html5lib=1.0.1=py_0
- ipykernel=4.8.2=py36_0
- ipython=6.2.1=py36_1
- ipython=6.3.1=py36_0
- ipython_genutils=0.2.0=py36_0
- ipywidgets=7.1.1=py36_0
- jedi=0.11.1=py36_0
- jedi=0.12.0=py36_0
- jinja2=2.10=py36_0
- jsonschema=2.6.0=py36_1
- jupyter_client=5.2.3=py36_0
@ -26,27 +27,27 @@ dependencies:
- jupyterlab_launcher=0.10.5=py36_0
- libsodium=1.0.16=0
- markupsafe=1.0=py36_0
- mistune=0.8.3=py_0
- mistune=0.8.3=py36_1
- nbconvert=5.3.1=py_1
- nbformat=4.4.0=py36_0
- ncurses=5.9=10
- notebook=5.4.1=py36_0
- openssl=1.0.2n=0
- pandoc=2.1.3=0
- pandocfilters=1.4.1=py36_0
- parso=0.1.1=py_0
- pexpect=4.4.0=py36_0
- openssl=1.0.2o=0
- pandoc=2.2=0
- pandocfilters=1.4.2=py36_0
- parso=0.2.0=py_0
- pexpect=4.5.0=py36_0
- pickleshare=0.7.4=py36_0
- pip=9.0.3=py36_0
- prompt_toolkit=1.0.15=py36_0
- ptyprocess=0.5.2=py36_0
- pygments=2.2.0=py36_0
- python=3.6.5=0
- python=3.6.5=1
- python-dateutil=2.7.2=py_0
- pyzmq=17.0.0=py36_4
- readline=7.0=0
- send2trash=1.5.0=py_0
- setuptools=39.0.1=py36_0
- setuptools=39.1.0=py36_0
- simplegeneric=0.8.1=py36_0
- six=1.11.0=py36_1
- sqlite=3.20.1=2
@ -57,12 +58,12 @@ dependencies:
- traitlets=4.3.2=py36_0
- wcwidth=0.1.7=py36_0
- webencodings=0.5=py36_0
- wheel=0.30.0=py36_2
- widgetsnbextension=3.2.0=py36_0
- wheel=0.31.0=py36_0
- widgetsnbextension=3.2.1=py36_0
- xz=5.2.3=0
- zeromq=4.2.5=1
- zlib=1.2.11=0
- pip:
- nteract-on-jupyter==1.6.0
- nteract-on-jupyter==1.7.0
prefix: /opt/conda/envs/r2d

Wyświetl plik

@ -1,5 +1,5 @@
# AUTO GENERATED FROM environment.py-2.7.yml, DO NOT MANUALLY MODIFY
# Frozen on 2018-04-02 07:21:15 UTC
# Frozen on 2018-05-08 20:15:09 UTC
name: r2d
channels:
- conda-forge
@ -9,31 +9,31 @@ dependencies:
- backports=1.0=py27_1
- backports.shutil_get_terminal_size=1.0.0=py_3
- backports_abc=0.5=py27_0
- ca-certificates=2018.1.18=0
- certifi=2018.1.18=py27_0
- decorator=4.2.1=py27_0
- ca-certificates=2018.4.16=0
- certifi=2018.4.16=py27_0
- decorator=4.3.0=py_0
- enum34=1.1.6=py27_1
- ipykernel=4.8.2=py27_0
- ipython=5.5.0=py27_0
- ipython=5.6.0=py27_0
- ipython_genutils=0.2.0=py27_0
- jupyter_client=5.2.3=py27_0
- jupyter_core=4.4.0=py_0
- libsodium=1.0.16=0
- ncurses=5.9=10
- openssl=1.0.2n=0
- pathlib2=2.3.0=py27_0
- pexpect=4.4.0=py27_0
- openssl=1.0.2o=0
- pathlib2=2.3.2=py27_0
- pexpect=4.5.0=py27_0
- pickleshare=0.7.4=py27_0
- pip=9.0.3=py27_0
- prompt_toolkit=1.0.15=py27_0
- ptyprocess=0.5.2=py27_0
- pygments=2.2.0=py27_0
- python=2.7.14=5
- python=2.7.15=0
- python-dateutil=2.7.2=py_0
- pyzmq=17.0.0=py27_4
- readline=7.0=0
- scandir=1.7=py27_0
- setuptools=39.0.1=py27_0
- setuptools=39.1.0=py27_0
- simplegeneric=0.8.1=py27_0
- singledispatch=3.4.0.3=py27_0
- six=1.11.0=py27_1
@ -43,7 +43,7 @@ dependencies:
- tornado=4.5.3=py27_0
- traitlets=4.3.2=py27_0
- wcwidth=0.1.7=py27_0
- wheel=0.30.0=py27_2
- wheel=0.31.0=py27_0
- zeromq=4.2.5=1
- zlib=1.2.11=0
- pip:

Wyświetl plik

@ -1,23 +1,24 @@
# AUTO GENERATED FROM environment.py-3.5.yml, DO NOT MANUALLY MODIFY
# Frozen on 2018-04-02 07:23:18 UTC
# Frozen on 2018-05-08 20:18:13 UTC
name: r2d
channels:
- conda-forge
- defaults
- conda-forge/label/broken
dependencies:
- backcall=0.1.0=py_0
- bleach=2.1.3=py_0
- ca-certificates=2018.1.18=0
- certifi=2018.1.18=py35_0
- decorator=4.2.1=py35_0
- ca-certificates=2018.4.16=0
- certifi=2018.4.16=py35_0
- decorator=4.3.0=py_0
- entrypoints=0.2.3=py35_1
- gmp=6.1.2=0
- html5lib=1.0.1=py_0
- ipykernel=4.8.2=py35_0
- ipython=6.2.1=py35_1
- ipython=6.3.1=py35_0
- ipython_genutils=0.2.0=py35_0
- ipywidgets=7.1.1=py35_0
- jedi=0.11.1=py35_0
- jedi=0.12.0=py35_0
- jinja2=2.10=py35_0
- jsonschema=2.6.0=py35_1
- jupyter_client=5.2.3=py35_0
@ -26,27 +27,27 @@ dependencies:
- jupyterlab_launcher=0.10.5=py35_0
- libsodium=1.0.16=0
- markupsafe=1.0=py35_0
- mistune=0.8.3=py_0
- mistune=0.8.3=py35_1
- nbconvert=5.3.1=py_1
- nbformat=4.4.0=py35_0
- ncurses=5.9=10
- notebook=5.4.1=py35_0
- openssl=1.0.2n=0
- pandoc=2.1.3=0
- pandocfilters=1.4.1=py35_0
- parso=0.1.1=py_0
- pexpect=4.4.0=py35_0
- openssl=1.0.2o=0
- pandoc=2.2=0
- pandocfilters=1.4.2=py35_0
- parso=0.2.0=py_0
- pexpect=4.5.0=py35_0
- pickleshare=0.7.4=py35_0
- pip=9.0.3=py35_0
- prompt_toolkit=1.0.15=py35_0
- ptyprocess=0.5.2=py35_0
- pygments=2.2.0=py35_0
- python=3.5.5=0
- python=3.5.5=1
- python-dateutil=2.7.2=py_0
- pyzmq=17.0.0=py35_4
- readline=7.0=0
- send2trash=1.5.0=py_0
- setuptools=39.0.1=py35_0
- setuptools=39.1.0=py35_0
- simplegeneric=0.8.1=py35_0
- six=1.11.0=py35_1
- sqlite=3.20.1=2
@ -57,12 +58,12 @@ dependencies:
- traitlets=4.3.2=py35_0
- wcwidth=0.1.7=py35_0
- webencodings=0.5=py35_0
- wheel=0.30.0=py35_2
- widgetsnbextension=3.2.0=py35_0
- wheel=0.31.0=py35_0
- widgetsnbextension=3.2.1=py35_0
- xz=5.2.3=0
- zeromq=4.2.5=1
- zlib=1.2.11=0
- pip:
- nteract-on-jupyter==1.6.0
- nteract-on-jupyter==1.7.0
prefix: /opt/conda/envs/r2d

Wyświetl plik

@ -1,23 +1,24 @@
# AUTO GENERATED FROM environment.py-3.6.yml, DO NOT MANUALLY MODIFY
# Frozen on 2018-04-02 07:27:43 UTC
# Frozen on 2018-05-08 20:22:20 UTC
name: r2d
channels:
- conda-forge
- defaults
- conda-forge/label/broken
dependencies:
- backcall=0.1.0=py_0
- bleach=2.1.3=py_0
- ca-certificates=2018.1.18=0
- certifi=2018.1.18=py36_0
- decorator=4.2.1=py36_0
- ca-certificates=2018.4.16=0
- certifi=2018.4.16=py36_0
- decorator=4.3.0=py_0
- entrypoints=0.2.3=py36_1
- gmp=6.1.2=0
- html5lib=1.0.1=py_0
- ipykernel=4.8.2=py36_0
- ipython=6.2.1=py36_1
- ipython=6.3.1=py36_0
- ipython_genutils=0.2.0=py36_0
- ipywidgets=7.1.1=py36_0
- jedi=0.11.1=py36_0
- jedi=0.12.0=py36_0
- jinja2=2.10=py36_0
- jsonschema=2.6.0=py36_1
- jupyter_client=5.2.3=py36_0
@ -26,27 +27,27 @@ dependencies:
- jupyterlab_launcher=0.10.5=py36_0
- libsodium=1.0.16=0
- markupsafe=1.0=py36_0
- mistune=0.8.3=py_0
- mistune=0.8.3=py36_1
- nbconvert=5.3.1=py_1
- nbformat=4.4.0=py36_0
- ncurses=5.9=10
- notebook=5.4.1=py36_0
- openssl=1.0.2n=0
- pandoc=2.1.3=0
- pandocfilters=1.4.1=py36_0
- parso=0.1.1=py_0
- pexpect=4.4.0=py36_0
- openssl=1.0.2o=0
- pandoc=2.2=0
- pandocfilters=1.4.2=py36_0
- parso=0.2.0=py_0
- pexpect=4.5.0=py36_0
- pickleshare=0.7.4=py36_0
- pip=9.0.3=py36_0
- prompt_toolkit=1.0.15=py36_0
- ptyprocess=0.5.2=py36_0
- pygments=2.2.0=py36_0
- python=3.6.5=0
- python=3.6.5=1
- python-dateutil=2.7.2=py_0
- pyzmq=17.0.0=py36_4
- readline=7.0=0
- send2trash=1.5.0=py_0
- setuptools=39.0.1=py36_0
- setuptools=39.1.0=py36_0
- simplegeneric=0.8.1=py36_0
- six=1.11.0=py36_1
- sqlite=3.20.1=2
@ -57,12 +58,12 @@ dependencies:
- traitlets=4.3.2=py36_0
- wcwidth=0.1.7=py36_0
- webencodings=0.5=py36_0
- wheel=0.30.0=py36_2
- widgetsnbextension=3.2.0=py36_0
- wheel=0.31.0=py36_0
- widgetsnbextension=3.2.1=py36_0
- xz=5.2.3=0
- zeromq=4.2.5=1
- zlib=1.2.11=0
- pip:
- nteract-on-jupyter==1.6.0
- nteract-on-jupyter==1.7.0
prefix: /opt/conda/envs/r2d

Wyświetl plik

@ -5,4 +5,4 @@ dependencies:
- tornado==4.5.3
- notebook==5.4.1
- pip:
- nteract_on_jupyter==1.6.0
- nteract_on_jupyter==1.7.0

Wyświetl plik

@ -3,7 +3,7 @@
set -ex
cd $(dirname $0)
CONDA_VERSION=4.3.30
CONDA_VERSION=4.5.1
URL="https://repo.continuum.io/miniconda/Miniconda3-${CONDA_VERSION}-Linux-x86_64.sh"
INSTALLER_PATH=/tmp/miniconda-installer.sh
@ -12,7 +12,7 @@ chmod +x ${INSTALLER_PATH}
# Only MD5 checksums are available for miniconda
# Can be obtained from https://repo.continuum.io/miniconda/
MD5SUM="0b80a152332a4ce5250f3c09589c7a81"
MD5SUM="0c28787e3126238df24c5d4858bd0744"
if ! echo "${MD5SUM} ${INSTALLER_PATH}" | md5sum --quiet -c -; then
echo "md5sum mismatch for ${INSTALLER_PATH}, exiting!"

Wyświetl plik

@ -23,7 +23,7 @@ class LegacyBinderDockerBuildPack(DockerBuildPack):
RUN conda install -yq conda>=4.3 && \
conda install -yq conda==4.4.11 && \
conda env update -n python3 -f /tmp/python3.frozen.yml && \
conda remove -yq -n python3 nb_conda_kernels && \
conda remove -yq -n python3 nb_conda_kernels _nb_ext_conf && \
conda env update -n root -f /tmp/root.frozen.yml && \
/home/main/anaconda2/envs/python3/bin/ipython kernel install --sys-prefix && \
/home/main/anaconda2/bin/ipython kernel install --prefix=/home/main/anaconda2/envs/python3 && \

Wyświetl plik

@ -1,139 +1,70 @@
"""Generates Dockerfiles based on an input matrix based on Python."""
import os
from ..base import BaseImage
from ..conda import CondaBuildPack
class PythonBuildPack(BaseImage):
"""Setup Python 3 for use with a repository."""
def get_packages(self):
"""Return a list of the Python 3 core language packages to be installed
via apt-get for this BuildPack.
class PythonBuildPack(CondaBuildPack):
"""Setup Python for use with a repository."""
Note: The packages specified here are for the core Python3 language.
Third party libraries are specified in other configuration files.
@property
def python_version(self):
if hasattr(self, '_python_version'):
return self._python_version
"""
return super().get_packages().union({
'python3',
'python3-venv',
'python3-dev',
})
try:
with open(self.binder_path('runtime.txt')) as f:
runtime = f.read().strip()
except FileNotFoundError:
runtime = ''
def get_env(self):
"""
Return environment variables to be set.
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
We set `VENV_PATH` to the virtual environment location and
the `NB_PYTHON_PREFIX` to the location of the jupyter binary.
"""
return super().get_env() + [
("VENV_PATH", "${APP_BASE}/venv"),
# Prefix to use for installing kernels and finding jupyter binary
("NB_PYTHON_PREFIX", "${VENV_PATH}"),
]
def get_path(self):
"""Return paths (including virtual environment path) to be added to
the PATH environment variable.
"""
return super().get_path() + [
"${VENV_PATH}/bin"
]
def get_build_script_files(self):
"""
Dict of files to be copied to the container image for use in building.
This is copied before the `build_scripts` & `assemble_scripts` are
run, so can be executed from either of them.
It's a dictionary where the key is the source file path in the host
system, and the value is the destination file path inside the
container image.
This currently adds a frozen set of Python 3 requirements to the dict
of files.
"""
files = {
'python/requirements.frozen.txt': '/tmp/requirements.frozen.txt',
}
files.update(super().get_build_script_files())
return files
def get_build_scripts(self):
"""
Return series of build-steps common to all Python 3 repositories.
All scripts here should be independent of contents of the repository.
This sets up:
- a directory for the virtual environment and its ownership by the
notebook user
- a Python 3 interpreter for the virtual environement
- a Python 3 jupyter kernel including a base set of requirements
- support for Jupyter widgets
- support for JupyterLab
- support for nteract
"""
return super().get_build_scripts() + [
(
"root",
r"""
mkdir -p ${VENV_PATH} && \
chown -R ${NB_USER}:${NB_USER} ${VENV_PATH}
"""
),
(
"${NB_USER}",
r"""
python3 -m venv ${VENV_PATH}
"""
),
(
"${NB_USER}",
r"""
pip install --no-cache-dir -r /tmp/requirements.frozen.txt && \
jupyter nbextension enable --py widgetsnbextension --sys-prefix && \
jupyter serverextension enable --py jupyterlab --sys-prefix && \
jupyter serverextension enable nteract_on_jupyter --sys-prefix
"""
)
]
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.
"""
# If we have a runtime.txt & that's set to python-2.7,
# we will *not* install requirements.txt but will find &
# install a requirements3.txt file if it exists.
# This way, when using python2 venv, requirements.txt will
# be installed in the python2 venv, and requirements3.txt
# will be installed in python3 venv. This is less of a
# surprise than requiring python2 to be requirements2.txt tho.
# requirements.txt will be installed in the *kernel* env
# 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'
try:
with open(self.binder_path('runtime.txt')) as f:
runtime = f.read().strip()
except FileNotFoundError:
runtime = 'python-3.5'
if runtime == 'python-2.7':
pip = "pip2"
requirements_file = self.binder_path('requirements3.txt')
else:
pip = "pip3"
requirements_file = self.binder_path('requirements.txt')
# 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
nb_requirements_file = self.binder_path('requirements3.txt')
if os.path.exists(nb_requirements_file):
assemble_scripts.append((
'${NB_USER}',
'${NB_PYTHON_PREFIX}/bin/pip install --no-cache-dir -r "{}"'.format(nb_requirements_file)
))
# install requirements.txt in the kernel env
requirements_file = self.binder_path('requirements.txt')
if os.path.exists(requirements_file):
assemble_scripts.append((
'${NB_USER}',
'pip3 install --no-cache-dir -r "{}"'.format(requirements_file)
'{} 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):
assemble_scripts.append((
'${NB_USER}',
@ -142,7 +73,7 @@ class PythonBuildPack(BaseImage):
return assemble_scripts
def detect(self):
"""Check if current repo should be built with the Python 3 Build pack.
"""Check if current repo should be built with the Python buildpack.
"""
requirements_txt = self.binder_path('requirements.txt')
runtime_txt = self.binder_path('runtime.txt')
@ -151,136 +82,10 @@ class PythonBuildPack(BaseImage):
if os.path.exists(runtime_txt):
with open(runtime_txt) as f:
runtime = f.read().strip()
if runtime.startswith("python-3"):
if runtime.startswith("python-"):
return True
else:
return False
if not os.path.exists('binder') and os.path.exists(setup_py):
return True
return os.path.exists(requirements_txt)
class Python2BuildPack(PythonBuildPack):
"""Setup Python 2 for use with a repository."""
def get_packages(self):
"""Return a list of the Python 2 core language packages to be installed
via apt-get for this BuildPack.
Note: The packages specified here are for the core Python2 language.
Third party libraries are specified in other configuration files.
"""
return super().get_packages().union({
'python',
'python-dev',
'virtualenv'
})
def get_env(self):
"""
Return environment variables to be set.
We set `VENV_PATH` to the virtual environment location containing
Python 2.
"""
return super().get_env() + [
('VENV2_PATH', '${APP_BASE}/venv2')
]
def get_path(self):
"""Return paths (including virtual environment path) to be added to
the PATH environment variable.
"""
return super().get_path() + [
"${VENV2_PATH}/bin"
]
def get_build_script_files(self):
"""
Dict of files to be copied to the container image for use in building.
This is copied before the `build_scripts` & `assemble_scripts` are
run, so can be executed from either of them.
It's a dictionary where the key is the source file path in the host
system, and the value is the destination file path inside the
container image.
This currently adds a frozen set of Python 2 requirements to the dict
of files.
"""
files = {
'python/requirements2.frozen.txt': '/tmp/requirements2.frozen.txt',
}
files.update(super().get_build_script_files())
return files
def get_build_scripts(self):
"""
Return series of build-steps common to all Python 2 repositories.
All scripts here should be independent of contents of the repository.
This sets up:
- a directory for the virtual environment and its ownership by the
notebook user
- a Python 2 interpreter for the virtual environement
- a Python 2 jupyter kernel
"""
return super().get_build_scripts() + [
(
"root",
r"""
mkdir -p ${VENV2_PATH} && \
chown -R ${NB_USER}:${NB_USER} ${VENV2_PATH}
"""
),
(
"${NB_USER}",
r"""
virtualenv -p python2 ${VENV2_PATH}
"""
),
(
"${NB_USER}",
r"""
pip2 install --no-cache-dir -r /tmp/requirements2.frozen.txt && \
python2 -m ipykernel install --prefix=${NB_PYTHON_PREFIX}
"""
)
]
def get_assemble_scripts(self):
"""Return series of build-steps specific to this repository.
"""
requirements_txt = self.binder_path('requirements.txt')
assemble_scripts = super().get_assemble_scripts()
if os.path.exists(requirements_txt):
assemble_scripts.insert(0, (
'${NB_USER}',
'pip2 install --no-cache-dir -r "{}"'.format(requirements_txt)
))
return assemble_scripts
def detect(self):
"""Check if current repo should be built with the Python 2 Build pack.
"""
runtime_txt = self.binder_path('runtime.txt')
if os.path.exists(runtime_txt):
with open(runtime_txt) as f:
runtime = f.read().strip()
if runtime == 'python-2.7':
return True
elif runtime.startswith('python-2'):
raise ValueError(
"Only python-2.7 or python-3.x is supported in "
"runtime.txt, not '{}'".format(runtime_txt))
else:
return False
return False

Wyświetl plik

@ -1,39 +0,0 @@
#!/bin/bash
set -euo pipefail
# Freeze requirements.txt into requirements.frozen.txt, pinning all dependent library versions to
# versions that are resolved at time of freezing.
# Does the same for requirements2.txt to requirements2.frozen.txt...
# cd to the directory where the freeze script is located
if [[ ! -z "$(which realpath 2>/dev/null)" ]]; then
realpath=realpath
else
realpath="readlink -f"
fi
cd $(dirname "$($realpath "$0")")
function freeze-requirements {
# Freeze a requirements file $2 into a frozen requirements file $3
# Requires that a completely empty venv of appropriate version exist in $1
PYTHON_VERSION="$1"
REQUIREMENTS_FILE="$2"
FROZEN_FILE="$3"
if [[ $(echo ${PYTHON_VERSION} | cut -d. -f 1) == "2" ]]; then
VENV=virtualenv
else
VENV=venv
fi
echo "# AUTO GENERATED FROM ${REQUIREMENTS_FILE}, DO NOT MANUALLY MODIFY" > ${FROZEN_FILE}
echo "# Frozen on $(date -u)" >> ${FROZEN_FILE}
docker run --rm -v $PWD:/python -it python:${PYTHON_VERSION} \
sh -c "
python -m $VENV /venv
/venv/bin/pip install -r /python/${REQUIREMENTS_FILE} &&
/venv/bin/pip freeze | sort --ignore-case >> /python/${FROZEN_FILE}"
}
freeze-requirements 3.5 requirements.txt requirements.frozen.txt
freeze-requirements 2.7 requirements2.txt requirements2.frozen.txt

Wyświetl plik

@ -1,42 +0,0 @@
# AUTO GENERATED FROM requirements.txt, DO NOT MANUALLY MODIFY
# Frozen on Mon Apr 2 07:17:48 UTC 2018
bleach==2.1.3
decorator==4.2.1
entrypoints==0.2.3
html5lib==1.0.1
ipykernel==4.8.2
ipython-genutils==0.2.0
ipython==6.2.1
ipywidgets==7.1.1
jedi==0.11.1
Jinja2==2.10
jsonschema==2.6.0
jupyter-client==5.2.3
jupyter-core==4.4.0
jupyterlab-launcher==0.10.5
jupyterlab==0.31.5
MarkupSafe==1.0
mistune==0.8.3
nbconvert==5.3.1
nbformat==4.4.0
notebook==5.4.1
nteract-on-jupyter==1.6.0
pandocfilters==1.4.2
parso==0.1.1
pexpect==4.4.0
pickleshare==0.7.4
prompt-toolkit==1.0.15
ptyprocess==0.5.2
Pygments==2.2.0
python-dateutil==2.7.2
pyzmq==17.0.0
Send2Trash==1.5.0
simplegeneric==0.8.1
six==1.11.0
terminado==0.8.1
testpath==0.3.1
tornado==4.5.3
traitlets==4.3.2
wcwidth==0.1.7
webencodings==0.5.1
widgetsnbextension==3.1.4

Wyświetl plik

@ -1,5 +0,0 @@
notebook==5.4.1
tornado==4.5.3
ipywidgets==7.1.1
jupyterlab==0.31.5
nteract_on_jupyter==1.6.0

Wyświetl plik

@ -1,27 +0,0 @@
# AUTO GENERATED FROM requirements2.txt, DO NOT MANUALLY MODIFY
# Frozen on Mon Apr 2 07:19:00 UTC 2018
backports-abc==0.5
backports.shutil-get-terminal-size==1.0.0
certifi==2018.1.18
decorator==4.2.1
enum34==1.1.6
ipykernel==4.8.2
ipython-genutils==0.2.0
ipython==5.5.0
jupyter-client==5.2.3
jupyter-core==4.4.0
pathlib2==2.3.0
pexpect==4.4.0
pickleshare==0.7.4
prompt-toolkit==1.0.15
ptyprocess==0.5.2
Pygments==2.2.0
python-dateutil==2.7.2
pyzmq==17.0.0
scandir==1.7
simplegeneric==0.8.1
singledispatch==3.4.0.3
six==1.11.0
tornado==4.5.3
traitlets==4.3.2
wcwidth==0.1.7

Wyświetl plik

@ -1,2 +0,0 @@
ipykernel==4.8.2
tornado==4.5.3

Wyświetl plik

@ -4,6 +4,7 @@ import datetime
from .python import PythonBuildPack
class RBuildPack(PythonBuildPack):
"""
Setup R for use with a repository
@ -128,6 +129,10 @@ class RBuildPack(PythonBuildPack):
# This is MD5, because that is what RStudio download page provides!
rstudio_checksum = '24cd11f0405d8372b4168fc9956e0386'
# Via https://www.rstudio.com/products/shiny/download-server/
shiny_url = 'https://download3.rstudio.org/ubuntu-14.04/x86_64/shiny-server-1.5.7.907-amd64.deb'
shiny_checksum = '78371a8361ba0e7fec44edd2b8e425ac'
# Version of MRAN to pull devtools from.
devtools_version = '2018-02-01'
@ -155,6 +160,20 @@ class RBuildPack(PythonBuildPack):
rstudio_checksum=rstudio_checksum
)
),
(
"root",
# Install Shiny Server!
r"""
curl --silent --location --fail {url} > {deb} && \
echo '{checksum} {deb}' | md5sum -c - && \
dpkg -i {deb} && \
rm {deb}
""".format(
url=shiny_url,
checksum=shiny_checksum,
deb='/tmp/shiny.deb'
)
),
(
"root",
# Set paths so that RStudio shares libraries with base R
@ -169,7 +188,7 @@ class RBuildPack(PythonBuildPack):
"${NB_USER}",
# Install nbrsessionproxy
r"""
pip install --no-cache-dir nbrsessionproxy==0.6.1 && \
pip install --no-cache-dir nbrsessionproxy==0.7.0 && \
jupyter serverextension enable nbrsessionproxy --sys-prefix && \
jupyter nbextension install --py nbrsessionproxy --sys-prefix && \
jupyter nbextension enable --py nbrsessionproxy --sys-prefix
@ -186,7 +205,16 @@ class RBuildPack(PythonBuildPack):
devtools_version=devtools_version,
irkernel_version=irkernel_version
)
)
),
(
"${NB_USER}",
# Install shiny library
r"""
R --quiet -e "install.packages('shiny', repos='https://mran.microsoft.com/snapshot/{}', method='libcurl')"
""".format(
self.checkpoint_date.isoformat()
)
),
]
def get_assemble_scripts(self):
@ -208,6 +236,16 @@ class RBuildPack(PythonBuildPack):
echo "options(repos = c(CRAN='{mran_url}'), download.file.method = 'libcurl')" > /etc/R/Rprofile.site
""".format(mran_url=mran_url)
),
(
# Not all of these locations are configurable; log_dir is
"root",
r"""
install -o ${NB_USER} -g ${NB_USER} -d /var/log/shiny-server && \
install -o ${NB_USER} -g ${NB_USER} -d /var/lib/shiny-server && \
install -o ${NB_USER} -g ${NB_USER} /dev/null /var/log/shiny-server.log && \
install -o ${NB_USER} -g ${NB_USER} /dev/null /var/run/shiny-server.pid
"""
),
]
installR_path = self.binder_path('install.R')

Wyświetl plik

@ -1,2 +1,5 @@
[wheel]
universal=1
universal=1
[metadata]
license_file = LICENSE

Wyświetl plik

@ -13,7 +13,7 @@ assert sorted(specs) == ['python2', 'python3'], specs.keys()
import json
from subprocess import check_output
envs = json.loads(check_output(['conda', 'env', 'list', '--json']).decode('utf8'))
assert envs == {'envs': ['/srv/conda/envs/kernel']}, envs
assert envs == {'envs': ['/srv/conda', '/srv/conda/envs/kernel']}, envs
pkgs = json.loads(check_output(['conda', 'list', '-n', 'kernel', '--json']).decode('utf8'))
pkg_names = [pkg['name'] for pkg in pkgs]

Wyświetl plik

@ -0,0 +1,26 @@
"""
Test if the environment.yml is empty or it constains other data structure than a dictionary
"""
import os
import sys
import pytest
from repo2docker import buildpacks
def test_empty_env_yml(tmpdir):
tmpdir.chdir()
p = tmpdir.join("environment.yml")
p.write("")
bp = buildpacks.CondaBuildPack()
py_ver = bp.python_version
# If the environment.yml is empty python_version will get an empty string
assert py_ver == ''
def test_no_dict_env_yml(tmpdir):
tmpdir.chdir()
q = tmpdir.join("environment.yml")
q.write("numpy\n "
"matplotlib\n")
bq = buildpacks.CondaBuildPack()
with pytest.raises(TypeError):
py_ver = bq.python_version

Wyświetl plik

@ -1,20 +0,0 @@
System - Specifying runtime environments
----------------------------------------
You can specify runtime environments (such as Python 2 or 3) with a
``runtime.txt`` file. To do so, include a line of the following form in
your ``runtime.txt`` file:
```
python-N
```
Where ``N`` is either ``2`` or ``3``. If ``N==2``, Python 2.7 will be used.
If ``N==3``, Python 3.6 will be used.
This is an example that selects Python 3. Currently you can not use
this to select a specific version of Python 3 (e.g. 3.4 vs 3.6). If you
need this level of control we recommend you use a `environment.yml`.
Note that you can also install Python environments using the Anaconda
distribution by using an ``environment.yml`` file.

Wyświetl plik

@ -0,0 +1 @@
python-3.5

Wyświetl plik

@ -0,0 +1,5 @@
#!/usr/bin/env python3
import sys
print(sys.version_info)
assert sys.version_info[:2] == (3, 5), sys.version

Wyświetl plik

@ -0,0 +1,5 @@
#!/usr/bin/env python
# Verify that ~/.local/bin is on the PATH
import os
assert os.path.expanduser('~/.local/bin') in os.getenv("PATH"), os.getenv("PATH")