# Path: djangoevents/domain.py
# class BaseAggregate(EventSourcedEntity):
#     """
#     `EventSourcedEntity` with saner mutator routing & naming:
# 
#     >>> class Asset(BaseAggregate):
#     >>>    class Created(BaseAggregate.Created):
#     >>>        def mutate(event, klass):
#     >>>            return klass(...)
#     >>>
#     >>>    class Updated(DomainEvent):
#     >>>        def mutate(event, instance):
#     >>>            instance.connect = True
#     >>>            return instance
#     """
# 
#     @classmethod
#     def is_abstract_class(cls):
#         return is_abstract(cls)
# 
#     @classmethod
#     def mutate(cls, aggregate=None, event=None):
#         if aggregate:
#             aggregate._validate_originator(event)
# 
#         if not hasattr(event, 'mutate_event'):
#             msg = "{} does not provide a mutate_event() method.".format(event.__class__)
#             raise NotImplementedError(msg)
# 
#         aggregate = event.mutate_event(event, aggregate or cls)
#         aggregate._increment_version()
#         return aggregate
# 
#     @classmethod
#     def create_for_event(cls, event):
#         aggregate = cls(
#             entity_id=event.entity_id,
#             domain_event_id=event.domain_event_id,
#             entity_version=event.entity_version,
#         )
#         return aggregate
# 
# Path: djangoevents/domain.py
# class BaseAggregate(EventSourcedEntity):
# class BaseEntity(BaseAggregate):
#     def is_abstract_class(cls):
#     def mutate(cls, aggregate=None, event=None):
#     def create_for_event(cls, event):
#     def is_abstract_class(cls):
#     def mutate(cls, entity=None, event=None):
# 
# Path: djangoevents/utils_abstract.py
# def abstract(cls):
#     """
#     Decorator marking classes as abstract.
# 
#     The "abstract" mark is an internal tag.  Classes can be checked for
#     being abstract with the `is_abstract` function.  The tag is non
#     inheritable: every class or subclass has to be explicitly marked
#     with the decorator to be considered abstract.
#     """
# 
#     _abstract_classes.add(cls)
#     return cls
# 
# Path: djangoevents/utils.py
# def camel_case_to_snake_case(text):
# 
#     def repl(match):
#         sep = match.group().lower()
#         if match.start() > 0:
#             sep = '_%s' % sep
#         return sep
# 
#     return re.sub(r'[A-Z][a-z]', repl, text).lower()
# 
# Path: djangoevents/utils.py
# def list_aggregate_events(aggregate_cls):
#     """
#     Lists all aggregate_cls events defined within the application.
#     Note: Only events with a defined `mutate_event` flow and are not marked as abstract will be returned.
#     """
#     events = _list_internal_classes(aggregate_cls, DomainEvent)
#     return [event_cls for event_cls in events if is_event_mutating(event_cls) and not is_abstract(event_cls)]
# 
# Path: djangoevents/utils.py
# def list_concrete_aggregates():
#     """
#     Lists all non abstract aggregates defined within the application.
#     """
#     aggregates = set(_list_subclasses(BaseAggregate) + _list_subclasses(BaseEntity))
#     return [aggregate for aggregate in aggregates if not aggregate.is_abstract_class()]
# 
# Path: djangoevents/utils.py
# def _list_subclasses(cls):
#     """
#     Recursively lists all subclasses of `cls`.
#     """
#     subclasses = cls.__subclasses__()
# 
#     for subclass in cls.__subclasses__():
#         subclasses += _list_subclasses(subclass)
# 
#     return subclasses
# 
# Path: djangoevents/utils.py
# def _list_internal_classes(cls, base_class=None):
#     base_class = base_class or object
# 
#     return [cls_attribute for cls_attribute in cls.__dict__.values()
#             if inspect.isclass(cls_attribute)
#             and issubclass(cls_attribute, base_class)]


from djangoevents.domain import BaseAggregate
from djangoevents.domain import DomainEvent
from djangoevents.utils_abstract import abstract
from ..utils import camel_case_to_snake_case
from ..utils import list_aggregate_events
from ..utils import list_concrete_aggregates
from ..utils import _list_subclasses
from ..utils import _list_internal_classes
from unittest import mock
import pytest
    assert _list_internal_classes(Parent) == []


def test_list_aggregates_skip_abstract():
    class Aggregate1(BaseAggregate):
        pass

    @abstract
    class Aggregate2(BaseAggregate):
        pass

    with mock.patch('djangoevents.utils._list_subclasses') as list_subclasses:
        list_subclasses.return_value = [Aggregate1, Aggregate2]
        aggregates = list_concrete_aggregates()
        assert aggregates == [Aggregate1]


def test_list_aggregates_none_present():
    with mock.patch('djangoevents.utils._list_subclasses') as list_subclasses:
        list_subclasses.return_value = []
        aggregates = list_concrete_aggregates()
        assert aggregates == []


def test_list_events_sample_event_appart_from_abstract():
    class Aggregate(BaseAggregate):
        class Evt1(DomainEvent):
            def mutate_event(self, *args, **kwargs):
                pass


# Path: djangoevents/domain.py
# class BaseAggregate(EventSourcedEntity):
#     """
#     `EventSourcedEntity` with saner mutator routing & naming:
# 
#     >>> class Asset(BaseAggregate):
#     >>>    class Created(BaseAggregate.Created):
#     >>>        def mutate(event, klass):
#     >>>            return klass(...)
#     >>>
#     >>>    class Updated(DomainEvent):
#     >>>        def mutate(event, instance):
#     >>>            instance.connect = True
#     >>>            return instance
#     """
# 
#     @classmethod
#     def is_abstract_class(cls):
#         return is_abstract(cls)
# 
#     @classmethod
#     def mutate(cls, aggregate=None, event=None):
#         if aggregate:
#             aggregate._validate_originator(event)
# 
#         if not hasattr(event, 'mutate_event'):
#             msg = "{} does not provide a mutate_event() method.".format(event.__class__)
#             raise NotImplementedError(msg)
# 
#         aggregate = event.mutate_event(event, aggregate or cls)
#         aggregate._increment_version()
#         return aggregate
# 
#     @classmethod
#     def create_for_event(cls, event):
#         aggregate = cls(
#             entity_id=event.entity_id,
#             domain_event_id=event.domain_event_id,
#             entity_version=event.entity_version,
#         )
#         return aggregate
# 
# Path: djangoevents/domain.py
# class BaseAggregate(EventSourcedEntity):
# class BaseEntity(BaseAggregate):
#     def is_abstract_class(cls):
#     def mutate(cls, aggregate=None, event=None):
#     def create_for_event(cls, event):
#     def is_abstract_class(cls):
#     def mutate(cls, entity=None, event=None):
# 
# Path: djangoevents/utils_abstract.py
# def abstract(cls):
#     """
#     Decorator marking classes as abstract.
# 
#     The "abstract" mark is an internal tag.  Classes can be checked for
#     being abstract with the `is_abstract` function.  The tag is non
#     inheritable: every class or subclass has to be explicitly marked
#     with the decorator to be considered abstract.
#     """
# 
#     _abstract_classes.add(cls)
#     return cls
# 
# Path: djangoevents/utils.py
# def camel_case_to_snake_case(text):
# 
#     def repl(match):
#         sep = match.group().lower()
#         if match.start() > 0:
#             sep = '_%s' % sep
#         return sep
# 
#     return re.sub(r'[A-Z][a-z]', repl, text).lower()
# 
# Path: djangoevents/utils.py
# def list_aggregate_events(aggregate_cls):
#     """
#     Lists all aggregate_cls events defined within the application.
#     Note: Only events with a defined `mutate_event` flow and are not marked as abstract will be returned.
#     """
#     events = _list_internal_classes(aggregate_cls, DomainEvent)
#     return [event_cls for event_cls in events if is_event_mutating(event_cls) and not is_abstract(event_cls)]
# 
# Path: djangoevents/utils.py
# def list_concrete_aggregates():
#     """
#     Lists all non abstract aggregates defined within the application.
#     """
#     aggregates = set(_list_subclasses(BaseAggregate) + _list_subclasses(BaseEntity))
#     return [aggregate for aggregate in aggregates if not aggregate.is_abstract_class()]
# 
# Path: djangoevents/utils.py
# def _list_subclasses(cls):
#     """
#     Recursively lists all subclasses of `cls`.
#     """
#     subclasses = cls.__subclasses__()
# 
#     for subclass in cls.__subclasses__():
#         subclasses += _list_subclasses(subclass)
# 
#     return subclasses
# 
# Path: djangoevents/utils.py
# def _list_internal_classes(cls, base_class=None):
#     base_class = base_class or object
# 
#     return [cls_attribute for cls_attribute in cls.__dict__.values()
#             if inspect.isclass(cls_attribute)
#             and issubclass(cls_attribute, base_class)]


# Path: djangoevents/tests/test_utils.py
from djangoevents.domain import BaseAggregate
from djangoevents.domain import DomainEvent
from djangoevents.utils_abstract import abstract
from ..utils import camel_case_to_snake_case
from ..utils import list_aggregate_events
from ..utils import list_concrete_aggregates
from ..utils import _list_subclasses
from ..utils import _list_internal_classes
from unittest import mock
import pytest

    assert _list_internal_classes(Parent) == []


def test_list_aggregates_skip_abstract():
    class Aggregate1(BaseAggregate):
        pass

    @abstract
    class Aggregate2(BaseAggregate):
        pass

    with mock.patch('djangoevents.utils._list_subclasses') as list_subclasses:
        list_subclasses.return_value = [Aggregate1, Aggregate2]
        aggregates = list_concrete_aggregates()
        assert aggregates == [Aggregate1]


def test_list_aggregates_none_present():
    with mock.patch('djangoevents.utils._list_subclasses') as list_subclasses:
        list_subclasses.return_value = []
        aggregates = list_concrete_aggregates()
        assert aggregates == []


def test_list_events_sample_event_appart_from_abstract():
    class Aggregate(BaseAggregate):
        class Evt1(DomainEvent):
            def mutate_event(self, *args, **kwargs):
                pass


        class Evt2(DomainEvent):