From aaa4fac9ef16d21c07b65cbda10164314ab52adf Mon Sep 17 00:00:00 2001 From: Bonelli Date: Fri, 27 Feb 2026 11:43:48 -0500 Subject: [PATCH 1/2] chore(dependencies): accommodate pandas 3 --- flopy/export/metadata.py | 2 +- flopy/utils/mtlistfile.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/flopy/export/metadata.py b/flopy/export/metadata.py index 3677f0ae6f..f94471cea6 100644 --- a/flopy/export/metadata.py +++ b/flopy/export/metadata.py @@ -188,7 +188,7 @@ def time_coverage(self): mlen = self.model_time.perlen.sum() tunits = self.model_time.time_units tc["duration"] = f"{mlen} {tunits}" - end = strt + pd.Timedelta(mlen, unit="d") + end = strt + pd.Timedelta(mlen, unit="D") tc["end"] = str(end) return tc diff --git a/flopy/utils/mtlistfile.py b/flopy/utils/mtlistfile.py index e3d40c6d2f..42cfcf9167 100644 --- a/flopy/utils/mtlistfile.py +++ b/flopy/utils/mtlistfile.py @@ -51,7 +51,7 @@ def __init__(self, file_name): return - def parse(self, forgive=True, diff=True, start_datetime=None, time_unit="d"): + def parse(self, forgive=True, diff=True, start_datetime=None, time_unit="D"): """ Main entry point for parsing the list file. diff --git a/pyproject.toml b/pyproject.toml index 0324b2d054..1ad5ce709c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,7 +28,7 @@ requires-python = ">=3.10" dependencies = [ "numpy>=1.20.3,<3.0", "matplotlib >=1.4.0", - "pandas >=2.0.0,<3.0", + "pandas >=2.0.0", ] dynamic = ["version", "readme"] From 33f590e1cb7f5b6dfa76f8764e42a995eaf5ce1d Mon Sep 17 00:00:00 2001 From: Bonelli Date: Fri, 27 Feb 2026 15:43:27 -0500 Subject: [PATCH 2/2] handle column renaming --- flopy/mf6/data/mfdataplist.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/flopy/mf6/data/mfdataplist.py b/flopy/mf6/data/mfdataplist.py index b2d7ee17c8..e2377d4906 100644 --- a/flopy/mf6/data/mfdataplist.py +++ b/flopy/mf6/data/mfdataplist.py @@ -676,9 +676,11 @@ def set_data(self, data, autofill=False, check_data=True, append=False): if len(data[0]) == len(self._data_item_names): # data most likely being stored with cellids as tuples, # create a dataframe and untuple the cellids - data = pandas.DataFrame( - data, columns=self._data_item_names - ) + # In pandas 3+, DataFrame() with recarray requires columns to match + # field names, so create without columns param then rename if needed + data = pandas.DataFrame(data) + if list(data.columns) != self._data_item_names: + data.columns = self._data_item_names data = self._untuple_cellids(data)[0] # make sure columns are still in correct order data = pandas.DataFrame(data, columns=self._header_names) @@ -691,19 +693,21 @@ def set_data(self, data, autofill=False, check_data=True, append=False): else: # data size matches the expected header names, create a pandas # dataframe from the data - data_new = pandas.DataFrame(data, columns=self._header_names) + # In pandas 3+, DataFrame() with recarray requires columns to match + # field names, so create without columns param then rename if needed + data_new = pandas.DataFrame(data) + if list(data_new.columns) != self._header_names: + data_new.columns = self._header_names if not self._dataframe_check(data_new): data_list = self._untuple_recarray(data) - data = pandas.DataFrame( - data_list, columns=self._header_names - ) + data = pandas.DataFrame(data_list) + if list(data.columns) != self._header_names: + data.columns = self._header_names else: data, count = self._untuple_cellids(data_new) if count > 0: # make sure columns are still in correct order - data = pandas.DataFrame( - data, columns=self._header_names - ) + data = pandas.DataFrame(data, columns=self._header_names) elif isinstance(data, list) or isinstance(data, tuple): if not (isinstance(data[0], list) or isinstance(data[0], tuple)): # get data in the format of a tuple of lists (or tuples)