diff --git a/pyproject.toml b/pyproject.toml index 54174b93..38db3e7d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,6 +64,9 @@ docs = [ [project.entry-points."everest"] everest-models = "everest_models.everest_hooks" +[project.entry-points."ert"] +everest_models_forward_models = "everest_models.forward_models" + [project.scripts] fm_add_templates = "everest_models.jobs.fm_add_templates.cli:main_entry_point" fm_drill_date_planner = "everest_models.jobs.fm_drill_date_planner.cli:main_entry_point" diff --git a/src/everest_models/__init__.py b/src/everest_models/__init__.py index 9d4130f3..607499a0 100644 --- a/src/everest_models/__init__.py +++ b/src/everest_models/__init__.py @@ -1,14 +1,12 @@ import pathlib from everest_models.everest_hooks import ( - get_forward_models, get_forward_models_schemas, parse_forward_model_schema, ) from everest_models.logger import set_up_logger __all__ = [ - "get_forward_models", "get_forward_models_schemas", "parse_forward_model_schema", ] diff --git a/src/everest_models/everest_hooks.py b/src/everest_models/everest_hooks.py index c2d04a9e..b344d711 100644 --- a/src/everest_models/everest_hooks.py +++ b/src/everest_models/everest_hooks.py @@ -7,7 +7,6 @@ import logging import pathlib -import sys from importlib import import_module, resources from typing import Any, Dict, List, Sequence, Type @@ -24,36 +23,13 @@ logger = logging.getLogger(__name__) -FORWARD_MODEL_DIR = "forward_models" -PACKAGE = "everest_models" -JOBS = f"{PACKAGE}.jobs" +JOBS = "everest_models.jobs" def _get_jobs(): return (job for job in resources.contents(JOBS) if job.startswith("fm_")) -@hookimpl -def get_forward_models() -> List[Dict[str, str]]: - """Accumulate all maintained forward model jobs by name and path. - - Returns: - (List[Dict[str, str]]): list of forward models and corrolated path - - {name: forward_model, path: /path/to/forward_model} - - ... - """ - if sys.version_info.minor >= 9: - jobs = resources.files(PACKAGE) / FORWARD_MODEL_DIR # type: ignore - else: - with resources.path(PACKAGE, FORWARD_MODEL_DIR) as fd: - jobs = fd - - return [ - {"name": (job_name := job.lstrip("fm_")), "path": str(jobs / job_name)} - for job in _get_jobs() - ] - - @hookimpl def get_forward_models_schemas() -> Dict[str, Dict[str, Type[BaseModel]]]: """Accumulate all forward model jobs and schemas. @@ -75,7 +51,9 @@ def get_forward_models_schemas() -> Dict[str, Dict[str, Type[BaseModel]]]: for job in _get_jobs(): schema = getattr(import_module(f"{JOBS}.{job}.parser"), "SCHEMAS", None) if schema: - res[job.lstrip("fm_")] = schema.get("-c/--config") or schema.get("config") + res[job[3:] if job.startswith("fm_") else job] = schema.get( + "-c/--config" + ) or schema.get("config") return res @@ -123,7 +101,7 @@ def get_forward_model_documentations() -> Dict[str, Any]: import_module(f"{JOBS}.{job}.cli"), "FULL_JOB_NAME", cmd_name ) examples = getattr(import_module(f"{JOBS}.{job}.cli"), "EXAMPLES", None) - docs[job.lstrip("fm_")] = { + docs[job[3:] if job.startswith("fm_") else job] = { "cmd_name": cmd_name, "examples": examples, "full_job_name": full_job_name, diff --git a/src/everest_models/forward_models.py b/src/everest_models/forward_models.py new file mode 100644 index 00000000..7d67f557 --- /dev/null +++ b/src/everest_models/forward_models.py @@ -0,0 +1,54 @@ +from importlib import resources +from importlib.util import find_spec +from typing import Final, List, Type + +_HAVE_ERT: Final = find_spec("ert") is not None + + +def get_forward_models() -> List[str]: + """Return the list of forward model names.""" + return [ + job[3:] + for job in resources.contents("everest_models.jobs") + if job.startswith("fm_") + ] + + +if _HAVE_ERT: # The everest-models package should remain installable without ERT. + import ert + from ert import ForwardModelStepDocumentation, ForwardModelStepPlugin + + def build_forward_model_step_plugin( + executable_name: str, + ) -> Type[ForwardModelStepPlugin]: + forward_model_name = ( + executable_name[3:] + if executable_name.startswith("fm_") + else executable_name + ) + class_name = "".join( + x.capitalize() for x in forward_model_name.lower().split("_") + ) + return type( + class_name, + (ForwardModelStepPlugin,), + { + "__init__": lambda x: ForwardModelStepPlugin.__init__( + x, name=forward_model_name, command=[executable_name] + ), + "documentation": lambda: ForwardModelStepDocumentation( + category="everest.everest_models", + source_package="everest_models", + source_function_name=class_name, + description=f"The {forward_model_name} forward model.", + ), + }, + ) + + @ert.plugin(name="everest_models") + def installable_forward_model_steps(): + return [ + build_forward_model_step_plugin(job) + for job in resources.contents("everest_models.jobs") + if job.startswith("fm_") + ] diff --git a/src/everest_models/forward_models/add_templates b/src/everest_models/forward_models/add_templates deleted file mode 100644 index 55f1c23a..00000000 --- a/src/everest_models/forward_models/add_templates +++ /dev/null @@ -1 +0,0 @@ -EXECUTABLE fm_add_templates diff --git a/src/everest_models/forward_models/compute_economics b/src/everest_models/forward_models/compute_economics deleted file mode 100644 index e4b24ec6..00000000 --- a/src/everest_models/forward_models/compute_economics +++ /dev/null @@ -1 +0,0 @@ -EXECUTABLE fm_compute_economics diff --git a/src/everest_models/forward_models/drill_date_planner b/src/everest_models/forward_models/drill_date_planner deleted file mode 100644 index b5652bbd..00000000 --- a/src/everest_models/forward_models/drill_date_planner +++ /dev/null @@ -1 +0,0 @@ -EXECUTABLE fm_drill_date_planner diff --git a/src/everest_models/forward_models/drill_planner b/src/everest_models/forward_models/drill_planner deleted file mode 100644 index 97dd0eb9..00000000 --- a/src/everest_models/forward_models/drill_planner +++ /dev/null @@ -1 +0,0 @@ -EXECUTABLE fm_drill_planner diff --git a/src/everest_models/forward_models/extract_summary_data b/src/everest_models/forward_models/extract_summary_data deleted file mode 100644 index a5ec2ae7..00000000 --- a/src/everest_models/forward_models/extract_summary_data +++ /dev/null @@ -1 +0,0 @@ -EXECUTABLE fm_extract_summary_data diff --git a/src/everest_models/forward_models/interpret_well_drill b/src/everest_models/forward_models/interpret_well_drill deleted file mode 100644 index 22f7d3cb..00000000 --- a/src/everest_models/forward_models/interpret_well_drill +++ /dev/null @@ -1 +0,0 @@ -EXECUTABLE fm_interpret_well_drill diff --git a/src/everest_models/forward_models/npv b/src/everest_models/forward_models/npv deleted file mode 100644 index 65b8f6dd..00000000 --- a/src/everest_models/forward_models/npv +++ /dev/null @@ -1 +0,0 @@ -EXECUTABLE fm_npv diff --git a/src/everest_models/forward_models/rf b/src/everest_models/forward_models/rf deleted file mode 100644 index 553ce983..00000000 --- a/src/everest_models/forward_models/rf +++ /dev/null @@ -1 +0,0 @@ -EXECUTABLE fm_rf diff --git a/src/everest_models/forward_models/schmerge b/src/everest_models/forward_models/schmerge deleted file mode 100644 index 3b995427..00000000 --- a/src/everest_models/forward_models/schmerge +++ /dev/null @@ -1 +0,0 @@ -EXECUTABLE fm_schmerge diff --git a/src/everest_models/forward_models/select_wells b/src/everest_models/forward_models/select_wells deleted file mode 100644 index bc30bfe9..00000000 --- a/src/everest_models/forward_models/select_wells +++ /dev/null @@ -1 +0,0 @@ -EXECUTABLE fm_select_wells diff --git a/src/everest_models/forward_models/stea b/src/everest_models/forward_models/stea deleted file mode 100644 index 17309782..00000000 --- a/src/everest_models/forward_models/stea +++ /dev/null @@ -1,4 +0,0 @@ -EXECUTABLE fm_stea -ARGLIST - -ARG_TYPE 0 STRING diff --git a/src/everest_models/forward_models/strip_dates b/src/everest_models/forward_models/strip_dates deleted file mode 100644 index ea2cd4d3..00000000 --- a/src/everest_models/forward_models/strip_dates +++ /dev/null @@ -1,3 +0,0 @@ -EXECUTABLE fm_strip_dates - -ARGLIST "--summary= --dates=" diff --git a/src/everest_models/forward_models/well_constraints b/src/everest_models/forward_models/well_constraints deleted file mode 100644 index 9dbd3694..00000000 --- a/src/everest_models/forward_models/well_constraints +++ /dev/null @@ -1 +0,0 @@ -EXECUTABLE fm_well_constraints diff --git a/src/everest_models/forward_models/well_filter b/src/everest_models/forward_models/well_filter deleted file mode 100644 index dab27f55..00000000 --- a/src/everest_models/forward_models/well_filter +++ /dev/null @@ -1 +0,0 @@ -EXECUTABLE fm_well_filter diff --git a/src/everest_models/forward_models/well_swapping b/src/everest_models/forward_models/well_swapping deleted file mode 100644 index b78cbd4d..00000000 --- a/src/everest_models/forward_models/well_swapping +++ /dev/null @@ -1 +0,0 @@ -EXECUTABLE fm_well_swapping diff --git a/src/everest_models/forward_models/well_trajectory b/src/everest_models/forward_models/well_trajectory deleted file mode 100644 index fc51caa0..00000000 --- a/src/everest_models/forward_models/well_trajectory +++ /dev/null @@ -1 +0,0 @@ -EXECUTABLE fm_well_trajectory diff --git a/tests/conftest.py b/tests/conftest.py index 285d9b09..a1756bb0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -66,9 +66,6 @@ class TestSpec: hookspec = pluggy.HookspecMarker("test") - @hookspec - def get_forward_models(self): ... - @hookspec def get_forward_models_schemas(self): ... diff --git a/tests/integration/test_plugin.py b/tests/integration/test_plugin.py index 3fcb93b8..3085420c 100644 --- a/tests/integration/test_plugin.py +++ b/tests/integration/test_plugin.py @@ -1,4 +1,3 @@ -import itertools import sys from pathlib import Path @@ -16,33 +15,6 @@ def test_hooks_registered(plugin_manager): assert sys.modules["everest_models.everest_hooks"] in plugin_manager.get_plugins() -def test_get_forward_models_hook(plugin_manager): - jobs = { - "stea": f"{FORWARD_MODEL_DIR}/stea", - "drill_planner": f"{FORWARD_MODEL_DIR}/drill_planner", - "compute_economics": f"{FORWARD_MODEL_DIR}/compute_economics", - "schmerge": f"{FORWARD_MODEL_DIR}/schmerge", - "extract_summary_data": f"{FORWARD_MODEL_DIR}/extract_summary_data", - "drill_date_planner": f"{FORWARD_MODEL_DIR}/drill_date_planner", - "strip_dates": f"{FORWARD_MODEL_DIR}/strip_dates", - "select_wells": f"{FORWARD_MODEL_DIR}/select_wells", - "npv": f"{FORWARD_MODEL_DIR}/npv", - "well_constraints": f"{FORWARD_MODEL_DIR}/well_constraints", - "add_templates": f"{FORWARD_MODEL_DIR}/add_templates", - "rf": f"{FORWARD_MODEL_DIR}/rf", - "well_filter": f"{FORWARD_MODEL_DIR}/well_filter", - "interpret_well_drill": f"{FORWARD_MODEL_DIR}/interpret_well_drill", - "well_trajectory": f"{FORWARD_MODEL_DIR}/well_trajectory", - "well_swapping": f"{FORWARD_MODEL_DIR}/well_swapping", - } - assert all( - jobs[job["name"]] in job["path"] - for job in itertools.chain.from_iterable( - plugin_manager.hook.get_forward_models() - ) - ) - - def test_get_forward_model_schemas_hook(plugin_manager): assert not set(plugin_manager.hook.get_forward_models_schemas().pop()) - { "add_templates",