Revision 473ab806
b/lib/objects.py | ||
---|---|---|
263 | 263 |
obj = cls(**val_str) # pylint: disable=W0142 |
264 | 264 |
return obj |
265 | 265 |
|
266 |
@staticmethod |
|
267 |
def _ContainerToDicts(container): |
|
268 |
"""Convert the elements of a container to standard python types. |
|
269 |
|
|
270 |
This method converts a container with elements derived from |
|
271 |
ConfigData to standard python types. If the container is a dict, |
|
272 |
we don't touch the keys, only the values. |
|
273 |
|
|
274 |
""" |
|
275 |
if isinstance(container, dict): |
|
276 |
ret = dict([(k, v.ToDict()) for k, v in container.iteritems()]) |
|
277 |
elif isinstance(container, (list, tuple, set, frozenset)): |
|
278 |
ret = [elem.ToDict() for elem in container] |
|
279 |
else: |
|
280 |
raise TypeError("Invalid type %s passed to _ContainerToDicts" % |
|
281 |
type(container)) |
|
282 |
return ret |
|
283 |
|
|
284 |
@staticmethod |
|
285 |
def _ContainerFromDicts(source, c_type, e_type): |
|
286 |
"""Convert a container from standard python types. |
|
287 |
|
|
288 |
This method converts a container with standard python types to |
|
289 |
ConfigData objects. If the container is a dict, we don't touch the |
|
290 |
keys, only the values. |
|
291 |
|
|
292 |
""" |
|
293 |
if not isinstance(c_type, type): |
|
294 |
raise TypeError("Container type %s passed to _ContainerFromDicts is" |
|
295 |
" not a type" % type(c_type)) |
|
296 |
if source is None: |
|
297 |
source = c_type() |
|
298 |
if c_type is dict: |
|
299 |
ret = dict([(k, e_type.FromDict(v)) for k, v in source.iteritems()]) |
|
300 |
elif c_type in (list, tuple, set, frozenset): |
|
301 |
ret = c_type([e_type.FromDict(elem) for elem in source]) |
|
302 |
else: |
|
303 |
raise TypeError("Invalid container type %s passed to" |
|
304 |
" _ContainerFromDicts" % c_type) |
|
305 |
return ret |
|
306 |
|
|
307 | 266 |
def Copy(self): |
308 | 267 |
"""Makes a deep copy of the current object and its children. |
309 | 268 |
|
... | ... | |
446 | 405 |
mydict = super(ConfigData, self).ToDict() |
447 | 406 |
mydict["cluster"] = mydict["cluster"].ToDict() |
448 | 407 |
for key in "nodes", "instances", "nodegroups", "networks": |
449 |
mydict[key] = self._ContainerToDicts(mydict[key])
|
|
408 |
mydict[key] = objectutils.ContainerToDicts(mydict[key])
|
|
450 | 409 |
|
451 | 410 |
return mydict |
452 | 411 |
|
... | ... | |
457 | 416 |
""" |
458 | 417 |
obj = super(ConfigData, cls).FromDict(val) |
459 | 418 |
obj.cluster = Cluster.FromDict(obj.cluster) |
460 |
obj.nodes = cls._ContainerFromDicts(obj.nodes, dict, Node) |
|
461 |
obj.instances = cls._ContainerFromDicts(obj.instances, dict, Instance) |
|
462 |
obj.nodegroups = cls._ContainerFromDicts(obj.nodegroups, dict, NodeGroup) |
|
463 |
obj.networks = cls._ContainerFromDicts(obj.networks, dict, Network) |
|
419 |
obj.nodes = objectutils.ContainerFromDicts(obj.nodes, dict, Node) |
|
420 |
obj.instances = \ |
|
421 |
objectutils.ContainerFromDicts(obj.instances, dict, Instance) |
|
422 |
obj.nodegroups = \ |
|
423 |
objectutils.ContainerFromDicts(obj.nodegroups, dict, NodeGroup) |
|
424 |
obj.networks = objectutils.ContainerFromDicts(obj.networks, dict, Network) |
|
464 | 425 |
return obj |
465 | 426 |
|
466 | 427 |
def HasAnyDiskOfType(self, dev_type): |
... | ... | |
768 | 729 |
for attr in ("children",): |
769 | 730 |
alist = bo.get(attr, None) |
770 | 731 |
if alist: |
771 |
bo[attr] = self._ContainerToDicts(alist)
|
|
732 |
bo[attr] = objectutils.ContainerToDicts(alist)
|
|
772 | 733 |
return bo |
773 | 734 |
|
774 | 735 |
@classmethod |
... | ... | |
778 | 739 |
""" |
779 | 740 |
obj = super(Disk, cls).FromDict(val) |
780 | 741 |
if obj.children: |
781 |
obj.children = cls._ContainerFromDicts(obj.children, list, Disk)
|
|
742 |
obj.children = objectutils.ContainerFromDicts(obj.children, list, Disk)
|
|
782 | 743 |
if obj.logical_id and isinstance(obj.logical_id, list): |
783 | 744 |
obj.logical_id = tuple(obj.logical_id) |
784 | 745 |
if obj.physical_id and isinstance(obj.physical_id, list): |
... | ... | |
1136 | 1097 |
for attr in "nics", "disks": |
1137 | 1098 |
alist = bo.get(attr, None) |
1138 | 1099 |
if alist: |
1139 |
nlist = self._ContainerToDicts(alist)
|
|
1100 |
nlist = objectutils.ContainerToDicts(alist)
|
|
1140 | 1101 |
else: |
1141 | 1102 |
nlist = [] |
1142 | 1103 |
bo[attr] = nlist |
... | ... | |
1155 | 1116 |
if "admin_up" in val: |
1156 | 1117 |
del val["admin_up"] |
1157 | 1118 |
obj = super(Instance, cls).FromDict(val) |
1158 |
obj.nics = cls._ContainerFromDicts(obj.nics, list, NIC)
|
|
1159 |
obj.disks = cls._ContainerFromDicts(obj.disks, list, Disk)
|
|
1119 |
obj.nics = objectutils.ContainerFromDicts(obj.nics, list, NIC)
|
|
1120 |
obj.disks = objectutils.ContainerFromDicts(obj.disks, list, Disk)
|
|
1160 | 1121 |
return obj |
1161 | 1122 |
|
1162 | 1123 |
def UpgradeConfig(self): |
... | ... | |
1344 | 1305 |
|
1345 | 1306 |
hv_state = data.get("hv_state", None) |
1346 | 1307 |
if hv_state is not None: |
1347 |
data["hv_state"] = self._ContainerToDicts(hv_state)
|
|
1308 |
data["hv_state"] = objectutils.ContainerToDicts(hv_state)
|
|
1348 | 1309 |
|
1349 | 1310 |
disk_state = data.get("disk_state", None) |
1350 | 1311 |
if disk_state is not None: |
1351 | 1312 |
data["disk_state"] = \ |
1352 |
dict((key, self._ContainerToDicts(value))
|
|
1313 |
dict((key, objectutils.ContainerToDicts(value))
|
|
1353 | 1314 |
for (key, value) in disk_state.items()) |
1354 | 1315 |
|
1355 | 1316 |
return data |
... | ... | |
1362 | 1323 |
obj = super(Node, cls).FromDict(val) |
1363 | 1324 |
|
1364 | 1325 |
if obj.hv_state is not None: |
1365 |
obj.hv_state = cls._ContainerFromDicts(obj.hv_state, dict, NodeHvState) |
|
1326 |
obj.hv_state = \ |
|
1327 |
objectutils.ContainerFromDicts(obj.hv_state, dict, NodeHvState) |
|
1366 | 1328 |
|
1367 | 1329 |
if obj.disk_state is not None: |
1368 | 1330 |
obj.disk_state = \ |
1369 |
dict((key, cls._ContainerFromDicts(value, dict, NodeDiskState))
|
|
1331 |
dict((key, objectutils.ContainerFromDicts(value, dict, NodeDiskState))
|
|
1370 | 1332 |
for (key, value) in obj.disk_state.items()) |
1371 | 1333 |
|
1372 | 1334 |
return obj |
... | ... | |
1935 | 1897 |
|
1936 | 1898 |
""" |
1937 | 1899 |
mydict = super(_QueryResponseBase, self).ToDict() |
1938 |
mydict["fields"] = self._ContainerToDicts(mydict["fields"])
|
|
1900 |
mydict["fields"] = objectutils.ContainerToDicts(mydict["fields"])
|
|
1939 | 1901 |
return mydict |
1940 | 1902 |
|
1941 | 1903 |
@classmethod |
... | ... | |
1944 | 1906 |
|
1945 | 1907 |
""" |
1946 | 1908 |
obj = super(_QueryResponseBase, cls).FromDict(val) |
1947 |
obj.fields = cls._ContainerFromDicts(obj.fields, list, QueryFieldDefinition) |
|
1909 |
obj.fields = \ |
|
1910 |
objectutils.ContainerFromDicts(obj.fields, list, QueryFieldDefinition) |
|
1948 | 1911 |
return obj |
1949 | 1912 |
|
1950 | 1913 |
|
b/lib/objectutils.py | ||
---|---|---|
21 | 21 |
"""Module for object related utils.""" |
22 | 22 |
|
23 | 23 |
|
24 |
#: Supported container types for serialization/de-serialization (must be a |
|
25 |
#: tuple as it's used as a parameter for C{isinstance}) |
|
26 |
_SEQUENCE_TYPES = (list, tuple, set, frozenset) |
|
27 |
|
|
28 |
|
|
24 | 29 |
class AutoSlots(type): |
25 | 30 |
"""Meta base class for __slots__ definitions. |
26 | 31 |
|
... | ... | |
91 | 96 |
|
92 | 97 |
""" |
93 | 98 |
raise NotImplementedError |
99 |
|
|
100 |
|
|
101 |
def ContainerToDicts(container): |
|
102 |
"""Convert the elements of a container to standard Python types. |
|
103 |
|
|
104 |
This method converts a container with elements to standard Python types. If |
|
105 |
the input container is of the type C{dict}, only its values are touched. |
|
106 |
Those values, as well as all elements of input sequences, must support a |
|
107 |
C{ToDict} method returning a serialized version. |
|
108 |
|
|
109 |
@type container: dict or sequence (see L{_SEQUENCE_TYPES}) |
|
110 |
|
|
111 |
""" |
|
112 |
if isinstance(container, dict): |
|
113 |
ret = dict([(k, v.ToDict()) for k, v in container.items()]) |
|
114 |
elif isinstance(container, _SEQUENCE_TYPES): |
|
115 |
ret = [elem.ToDict() for elem in container] |
|
116 |
else: |
|
117 |
raise TypeError("Unknown container type '%s'" % type(container)) |
|
118 |
|
|
119 |
return ret |
|
120 |
|
|
121 |
|
|
122 |
def ContainerFromDicts(source, c_type, e_type): |
|
123 |
"""Convert a container from standard python types. |
|
124 |
|
|
125 |
This method converts a container with standard Python types to objects. If |
|
126 |
the container is a dict, we don't touch the keys, only the values. |
|
127 |
|
|
128 |
@type source: None, dict or sequence (see L{_SEQUENCE_TYPES}) |
|
129 |
@param source: Input data |
|
130 |
@type c_type: type class |
|
131 |
@param c_type: Desired type for returned container |
|
132 |
@type e_type: element type class |
|
133 |
@param e_type: Item type for elements in returned container (must have a |
|
134 |
C{FromDict} class method) |
|
135 |
|
|
136 |
""" |
|
137 |
if not isinstance(c_type, type): |
|
138 |
raise TypeError("Container type '%s' is not a type" % type(c_type)) |
|
139 |
|
|
140 |
if source is None: |
|
141 |
source = c_type() |
|
142 |
|
|
143 |
if c_type is dict: |
|
144 |
ret = dict([(k, e_type.FromDict(v)) for k, v in source.items()]) |
|
145 |
elif c_type in _SEQUENCE_TYPES: |
|
146 |
ret = c_type(map(e_type.FromDict, source)) |
|
147 |
else: |
|
148 |
raise TypeError("Unknown container type '%s'" % c_type) |
|
149 |
|
|
150 |
return ret |
b/test/py/ganeti.objectutils_unittest.py | ||
---|---|---|
46 | 46 |
slotted = AutoSlotted() |
47 | 47 |
self.assertEqual(slotted.__slots__, AutoSlotted.SLOTS) |
48 | 48 |
|
49 |
|
|
50 |
class TestContainerToDicts(unittest.TestCase): |
|
51 |
def testUnknownType(self): |
|
52 |
for value in [None, 19410, "xyz"]: |
|
53 |
try: |
|
54 |
objectutils.ContainerToDicts(value) |
|
55 |
except TypeError, err: |
|
56 |
self.assertTrue(str(err).startswith("Unknown container type")) |
|
57 |
else: |
|
58 |
self.fail("Exception was not raised") |
|
59 |
|
|
60 |
def testEmptyDict(self): |
|
61 |
value = {} |
|
62 |
self.assertFalse(type(value) in objectutils._SEQUENCE_TYPES) |
|
63 |
self.assertEqual(objectutils.ContainerToDicts(value), {}) |
|
64 |
|
|
65 |
def testEmptySequences(self): |
|
66 |
for cls in [list, tuple, set, frozenset]: |
|
67 |
self.assertEqual(objectutils.ContainerToDicts(cls()), []) |
|
68 |
|
|
69 |
|
|
70 |
class _FakeWithFromDict: |
|
71 |
def FromDict(self, _): |
|
72 |
raise NotImplemented |
|
73 |
|
|
74 |
|
|
75 |
class TestContainerFromDicts(unittest.TestCase): |
|
76 |
def testUnknownType(self): |
|
77 |
for cls in [str, int, bool]: |
|
78 |
try: |
|
79 |
objectutils.ContainerFromDicts(None, cls, NotImplemented) |
|
80 |
except TypeError, err: |
|
81 |
self.assertTrue(str(err).startswith("Unknown container type")) |
|
82 |
else: |
|
83 |
self.fail("Exception was not raised") |
|
84 |
|
|
85 |
try: |
|
86 |
objectutils.ContainerFromDicts(None, cls(), NotImplemented) |
|
87 |
except TypeError, err: |
|
88 |
self.assertTrue(str(err).endswith("is not a type")) |
|
89 |
else: |
|
90 |
self.fail("Exception was not raised") |
|
91 |
|
|
92 |
def testEmptyDict(self): |
|
93 |
value = {} |
|
94 |
self.assertFalse(type(value) in objectutils._SEQUENCE_TYPES) |
|
95 |
self.assertEqual(objectutils.ContainerFromDicts(value, dict, |
|
96 |
NotImplemented), |
|
97 |
{}) |
|
98 |
|
|
99 |
def testEmptySequences(self): |
|
100 |
for cls in [list, tuple, set, frozenset]: |
|
101 |
self.assertEqual(objectutils.ContainerFromDicts([], cls, |
|
102 |
_FakeWithFromDict), |
|
103 |
cls()) |
|
104 |
|
|
105 |
|
|
49 | 106 |
if __name__ == "__main__": |
50 | 107 |
testutils.GanetiTestProgram() |
Also available in: Unified diff