Skip to content

Commit

Permalink
Merge branch 'main' into 540-classification-arg
Browse files Browse the repository at this point in the history
  • Loading branch information
perolavsvendsen authored Apr 11, 2024
2 parents db9b524 + 6ba4b49 commit 7c069b6
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 67 deletions.
5 changes: 3 additions & 2 deletions src/fmu/dataio/case.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,11 @@ def generate_metadata(self) -> dict:
model=global_configuration.Model.model_validate(
self.config["model"],
),
case=internal.CaseMetadata(
case=meta.FMUCase(
name=self.casename,
uuid=str(self._case_uuid()),
uuid=self._case_uuid(),
user=meta.User(id=self.caseuser),
description=None,
),
),
tracklog=_metadata.generate_meta_tracklog(),
Expand Down
46 changes: 25 additions & 21 deletions src/fmu/dataio/dataio.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,9 @@
)
from .aggregation import AggregatedData
from .case import InitializeCase
from .datastructure._internal.internal import (
AllowedContent,
)
from .datastructure._internal.internal import AllowedContent
from .datastructure.configuration import global_configuration
from .datastructure.meta import meta
from .providers._fmu import FmuProvider, get_fmu_context_from_environment

# always show PendingDeprecationWarnings
Expand Down Expand Up @@ -433,7 +432,7 @@ class ExportData:
unit: str = ""
verbosity: str = "DEPRECATED" # remove in version 2
vertical_domain: dict = field(default_factory=dict)
workflow: str = ""
workflow: Optional[str | dict[str, str]] = None
table_index: Optional[list] = None

# some keys that are modified version of input, prepended with _use
Expand All @@ -456,37 +455,23 @@ class ExportData:
def __post_init__(self) -> None:
logger.info("Running __post_init__ ExportData")

self._show_deprecations_or_notimplemented()

self._fmurun = get_fmu_context_from_environment() != FmuContext.NON_FMU

# set defaults for mutable keys
self.vertical_domain = {"depth": "msl"}

self._validate_content_key()
self._validate_and_establish_fmucontext()
self._validate_access_ssdl_key()

# parse and validate the config
logger.debug("Global config given %s", prettyprint_dict(self.config))

# NB overwriting self.config. Ugly, but needed (?)
# Input argument is called "config", don't want to change that.
# Class variable self.config is used a lot, don't want to change it.
self.config = global_configuration.parse(self.config)
logger.debug("Global config after parsing is %s", prettyprint_dict(self.config))
# TODO: Consider if we should wipe self.config at this point, to avoid any
# (misuse) of it downstream. Since we are no longer carrying it and updating it,
# it will potentially NOT contain the values we are actually using. So there is
# a risk keeping it around.

# keeping this block here, while we still require the "_config_is_valid"
self._validate_workflow_key()

self._config_is_valid = global_configuration.is_valid(self.config)
if self._config_is_valid:
# TODO: This needs refinement: _config_is_valid should be removed
self.config = global_configuration.roundtrip(self.config)

self._establish_pwd_rootpath()
self._show_deprecations_or_notimplemented()
logger.info("Ran __post_init__")

def _validate_access_ssdl_key(self) -> None:
Expand Down Expand Up @@ -582,6 +567,23 @@ def _show_deprecations_or_notimplemented(self) -> None:
"manner instead.",
UserWarning,
)
if isinstance(self.workflow, dict):
warn(
"The 'workflow' argument should be given as a string. "
"Support for dictionary will be deprecated.",
FutureWarning,
)

def _validate_workflow_key(self) -> None:
if self.workflow:
if isinstance(self.workflow, str):
workflow = meta.Workflow(reference=self.workflow)
elif isinstance(self.workflow, dict):
workflow = meta.Workflow.model_validate(self.workflow)
else:
raise TypeError("'workflow' should be string.")

self.workflow = workflow.model_dump(mode="json", exclude_none=True)

def _validate_content_key(self) -> None:
"""Validate the given 'content' input."""
Expand Down Expand Up @@ -643,6 +645,7 @@ def _update_check_settings(self, newsettings: dict) -> None:

self._show_deprecations_or_notimplemented()
self._validate_content_key()
self._validate_workflow_key()
self._validate_and_establish_fmucontext()

def _establish_pwd_rootpath(self) -> None:
Expand Down Expand Up @@ -719,6 +722,7 @@ def _check_process_object(self, obj: types.Inferrable) -> None:

def _get_fmu_provider(self) -> FmuProvider:
assert isinstance(self.fmu_context, FmuContext)
assert isinstance(self.workflow, dict) or self.workflow is None
return FmuProvider(
model=self.config.get("model"),
fmu_context=self.fmu_context,
Expand Down
8 changes: 1 addition & 7 deletions src/fmu/dataio/datastructure/_internal/internal.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,9 @@ class JsonSchemaMetadata(BaseModel, populate_by_name=True):
source: str = Field(default=SOURCE)


class CaseMetadata(BaseModel):
name: str
uuid: str
user: meta.User


class FMUModel(BaseModel):
model: GlobalConfigurationModel
case: CaseMetadata
case: meta.FMUCase


class PreprocessedInfo(BaseModel):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class Model(BaseModel):

name: str
revision: str
description: Optional[List[str]] = Field(default=None)


class Ssdl(BaseModel):
Expand Down
25 changes: 2 additions & 23 deletions src/fmu/dataio/providers/_fmu.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class FmuProvider:
include_ertjobs: bool = True
casepath_proposed: str | Path = ""
forced_realization: Optional[int] = None
workflow: str | dict = ""
workflow: Optional[dict[str, str]] = None

# private properties for this class
_runpath: Path | str = field(default="", init=False)
Expand Down Expand Up @@ -364,29 +364,8 @@ def _generate_ert_metadata(self) -> None:
meta = self._metadata # shortform

meta["model"] = self.model

meta["context"] = {"stage": self.fmu_context.name.lower()}

if self.workflow:
if isinstance(self.workflow, str):
meta["workflow"] = {"reference": self.workflow}
elif isinstance(self.workflow, dict):
if "reference" not in self.workflow:
raise ValueError(
"When workflow is given as a dict, the 'reference' "
"key must be included and be a string"
)
warn(
"The 'workflow' argument should be given as a string. "
"Support for dictionary input is scheduled for deprecation.",
PendingDeprecationWarning,
)

meta["workflow"] = {"reference": self.workflow["reference"]}

else:
raise TypeError("'workflow' should be string.")

meta["workflow"] = self.workflow
case_uuid = "not_present" # TODO! not allow missing case metadata?
if self._case_metadata and "fmu" in self._case_metadata:
meta["case"] = deepcopy(self._case_metadata["fmu"]["case"])
Expand Down
35 changes: 21 additions & 14 deletions tests/test_units/test_fmuprovider_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from pathlib import Path

import fmu.dataio as dataio
import pydantic
import pytest

# from conftest import pretend_ert_env_run1
Expand All @@ -14,6 +15,7 @@
logger = logging.getLogger(__name__)

FOLDERTREE = "/scratch/myfield/case/realization-13/iter-2/"
WORKFLOW = {"reference": "some_work_flow"}

GLOBAL_CONFIG_MODEL = {"name": "Model2", "revision": "22.1.0"}

Expand Down Expand Up @@ -45,7 +47,7 @@ def test_fmuprovider_no_provider():
casepath_proposed="",
include_ertjobs=False,
forced_realization=None,
workflow="some work flow",
workflow=WORKFLOW,
)
assert myfmu.get_provider() is None

Expand Down Expand Up @@ -83,7 +85,7 @@ def test_fmuprovider_ert_provider_guess_casemeta_path(fmurun):
casepath_proposed="", # if casepath is undef, try deduce from, _ERT_RUNPATH
include_ertjobs=False,
forced_realization=None,
workflow="some work flow",
workflow=WORKFLOW,
)

assert myfmu.get_provider() == "ERT"
Expand All @@ -106,7 +108,7 @@ def test_fmuprovider_ert_provider_missing_parameter_txt(
model=GLOBAL_CONFIG_MODEL,
fmu_context=FmuContext.REALIZATION,
include_ertjobs=True,
workflow="some work flow",
workflow=WORKFLOW,
)
assert myfmu._case_name == "ertrun1"
assert myfmu._real_name == "realization-0"
Expand All @@ -121,7 +123,7 @@ def test_fmuprovider_arbitrary_iter_name(fmurun_w_casemetadata_pred):
model=GLOBAL_CONFIG_MODEL,
fmu_context=FmuContext.REALIZATION,
include_ertjobs=True,
workflow="some work flow",
workflow=WORKFLOW,
)
assert myfmu._case_name == "ertrun1"
assert myfmu._real_name == "realization-0"
Expand Down Expand Up @@ -169,7 +171,7 @@ def test_fmuprovider_prehook_case(tmp_path, globalconfig2, fmurun_prehook):
model=GLOBAL_CONFIG_MODEL,
fmu_context=FmuContext.CASE,
include_ertjobs=False,
workflow="some work flow",
workflow=WORKFLOW,
casepath_proposed=caseroot,
)

Expand Down Expand Up @@ -257,7 +259,7 @@ def test_fmuprovider_no_restart_env(monkeypatch, fmurun_w_casemetadata, fmurun_p
assert "restart_from" not in fmu_restart._metadata["iteration"]


def test_fmuprovider_workflow_reference(fmurun_w_casemetadata):
def test_fmuprovider_workflow_reference(fmurun_w_casemetadata, edataobj1):
"""Testing the handling of workflow reference input.
Metadata definitions of fmu.workflow is that it is a dictionary with 'reference'
Expand All @@ -274,20 +276,25 @@ def test_fmuprovider_workflow_reference(fmurun_w_casemetadata):
os.chdir(fmurun_w_casemetadata)

# workflow input is a string
myfmu = FmuProvider(workflow="workflow as string")
edata = dataio.ExportData(workflow="workflow as string")
# check that the conversion to dict works
assert edata.workflow == {"reference": "workflow as string"}
myfmu = FmuProvider(workflow=edata.workflow)
assert "workflow" in myfmu._metadata
assert myfmu._metadata["workflow"] == {"reference": "workflow as string"}
assert myfmu._metadata["workflow"] == edata.workflow

# workflow input is a correct dict
with pytest.warns(PendingDeprecationWarning, match="The 'workflow' argument"):
myfmu = FmuProvider(workflow={"reference": "workflow as dict"})
with pytest.warns(FutureWarning, match="The 'workflow' argument"):
edata = dataio.ExportData(workflow={"reference": "workflow as dict"})
assert edata.workflow == {"reference": "workflow as dict"}
myfmu = FmuProvider(workflow=edata.workflow)
assert "workflow" in myfmu._metadata
assert myfmu._metadata["workflow"] == {"reference": "workflow as dict"}
assert myfmu._metadata["workflow"] == edata.workflow

# workflow input is non-correct dict
with pytest.raises(ValueError):
myfmu = FmuProvider(workflow={"wrong": "workflow as dict"})
with pytest.raises(pydantic.ValidationError):
dataio.ExportData(workflow={"wrong": "workflow as dict"})

# workflow input is other types - shall fail
with pytest.raises(TypeError):
myfmu = FmuProvider(workflow=123.4)
dataio.ExportData(workflow=123.4)

0 comments on commit 7c069b6

Please sign in to comment.