Move the DesignateAdapter to return non-wrapped objects

Change-Id: Iaab9514fc5f443cc6dd09c10f928c042b9dbcfb7
Partially-Implements: blueprint validation-cleanup
This commit is contained in:
Graham Hayes 2015-03-13 19:47:38 +00:00
parent 0c982b7d8d
commit fce8049cb6
4 changed files with 46 additions and 93 deletions

View File

@ -21,39 +21,3 @@ LOG = logging.getLogger(__name__)
class APIv1Adapter(base.DesignateAdapter):
ADAPTER_FORMAT = 'API_v1'
#####################
# Rendering methods #
#####################
@classmethod
def render(cls, object, *args, **kwargs):
return super(APIv1Adapter, cls).render(
cls.ADAPTER_FORMAT, object, *args, **kwargs)
@classmethod
def _render_list(cls, list_object, *args, **kwargs):
inner = cls._render_inner_list(list_object, *args, **kwargs)
return {cls.MODIFICATIONS['options']['collection_name']: inner}
@classmethod
def _render_object(cls, object, *args, **kwargs):
return cls._render_inner_object(object, *args, **kwargs)
#####################
# Parsing methods #
#####################
@classmethod
def parse(cls, values, output_object, *args, **kwargs):
return super(APIv1Adapter, cls).parse(
cls.ADAPTER_FORMAT, values, output_object, *args, **kwargs)
@classmethod
def _parse_list(cls, values, output_object, *args, **kwargs):
return cls._parse_inner_list(values, output_object, *args, **kwargs)
@classmethod
def _parse_object(cls, values, output_object, *args, **kwargs):
return cls._parse_inner_object(values, output_object, *args, **kwargs)

View File

@ -34,37 +34,32 @@ class APIv2Adapter(base.DesignateAdapter):
# Rendering methods #
#####################
@classmethod
def render(cls, object, *args, **kwargs):
return super(APIv2Adapter, cls).render(
cls.ADAPTER_FORMAT, object, *args, **kwargs)
@classmethod
def _render_list(cls, list_object, *args, **kwargs):
inner = cls._render_inner_list(list_object, *args, **kwargs)
outer = {}
r_list = super(APIv2Adapter, cls)._render_list(
list_object, *args, **kwargs)
if cls.MODIFICATIONS['options'].get('links', True):
outer['links'] = cls._get_collection_links(
if cls.MODIFICATIONS['options'].get('links', True)\
and 'request' in kwargs:
r_list['links'] = cls._get_collection_links(
list_object, kwargs['request'])
# Check if we should include metadata
if isinstance(list_object, obj_base.PagedListObjectMixin):
metadata = {}
metadata['total_count'] = list_object.total_count
outer['metadata'] = metadata
r_list['metadata'] = metadata
outer[cls.MODIFICATIONS['options']['collection_name']] = inner
return outer
return r_list
@classmethod
def _render_object(cls, object, *args, **kwargs):
inner = cls._render_inner_object(object, *args, **kwargs)
obj = super(APIv2Adapter, cls)._render_object(object, *args, **kwargs)
if cls.MODIFICATIONS['options'].get('links', True):
inner['links'] = cls._get_resource_links(object, kwargs['request'])
if cls.MODIFICATIONS['options'].get('links', True)\
and 'request' in kwargs:
obj['links'] = cls._get_resource_links(object, kwargs['request'])
return {cls.MODIFICATIONS['options']['resource_name']: inner}
return obj
#####################
# Parsing methods #
@ -75,16 +70,6 @@ class APIv2Adapter(base.DesignateAdapter):
return super(APIv2Adapter, cls).parse(
cls.ADAPTER_FORMAT, values, output_object, *args, **kwargs)
@classmethod
def _parse_list(cls, values, output_object, *args, **kwargs):
return cls._parse_inner_list(values, output_object, *args, **kwargs)
@classmethod
def _parse_object(cls, values, output_object, *args, **kwargs):
inner = values[cls.MODIFICATIONS['options']['resource_name']]
return cls._parse_inner_object(inner, output_object, *args, **kwargs)
#####################
# Link methods #
#####################

View File

@ -57,7 +57,10 @@ class DesignateAdapter(object):
@classmethod
def get_object_adapter(cls, format_, object):
key = '%s:%s' % (format_, object.obj_name())
if isinstance(object, objects.DesignateObject):
key = '%s:%s' % (format_, object.obj_name())
else:
key = '%s:%s' % (format_, object)
try:
return cls._adapter_classes[key]
except KeyError as e:
@ -85,7 +88,7 @@ class DesignateAdapter(object):
format_, object)._render_object(object, *args, **kwargs)
@classmethod
def _render_inner_object(cls, object, *args, **kwargs):
def _render_object(cls, object, *args, **kwargs):
# The dict we will return to be rendered to JSON / output format
r_obj = {}
# Loop over all fields that are supposed to be output
@ -110,7 +113,7 @@ class DesignateAdapter(object):
r_obj[key] = cls.get_object_adapter(
cls.ADAPTER_FORMAT,
object.FIELDS[obj_key].get('relation_cls')).render(
obj, *args, **kwargs)
cls.ADAPTER_FORMAT, obj, *args, **kwargs)
else:
# Just attach the damn item if there is no weird edge cases
r_obj[key] = obj
@ -118,7 +121,7 @@ class DesignateAdapter(object):
return r_obj
@classmethod
def _render_inner_list(cls, list_object, *args, **kwargs):
def _render_list(cls, list_object, *args, **kwargs):
# The list we will return to be rendered to JSON / output format
r_list = []
# iterate and convert each DesignateObject in the list, and append to
@ -126,8 +129,8 @@ class DesignateAdapter(object):
for object in list_object:
r_list.append(cls.get_object_adapter(
cls.ADAPTER_FORMAT,
object.obj_name()).render(object, *args, **kwargs))
return r_list
object).render(cls.ADAPTER_FORMAT, object, *args, **kwargs))
return {cls.MODIFICATIONS['options']['collection_name']: r_list}
#####################
# Parsing methods #
@ -140,17 +143,17 @@ class DesignateAdapter(object):
# type_ = 'list'
return cls.get_object_adapter(
format_,
output_object.obj_name())._parse_list(
output_object)._parse_list(
values, output_object, *args, **kwargs)
else:
# type_ = 'object'
return cls.get_object_adapter(
format_,
output_object.obj_name())._parse_object(
output_object)._parse_object(
values, output_object, *args, **kwargs)
@classmethod
def _parse_inner_object(cls, values, output_object, *args, **kwargs):
def _parse_object(cls, values, output_object, *args, **kwargs):
error_keys = []
for key, value in values.iteritems():
@ -163,6 +166,24 @@ class DesignateAdapter(object):
if cls.MODIFICATIONS['fields'][key].get('rename', False):
obj_key = cls.MODIFICATIONS['fields'][key].get('rename')
##############################################################
# TODO(graham): Remove this section of code when validation #
# is moved into DesignateObjects properly #
##############################################################
# Check if the field should be allowed change after it is initially
# set (eg domain name)
if cls.MODIFICATIONS['fields'][key].get('idempotent', False):
if getattr(output_object, obj_key, False) and \
getattr(output_object, obj_key) != value:
error_keys.append(key)
break
# Is this field a read only field
elif cls.MODIFICATIONS['fields'][key].get('read_only', True) and \
getattr(output_object, obj_key) != value:
error_keys.append(key)
break
# Check if the key is a nested object
if output_object.FIELDS.get(obj_key, {}).get('relation', False):
# Get the right class name
@ -196,5 +217,5 @@ class DesignateAdapter(object):
return output_object
@classmethod
def _parse_inner_list(cls, values, output_object, *args, **kwargs):
def _parse_list(cls, values, output_object, *args, **kwargs):
raise exceptions.NotImplemented('List adaption not implemented')

View File

@ -32,28 +32,11 @@ class DesignateTestAdapter(adapters.DesignateAdapter):
'options': {}
}
@classmethod
def render(cls, object, *args, **kwargs):
return super(DesignateTestAdapter, cls).render(
cls.ADAPTER_FORMAT, object, *args, **kwargs)
@classmethod
def _render_list(cls, list_object, *args, **kwargs):
inner = cls._render_inner_list(list_object, *args, **kwargs)
return inner
@classmethod
def _render_object(cls, object, *args, **kwargs):
inner = cls._render_inner_object(object, *args, **kwargs)
return inner
class DesignateAdapterTest(tests.TestCase):
def test_get_object_adapter(self):
adapters.DesignateAdapter.get_object_adapter(
'TEST_API', objects.DesignateObject)
'TEST_API', objects.DesignateObject())
def test_get_object_render(self):
adapters.DesignateAdapter.render('TEST_API', objects.DesignateObject)
def test_object_render(self):
adapters.DesignateAdapter.render('TEST_API', objects.DesignateObject())