diff --git a/.gitignore b/.gitignore index a0097e73..d0938cd7 100644 --- a/.gitignore +++ b/.gitignore @@ -26,10 +26,7 @@ build/ *.bak0 *.bak1 sundials-*.tar.gz -.local/ -.ipython/ -.jupyter/* -!.jupyter/jupyter_notebook_config.py +.env/ tmp/ .coverage htmlcov/ diff --git a/README.rst b/README.rst index a16c85af..83f1d2e4 100644 --- a/README.rst +++ b/README.rst @@ -107,13 +107,13 @@ Using Docker If you have `Docker `_ installed, you may use it to host a jupyter notebook server:: - $ ./scripts/host-jupyter-using-docker.sh . 8888 + $ ./scripts/host-env.sh host-notebook --port 8888 the first time you run the command, some dependencies will be downloaded. When the installation is complete there will be a link visible which you can open in your browser. You can also run the test suite using the same docker-image:: - $ ./scripts/host-jupyter-using-docker.sh . 0 + $ ./scripts/host-env.sh run-tests there will be a few skipped test (due to some dependencies not being installed by default) and quite a few warnings. diff --git a/scripts/environment/Dockerfile b/scripts/environment/Containerfile similarity index 100% rename from scripts/environment/Dockerfile rename to scripts/environment/Containerfile diff --git a/scripts/host-env.sh b/scripts/host-env.sh new file mode 100755 index 00000000..370831a7 --- /dev/null +++ b/scripts/host-env.sh @@ -0,0 +1,106 @@ +#!/bin/bash +show_help() { + echo "Usage:" + echo "$(basename $0) host-notebook --port 8888 --listen 127.0.0.1" + echo "$(basename $0) run-tests" +} +HOST_NOTEBOOK=0 +RUN_TESTS=0 +PORT=8000 +while [ $# -gt 0]; do + case "$1" in + host-notebook) + HOST_NOTEBOOK=1 + shift + ;; + --port) + shift + PORT=$1 + shift + ;; + --listen) + shift + LISTEN=$1 + shift + ;; + run-tests) + RUN_TESTS=1 + shift + ;; + --help|-h) + show_help + exit 0 + ;; + --) + break; + *) + show_help + exit 1 + ;; + esac +done + +set -euxo pipefail +if ! which pod-run >/dev/null; then + SOME_TEMP_DIR=$(mktemp -d) + trap 'rm -rf -- "$SOME_TEMP_DIR"' EXIT + ( cd "$SOME_TEMP_DIR"; curl -LOs https://raw.githubusercontent.com/bjodah/dotfiles/master/per-leaf-dir/bin/podrun; chmod +x podrun ) + export PATH="$SOME_TEMP_DIR:$PATH" +fi + +SCRIPTS_DIR=$(dirname $(realpath "$BASH_SOURCE")) +REPO_DIR=$(realpath "$SCRIPTS_DIR/..") +ENV_DIR="$REPO_DIR/.env" +PKG_NAME=${PKG_NAME:-$(basename $REPO_DIR)} + +mkdir -p $ENV_DIR + +cat <$ENV_DIR/setup.sh +if [ ! -d .env/ ]; then + >&2 echo "No .env directory?" + exit 1 +fi +if [ ! -d .env/venv ]; then + python3 -m venv .env/venv +fi +source .env/venv/activate +if ! python -c "import pycvodes" 2>&1 >/dev/null; then + env \ + PYCVODES_NO_LAPACK=1 \ + PYCVODES_NO_KLU=1 \ + LDFLAGS='-Wl,--disable-new-dtags -Wl,-rpath,/usr/local/lib -L/usr/local/lib' \ + python -m pip install --cache-dir .env/pypi-cache -e .[all] +fi +if ! python -c "import pyodesys" 2>&1 >/dev/null; then + pip install --cache-dir .env/pypi-cache -e .[all] + jupyter-nbextension enable --user --py widgetsnbextension +fi +export MPLBACKEND=Agg +EOF + +cat <$ENV_DIR/run-tests.sh +source .env/setup.sh +pytest -sv -ra --pyargs $PKG_NAME +EOF + +cat <$ENV_DIR/host-notebook.sh +source .env/setup.sh +jupyter notebook --no-browser --port $PORT --ip=* index.ipynb +EOF + + +if [ $RUN_TESTS = 1 ]; then + podrun --cont-img-dir $SCRIPTS_DIR/environment \ + --name "${PKG_NAME}_run_tests" \ + --image $DOCKERIMAGE \ + -- $ENV_DIR/run-tests.sh +fi +if [ $HOST_NOTEBOOK = 1 ]; then + podrun --cont-img-dir $SCRIPTS_DIR/environment \ + --name "${PKG_NAME}_host_notebook_${PORT}" \ + --image $DOCKERIMAGE \ + -p $LISTEN:$PORT:$PORT \ + -- $ENV_DIR/host-notebook.sh +fi + + diff --git a/scripts/host-jupyter-using-docker.sh b/scripts/host-jupyter-using-docker.sh deleted file mode 100755 index 6543ac80..00000000 --- a/scripts/host-jupyter-using-docker.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/bash -ue -# -# This script requires that Docker (or podman) is installed. -# -# Arguments: mount-path, port-number, Dockerfile-path -# -# To host a local jupyter notebook server rung e.g.: -# -# $ ./scripts/host-jupyter-using-docker.sh -# $ ./scripts/host-jupyter-using-docker.sh . 8888 ./scripts/environment -# -# To instead run the test suite, specify "0" as the port number: -# -# $ ./scripts/host-jupyter-using-docker.sh . 0 ./scripts/environment -# -MOUNT=${1:-.} -PORT=${2:-8888} -DOCKERIMAGE=${3:-./scripts/environment} -PKG=$(find . -maxdepth 2 -name __init__.py -print0 | xargs -0 -n1 dirname | xargs basename) -HOST_USER=${SUDO_USER:-${LOGNAME}} -if [[ "${HOST_USER}" == root ]]; then - >&2 echo "Need another user name than root (pip will fail)" - exit 1 -fi - -if which podman; then - PODMAN=podman -elif which docker; then - if groups | grep docker; then - PODMAN=docker - else - PODMAN="sudo docker" - fi -else - >&2 echo "Neither podman nor docker found on \$PATH" - exit 1 -fi - -if [[ "$MOUNT" == .* ]]; then - MOUNT="$(pwd)/$MOUNT" -fi - - -if [[ "$DOCKERIMAGE" == ./* ]]; then - DOCKERIMAGE=$($PODMAN build $DOCKERIMAGE | tee /dev/tty | tail -1 | cut -d' ' -f3) -fi -if [[ "$PORT" == "0" ]]; then - LOCALCMD="pytest -sv -ra --pyargs $PKG" - PORTFWD="" -else - LOCALCMD="jupyter notebook --no-browser --port $PORT --ip=* index.ipynb" - PORTFWD="-p ${4:-127.0.0.1}:$PORT:$PORT" -fi -MYCMD="\ -groupadd -f --gid \$HOST_GID \$HOST_WHOAMI; \ -useradd --uid \$HOST_UID --gid \$HOST_GID --home /mount/.env \$HOST_WHOAMI; \ -sudo -u \$HOST_WHOAMI PYCVODES_NO_LAPACK=1 PYCVODES_NO_KLU=1 python3 -m pip install --cache-dir /mount/.env/pypi-cache --user -e .[all]; \ -sudo -u \$HOST_WHOAMI /mount/.env/.local/bin/jupyter-nbextension enable --user --py widgetsnbextension; \ -sudo -u \$HOST_WHOAMI LD_LIBRARY_PATH=/usr/local/lib MPLBACKEND=Agg PYTHONPATH=/mount /mount/.env/.local/bin/$LOCALCMD" - -set -x - -mkdir -m 777 -p .env - -$PODMAN run \ - --rm \ - --name "${PKG}_nb_${PORT}" $PORTFWD \ - -e HOST_WHOAMI=${HOST_USER} \ - -e HOST_UID=$(id -u ${HOST_USER}) \ - -e HOST_GID=$(id -g ${HOST_USER}) \ - -v $MOUNT:/mount -w /mount -it $DOCKERIMAGE /bin/bash -x -c "$MYCMD" diff --git a/setup.py b/setup.py index 06dc181d..84529cc3 100755 --- a/setup.py +++ b/setup.py @@ -100,7 +100,7 @@ def _path_under_setup(*args): _author, _author_email = open(_path_under_setup("AUTHORS"), "rt").readline().split("<") extras_req = { - "integrators": ["pyodeint>=0.10.4", "pycvodes>=0.14.0", "pygslodeiv2>=0.9.4"], + "integrators": ["pyodeint>=0.10.4", "pycvodes>=0.14.5", "pygslodeiv2>=0.9.4"], "solvers": ["pykinsol>=0.1.6"], "native": ["pycompilation>=0.4.12", "pycodeexport>=0.1.3", "appdirs"], "docs": ["Sphinx", "sphinx_rtd_theme", "numpydoc"],