Skip to content

Commit

Permalink
Merge pull request #178 from geo-engine/updates-2024-03-15
Browse files Browse the repository at this point in the history
Updates-2024-03-15
  • Loading branch information
jdroenner authored Mar 18, 2024
2 parents ce3990d + d3c862c commit 3651d00
Show file tree
Hide file tree
Showing 20 changed files with 127 additions and 55 deletions.
52 changes: 46 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
workflow_dispatch:

jobs:
build-and-publish:
check:
runs-on: ubuntu-22.04

strategy:
Expand Down Expand Up @@ -53,8 +53,48 @@ jobs:
python -m mypy tests
- name: Test
run: pytest
# - name: Publish
# uses: pypa/gh-action-pypi-publish@master
# with:
# password: ${{ secrets.pypi_password }}
# skip_existing: true

# Checks the library using minimum version resolution
# `uv` has this feature built-in, c.f. https://github.com/astral-sh/uv
check-min-version:
runs-on: ubuntu-22.04

env:
# use minimum supported versions from https://devguide.python.org/versions/
python-version: "3.8"
# lowest compatible versions for all direct dependencies
# cf., https://github.com/astral-sh/uv#resolution-strategy
resolution: "lowest-direct"

steps:
- uses: actions/checkout@v3
- name: APT update
run: sudo apt-get update
- name: Install system dependencies
run: sudo apt-get install libgeos-dev libproj-dev
- name: Set up Python ${{ env.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ env.python-version }}
- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install uv
uv venv
source .venv/bin/activate
uv pip install --resolution=${{ env.resolution}} -e .
uv pip install --resolution=${{ env.resolution}} -e .[dev]
- name: Build
run: |
source .venv/bin/activate
python -m build .
- name: Install test dependencies
run: |
source .venv/bin/activate
uv pip install --resolution=${{ env.resolution}} -e .[test]
- name: Test
run: |
source .venv/bin/activate
pytest
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ Keep in mind, that you need to add the missing stubs by extending the dependenci

Our tip is to activate type checking with `mypy` in your IDE.

## All checks from above

You can call `./check.sh` to run all the checks that are shown above.

## Documentation

Generate documentation HTML with:
Expand Down
30 changes: 30 additions & 0 deletions check.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/bash

set -e # exit on error

set -T

trap '! [[ "$BASH_COMMAND" =~ ^(echo|printf) ]] &&
printf "+ %s\n" "$BASH_COMMAND"' DEBUG

function echoerr() {
echo "$@" 1>&2;
}

echoerr "Running tests"

pytest

echoerr "Check code style"

python3 -m pycodestyle

echoerr "Check code with linter"

python3 -m pylint geoengine
python3 -m pylint tests

echoerr "Check code with type checker"

python3 -m mypy geoengine
python3 -m mypy tests
18 changes: 9 additions & 9 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,21 @@ packages = find:
python_requires = >=3.8
install_requires =
geoengine-openapi-client == 0.0.4
geopandas >=0.9,<0.14
matplotlib >=3.4,<3.8
geopandas >=0.9,<0.15
matplotlib >=3.5,<3.8
numpy >=1.21,<2
owslib >=0.26,<0.30
owslib >=0.27,<0.30
pillow >=9.0,<10
pyarrow >=10.0,<13
pyarrow >=10.0,<14
python-dotenv >=0.19,<1.1
rasterio >=1.2,<2
rasterio >=1.3,<2
requests >= 2.26,<3
rioxarray >=0.9.1, <0.10
StrEnum >=0.4.6,<0.5 # TODO: use from stdlib when `python_requires = >=3.11`
vega >= 3.5,<4
websockets >= 10.0,<11
xarray >=0.19,<2023.6
urllib3 >= 1.25.3, < 2.1.0
xarray >=0.19,<2024.3
urllib3 >= 2.0, < 2.3
pydantic >= 1.10.5, < 2

[options.extras_require]
Expand All @@ -47,9 +47,9 @@ dev =
twine >=3.4,<5 # PyPI
types-pkg-resources >=0.1.3 # mypy type hints
types-requests >=2.26,<3 # mypy type hints
wheel >=0.37,<0.41
wheel >=0.37,<0.44
test =
pytest >=6.2,<8
pytest >=6.3,<8
requests_mock >=1.9,<2
examples =
cartopy==0.21.1 # for WMS example
Expand Down
5 changes: 5 additions & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'''
Tests for the package.
'''

from .util import UrllibMocker
4 changes: 1 addition & 3 deletions tests/test_auth.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
'''Tests regarding Geo Engine authentication'''

from datetime import datetime

import unittest
import os
from pkg_resources import get_distribution

from test_util import UrllibMocker
import geoengine as ge
from geoengine.error import GeoEngineException
from geoengine.types import QueryRectangle
from . import UrllibMocker


class AuthTests(unittest.TestCase):
Expand Down
7 changes: 3 additions & 4 deletions tests/test_colorizer.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Tests for the colorizer module."""

import json
import sys
import unittest
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
Expand Down Expand Up @@ -124,8 +123,8 @@ def test_colormap_not_available(self):
colorizer.Colorizer.linear_with_mpl_cmap(color_map="some_map", min_max=(0.0, 255.0))

result = str(ctx.exception)
expected = f"'some_map' is not a valid value for {'cmap' if sys.version_info >= (3,8) else 'name'}; "\
"supported values are 'Accent', 'Accent_r', "\

expected_end = "supported values are 'Accent', 'Accent_r', "\
"'Blues', 'Blues_r', 'BrBG', 'BrBG_r', 'BuGn', 'BuGn_r', 'BuPu', 'BuPu_r', 'CMRmap', "\
"'CMRmap_r', 'Dark2', 'Dark2_r', 'GnBu', 'GnBu_r', 'Greens', 'Greens_r', 'Greys', 'Greys_r', "\
"'OrRd', 'OrRd_r', 'Oranges', 'Oranges_r', 'PRGn', 'PRGn_r', 'Paired', 'Paired_r', 'Pastel1', "\
Expand All @@ -148,7 +147,7 @@ def test_colormap_not_available(self):
"'terrain_r', 'turbo', " "'turbo_r', 'twilight', 'twilight_r', 'twilight_shifted', "\
"'twilight_shifted_r', 'viridis', 'viridis_r', 'winter', 'winter_r'"

assert result == expected
assert result.endswith(expected_end)

def test_defaults(self):
"""Tests the manipulation of the default values."""
Expand Down
3 changes: 1 addition & 2 deletions tests/test_datasets.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
"""Tests for the datasets module."""

import unittest

import geoengine as ge
from test_util import UrllibMocker
from . import UrllibMocker


class DatasetsTests(unittest.TestCase):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from geoengine.datasets import DatasetName, UploadId
from geoengine.layers import Layer, LayerId, LayerProviderId
from geoengine.types import RasterSymbology
from test_util import UrllibMocker
from . import UrllibMocker


class LayerTests(unittest.TestCase):
Expand Down
3 changes: 1 addition & 2 deletions tests/test_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
from datetime import datetime
import unittest
from vega import VegaLite

from test_util import UrllibMocker
import geoengine as ge
from . import UrllibMocker


class PlotTests(unittest.TestCase):
Expand Down
3 changes: 1 addition & 2 deletions tests/test_provenance.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

import unittest
from uuid import UUID
from test_util import UrllibMocker

from geoengine.types import InternalDataId, Provenance, ProvenanceEntry
import geoengine as ge
from . import UrllibMocker


class ProvenanceTests(unittest.TestCase):
Expand Down
4 changes: 1 addition & 3 deletions tests/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@

import unittest
from uuid import UUID

import datetime
from test_util import UrllibMocker

import geoengine as ge
from geoengine import BadRequestException, ValidationError, DEFAULT_ISO_TIME_FORMAT
from geoengine.tasks import CompletedTaskStatusInfo, TaskStatus, RunningTaskStatusInfo, \
AbortedTaskStatusInfo, FailedTaskStatusInfo, TaskId, Task
from . import UrllibMocker


class TaskTests(unittest.TestCase):
Expand Down
3 changes: 1 addition & 2 deletions tests/test_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
import unittest
import pandas as pd
import geopandas

from test_util import UrllibMocker
import geoengine as ge
from geoengine.datasets import DatasetName, OgrSourceDatasetTimeType, OgrSourceDuration, OgrSourceTimeFormat
from geoengine.types import TimeStepGranularity
from . import UrllibMocker


class UploadTests(unittest.TestCase):
Expand Down
3 changes: 1 addition & 2 deletions tests/test_wcs.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
'''Tests for WCS calls'''

from datetime import datetime

import unittest
import owslib.util
import requests_mock
import numpy as np
import xarray as xr
from test_util import UrllibMocker
import geoengine as ge
from . import UrllibMocker


class WcsTests(unittest.TestCase):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_wfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
import geopandas.testing # pylint: disable=unused-import
from shapely.geometry import Point
from pkg_resources import get_distribution
from test_util import UrllibMocker
import geoengine as ge
from . import UrllibMocker


class WfsTests(unittest.TestCase):
Expand Down
5 changes: 1 addition & 4 deletions tests/test_wms.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@
from datetime import datetime
import textwrap
import unittest
# import textwrap
from PIL import Image

from test_util import UrllibMocker

import geoengine as ge
from geoengine.colorizer import Colorizer
from . import UrllibMocker


class WmsTests(unittest.TestCase):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_workflow_raster_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
import pyarrow as pa
import xarray as xr
from geoengine.types import RasterBandDescriptor
from test_util import UrllibMocker
import geoengine as ge
from . import UrllibMocker


class MockWebsocket:
Expand Down
2 changes: 1 addition & 1 deletion tests/test_workflow_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import unittest
from uuid import UUID
import geoengine_openapi_client
from test_util import UrllibMocker
from geoengine.datasets import DatasetName, UploadId, StoredDataset
import geoengine as ge
from . import UrllibMocker


class WorkflowStorageTests(unittest.TestCase):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_workflow_vector_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import geopandas as gpd
import numpy as np
import pandas as pd
from test_util import UrllibMocker
import geoengine as ge
from . import UrllibMocker


class MockRequestsGet:
Expand Down
28 changes: 17 additions & 11 deletions test_util.py → tests/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,22 @@ def _handle_request(self, method, url, *_args, **kwargs):
sent_body = None

for matcher in self._matchers:
if matcher["method"] == method and matcher["url"] == url and (
matcher["requestHeaders"] is None or (
"headers" in kwargs and matcher["requestHeaders"].items() <= kwargs["headers"].items()
)
) and (
matcher["expectedRequestBody"] is None or matcher["expectedRequestBody"] == sent_body):
return urllib3.response.HTTPResponse(
status=matcher["statusCode"],
reason=UrllibMocker.STATUS_CODE_REASON_MAP[matcher["statusCode"]],
body=matcher["body"]
)
if matcher["method"] != method or matcher["url"] != url:
continue

if matcher["requestHeaders"] is not None and (
"headers" in kwargs and matcher["requestHeaders"].items() > kwargs["headers"].items()
):
continue

if matcher["expectedRequestBody"] is not None and matcher["expectedRequestBody"] != sent_body:
continue

return urllib3.response.HTTPResponse(
status=matcher["statusCode"],
reason=UrllibMocker.STATUS_CODE_REASON_MAP[matcher["statusCode"]],
body=matcher["body"]
)

# TODO: remove
print([matcher["url"] for matcher in self._matchers])
Expand All @@ -82,6 +87,7 @@ def _handle_request(self, method, url, *_args, **kwargs):

raise KeyError(f'No handler found for {method} {url}')

# pylint: disable-next=too-many-arguments # follows `requests-mock` API
def register_uri(self, method, url,
request_headers=None, expected_request_body=None, status_code=200,
json=None, text=None, body=None):
Expand Down

0 comments on commit 3651d00

Please sign in to comment.