From 8408368daf5fe42c806a55f4d0ee27ca8217baa8 Mon Sep 17 00:00:00 2001 From: Ewout ter Hoeven Date: Sun, 25 Aug 2024 15:47:49 +0200 Subject: [PATCH 1/6] gis: Use relative imports in all models Use relative imports in all models. This way models can be ran from different locations, which will help with testing them. --- gis/agents_and_networks/src/agent/commuter.py | 4 ++-- gis/agents_and_networks/src/model/model.py | 10 +++++----- gis/agents_and_networks/src/space/campus.py | 4 ++-- gis/agents_and_networks/src/space/road_network.py | 2 +- gis/agents_and_networks/src/visualization/server.py | 6 +++--- gis/geo_sir/model.py | 3 ++- 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/gis/agents_and_networks/src/agent/commuter.py b/gis/agents_and_networks/src/agent/commuter.py index 71c59f1e..85a928bb 100644 --- a/gis/agents_and_networks/src/agent/commuter.py +++ b/gis/agents_and_networks/src/agent/commuter.py @@ -8,8 +8,8 @@ import pyproj from shapely.geometry import LineString, Point -from src.agent.building import Building -from src.space.utils import UnitTransformer, redistribute_vertices +from ..space.utils import UnitTransformer, redistribute_vertices +from .building import Building class Commuter(mg.GeoAgent): diff --git a/gis/agents_and_networks/src/model/model.py b/gis/agents_and_networks/src/model/model.py index 9e4ca37c..e0b03114 100644 --- a/gis/agents_and_networks/src/model/model.py +++ b/gis/agents_and_networks/src/model/model.py @@ -7,11 +7,11 @@ import pandas as pd from shapely.geometry import Point -from src.agent.building import Building -from src.agent.commuter import Commuter -from src.agent.geo_agents import Driveway, LakeAndRiver, Walkway -from src.space.campus import Campus -from src.space.road_network import CampusWalkway +from ..agent.building import Building +from ..agent.commuter import Commuter +from ..agent.geo_agents import Driveway, LakeAndRiver, Walkway +from ..space.campus import Campus +from ..space.road_network import CampusWalkway def get_time(model) -> pd.Timedelta: diff --git a/gis/agents_and_networks/src/space/campus.py b/gis/agents_and_networks/src/space/campus.py index 0d415538..5b3ebb35 100644 --- a/gis/agents_and_networks/src/space/campus.py +++ b/gis/agents_and_networks/src/space/campus.py @@ -6,8 +6,8 @@ import mesa_geo as mg from shapely.geometry import Point -from src.agent.building import Building -from src.agent.commuter import Commuter +from ..agent.building import Building +from ..agent.commuter import Commuter class Campus(mg.GeoSpace): diff --git a/gis/agents_and_networks/src/space/road_network.py b/gis/agents_and_networks/src/space/road_network.py index 9f4d1940..be5e1cb8 100644 --- a/gis/agents_and_networks/src/space/road_network.py +++ b/gis/agents_and_networks/src/space/road_network.py @@ -9,7 +9,7 @@ import pyproj from sklearn.neighbors import KDTree -from src.space.utils import segmented +from .utils import segmented class RoadNetwork: diff --git a/gis/agents_and_networks/src/visualization/server.py b/gis/agents_and_networks/src/visualization/server.py index 64c43235..c3c04e17 100644 --- a/gis/agents_and_networks/src/visualization/server.py +++ b/gis/agents_and_networks/src/visualization/server.py @@ -1,8 +1,8 @@ import mesa -from src.agent.building import Building -from src.agent.commuter import Commuter -from src.agent.geo_agents import Driveway, LakeAndRiver, Walkway +from ..agent.building import Building +from ..agent.commuter import Commuter +from ..agent.geo_agents import Driveway, LakeAndRiver, Walkway class ClockElement(mesa.visualization.TextElement): diff --git a/gis/geo_sir/model.py b/gis/geo_sir/model.py index d9d49585..c6882ed8 100644 --- a/gis/geo_sir/model.py +++ b/gis/geo_sir/model.py @@ -1,8 +1,9 @@ import mesa import mesa_geo as mg -from agents import NeighbourhoodAgent, PersonAgent from shapely.geometry import Point +from .agents import NeighbourhoodAgent, PersonAgent + class GeoSir(mesa.Model): """Model class for a simplistic infection model.""" From 377bf15d00ef777c2faa4deeb58a25cda23cd323 Mon Sep 17 00:00:00 2001 From: Ewout ter Hoeven Date: Sun, 25 Aug 2024 15:57:50 +0200 Subject: [PATCH 2/6] Create script to test GIS examples Co-Authored-By: rht --- test_gis_examples.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 test_gis_examples.py diff --git a/test_gis_examples.py b/test_gis_examples.py new file mode 100644 index 00000000..39015ecd --- /dev/null +++ b/test_gis_examples.py @@ -0,0 +1,34 @@ +import importlib +import os + +import pytest +from mesa import Model + + +def get_models(directory): + models = [] + for root, dirs, files in os.walk(directory): + for file in files: + if file == "model.py": + module_name = os.path.relpath(os.path.join(root, file[:-3])).replace( + os.sep, "." + ) + + module = importlib.import_module(module_name) + for item in dir(module): + obj = getattr(module, item) + if ( + isinstance(obj, type) + and issubclass(obj, Model) + and obj is not Model + ): + models.append(obj) + + return models + + +@pytest.mark.parametrize("model_class", get_models("gis")) +def test_model_steps(model_class): + model = model_class() # Assume no arguments are needed + for _ in range(10): + model.step() From 805b93d4965ce03ac689ea78e247ab5db98b05dc Mon Sep 17 00:00:00 2001 From: Ewout ter Hoeven Date: Sun, 25 Aug 2024 16:03:58 +0200 Subject: [PATCH 3/6] CI: Modernize examples test script - Rename workflow - Run on each push (which allows developing on test branches in this repo) - Run only on changes to the example models, the test script or the CI config - Allow multiple commits after each other (to allow continuous trial and error --- .../{build_lint.yml => test_examples.yml} | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) rename .github/workflows/{build_lint.yml => test_examples.yml} (73%) diff --git a/.github/workflows/build_lint.yml b/.github/workflows/test_examples.yml similarity index 73% rename from .github/workflows/build_lint.yml rename to .github/workflows/test_examples.yml index 0da5147b..4821604c 100644 --- a/.github/workflows/build_lint.yml +++ b/.github/workflows/test_examples.yml @@ -1,28 +1,20 @@ -name: build +name: Test example models on: push: - branches: - - main - - release** - paths-ignore: - - '**.md' - - '**.rst' + paths: + - 'examples/**/*.py' # If an example model is modified + - 'test_examples.py' # If the test script is modified + - '.github/workflows/test_examples.yml' # If this workflow is modified pull_request: - paths-ignore: - - '**.md' - - '**.rst' + paths: + - 'examples/**/*.py' + - 'test_examples.py' + - '.github/workflows/test_examples.yml' workflow_dispatch: schedule: - cron: '0 6 * * 1' # Monday at 6:00 UTC -# This will cancel previous run if a newer job that obsoletes the said previous -# run, is started. -# Based on https://github.com/zulip/zulip/commit/4a11642cee3c8aec976d305d51a86e60e5d70522 -concurrency: - group: "${{ github.workflow }}-${{ github.head_ref || github.run_id }}" - cancel-in-progress: true - jobs: # build-stable: # runs-on: ubuntu-latest From b6622166a2a971390540fac340c6bbc122f98a34 Mon Sep 17 00:00:00 2001 From: Ewout ter Hoeven Date: Sun, 25 Aug 2024 16:07:36 +0200 Subject: [PATCH 4/6] CI: Add workflow to test gis models --- .github/workflows/test_gis_examples.yml | 62 +++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 .github/workflows/test_gis_examples.yml diff --git a/.github/workflows/test_gis_examples.yml b/.github/workflows/test_gis_examples.yml new file mode 100644 index 00000000..49a3ae43 --- /dev/null +++ b/.github/workflows/test_gis_examples.yml @@ -0,0 +1,62 @@ +name: Test GIS models + +on: + push: + paths: + - 'gis/**/*.py' # If a gis model is modified + - 'test_gis_examples.py' # If the gis test script is modified + - '.github/workflows/test_gis_examples.yml' # If this workflow is modified + pull_request: + paths: + - 'gis/**/*.py' + - 'test_gis_examples.py' + - '.github/workflows/test_gis_examples.yml' + workflow_dispatch: + schedule: + - cron: '0 6 * * 1' # Monday at 6:00 UTC + +jobs: + # build-stable: + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # - name: Set up Python + # uses: actions/setup-python@v5 + # with: + # python-version: "3.12" + # - name: Install dependencies + # run: pip install mesa pytest + # - name: Test with pytest + # run: pytest -rA -Werror test_examples.py + + build-pre: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + - name: Install dependencies + run: | + pip install mesa mesa-geo --pre + pip install + pip install pytest + - name: Test with pytest + run: pytest -rA -Werror test_gis_examples.py + + build-main: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.12" + - name: Install dependencies + run: | + pip install pytest + pip install -U git+https://github.com/projectmesa/mesa@main#egg=mesa + pip install -U git+https://github.com/projectmesa/mesa-geo@main#egg=mesa-geo + - name: Test with pytest + run: pytest -rA -Werror test_gis_examples.py From 533c606b1c99ba952b781c93895aa1ce011d0c6f Mon Sep 17 00:00:00 2001 From: Ewout ter Hoeven Date: Sun, 25 Aug 2024 16:15:13 +0200 Subject: [PATCH 5/6] Define optional gis dependencies in pyproject.toml --- .github/workflows/test_gis_examples.yml | 2 +- pyproject.toml | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test_gis_examples.yml b/.github/workflows/test_gis_examples.yml index 49a3ae43..71dcfbfe 100644 --- a/.github/workflows/test_gis_examples.yml +++ b/.github/workflows/test_gis_examples.yml @@ -40,7 +40,7 @@ jobs: - name: Install dependencies run: | pip install mesa mesa-geo --pre - pip install + pip install .[test_gis] pip install pytest - name: Test with pytest run: pytest -rA -Werror test_gis_examples.py diff --git a/pyproject.toml b/pyproject.toml index d82e0f3b..41bb1d02 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,12 @@ license = {file = "LICENSE"} readme = "README.rst" requires-python = ">=3.8" +[project.optional-dependencies] +test = [""] +test_gis = [ + "momepy", +] + [build-system] requires = [ "setuptools", From 897fe59ea2011b2d472b97cbfde264042279bf5f Mon Sep 17 00:00:00 2001 From: Ewout ter Hoeven Date: Sun, 25 Aug 2024 16:22:51 +0200 Subject: [PATCH 6/6] Update optional dependencies and CI --- .github/workflows/test_examples.yml | 4 ++-- .github/workflows/test_gis_examples.yml | 6 ++---- pyproject.toml | 7 +++++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test_examples.yml b/.github/workflows/test_examples.yml index 4821604c..6061c145 100644 --- a/.github/workflows/test_examples.yml +++ b/.github/workflows/test_examples.yml @@ -40,7 +40,7 @@ jobs: - name: Install dependencies run: | pip install mesa --pre - pip install pytest + pip install .[test] - name: Test with pytest run: pytest -rA -Werror test_examples.py @@ -54,7 +54,7 @@ jobs: python-version: "3.12" - name: Install dependencies run: | - pip install pytest + pip install .[test] pip install -U git+https://github.com/projectmesa/mesa@main#egg=mesa - name: Test with pytest run: pytest -rA -Werror test_examples.py diff --git a/.github/workflows/test_gis_examples.yml b/.github/workflows/test_gis_examples.yml index 71dcfbfe..f52986cf 100644 --- a/.github/workflows/test_gis_examples.yml +++ b/.github/workflows/test_gis_examples.yml @@ -39,9 +39,8 @@ jobs: python-version: "3.12" - name: Install dependencies run: | - pip install mesa mesa-geo --pre + pip install mesa-geo --pre pip install .[test_gis] - pip install pytest - name: Test with pytest run: pytest -rA -Werror test_gis_examples.py @@ -55,8 +54,7 @@ jobs: python-version: "3.12" - name: Install dependencies run: | - pip install pytest - pip install -U git+https://github.com/projectmesa/mesa@main#egg=mesa pip install -U git+https://github.com/projectmesa/mesa-geo@main#egg=mesa-geo + pip install .[test_gis] - name: Test with pytest run: pytest -rA -Werror test_gis_examples.py diff --git a/pyproject.toml b/pyproject.toml index 41bb1d02..ab2b4abd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,9 +10,12 @@ readme = "README.rst" requires-python = ">=3.8" [project.optional-dependencies] -test = [""] +test = [ + "pytest", +] test_gis = [ - "momepy", + "pytest", + "momepy", ] [build-system]