<reponame>thomasyi17/diana2<gh_stars>10-100
"""
CRUD Endpoint API
"""

from abc import ABC
from typing import Mapping, TypeVar, NewType, Union, Sequence, Iterator, Collection
import logging
import attr

Item = TypeVar('Item')
ItemID = NewType('ItemID', str)
Query = NewType('Query', Mapping)


@attr.s
class Endpoint(ABC):
    """
    Generic CRUD endpoint API.
    """

    name = attr.ib(type=str, default="Endpoint")
    ctype = attr.ib(default=None, repr=False)

    def check(self) -> bool:
        """Check endpoint health"""
        raise NotImplementedError

    # Create
    def put(self, item: Item, **kwargs) -> ItemID:
        """Add or replace an item in the collection"""
        raise NotImplementedError

    # Retrieve
    def get(self, item: Union[ItemID, Item], **kwargs) -> Item:
        """Retrieve item data"""
        raise NotImplementedError

    def find(self, item: Union[ItemID, Item, Query],
             **kwargs) -> Union[Sequence[ItemID], Sequence[Item]]:
        """Identify items and optionally retrieve data by query"""
        raise NotImplementedError

    def exists(self, item: Union[ItemID, Item, Query], **kwargs) -> bool:
        """Check if an item exists by id or query"""
        logger = logging.getLogger(self.name)
        logger.debug("Checking exists on {}".format(item))
        if isinstance(item, Mapping):
            return self.find(item, **kwargs) is not None
        else:
            try:
                return self.get(item, **kwargs) is not None
            except Exception:
                return False

    # Update
    def update(self, item: Union[ItemID, Item], data: Mapping, **kwargs) -> ItemID:
        """Update data for an item in the endpoint"""
        raise NotImplementedError

    # Handle
    def handle(self, item: Union[ItemID, Item], method: str, *args, **kwargs):
        """Call a class-specific method"""
        func = self.__getattribute__(method)
        return func(item, *args, **kwargs)

    # Delete
    def delete(self, item: Union[ItemID, Item], **kwargs) -> bool:
        """Remove an item from the endpoint"""
        raise NotImplementedError


@attr.s
class BroadcastingEndpoint(Endpoint):

    eps = attr.ib(type=Iterator[Endpoint], default=None)

    def put(self, item: Item, **kwargs):
        for ep in self.eps:
            ep.put(item, **kwargs)


@attr.s
class SelectiveEndpoint(Endpoint):

    eps = attr.ib(type=Collection[Endpoint], default=None)

    def put(self, item: Item, selector=None, **kwargs):
        ep = self.eps[selector]
        ep.put(item, **kwargs)

"""
CRUD Endpoint API
"""

from abc import ABC
from typing import Mapping, TypeVar, NewType, Union, Sequence, Iterator, Collection
import logging
import attr

Item = TypeVar('Item')
ItemID = NewType('ItemID', str)
Query = NewType('Query', Mapping)


@attr.s
class Endpoint(ABC):
    """
    Generic CRUD endpoint API.
    """

    name = attr.ib(type=str, default="Endpoint")
    ctype = attr.ib(default=None, repr=False)

    def check(self) -> bool:
        """Check endpoint health"""
        raise NotImplementedError

    # Create
    def put(self, item: Item, **kwargs) -> ItemID:
        """Add or replace an item in the collection"""
        raise NotImplementedError

    # Retrieve
    def get(self, item: Union[ItemID, Item], **kwargs) -> Item:
        """Retrieve item data"""
        raise NotImplementedError

    def find(self, item: Union[ItemID, Item, Query],
             **kwargs) -> Union[Sequence[ItemID], Sequence[Item]]:
        """Identify items and optionally retrieve data by query"""
        raise NotImplementedError

    def exists(self, item: Union[ItemID, Item, Query], **kwargs) -> bool:
        """Check if an item exists by id or query"""
        logger = logging.getLogger(self.name)
        logger.debug("Checking exists on {}".format(item))
        if isinstance(item, Mapping):
            return self.find(item, **kwargs) is not None
        else:
            try:
                return self.get(item, **kwargs) is not None
            except Exception:
                return False

    # Update
    def update(self, item: Union[ItemID, Item], data: Mapping, **kwargs) -> ItemID:
        """Update data for an item in the endpoint"""
        raise NotImplementedError

    # Handle
    def handle(self, item: Union[ItemID, Item], method: str, *args, **kwargs):
        """Call a class-specific method"""
        func = self.__getattribute__(method)
        return func(item, *args, **kwargs)

    # Delete
    def delete(self, item: Union[ItemID, Item], **kwargs) -> bool:
        """Remove an item from the endpoint"""
        raise NotImplementedError


@attr.s
class BroadcastingEndpoint(Endpoint):

    eps = attr.ib(type=Iterator[Endpoint], default=None)

    def put(self, item: Item, **kwargs):
        for ep in self.eps:
            ep.put(item, **kwargs)


@attr.s
class SelectiveEndpoint(Endpoint):

    eps = attr.ib(type=Collection[Endpoint], default=None)

    def put(self, item: Item, selector=None, **kwargs):
        ep = self.eps[selector]
        ep.put(item, **kwargs)
CRUD Endpoint API Generic CRUD endpoint API. Check endpoint health # Create Add or replace an item in the collection # Retrieve Retrieve item data Identify items and optionally retrieve data by query Check if an item exists by id or query # Update Update data for an item in the endpoint # Handle Call a class-specific method # Delete Remove an item from the endpoint