# Path: anom/adapter.py
# class Adapter:  # pragma: no cover
#     """Abstract base class for Datastore adapters.  Adapters determine
#     how your :class:`Models<Model>` interact with the Datastore.
#     """
# 
#     def delete_multi(self, keys):
#         """Delete a list of entities from the Datastore by their
#         respective keys.
# 
#         Parameters:
#           keys(list[anom.Key]): A list of datastore Keys to delete.
#         """
#         raise NotImplementedError
# 
#     def get_multi(self, keys):
#         """Get multiple entities from the Datastore by their
#         respective keys.
# 
#         Parameters:
#           keys(list[anom.Key]): A list of datastore Keys to get.
# 
#         Returns:
#           list[dict]: A list of dictionaries of data that can be loaded
#           into individual Models.  Entries for Keys that cannot be
#           found are going to be ``None``.
#         """
#         raise NotImplementedError
# 
#     def put_multi(self, requests):
#         """Store multiple entities into the Datastore.
# 
#         Parameters:
#           requests(list[PutRequest]): A list of datastore requets to
#             persist a set of entities.
# 
#         Returns:
#           list[anom.Key]: The list of full keys for each stored
#           entity.
#         """
#         raise NotImplementedError
# 
#     def query(self, query, options):
#         """Run a query against the datastore.
# 
#         Parameters:
#           query(Query): The query to run.
#           options(QueryOptions): Options that determine how the data
#             should be fetched.
# 
#         Returns:
#           QueryResponse: The query response from Datastore.
#         """
#         raise NotImplementedError
# 
#     def transaction(self, propagation):
#         """Create a new Transaction object.
# 
#         Parameters:
#           propagation(Transaction.Propagation): How the new
#             transaction should be propagated with regards to any
#             previously-created transactions.
# 
#         Returns:
#           Transaction: The transaction.
#         """
#         raise NotImplementedError
# 
#     @property
#     def in_transaction(self):
#         "bool: True if the adapter is currently in a Transaction."
#         raise NotImplementedError
# 
#     @property
#     def current_transaction(self):
#         "Transaction: The current Transaction or None."
#         raise NotImplementedError
# 
# Path: anom/transaction.py
# class Transaction:  # pragma: no cover
#     """Abstract base class for Datastore transactions.
#     """
# 
#     class Propagation(Enum):
#         """An enum of the various modes transactions can be run in.
#         """
# 
#         #: Nested transactions should be grouped together into a single
#         #: transaction.
#         Nested = auto()
# 
#         #: Nested transcations should be run independently of their
#         #: parent transactions.
#         Independent = auto()
# 
#     def begin(self):
#         "Start this transaction."
#         raise NotImplementedError
# 
#     def commit(self):
#         "Commit this Transaction to Datastore."
#         raise NotImplementedError
# 
#     def rollback(self):
#         "Roll this Transaction back."
#         raise NotImplementedError
# 
#     def end(self):
#         "Clean up this Transaction object."
#         raise NotImplementedError
# 
# Path: anom/properties.py
# class Msgpack(Serializer):
#     """A Property for values that should be stored as msgpack data.
# 
#     Parameters:
#       name(str, optional): The name of this property on the Datastore
#         entity.  Defaults to the name of this property on the model.
#       default(object, optional): The property's default value.
#       optional(bool, optional): Whether or not this property is
#         optional.  Defaults to ``False``.  Required but empty values
#         cause models to raise an exception before data is persisted.
#       compressed(bool, optional): Whether or not this property should
#         be compressed before being persisted.
#       compression_level(int, optional): The amount of compression to
#         apply when compressing values.
#     """
# 
#     class Extensions(IntEnum):
#         Model = 0
#         DateTime = 1
# 
#     @classmethod
#     def _serialize(cls, value):
#         if isinstance(value, model.Model):
#             kind, value = cls.Extensions.Model, cls._entity_to_dict(value)
# 
#         elif isinstance(value, datetime):
#             kind, value = cls.Extensions.DateTime, _seconds_since_epoch(value)
# 
#         else:
#             raise TypeError(f"Value of type {type(value)} cannot be serialized.")
# 
#         return msgpack.ExtType(kind, cls._dumps(value))
# 
#     @classmethod
#     def _deserialize(cls, code, data):
#         try:
#             kind = cls.Extensions(code)
#         except ValueError:
#             raise ValueError(f"Invalid extension code {code}.")
# 
#         value = cls._loads(data)
#         if kind is cls.Extensions.Model:
#             return cls._entity_from_dict(value)
# 
#         elif kind is cls.Extensions.DateTime:
#             return datetime.fromtimestamp(value, tz.tzutc())
# 
#     @classmethod
#     def _dumps(cls, value):
#         return msgpack.packb(value, default=cls._serialize, use_bin_type=True)
# 
#     @classmethod
#     def _loads(cls, data):
#         return msgpack.unpackb(data, ext_hook=cls._deserialize, encoding="utf-8")


import pylibmc
import uuid
from contextlib import contextmanager
from hashlib import md5
from threading import local
from .. import Adapter, Transaction
from ..properties import Msgpack




class _MemcacheOuterTransaction(Transaction):
    def __init__(self, adapter, ds_transaction):
        self.adapter = adapter
        self.ds_transaction = ds_transaction

        self.batch = []
        self.begin = self.ds_transaction.begin
        self.rollback = self.ds_transaction.rollback

    def _push_keys(self, keys):
        self.batch.extend(keys)

    def commit(self):

# Path: anom/adapter.py
# class Adapter:  # pragma: no cover
#     """Abstract base class for Datastore adapters.  Adapters determine
#     how your :class:`Models<Model>` interact with the Datastore.
#     """
# 
#     def delete_multi(self, keys):
#         """Delete a list of entities from the Datastore by their
#         respective keys.
# 
#         Parameters:
#           keys(list[anom.Key]): A list of datastore Keys to delete.
#         """
#         raise NotImplementedError
# 
#     def get_multi(self, keys):
#         """Get multiple entities from the Datastore by their
#         respective keys.
# 
#         Parameters:
#           keys(list[anom.Key]): A list of datastore Keys to get.
# 
#         Returns:
#           list[dict]: A list of dictionaries of data that can be loaded
#           into individual Models.  Entries for Keys that cannot be
#           found are going to be ``None``.
#         """
#         raise NotImplementedError
# 
#     def put_multi(self, requests):
#         """Store multiple entities into the Datastore.
# 
#         Parameters:
#           requests(list[PutRequest]): A list of datastore requets to
#             persist a set of entities.
# 
#         Returns:
#           list[anom.Key]: The list of full keys for each stored
#           entity.
#         """
#         raise NotImplementedError
# 
#     def query(self, query, options):
#         """Run a query against the datastore.
# 
#         Parameters:
#           query(Query): The query to run.
#           options(QueryOptions): Options that determine how the data
#             should be fetched.
# 
#         Returns:
#           QueryResponse: The query response from Datastore.
#         """
#         raise NotImplementedError
# 
#     def transaction(self, propagation):
#         """Create a new Transaction object.
# 
#         Parameters:
#           propagation(Transaction.Propagation): How the new
#             transaction should be propagated with regards to any
#             previously-created transactions.
# 
#         Returns:
#           Transaction: The transaction.
#         """
#         raise NotImplementedError
# 
#     @property
#     def in_transaction(self):
#         "bool: True if the adapter is currently in a Transaction."
#         raise NotImplementedError
# 
#     @property
#     def current_transaction(self):
#         "Transaction: The current Transaction or None."
#         raise NotImplementedError
# 
# Path: anom/transaction.py
# class Transaction:  # pragma: no cover
#     """Abstract base class for Datastore transactions.
#     """
# 
#     class Propagation(Enum):
#         """An enum of the various modes transactions can be run in.
#         """
# 
#         #: Nested transactions should be grouped together into a single
#         #: transaction.
#         Nested = auto()
# 
#         #: Nested transcations should be run independently of their
#         #: parent transactions.
#         Independent = auto()
# 
#     def begin(self):
#         "Start this transaction."
#         raise NotImplementedError
# 
#     def commit(self):
#         "Commit this Transaction to Datastore."
#         raise NotImplementedError
# 
#     def rollback(self):
#         "Roll this Transaction back."
#         raise NotImplementedError
# 
#     def end(self):
#         "Clean up this Transaction object."
#         raise NotImplementedError
# 
# Path: anom/properties.py
# class Msgpack(Serializer):
#     """A Property for values that should be stored as msgpack data.
# 
#     Parameters:
#       name(str, optional): The name of this property on the Datastore
#         entity.  Defaults to the name of this property on the model.
#       default(object, optional): The property's default value.
#       optional(bool, optional): Whether or not this property is
#         optional.  Defaults to ``False``.  Required but empty values
#         cause models to raise an exception before data is persisted.
#       compressed(bool, optional): Whether or not this property should
#         be compressed before being persisted.
#       compression_level(int, optional): The amount of compression to
#         apply when compressing values.
#     """
# 
#     class Extensions(IntEnum):
#         Model = 0
#         DateTime = 1
# 
#     @classmethod
#     def _serialize(cls, value):
#         if isinstance(value, model.Model):
#             kind, value = cls.Extensions.Model, cls._entity_to_dict(value)
# 
#         elif isinstance(value, datetime):
#             kind, value = cls.Extensions.DateTime, _seconds_since_epoch(value)
# 
#         else:
#             raise TypeError(f"Value of type {type(value)} cannot be serialized.")
# 
#         return msgpack.ExtType(kind, cls._dumps(value))
# 
#     @classmethod
#     def _deserialize(cls, code, data):
#         try:
#             kind = cls.Extensions(code)
#         except ValueError:
#             raise ValueError(f"Invalid extension code {code}.")
# 
#         value = cls._loads(data)
#         if kind is cls.Extensions.Model:
#             return cls._entity_from_dict(value)
# 
#         elif kind is cls.Extensions.DateTime:
#             return datetime.fromtimestamp(value, tz.tzutc())
# 
#     @classmethod
#     def _dumps(cls, value):
#         return msgpack.packb(value, default=cls._serialize, use_bin_type=True)
# 
#     @classmethod
#     def _loads(cls, data):
#         return msgpack.unpackb(data, ext_hook=cls._deserialize, encoding="utf-8")


# Path: anom/adapters/memcache_adapter.py
import pylibmc
import uuid
from contextlib import contextmanager
from hashlib import md5
from threading import local
from .. import Adapter, Transaction
from ..properties import Msgpack





class _MemcacheOuterTransaction(Transaction):
    def __init__(self, adapter, ds_transaction):
        self.adapter = adapter
        self.ds_transaction = ds_transaction

        self.batch = []
        self.begin = self.ds_transaction.begin
        self.rollback = self.ds_transaction.rollback

    def _push_keys(self, keys):
        self.batch.extend(keys)

    def commit(self):

        with self.adapter._bust(self.batch):