diff --git a/leapp/messaging/__init__.py b/leapp/messaging/__init__.py index dce92d418..4c7f4d1e1 100644 --- a/leapp/messaging/__init__.py +++ b/leapp/messaging/__init__.py @@ -189,4 +189,4 @@ def consume(self, actor, *types): if types: filtered = set(requested.__name__ for requested in types) messages = [message for message in messages if message['type'] in filtered] - return (lookup[message['type']].create(json.loads(message['message']['data'])) for message in messages) + return (lookup[msg['type']].create(msg, json.loads(msg['message']['data'])) for msg in messages) diff --git a/leapp/models/__init__.py b/leapp/models/__init__.py index 39bfc94dd..2c915e75f 100644 --- a/leapp/models/__init__.py +++ b/leapp/models/__init__.py @@ -71,6 +71,41 @@ def __init__(cls, name, bases, attrs): super(ModelMeta, cls).__init__(name, bases, attrs) +class MetaData(object): + def __init__(self, data): + self._data = data + + @property + def row_id(self): + """ Returns the row id of the message in the message table. """ + return self._data.get('id') + + @property + def actor(self): + """ Returns the name of the actor that has sent this message. """ + return self._data.get('actor') + + @property + def phase(self): + """ Returns the name of the phase in which this message has been sent. """ + return self._data.get('phase') + + @property + def timestamp(self): + """ Returns the timestamp string in ISO formst from when this message has been sent. """ + return self._data.get('stamp') + + @property + def topic(self): + """ Returns the name of the topic of this message. """ + return self._data.get('topic') + + @property + def hostname(self): + """ Returns the name of the host (FQDN) from where this message originates. """ + return self._data.get('hostname') + + class Model(with_metaclass(ModelMeta)): """ Model is a base class for all models. @@ -78,7 +113,8 @@ class Model(with_metaclass(ModelMeta)): Models are defining the data structure of the payload of messages and the metadata required, such as a name and topic. """ - def __init__(self, init_method='from_initialization', **kwargs): + def __init__(self, metadata=None, init_method='from_initialization', **kwargs): + self._metadata = MetaData(metadata or {}) super(Model, self).__init__() defined_fields = type(self).fields for key in kwargs.keys(): @@ -101,8 +137,17 @@ def __init__(self, init_method='from_initialization', **kwargs): Note: Dynamically added fields are ignored by the framework. """ + def message_metadata(self): + """ + Provides the message meta data of a message. + + :returns: An instance of :py:class:`leapp.models.MetaData` or None + :rtype: :py:class:`leapp.models.MetaData` or `NoneType` + """ + return self._metadata + @classmethod - def create(cls, data): + def create(cls, metadata, data): """ Create an instance of this class and use the data to initialize the fields within. @@ -110,7 +155,7 @@ def create(cls, data): :type data: dict :return: Instance of this class """ - return cls(init_method='to_model', **data) + return cls(metadata=metadata, init_method='to_model', **data) def dump(self): """ diff --git a/tests/scripts/test_serialization.py b/tests/scripts/test_serialization.py index 2075e9d5a..8805103bd 100644 --- a/tests/scripts/test_serialization.py +++ b/tests/scripts/test_serialization.py @@ -70,13 +70,13 @@ def test_base_usage(): def test_basic_model(): m = BasicModel(message='Some message') - m2 = BasicModel.create(m.dump()) + m2 = BasicModel.create(None, m.dump()) assert m.message == m2.message def test_string_list_model(): m = WithStringListModel(messages=['Some message']) - m2 = WithStringListModel.create(m.dump()) + m2 = WithStringListModel.create(None, m.dump()) assert m.messages == m2.messages m2.messages = 'str' @@ -98,7 +98,7 @@ def test_string_fields_violations(): def test_nested_model(): m = WithNestedModel(basic=BasicModel(message='Some message')) - m2 = WithNestedModel.create(m.dump()) + m2 = WithNestedModel.create(None, m.dump()) assert m.basic == m2.basic with pytest.raises(fields.ModelMisuseError): @@ -120,24 +120,24 @@ def test_nested_model(): x.dump() with pytest.raises(fields.ModelViolationError): - WithNestedModel.create(dict(basic=None)) + WithNestedModel.create(None, dict(basic=None)) with pytest.raises(fields.ModelViolationError): WithNestedModel(basic=None) - assert WithNestedModel.create({'basic': {'message': 'test-message'}}).basic.message == 'test-message' + assert WithNestedModel.create(None, {'basic': {'message': 'test-message'}}).basic.message == 'test-message' assert WithNestedModel(basic=BasicModel(message='test-message')).basic.message == 'test-message' def test_nested_list_model(): m = WithNestedListModel(items=[BasicModel(message='Some message')]) - m2 = WithNestedListModel.create(m.dump()) + m2 = WithNestedListModel.create(None, m.dump()) assert m.items == m2.items def test_field_types(): m = AllFieldTypesModel() - m2 = AllFieldTypesModel.create(m.dump()) + m2 = AllFieldTypesModel.create(None, m.dump()) assert m == m2