1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import re
from designate.objects.adapters.api_v2 import base
from designate import objects
class NotSpecifiedSential:
pass
REQUIRED_RE = re.compile(r"\'([\w]*)\' is a required property")
class ValidationErrorAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.ValidationError
MODIFICATIONS = {
'fields': {
"path": {},
"message": {},
"validator": {},
"validator_value": {},
},
'options': {
'links': False,
'resource_name': 'error',
'collection_name': 'errors',
}
}
@classmethod
def _render_object(cls, error, *args, **kwargs):
# Do the usual rename
error_dict = super(ValidationErrorAPIv2Adapter, cls)._render_object(
error, *args, **kwargs)
# Currently JSON Schema doesn't add the path on for required items
if error_dict.get('validator', '') == 'required':
error_dict['path'].append(
REQUIRED_RE.match(error.message).group(1))
object = kwargs['failed_object']
# Rename the keys in the path list
error_dict['path'] = cls._rename_path(object, error_dict['path'])
return error_dict
@classmethod
def _rename_path(cls, object, path):
new_path = list()
obj_adapter = cls.get_object_adapter(cls.ADAPTER_FORMAT, object)
for path_segment in path:
new_path_segment, obj_adapter = cls._rename_path_segment(
obj_adapter, object, path_segment)
new_path.append(new_path_segment)
return new_path
@classmethod
def _rename_path_segment(cls, obj_adapter, object, path_segment):
# Check if the object is a list - lists will just have an index as a
# value, ands this can't be renamed
if issubclass(obj_adapter.ADAPTER_OBJECT, objects.ListObjectMixin):
obj_adapter = cls.get_object_adapter(
cls.ADAPTER_FORMAT,
obj_adapter.ADAPTER_OBJECT.LIST_ITEM_TYPE.obj_name())
# Return the segment as is, and the next adapter (which is the
# LIST_ITEM_TYPE)
return path_segment, obj_adapter
for key, value in obj_adapter.MODIFICATIONS.get(
'fields', {}).items():
# Check if this field as actually a nested object
field = object.FIELDS.get(path_segment, {})
if isinstance(field, dict) and field.get('relation'):
obj_cls = object.FIELDS.get(path_segment).get('relation_cls')
obj_adapter = cls.get_object_adapter(
cls.ADAPTER_FORMAT,
obj_cls)
object = objects.DesignateObject.obj_cls_from_name(obj_cls)()
# Recurse down into this object
path_segment, obj_adapter = cls._rename_path_segment(
obj_adapter, object, path_segment)
# No need to continue the loop
break
elif hasattr(field, 'objname'):
obj_cls = field.objname
obj_adapter = cls.get_object_adapter(
cls.ADAPTER_FORMAT, obj_cls)
object = objects.DesignateObject.obj_cls_from_name(obj_cls)() # noqa
# Recurse down into this object
path_segment, obj_adapter = cls._rename_path_segment(
obj_adapter, object, path_segment)
# No need to continue the loop
break
if not isinstance(
value.get(
'rename', NotSpecifiedSential()), NotSpecifiedSential)\
and path_segment == value.get('rename'):
# Just do the rename
path_segment = key
return path_segment, obj_adapter
class ValidationErrorListAPIv2Adapter(base.APIv2Adapter):
ADAPTER_OBJECT = objects.ValidationErrorList
MODIFICATIONS = {
'options': {
'links': False,
'resource_name': 'error',
'collection_name': 'errors',
}
}
|