Chromium Code Reviews| OLD | NEW |
|---|---|
| (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.IsElement(), 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, meta_constructor, element_constructor=None): | |
| 91 """De-serializes from element_list to an ``MetaDict``. | |
| 92 | |
| 93 Args: | |
| 94 element_list (list of Element): A list of ``Element`` object. | |
| 95 element_constructor (callable): The constructor of ``Element`` object that | |
| 96 takes one value in element_list as input. | |
| 97 meta_constructor (callable): The contructor of ``MetaDict`` object that | |
| 98 only take one dict of MetaObjects as input. | |
| 99 | |
| 100 Returns: | |
| 101 The ``MetaDict`` object contructed from element_list. | |
| 102 | |
| 103 Raises: | |
| 104 Exception: An error occurs when the length of element_list is not equal | |
| 105 to the serializer length. | |
| 106 """ | |
| 107 assert len(self) == len(element_list), Exception( | |
| 108 'The element list should have the same length as serializer') | |
| 109 | |
| 110 meta_objs = {} | |
| 111 index = 0 | |
| 112 for key, serializer in self.iteritems(): | |
| 113 # Trucate the segment in the element list to construct | |
|
chanli
2017/01/18 22:14:23
Nit:Truncate?
chanli
2017/01/18 22:14:23
Nit: 2 spaces between 'the' and 'segment'
Sharu Jiang
2017/01/19 00:00:52
Done.
Sharu Jiang
2017/01/19 00:00:52
Done.
| |
| 114 # the ``MetaObject`` corresponding to ``key``. | |
| 115 segment = element_list[index : (index + len(serializer))] | |
| 116 if serializer.IsElement(): | |
| 117 meta_objs[key] = serializer.FromList(segment, element_constructor) | |
|
chanli
2017/01/18 22:14:23
This means all elements in the dict must use the s
Sharu Jiang
2017/01/19 00:00:52
Yes.
chanli
2017/01/19 02:10:58
So I assume this is expected behavior.
| |
| 118 else: | |
| 119 meta_objs[key] = serializer.FromList(segment, meta_constructor, | |
| 120 element_constructor) | |
| 121 | |
| 122 index += len(serializer) | |
| 123 | |
| 124 return meta_constructor(meta_objs) | |
| 125 | |
| 126 def _Length(self): | |
| 127 """Methods to get the length of the serializer recusively. | |
| 128 | |
| 129 Note, the length of a serializer is the number of elements, which is also | |
| 130 the number of "real values" in a ``MetaDict`` structure. | |
| 131 """ | |
| 132 if self._length is not None: | |
| 133 return self._length | |
| 134 | |
| 135 self._length = 0 | |
| 136 for value in self.itervalues(): | |
| 137 self._length += len(value) | |
| 138 | |
| 139 return self._length | |
| 140 | |
| 141 def __len__(self): | |
| 142 return self._Length() | |
| 143 | |
| 144 | |
| 145 def GetSerializer(meta_object, key=None): | |
| 146 """Factory to get a serializer corresponding to a ``MetaObject``. | |
| 147 | |
| 148 Args: | |
| 149 meta_object (MetaObject): ``Element`` or ``MetaDict`` objects. | |
| 150 constructor (callable or None): Callable with dict as input and returns a | |
|
chanli
2017/01/18 22:14:23
constructor is not in argument list?
Sharu Jiang
2017/01/19 00:00:52
Oops, forgot to delete it.
| |
| 151 serializer(either ``ElementSerializer`` or ``MetaDictSerializer``). If | |
| 152 None, the init function of meta_object is used. | |
| 153 key (callable or None): Key function to sort ``MetaDict`` object. | |
| 154 """ | |
| 155 if meta_object.IsElement(): | |
| 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) | |
| OLD | NEW |