diff --git a/Dockerfile b/Dockerfile index 5ca8096..1dc45d4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,17 +25,13 @@ COPY requirements.txt ./ # Copy the full source (needed for editable install) COPY rcpchgrowth rcpchgrowth -# Upgrade pip/setuptools/wheel first -RUN pip install --upgrade pip setuptools wheel - -# Install runtime + notebook deps first (ensures wheels pulled before editable wiring) -RUN pip install python-dateutil scipy pandas matplotlib jupyterlab ipykernel - -# Install dev/test tools -RUN pip install -r requirements.txt - -# Finally perform editable install (should be fast now; minimal build isolation work) -RUN pip install -e . || (echo '--- Editable install failed; running pip debug ---' && python -m pip debug && exit 1) +# Upgrade build tooling, install the package (with notebook extras) editable, +# and install dev/test deps. Notebook extras (jupyterlab, ipykernel, pandas, +# matplotlib) and runtime deps (python-dateutil, scipy) come from pyproject.toml. +RUN pip install --upgrade pip setuptools wheel \ + && pip install -e .[notebook] \ + && pip install -r requirements.txt \ + && python -m ipykernel install --name rcpchgrowth --display-name 'rcpchgrowth' --sys-prefix # Bring in notebooks only after package install so they are never considered for package discovery COPY notebooks notebooks diff --git a/docker-compose.yml b/docker-compose.yml index 41eb22b..bf0312f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,22 +13,11 @@ services: - PYTHONPATH=/app ports: - "8888:8888" - command: - - bash - - -lc - - | - set -e - mkdir -p /app/notebooks - echo '[DEV] Editable install' - pip install -e /app[notebook] - echo '[DEV] Installing test dependencies' - pip install pytest - echo '[DEV] Sanity import' - echo '[DEV] Register kernel' - python -m ipykernel install --name rcpchgrowth --display-name 'rcpchgrowth' --sys-prefix - echo '[DEV] Launching JupyterLab in background' - jupyter lab --ip=0.0.0.0 --no-browser --allow-root \ - --NotebookApp.token='' --NotebookApp.password='' \ - --notebook-dir=/app/notebooks & - echo '[DEV] Container ready for testing' - wait + # Re-wire the editable install against the bind-mounted source (creates + # rcpchgrowth.egg-info on the host on first run), then exec JupyterLab. + # All deps and the Jupyter kernel are baked into the image at build time. + command: > + bash -lc "pip install -e . -q && + exec jupyter lab --ip=0.0.0.0 --no-browser --allow-root + --NotebookApp.token='' --NotebookApp.password='' + --notebook-dir=/app/notebooks" diff --git a/notebooks/AdditionalFunctions.ipynb b/notebooks/AdditionalFunctions.ipynb index 60c746f..1a4c19d 100644 --- a/notebooks/AdditionalFunctions.ipynb +++ b/notebooks/AdditionalFunctions.ipynb @@ -201,7 +201,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.11" + "version": "3.12.13" } }, "nbformat": 4, diff --git a/s/build b/s/build old mode 100644 new mode 100755 index cc4000b..a67ffe8 --- a/s/build +++ b/s/build @@ -1,10 +1,5 @@ #!/bin/bash - -set -v # Enable verbose mode -set -e # Exit on error - -# scripts may need to be made executable on some platforms before they can be run -# chmod +x is the command to do this on unixy systems +set -e # Build the development container image -docker compose build \ No newline at end of file +docker compose build "$@" diff --git a/s/down b/s/down index b1ad20c..63dafb7 100755 --- a/s/down +++ b/s/down @@ -1,10 +1,5 @@ #!/bin/bash +set -e -set -v # Enable verbose mode -set -e # Exit on error - -# scripts may need to be made executable on some platforms before they can be run -# chmod +x is the command to do this on unixy systems - -# shuts down the Docker Compose setup but does not destroy containers or images +# Stop the Compose setup (containers and images are preserved). docker compose down diff --git a/s/notebook b/s/notebook index 3532f0d..0a78e4e 100755 --- a/s/notebook +++ b/s/notebook @@ -2,32 +2,33 @@ set -e # Exit on error -# Check if container is running -CONTAINER_NAME="rcpchgrowth-python" -CONTAINER_STATUS=$(docker inspect -f '{{.State.Running}}' $CONTAINER_NAME 2>/dev/null || echo "false") +JUPYTER_URL="http://localhost:8888/lab" -if [ "$CONTAINER_STATUS" = "false" ]; then - echo "Container not running. Starting container..." - docker compose up -d - echo "Waiting for JupyterLab to start..." - sleep 15 -fi +# Always run docker compose up -d; it's idempotent (no-op if already running) +echo "Ensuring container is running..." +docker compose up -d -# Get the JupyterLab URL -JUPYTER_URL="http://localhost:8888/lab" +# Wait for JupyterLab to respond rather than a blind sleep +echo "Waiting for JupyterLab to be ready..." +for i in $(seq 1 30); do + if curl -s -o /dev/null -w '' "$JUPYTER_URL" 2>/dev/null; then + break + fi + sleep 2 +done echo "" echo "🎓 JupyterLab is running!" echo "Opening: $JUPYTER_URL" echo "" -# Try to open in browser (works on macOS, Linux with xdg-open, etc.) +# Try to open in browser (suppress stderr to avoid Chromium noise) if command -v open &> /dev/null; then # macOS open "$JUPYTER_URL" elif command -v xdg-open &> /dev/null; then # Linux - xdg-open "$JUPYTER_URL" + xdg-open "$JUPYTER_URL" 2>/dev/null & elif command -v wslview &> /dev/null; then # WSL wslview "$JUPYTER_URL" diff --git a/s/rebuild b/s/rebuild index da82a21..00a9a5a 100755 --- a/s/rebuild +++ b/s/rebuild @@ -1,12 +1,9 @@ #!/bin/bash +set -e -set -v # Enable verbose mode -set -e # Exit on error +# Rebuild the container from scratch. +DIR="$(cd "$(dirname "$0")" && pwd)" +"$DIR/remove-containers-and-images" +"$DIR/build" +"$DIR/up" -# scripts may need to be made executable on some platforms before they can be run -# chmod +x is the command to do this on unixy systems - -# Rebuild the container from scratch -s/remove-containers-and-images -s/build -s/up diff --git a/s/remove-containers-and-images b/s/remove-containers-and-images index 2a227c0..abffa68 100755 --- a/s/remove-containers-and-images +++ b/s/remove-containers-and-images @@ -1,10 +1,7 @@ #!/bin/bash +set -e -set -v # Enable verbose mode -set -e # Exit on error +# Stop the Compose setup AND remove containers and locally-built images +# (named/anonymous volumes are preserved). +docker compose down --rmi local -# scripts may need to be made executable on some platforms before they can be run -# chmod +x is the command to do this on unixy systems - -# shuts down the Docker Compose setup AND deletes containers and images (but not volumes) -docker compose down --rmi local # removes the container and local images diff --git a/s/up b/s/up index e046ff7..2c952eb 100755 --- a/s/up +++ b/s/up @@ -1,18 +1,6 @@ #!/bin/bash +set -e -set -v # Enable verbose mode -set -e # Exit on error +# Build (if needed) and start the development container in detached mode. +docker compose up -d "$@" -# scripts may need to be made executable on some platforms before they can be run -# chmod +x is the command to do this on unixy systems - -# Build and start the development container in detached mode -docker compose up -d - -echo "" -echo "Container started! Use these commands:" -echo " s/shell - Enter the container for interactive work" -echo " s/test - Run pytest inside the container" -echo " s/python - Run Python REPL inside the container" -echo " s/down - Stop the container" -echo "" \ No newline at end of file