Skip to content

Commit

Permalink
ENH: Make ObjectDataProviders return Pydantic models
Browse files Browse the repository at this point in the history
  • Loading branch information
mferrera committed Jun 12, 2024
1 parent eae2ea1 commit 1547032
Show file tree
Hide file tree
Showing 13 changed files with 237 additions and 238 deletions.
212 changes: 112 additions & 100 deletions schema/definitions/0.8.0/schema/fmu_meta.json

Large diffs are not rendered by default.

9 changes: 0 additions & 9 deletions src/fmu/dataio/_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,6 @@ class ExportFolder(str, Enum):
tables = "tables"


class Layout(str, Enum):
regular = "regular"
unset = "unset"
cornerpoint = "cornerpoint"
table = "table"
dictionary = "dictionary"
faultroom_triangulated = "faultroom_triangulated"


STANDARD_TABLE_INDEX_COLUMNS: Final[dict[str, list[str]]] = {
"volumes": ["ZONE", "REGION", "FACIES", "LICENCE"],
"rft": ["measured_depth", "well", "time"],
Expand Down
10 changes: 3 additions & 7 deletions src/fmu/dataio/_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
from . import types
from ._definitions import SCHEMA, SOURCE, VERSION, FmuContext
from ._logging import null_logger
from ._utils import drop_nones
from .datastructure._internal import internal
from .datastructure.meta import meta
from .exceptions import InvalidMetadataError
Expand Down Expand Up @@ -109,8 +108,7 @@ def generate_export_metadata(
dataio: ExportData,
fmudata: FmuProvider | None = None,
compute_md5: bool = True,
skip_null: bool = True,
) -> dict: # TODO! -> skip_null?
) -> internal.DataClassMeta:
"""
Main function to generate the full metadata
Expand Down Expand Up @@ -141,7 +139,7 @@ def generate_export_metadata(
objdata = objectdata_provider_factory(obj, dataio)
masterdata = dataio.config.get("masterdata")

metadata = internal.DataClassMeta(
return internal.DataClassMeta(
schema_=TypeAdapter(AnyHttpUrl).validate_strings(SCHEMA), # type: ignore[call-arg]
version=VERSION,
source=SOURCE,
Expand All @@ -154,6 +152,4 @@ def generate_export_metadata(
tracklog=generate_meta_tracklog(),
display=_get_meta_display(dataio, objdata),
preprocessed=dataio.fmu_context == FmuContext.PREPROCESSED,
).model_dump(mode="json", exclude_none=True, by_alias=True)

return metadata if not skip_null else drop_nones(metadata)
)
7 changes: 5 additions & 2 deletions src/fmu/dataio/dataio.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from ._metadata import generate_export_metadata
from ._utils import (
detect_inside_rms, # dataio_examples,
drop_nones,
export_file,
export_metadata_file,
prettyprint_dict,
Expand Down Expand Up @@ -769,8 +770,10 @@ def generate_metadata(

self._update_fmt_flag()
fmudata = self._get_fmu_provider() if self._fmurun else None
self._metadata = generate_export_metadata(
obj, self, fmudata, compute_md5=compute_md5
self._metadata = drop_nones(
generate_export_metadata(
obj, self, fmudata, compute_md5=compute_md5
).model_dump(mode="json", exclude_none=True, by_alias=True)
)

logger.info("The metadata are now ready!")
Expand Down
4 changes: 2 additions & 2 deletions src/fmu/dataio/datastructure/meta/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,9 @@ class Content(BaseModel):
is_prediction: bool = Field(
title="Is prediction flag",
)
layout: Optional[str] = Field(
layout: Optional[enums.Layout] = Field(
default=None,
examples=["regular"],
examples=["regular", "cornerpoint"],
)
name: str = Field(
description=(
Expand Down
27 changes: 18 additions & 9 deletions src/fmu/dataio/datastructure/meta/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@
from typing import Type


class AccessLevel(str, Enum):
asset = "asset"
internal = "internal"
restricted = "restricted"


class AxisOrientation(IntEnum):
normal = 1
flipped = -1


class ContentEnum(str, Enum):
depth = "depth"
facies_thickness = "facies_thickness"
Expand Down Expand Up @@ -52,12 +63,10 @@ class FMUClassEnum(str, Enum):
dictionary = "dictionary"


class AccessLevel(str, Enum):
asset = "asset"
internal = "internal"
restricted = "restricted"


class AxisOrientation(IntEnum):
normal = 1
flipped = -1
class Layout(str, Enum):
regular = "regular"
unset = "unset"
cornerpoint = "cornerpoint"
table = "table"
dictionary = "dictionary"
faultroom_triangulated = "faultroom_triangulated"
87 changes: 37 additions & 50 deletions src/fmu/dataio/providers/objectdata/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from copy import deepcopy
from dataclasses import dataclass, field
from datetime import datetime
from typing import TYPE_CHECKING, Final
from typing import TYPE_CHECKING, Any, Final
from warnings import warn

from fmu.dataio._definitions import ConfigurationError, ValidFormats
Expand All @@ -20,10 +20,9 @@
from fmu.dataio.providers._base import Provider

if TYPE_CHECKING:
from fmu.dataio._definitions import Layout
from fmu.dataio.dataio import ExportData
from fmu.dataio.datastructure.meta.content import BoundingBox2D, BoundingBox3D
from fmu.dataio.datastructure.meta.enums import FMUClassEnum
from fmu.dataio.datastructure.meta.enums import FMUClassEnum, Layout
from fmu.dataio.datastructure.meta.specification import AnySpecification
from fmu.dataio.types import Inferrable

Expand Down Expand Up @@ -62,7 +61,7 @@ class ObjectDataProvider(Provider):
# result properties; the most important is metadata which IS the 'data' part in
# the resulting metadata. But other variables needed later are also given
# as instance properties in addition (for simplicity in other classes/functions)
_metadata: dict = field(default_factory=dict)
_metadata: AnyContent | UnsetAnyContent | None = field(default=None)
name: str = field(default="")
time0: datetime | None = field(default=None)
time1: datetime | None = field(default=None)
Expand All @@ -80,53 +79,44 @@ def __post_init__(self) -> None:

content_model = self._get_validated_content(self.dataio.content)
named_stratigraphy = self._get_named_stratigraphy()

self.name = named_stratigraphy.name
self._metadata["name"] = self.name
self._metadata["stratigraphic"] = named_stratigraphy.stratigraphic
self._metadata["offset"] = named_stratigraphy.offset
self._metadata["alias"] = named_stratigraphy.alias
self._metadata["top"] = named_stratigraphy.top
self._metadata["base"] = named_stratigraphy.base

self._metadata["content"] = (usecontent := content_model.content)

metadata: dict[str, Any] = {}
metadata["name"] = self.name
metadata["stratigraphic"] = named_stratigraphy.stratigraphic
metadata["offset"] = named_stratigraphy.offset
metadata["alias"] = named_stratigraphy.alias
metadata["top"] = named_stratigraphy.top
metadata["base"] = named_stratigraphy.base

metadata["content"] = (usecontent := content_model.content)
if content_model.content_incl_specific:
self._metadata[usecontent] = getattr(
metadata[usecontent] = getattr(
content_model.content_incl_specific, usecontent, None
)

self._metadata["tagname"] = self.dataio.tagname
self._metadata["format"] = self.fmt
self._metadata["layout"] = self.layout
self._metadata["unit"] = self.dataio.unit or ""
self._metadata["vertical_domain"] = list(self.dataio.vertical_domain.keys())[0]
self._metadata["depth_reference"] = list(self.dataio.vertical_domain.values())[
0
]

self._metadata["spec"] = (
spec.model_dump(mode="json", exclude_none=True)
if (spec := self.get_spec())
else None
)
self._metadata["bbox"] = (
bbox.model_dump(mode="json", exclude_none=True)
if (bbox := self.get_bbox())
else None
metadata["tagname"] = self.dataio.tagname
metadata["format"] = self.fmt
metadata["layout"] = self.layout
metadata["unit"] = self.dataio.unit or ""
metadata["vertical_domain"] = list(self.dataio.vertical_domain.keys())[0]
metadata["depth_reference"] = list(self.dataio.vertical_domain.values())[0]

metadata["spec"] = self.get_spec()
metadata["bbox"] = self.get_bbox()
metadata["time"] = self._get_timedata()
metadata["table_index"] = self.table_index
metadata["undef_is_zero"] = self.dataio.undef_is_zero

metadata["is_prediction"] = self.dataio.is_prediction
metadata["is_observation"] = self.dataio.is_observation
metadata["description"] = generate_description(self.dataio.description)

self._metadata = (
UnsetAnyContent.model_validate(metadata)
if metadata["content"] == "unset"
else AnyContent.model_validate(metadata)
)
self._metadata["time"] = (
timedata.model_dump(mode="json", exclude_none=True)
if (timedata := self._get_timedata())
else None
)

self._metadata["table_index"] = self.table_index
self._metadata["undef_is_zero"] = self.dataio.undef_is_zero

# timedata:
self._metadata["is_prediction"] = self.dataio.is_prediction
self._metadata["is_observation"] = self.dataio.is_observation
self._metadata["description"] = generate_description(self.dataio.description)
logger.info("Derive all metadata for data object... DONE")

@property
Expand Down Expand Up @@ -168,11 +158,8 @@ def get_spec(self) -> AnySpecification | None:
raise NotImplementedError

def get_metadata(self) -> AnyContent | UnsetAnyContent:
return (
UnsetAnyContent.model_validate(self._metadata)
if self._metadata["content"] == "unset"
else AnyContent.model_validate(self._metadata)
)
assert self._metadata is not None
return self._metadata

def _get_validated_content(self, content: str | dict | None) -> AllowedContent:
"""Check content and return a validated model."""
Expand Down
4 changes: 2 additions & 2 deletions src/fmu/dataio/providers/objectdata/_faultroom.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
from dataclasses import dataclass
from typing import Final

from fmu.dataio._definitions import ExportFolder, Layout, ValidFormats
from fmu.dataio._definitions import ExportFolder, ValidFormats
from fmu.dataio._logging import null_logger
from fmu.dataio.datastructure.meta.content import BoundingBox3D
from fmu.dataio.datastructure.meta.enums import FMUClassEnum
from fmu.dataio.datastructure.meta.enums import FMUClassEnum, Layout
from fmu.dataio.datastructure.meta.specification import FaultRoomSurfaceSpecification
from fmu.dataio.readers import FaultRoomSurface

Expand Down
4 changes: 2 additions & 2 deletions src/fmu/dataio/providers/objectdata/_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@
import pandas as pd
import xtgeo

from fmu.dataio._definitions import ExportFolder, Layout, ValidFormats
from fmu.dataio._definitions import ExportFolder, ValidFormats
from fmu.dataio._logging import null_logger
from fmu.dataio.datastructure.meta.enums import FMUClassEnum
from fmu.dataio.datastructure.meta.enums import FMUClassEnum, Layout
from fmu.dataio.readers import FaultRoomSurface

from ._base import (
Expand Down
3 changes: 1 addition & 2 deletions src/fmu/dataio/providers/objectdata/_tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@
from fmu.dataio._definitions import (
STANDARD_TABLE_INDEX_COLUMNS,
ExportFolder,
Layout,
ValidFormats,
)
from fmu.dataio._logging import null_logger
from fmu.dataio.datastructure.meta.enums import FMUClassEnum
from fmu.dataio.datastructure.meta.enums import FMUClassEnum, Layout
from fmu.dataio.datastructure.meta.specification import TableSpecification

from ._base import (
Expand Down
8 changes: 3 additions & 5 deletions src/fmu/dataio/providers/objectdata/_xtgeo.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
import pandas as pd
import xtgeo

from fmu.dataio._definitions import ExportFolder, Layout, ValidFormats
from fmu.dataio._definitions import ExportFolder, ValidFormats
from fmu.dataio._logging import null_logger
from fmu.dataio._utils import npfloat_to_float
from fmu.dataio.datastructure.meta.content import BoundingBox2D, BoundingBox3D
from fmu.dataio.datastructure.meta.enums import FMUClassEnum
from fmu.dataio.datastructure.meta.enums import FMUClassEnum, Layout
from fmu.dataio.datastructure.meta.specification import (
CPGridPropertySpecification,
CPGridSpecification,
Expand All @@ -21,9 +21,7 @@
SurfaceSpecification,
)

from ._base import (
ObjectDataProvider,
)
from ._base import ObjectDataProvider

if TYPE_CHECKING:
import pandas as pd
Expand Down
Loading

0 comments on commit 1547032

Please sign in to comment.