diff --git a/leapp/models/fields/__init__.py b/leapp/models/fields/__init__.py index b11559ebe..622b9eee7 100644 --- a/leapp/models/fields/__init__.py +++ b/leapp/models/fields/__init__.py @@ -1,3 +1,4 @@ +import base64 import copy import datetime import json @@ -239,6 +240,33 @@ def _model_type(self): return six.string_types + (six.binary_type,) +class Blob(BuiltinField): + """ + Blob field + """ + @property + def _model_type(self): + # NOTE(ivasilev) Both string_types and binary_types are necessary here to pass value checks on + # serialization/deserialization. Serialized JSON-friendly model will have a string type field (the base64 + # ascii string) while deserialized model will have a binary type field. + return six.string_types + (six.binary_type,) + + def _convert_to_model(self, value, name): + self._validate_model_value(value=value, name=name) + if value is None: + return None + + return base64.b64decode(value) + + def _convert_from_model(self, value, name): + self._validate_model_value(value=value, name=name) + if value is None: + return None + + # NOTE(ivasilev) b64 encoding is always ascii, thus ascii decoding to get a string + return base64.b64encode(value).decode('ascii') + + class DateTime(BuiltinField): """ DateTime field to handle datetime objects which are converted to the ISO format and parsed back from there diff --git a/packaging/leapp.spec b/packaging/leapp.spec index f6af9dcb3..a22f19f29 100644 --- a/packaging/leapp.spec +++ b/packaging/leapp.spec @@ -13,7 +13,7 @@ # This is kind of help for more flexible development of leapp repository, # so people do not have to wait for new official release of leapp to ensure # it is installed/used the compatible one. -%global framework_version 3.0 +%global framework_version 3.1 # IMPORTANT: everytime the requirements are changed, increment number by one # - same for Provides in deps subpackage diff --git a/tests/scripts/test_serialization.py b/tests/scripts/test_serialization.py index d5d2fd853..c61f2dadc 100644 --- a/tests/scripts/test_serialization.py +++ b/tests/scripts/test_serialization.py @@ -41,6 +41,12 @@ class WithNestedListModel(Model): items = fields.List(fields.Model(BasicModel)) +class WithBlobModel(Model): + topic = ModelTestTopic + message = fields.Blob() + can_be_empty = fields.Nullable(fields.Blob()) + + class AllFieldTypesModel(Model): topic = ModelTestTopic float_field = fields.Float(default=3.14) @@ -74,6 +80,12 @@ def test_basic_model(): assert m.message == m2.message +def test_bytestring_model(): + m = WithBlobModel(message=b'\xf3\xcf\xcf\xc2\xdd\xc5\xce\xc9\xc5') + m2 = WithBlobModel.create(m.dump()) + assert m.message == m2.message + + def test_string_list_model(): m = WithStringListModel(messages=['Some message']) m2 = WithStringListModel.create(m.dump())