From c494f3c52459a686e2b59697f1503348e8241761 Mon Sep 17 00:00:00 2001 From: Sergio Souza Costa Date: Thu, 11 Jun 2026 18:30:40 -0300 Subject: [PATCH 01/10] doc(geo): converte exemplo narrativo de fill() em bloco python simples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit O exemplo assumia GeoDataFrames externos (grid, roads) e falhava como doctest. Mantido como documentação ilustrativa sem prompts >>>. Co-Authored-By: Claude Fable 5 --- dissmodel/geo/vector/fill.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/dissmodel/geo/vector/fill.py b/dissmodel/geo/vector/fill.py index 9e73e60..762eebd 100644 --- a/dissmodel/geo/vector/fill.py +++ b/dissmodel/geo/vector/fill.py @@ -286,12 +286,15 @@ def fill(strategy: FillStrategy | str, **kwargs: Any) -> Any: Examples -------- - >>> fill(FillStrategy.RANDOM_SAMPLE, gdf=grid, attr="state", - ... data=[0, 1], seed=42) - >>> fill("min_distance", from_gdf=grid, to_gdf=roads, - ... attr_name="dist_road") - >>> fill(FillStrategy.PATTERN, gdf=grid, attr="zone", - ... pattern=[[1, 2], [3, 4]]) + ```python + # grid, roads: existing GeoDataFrames (e.g. from vector_grid / read_file) + fill(FillStrategy.RANDOM_SAMPLE, gdf=grid, attr="state", + data=[0, 1], seed=42) + fill("min_distance", from_gdf=grid, to_gdf=roads, + attr_name="dist_road") + fill(FillStrategy.PATTERN, gdf=grid, attr="zone", + pattern=[[1, 2], [3, 4]]) + ``` """ key = FillStrategy(strategy) if key not in _fill_strategies: From 39c60dbf67c721143bc5c70769dd025e3e6962f6 Mon Sep 17 00:00:00 2001 From: Sergio Souza Costa Date: Thu, 11 Jun 2026 18:31:32 -0300 Subject: [PATCH 02/10] doc(geo): corrige exemplo de _generate_sample no docstring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As saídas documentadas não correspondiam ao resultado real com random.seed(0): [2, 1, 3] -> [3, 3, 2] e [0, 1] -> [1, 1]. random.choices e random.randint são determinísticos para a mesma semente nas versões suportadas (3.10-3.12). Co-Authored-By: Claude Fable 5 --- dissmodel/geo/vector/fill.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dissmodel/geo/vector/fill.py b/dissmodel/geo/vector/fill.py index 762eebd..f3f8491 100644 --- a/dissmodel/geo/vector/fill.py +++ b/dissmodel/geo/vector/fill.py @@ -109,9 +109,9 @@ def _generate_sample(data: _SampleData, size: int = 1) -> list[Any]: -------- >>> import random; random.seed(0) >>> _generate_sample([1, 2, 3], size=3) - [2, 1, 3] + [3, 3, 2] >>> _generate_sample({"min": 0, "max": 1}, size=2) - [0, 1] + [1, 1] """ if isinstance(data, dict): if "min" in data and "max" in data: From 0ba0a40a32c442ef6053410cbe52df892c13478a Mon Sep 17 00:00:00 2001 From: Sergio Souza Costa Date: Thu, 11 Jun 2026 18:32:02 -0300 Subject: [PATCH 03/10] doc(geo): converte exemplos narrativos de neighborhood em blocos python simples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit attach_neighbors, get_neighbors, get_neighbor_values e export_neighbors assumiam um GeoDataFrame externo (gdf) e falhavam como doctest. Mantidos como documentação ilustrativa sem prompts >>>. Co-Authored-By: Claude Fable 5 --- dissmodel/geo/vector/neighborhood.py | 29 +++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/dissmodel/geo/vector/neighborhood.py b/dissmodel/geo/vector/neighborhood.py index 2345c2e..0e9d82d 100644 --- a/dissmodel/geo/vector/neighborhood.py +++ b/dissmodel/geo/vector/neighborhood.py @@ -127,10 +127,14 @@ def attach_neighbors( Examples -------- - >>> from libpysal.weights import Queen - >>> gdf = attach_neighbors(gdf, strategy=Queen) - >>> gdf = attach_neighbors(gdf, neighbors_dict="neighborhood.json") - >>> gdf = attach_neighbors(gdf, strategy=Queen, ids="cell_id") + ```python + from libpysal.weights import Queen + + # gdf: an existing GeoDataFrame (e.g. from vector_grid or read_file) + gdf = attach_neighbors(gdf, strategy=Queen) + gdf = attach_neighbors(gdf, neighbors_dict="neighborhood.json") + gdf = attach_neighbors(gdf, strategy=Queen, ids="cell_id") + ``` """ resolved = _resolve_neighbors_dict(neighbors_dict) @@ -173,8 +177,10 @@ def get_neighbors(gdf: gpd.GeoDataFrame, idx: Any) -> list[Any]: Examples -------- - >>> get_neighbors(gdf, "10-5") - ['9-5', '11-5', '10-4', '10-6'] + ```python + # gdf: a GeoDataFrame with a "_neighs" column from attach_neighbors() + get_neighbors(gdf, "10-5") # ['9-5', '11-5', '10-4', '10-6'] + ``` """ if "_neighs" not in gdf.columns: raise ValueError( @@ -216,8 +222,10 @@ def get_neighbor_values( Examples -------- - >>> get_neighbor_values(gdf, "10-5", "land_use") - [1, 1, 2, 1] + ```python + # gdf: a GeoDataFrame with a "_neighs" column from attach_neighbors() + get_neighbor_values(gdf, "10-5", "land_use") # [1, 1, 2, 1] + ``` """ neighbors = get_neighbors(gdf, idx) if attr not in gdf.columns: @@ -246,7 +254,10 @@ def export_neighbors(gdf: gpd.GeoDataFrame, path: str) -> None: Examples -------- - >>> export_neighbors(gdf, "neighborhood.json") + ```python + # gdf: a GeoDataFrame with a "_neighs" column from attach_neighbors() + export_neighbors(gdf, "neighborhood.json") + ``` """ if "_neighs" not in gdf.columns: raise ValueError( From ad25d755d7f0829546c13a0b0594e9e7c0af9fd8 Mon Sep 17 00:00:00 2001 From: Sergio Souza Costa Date: Thu, 11 Jun 2026 18:32:25 -0300 Subject: [PATCH 04/10] doc(io): converte exemplos narrativos de load_xarray e save_xarray em blocos python simples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Os exemplos dependiam de arquivos externos e de um RasterBackend pré-existente e falhavam como doctest. Mantidos como documentação ilustrativa sem prompts >>>. Co-Authored-By: Claude Fable 5 --- dissmodel/io/_xarray.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/dissmodel/io/_xarray.py b/dissmodel/io/_xarray.py index 5b4345f..981d20f 100644 --- a/dissmodel/io/_xarray.py +++ b/dissmodel/io/_xarray.py @@ -50,9 +50,10 @@ def load_xarray(uri: str, minio_client=None, **kwargs): Examples -------- - >>> backend, checksum = load_xarray("simulation_step_42.nc") - >>> backend.band_names() - ['uso', 'alt', 'solo'] + ```python + backend, checksum = load_xarray("simulation_step_42.nc") + backend.band_names() # ['uso', 'alt', 'solo'] + ``` """ try: import xarray as xr @@ -119,10 +120,13 @@ def save_xarray( Examples -------- - >>> checksum = save_xarray(backend, "output_step_42.nc", step=42) + ```python + # backend: a RasterBackend (e.g. from load_xarray or vector_to_raster_backend) + checksum = save_xarray(backend, "output_step_42.nc", step=42) - >>> # save as Zarr (requires zarr package) - >>> checksum = save_xarray(backend, "output.zarr", step=42) + # save as Zarr (requires zarr package) + checksum = save_xarray(backend, "output.zarr", step=42) + ``` """ try: import xarray # noqa: F401 — availability check; used via to_xarray() From 1e2642a80f2f68f584a8fbddc77048ef44b20bbd Mon Sep 17 00:00:00 2001 From: Sergio Souza Costa Date: Thu, 11 Jun 2026 18:32:47 -0300 Subject: [PATCH 05/10] doc(io): converte exemplo narrativo de vector_to_raster_backend em bloco python simples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit O exemplo dependia de um shapefile externo e falhava como doctest. Mantido como documentação ilustrativa sem prompts >>>. Co-Authored-By: Claude Fable 5 --- dissmodel/io/convert.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/dissmodel/io/convert.py b/dissmodel/io/convert.py index 457ea24..afb1596 100644 --- a/dissmodel/io/convert.py +++ b/dissmodel/io/convert.py @@ -67,15 +67,17 @@ def vector_to_raster_backend( Examples -------- - >>> # From file path - >>> b = vector_to_raster_backend( - ... "data/mangue_grid.shp", resolution=100, attrs=["uso", "alt"] - ... ) - - >>> # From in-memory GeoDataFrame - >>> import geopandas as gpd - >>> gdf = gpd.read_file("data/mangue_grid.shp").to_crs("EPSG:31984") - >>> b = vector_to_raster_backend(gdf, resolution=100, attrs={"uso": -1}) + ```python + # From file path + b = vector_to_raster_backend( + "data/mangue_grid.shp", resolution=100, attrs=["uso", "alt"] + ) + + # From in-memory GeoDataFrame + import geopandas as gpd + gdf = gpd.read_file("data/mangue_grid.shp").to_crs("EPSG:31984") + b = vector_to_raster_backend(gdf, resolution=100, attrs={"uso": -1}) + ``` """ try: import rasterio From e5417da623c3b4c161c4e6fbd29d1b632b34822f Mon Sep 17 00:00:00 2001 From: Sergio Souza Costa Date: Thu, 11 Jun 2026 18:34:49 -0300 Subject: [PATCH 06/10] doc(visualization): converte exemplo narrativo de Chart em bloco python simples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit O exemplo assumia Environment no escopo e falhava como doctest. Mantido como documentação ilustrativa sem prompts >>>. Co-Authored-By: Claude Fable 5 --- dissmodel/visualization/chart.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/dissmodel/visualization/chart.py b/dissmodel/visualization/chart.py index ce0cc63..7c42b2d 100644 --- a/dissmodel/visualization/chart.py +++ b/dissmodel/visualization/chart.py @@ -94,9 +94,13 @@ class Chart(Model): Examples -------- - >>> env = Environment(end_time=30) - >>> Chart(show_legend=True, show_grid=True, title="SIR Model") - >>> env.run() + ```python + from dissmodel.core import Environment + + env = Environment(end_time=30) + Chart(show_legend=True, show_grid=True, title="SIR Model") + env.run() + ``` """ fig: matplotlib.figure.Figure From fbf5893b4911ab6385d5c3edb9eed2db409673de Mon Sep 17 00:00:00 2001 From: Sergio Souza Costa Date: Thu, 11 Jun 2026 18:34:49 -0300 Subject: [PATCH 07/10] doc(visualization): converte exemplo narrativo de Map em bloco python simples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit O exemplo assumia Environment e um GeoDataFrame (grid) no escopo e falhava como doctest. Mantido como documentação ilustrativa sem prompts >>>. Co-Authored-By: Claude Fable 5 --- dissmodel/visualization/map.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/dissmodel/visualization/map.py b/dissmodel/visualization/map.py index 89fecde..eb10202 100644 --- a/dissmodel/visualization/map.py +++ b/dissmodel/visualization/map.py @@ -50,9 +50,14 @@ class Map(Model): Examples -------- - >>> env = Environment(end_time=10) - >>> Map(gdf=grid, plot_params={"column": "state", "cmap": "viridis"}) - >>> env.run() + ```python + from dissmodel.core import Environment + + # grid: a GeoDataFrame (e.g. from vector_grid or read_file) + env = Environment(end_time=10) + Map(gdf=grid, plot_params={"column": "state", "cmap": "viridis"}) + env.run() + ``` """ # Narrowing the base Model.setup(**kwargs) contract is intentional: From 69f412ab206ee13b83ec9d2484d788bd1fdf5bdc Mon Sep 17 00:00:00 2001 From: Sergio Souza Costa Date: Thu, 11 Jun 2026 18:34:49 -0300 Subject: [PATCH 08/10] doc(visualization): converte exemplo narrativo de display_inputs em bloco python simples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit O exemplo assumia instâncias de modelo e o módulo streamlit no escopo e falhava como doctest. Mantido como documentação ilustrativa sem prompts >>>. Co-Authored-By: Claude Fable 5 --- dissmodel/visualization/widgets.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dissmodel/visualization/widgets.py b/dissmodel/visualization/widgets.py index f47ae36..3b0dbf7 100644 --- a/dissmodel/visualization/widgets.py +++ b/dissmodel/visualization/widgets.py @@ -30,8 +30,11 @@ def display_inputs(obj: Any, st: Any) -> None: Examples -------- - >>> display_inputs(sir_model, st.sidebar) - >>> display_inputs(ca_model, st) + ```python + # sir_model, ca_model: Model instances; st: the imported streamlit module + display_inputs(sir_model, st.sidebar) + display_inputs(ca_model, st) + ``` """ annotations: dict[str, Any] = getattr(obj, "__annotations__", {}) From 2ae94a4a4e7e557af19abd759d64a9d5df9c41ae Mon Sep 17 00:00:00 2001 From: Sergio Souza Costa Date: Thu, 11 Jun 2026 18:35:42 -0300 Subject: [PATCH 09/10] ci: simplifica step de doctests para rodar sobre todo o pacote dissmodel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Com todos os exemplos >>> agora autocontidos, a lista fixa de módulos deixa de ser necessária. Co-Authored-By: Claude Fable 5 --- .github/workflows/ci.yml | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9e3a213..5455a1d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,22 +55,11 @@ jobs: - name: Run tests with coverage run: pytest tests/ --cov=dissmodel --cov-report=term-missing --cov-report=xml - # Scoped to the modules whose Examples sections are runnable doctests; - # the remaining modules have illustrative pseudo-examples (external - # data / optional deps) — converting them is tracked as a follow-up. + # All >>> examples in the package are self-contained doctests; + # illustrative snippets use plain ```python fences instead + # (see CONTRIBUTING.md, "Documentation / Docstrings"). - name: Run doctests - run: | - pytest --doctest-modules \ - dissmodel/core/model.py \ - dissmodel/core/environment.py \ - dissmodel/geo/raster/backend.py \ - dissmodel/geo/raster/raster_grid.py \ - dissmodel/geo/raster/raster_model.py \ - dissmodel/geo/raster/cellular_automaton.py \ - dissmodel/geo/raster/sync_model.py \ - dissmodel/geo/vector/vector_grid.py \ - dissmodel/geo/vector/cellular_automaton.py \ - dissmodel/geo/vector/sync_model.py + run: pytest --doctest-modules dissmodel - name: Run mypy run: mypy dissmodel --ignore-missing-imports \ No newline at end of file From bcaca230621cdc81af929a8e2e14a583214ef1a5 Mon Sep 17 00:00:00 2001 From: Sergio Souza Costa Date: Thu, 11 Jun 2026 18:36:05 -0300 Subject: [PATCH 10/10] =?UTF-8?q?doc:=20documenta=20conven=C3=A7=C3=A3o=20?= =?UTF-8?q?de=20exemplos=20com=20e=20sem=20doctest=20no=20CONTRIBUTING?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- CONTRIBUTING.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a9e6b62..73ff052 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -50,5 +50,16 @@ If you have an idea for a new feature or improvement, please open an issue and t - Use type hints where possible. - Write docstrings for new functions and classes (NumPy style). +## Documentation / Docstrings + +Examples in NumPy-style docstrings that use `>>>` prompts are executed as +doctests in CI (`pytest --doctest-modules dissmodel`) and must be fully +self-contained and runnable — every name they use must be defined within the +example itself, and the expected output must match exactly. Longer +illustrative examples that assume objects from a broader context (e.g. an +existing GeoDataFrame, `Environment`, or model instance) should use plain +` ```python ` fenced code blocks instead of `>>>` prompts; mkdocstrings +renders both forms in the API reference. + ## License By contributing, you agree that your contributions will be licensed under the MIT License. \ No newline at end of file