Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: appengine/findit/libs/meta_dict_serializer.py

Issue 2641583002: [Cuprit-finder] Add MetaDict class. (Closed)
Patch Set: Fix nits. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2017 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 from collections import OrderedDict
6
7 from libs.meta_object import Element
8 from libs.meta_object import MetaDict
9
10
11 class ElementSerializer(Element):
12
13 def ToList(self, element, default=None):
14 """Serializes an ``Element`` to a list of this single element.
15
16 Args:
17 element (Element or None): The element to be serialized. If the element
18 is None, return a list of one default value.
19 default (Element or None) The default value to set when None element is
20 provided.
21
22 Returns:
23 A list of single element.
24
25 Raises:
26 Exception: An error occurs when the passed-in meta object is not an
27 ``Element`` object.
28 """
29 if element is None:
30 return [default]
31
32 assert element.is_element, Exception(
33 '%s can only serialize Element object.' % self.__class__.__name__)
34 return [element]
35
36 def FromList(self, element_list, constructor=None):
37 """De-serializes from element_list to an ``Element``.
38
39 Args:
40 element_list (list of Element): A list of ``Element`` object.
41 constructor (callable): contructor of ``Element`` class.
42
43 Returns:
44 The ``Element`` object in the element_list.
45
46 Raises:
47 Exception: An error occurs when the element_list is not 1.
48 """
49 assert len(element_list) == len(self), Exception(
50 'The element list should have the same length as serializer')
51
52 constructor = constructor or (lambda x: x)
53 return constructor(element_list[0])
54
55 def __len__(self):
56 return 1
57
58
59 class MetaDictSerializer(MetaDict):
60 """Class that serialize a ``MetaDict`` to a list of ``Element``s.
61
62 This class itself is a ``MetaDict``, it has the same structure as the
63 meta_dict it wants to serialize or de-serialize, and it is using a
64 ``OrderedDict`` to keep track of the serializing order.
65 """
66
67 def __init__(self, value):
68 super(MetaDictSerializer, self).__init__(value)
69 self._length = None
70
71 def ToList(self, meta_dict, default=None):
72 """Serializes a ``MetaDict`` to a list of ``Element``s.
73
74 Args:
75 meta_dict (MetaDict or None): The element to be serialized. If meta_dict
76 is None, return a list of default values.
77 default (Element or None) The default value to set when None meta_dict is
78 provided.
79
80 Returns:
81 A list of ``Element``s.
82 """
83 element_list = []
84 for key, serializer in self.iteritems():
85 sub_meta_dict = meta_dict.get(key) if meta_dict else None
86 element_list.extend(serializer.ToList(sub_meta_dict, default=default))
87
88 return element_list
89
90 def FromList(self, element_list,
91 meta_constructor=None,
92 element_constructor=None):
chanli 2017/01/19 02:10:58 Nit: The argument list can be in 2 lines.
Sharu Jiang 2017/01/19 21:00:45 Done.
93 """De-serializes from element_list to an ``MetaDict``.
94
95 Args:
96 element_list (list of Element): A list of ``Element`` object.
97 element_constructor (callable): The constructor of ``Element`` object that
98 takes one value in element_list as input.
99 meta_constructor (callable): The contructor of ``MetaDict`` object that
100 only take one dict of MetaObjects as input.
101
102 Returns:
103 The ``MetaDict`` object contructed from element_list.
104
105 Raises:
106 Exception: An error occurs when the length of element_list is not equal
107 to the serializer length.
108 """
109 assert len(self) == len(element_list), Exception(
110 'The element list should have the same length as serializer')
111
112 meta_constructor = meta_constructor or (lambda x: x)
113 meta_objs = {}
114 index = 0
115 for key, serializer in self.iteritems():
116 # Truncate the segment in the element list to construct
117 # the ``MetaObject`` corresponding to ``key``.
118 segment = element_list[index : (index + len(serializer))]
119 if serializer.is_element:
120 meta_objs[key] = serializer.FromList(segment, element_constructor)
121 else:
122 meta_objs[key] = serializer.FromList(segment, meta_constructor,
123 element_constructor)
124
125 index += len(serializer)
126
127 return meta_constructor(meta_objs)
128
129 def _Length(self):
130 """Methods to get the length of the serializer recusively.
131
132 Note, the length of a serializer is the number of elements, which is also
133 the number of "real values" in a ``MetaDict`` structure.
134 """
135 if self._length is not None:
136 return self._length
137
138 self._length = 0
139 for value in self.itervalues():
140 self._length += len(value)
141
142 return self._length
143
144 def __len__(self):
145 return self._Length()
146
147
148 def GetSerializer(meta_object, key=None):
149 """Factory to get a serializer corresponding to a ``MetaObject``.
150
151 Args:
152 meta_object (MetaObject): ``Element`` or ``MetaDict`` objects.
153 key (callable or None): Key function to sort ``MetaDict`` object.
154 """
155 if meta_object.is_element:
156 return ElementSerializer()
157
158 sorted_meta = sorted(meta_object.iteritems(), key=key)
159 ordered_dict = OrderedDict((key, GetSerializer(sub_meta))
160 for key, sub_meta in sorted_meta)
161
162 return MetaDictSerializer(ordered_dict)
OLDNEW
« no previous file with comments | « no previous file | appengine/findit/libs/meta_object.py » ('j') | appengine/findit/libs/test/meta_dict_serializer_test.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698