diff --git a/pyproject.toml b/pyproject.toml index c0c6ea067..7efd03090 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,13 +34,11 @@ classifiers = [ dynamic = ["version"] dependencies = [ "resdata", - "res2df", "ert>=10.2.0b13", "fmu-tools", "grid3d_maps", "matplotlib", "numpy", - "opm>=2023.04", "pandas", "pydantic", "pyscal", @@ -55,6 +53,9 @@ dependencies = [ ] [project.optional-dependencies] +res2df = ["res2df"] +opm = ["opm"] +all = [res2f, opm] tests = [ "mypy", "pytest", diff --git a/src/subscript/__init__.py b/src/subscript/__init__.py index c8ee202ae..71fbe711d 100644 --- a/src/subscript/__init__.py +++ b/src/subscript/__init__.py @@ -1,6 +1,5 @@ import logging import sys -from pathlib import Path try: from importlib import metadata @@ -10,21 +9,6 @@ pass -def detect_os(release_file: Path = Path("/etc/redhat-release")) -> str: - """Detect operating system string in runtime, just use default if not found.""" - default_os_version = "x86_64_RH_7" - - if release_file.is_file(): - with open(release_file, encoding="utf-8") as buffer: - tokens = buffer.read().split() - for t in tokens: - if "." in t: - major = t.split(".")[0] - return f"x86_64_RH_{major}" - raise ValueError("Could not detect RHEL version") - return default_os_version - - def getLogger(module_name="subscript"): """Provides a unified logger for subscript scripts. diff --git a/src/subscript/check_swatinit/check_swatinit.py b/src/subscript/check_swatinit/check_swatinit.py index ce5e7797c..7faee3085 100644 --- a/src/subscript/check_swatinit/check_swatinit.py +++ b/src/subscript/check_swatinit/check_swatinit.py @@ -8,7 +8,13 @@ import numpy as np import numpy.typing as npt import pandas as pd -import res2df + +try: + import res2df + + _HAS_RES2DF = True +except ImportError: + _HAS_RES2DF = False import subscript from subscript.check_swatinit import plotter @@ -42,6 +48,10 @@ def main() -> None: Acts on command line arguments, loads data, performs qc and dumps to CSV if requested.""" + if not _HAS_RES2DF: + sys.exit( + "Error 'res2df' is required for 'check_swatinit' to work.\n Please install using 'pip install subscript[res2df]' or similar." + ) parser = get_parser() args = parser.parse_args() diff --git a/src/subscript/fmu_copy_revision/fmu_copy_revision.py b/src/subscript/fmu_copy_revision/fmu_copy_revision.py index ec97f560c..52a81f67f 100755 --- a/src/subscript/fmu_copy_revision/fmu_copy_revision.py +++ b/src/subscript/fmu_copy_revision/fmu_copy_revision.py @@ -15,9 +15,9 @@ from os.path import join from pathlib import Path -import subscript +from subscript import getLogger, __version__ -logger = subscript.getLogger(__name__) +logger = getLogger(__name__) DESCRIPTION = """This is a simple interactive script for copying a FMU revision folder with features: @@ -293,7 +293,7 @@ def get_parser() -> argparse.ArgumentParser: parser.add_argument( "--version", action="version", - version="%(prog)s (subscript version " + subscript.__version__ + ")", + version="%(prog)s (subscript version " + __version__ + ")", ) logger.info("Parsing commandline") diff --git a/src/subscript/fmuobs/fmuobs.py b/src/subscript/fmuobs/fmuobs.py index d77db4b81..35dbd6976 100644 --- a/src/subscript/fmuobs/fmuobs.py +++ b/src/subscript/fmuobs/fmuobs.py @@ -13,13 +13,13 @@ import yaml from subscript import __version__, getLogger -from subscript.fmuobs.parsers import ( +from .parsers import ( compute_date_from_days, ertobs2df, obsdict2df, resinsight_df2df, ) -from subscript.fmuobs.writers import ( +from .writers import ( CLASS_SHORTNAME, df2ertobs, df2obsdict, diff --git a/src/subscript/fmuobs/parsers.py b/src/subscript/fmuobs/parsers.py index fc5460bb5..8c2c4b591 100644 --- a/src/subscript/fmuobs/parsers.py +++ b/src/subscript/fmuobs/parsers.py @@ -9,7 +9,7 @@ import pandas as pd from subscript import getLogger -from subscript.fmuobs.util import ( +from .util import ( ERT_ALT_DATE_FORMAT, ERT_DATE_FORMAT, ERT_ISO_DATE_FORMAT, diff --git a/src/subscript/fmuobs/writers.py b/src/subscript/fmuobs/writers.py index 39bc15ccb..59d0bff25 100644 --- a/src/subscript/fmuobs/writers.py +++ b/src/subscript/fmuobs/writers.py @@ -9,7 +9,7 @@ import pandas as pd from subscript import getLogger -from subscript.fmuobs.util import ( +from .util import ( CLASS_SHORTNAME, ERT_ISO_DATE_FORMAT, lowercase_dictkeys, diff --git a/src/subscript/grav_subs_maps/grav_subs_maps.py b/src/subscript/grav_subs_maps/grav_subs_maps.py index c93182cac..78c3bf3a5 100644 --- a/src/subscript/grav_subs_maps/grav_subs_maps.py +++ b/src/subscript/grav_subs_maps/grav_subs_maps.py @@ -14,9 +14,9 @@ from resdata.grid import Grid from resdata.resfile import ResdataFile -import subscript +from subscript import getLogger, __version__ -logger = subscript.getLogger(__name__) +logger = getLogger(__name__) # Constant for subsidence modelling, not influencing results # since subsidence is calculated from porevolume change @@ -111,7 +111,7 @@ def get_parser() -> argparse.ArgumentParser: parser.add_argument( "--version", action="version", - version="%(prog)s (subscript version " + subscript.__version__ + ")", + version="%(prog)s (subscript version " + __version__ + ")", ) return parser diff --git a/src/subscript/grav_subs_points/grav_subs_points.py b/src/subscript/grav_subs_points/grav_subs_points.py index d2784a6dd..f27f6f56d 100644 --- a/src/subscript/grav_subs_points/grav_subs_points.py +++ b/src/subscript/grav_subs_points/grav_subs_points.py @@ -14,9 +14,9 @@ from resdata.grid import Grid from resdata.resfile import ResdataFile -import subscript +from subscript import getLogger, __version__ -logger = subscript.getLogger(__name__) +logger = getLogger(__name__) # Constant for subsidence modelling, not influencing results # since subsidence is calculated from porevolume change RPORV @@ -133,7 +133,7 @@ def get_parser() -> argparse.ArgumentParser: parser.add_argument( "--version", action="version", - version="%(prog)s (subscript version " + subscript.__version__ + ")", + version="%(prog)s (subscript version " + __version__ + ")", ) return parser diff --git a/src/subscript/interp_relperm/interp_relperm.py b/src/subscript/interp_relperm/interp_relperm.py index fea7bd7eb..b68c9c5e7 100755 --- a/src/subscript/interp_relperm/interp_relperm.py +++ b/src/subscript/interp_relperm/interp_relperm.py @@ -11,11 +11,17 @@ import pyscal import yaml from pydantic import BaseModel, Field, FilePath, model_validator -from res2df import satfunc -import subscript +try: + from res2df import satfunc -logger = subscript.getLogger(__name__) + _HAS_RES2DF = True +except ImportError: + _HAS_RES2DF = False + +from subscript import getLogger, __version__ + +logger = getLogger(__name__) DESCRIPTION = """Interpolation script for relperm tables. @@ -288,13 +294,17 @@ def get_parser() -> argparse.ArgumentParser: parser.add_argument( "--version", action="version", - version="%(prog)s (subscript version " + subscript.__version__ + ")", + version="%(prog)s (subscript version " + __version__ + ")", ) return parser def main() -> None: """Invocated from the command line, parsing command line arguments""" + if not _HAS_RES2DF: + sys.exit( + "Error 'res2df' is required for 'interp_relperm' to work.\n Please install using 'pip install subscript[res2df]' or similar." + ) parser = get_parser() args = parser.parse_args() diff --git a/src/subscript/merge_rft_ertobs/merge_rft_ertobs.py b/src/subscript/merge_rft_ertobs/merge_rft_ertobs.py index 08a2092c6..2e9cb3c6d 100644 --- a/src/subscript/merge_rft_ertobs/merge_rft_ertobs.py +++ b/src/subscript/merge_rft_ertobs/merge_rft_ertobs.py @@ -6,9 +6,9 @@ import numpy as np import pandas as pd -import subscript +from subscript import getLogger, __version__ -logger = subscript.getLogger(__name__) +logger = getLogger(__name__) DESCRIPTION = """Collect ERT RFT observations and merge with CSV output from GENDATA_RFT. Dump to CSV file for visualization in Webviz. @@ -64,7 +64,7 @@ def get_parser() -> argparse.ArgumentParser: parser.add_argument( "--version", action="version", - version="%(prog)s (subscript version " + subscript.__version__ + ")", + version="%(prog)s (subscript version " + __version__ + ")", ) return parser diff --git a/src/subscript/presentvalue/presentvalue.py b/src/subscript/presentvalue/presentvalue.py index 5e71d6337..c268603fa 100755 --- a/src/subscript/presentvalue/presentvalue.py +++ b/src/subscript/presentvalue/presentvalue.py @@ -4,10 +4,16 @@ import datetime import logging from pathlib import Path - +import sys import numpy as np import pandas as pd -import res2df + +try: + import res2df + + _HAS_RES2DF = True +except ImportError: + _HAS_RES2DF = False import scipy.optimize from subscript import __version__, getLogger @@ -124,6 +130,10 @@ def main() -> None: """Function for command line invocation. Parses command line arguments, and writes output to file and/or terminal.""" + if not _HAS_RES2DF: + sys.exit( + "Error 'res2df' is required for 'presentvalue' to work.\n Please install using 'pip install subscript[res2df]' or similar." + ) parser = get_parser() args = parser.parse_args() diff --git a/src/subscript/prtvol2csv/prtvol2csv.py b/src/subscript/prtvol2csv/prtvol2csv.py index b69426d34..dc501b2b6 100644 --- a/src/subscript/prtvol2csv/prtvol2csv.py +++ b/src/subscript/prtvol2csv/prtvol2csv.py @@ -7,9 +7,15 @@ import warnings from datetime import datetime from pathlib import Path - +import sys import pandas as pd -import res2df + +try: + import res2df + + _HAS_RES2DF = True +except ImportError: + _HAS_RES2DF = False from fmu.tools.fipmapper.fipmapper import FipMapper from subscript import __version__, getLogger @@ -327,6 +333,10 @@ def reservoir_volumes_from_prt(prt_file: str, fipname: str = "FIPNUM") -> pd.Dat def main() -> None: """Function for command line invocation""" + if not _HAS_RES2DF: + sys.exit( + "Error 'res2df' is required for 'prtvol2csv' to work.\n Please install using 'pip install subscript[res2df]' or similar." + ) args = get_parser().parse_args() tablesdir = prep_output_dir(args.dir) diff --git a/src/subscript/rmsecl_volumetrics/rmsecl_volumetrics.py b/src/subscript/rmsecl_volumetrics/rmsecl_volumetrics.py index ac9e14495..aa629b043 100644 --- a/src/subscript/rmsecl_volumetrics/rmsecl_volumetrics.py +++ b/src/subscript/rmsecl_volumetrics/rmsecl_volumetrics.py @@ -5,14 +5,14 @@ import logging from pathlib import Path from typing import Any, cast - +import sys import pandas as pd import yaml from fmu.tools.fipmapper import fipmapper from fmu.tools.rms import volumetrics from subscript import getLogger -from subscript.prtvol2csv.prtvol2csv import currently_in_place_from_prt +from subscript.prtvol2csv.prtvol2csv import currently_in_place_from_prt, _HAS_RES2DF logger = getLogger(__name__) logger.setLevel(logging.INFO) @@ -143,6 +143,10 @@ def _disjoint_sets_to_dict( def main() -> None: """Parse command line arguments and run""" + if not _HAS_RES2DF: + sys.exit( + "Error 'res2df' is required for 'rmsecl_volumetrics' to work.\n Please install using 'pip install subscript[res2df]' or similar." + ) args = get_parser().parse_args() if args.PRTFILE.endswith("csv"): diff --git a/src/subscript/sector2fluxnum/completions.py b/src/subscript/sector2fluxnum/completions.py index f6cb8823c..4359f7f1c 100644 --- a/src/subscript/sector2fluxnum/completions.py +++ b/src/subscript/sector2fluxnum/completions.py @@ -1,4 +1,8 @@ -from res2df import ResdataFiles, compdat +try: + from res2df import ResdataFiles, compdat + _HAS_RES2DF = True +except ImportError: + _HAS_RES2DF=False def get_completion_list(ecl_data_file_name): diff --git a/src/subscript/sector2fluxnum/sector2fluxnum.py b/src/subscript/sector2fluxnum/sector2fluxnum.py index 82e834fe5..f3938f0ac 100755 --- a/src/subscript/sector2fluxnum/sector2fluxnum.py +++ b/src/subscript/sector2fluxnum/sector2fluxnum.py @@ -5,8 +5,8 @@ import cwrap from resdata.grid import Grid from resdata.resfile import FortIO, ResdataFile - -from subscript.sector2fluxnum import completions, datafile_obj, flux_obj, fluxfile_obj +import sys +from . import completions, datafile_obj, flux_obj, fluxfile_obj DESCRIPTION = """ The script sector2fluxnum will execute different steps in a workflow @@ -225,6 +225,10 @@ def main(): """ main method """ + if not completions._HAS_RES2DF: + sys.exit( + "Error 'res2df' is required for 'sector2fluxnum' to work.\n Please install using 'pip install subscript[res2df]' or similar." + ) parser = get_parser() input_args = parser.parse_args() diff --git a/src/subscript/summaryplot/summaryplot.py b/src/subscript/summaryplot/summaryplot.py index 8de4d852f..971f9eb45 100644 --- a/src/subscript/summaryplot/summaryplot.py +++ b/src/subscript/summaryplot/summaryplot.py @@ -34,13 +34,13 @@ # Get rid of FutureWarning from pandas/plotting.py from pandas.plotting import register_matplotlib_converters -from resdata.grid import Grid # type: ignore -from resdata.resfile import ResdataFile # type: ignore -from resdata.summary import Summary # type: ignore +from resdata.grid import Grid +from resdata.resfile import ResdataFile +from resdata.summary import Summary -import subscript +from subscript import getLogger, __version__ -logger = subscript.getLogger(__name__) +logger = getLogger(__name__) register_matplotlib_converters() @@ -120,7 +120,7 @@ def get_parser() -> argparse.ArgumentParser: parser.add_argument( "--version", action="version", - version="%(prog)s (subscript version " + subscript.__version__ + ")", + version="%(prog)s (subscript version " + __version__ + ")", ) return parser diff --git a/src/subscript/sunsch/sunsch.py b/src/subscript/sunsch/sunsch.py index 2ef4d293f..3c911daf0 100755 --- a/src/subscript/sunsch/sunsch.py +++ b/src/subscript/sunsch/sunsch.py @@ -17,9 +17,9 @@ import dateutil.parser import yaml from pydantic import BaseModel, FilePath - +import sys from subscript import __version__, getLogger -from subscript.sunsch.time_vector import TimeVector +from .time_vector import TimeVector, _HAS_OPM logger = getLogger(__name__) @@ -539,6 +539,10 @@ def get_parser() -> argparse.ArgumentParser: def main() -> None: """Entry point from command line""" + if not _HAS_OPM: + sys.exit( + "Error 'opm' is required for 'sunsch' to work.\nPlease install using 'pip install subscript[opm]' or similar." + ) parser = get_parser() args = parser.parse_args() diff --git a/src/subscript/sunsch/time_vector.py b/src/subscript/sunsch/time_vector.py index b4752c47e..5f693e68e 100644 --- a/src/subscript/sunsch/time_vector.py +++ b/src/subscript/sunsch/time_vector.py @@ -4,10 +4,13 @@ from io import StringIO from operator import attrgetter -import opm.io -from opm.io.parser import ParseContext, Parser - -error_actions = [("PARSE_INVALID_KEYWORD_COMBINATION", opm.io.action.ignore)] +try: + import opm.io + from opm.io.parser import ParseContext, Parser + _HAS_OPM=True + error_actions = [("PARSE_INVALID_KEYWORD_COMBINATION", opm.io.action.ignore)] +except ImportError: + _HAS_OPM=False # This is from the TimeMap.cpp implementation in opm ecl_month = {