Skip to content

Commit

Permalink
Address FutureWarnings from pandas 2.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
khaeru committed Aug 30, 2023
1 parent ce6807a commit bb8723e
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 13 deletions.
4 changes: 2 additions & 2 deletions genno/core/attrseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ def bfill(self, dim: Hashable, limit: Optional[int] = None):
# if needed use _maybe_groupby()
return self._replace(
self.unstack(dim)
.fillna(method="bfill", axis=1, limit=limit)
.bfill(axis=1, limit=limit)
.stack()
.reorder_levels(self.dims),
)
Expand Down Expand Up @@ -271,7 +271,7 @@ def ffill(self, dim: Hashable, limit: Optional[int] = None):
# if needed use _maybe_groupby()
return self._replace(
self.unstack(dim)
.fillna(method="ffill", axis=1, limit=limit)
.ffill(axis=1, limit=limit)
.stack()
.reorder_levels(self.dims),
)
Expand Down
5 changes: 5 additions & 0 deletions genno/tests/compat/test_pyam.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
# Skip this entire file if pyam is not installed
pyam = pytest.importorskip("pyam", reason="pyam-iamc not installed")

# Warning emitted by pandas ≥ 2.1.0 with pyam 1.9.0
pytestmark = pytest.mark.filterwarnings(
"ignore:.*unique with argument that is not.*:FutureWarning:pyam.core"
)


@pytest.fixture(scope="session")
def scenario():
Expand Down
30 changes: 19 additions & 11 deletions genno/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from inspect import Parameter, signature
from typing import Callable, Iterable, Mapping, MutableMapping, Tuple, Type, Union

import numpy as np
import pandas as pd
import pint
from dask.core import literal
Expand Down Expand Up @@ -70,6 +71,16 @@ def filter_concat_args(args):
yield arg


def _invalid(unit: str, exc: Exception) -> Exception:
"""Helper method to return an intelligible exception from :func:`parse_units`."""
chars = "".join(filter("-?$".__contains__, unit))
msg = f"unit {unit!r} cannot be parsed; contains invalid character(s) {chars!r}"
# Use the original class of `exc`, mapped in some cases
cls_map: Mapping[Type[Exception], Type[Exception]] = {TypeError: ValueError}
return_cls = cls_map.get(type(exc), type(exc))
return return_cls(msg)


def parse_units(data: Iterable, registry=None) -> pint.Unit:
"""Return a :class:`pint.Unit` for an iterable of strings.
Expand All @@ -95,6 +106,12 @@ def parse_units(data: Iterable, registry=None) -> pint.Unit:
"""
registry = registry or pint.get_application_registry()

# Ensure a type that is accepted by pd.unique()
if isinstance(data, str):
data = np.array([data])
elif not isinstance(data, (np.ndarray, pd.Index, pd.Series)):
data = np.array(data)

unit = pd.unique(data)

if len(unit) > 1:
Expand All @@ -106,15 +123,6 @@ def parse_units(data: Iterable, registry=None) -> pint.Unit:
# `units_series` is length 0 → no data → dimensionless
unit = registry.dimensionless

def invalid(unit: str, exc: Exception) -> Exception:
"""Helper method to return an intelligible exception."""
chars = "".join(filter("-?$".__contains__, unit))
msg = f"unit {unit!r} cannot be parsed; contains invalid character(s) {chars!r}"
# Use the original class of `exc`, mapped in some cases
cls_map: Mapping[Type[Exception], Type[Exception]] = {TypeError: ValueError}
return_cls = cls_map.get(type(exc), type(exc))
return return_cls(msg)

# Parse units
try:
return registry.Unit(unit)
Expand All @@ -139,12 +147,12 @@ def invalid(unit: str, exc: Exception) -> Exception:
return registry.Unit(unit)
except PintError as e:
# registry.define() failed somehow
raise invalid(unit, e)
raise _invalid(unit, e)
except (AttributeError, TypeError) + PintError as e: # type: ignore [misc]
# Unit contains a character like '-' that throws off pint
# NB this 'except' clause must be *after* UndefinedUnitError, since that is a
# subclass of AttributeError.
raise invalid(unit, e)
raise _invalid(unit, e)


def partial_split(func: Callable, kwargs: Mapping) -> Tuple[Callable, MutableMapping]:
Expand Down

0 comments on commit bb8723e

Please sign in to comment.