# Path: anom/model.py
# def delete_multi(keys):
#     """Delete a set of entitites from Datastore by their
#     respective keys.
# 
#     Note:
#       This uses the adapter that is tied to the first model in the list.
#       If the keys have disparate adapters this function may behave in
#       unexpected ways.
# 
#     Warning:
#       You must pass a **list** and not a generator or some other kind
#       of iterable to this function as it has to iterate over the list
#       of keys multiple times.
# 
#     Parameters:
#       keys(list[anom.Key]): The list of keys whose entities to delete.
# 
#     Raises:
#       RuntimeError: If the given set of keys have models that use
#         a disparate set of adapters or if any of the keys are
#         partial.
#     """
#     if not keys:
#         return
# 
#     adapter = None
#     for key in keys:
#         if key.is_partial:
#             raise RuntimeError(f"Key {key!r} is partial.")
# 
#         model = lookup_model_by_kind(key.kind)
#         if adapter is None:
#             adapter = model._adapter
# 
#         model.pre_delete_hook(key)
# 
#     adapter.delete_multi(keys)
#     for key in keys:
#         # Micro-optimization to avoid calling get_model.  This is OK
#         # to do here because we've already proved that a model for
#         # that kind exists in the previous block.
#         model = _known_models[key.kind]
#         model.post_delete_hook(key)
# 
# def get_multi(keys):
#     """Get a set of entities from Datastore by their respective keys.
# 
#     Note:
#       This uses the adapter that is tied to the first model in the
#       list.  If the keys have disparate adapters this function may
#       behave in unexpected ways.
# 
#     Warning:
#       You must pass a **list** and not a generator or some other kind
#       of iterable to this function as it has to iterate over the list
#       of keys multiple times.
# 
#     Parameters:
#       keys(list[anom.Key]): The list of keys whose entities to get.
# 
#     Raises:
#       RuntimeError: If the given set of keys have models that use
#         a disparate set of adapters or if any of the keys are
#         partial.
# 
#     Returns:
#       list[Model]: Entities that do not exist are going to be None
#       in the result list.  The order of results matches the order
#       of the input keys.
#     """
#     if not keys:
#         return []
# 
#     adapter = None
#     for key in keys:
#         if key.is_partial:
#             raise RuntimeError(f"Key {key!r} is partial.")
# 
#         model = lookup_model_by_kind(key.kind)
#         if adapter is None:
#             adapter = model._adapter
# 
#         model.pre_get_hook(key)
# 
#     entities_data, entities = adapter.get_multi(keys), []
#     for key, entity_data in zip(keys, entities_data):
#         if entity_data is None:
#             entities.append(None)
#             continue
# 
#         # Micro-optimization to avoid calling get_model.  This is OK
#         # to do here because we've already proved that a model for
#         # that kind exists in the previous block.
#         model = _known_models[key.kind]
#         entity = model._load(key, entity_data)
#         entities.append(entity)
#         entity.post_get_hook()
# 
#     return entities
# 
# def put_multi(entities):
#     """Persist a set of entities to Datastore.
# 
#     Note:
#       This uses the adapter that is tied to the first Entity in the
#       list.  If the entities have disparate adapters this function may
#       behave in unexpected ways.
# 
#     Warning:
#       You must pass a **list** and not a generator or some other kind
#       of iterable to this function as it has to iterate over the list
#       of entities multiple times.
# 
#     Parameters:
#       entities(list[Model]): The list of entities to persist.
# 
#     Raises:
#       RuntimeError: If the given set of models use a disparate set of
#         adapters.
# 
#     Returns:
#       list[Model]: The list of persisted entitites.
#     """
#     if not entities:
#         return []
# 
#     adapter, requests = None, []
#     for entity in entities:
#         if adapter is None:
#             adapter = entity._adapter
# 
#         entity.pre_put_hook()
#         requests.append(PutRequest(entity.key, entity.unindexed_properties, entity))
# 
#     keys = adapter.put_multi(requests)
#     for key, entity in zip(keys, entities):
#         entity.key = key
#         entity.post_put_hook()
# 
#     return entities
# 
# def lookup_model_by_kind(kind):
#     """Look up the model instance for a given Datastore kind.
# 
#     Parameters:
#       kind(str)
# 
#     Raises:
#       RuntimeError: If a model for the given kind has not been
#         defined.
# 
#     Returns:
#       model: The model class.
#     """
#     model = _known_models.get(kind)
#     if model is None:
#         raise RuntimeError(f"Model for kind {kind!r} not found.")
#     return model
# 
# Path: tests/models.py
# class Person(FullName, Model):
#     email = props.String(indexed=True)
#     first_name = props.String(indexed=True)
#     last_name = props.String(optional=True)
#     parent = props.Key(optional=True, indexed=True)
#     created_at = props.DateTime(auto_now_add=True, indexed=True)


import pytest
from anom import delete_multi, get_multi, put_multi, lookup_model_by_kind
from .models import Person




def test_can_look_up_known_models_by_kind():
    assert lookup_model_by_kind("Person") is Person


def test_can_fail_to_look_up_unknown_models_by_kind():
    with pytest.raises(RuntimeError):

# Path: anom/model.py
# def delete_multi(keys):
#     """Delete a set of entitites from Datastore by their
#     respective keys.
# 
#     Note:
#       This uses the adapter that is tied to the first model in the list.
#       If the keys have disparate adapters this function may behave in
#       unexpected ways.
# 
#     Warning:
#       You must pass a **list** and not a generator or some other kind
#       of iterable to this function as it has to iterate over the list
#       of keys multiple times.
# 
#     Parameters:
#       keys(list[anom.Key]): The list of keys whose entities to delete.
# 
#     Raises:
#       RuntimeError: If the given set of keys have models that use
#         a disparate set of adapters or if any of the keys are
#         partial.
#     """
#     if not keys:
#         return
# 
#     adapter = None
#     for key in keys:
#         if key.is_partial:
#             raise RuntimeError(f"Key {key!r} is partial.")
# 
#         model = lookup_model_by_kind(key.kind)
#         if adapter is None:
#             adapter = model._adapter
# 
#         model.pre_delete_hook(key)
# 
#     adapter.delete_multi(keys)
#     for key in keys:
#         # Micro-optimization to avoid calling get_model.  This is OK
#         # to do here because we've already proved that a model for
#         # that kind exists in the previous block.
#         model = _known_models[key.kind]
#         model.post_delete_hook(key)
# 
# def get_multi(keys):
#     """Get a set of entities from Datastore by their respective keys.
# 
#     Note:
#       This uses the adapter that is tied to the first model in the
#       list.  If the keys have disparate adapters this function may
#       behave in unexpected ways.
# 
#     Warning:
#       You must pass a **list** and not a generator or some other kind
#       of iterable to this function as it has to iterate over the list
#       of keys multiple times.
# 
#     Parameters:
#       keys(list[anom.Key]): The list of keys whose entities to get.
# 
#     Raises:
#       RuntimeError: If the given set of keys have models that use
#         a disparate set of adapters or if any of the keys are
#         partial.
# 
#     Returns:
#       list[Model]: Entities that do not exist are going to be None
#       in the result list.  The order of results matches the order
#       of the input keys.
#     """
#     if not keys:
#         return []
# 
#     adapter = None
#     for key in keys:
#         if key.is_partial:
#             raise RuntimeError(f"Key {key!r} is partial.")
# 
#         model = lookup_model_by_kind(key.kind)
#         if adapter is None:
#             adapter = model._adapter
# 
#         model.pre_get_hook(key)
# 
#     entities_data, entities = adapter.get_multi(keys), []
#     for key, entity_data in zip(keys, entities_data):
#         if entity_data is None:
#             entities.append(None)
#             continue
# 
#         # Micro-optimization to avoid calling get_model.  This is OK
#         # to do here because we've already proved that a model for
#         # that kind exists in the previous block.
#         model = _known_models[key.kind]
#         entity = model._load(key, entity_data)
#         entities.append(entity)
#         entity.post_get_hook()
# 
#     return entities
# 
# def put_multi(entities):
#     """Persist a set of entities to Datastore.
# 
#     Note:
#       This uses the adapter that is tied to the first Entity in the
#       list.  If the entities have disparate adapters this function may
#       behave in unexpected ways.
# 
#     Warning:
#       You must pass a **list** and not a generator or some other kind
#       of iterable to this function as it has to iterate over the list
#       of entities multiple times.
# 
#     Parameters:
#       entities(list[Model]): The list of entities to persist.
# 
#     Raises:
#       RuntimeError: If the given set of models use a disparate set of
#         adapters.
# 
#     Returns:
#       list[Model]: The list of persisted entitites.
#     """
#     if not entities:
#         return []
# 
#     adapter, requests = None, []
#     for entity in entities:
#         if adapter is None:
#             adapter = entity._adapter
# 
#         entity.pre_put_hook()
#         requests.append(PutRequest(entity.key, entity.unindexed_properties, entity))
# 
#     keys = adapter.put_multi(requests)
#     for key, entity in zip(keys, entities):
#         entity.key = key
#         entity.post_put_hook()
# 
#     return entities
# 
# def lookup_model_by_kind(kind):
#     """Look up the model instance for a given Datastore kind.
# 
#     Parameters:
#       kind(str)
# 
#     Raises:
#       RuntimeError: If a model for the given kind has not been
#         defined.
# 
#     Returns:
#       model: The model class.
#     """
#     model = _known_models.get(kind)
#     if model is None:
#         raise RuntimeError(f"Model for kind {kind!r} not found.")
#     return model
# 
# Path: tests/models.py
# class Person(FullName, Model):
#     email = props.String(indexed=True)
#     first_name = props.String(indexed=True)
#     last_name = props.String(optional=True)
#     parent = props.Key(optional=True, indexed=True)
#     created_at = props.DateTime(auto_now_add=True, indexed=True)


# Path: tests/test_functions.py
import pytest
from anom import delete_multi, get_multi, put_multi, lookup_model_by_kind
from .models import Person





def test_can_look_up_known_models_by_kind():
    assert lookup_model_by_kind("Person") is Person


def test_can_fail_to_look_up_unknown_models_by_kind():
    with pytest.raises(RuntimeError):

        assert lookup_model_by_kind("UnknownKind")