Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions edr_server/core/models/extents.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,25 @@ class VerticalExtent(EdrModel["VerticalExtent"]):
# * list of vertical levels (e.g. "2",10,"80","100"}
# The value `null` is supported and indicates an open vertical interval.

def __post_init__(self):
if not isinstance(self.values, List):
raise TypeError(
f'Expected List of values, received {type(self.values)}')
if not all(isinstance((invalid_value := value), (float, str)) for value in self.values):
raise TypeError(
f"Expected all float or string values, received value '{invalid_value}' of type {type(invalid_value)}")
if not isinstance(self.vrs, CrsObject):
raise TypeError(f'Expected CrsObject, received {type(self.vrs)}')

@classmethod
def _prepare_json_for_init(cls, json_dict: JsonDict) -> JsonDict:
json_dict["vrs"] = CrsObject.from_wkt(json_dict["vrs"])

with suppress(KeyError): # Remove things not required by __init__
# 'interval' stores the bounds, which is different from the 'intervals' argument to the __init__ method
del json_dict["interval"]
del json_dict["name"]

return json_dict

@classmethod
Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ version = 0.1.0
# We're affected by https://bugs.python.org/issue43923, so can only use 3.7 & 3.8
python_requires = >=3.7,<3.9
install_requires =
numpy
shapely
pyproj
tornado>=6.1
Expand Down
59 changes: 58 additions & 1 deletion tests/unit/core/models/test_extents.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import unittest
from datetime import datetime, timedelta
from shapely.geometry import Polygon
import numpy as np

from edr_server.core.models.extents import TemporalExtent, SpatialExtent
from edr_server.core.models.extents import TemporalExtent, SpatialExtent, VerticalExtent
from edr_server.core.models.time import DateTimeInterval, Duration
from edr_server.core.models.crs import CrsObject


class TemporalExtentTest(unittest.TestCase):
Expand Down Expand Up @@ -443,3 +445,58 @@ def test_init_type_checking_crs(self):

with self.assertRaisesRegex(TypeError, "Expected CrsObject, received <class 'str'>"):
SpatialExtent(poly, input)


class VerticalExtentTest(unittest.TestCase):

def test_from_json(self):
"""
GIVEN a typical json_dict
WHEN from_json is called
THEN a VerticalExtent is returned
"""
expected = VerticalExtent([1.65])

json_dict = {'interval': ['ScalarBounds(lower=1.65, upper=1.65)'],
'values': [1.65],
'vrs': 'VERTCRS["WGS_1984",VDATUM["World Geodetic System 1984"],CS[vertical,1],AXIS["ellipsoidal height (h)",up,LENGTHUNIT["metre",1,ID["EPSG",9001]]]]',
'name': 'WGS_1984'}

actual = VerticalExtent.from_json(json_dict)

self.assertEqual(actual, expected)

def test_init_type_checking_values(self):
"""
GIVEN a non-list
WHEN passed to VerticalExtent.values
THEN a TypeError is returned
"""
heights = {"value": 4}

with self.assertRaisesRegex(TypeError, "Expected List of values, received <class 'dict'>"):
VerticalExtent(values=heights)

def test_init_type_checking_values_entry(self):
"""
GIVEN a list of floats with one bad entry
WHEN passed to VerticalExtent.values
THEN a TypeError is returned with value and type
"""
vals = list(np.arange(0, 1, 0.2))
vals.append([1])

with self.assertRaisesRegex(TypeError, r"Expected all float or string values, received value '\[1\]' of type <class 'list'>"):
VerticalExtent(values=vals)

def test_init_type_checking_vrs(self):
"""
GIVEN a non-CrsObject input
WHEN passed to VerticalExtent
THEN a TypeError is returned
"""
vals = list(np.arange(0, 1, 0.2))
input = "bad input"

with self.assertRaisesRegex(TypeError, "Expected CrsObject, received <class 'str'>"):
VerticalExtent(values=vals, vrs=input)