From 50cba44dd8c2e436c51b5c5c3b045b7c734bf1e9 Mon Sep 17 00:00:00 2001 From: mferrera Date: Tue, 27 Feb 2024 10:16:15 +0100 Subject: [PATCH] CLN: Simplify `InitializeCase` This class had functionality built into it that did not end up being used or may have been undesirable to allow users to use (hence was not used). This functionality was cleaned up, the tests adjusted, and some other tweaks and adjustments. The items removed that were marked deprecated should be OK to delete as they were relevant only to the create_case_data.py workflow job and not used or imported by users. The workflow job did not use these items. --- src/fmu/dataio/dataio.py | 154 ++-------- .../dataio/scripts/create_case_metadata.py | 13 +- tests/conftest.py | 42 +-- tests/test_units/test_fmuprovider_class.py | 12 +- tests/test_units/test_initialize_case.py | 264 +++++++++--------- 5 files changed, 188 insertions(+), 297 deletions(-) diff --git a/src/fmu/dataio/dataio.py b/src/fmu/dataio/dataio.py index 86a087a7d..fdc4f5677 100644 --- a/src/fmu/dataio/dataio.py +++ b/src/fmu/dataio/dataio.py @@ -796,13 +796,13 @@ def export( # # The InitializeCase is used for making the case matadata prior to any other actions, # e.g. forward jobs. However, case metadata file may already exist, and in that case -# this class should only emit a message or warning +# this class should only emit a message or warning. # ###################################################################################### @dataclass class InitializeCase: # pylint: disable=too-few-public-methods - """Instantate InitializeCase object. + """Initialize metadata for an FMU Case. In ERT this is typically ran as an hook workflow in advance. @@ -812,27 +812,21 @@ class InitializeCase: # pylint: disable=too-few-public-methods some predefined main level keys. If config is None or the env variable FMU_GLOBAL_CONFIG pointing to a file is provided, then it will attempt to parse that file instead. - rootfolder: To override the automatic and actual ``rootpath``. Absolute path to - the case root, including case name. If not provided (which is not - recommended), the rootpath will be attempted parsed from the file structure - or by other means. + rootfolder: Absolute path to the case root, including case name. casename: Name of case (experiment) caseuser: Username provided - restart_from: ID of eventual restart (deprecated) - description: Description text as string or list of strings. + description (Optional): Description text as string or list of strings. """ # class variables meta_format: ClassVar[Literal["yaml", "json"]] = "yaml" - # instance config: dict - rootfolder: Optional[Union[str, Path]] = None - casename: Optional[str] = None - caseuser: Optional[str] = None - restart_from: Optional[str] = None + rootfolder: str | Path + casename: str + caseuser: str + description: Optional[Union[str, list]] = None - verbosity: str = "DEPRECATED" _metadata: dict = field(default_factory=dict, init=False) _metafile: Path = field(default_factory=Path, init=False) @@ -840,19 +834,9 @@ class InitializeCase: # pylint: disable=too-few-public-methods _casepath: Path = field(default_factory=Path, init=False) def __post_init__(self) -> None: - if self.verbosity != "DEPRECATED": - warn( - "Using the 'verbosity' key is now deprecated and will have no " - "effect and will be removed in near future. Please remove it from the " - "argument list. Set logging level from client script in the standard " - "manner instead.", - UserWarning, - ) - - if not self.config or GLOBAL_ENVNAME in os.environ: - cnf = some_config_from_env(GLOBAL_ENVNAME) - assert cnf is not None - self.config = cnf + self._pwd = Path().absolute() + self._casepath = Path(self.rootfolder) + self._metafile = self._casepath / "share/metadata/fmu_case.yml" # For this class, the global config must be valid; hence error if not try: @@ -862,93 +846,31 @@ def __post_init__(self) -> None: raise logger.info("Ran __post_init__ for InitializeCase") - def _update_settings(self, newsettings: dict) -> None: - """Update instance settings (properties) from other routines.""" - logger.info("Try new settings %s", newsettings) + def _establish_metadata_files(self) -> bool: + """Checks if the metadata files and directories are established and creates + relevant directories and files if not. - # derive legal input from dataclass signature - annots = getattr(self, "__annotations__", {}) - legals = {key: val for key, val in annots.items() if not key.startswith("_")} - - for setting, value in newsettings.items(): - if setting == "restart_from": - warn( - "The 'restart_from' argument is deprecated and will be removed in " - "a future version. Please refer to the fmu-dataio documentation " - "for information on how to record information about restart " - "source.", - DeprecationWarning, - ) - if _validate_variable(setting, value, legals): - setattr(self, setting, value) - logger.info("New setting OK for %s", setting) - - def _establish_pwd_casepath(self) -> None: - """Establish state variables pwd and casepath. - - See ExportData's method but this is much simpler (e.g. no RMS context) + Returns: + False if fmu_case.yml exists (not established), True if it doesn't. """ - self._pwd = Path().absolute() - - if self.rootfolder: - self._casepath = Path(self.rootfolder) - else: - logger.info("Emit UserWarning") - warn( - "The rootfolder is defaulted, but it is strongly recommended to give " - "an explicit rootfolder", - UserWarning, - ) - self._casepath = self._pwd.parent.parent - - logger.info("Set PWD (case): %s", str(self._pwd)) - logger.info("Set rootpath (case): %s", str(self._casepath)) - - def _establish_case_metadata(self, force: bool = False) -> bool: - if not self._casepath.exists(): - self._casepath.mkdir(parents=True, exist_ok=True) + if not self._metafile.parent.exists(): + self._metafile.parent.mkdir(parents=True, exist_ok=True) logger.info("Created rootpath (case) %s", self._casepath) - - metadata_path = self._casepath / "share/metadata" - self._metafile = metadata_path / "fmu_case.yml" logger.info("The requested metafile is %s", self._metafile) - - if force: - logger.info("Forcing a new metafile") - - if not self._metafile.is_file() or force: - metadata_path.mkdir(parents=True, exist_ok=True) - return True - - return False + return not self._metafile.exists() # ================================================================================== # Public methods: # ================================================================================== - def generate_metadata( - self, - force: bool = False, - skip_null: bool = True, - **kwargs: object, - ) -> dict | None: + def generate_metadata(self) -> dict: """Generate case metadata. - Args: - force: Overwrite existing case metadata if True. Default is False. If force - is False and case metadata already exists, a warning will issued and - None will be returned. - skip_null: Fields with None/missing values will be skipped if True (default) - **kwargs: See InitializeCase() arguments; initial will be overrided by - settings here. - Returns: - A dictionary with case metadata or None + A dictionary with case metadata or an empty dictionary if the metadata + already exists. """ - self._update_settings(kwargs) - self._establish_pwd_casepath() - - if not self._establish_case_metadata(force=force): + if not self._establish_metadata_files(): exists_warning = ( "The case metadata file already exists and will not be overwritten. " "To make new case metadata delete the old case or run on a different " @@ -956,7 +878,7 @@ def generate_metadata( ) logger.warning(exists_warning) warn(exists_warning, UserWarning) - return None + return {} meta = _metadata.default_meta_dollars() meta["class"] = "case" @@ -979,40 +901,22 @@ def generate_metadata( mcase["user"] = {"id": self.caseuser} mcase["description"] = generate_description(self.description) - mcase["restart_from"] = self.restart_from meta["tracklog"] = _metadata.generate_meta_tracklog() - - if skip_null: - meta = drop_nones(meta) + meta = drop_nones(meta) self._metadata = meta + logger.info("The case metadata are now ready!") return deepcopy(self._metadata) - # alias - generate_case_metadata = generate_metadata - - def export( - self, - force: bool = False, - skip_null: bool = True, - **kwargs: dict[str, Any], - ) -> str | None: + def export(self) -> str: """Export case metadata to file. - Args: - force: Overwrite existing case metadata if True. Default is False. If force - is False and case metadata already exists, a warning will issued and - None will be returned. - skip_null: Fields with None/missing values will be skipped if True (default) - **kwargs: See InitializeCase() arguments; initial will be overrided by - settings here. - Returns: - Full path of metadata file or None + Full path of metadata file. """ - if self.generate_case_metadata(force=force, skip_null=skip_null, **kwargs): + if self.generate_metadata(): export_metadata_file( self._metafile, self._metadata, savefmt=self.meta_format ) diff --git a/src/fmu/dataio/scripts/create_case_metadata.py b/src/fmu/dataio/scripts/create_case_metadata.py index 3d699a5ee..2eb74c101 100644 --- a/src/fmu/dataio/scripts/create_case_metadata.py +++ b/src/fmu/dataio/scripts/create_case_metadata.py @@ -115,19 +115,12 @@ def create_metadata(args: argparse.Namespace) -> str: ) as f: global_variables = yaml.safe_load(f) - # fmu.dataio.InitializeCase class is scheduled to be renamed. - case = InitializeCase(config=global_variables) - case_metadata_path = case.export( + return InitializeCase( + config=global_variables, rootfolder=args.ert_caseroot, casename=args.ert_casename, caseuser=args.ert_username, - description=None, # type: ignore - # BUG(JB): description must be str accoring to dataclass - ) - - logger.info("Case metadata has been made: %s", case_metadata_path) - assert case_metadata_path is not None - return case_metadata_path + ).export() def register_on_sumo( diff --git a/tests/conftest.py b/tests/conftest.py index 13af36bdb..f24502242 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -20,21 +20,21 @@ logger = logging.getLogger(__name__) -RUN1 = "tests/data/drogon/ertrun1/realization-0/iter-0" -RUN2 = "tests/data/drogon/ertrun1" -RUN_PRED = "tests/data/drogon/ertrun1/realization-0/pred" +ERTRUN = "tests/data/drogon/ertrun1" +ERTRUN_REAL0_ITER0 = f"{ERTRUN}/realization-0/iter-0" +ERTRUN_PRED = f"{ERTRUN}/realization-0/pred" -RUN1_ENV_PREHOOK = { +ERTRUN_ENV_PREHOOK = { f"_ERT_{FmuEnv.EXPERIMENT_ID.name}": "6a8e1e0f-9315-46bb-9648-8de87151f4c7", f"_ERT_{FmuEnv.ENSEMBLE_ID.name}": "b027f225-c45d-477d-8f33-73695217ba14", f"_ERT_{FmuEnv.SIMULATION_MODE.name}": "test_run", } -RUN1_ENV_FORWARD = { +ERTRUN_ENV_FORWARD = { f"_ERT_{FmuEnv.ITERATION_NUMBER.name}": "0", f"_ERT_{FmuEnv.REALIZATION_NUMBER.name}": "0", f"_ERT_{FmuEnv.RUNPATH.name}": "---", # set dynamically due to pytest tmp rotation } -RUN1_ENV_FULLRUN = {**RUN1_ENV_PREHOOK, **RUN1_ENV_FORWARD} +ERTRUN_ENV_FULLRUN = {**ERTRUN_ENV_PREHOOK, **ERTRUN_ENV_FORWARD} ERT_RUNPATH = f"_ERT_{FmuEnv.RUNPATH.name}" @@ -65,19 +65,19 @@ def _fmu_run1_env_variables(monkeypatch, usepath="", case_only=False): Will here monkeypatch the ENV variables, with a particular setting for RUNPATH (trough `usepath`) which may vary dynamically due to pytest tmp area rotation. """ - env = RUN1_ENV_FULLRUN if not case_only else RUN1_ENV_PREHOOK + env = ERTRUN_ENV_FULLRUN if not case_only else ERTRUN_ENV_PREHOOK for key, value in env.items(): env_value = str(usepath) if "RUNPATH" in key else value monkeypatch.setenv(key, env_value) logger.debug("Setting env %s as %s", key, env_value) -@pytest.fixture(name="fmurun", scope="function") -def fixture_fmurun(tmp_path_factory, monkeypatch, rootpath): +@pytest.fixture(scope="function") +def fmurun(tmp_path_factory, monkeypatch, rootpath): """A tmp folder structure for testing; here a new fmurun without case metadata.""" tmppath = tmp_path_factory.mktemp("data") - newpath = tmppath / RUN1 - shutil.copytree(rootpath / RUN1, newpath) + newpath = tmppath / ERTRUN_REAL0_ITER0 + shutil.copytree(rootpath / ERTRUN_REAL0_ITER0, newpath) _fmu_run1_env_variables(monkeypatch, usepath=newpath, case_only=False) @@ -89,8 +89,8 @@ def fixture_fmurun(tmp_path_factory, monkeypatch, rootpath): def fixture_fmurun_prehook(tmp_path_factory, monkeypatch, rootpath): """A tmp folder structure for testing; here a new fmurun without case metadata.""" tmppath = tmp_path_factory.mktemp("data") - newpath = tmppath / RUN2 - shutil.copytree(rootpath / RUN2, newpath) + newpath = tmppath / ERTRUN + shutil.copytree(rootpath / ERTRUN, newpath) _fmu_run1_env_variables(monkeypatch, usepath=newpath, case_only=True) @@ -102,8 +102,8 @@ def fixture_fmurun_prehook(tmp_path_factory, monkeypatch, rootpath): def fixture_fmurun_w_casemetadata(tmp_path_factory, monkeypatch, rootpath): """Create a tmp folder structure for testing; here existing fmurun w/ case meta!""" tmppath = tmp_path_factory.mktemp("data3") - newpath = tmppath / RUN2 - shutil.copytree(rootpath / RUN2, newpath) + newpath = tmppath / ERTRUN + shutil.copytree(rootpath / ERTRUN, newpath) rootpath = newpath / "realization-0/iter-0" _fmu_run1_env_variables(monkeypatch, usepath=rootpath, case_only=False) @@ -116,8 +116,8 @@ def fixture_fmurun_w_casemetadata(tmp_path_factory, monkeypatch, rootpath): def fixture_fmurun_w_casemetadata_pred(tmp_path_factory, monkeypatch, rootpath): """Create a tmp folder structure for testing; here existing fmurun w/ case meta!""" tmppath = tmp_path_factory.mktemp("data3") - newpath = tmppath / RUN2 - shutil.copytree(rootpath / RUN2, newpath) + newpath = tmppath / ERTRUN + shutil.copytree(rootpath / ERTRUN, newpath) rootpath = newpath / "realization-0/pred" _fmu_run1_env_variables(monkeypatch, usepath=rootpath, case_only=False) @@ -130,8 +130,8 @@ def fixture_fmurun_w_casemetadata_pred(tmp_path_factory, monkeypatch, rootpath): def fixture_fmurun_pred(tmp_path_factory, rootpath): """Create a tmp folder structure for testing; here a new fmurun for prediction.""" tmppath = tmp_path_factory.mktemp("data_pred") - newpath = tmppath / RUN_PRED - shutil.copytree(rootpath / RUN_PRED, newpath) + newpath = tmppath / ERTRUN_PRED + shutil.copytree(rootpath / ERTRUN_PRED, newpath) logger.debug("Ran %s", _current_function_name()) return newpath @@ -144,8 +144,8 @@ def fixture_rmsrun_fmu_w_casemetadata(tmp_path_factory, rootpath): in a FMU setup where case metadata are present """ tmppath = tmp_path_factory.mktemp("data3") - newpath = tmppath / RUN2 - shutil.copytree(rootpath / RUN2, newpath) + newpath = tmppath / ERTRUN + shutil.copytree(rootpath / ERTRUN, newpath) rmspath = newpath / "realization-0/iter-0/rms/model" rmspath.mkdir(parents=True, exist_ok=True) logger.debug("Active folder is %s", rmspath) diff --git a/tests/test_units/test_fmuprovider_class.py b/tests/test_units/test_fmuprovider_class.py index 5a64d6e91..7c36bc794 100644 --- a/tests/test_units/test_fmuprovider_class.py +++ b/tests/test_units/test_fmuprovider_class.py @@ -123,25 +123,25 @@ def test_fmuprovider_prehook_case(tmp_path, globalconfig2, fmurun_prehook): I *may* be that this behaviour can be removed in near future, since the ERT env variables now will tell us that this is an active ERT run. """ - - icase = dataio.InitializeCase(config=globalconfig2) - caseroot = tmp_path / "prehook" caseroot.mkdir(parents=True) - os.chdir(caseroot) - exp = icase.export( + icase = dataio.InitializeCase( + config=globalconfig2, rootfolder=caseroot, casename="MyCaseName", caseuser="MyUser", description="Some description", ) + exp = icase.export() + casemetafile = caseroot / "share/metadata/fmu_case.yml" + assert casemetafile.is_file() assert exp == str(casemetafile.resolve()) - os.chdir(fmurun_prehook) + os.chdir(fmurun_prehook) logger.debug("Case root proposed is: %s", caseroot) myfmu = FmuProvider( model="Model567", diff --git a/tests/test_units/test_initialize_case.py b/tests/test_units/test_initialize_case.py index 97795715c..cbc9e806c 100644 --- a/tests/test_units/test_initialize_case.py +++ b/tests/test_units/test_initialize_case.py @@ -4,192 +4,186 @@ interactive. Hence the basepath will be ../../ """ import logging -import os +from copy import deepcopy +from pathlib import Path import pytest import yaml from fmu.dataio import InitializeCase -from fmu.dataio._utils import prettyprint_dict +from pydantic import ValidationError logger = logging.getLogger(__name__) -def test_inicase_barebone(globalconfig2): - icase = InitializeCase(config=globalconfig2) - assert "Drogon" in str(icase.config) - +def test_initialize_case_barebone(globalconfig2): + icase = InitializeCase( + config=globalconfig2, rootfolder="", casename="", caseuser="MyUser" + ) + assert icase.config == globalconfig2 + assert icase.rootfolder == "" + assert icase.casename == "" + assert icase.caseuser == "MyUser" + assert not icase.description -def test_inicase_barebone_with_export(globalconfig2, fmurun): - icase = InitializeCase(config=globalconfig2) - assert "Drogon" in str(icase.config) - - globalconfig2["masterdata"]["smda"]["field"][0]["identifier"] = "æøå" +def test_initialize_case_post_init(monkeypatch, fmurun, globalconfig2): + monkeypatch.chdir(fmurun) caseroot = fmurun.parent.parent + logger.info("Active folder is %s", fmurun) - icase.export( + icase = InitializeCase( + config=globalconfig2, rootfolder=caseroot, - force=True, - casename="MyCaseName_with_Æ", - caseuser="MyUser", + casename="mycase", + caseuser="user", description="Some description", ) - - casemetafile = caseroot / "share/metadata/fmu_case.yml" - - # check that special characters made it through - with open(casemetafile) as stream: - metadata = yaml.safe_load(stream) - - assert metadata["fmu"]["case"]["name"] == "MyCaseName_with_Æ" - assert metadata["masterdata"]["smda"]["field"][0]["identifier"] == "æøå" - - # Check that special characters are encoded properly in stored metadatafile. - # yaml.safe_load() seems to sort this out, but we want files on disk to be readable. - # Therefore check by reading the raw file content. - with open(casemetafile) as stream: - metadata_string = stream.read() - - assert "æøå" in metadata_string - - -def test_inicase_pwd_basepath(fmurun, globalconfig2): - logger.info("Active folder is %s", fmurun) - os.chdir(fmurun) - - icase = InitializeCase(config=globalconfig2) - with pytest.warns(UserWarning): - icase._establish_pwd_casepath() - - logger.info("Casepath is %s", icase._casepath) - - assert icase._casepath == fmurun.parent.parent - assert icase._pwd == fmurun - - -def test_inicase_pwd_basepath_explicit(fmurun, globalconfig2): - """The casepath should in general be explicit.""" - logger.info("Active folder is %s", fmurun) - os.chdir(fmurun) - - myroot = fmurun - - icase = InitializeCase(config=globalconfig2, rootfolder=myroot, casename="mycase") - icase._establish_pwd_casepath() - logger.info("Casepath is %s", icase._casepath) - assert icase._casepath == myroot + assert icase._casepath == caseroot assert icase._pwd == fmurun + assert icase._metafile == caseroot / "share/metadata/fmu_case.yml" -def test_inicase_update_settings(fmurun, globalconfig2): - """Update self attributes after init.""" +@pytest.mark.filterwarnings("ignore:The global configuration") +def test_initialize_case_post_init_bad_globalconfig(monkeypatch, fmurun, globalconfig2): + monkeypatch.chdir(fmurun) logger.info("Active folder is %s", fmurun) - os.chdir(fmurun) - myroot = fmurun / "mycase" - - icase = InitializeCase(config=globalconfig2, rootfolder=myroot) - kwargs = {"rootfolder": "/tmp"} - icase._update_settings(newsettings=kwargs) - - assert icase.rootfolder == "/tmp" + caseroot = fmurun.parent.parent + logger.info("Case folder is now %s", caseroot) - kwargs = {"casename": "Here we go"} - icase._update_settings(newsettings=kwargs) + config = deepcopy(globalconfig2) + del config["masterdata"] - assert icase.casename == "Here we go" + with pytest.raises(ValidationError, match="masterdata"): + InitializeCase( + config=config, + rootfolder=caseroot, + casename="mycase", + caseuser="user", + ) -def test_inicase_update_settings_correct_key_wrong_type(fmurun, globalconfig2): - """Update self attributes after init, but with wrong type.""" +def test_initialize_case_establish_metadata_files(monkeypatch, fmurun, globalconfig2): + """Tests that the required directories are made when establishing the case""" + monkeypatch.chdir(fmurun) logger.info("Active folder is %s", fmurun) - os.chdir(fmurun) - myroot = fmurun / "mycase" + caseroot = fmurun.parent.parent + logger.info("Case folder is now %s", caseroot) - icase = InitializeCase(config=globalconfig2, rootfolder=myroot) - kwargs = {"rootfolder": 1234567} - with pytest.raises(ValueError, match=r"The value of '"): - icase._update_settings(newsettings=kwargs) + icase = InitializeCase( + config=globalconfig2, rootfolder=caseroot, casename="mycase", caseuser="user" + ) + share_metadata = caseroot / "share/metadata" + assert not share_metadata.exists() + assert icase._establish_metadata_files() + assert share_metadata.exists() + assert not icase._metafile.exists() -def test_inicase_update_settings_shall_fail(fmurun, globalconfig2): - """Update self attributes after init, but using an invalid key.""" +def test_initialize_case_establish_metadata_files_exists( + monkeypatch, fmurun, globalconfig2 +): + """Tests that _establish_metadata_files returns correctly if the share/metadata + directory already exists.""" + monkeypatch.chdir(fmurun) logger.info("Active folder is %s", fmurun) - os.chdir(fmurun) - myroot = fmurun / "mycase" + caseroot = fmurun.parent.parent + logger.info("Case folder is now %s", caseroot) - icase = InitializeCase(config=globalconfig2, rootfolder=myroot) - kwargs = {"invalidfolder": "/tmp"} - with pytest.raises(KeyError): - icase._update_settings(newsettings=kwargs) + icase = InitializeCase( + config=globalconfig2, rootfolder=caseroot, casename="mycase", caseuser="user" + ) + (caseroot / "share/metadata").mkdir(parents=True, exist_ok=True) + assert icase._establish_metadata_files() + assert not icase._metafile.exists() + # Again but with fmu_case.yml created + icase._metafile.touch() + assert not icase._establish_metadata_files() + assert icase._metafile.exists() -def test_inicase_generate_case_metadata(fmurun, globalconfig2): +def test_initialize_case_generate_metadata(monkeypatch, fmurun, globalconfig2): + monkeypatch.chdir(fmurun) logger.info("Active folder is %s", fmurun) - os.chdir(fmurun) myroot = fmurun.parent.parent.parent / "mycase" logger.info("Case folder is now %s", myroot) - icase = InitializeCase(globalconfig2) - with pytest.warns(UserWarning, match="The rootfolder is defaulted"): - icase.generate_case_metadata() + icase = InitializeCase( + config=globalconfig2, rootfolder=myroot, casename="mycase", caseuser="user" + ) + metadata = icase.generate_metadata() + assert metadata + assert metadata["fmu"]["case"]["name"] == "mycase" + assert metadata["fmu"]["case"]["user"]["id"] == "user" -def test_inicase_generate_case_metadata_exists_so_fails( - fmurun_w_casemetadata, globalconfig2 +def test_initialize_case_generate_metadata_warn_if_exists( + monkeypatch, fmurun_w_casemetadata, globalconfig2 ): + monkeypatch.chdir(fmurun_w_casemetadata) logger.info("Active folder is %s", fmurun_w_casemetadata) - os.chdir(fmurun_w_casemetadata) - logger.info("Folder is %s", fmurun_w_casemetadata) casemetafolder = fmurun_w_casemetadata.parent.parent - icase = InitializeCase(globalconfig2) + icase = InitializeCase( + config=globalconfig2, + rootfolder=casemetafolder, + casename="abc", + caseuser="user", + ) with pytest.warns(UserWarning, match=r"The case metadata file already exists"): - icase.generate_case_metadata(rootfolder=casemetafolder) + icase.generate_metadata() -def test_inicase_generate_case_metadata_exists_but_force( - fmurun_w_casemetadata, globalconfig2 -): - logger.info("Active folder is %s", fmurun_w_casemetadata) - os.chdir(fmurun_w_casemetadata) - logger.info("Folder is %s", fmurun_w_casemetadata) - casemetafolder = fmurun_w_casemetadata.parent.parent - old_metafile = casemetafolder / "share/metadata/fmu_case.yml" +def test_initialize_case_with_export(monkeypatch, globalconfig2, fmurun): + monkeypatch.chdir(fmurun) + caseroot = fmurun.parent.parent - with open(old_metafile, encoding="utf-8") as stream: - old_content = yaml.safe_load(stream) + icase = InitializeCase( + config=globalconfig2, + rootfolder=caseroot, + casename="MyCaseName", + caseuser="MyUser", + description="Some description", + ) + fmu_case_yml = Path(icase.export()) + assert fmu_case_yml.exists() + assert fmu_case_yml == caseroot / "share/metadata/fmu_case.yml" - icase = InitializeCase(globalconfig2) - icase.export( - rootfolder=casemetafolder, - force=True, - casename="ertrun1", - caseuser="guffen", - description="My curious case", + with open(fmu_case_yml) as stream: + metadata = yaml.safe_load(stream) + + assert metadata["fmu"]["case"]["name"] == "MyCaseName" + assert metadata["masterdata"]["smda"]["field"][0]["identifier"] == "DROGON" + + +def test_initialize_case_export_with_norsk_alphabet(monkeypatch, globalconfig2, fmurun): + monkeypatch.chdir(fmurun) + caseroot = fmurun.parent.parent + + icase = InitializeCase( + config=globalconfig2, + rootfolder=caseroot, + casename="MyCaseName_with_Æ", + caseuser="MyUser", + description="Søme description", ) + globalconfig2["masterdata"]["smda"]["field"][0]["identifier"] = "æøå" - new_metafile = casemetafolder / "share/metadata/fmu_case.yml" - with open(new_metafile, encoding="utf-8") as stream: - new_content = yaml.safe_load(stream) + fmu_case_yml = Path(icase.export()) + assert fmu_case_yml.exists() + assert fmu_case_yml == caseroot / "share/metadata/fmu_case.yml" - logger.debug("\n%s\n", prettyprint_dict(old_content)) - logger.debug("\n%s\n", prettyprint_dict(new_content)) + with open(fmu_case_yml) as stream: + metadata = yaml.safe_load(stream) - assert old_content["class"] == new_content["class"] - assert old_content["fmu"]["case"]["uuid"] != new_content["fmu"]["case"]["uuid"] + assert metadata["fmu"]["case"]["name"] == "MyCaseName_with_Æ" + assert metadata["masterdata"]["smda"]["field"][0]["identifier"] == "æøå" + # Check that special characters are encoded properly in stored metadatafile. + # yaml.safe_load() seems to sort this out, but we want files on disk to be readable. + # Therefore check by reading the raw file content. + with open(fmu_case_yml) as stream: + metadata_string = stream.read() -def test_inicase_deprecated_restart_from(fmurun_w_casemetadata, globalconfig2): - icase = InitializeCase(globalconfig2) - with pytest.warns( - DeprecationWarning, - match="The 'restart_from' argument is deprecated and will be removed in a " - "future version. Please refer to the fmu-dataio documentation for information " - "on how to record information about restart source.", - ): - icase.export( - rootfolder=fmurun_w_casemetadata.parent.parent, - restart_from="Jurassic era", - ) + assert "æøå" in metadata_string