interpretation-models 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of interpretation-models might be problematic. Click here for more details.
- interpretation_models-0.1.0/LICENSE +21 -0
- interpretation_models-0.1.0/PKG-INFO +18 -0
- interpretation_models-0.1.0/README.md +7 -0
- interpretation_models-0.1.0/pyproject.toml +28 -0
- interpretation_models-0.1.0/setup.cfg +4 -0
- interpretation_models-0.1.0/src/interpretation_models.egg-info/PKG-INFO +18 -0
- interpretation_models-0.1.0/src/interpretation_models.egg-info/SOURCES.txt +21 -0
- interpretation_models-0.1.0/src/interpretation_models.egg-info/dependency_links.txt +1 -0
- interpretation_models-0.1.0/src/interpretation_models.egg-info/requires.txt +2 -0
- interpretation_models-0.1.0/src/interpretation_models.egg-info/top_level.txt +2 -0
- interpretation_models-0.1.0/src/mappers/__init__.py +1 -0
- interpretation_models-0.1.0/src/mappers/mappers_dsis.py +93 -0
- interpretation_models-0.1.0/src/mappers/surface_helpers.py +12 -0
- interpretation_models-0.1.0/src/models/__init__.py +0 -0
- interpretation_models-0.1.0/src/models/extent.py +33 -0
- interpretation_models-0.1.0/src/models/interpretation.py +50 -0
- interpretation_models-0.1.0/src/models/origin.py +19 -0
- interpretation_models-0.1.0/src/models/py.typed +0 -0
- interpretation_models-0.1.0/src/models/surface.py +25 -0
- interpretation_models-0.1.0/src/models/surfacegrid_sidv2.py +67 -0
- interpretation_models-0.1.0/tests/test_extent.py +34 -0
- interpretation_models-0.1.0/tests/test_surface.py +13 -0
- interpretation_models-0.1.0/tests/test_surfacegrid_json_validation.py +15 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Equinor
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: interpretation-models
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Interpretation models maintained by the SID team
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Dist: dsis-schemas>=0.0.6
|
|
9
|
+
Requires-Dist: pydantic<3,>=2
|
|
10
|
+
Dynamic: license-file
|
|
11
|
+
|
|
12
|
+
# Interpretation models
|
|
13
|
+
|
|
14
|
+
This repo is meant to contain the core models for interpretations - horizons, faults, surface grids, polygons, pointsets -
|
|
15
|
+
handled by the SID team in SUB/EXD/DI/SDD
|
|
16
|
+
|
|
17
|
+
Models are contained in the src folder, and are meant to be used as a basis for the interpretations ingested into OSDU and
|
|
18
|
+
the Surfaces API im APIM.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Interpretation models
|
|
2
|
+
|
|
3
|
+
This repo is meant to contain the core models for interpretations - horizons, faults, surface grids, polygons, pointsets -
|
|
4
|
+
handled by the SID team in SUB/EXD/DI/SDD
|
|
5
|
+
|
|
6
|
+
Models are contained in the src folder, and are meant to be used as a basis for the interpretations ingested into OSDU and
|
|
7
|
+
the Surfaces API im APIM.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "interpretation-models"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Interpretation models maintained by the SID team"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"dsis-schemas>=0.0.6",
|
|
9
|
+
"pydantic>=2, <3",
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
[build-system]
|
|
13
|
+
requires = ["setuptools>=61.0"]
|
|
14
|
+
build-backend = "setuptools.build_meta"
|
|
15
|
+
|
|
16
|
+
[tool.setuptools.packages.find]
|
|
17
|
+
where = ["src"]
|
|
18
|
+
|
|
19
|
+
[tool.setuptools.package-data]
|
|
20
|
+
"models" = ["py.typed"]
|
|
21
|
+
|
|
22
|
+
[dependency-groups]
|
|
23
|
+
dev = [
|
|
24
|
+
"pytest>=9.0.2",
|
|
25
|
+
"mypy>=1.19.1",
|
|
26
|
+
"ruff>=0.15.0",
|
|
27
|
+
"ipykernel>=7.2.0",
|
|
28
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: interpretation-models
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Interpretation models maintained by the SID team
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Dist: dsis-schemas>=0.0.6
|
|
9
|
+
Requires-Dist: pydantic<3,>=2
|
|
10
|
+
Dynamic: license-file
|
|
11
|
+
|
|
12
|
+
# Interpretation models
|
|
13
|
+
|
|
14
|
+
This repo is meant to contain the core models for interpretations - horizons, faults, surface grids, polygons, pointsets -
|
|
15
|
+
handled by the SID team in SUB/EXD/DI/SDD
|
|
16
|
+
|
|
17
|
+
Models are contained in the src folder, and are meant to be used as a basis for the interpretations ingested into OSDU and
|
|
18
|
+
the Surfaces API im APIM.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/interpretation_models.egg-info/PKG-INFO
|
|
5
|
+
src/interpretation_models.egg-info/SOURCES.txt
|
|
6
|
+
src/interpretation_models.egg-info/dependency_links.txt
|
|
7
|
+
src/interpretation_models.egg-info/requires.txt
|
|
8
|
+
src/interpretation_models.egg-info/top_level.txt
|
|
9
|
+
src/mappers/__init__.py
|
|
10
|
+
src/mappers/mappers_dsis.py
|
|
11
|
+
src/mappers/surface_helpers.py
|
|
12
|
+
src/models/__init__.py
|
|
13
|
+
src/models/extent.py
|
|
14
|
+
src/models/interpretation.py
|
|
15
|
+
src/models/origin.py
|
|
16
|
+
src/models/py.typed
|
|
17
|
+
src/models/surface.py
|
|
18
|
+
src/models/surfacegrid_sidv2.py
|
|
19
|
+
tests/test_extent.py
|
|
20
|
+
tests/test_surface.py
|
|
21
|
+
tests/test_surfacegrid_json_validation.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Mappers for converting between internal models and external schemas."""
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import math
|
|
3
|
+
|
|
4
|
+
from models.origin import Project
|
|
5
|
+
from models.interpretation import SourceMetadata, OWMetadata, PipelineMetadata
|
|
6
|
+
from models.surface import GridGeometry, Surface
|
|
7
|
+
from dsis_model_sdk.models.common import SurfaceGrid, SurfaceGridProperties
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def normalize_surfacegrid_payload(payload: dict) -> dict:
|
|
11
|
+
normalized = dict(payload)
|
|
12
|
+
|
|
13
|
+
rotation_i = normalized.get("rotation_i")
|
|
14
|
+
if rotation_i is not None:
|
|
15
|
+
normalized["rotation_i"] = round(float(rotation_i), 4)
|
|
16
|
+
|
|
17
|
+
rotation_j = normalized.get("rotation_j")
|
|
18
|
+
if rotation_j is not None:
|
|
19
|
+
normalized["rotation_j"] = round(float(rotation_j), 4)
|
|
20
|
+
|
|
21
|
+
data_min = normalized.get("data_min")
|
|
22
|
+
if data_min is not None:
|
|
23
|
+
normalized["data_min"] = round(float(data_min), 3)
|
|
24
|
+
|
|
25
|
+
data_max = normalized.get("data_max")
|
|
26
|
+
if data_max is not None:
|
|
27
|
+
normalized["data_max"] = round(float(data_max), 3)
|
|
28
|
+
|
|
29
|
+
return normalized
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def ow_to_sid(
|
|
33
|
+
project: Project,
|
|
34
|
+
ow_surface: SurfaceGrid | SurfaceGridProperties,
|
|
35
|
+
pipeline_metadata: PipelineMetadata | None = None,
|
|
36
|
+
) -> Surface:
|
|
37
|
+
"""Map OW surface schema to the internal Surface model.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
ow_surface: DSIS CommonModel surface object to convert
|
|
41
|
+
pipeline_metadata: metadata calculated within or related to the run of the pipeline
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
Surface instance
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def convert_date_to_utc(
|
|
48
|
+
date: datetime.datetime | None = None, timezone: str | None = None
|
|
49
|
+
) -> datetime.datetime | None:
|
|
50
|
+
pass # TODO: implement time conversion to UTC based on the timezone from Project table
|
|
51
|
+
|
|
52
|
+
if ow_surface.crs is None:
|
|
53
|
+
raise ValueError("SurfaceGrid.crs is required to map to SourceMetadata")
|
|
54
|
+
|
|
55
|
+
source_metadata = SourceMetadata(
|
|
56
|
+
project=project,
|
|
57
|
+
native_uid=ow_surface.native_uid,
|
|
58
|
+
name=ow_surface.map_data_set_name,
|
|
59
|
+
crs=ow_surface.crs,
|
|
60
|
+
z_domain=ow_surface.data_domain,
|
|
61
|
+
z_unit=ow_surface.z_unit,
|
|
62
|
+
create_user=ow_surface.create_user_id,
|
|
63
|
+
update_user=ow_surface.update_user_id,
|
|
64
|
+
remark=ow_surface.remark,
|
|
65
|
+
create_date=ow_surface.create_date,
|
|
66
|
+
create_date_utc=convert_date_to_utc(ow_surface.create_date, project.timezone),
|
|
67
|
+
update_date=ow_surface.update_date,
|
|
68
|
+
update_date_utc=convert_date_to_utc(ow_surface.update_date, project.timezone),
|
|
69
|
+
ow=OWMetadata(
|
|
70
|
+
geo_name=ow_surface.geo_name,
|
|
71
|
+
geo_type=ow_surface.geo_type,
|
|
72
|
+
attribute=ow_surface.attribute,
|
|
73
|
+
),
|
|
74
|
+
)
|
|
75
|
+
geometry = GridGeometry(
|
|
76
|
+
ncol=ow_surface.num_cols,
|
|
77
|
+
nrow=ow_surface.num_rows,
|
|
78
|
+
xori=ow_surface.rotation_origin_x,
|
|
79
|
+
yori=ow_surface.rotation_origin_y,
|
|
80
|
+
xinc=ow_surface.grid_interval_x,
|
|
81
|
+
yinc=ow_surface.grid_interval_y,
|
|
82
|
+
rotation=math.degrees(ow_surface.rotation_i)
|
|
83
|
+
if ow_surface.rotation_i is not None
|
|
84
|
+
else None,
|
|
85
|
+
left_handed=True, # TODO: should this be default for surfaces from OW?
|
|
86
|
+
)
|
|
87
|
+
return Surface(
|
|
88
|
+
source=source_metadata,
|
|
89
|
+
pipeline=pipeline_metadata,
|
|
90
|
+
geometry=geometry,
|
|
91
|
+
extent=None, # TODO: calculate from grid geometry
|
|
92
|
+
collection=[], # TODO
|
|
93
|
+
)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from collections.abc import Mapping
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def flatten_dict(obj: Mapping, prefix: str = "", sep: str = ".") -> dict[str, object]:
|
|
5
|
+
flat: dict[str, object] = {}
|
|
6
|
+
for key, value in obj.items():
|
|
7
|
+
full_key = f"{prefix}{sep}{key}" if prefix else str(key)
|
|
8
|
+
if isinstance(value, Mapping):
|
|
9
|
+
flat.update(flatten_dict(value, prefix=full_key, sep=sep))
|
|
10
|
+
else:
|
|
11
|
+
flat[full_key] = value
|
|
12
|
+
return flat
|
|
File without changes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from pydantic import BaseModel, field_validator
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Point(BaseModel):
|
|
5
|
+
"""A 2D coordinate point."""
|
|
6
|
+
|
|
7
|
+
x: float
|
|
8
|
+
y: float
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Extent(BaseModel):
|
|
12
|
+
"""A polygon extent defined by corner points."""
|
|
13
|
+
|
|
14
|
+
points: list[Point]
|
|
15
|
+
|
|
16
|
+
@field_validator("points")
|
|
17
|
+
@classmethod
|
|
18
|
+
def validate_minimum_points(cls, v):
|
|
19
|
+
if len(v) < 3:
|
|
20
|
+
raise ValueError("Extent must have at least 3 points to form a polygon")
|
|
21
|
+
return v
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def is_closed(self) -> bool:
|
|
25
|
+
"""Check if the polygon is closed (first and last points are the same)."""
|
|
26
|
+
if len(self.points) < 2:
|
|
27
|
+
return False
|
|
28
|
+
return self.points[0] == self.points[-1]
|
|
29
|
+
|
|
30
|
+
def close(self) -> None:
|
|
31
|
+
"""Close the polygon by appending the first point at the end if not already closed."""
|
|
32
|
+
if not self.is_closed and len(self.points) > 0:
|
|
33
|
+
self.points.append(self.points[0])
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from pydantic import BaseModel
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from models.extent import Extent
|
|
4
|
+
from models.origin import Collection, Project
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class OWMetadata(BaseModel):
|
|
8
|
+
geo_name: str | None = None
|
|
9
|
+
geo_type: str | None = None
|
|
10
|
+
attribute: str | None = None
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class PetrelMetadata(BaseModel):
|
|
14
|
+
business_project: str | None = None
|
|
15
|
+
data_status: str | None = None
|
|
16
|
+
confidence_factor: str | None = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SourceMetadata(BaseModel):
|
|
20
|
+
project: Project
|
|
21
|
+
native_uid: str | None = None
|
|
22
|
+
name: str
|
|
23
|
+
crs: str
|
|
24
|
+
z_domain: str | None = None
|
|
25
|
+
z_unit: str | None = None
|
|
26
|
+
create_user: str | None = None
|
|
27
|
+
update_user: str | None = None
|
|
28
|
+
remark: str | None = None
|
|
29
|
+
create_date: datetime | None = None
|
|
30
|
+
create_date_utc: datetime | None = None
|
|
31
|
+
update_date: datetime | None = None
|
|
32
|
+
update_date_utc: datetime | None = None
|
|
33
|
+
ow: OWMetadata | None = None
|
|
34
|
+
petrel: PetrelMetadata | None = None
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class PipelineMetadata(BaseModel):
|
|
38
|
+
id: str # SID UUID
|
|
39
|
+
create_date: datetime | None = None
|
|
40
|
+
update_date: datetime | None = None
|
|
41
|
+
file_availability: str | None = None
|
|
42
|
+
deleted: bool | None = None
|
|
43
|
+
deleted_date: datetime | None = None
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class Interpretation(BaseModel):
|
|
47
|
+
source: SourceMetadata | None = None
|
|
48
|
+
pipeline: PipelineMetadata | None = None
|
|
49
|
+
extent: Extent | None = None
|
|
50
|
+
collection: list[Collection]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from pydantic import BaseModel
|
|
2
|
+
from enum import Enum
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class SourceSystem(str, Enum):
|
|
6
|
+
OPENWORKS = "OpenWorks R5000" # or 'OpenWorks'?
|
|
7
|
+
PETREL = "Petrel Studio"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Project(BaseModel):
|
|
11
|
+
source_system: SourceSystem
|
|
12
|
+
database: str
|
|
13
|
+
name: str
|
|
14
|
+
timezone: str
|
|
15
|
+
last_pipeline_run_date: str | None = None
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Collection(BaseModel):
|
|
19
|
+
id: str # SID UUID
|
|
File without changes
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from pydantic import BaseModel
|
|
2
|
+
from models.interpretation import Interpretation
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class GridGeometry(BaseModel):
|
|
6
|
+
ncol: int | None = None
|
|
7
|
+
nrow: int | None = None
|
|
8
|
+
xori: float | None = None
|
|
9
|
+
yori: float | None = None
|
|
10
|
+
xinc: float | None = None
|
|
11
|
+
yinc: float | None = None
|
|
12
|
+
rotation: float | None = None
|
|
13
|
+
left_handed: bool | None = True # yflip
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Surface(Interpretation):
|
|
17
|
+
geometry: GridGeometry | None = None
|
|
18
|
+
parent_surface_id: str | None = (
|
|
19
|
+
None # for SurfaceGridProperties objects? source or SID id?
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# Redundant?
|
|
23
|
+
z_non: float | None = None
|
|
24
|
+
ntotal: int | None = None
|
|
25
|
+
nnan: int | None = None
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from pydantic import BaseModel
|
|
3
|
+
|
|
4
|
+
# this class is just here for development purposes, to compare the v2 and v3 models; can be removed later
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class SurfaceGrid_SIDv2(BaseModel):
|
|
8
|
+
ssdf_uuid: str | None = None
|
|
9
|
+
|
|
10
|
+
# Source
|
|
11
|
+
source: str | None = None
|
|
12
|
+
source_database: str | None = None
|
|
13
|
+
source_project: str | None = None
|
|
14
|
+
source_grid_id: str | None = None
|
|
15
|
+
|
|
16
|
+
# Surface properties
|
|
17
|
+
surface_name: str | None = None
|
|
18
|
+
geo_name: str | None = None
|
|
19
|
+
geo_type: str | None = None
|
|
20
|
+
z_unit: str | None = None
|
|
21
|
+
z_non: float | None = None
|
|
22
|
+
z_domain: str | None = None
|
|
23
|
+
attribute_source: str | None = None
|
|
24
|
+
interpreter_source: str | None = None
|
|
25
|
+
create_user_source: str | None = None
|
|
26
|
+
update_user_source: str | None = None
|
|
27
|
+
remark_source: str | None = None
|
|
28
|
+
business_project_source: str | None = None
|
|
29
|
+
data_status_source: str | None = None
|
|
30
|
+
confidence_factor_source: str | None = None
|
|
31
|
+
|
|
32
|
+
# Coordinate systems
|
|
33
|
+
object_coordinate_system_name_source: str | None = None # OpenWorks R5000
|
|
34
|
+
object_coordinate_system_unit_source: str | None = None # OpenWorks R5000
|
|
35
|
+
object_coordinate_system_id_source: str | None = None # OpenWorks R5000
|
|
36
|
+
projected_coordinate_system: str | None = None # Petrel Studio
|
|
37
|
+
projected_coordinate_unit: str | None = None # Petrel Studio
|
|
38
|
+
projected_coordinate_uuid: str | None = None # Petrel Studio
|
|
39
|
+
|
|
40
|
+
# Grid geometry and properties
|
|
41
|
+
xinc: float | None = None
|
|
42
|
+
yinc: float | None = None
|
|
43
|
+
xori: float | None = None
|
|
44
|
+
yori: float | None = None
|
|
45
|
+
rotation: float | None = None
|
|
46
|
+
yflip: int | None = None
|
|
47
|
+
ncol: int | None = None
|
|
48
|
+
nrow: int | None = None
|
|
49
|
+
ntotal: int | None = None
|
|
50
|
+
nnan: int | None = None
|
|
51
|
+
|
|
52
|
+
# Timestamps
|
|
53
|
+
create_date: datetime | None = None
|
|
54
|
+
create_date_source: datetime | None = None
|
|
55
|
+
create_date_source_utc: datetime | None = None
|
|
56
|
+
update_date: datetime | None = None
|
|
57
|
+
update_date_source: datetime | None = None
|
|
58
|
+
update_date_source_utc: datetime | None = None
|
|
59
|
+
|
|
60
|
+
# SMDA
|
|
61
|
+
smda_project_uuid: str | None = None
|
|
62
|
+
cs_smda_project_uuid: int | None = None
|
|
63
|
+
|
|
64
|
+
# Bulk file and deletion status
|
|
65
|
+
file_availability: str | None = None
|
|
66
|
+
deleted: bool | None = None
|
|
67
|
+
deleted_date: datetime | None = None
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from pydantic import ValidationError
|
|
3
|
+
from models.extent import Extent, Point
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_extent_validate_minimum_points_valid():
|
|
7
|
+
"""Test that Extent accepts 3 or more points."""
|
|
8
|
+
# Test with exactly 3 points (minimum valid)
|
|
9
|
+
extent = Extent(points=[Point(x=0, y=0), Point(x=1, y=0), Point(x=0, y=1)])
|
|
10
|
+
assert len(extent.points) == 3
|
|
11
|
+
|
|
12
|
+
# Test with 4 points
|
|
13
|
+
extent = Extent(
|
|
14
|
+
points=[Point(x=0, y=0), Point(x=1, y=0), Point(x=1, y=1), Point(x=0, y=1)]
|
|
15
|
+
)
|
|
16
|
+
assert len(extent.points) == 4
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_extent_validate_minimum_points_invalid():
|
|
20
|
+
"""Test that Extent rejects less than 3 points."""
|
|
21
|
+
# Test with 2 points (invalid)
|
|
22
|
+
with pytest.raises(ValidationError) as exc_info:
|
|
23
|
+
Extent(points=[Point(x=0, y=0), Point(x=1, y=0)])
|
|
24
|
+
assert "at least 3 points" in str(exc_info.value)
|
|
25
|
+
|
|
26
|
+
# Test with 1 point (invalid)
|
|
27
|
+
with pytest.raises(ValidationError) as exc_info:
|
|
28
|
+
Extent(points=[Point(x=0, y=0)])
|
|
29
|
+
assert "at least 3 points" in str(exc_info.value)
|
|
30
|
+
|
|
31
|
+
# Test with 0 points (invalid)
|
|
32
|
+
with pytest.raises(ValidationError) as exc_info:
|
|
33
|
+
Extent(points=[])
|
|
34
|
+
assert "at least 3 points" in str(exc_info.value)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from pydantic import ValidationError
|
|
3
|
+
from models.surface import Surface
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_surface_grid_missing_required_field():
|
|
7
|
+
with pytest.raises(ValidationError):
|
|
8
|
+
Surface(
|
|
9
|
+
id="11111111-1111-1111-1111-111111111111",
|
|
10
|
+
crs="ST_ED50_UTM31N_P23031_T1133",
|
|
11
|
+
rotation=0.0,
|
|
12
|
+
# name omitted on purpose
|
|
13
|
+
)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from dsis_model_sdk.models.common import SurfaceGrid
|
|
3
|
+
from pydantic import ValidationError
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_surfacegrid_raw_json_fails_strict_validation(surfacegrid_payload: dict):
|
|
7
|
+
with pytest.raises(ValidationError):
|
|
8
|
+
SurfaceGrid.model_validate(surfacegrid_payload)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_surfacegrid_normalized_json_validates(
|
|
12
|
+
surfacegrid_payload_normalized: dict,
|
|
13
|
+
):
|
|
14
|
+
obj = SurfaceGrid.model_validate(surfacegrid_payload_normalized)
|
|
15
|
+
assert isinstance(obj, SurfaceGrid)
|