Skip to content

Commit 2dab9ae

Browse files
authored
display the units in _repr_inline_ and __repr__ (#325)
* properly pass a mapping of units * add the units onto the inline repr * simplify the formatting of the units * also add a custom string `repr` * closing parens * make sure we always pass a dict of units * expect init to fail on invalid units * also change the replace test * changelog
1 parent 1ed633e commit 2dab9ae

File tree

4 files changed

+44
-7
lines changed

4 files changed

+44
-7
lines changed

docs/whats-new.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ What's new
2222
By `Justus Magin <https://github.com/keewis>`_ and `Tom Nicholas <https://github.com/TomNicholas>`_.
2323
- Follow the change in signature of :py:meth:`xarray.Index.equals` (:issue:`322`, :pull:`324`)
2424
By `Justus Magin <https://github.com/keewis>`_.
25+
- Add units to the inline ``repr`` and define a custom ``repr`` (:issue:`308`, :pull:`325`)
26+
By `Justus Magin <https://github.com/keewis>`_.
2527

2628
0.5.1 (10 Aug 2025)
2729
-------------------

pint_xarray/index.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ def __init__(self, *, index, units):
1515
units : mapping of hashable to unit-like
1616
The units of the indexed coordinates
1717
"""
18+
if not isinstance(units, dict):
19+
raise TypeError(
20+
"Index units have to be a dict of coordinate names to units."
21+
)
22+
1823
self.index = index
1924
self.units = units
2025

@@ -94,4 +99,14 @@ def __getitem__(self, indexer):
9499
return self._replace(self.index[indexer])
95100

96101
def _repr_inline_(self, max_width):
97-
return f"{self.__class__.__name__}({self.index.__class__.__name__})"
102+
name = self.__class__.__name__
103+
wrapped_name = self.index.__class__.__name__
104+
105+
formatted_units = {n: f"{u:~P}" for n, u in self.units.items()}
106+
return f"{name}({wrapped_name}, units={formatted_units})"
107+
108+
def __repr__(self):
109+
formatted_units = {n: f"{u:~P}" for n, u in self.units.items()}
110+
summary = f"<{self.__class__.__name__} (units={formatted_units})>"
111+
112+
return "\n".join([summary, repr(self.index)])

pint_xarray/tests/test_conversion.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ def test_attach_units(self, type, units):
252252

253253
index = PandasIndex(x, dim="x")
254254
if units.get("x") is not None:
255-
index = PintIndex(index=index, units=units.get("x"))
255+
index = PintIndex(index=index, units={"x": units.get("x")})
256256

257257
obj = Dataset({"a": ("x", a), "b": ("x", b)}, coords={"u": ("x", u), "x": x})
258258
coords = Coordinates(

pint_xarray/tests/test_index.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,24 @@ def indexer_equal(first, second):
2828
)
2929
@pytest.mark.parametrize("units", [ureg.Unit("m"), ureg.Unit("s")])
3030
def test_init(base_index, units):
31-
index = PintIndex(index=base_index, units=units)
31+
index = PintIndex(index=base_index, units={base_index.dim: units})
3232

3333
assert index.index.equals(base_index)
34-
assert index.units == units
34+
assert index.units == {base_index.dim: units}
35+
36+
37+
def test_init_error():
38+
base_index = PandasIndex(pd.Index([1, 2, 3]), dim="x")
39+
40+
with pytest.raises(TypeError, match="dict of coordinate names to units"):
41+
PintIndex(index=base_index, units=ureg.Unit("s"))
3542

3643

3744
def test_replace():
38-
old_index = PandasIndex([1, 2, 3], dim="y")
45+
old_index = PandasIndex([1, 2, 3], dim="x")
3946
new_index = PandasIndex([0.1, 0.2, 0.3], dim="x")
4047

41-
old = PintIndex(index=old_index, units=ureg.Unit("m"))
48+
old = PintIndex(index=old_index, units={"x": ureg.Unit("m")})
4249
new = old._replace(new_index)
4350

4451
assert new.index.equals(new_index)
@@ -276,10 +283,23 @@ def test_getitem(indexer):
276283

277284
@pytest.mark.parametrize("wrapped_index", (PandasIndex(pd.Index([1, 2]), dim="x"),))
278285
def test_repr_inline(wrapped_index):
279-
index = PintIndex(index=wrapped_index, units=ureg.Unit("m"))
286+
index = PintIndex(index=wrapped_index, units={"x": ureg.Unit("m")})
280287

281288
# TODO: parametrize
282289
actual = index._repr_inline_(90)
283290

284291
assert "PintIndex" in actual
285292
assert wrapped_index.__class__.__name__ in actual
293+
assert "units" in actual
294+
295+
296+
@pytest.mark.parametrize("wrapped_index", (PandasIndex(pd.Index([1, 2]), dim="x"),))
297+
def test_repr(wrapped_index):
298+
index = PintIndex(index=wrapped_index, units={"x": ureg.Unit("m")})
299+
300+
# TODO: parametrize
301+
actual = repr(index)
302+
303+
assert "<PintIndex" in actual
304+
assert "'x': 'm'" in actual
305+
assert wrapped_index.__class__.__name__ in actual

0 commit comments

Comments
 (0)