Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

html repr fails for empty cftime arrays #7298

Closed
4 tasks
mathause opened this issue Nov 18, 2022 · 1 comment · Fixed by #8600
Closed
4 tasks

html repr fails for empty cftime arrays #7298

mathause opened this issue Nov 18, 2022 · 1 comment · Fixed by #8600

Comments

@mathause
Copy link
Collaborator

What happened?

The html repr of a cftime array wants to display the "calendar", which it cannot if it is empty.

What did you expect to happen?

No error.

Minimal Complete Verifiable Example

import numpy as np
import xarray as xr


data_obs = np.random.randn(3)
time_obs = xr.date_range("2000-01-01", periods=3, freq="YS", calendar="noleap")

obs = xr.DataArray(data_obs, coords={"time": time_obs})

o = obs[:0]

xr.core.formatting_html.array_repr(o)

MVCE confirmation

  • Minimal example — the example is as focused as reasonably possible to demonstrate the underlying issue in xarray.
  • Complete example — the example is self-contained, including all data and the text of any traceback.
  • Verifiable example — the example copy & pastes into an IPython prompt or Binder notebook, returning the result.
  • New issue — a search of GitHub Issues suggests this is not a duplicate.

Relevant log output

ValueError                                Traceback (most recent call last)
Input In [1], in <cell line: 12>()
      8 obs = xr.DataArray(data_obs, coords={"time": time_obs})
     10 o = obs[:0]
---> 12 xr.core.formatting_html.array_repr(o)

File ~/code/xarray/xarray/core/formatting_html.py:318, in array_repr(arr)
    316 if hasattr(arr, "xindexes"):
    317     indexes = _get_indexes_dict(arr.xindexes)
--> 318     sections.append(index_section(indexes))
    320 sections.append(attr_section(arr.attrs))
    322 return _obj_repr(arr, header_components, sections)

File ~/code/xarray/xarray/core/formatting_html.py:195, in _mapping_section(mapping, name, details_func, max_items_collapse, expand_option_name, enabled)
    188 expanded = _get_boolean_with_default(
    189     expand_option_name, n_items < max_items_collapse
    190 )
    191 collapsed = not expanded
    193 return collapsible_section(
    194     name,
--> 195     details=details_func(mapping),
    196     n_items=n_items,
    197     enabled=enabled,
    198     collapsed=collapsed,
    199 )

File ~/code/xarray/xarray/core/formatting_html.py:155, in summarize_indexes(indexes)
    154 def summarize_indexes(indexes):
--> 155     indexes_li = "".join(
    156         f"<li class='xr-var-item'>{summarize_index(v, i)}</li>"
    157         for v, i in indexes.items()
    158     )
    159     return f"<ul class='xr-var-list'>{indexes_li}</ul>"

File ~/code/xarray/xarray/core/formatting_html.py:156, in <genexpr>(.0)
    154 def summarize_indexes(indexes):
    155     indexes_li = "".join(
--> 156         f"<li class='xr-var-item'>{summarize_index(v, i)}</li>"
    157         for v, i in indexes.items()
    158     )
    159     return f"<ul class='xr-var-list'>{indexes_li}</ul>"

File ~/code/xarray/xarray/core/formatting_html.py:140, in summarize_index(coord_names, index)
    138 index_id = f"index-{uuid.uuid4()}"
    139 preview = escape(inline_index_repr(index))
--> 140 details = short_index_repr_html(index)
    142 data_icon = _icon("icon-database")
    144 return (
    145     f"<div class='xr-index-name'><div>{name}</div></div>"
    146     f"<div class='xr-index-preview'>{preview}</div>"
   (...)
    150     f"<div class='xr-index-data'>{details}</div>"
    151 )

File ~/code/xarray/xarray/core/formatting_html.py:132, in short_index_repr_html(index)
    129 if hasattr(index, "_repr_html_"):
    130     return index._repr_html_()
--> 132 return f"<pre>{escape(repr(index))}</pre>"

File ~/code/xarray/xarray/core/indexes.py:547, in PandasIndex.__repr__(self)
    546 def __repr__(self):
--> 547     return f"PandasIndex({repr(self.index)})"

File ~/code/xarray/xarray/coding/cftimeindex.py:353, in CFTimeIndex.__repr__(self)
    345     end_str = format_times(
    346         self.values[-REPR_ELLIPSIS_SHOW_ITEMS_FRONT_END:],
    347         display_width,
    348         offset=offset,
    349         first_row_offset=offset,
    350     )
    351     datastr = "\n".join([front_str, f"{' '*offset}...", end_str])
--> 353 attrs_str = format_attrs(self)
    354 # oneliner only if smaller than display_width
    355 full_repr_str = f"{klass_name}([{datastr}], {attrs_str})"

File ~/code/xarray/xarray/coding/cftimeindex.py:272, in format_attrs(index, separator)
    267 def format_attrs(index, separator=", "):
    268     """Format attributes of CFTimeIndex for __repr__."""
    269     attrs = {
    270         "dtype": f"'{index.dtype}'",
    271         "length": f"{len(index)}",
--> 272         "calendar": f"'{index.calendar}'",
    273         "freq": f"'{index.freq}'" if len(index) >= 3 else None,
    274     }
    276     attrs_str = [f"{k}={v}" for k, v in attrs.items()]
    277     attrs_str = f"{separator}".join(attrs_str)

File ~/code/xarray/xarray/coding/cftimeindex.py:698, in CFTimeIndex.calendar(self)
    695 """The calendar used by the datetimes in the index."""
    696 from .times import infer_calendar_name
--> 698 return infer_calendar_name(self)

File ~/code/xarray/xarray/coding/times.py:374, in infer_calendar_name(dates)
    371             return sample.calendar
    373 # Error raise if dtype is neither datetime or "O", if cftime is not importable, and if element of 'O' dtype is not cftime.
--> 374 raise ValueError("Array does not contain datetime objects.")

ValueError: Array does not contain datetime objects.

Anything else we need to know?

Bisected to 7379923 use _repr_inline_ for indexes that define it.

Environment

@mathause mathause added bug needs triage Issue that has not been reviewed by xarray team member topic-internals topic-cftime topic-html-repr and removed needs triage Issue that has not been reviewed by xarray team member labels Nov 18, 2022
@keewis
Copy link
Collaborator

keewis commented Jan 10, 2023

you can reproduce this error even without going through the html repr: repr(time_objs[:0]) and time_objs[:0].calendar raise the same error (but with a much shorter traceback).

To fix that, I wonder if we should either return None (since we can't infer the calendar from an empty array) or somehow cache the calendar (and all other dynamically inferred properties, if there are others) on creation / modification of the CFTimeIndex object.

cc @spencerkclark

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants