Source code for lories.core.resources
# -*- coding: utf-8 -*-
"""
lories.core.resources
~~~~~~~~~~~~~~~~~~~~~
"""
from __future__ import annotations
import logging
from typing import Any, Callable, Dict, Generic, Iterable, Iterator, List, Sequence, Tuple
from lories._core._resource import Resource # noqa
from lories._core._resources import Resources as ResourcesType # noqa
from lories._core._resources import _Resources # noqa
[docs]
class Resources(_Resources, Generic[Resource]):
_resources: List[Resource]
def __init__(self, resources=()) -> None:
self._logger = logging.getLogger(type(self).__module__)
self._resources = [*resources]
def __repr__(self) -> str:
return f"{type(self).__name__}({', '.join(str(r.id) for r in self._resources)})"
def __str__(self) -> str:
return f"{type(self).__name__}:\n\t" + "\n\t".join(f"{r.id} = {repr(r)}" for r in self._resources)
def __contains__(self, resource: str | Resource) -> bool:
if isinstance(resource, str):
return any(resource == r.id for r in self._resources)
return resource in self._resources
def __getitem__(self, index: Iterable[str] | str | int) -> Resource | ResourcesType:
if isinstance(index, str):
for resource in self._resources:
if resource.id == index:
return resource
if isinstance(index, Iterable):
return type(self)([r for r in self._resources if r.id == index])
raise KeyError(index)
def __iter__(self) -> Iterator[Resource]:
return iter(self._resources)
def __len__(self) -> int:
return len(self._resources)
def __add__(self, other) -> ResourcesType:
return type(self)([*self, *other])
def append(self, resource: Resource) -> None:
self._resources.append(resource)
def extend(self, resources: Iterable[Resource]) -> None:
self._resources.extend(resources)
def update(self, resources: Iterable[Resource]) -> None:
resource_ids = [r.id for r in resources]
for resource in [r for r in self._resources if r.id in resource_ids]:
self._resources.remove(resource)
self._resources.extend(resources)
@property
def ids(self) -> Sequence[str]:
return [str(resource.id) for resource in self._resources]
@property
def keys(self) -> Sequence[str]:
return [str(resource.key) for resource in self._resources]
def copy(self) -> ResourcesType:
return type(self)([resource.copy() for resource in self._resources])
def apply(self, apply: Callable[[Resource], Resource], inplace: bool = False) -> ResourcesType:
resources = self._resources if not inplace else self._resources.copy()
return type(self)([apply(resource) for resource in resources])
def filter(self, *filters: Callable[[Resource], bool]) -> ResourcesType:
def _filters(channel: Resource) -> bool:
for _filter in filters:
if _filter is not None and not _filter(channel):
return False
return True
return type(self)([resource for resource in self._resources if _filters(resource)])
# noinspection PyShadowingBuiltins, SpellCheckingInspection
def groupby(self, by: Callable[[Resource], Any] | str) -> Iterator[Tuple[Any, ResourcesType]]:
def _by(r: Resource) -> Any:
return r.get(by, default=None)
filter = _by if isinstance(by, str) else by
for group_by in list(dict.fromkeys([filter(r) for r in self])):
yield group_by, self.filter(lambda r: filter(r) == group_by)
# noinspection PyTypeChecker
def to_configs(self) -> Dict[str, Any]:
return {r.id: r.to_configs() for r in self._resources}