# Path: baroque/entities/topic.py
# class Topic:
#     """A distribution channel where events of specific types can be published
#     and can be seen by subscribers of the topic. Topic subscribers will attach
#     a reactor to the topic, which will be fired whenever any event of the types
#     that are supported by the topic is published on the topic itself.
# 
#     Args:
#         name (str): the name of this topic
#         eventtypes (collection): the :obj:`baroque.entities.eventtype.EventType` objects that characterize this topic
#         description (str, optional): a description of this topic
#         owner (str, optional): the owner of this topic
#         tags (set, optional): the `set` of tags that describe this topic
# 
#     Raises:
#         `AssertionError`: name or tags are `None` or have a wrong type
# 
#     """
# 
#     def __init__(self, name, eventtypes, description=None, owner=None,
#                  tags=None):
#         assert name is not None
#         assert isinstance(name, str)
#         self.name = name
#         assert eventtypes is not None
#         if len(eventtypes) != 0:
#             self.types = EventTypesBag(eventtypes)
#         else:
#             self.types = EventTypesBag()
#         self.description = description
#         self.owner = owner
#         if tags is not None:
#             assert not isinstance(tags, str)
#             assert isinstance(tags, collections.Iterable)
#             self.tags = set(tags)
#         else:
#             self.tags = set()
#         self.id = str(uuid.uuid4())
#         self.timestamp = None
#         self.touch()
# 
#     @property
#     def eventtypes(self):
#         """:obj:`baroque.datastructures.bags.EventTypesBag`: bag containing the
#          event types of this topic"""
#         return self.types
# 
#     def touch(self):
#         """Sets the current time as timestamp of this topic"""
#         self.timestamp = ts.utc_now()
# 
#     def json(self):
#         """Dumps this object to a JSON string.
# 
#         Returns:
#             str
# 
#         """
#         data = dict(id=self.id, owner=self.owner, description=self.description,
#                     eventtypes=[str(et) for et in self.types],
#                     tags=list(self.tags), timestamp=ts.stringify(self.timestamp))
#         return dumps(data)
# 
#     def md5(self):
#         """Returns the MD5 hash of this object.
# 
#         Returns:
#             str
# 
#         """
#         m = hashlib.md5()
#         m.update(self.json().encode('utf-8'))
#         return m.hexdigest()
# 
#     def __repr__(self):
#         return '<{}.{} - name: {} - owner: {} - eventtypes: {}>'.format(
#             __name__,
#             self.__class__.__name__,
#             self.name,
#             self.owner or 'None',
#             ', '.join([str(et) for et in self.types]) or 'None'
#         )
# 
# Path: baroque/defaults/eventtypes.py
# class GenericEventType(EventType):
#     """Describes generic events with a free-form content.
# 
#     Args:
#         owner (str, optional): ID of the owner of this event type.
# 
#     """
#     def __init__(self, owner=None):
#         EventType.__init__(self,
#                            '''{
#                              "$schema": "http://json-schema.org/draft-04/schema#"
#                            }''',
#                            description='Generic event',
#                            owner=owner)
# 
# class DataOperationEventType(EventType):
#     """Describes events cast when some kind of operation is done on a
#     piece of data.
#     Suitable i.e. to track CRUD operations on DB tables or whole datastores.
#     Details about the impacted data entity and the operation are
#     conveyed in the event payload.
# 
#     Args:
#         owner (str, optional): ID of the owner of this event type.
# 
#     """
#     def __init__(self, owner=None):
#         EventType.__init__(
#             self,
#             '''
#             {
#               "$schema": "http://json-schema.org/draft-04/schema#",
#               "type": "object",
#               "properties": {
#                 "payload": {
#                   "type": "object",
#                   "properties": {
#                     "datum": {
#                       "type": "object",
#                       "properties": {}
#                     },
#                     "operation": {
#                       "type": "string"
#                     },
#                     "timestamp": {
#                       "type": ["number", "string"]
#                     },
#                     "meta": {
#                       "type": "object",
#                       "properties": {}
#                     }
#                   },
#                   "required": [
#                     "datum",
#                     "operation",
#                     "timestamp"
#                   ]
#                 }
#               },
#               "required": [
#                 "payload"
#               ]
#             }
#             ''',
#             description='Data operation events',
#             owner=owner)


import pytest
from baroque.entities.topic import Topic
from baroque.defaults.eventtypes import GenericEventType, DataOperationEventType
    with pytest.raises(AssertionError):
        Topic('test', None)
        pytest.fail()
    with pytest.raises(AssertionError):
        Topic('test', 'abc')
        pytest.fail()
    with pytest.raises(AssertionError):
        Topic('test', ['abc'])
        pytest.fail()
    with pytest.raises(AssertionError):
        Topic('test', [], tags='abc')
        pytest.fail()


def test_constructor():
    t = Topic('test', [], description='this is a test topic', owner='me')
    assert t.id is not None
    assert len(t.eventtypes) == 0
    assert t.owner is not None
    assert len(t.tags) == 0
    assert t.timestamp is not None
    ets = [GenericEventType(), DataOperationEventType()]
    t = Topic('test', ets,
              description='this is a test topic', owner='me',
              tags=['x', 'y'])
    assert len(t.eventtypes) == 2
    assert len(t.tags) == 2


def test_print():

# Path: baroque/entities/topic.py
# class Topic:
#     """A distribution channel where events of specific types can be published
#     and can be seen by subscribers of the topic. Topic subscribers will attach
#     a reactor to the topic, which will be fired whenever any event of the types
#     that are supported by the topic is published on the topic itself.
# 
#     Args:
#         name (str): the name of this topic
#         eventtypes (collection): the :obj:`baroque.entities.eventtype.EventType` objects that characterize this topic
#         description (str, optional): a description of this topic
#         owner (str, optional): the owner of this topic
#         tags (set, optional): the `set` of tags that describe this topic
# 
#     Raises:
#         `AssertionError`: name or tags are `None` or have a wrong type
# 
#     """
# 
#     def __init__(self, name, eventtypes, description=None, owner=None,
#                  tags=None):
#         assert name is not None
#         assert isinstance(name, str)
#         self.name = name
#         assert eventtypes is not None
#         if len(eventtypes) != 0:
#             self.types = EventTypesBag(eventtypes)
#         else:
#             self.types = EventTypesBag()
#         self.description = description
#         self.owner = owner
#         if tags is not None:
#             assert not isinstance(tags, str)
#             assert isinstance(tags, collections.Iterable)
#             self.tags = set(tags)
#         else:
#             self.tags = set()
#         self.id = str(uuid.uuid4())
#         self.timestamp = None
#         self.touch()
# 
#     @property
#     def eventtypes(self):
#         """:obj:`baroque.datastructures.bags.EventTypesBag`: bag containing the
#          event types of this topic"""
#         return self.types
# 
#     def touch(self):
#         """Sets the current time as timestamp of this topic"""
#         self.timestamp = ts.utc_now()
# 
#     def json(self):
#         """Dumps this object to a JSON string.
# 
#         Returns:
#             str
# 
#         """
#         data = dict(id=self.id, owner=self.owner, description=self.description,
#                     eventtypes=[str(et) for et in self.types],
#                     tags=list(self.tags), timestamp=ts.stringify(self.timestamp))
#         return dumps(data)
# 
#     def md5(self):
#         """Returns the MD5 hash of this object.
# 
#         Returns:
#             str
# 
#         """
#         m = hashlib.md5()
#         m.update(self.json().encode('utf-8'))
#         return m.hexdigest()
# 
#     def __repr__(self):
#         return '<{}.{} - name: {} - owner: {} - eventtypes: {}>'.format(
#             __name__,
#             self.__class__.__name__,
#             self.name,
#             self.owner or 'None',
#             ', '.join([str(et) for et in self.types]) or 'None'
#         )
# 
# Path: baroque/defaults/eventtypes.py
# class GenericEventType(EventType):
#     """Describes generic events with a free-form content.
# 
#     Args:
#         owner (str, optional): ID of the owner of this event type.
# 
#     """
#     def __init__(self, owner=None):
#         EventType.__init__(self,
#                            '''{
#                              "$schema": "http://json-schema.org/draft-04/schema#"
#                            }''',
#                            description='Generic event',
#                            owner=owner)
# 
# class DataOperationEventType(EventType):
#     """Describes events cast when some kind of operation is done on a
#     piece of data.
#     Suitable i.e. to track CRUD operations on DB tables or whole datastores.
#     Details about the impacted data entity and the operation are
#     conveyed in the event payload.
# 
#     Args:
#         owner (str, optional): ID of the owner of this event type.
# 
#     """
#     def __init__(self, owner=None):
#         EventType.__init__(
#             self,
#             '''
#             {
#               "$schema": "http://json-schema.org/draft-04/schema#",
#               "type": "object",
#               "properties": {
#                 "payload": {
#                   "type": "object",
#                   "properties": {
#                     "datum": {
#                       "type": "object",
#                       "properties": {}
#                     },
#                     "operation": {
#                       "type": "string"
#                     },
#                     "timestamp": {
#                       "type": ["number", "string"]
#                     },
#                     "meta": {
#                       "type": "object",
#                       "properties": {}
#                     }
#                   },
#                   "required": [
#                     "datum",
#                     "operation",
#                     "timestamp"
#                   ]
#                 }
#               },
#               "required": [
#                 "payload"
#               ]
#             }
#             ''',
#             description='Data operation events',
#             owner=owner)


# Path: tests/entities/test_topic.py
import pytest
from baroque.entities.topic import Topic
from baroque.defaults.eventtypes import GenericEventType, DataOperationEventType

    with pytest.raises(AssertionError):
        Topic('test', None)
        pytest.fail()
    with pytest.raises(AssertionError):
        Topic('test', 'abc')
        pytest.fail()
    with pytest.raises(AssertionError):
        Topic('test', ['abc'])
        pytest.fail()
    with pytest.raises(AssertionError):
        Topic('test', [], tags='abc')
        pytest.fail()


def test_constructor():
    t = Topic('test', [], description='this is a test topic', owner='me')
    assert t.id is not None
    assert len(t.eventtypes) == 0
    assert t.owner is not None
    assert len(t.tags) == 0
    assert t.timestamp is not None
    ets = [GenericEventType(), DataOperationEventType()]
    t = Topic('test', ets,
              description='this is a test topic', owner='me',
              tags=['x', 'y'])
    assert len(t.eventtypes) == 2
    assert len(t.tags) == 2


def test_print():

    print(Topic('test', []))