From 034216702c9080b8603047e9c12b3d9ea83bc3a0 Mon Sep 17 00:00:00 2001 From: Kegan Maher Date: Fri, 18 Jul 2025 13:19:51 -0700 Subject: [PATCH 1/9] feat(pems_streamlit): pyproject file for metadata --- pems_streamlit/pyproject.toml | 27 +++++++++++++++++++++++++++ streamlit_app/requirements.txt | 4 ---- 2 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 pems_streamlit/pyproject.toml delete mode 100644 streamlit_app/requirements.txt diff --git a/pems_streamlit/pyproject.toml b/pems_streamlit/pyproject.toml new file mode 100644 index 00000000..84447bbf --- /dev/null +++ b/pems_streamlit/pyproject.toml @@ -0,0 +1,27 @@ +[project] +name = "pems_streamlit" +description = "The Streamlit application for PeMS data visualizations." +dynamic = ["version"] +requires-python = ">=3.12" +dependencies = [ + "boto3==1.39.7", + "django==5.2.3", + "pandas==2.3.0", + "streamlit==1.45.1", +] + +[build-system] +requires = ["setuptools>=75", "setuptools_scm>=8"] +build-backend = "setuptools.build_meta" + +[tool.setuptools.packages.find] +where = ["src"] +include = ["pems_streamlit*"] +namespaces = false + +[tool.setuptools.package-data] +pems_streamlit = ["*.txt"] + +[tool.setuptools_scm] +# Tell scm to look one directory up for the .git folder +root = ".." diff --git a/streamlit_app/requirements.txt b/streamlit_app/requirements.txt deleted file mode 100644 index c823037c..00000000 --- a/streamlit_app/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -boto3==1.39.7 -django==5.2.3 -pandas==2.3.0 -streamlit==1.45.1 From 6635de34c9158c580144ddb59cb409eb9740b56c Mon Sep 17 00:00:00 2001 From: Kegan Maher Date: Fri, 18 Jul 2025 13:21:31 -0700 Subject: [PATCH 2/9] refactor(pems_streamlit): move Dockerfile and assets update the build into a multi-stage: - first build the pems_streamlit wheel - then install it with other necessary tooling similar to how the pems_web Docker build works --- compose.yml | 4 +- infra/copilot/streamlit/manifest.yml | 2 +- pems_streamlit/container/Dockerfile | 61 +++++++++++++++++++ .../container}/entrypoint.sh | 3 +- pems_streamlit/container/run.py | 10 +++ streamlit_app/Dockerfile | 42 ------------- 6 files changed, 75 insertions(+), 47 deletions(-) create mode 100644 pems_streamlit/container/Dockerfile rename {streamlit_app => pems_streamlit/container}/entrypoint.sh (77%) create mode 100755 pems_streamlit/container/run.py delete mode 100644 streamlit_app/Dockerfile diff --git a/compose.yml b/compose.yml index 9d028afa..8a3f4771 100644 --- a/compose.yml +++ b/compose.yml @@ -69,13 +69,11 @@ services: streamlit: build: context: . - dockerfile: streamlit_app/Dockerfile + dockerfile: pems_streamlit/container/Dockerfile image: caltrans/pems:streamlit env_file: .env ports: - "${STREAMLIT_LOCAL_PORT:-8501}:8501" - volumes: - - ./:/caltrans/app volumes: pgdata: diff --git a/infra/copilot/streamlit/manifest.yml b/infra/copilot/streamlit/manifest.yml index 16e61852..fcc0ffd1 100644 --- a/infra/copilot/streamlit/manifest.yml +++ b/infra/copilot/streamlit/manifest.yml @@ -17,7 +17,7 @@ http: image: # Docker build arguments. For additional overrides: https://aws.github.io/copilot-cli/docs/manifest/backend-service/#image-build build: - dockerfile: ../streamlit_app/Dockerfile + dockerfile: ../pems_streamlit/container/Dockerfile context: ../ # Port exposed through your container to route traffic to it. port: 8501 diff --git a/pems_streamlit/container/Dockerfile b/pems_streamlit/container/Dockerfile new file mode 100644 index 00000000..e0302788 --- /dev/null +++ b/pems_streamlit/container/Dockerfile @@ -0,0 +1,61 @@ +ARG PYTHON_VERSION=3.12 + +# multi-stage build +# +# stage 1: builds the package wheel from source +# using the git metadata for version info +FROM python:${PYTHON_VERSION} AS build_wheel +WORKDIR /build + +# upgrade pip, install build dependencies +RUN python -m pip install --upgrade pip build setuptools_scm + +# copy source files +COPY . . +RUN git config --global --add safe.directory /build + +# Move into directory to run the build +WORKDIR /build/pems_streamlit + +# build package +RUN python -m build + +# multi-stage build +# +# stage 2: installs the wheel in a fresh base container +# using the pre-built package, and copying only needed source +FROM python:${PYTHON_VERSION} AS app_container + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + USER=caltrans + +EXPOSE 8501 + +# create non-root $USER and home directory +RUN useradd --create-home --shell /bin/bash $USER && \ + python -m pip install --upgrade pip + +COPY LICENSE LICENSE + +# switch to non-root $USER +USER $USER + +# update env for local pip installs +# see https://docs.python.org/3/using/cmdline.html#envvar-PYTHONUSERBASE +# since all `pip install` commands are in the context of $USER +# $PYTHONUSERBASE is the location used by default +ENV PATH="$PATH:/$USER/.local/bin" \ + PYTHONUSERBASE="/$USER/.local" \ + PYTHONPATH="$PYTHONPATH:/$USER/app" + +WORKDIR /$USER/app + +COPY .streamlit .streamlit +COPY pems_streamlit/container/entrypoint.sh entrypoint.sh +COPY pems_streamlit/container/run.py run.py +COPY --from=build_wheel /build/pems_streamlit/dist /wheels + +RUN pip install $(find /wheels -name pems_streamlit*.whl) + +ENTRYPOINT ["./entrypoint.sh"] diff --git a/streamlit_app/entrypoint.sh b/pems_streamlit/container/entrypoint.sh similarity index 77% rename from streamlit_app/entrypoint.sh rename to pems_streamlit/container/entrypoint.sh index 14338e55..7c0acf08 100755 --- a/streamlit_app/entrypoint.sh +++ b/pems_streamlit/container/entrypoint.sh @@ -7,7 +7,8 @@ BASE_URL_PATH=${STREAMLIT_BASE_URL:-""} echo "Starting Streamlit with base URL path: ${BASE_URL_PATH}" # Execute the Streamlit command, passing the base URL path -exec streamlit run streamlit_app/main.py \ +# Use the run.py helper since streamlit run wants the path to a python file +exec streamlit run run.py \ --server.port=8501 \ --server.address=0.0.0.0 \ --server.baseUrlPath="${BASE_URL_PATH}" diff --git a/pems_streamlit/container/run.py b/pems_streamlit/container/run.py new file mode 100755 index 00000000..0d07f04a --- /dev/null +++ b/pems_streamlit/container/run.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +import runpy + +# since we're installing pems_streamlit as a package now, the main.py file won't exist +# in the running container, so we can't point `streamlit run` at it + +# instead, use runpy to run the pems_streamlit.main module directly. + +if __name__ == "__main__": + runpy.run_module("pems_streamlit.main", run_name="__main__", alter_sys=True) diff --git a/streamlit_app/Dockerfile b/streamlit_app/Dockerfile deleted file mode 100644 index 14a8dc9c..00000000 --- a/streamlit_app/Dockerfile +++ /dev/null @@ -1,42 +0,0 @@ -ARG PYTHON_VERSION=3.12 - -FROM python:${PYTHON_VERSION} - -ENV PYTHONDONTWRITEBYTECODE=1 \ - PYTHONUNBUFFERED=1 \ - USER=caltrans - -# create non-root $USER and home directory -RUN useradd --create-home --shell /bin/bash $USER && \ - # setup directories and permissions - mkdir -p /$USER/app && \ - chown -R $USER:$USER /$USER - -# enter source directory -WORKDIR /$USER - -COPY LICENSE app/LICENSE - -# switch to non-root $USER -USER $USER - -# update env for local pip installs -# see https://docs.python.org/3/using/cmdline.html#envvar-PYTHONUSERBASE -# since all `pip install` commands are in the context of $USER -# $PYTHONUSERBASE is the location used by default -ENV PATH="$PATH:/$USER/.local/bin" \ - PYTHONUSERBASE="/$USER/.local" - -WORKDIR /$USER/app - -ENV PYTHONPATH="$PYTHONPATH:/$USER/app" - -EXPOSE 8501 - -COPY .streamlit .streamlit - -COPY streamlit_app streamlit_app - -RUN pip install -r streamlit_app/requirements.txt - -ENTRYPOINT ["./streamlit_app/entrypoint.sh"] From f3981af9e0a21d00d1b391bef0151808f7202d25 Mon Sep 17 00:00:00 2001 From: Kegan Maher Date: Fri, 18 Jul 2025 13:23:20 -0700 Subject: [PATCH 3/9] refactor(pems_streamlit): move app, update paths --- .vscode/launch.json | 4 ++-- .../src/pems_streamlit}/__init__.py | 0 .../src/pems_streamlit/apps}/__init__.py | 0 .../src/pems_streamlit}/apps/stations/__init__.py | 0 .../src/pems_streamlit}/apps/stations/app_stations.py | 0 .../src/pems_streamlit}/main.py | 3 +-- .../src/pems_streamlit}/utils.py | 0 tests/pytest/streamlit_app/test_main.py | 7 ++++--- tests/pytest/streamlit_app/test_utils.py | 8 ++++---- 9 files changed, 11 insertions(+), 11 deletions(-) rename {streamlit_app/apps => pems_streamlit/src/pems_streamlit}/__init__.py (100%) rename {streamlit_app => pems_streamlit/src/pems_streamlit/apps}/__init__.py (100%) rename {streamlit_app => pems_streamlit/src/pems_streamlit}/apps/stations/__init__.py (100%) rename {streamlit_app => pems_streamlit/src/pems_streamlit}/apps/stations/app_stations.py (100%) rename {streamlit_app => pems_streamlit/src/pems_streamlit}/main.py (94%) rename {streamlit_app => pems_streamlit/src/pems_streamlit}/utils.py (100%) diff --git a/.vscode/launch.json b/.vscode/launch.json index c784b794..f7d5e5d0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -33,7 +33,7 @@ "type": "debugpy", "request": "launch", "module": "streamlit", - "args": ["run", "streamlit_app/main.py"], + "args": ["run", "pems_streamlit/src/pems_streamlit/main.py"], "env": { "PYTHONBUFFERED": "1", "PYTHONWARNINGS": "default", @@ -45,7 +45,7 @@ "type": "debugpy", "request": "launch", "module": "streamlit", - "args": ["run", "streamlit_app/main.py"], + "args": ["run", "pems_streamlit/src/pems_streamlit/main.py"], "env": { "PYTHONBUFFERED": "1", "PYTHONWARNINGS": "default", diff --git a/streamlit_app/apps/__init__.py b/pems_streamlit/src/pems_streamlit/__init__.py similarity index 100% rename from streamlit_app/apps/__init__.py rename to pems_streamlit/src/pems_streamlit/__init__.py diff --git a/streamlit_app/__init__.py b/pems_streamlit/src/pems_streamlit/apps/__init__.py similarity index 100% rename from streamlit_app/__init__.py rename to pems_streamlit/src/pems_streamlit/apps/__init__.py diff --git a/streamlit_app/apps/stations/__init__.py b/pems_streamlit/src/pems_streamlit/apps/stations/__init__.py similarity index 100% rename from streamlit_app/apps/stations/__init__.py rename to pems_streamlit/src/pems_streamlit/apps/stations/__init__.py diff --git a/streamlit_app/apps/stations/app_stations.py b/pems_streamlit/src/pems_streamlit/apps/stations/app_stations.py similarity index 100% rename from streamlit_app/apps/stations/app_stations.py rename to pems_streamlit/src/pems_streamlit/apps/stations/app_stations.py diff --git a/streamlit_app/main.py b/pems_streamlit/src/pems_streamlit/main.py similarity index 94% rename from streamlit_app/main.py rename to pems_streamlit/src/pems_streamlit/main.py index 2b3f63e6..02cd0b0a 100644 --- a/streamlit_app/main.py +++ b/pems_streamlit/src/pems_streamlit/main.py @@ -1,10 +1,9 @@ import logging import os - import streamlit as st -from streamlit_app.utils import discover_apps +from pems_streamlit.utils import discover_apps logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) diff --git a/streamlit_app/utils.py b/pems_streamlit/src/pems_streamlit/utils.py similarity index 100% rename from streamlit_app/utils.py rename to pems_streamlit/src/pems_streamlit/utils.py diff --git a/tests/pytest/streamlit_app/test_main.py b/tests/pytest/streamlit_app/test_main.py index 39240813..940f1f0a 100644 --- a/tests/pytest/streamlit_app/test_main.py +++ b/tests/pytest/streamlit_app/test_main.py @@ -1,5 +1,6 @@ import pytest -from streamlit_app import main + +from pems_streamlit import main @pytest.mark.parametrize( @@ -19,8 +20,8 @@ def test_main(mocker, monkeypatch, nav_option, expected_nav): else: monkeypatch.delenv(nav_key, False) - mock_discover = mocker.patch("streamlit_app.main.discover_apps", return_value=apps) - mock_navigate = mocker.patch("streamlit_app.main.st.navigation") + mock_discover = mocker.patch("pems_streamlit.main.discover_apps", return_value=apps) + mock_navigate = mocker.patch("pems_streamlit.main.st.navigation") main.main() diff --git a/tests/pytest/streamlit_app/test_utils.py b/tests/pytest/streamlit_app/test_utils.py index d731c10e..bd82af32 100644 --- a/tests/pytest/streamlit_app/test_utils.py +++ b/tests/pytest/streamlit_app/test_utils.py @@ -3,7 +3,7 @@ import pytest from streamlit.navigation.page import StreamlitPage -from streamlit_app import utils +from pems_streamlit import utils @pytest.fixture @@ -25,7 +25,7 @@ def app_paths(test_apps_path): def test_convert_to_pages(mocker, app_paths): - page_factory = mocker.patch("streamlit_app.utils._make_app_page", return_value="page") + page_factory = mocker.patch("pems_streamlit.utils._make_app_page", return_value="page") pages = utils._convert_to_pages(app_paths) @@ -67,8 +67,8 @@ def test_make_app_page(app_paths): def test_discover_apps(mocker): - mock_discover = mocker.patch("streamlit_app.utils._discover_apps", return_value=[]) - mock_convert = mocker.patch("streamlit_app.utils._convert_to_pages", return_value=[]) + mock_discover = mocker.patch("pems_streamlit.utils._discover_apps", return_value=[]) + mock_convert = mocker.patch("pems_streamlit.utils._convert_to_pages", return_value=[]) result = utils.discover_apps() From d968b021c864704e0974b397b4894a301a1497c1 Mon Sep 17 00:00:00 2001 From: Kegan Maher Date: Fri, 18 Jul 2025 20:50:30 +0000 Subject: [PATCH 4/9] refactor(tests): rename pems_streamlit directory --- pyproject.toml | 6 +++--- tests/pytest/{streamlit_app => pems_streamlit}/__init__.py | 0 tests/pytest/{streamlit_app => pems_streamlit}/conftest.py | 0 .../{streamlit_app => pems_streamlit}/test_apps/__init__.py | 0 .../{streamlit_app => pems_streamlit}/test_apps/app_one.py | 0 .../{streamlit_app => pems_streamlit}/test_apps/app_two.py | 0 .../test_apps/not_an_app.py | 0 tests/pytest/{streamlit_app => pems_streamlit}/test_main.py | 0 .../pytest/{streamlit_app => pems_streamlit}/test_utils.py | 0 9 files changed, 3 insertions(+), 3 deletions(-) rename tests/pytest/{streamlit_app => pems_streamlit}/__init__.py (100%) rename tests/pytest/{streamlit_app => pems_streamlit}/conftest.py (100%) rename tests/pytest/{streamlit_app => pems_streamlit}/test_apps/__init__.py (100%) rename tests/pytest/{streamlit_app => pems_streamlit}/test_apps/app_one.py (100%) rename tests/pytest/{streamlit_app => pems_streamlit}/test_apps/app_two.py (100%) rename tests/pytest/{streamlit_app => pems_streamlit}/test_apps/not_an_app.py (100%) rename tests/pytest/{streamlit_app => pems_streamlit}/test_main.py (100%) rename tests/pytest/{streamlit_app => pems_streamlit}/test_utils.py (100%) diff --git a/pyproject.toml b/pyproject.toml index 82ae3e2e..7e14e7da 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,8 +41,8 @@ include = '\.pyi?$' [tool.coverage.run] branch = true relative_files = true -source = ["pems_web", "streamlit_app"] -omit = ["streamlit_app/apps/*"] +source = ["pems_streamlit", "pems_web"] +omit = ["pems_streamlit/src/pems_streamlit/apps/*"] [tool.djlint] ignore = "H006,H017,H031" @@ -56,4 +56,4 @@ use_gitignore = true [tool.pytest.ini_options] DJANGO_SETTINGS_MODULE = "tests.pytest.pems_web.settings" # Explicitly add src directories to pytest's python path. -pythonpath = ["pems_web/src"] +pythonpath = ["pems_streamlit/src", "pems_web/src"] diff --git a/tests/pytest/streamlit_app/__init__.py b/tests/pytest/pems_streamlit/__init__.py similarity index 100% rename from tests/pytest/streamlit_app/__init__.py rename to tests/pytest/pems_streamlit/__init__.py diff --git a/tests/pytest/streamlit_app/conftest.py b/tests/pytest/pems_streamlit/conftest.py similarity index 100% rename from tests/pytest/streamlit_app/conftest.py rename to tests/pytest/pems_streamlit/conftest.py diff --git a/tests/pytest/streamlit_app/test_apps/__init__.py b/tests/pytest/pems_streamlit/test_apps/__init__.py similarity index 100% rename from tests/pytest/streamlit_app/test_apps/__init__.py rename to tests/pytest/pems_streamlit/test_apps/__init__.py diff --git a/tests/pytest/streamlit_app/test_apps/app_one.py b/tests/pytest/pems_streamlit/test_apps/app_one.py similarity index 100% rename from tests/pytest/streamlit_app/test_apps/app_one.py rename to tests/pytest/pems_streamlit/test_apps/app_one.py diff --git a/tests/pytest/streamlit_app/test_apps/app_two.py b/tests/pytest/pems_streamlit/test_apps/app_two.py similarity index 100% rename from tests/pytest/streamlit_app/test_apps/app_two.py rename to tests/pytest/pems_streamlit/test_apps/app_two.py diff --git a/tests/pytest/streamlit_app/test_apps/not_an_app.py b/tests/pytest/pems_streamlit/test_apps/not_an_app.py similarity index 100% rename from tests/pytest/streamlit_app/test_apps/not_an_app.py rename to tests/pytest/pems_streamlit/test_apps/not_an_app.py diff --git a/tests/pytest/streamlit_app/test_main.py b/tests/pytest/pems_streamlit/test_main.py similarity index 100% rename from tests/pytest/streamlit_app/test_main.py rename to tests/pytest/pems_streamlit/test_main.py diff --git a/tests/pytest/streamlit_app/test_utils.py b/tests/pytest/pems_streamlit/test_utils.py similarity index 100% rename from tests/pytest/streamlit_app/test_utils.py rename to tests/pytest/pems_streamlit/test_utils.py From 02c05dc4c8ca27891e54a504cbf01eab91188e16 Mon Sep 17 00:00:00 2001 From: Kegan Maher Date: Fri, 18 Jul 2025 13:23:55 -0700 Subject: [PATCH 5/9] refactor(devcontainer): add pems_streamlit dependency --- .devcontainer/Dockerfile | 3 --- pyproject.toml | 5 ++++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index a1cd65ba..0283e56f 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -54,6 +54,3 @@ RUN pip install -e .[dev,test] # install docs requirements RUN pip install --no-cache-dir -r docs/requirements.txt - -# install streamlit requirements -RUN pip install --no-cache-dir -r streamlit_app/requirements.txt diff --git a/pyproject.toml b/pyproject.toml index 7e14e7da..69dd2d3e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,10 @@ classifiers = ["Programming Language :: Python :: 3 :: Only"] requires-python = ">=3.12" maintainers = [{ name = "Compiler LLC", email = "dev@compiler.la" }] # Link all the local packages so they are installed together -dependencies = ["pems_web @ file:./pems_web"] +dependencies = [ + "pems_streamlit @ file:./pems_streamlit", + "pems_web @ file:./pems_web", +] [project.optional-dependencies] dev = [ From 470e03f7323566673e65ca3b035741074268eda1 Mon Sep 17 00:00:00 2001 From: Kegan Maher Date: Fri, 18 Jul 2025 20:54:45 +0000 Subject: [PATCH 6/9] fix(ci): remove old requirements install --- .github/workflows/tests-pytest.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/tests-pytest.yml b/.github/workflows/tests-pytest.yml index 3fc1ba15..28edd33c 100644 --- a/.github/workflows/tests-pytest.yml +++ b/.github/workflows/tests-pytest.yml @@ -26,7 +26,6 @@ jobs: - name: Install Python dependencies run: | pip install -e .[test] - pip install -r streamlit_app/requirements.txt - name: Run tests run: ./tests/pytest/run.sh From ea1f400df6fd8ea396d9517dcf574daafa656d50 Mon Sep 17 00:00:00 2001 From: Kegan Maher Date: Tue, 22 Jul 2025 22:31:39 +0000 Subject: [PATCH 7/9] chore(pems_streamlit): remove placeholder app content --- pems_streamlit/src/pems_streamlit/__init__.py | 3 --- pems_streamlit/src/pems_streamlit/utils.py | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pems_streamlit/src/pems_streamlit/__init__.py b/pems_streamlit/src/pems_streamlit/__init__.py index 932f695f..e69de29b 100644 --- a/pems_streamlit/src/pems_streamlit/__init__.py +++ b/pems_streamlit/src/pems_streamlit/__init__.py @@ -1,3 +0,0 @@ -import streamlit as st - -st.write("https://pems.dot.ca.gov") diff --git a/pems_streamlit/src/pems_streamlit/utils.py b/pems_streamlit/src/pems_streamlit/utils.py index 355b9724..b7f53f27 100644 --- a/pems_streamlit/src/pems_streamlit/utils.py +++ b/pems_streamlit/src/pems_streamlit/utils.py @@ -15,6 +15,7 @@ def _convert_to_pages(apps: list[Path]) -> list[StreamlitPage]: def _default_app_page() -> StreamlitPage: + """Creates a no-op default page.""" return st.Page(APP_DIR / "__init__.py", default=True, title="PeMS Streamlit apps") @@ -54,5 +55,6 @@ def discover_apps() -> list[StreamlitPage]: default_app_page = _default_app_page() apps = _discover_apps() pages = _convert_to_pages(apps) + # Streamlit needs at least one page marked as default pages.insert(0, default_app_page) return pages From 3fcf8314d8338baa4e1b7602b90eb30ab623af18 Mon Sep 17 00:00:00 2001 From: Kegan Maher Date: Wed, 23 Jul 2025 16:47:31 +0000 Subject: [PATCH 8/9] fix(devcontainer): ensure packages install as editable pip installing the root-level pyproject.toml with package dependencies didn't install them in editable mode, meaning it was difficult to work with the code in the devcontainer instead explicitly pip install each package as editable in the Docker build process --- .devcontainer/Dockerfile | 6 ++++-- pyproject.toml | 8 +++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 0283e56f..6e0a35e6 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -50,7 +50,9 @@ ENV PATH="$PATH:/$USER/.local/bin" \ PYTHONUSERBASE="/$USER/.local" # install devcontainer requirements -RUN pip install -e .[dev,test] - +RUN pip install .[dev,test] # install docs requirements RUN pip install --no-cache-dir -r docs/requirements.txt + +# install source packages as editable +RUN pip install -e ./pems_streamlit -e ./pems_web diff --git a/pyproject.toml b/pyproject.toml index 69dd2d3e..22c21d77 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,11 +8,9 @@ license-files = ["LICENSE"] classifiers = ["Programming Language :: Python :: 3 :: Only"] requires-python = ">=3.12" maintainers = [{ name = "Compiler LLC", email = "dev@compiler.la" }] -# Link all the local packages so they are installed together -dependencies = [ - "pems_streamlit @ file:./pems_streamlit", - "pems_web @ file:./pems_web", -] +# local packages are installed as part of devcontainer build +# to ensure they are all installed in editable mode +dependencies = [] [project.optional-dependencies] dev = [ From 9be9a633ba6c376309d32a00205316a12d6379f8 Mon Sep 17 00:00:00 2001 From: Kegan Maher Date: Wed, 23 Jul 2025 16:52:02 +0000 Subject: [PATCH 9/9] fix(ci): install packages for testing --- .github/workflows/tests-pytest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests-pytest.yml b/.github/workflows/tests-pytest.yml index 28edd33c..b958d2d4 100644 --- a/.github/workflows/tests-pytest.yml +++ b/.github/workflows/tests-pytest.yml @@ -25,7 +25,7 @@ jobs: - name: Install Python dependencies run: | - pip install -e .[test] + pip install .[test] ./pems_streamlit ./pems_web - name: Run tests run: ./tests/pytest/run.sh