diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 46fec8a8..604506e8 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -13,15 +13,15 @@ jobs: os: [ubuntu-latest] env: OS: ${{ matrix.os }} - PYTHON: "3.11" + PYTHON: "3.12" steps: - uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: 3.11 + python-version: 3.12 - name: Install fmu-ensemble and test dependencies run: | diff --git a/.github/workflows/fmu-ensemble.yml b/.github/workflows/fmu-ensemble.yml index cae92fc5..03c21af6 100644 --- a/.github/workflows/fmu-ensemble.yml +++ b/.github/workflows/fmu-ensemble.yml @@ -20,6 +20,16 @@ jobs: strategy: matrix: python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + numpy-version: ["numpy<2", "numpy>=2"] + exclude: + - python-version: "3.8" + numpy-version: "numpy>=2" + - python-version: "3.9" + numpy-version: "numpy>=2" + - python-version: "3.10" + numpy-version: "numpy<2" + - python-version: "3.12" + numpy-version: "numpy<2" steps: - name: ๐Ÿ“– Checkout commit locally @@ -42,8 +52,14 @@ jobs: - name: ๐Ÿ“ฆ Install test dependencies run: | - pip install res2df ecl2df + pip install res2df pip install .[tests,docs] + pip install "${{ matrix.numpy-version }}" + + - name: Install ecl2df + if: matrix.numpy-version == 'numpy<2' + run: | + pip install ecl2df - name: ๐Ÿงพ List all installed packages run: pip freeze diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5e269b39..9b7251a5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: no-commit-to-branch args: ['--branch', 'master'] @@ -13,14 +13,10 @@ repos: - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.2 + rev: v0.6.4 hooks: - id: ruff args: [ --extend-select, I, --fix ] - -- repo: https://github.com/psf/black - rev: 23.11.0 - hooks: - - id: black + - id: ruff-format exclude: "tests/data/testensemble-reek001" diff --git a/setup.py b/setup.py index bd84ce61..1ec2c85f 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,7 @@ #!/usr/bin/env python """The setup script.""" + from setuptools import find_packages, setup with open("README.rst") as readme_file: @@ -12,12 +13,12 @@ REQUIREMENTS = [ "resdata>=4.0.0", - "numpy<2", + "numpy", "pandas", "pyyaml>=5.1", ] -SETUP_REQUIREMENTS = ["setuptools>=28", "setuptools_scm"] +SETUP_REQUIREMENTS = ["setuptools>=65", "setuptools_scm"] with open("test_requirements.txt") as f: test_requirements = f.read().splitlines() @@ -54,6 +55,7 @@ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ], test_suite="tests", tests_require=test_requirements, diff --git a/src/fmu/ensemble/realization.py b/src/fmu/ensemble/realization.py index 71e0ccfb..ee41a574 100644 --- a/src/fmu/ensemble/realization.py +++ b/src/fmu/ensemble/realization.py @@ -523,7 +523,6 @@ def load_status(self): status.fillna("", inplace=True) errorjobs = status[errorcolumns[0]] != "" - # Merge any error strings: error_string = ( status.loc[errorjobs, errorcolumns] @@ -531,7 +530,7 @@ def load_status(self): .apply(" ".join, axis=1) .apply(str.strip) ) - status["errorstring"] = np.nan + status["errorstring"] = pd.NA status.loc[errorjobs, "errorstring"] = error_string status.drop(errorcolumns, axis=1, inplace=True) diff --git a/src/fmu/ensemble/realizationcombination.py b/src/fmu/ensemble/realizationcombination.py index 4d45298b..e3dfcde2 100644 --- a/src/fmu/ensemble/realizationcombination.py +++ b/src/fmu/ensemble/realizationcombination.py @@ -1,4 +1,4 @@ -"""Module for handling linear combinations of realizations. """ +"""Module for handling linear combinations of realizations.""" import fnmatch import logging diff --git a/src/fmu/ensemble/virtualrealization.py b/src/fmu/ensemble/virtualrealization.py index 95f9a17f..1dbbcccf 100644 --- a/src/fmu/ensemble/virtualrealization.py +++ b/src/fmu/ensemble/virtualrealization.py @@ -381,15 +381,10 @@ def get_smry(self, column_keys=None, time_index="monthly"): ] if cum_columns: smry[cum_columns] = ( - smry[cum_columns] - .interpolate(method="time") - .fillna(method="ffill") - .fillna(method="bfill") + smry[cum_columns].interpolate(method="time").ffill().bfill() ) if noncum_columns: - smry[noncum_columns] = ( - smry[noncum_columns].fillna(method="bfill").fillna(value=0) - ) + smry[noncum_columns] = smry[noncum_columns].bfill().fillna(value=0) smry.index = smry.index.set_names(["DATE"]) return smry.loc[pd.to_datetime(time_index_dt)] diff --git a/tests/test_batch.py b/tests/test_batch.py index 78f981f3..6bed5204 100644 --- a/tests/test_batch.py +++ b/tests/test_batch.py @@ -4,6 +4,7 @@ import os import yaml + from fmu.ensemble import EnsembleSet, ScratchEnsemble logger = logging.getLogger(__name__) diff --git a/tests/test_dates.py b/tests/test_dates.py index 58e848a0..57dfcf13 100644 --- a/tests/test_dates.py +++ b/tests/test_dates.py @@ -1,6 +1,7 @@ from datetime import datetime as dt import pytest + from fmu.ensemble.util.dates import _fallback_date_roll, date_range # These tests are duplicated from https://github.com/equinor/res2df/blob/master/tests/test_summary.py diff --git a/tests/test_ensemble.py b/tests/test_ensemble.py index e52da755..761fa296 100644 --- a/tests/test_ensemble.py +++ b/tests/test_ensemble.py @@ -5,10 +5,11 @@ import logging import os -import numpy +import numpy as np import pandas as pd import pytest import yaml + from fmu.ensemble import ScratchEnsemble, ScratchRealization from .test_ensembleset import symlink_iter @@ -58,7 +59,7 @@ def test_reek001(tmpdir): assert int(statusdf.loc[4, "RMS_BATCH"]["DURATION"].values[0]) == 195 # STATUS in real4 is modified to simulate that Eclipse never finished: - assert numpy.isnan(statusdf.loc[4, "ECLIPSE100_2014.2"]["DURATION"].values[0]) + assert np.isnan(statusdf.loc[4, "ECLIPSE100_2014.2"]["DURATION"].values[0]) tmpdir.chdir() statusdf.to_csv("status.csv", index=False) @@ -284,13 +285,14 @@ def test_reek001_scalars(): assert "REAL" in npv assert "npv.txt" in npv # filename is the column name assert len(npv) == 5 - assert npv.dtypes["REAL"] == int - assert npv.dtypes["npv.txt"] == object + + assert npv.dtypes["REAL"] == np.int64 + assert isinstance(npv.dtypes["npv.txt"], object) # This is undesirable, can cause trouble with aggregation # Try again: reekensemble.load_scalar("npv.txt", force_reread=True, convert_numeric=True) npv = reekensemble.get_df("npv.txt") - assert npv.dtypes["npv.txt"] == int or npv.dtypes["npv.txt"] == float + assert npv.dtypes["npv.txt"] in (np.int64, np.float64) assert len(npv) == 4 # the error should now be removed reekensemble.load_scalar("emptyscalarfile") # missing in real-4 @@ -542,7 +544,8 @@ def test_ensemble_ecl(): # For oil industry, p15 on FOPT should yield a larger value than p85. # But the quantiles we get out follows the rest of the world # so we check for the opposite. - assert df_stats["FOPT"]["p85"][-1] > df_stats["FOPT"]["p15"][-1] + + assert df_stats["FOPT"]["p85"].iloc[-1] > df_stats["FOPT"]["p15"].iloc[-1] with pytest.raises(ValueError): reekensemble.get_smry_stats( diff --git a/tests/test_ensemble_agg.py b/tests/test_ensemble_agg.py index 79565123..da6de1b2 100644 --- a/tests/test_ensemble_agg.py +++ b/tests/test_ensemble_agg.py @@ -5,6 +5,7 @@ import pandas as pd import pytest + from fmu.ensemble import ScratchEnsemble logger = logging.getLogger(__name__) diff --git a/tests/test_ensemble_eclfail.py b/tests/test_ensemble_eclfail.py index a64ea8b4..e5d66e70 100644 --- a/tests/test_ensemble_eclfail.py +++ b/tests/test_ensemble_eclfail.py @@ -14,6 +14,7 @@ import numpy as np import pandas as pd + from fmu.ensemble import ScratchEnsemble logger = logging.getLogger(__name__) diff --git a/tests/test_ensemblecombination.py b/tests/test_ensemblecombination.py index 8506851a..e4d0dee8 100644 --- a/tests/test_ensemblecombination.py +++ b/tests/test_ensemblecombination.py @@ -5,6 +5,7 @@ import pandas as pd import pytest + from fmu import ensemble logger = logging.getLogger(__name__) diff --git a/tests/test_ensembleset.py b/tests/test_ensembleset.py index 76deff00..dfed25bb 100644 --- a/tests/test_ensembleset.py +++ b/tests/test_ensembleset.py @@ -8,6 +8,7 @@ import pandas as pd import pytest + from fmu.ensemble import EnsembleSet, ScratchEnsemble try: diff --git a/tests/test_etc.py b/tests/test_etc.py index f21fd04c..2db039b3 100644 --- a/tests/test_etc.py +++ b/tests/test_etc.py @@ -1,6 +1,7 @@ """Test a deprecated submodule""" import pytest + from fmu import ensemble diff --git a/tests/test_observations.py b/tests/test_observations.py index d7c3ec1e..c7299b40 100644 --- a/tests/test_observations.py +++ b/tests/test_observations.py @@ -10,6 +10,7 @@ import pandas as pd import pytest import yaml + from fmu.ensemble import EnsembleSet, Observations, ScratchEnsemble, ScratchRealization logger = logging.getLogger(__name__) diff --git a/tests/test_realization.py b/tests/test_realization.py index 30a71248..91c490b5 100644 --- a/tests/test_realization.py +++ b/tests/test_realization.py @@ -13,9 +13,10 @@ import pytest import yaml from dateutil.relativedelta import relativedelta -from fmu import ensemble from resdata.summary import Summary +from fmu import ensemble + from .test_ensembleset import symlink_iter try: @@ -380,7 +381,9 @@ def test_volumetric_rates(): # Calculate cumulative production from the computed volumetric daily rates: dayscum["FOPRcum"] = dayscum["FOPR"] * dayscum["DIFFDAYS"] # Check that this sum is equal to FOPT between first and last date: - assert dayscum["FOPRcum"].sum() == pytest.approx(dcum["FOPT"][-1] - dcum["FOPT"][0]) + assert dayscum["FOPRcum"].sum() == pytest.approx( + dcum["FOPT"].iloc[-1] - dcum["FOPT"].iloc[0] + ) # (here we could catch an error in case we don't support leap days) # Monthly rates between the random dates: diff --git a/tests/test_realizationcombination.py b/tests/test_realizationcombination.py index 57039825..18f17426 100644 --- a/tests/test_realizationcombination.py +++ b/tests/test_realizationcombination.py @@ -4,6 +4,7 @@ import os import pytest + from fmu import ensemble from fmu.ensemble import ScratchEnsemble diff --git a/tests/test_res2df.py b/tests/test_res2df.py index 151930c1..3ca1b7ca 100644 --- a/tests/test_res2df.py +++ b/tests/test_res2df.py @@ -4,6 +4,7 @@ import os import pytest + from fmu.ensemble import ScratchEnsemble, ScratchRealization HAVE_RES2DF = True diff --git a/tests/test_util.py b/tests/test_util.py index e45a45d2..ff56440a 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -5,6 +5,7 @@ import numpy as np import pytest + from fmu.ensemble.util import flatten, parse_number, shortcut2path from fmu.ensemble.util.dates import normalize_dates from fmu.ensemble.util.rates import cumcolumn_to_ratecolumn diff --git a/tests/test_virtualensemble.py b/tests/test_virtualensemble.py index d299e8c2..9a522fcc 100644 --- a/tests/test_virtualensemble.py +++ b/tests/test_virtualensemble.py @@ -7,6 +7,7 @@ import numpy as np import pandas as pd import pytest + from fmu.ensemble import ScratchEnsemble, VirtualEnsemble try: diff --git a/tests/test_virtualrealization.py b/tests/test_virtualrealization.py index 41a9c5b2..c33f1cfe 100644 --- a/tests/test_virtualrealization.py +++ b/tests/test_virtualrealization.py @@ -9,6 +9,7 @@ import numpy as np import pandas as pd import pytest + from fmu import ensemble from fmu.ensemble.virtualrealization import smry_cumulative