I’m trying to implement _repr_html_
on a python class (docs).
The class is a read-only facade for navigating a JSON-like object using attribute notation (based on example 19-5 from Fluent Python, Rahmalho (O’Reilly)). It has a custom __getatrr__
method to achieve this behavior:
from collections import abc
class FrozenJSON:
"""
Read-only facade for navigating a JSON-like object using attribute notation.
Notes:
Based on example 19-5 from Fluent Python, Rahmalho (O'Reilly).
"""
def __init__(self, mapping):
self._data = dict(mapping)
def __repr__(self):
return "FrozenJSON({})".format(repr(self._data))
def _repr_html_(self):
return (
"<ul>"
+ "n".join(
f"<li><strong>{k}:</strong> {v}</li>" for k, v in self._data.items()
)
+ "</ul>"
)
def __getattr__(self, name):
if hasattr(self._data, name):
return getattr(self._data, name)
else:
return FrozenJSON.build(self._data[name])
def __dir__(self):
return list(self._data.keys())
@classmethod
def build(cls, obj):
if isinstance(obj, abc.Mapping):
return cls(obj)
elif isinstance(obj, abc.MutableSequence):
return [cls.build(item) for item in obj]
else:
return obj
The class behaves like this:
>>> record = FrozenJSON({"name": "waldo", "age": 32, "occupation": "lost"})
>>> record.occupation
'lost'
However the _repr_html_
doesn’t get displayed in an IPython environment (I’ve tried vscode and a jupyter lab).
Commenting out the __getattr__
method causes the HTML representation to be displayed, so I’m fairly confident the issue is something to do with that.
(_repr_html_
on other objects work fine in my environments (e.g. pandas DataFrames).)
The following doesn’t help:
def __getattr__(self, name):
if hasattr(self._data, name):
return getattr(self._data, name)
elif name == "_repr_html_":
return self._repr_html_
else:
return FrozenJSON.build(self._data[name])
I don’t know enough about how vscode / juptyer lab knows to call _repr_html_
rather than __repr__
, and how this __getattr__
is breaking that.
Thanks in advance for any help!