class LazyDict(MutableMapping):
    """A dictionary backed by Arrow data. The values are formatted on-the-fly when accessing the dictionary."""

    def __init__(self, pa_table: pa.Table, formatter: "Formatter"):
        self.pa_table = pa_table
        self.formatter = formatter

        self.data = {key: None for key in pa_table.column_names}
        self.keys_to_format = set(self.data.keys())

    def __len__(self):
        return len(self.data)

    def __getitem__(self, key):
        value = self.data[key]
        if key in self.keys_to_format:
            value = self.format(key)
            self.data[key] = value
            self.keys_to_format.remove(key)
        return value

    def __setitem__(self, key, value):
        if key in self.keys_to_format:
            self.keys_to_format.remove(key)
        self.data[key] = value

    def __delitem__(self, key) -> None:
        if key in self.keys_to_format:
            self.keys_to_format.remove(key)
        del self.data[key]

    def __iter__(self):
        return iter(self.data)

    def __contains__(self, key):
        return key in self.data

    def __repr__(self):
        self._format_all()
        return repr(self.data)

    if config.PY_VERSION >= version.parse("3.9"):
        # merging with the union ("|") operator is supported in Python 3.9+

        def __or__(self, other):
            if isinstance(other, LazyDict):
                inst = self.copy()
                other = other.copy()
                other._format_all()
                inst.keys_to_format -= other.data.keys()
                inst.data = inst.data | other.data
                return inst
            if isinstance(other, dict):
                inst = self.copy()
                inst.keys_to_format -= other.keys()
                inst.data = inst.data | other
                return inst
            return NotImplemented

        def __ror__(self, other):
            if isinstance(other, LazyDict):
                inst = self.copy()
                other = other.copy()
                other._format_all()
                inst.keys_to_format -= other.data.keys()
                inst.data = other.data | inst.data
                return inst
            if isinstance(other, dict):
                inst = self.copy()
                inst.keys_to_format -= other.keys()
                inst.data = other | inst.data
                return inst
            return NotImplemented

        def __ior__(self, other):
            if isinstance(other, LazyDict):
                other = other.copy()
                other._format_all()
                self.keys_to_format -= other.data.keys()
                self.data |= other.data
            else:
                self.keys_to_format -= other.keys()
                self.data |= other
            return self

    def __copy__(self):
        # Identical to `UserDict.__copy__`
        inst = self.__class__.__new__(self.__class__)
        inst.__dict__.update(self.__dict__)
        # Create a copy and avoid triggering descriptors
        inst.__dict__["data"] = self.__dict__["data"].copy()
        inst.__dict__["keys_to_format"] = self.__dict__["keys_to_format"].copy()
        return inst

    def copy(self):
        import copy

        return copy.copy(self)

    @classmethod
    def fromkeys(cls, iterable, value=None):
        raise NotImplementedError

    def format(self, key):
        raise NotImplementedError

    def _format_all(self):
        for key in self.keys_to_format:
            self.data[key] = self.format(key)
        self.keys_to_format.clear()
/Users/nielsrogge/Documents/python_projecten/datasets/src/datasets/formatting/formatting.py