Source code for geestac.custom_types

"""Custom types."""

import json
import logging
from typing import Any, Generic, List, TypeVar

from .helpers import format_attribute

[docs] logger = logging.getLogger("geestac")
# Create a TypeVar for generic typing
[docs] T = TypeVar("T")
[docs] class ListNamespace(Generic[T]): """A Namespace to store objects with a unique attribute (key).""" def __init__(self, *args: T, key: str): """A Namespace to store objects with a unique attribute (key). If the value of the key is not suitable for an attribute, it'll be converted with format_attribute function. The values of the keys must be unique, else the first occurrence will be kept. Args: args: a list of objects. key: the attribute of the object to get the key from. """
[docs] self._key = key
[docs] self._args: List[T] = []
for obj in args: self.__setattr__(getattr(obj, key), obj)
[docs] def keys(self) -> list: """Key values as list.""" return [getattr(obj, self._key) for obj in self._args]
[docs] def __setattr__(self, key: str, value: Any): """Set attribute to this object.""" if key in ["_key", "_args"]: super().__setattr__(key, value) return self key = format_attribute(key) try: getattr(self, key) except AttributeError: args = list(self._args) args.append(value) self._args = args super().__setattr__(key, value) else: raise AttributeError(f"object with attribute {self._key} = {key} already exists.") return self
[docs] def as_list(self, key: str | None = None) -> list: """ListNamespace as list. Args: key: attribute of the object to put in the list. If None it will put the objects in the list. """ if key is None: return list(self._args) else: args: List[Any] = [] for arg in self._args: try: attr = getattr(arg, key) except AttributeError: continue else: args.append(attr) return args
[docs] def as_dict(self, value: str | None = None) -> dict: """ListNamespace as a dict. Args: value: attribute of the object to use as value. """ keys = self.as_list(self._key) values = self.as_list(value) return dict(zip(keys, values))
[docs] def __repr__(self): """Object representation.""" return json.dumps([item for item in self.as_list(self._key)])
[docs] def __getitem__(self, index: int | str): """Get item from ListNamepace. Args: index: index of the element in the ListNamespace. """ if isinstance(index, int): return self._args[index] else: return self.as_dict()[index]
[docs] def __len__(self): """Length of the ListNamespace.""" return len(self._args)
[docs] def _append(self, obj: T): """Append an object to the list.""" key = getattr(obj, self._key) return self.__setattr__(key, obj)
[docs] def is_empty(self) -> bool: """Is this object empty?.""" return len(self.as_list()) == 0
[docs] def __iter__(self): """Iterator.""" return iter(self._args)