Merge "Recurse dictionary generation in model to_dict()"

This commit is contained in:
Jenkins 2017-03-07 13:37:52 +00:00 committed by Gerrit Code Review
commit 1fbfd3c065
2 changed files with 89 additions and 8 deletions

View File

@ -15,6 +15,7 @@
# under the License.
import re
import six
from sqlalchemy.orm import collections
@ -22,19 +23,44 @@ from octavia.common import constants
class BaseDataModel(object):
# NOTE(brandon-logan) This does not discover dicts for relationship
# attributes.
def to_dict(self):
def to_dict(self, calling_classes=None, recurse=False, **kwargs):
"""Converts a data model to a dictionary."""
calling_classes = calling_classes or []
ret = {}
for attr in self.__dict__:
if attr.startswith('_'):
if attr.startswith('_') or not kwargs.get(attr, True):
continue
if isinstance(getattr(self, attr), (BaseDataModel, list)):
ret[attr] = None
value = self.__dict__[attr]
if recurse:
if isinstance(getattr(self, attr), list):
ret[attr] = []
for item in value:
if isinstance(item, BaseDataModel):
if type(self) not in calling_classes:
ret[attr].append(
item.to_dict(calling_classes=(
calling_classes + [type(self)])))
else:
ret[attr] = None
else:
ret[attr] = item
elif isinstance(getattr(self, attr), BaseDataModel):
if type(self) not in calling_classes:
ret[attr] = value.to_dict(
calling_classes=calling_classes + [type(self)])
else:
ret[attr] = None
elif six.PY2 and isinstance(value, six.text_type):
ret[attr.encode('utf8')] = value.encode('utf8')
else:
ret[attr] = value
else:
ret[attr] = self.__dict__[attr]
if isinstance(getattr(self, attr), (BaseDataModel, list)):
ret[attr] = None
else:
ret[attr] = value
return ret
def __eq__(self, other):

View File

@ -98,3 +98,58 @@ class TestTypeDataModelRenames(base.TestCase):
type_dict = TestTypeTenantProject(tenant_id='1234').to_dict()
self.assertEqual('1234', type_dict['project_id'])
self.assertNotIn('tenant_id', type_dict)
class TestToDictModel(data_models.BaseDataModel):
def __init__(self, text, parent=None):
self.parent = parent
self.child = None
self.children = None
self.text = text
def set_children(self, children):
self.children = children
def set_child(self, child):
self.child = child
def set_parent(self, parent):
self.parent = parent
class TestDataModelToDict(base.TestCase):
RECURSED_RESULT = {'parent': None,
'text': 'parent_text',
'child': {'parent': None,
'text': 'child_text',
'child': None,
'children': None},
'children': [
{'parent': None,
'text': 'child1_text',
'child': None,
'children': None},
{'parent': None,
'text': 'child2_text',
'child': None,
'children': None}]}
NO_RECURSE_RESULT = {'parent': None,
'text': 'parent_text',
'child': None,
'children': None}
def setUp(self):
super(TestDataModelToDict, self).setUp()
self.model = TestToDictModel('parent_text')
self.model.set_child(TestToDictModel('child_text', self.model))
self.model.set_children([TestToDictModel('child1_text', self.model),
TestToDictModel('child2_text', self.model)])
def test_to_dict_no_recurse(self):
self.assertEqual(self.model.to_dict(),
self.NO_RECURSE_RESULT)
def test_to_dict_recurse(self):
self.assertEqual(self.model.to_dict(recurse=True),
self.RECURSED_RESULT)