From 4ebbf3cfd5a87b6ecc5b2779cf614df27600885e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Therese=20Natter=C3=B8y?= <61694854+tnatt@users.noreply.github.com> Date: Tue, 14 Jan 2025 10:03:15 +0100 Subject: [PATCH] MAINT: Define schema inside FmuResults model (#970) --- schemas/0.8.0/fmu_results.json | 24 +++++++++++++++++++ src/fmu/dataio/_metadata.py | 21 +++------------- .../dataio/_models/fmu_results/fmu_results.py | 7 ++++++ tests/test_units/test_metadata_class.py | 10 +++++++- 4 files changed, 43 insertions(+), 19 deletions(-) diff --git a/schemas/0.8.0/fmu_results.json b/schemas/0.8.0/fmu_results.json index 951a8e2c3..f01e82bf5 100644 --- a/schemas/0.8.0/fmu_results.json +++ b/schemas/0.8.0/fmu_results.json @@ -458,6 +458,12 @@ "CaseMetadata": { "description": "The FMU metadata model for an FMU case.\n\nA case represent a set of iterations that belong together, either by being part of\nthe same run (i.e. history matching) or by being placed together by the user,\ncorresponding to /scratch////.", "properties": { + "$schema": { + "format": "uri", + "minLength": 1, + "title": "$Schema", + "type": "string" + }, "access": { "$ref": "#/$defs/Access" }, @@ -3529,6 +3535,12 @@ "IterationMetadata": { "description": "The FMU metadata model for an FMU Iteration.\n\nAn object representing a single Iteration of a specific case.", "properties": { + "$schema": { + "format": "uri", + "minLength": 1, + "title": "$Schema", + "type": "string" + }, "access": { "$ref": "#/$defs/Access" }, @@ -4614,6 +4626,12 @@ "ObjectMetadata": { "description": "The FMU metadata model for a given data object.", "properties": { + "$schema": { + "format": "uri", + "minLength": 1, + "title": "$Schema", + "type": "string" + }, "access": { "$ref": "#/$defs/SsdlAccess" }, @@ -6454,6 +6472,12 @@ "RealizationMetadata": { "description": "The FMU metadata model for an FMU Realization.\n\nAn object representing a single Realization of a specific Iteration.", "properties": { + "$schema": { + "format": "uri", + "minLength": 1, + "title": "$Schema", + "type": "string" + }, "access": { "$ref": "#/$defs/Access" }, diff --git a/src/fmu/dataio/_metadata.py b/src/fmu/dataio/_metadata.py index 58d01b858..3d6cb8c94 100644 --- a/src/fmu/dataio/_metadata.py +++ b/src/fmu/dataio/_metadata.py @@ -12,18 +12,13 @@ from typing import TYPE_CHECKING, Final, List, Literal, Optional, Union -from pydantic import ( - AnyHttpUrl, - BaseModel, - Field, -) +from pydantic import Field from ._logging import null_logger from ._models.fmu_results import data, fields from ._models.fmu_results.enums import FMUClass from ._models.fmu_results.fmu_results import ( CaseMetadata, - FmuResultsSchema, ObjectMetadata, ) from ._models.fmu_results.global_configuration import GlobalConfiguration @@ -42,17 +37,7 @@ logger: Final = null_logger(__name__) -class JsonSchemaMetadata(BaseModel): - """Mixin to inject the $schema field into exported metadata.""" - - schema_: AnyHttpUrl = Field( - default_factory=lambda: AnyHttpUrl(FmuResultsSchema.url()), - alias="$schema", - frozen=True, - ) - - -class ObjectMetadataExport(JsonSchemaMetadata, ObjectMetadata, populate_by_name=True): +class ObjectMetadataExport(ObjectMetadata, populate_by_name=True): """Wraps the schema ObjectMetadata, adjusting some values to optional for pragmatic purposes when exporting metadata.""" @@ -65,7 +50,7 @@ class ObjectMetadataExport(JsonSchemaMetadata, ObjectMetadata, populate_by_name= preprocessed: Optional[bool] = Field(alias="_preprocessed", default=None) -class CaseMetadataExport(JsonSchemaMetadata, CaseMetadata, populate_by_name=True): +class CaseMetadataExport(CaseMetadata, populate_by_name=True): """Adds the optional description field for backward compatibility.""" class_: Literal[FMUClass.case] = Field( diff --git a/src/fmu/dataio/_models/fmu_results/fmu_results.py b/src/fmu/dataio/_models/fmu_results/fmu_results.py index 91322864d..1d6e17462 100644 --- a/src/fmu/dataio/_models/fmu_results/fmu_results.py +++ b/src/fmu/dataio/_models/fmu_results/fmu_results.py @@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Literal, Union from pydantic import ( + AnyHttpUrl, BaseModel, Field, GetJsonSchemaHandler, @@ -131,6 +132,12 @@ class MetadataBase(BaseModel): version: str = Field(default=FmuResultsSchema.VERSION) """The version of the schema that generated this data.""" + schema_: AnyHttpUrl = Field( + default_factory=lambda: AnyHttpUrl(FmuResultsSchema.url()), + alias="$schema", + ) + """The url of the schema that generated this data.""" + class CaseMetadata(MetadataBase): """The FMU metadata model for an FMU case. diff --git a/tests/test_units/test_metadata_class.py b/tests/test_units/test_metadata_class.py index c8f8f8d93..126e2deef 100644 --- a/tests/test_units/test_metadata_class.py +++ b/tests/test_units/test_metadata_class.py @@ -12,7 +12,7 @@ OperatingSystem, TracklogEvent, ) -from fmu.dataio._utils import prettyprint_dict +from fmu.dataio._utils import prettyprint_dict, read_metadata_from_file from fmu.dataio.providers.objectdata._provider import objectdata_provider_factory # pylint: disable=no-member @@ -33,6 +33,14 @@ def test_metadata_dollars(edataobj1, regsurf): assert mymeta["$schema"] == FmuResultsSchema.url() assert mymeta["source"] == FmuResultsSchema.SOURCE + # also check that it is preserved in the exported metadata + exportpath = edataobj1.export(regsurf) + exportmeta = read_metadata_from_file(exportpath) + + assert exportmeta["version"] == FmuResultsSchema.VERSION + assert exportmeta["$schema"] == FmuResultsSchema.url() + assert exportmeta["source"] == FmuResultsSchema.SOURCE + # -------------------------------------------------------------------------------------- # Tracklog