Merge "Recurse dictionary generation in model to_dict()"
This commit is contained in:
commit
1fbfd3c065
@ -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):
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user