obj = cls(**val_str) # pylint: disable=W0142
return obj
- @staticmethod
- def _ContainerToDicts(container):
- """Convert the elements of a container to standard python types.
-
- This method converts a container with elements derived from
- ConfigData to standard python types. If the container is a dict,
- we don't touch the keys, only the values.
-
- """
- if isinstance(container, dict):
- ret = dict([(k, v.ToDict()) for k, v in container.iteritems()])
- elif isinstance(container, (list, tuple, set, frozenset)):
- ret = [elem.ToDict() for elem in container]
- else:
- raise TypeError("Invalid type %s passed to _ContainerToDicts" %
- type(container))
- return ret
-
- @staticmethod
- def _ContainerFromDicts(source, c_type, e_type):
- """Convert a container from standard python types.
-
- This method converts a container with standard python types to
- ConfigData objects. If the container is a dict, we don't touch the
- keys, only the values.
-
- """
- if not isinstance(c_type, type):
- raise TypeError("Container type %s passed to _ContainerFromDicts is"
- " not a type" % type(c_type))
- if source is None:
- source = c_type()
- if c_type is dict:
- ret = dict([(k, e_type.FromDict(v)) for k, v in source.iteritems()])
- elif c_type in (list, tuple, set, frozenset):
- ret = c_type([e_type.FromDict(elem) for elem in source])
- else:
- raise TypeError("Invalid container type %s passed to"
- " _ContainerFromDicts" % c_type)
- return ret
-
def Copy(self):
"""Makes a deep copy of the current object and its children.
mydict = super(ConfigData, self).ToDict()
mydict["cluster"] = mydict["cluster"].ToDict()
for key in "nodes", "instances", "nodegroups", "networks":
- mydict[key] = self._ContainerToDicts(mydict[key])
+ mydict[key] = objectutils.ContainerToDicts(mydict[key])
return mydict
"""
obj = super(ConfigData, cls).FromDict(val)
obj.cluster = Cluster.FromDict(obj.cluster)
- obj.nodes = cls._ContainerFromDicts(obj.nodes, dict, Node)
- obj.instances = cls._ContainerFromDicts(obj.instances, dict, Instance)
- obj.nodegroups = cls._ContainerFromDicts(obj.nodegroups, dict, NodeGroup)
- obj.networks = cls._ContainerFromDicts(obj.networks, dict, Network)
+ obj.nodes = objectutils.ContainerFromDicts(obj.nodes, dict, Node)
+ obj.instances = \
+ objectutils.ContainerFromDicts(obj.instances, dict, Instance)
+ obj.nodegroups = \
+ objectutils.ContainerFromDicts(obj.nodegroups, dict, NodeGroup)
+ obj.networks = objectutils.ContainerFromDicts(obj.networks, dict, Network)
return obj
def HasAnyDiskOfType(self, dev_type):
for attr in ("children",):
alist = bo.get(attr, None)
if alist:
- bo[attr] = self._ContainerToDicts(alist)
+ bo[attr] = objectutils.ContainerToDicts(alist)
return bo
@classmethod
"""
obj = super(Disk, cls).FromDict(val)
if obj.children:
- obj.children = cls._ContainerFromDicts(obj.children, list, Disk)
+ obj.children = objectutils.ContainerFromDicts(obj.children, list, Disk)
if obj.logical_id and isinstance(obj.logical_id, list):
obj.logical_id = tuple(obj.logical_id)
if obj.physical_id and isinstance(obj.physical_id, list):
for attr in "nics", "disks":
alist = bo.get(attr, None)
if alist:
- nlist = self._ContainerToDicts(alist)
+ nlist = objectutils.ContainerToDicts(alist)
else:
nlist = []
bo[attr] = nlist
if "admin_up" in val:
del val["admin_up"]
obj = super(Instance, cls).FromDict(val)
- obj.nics = cls._ContainerFromDicts(obj.nics, list, NIC)
- obj.disks = cls._ContainerFromDicts(obj.disks, list, Disk)
+ obj.nics = objectutils.ContainerFromDicts(obj.nics, list, NIC)
+ obj.disks = objectutils.ContainerFromDicts(obj.disks, list, Disk)
return obj
def UpgradeConfig(self):
hv_state = data.get("hv_state", None)
if hv_state is not None:
- data["hv_state"] = self._ContainerToDicts(hv_state)
+ data["hv_state"] = objectutils.ContainerToDicts(hv_state)
disk_state = data.get("disk_state", None)
if disk_state is not None:
data["disk_state"] = \
- dict((key, self._ContainerToDicts(value))
+ dict((key, objectutils.ContainerToDicts(value))
for (key, value) in disk_state.items())
return data
obj = super(Node, cls).FromDict(val)
if obj.hv_state is not None:
- obj.hv_state = cls._ContainerFromDicts(obj.hv_state, dict, NodeHvState)
+ obj.hv_state = \
+ objectutils.ContainerFromDicts(obj.hv_state, dict, NodeHvState)
if obj.disk_state is not None:
obj.disk_state = \
- dict((key, cls._ContainerFromDicts(value, dict, NodeDiskState))
+ dict((key, objectutils.ContainerFromDicts(value, dict, NodeDiskState))
for (key, value) in obj.disk_state.items())
return obj
"""
mydict = super(_QueryResponseBase, self).ToDict()
- mydict["fields"] = self._ContainerToDicts(mydict["fields"])
+ mydict["fields"] = objectutils.ContainerToDicts(mydict["fields"])
return mydict
@classmethod
"""
obj = super(_QueryResponseBase, cls).FromDict(val)
- obj.fields = cls._ContainerFromDicts(obj.fields, list, QueryFieldDefinition)
+ obj.fields = \
+ objectutils.ContainerFromDicts(obj.fields, list, QueryFieldDefinition)
return obj
"""Module for object related utils."""
+#: Supported container types for serialization/de-serialization (must be a
+#: tuple as it's used as a parameter for C{isinstance})
+_SEQUENCE_TYPES = (list, tuple, set, frozenset)
+
+
class AutoSlots(type):
"""Meta base class for __slots__ definitions.
"""
raise NotImplementedError
+
+
+def ContainerToDicts(container):
+ """Convert the elements of a container to standard Python types.
+
+ This method converts a container with elements to standard Python types. If
+ the input container is of the type C{dict}, only its values are touched.
+ Those values, as well as all elements of input sequences, must support a
+ C{ToDict} method returning a serialized version.
+
+ @type container: dict or sequence (see L{_SEQUENCE_TYPES})
+
+ """
+ if isinstance(container, dict):
+ ret = dict([(k, v.ToDict()) for k, v in container.items()])
+ elif isinstance(container, _SEQUENCE_TYPES):
+ ret = [elem.ToDict() for elem in container]
+ else:
+ raise TypeError("Unknown container type '%s'" % type(container))
+
+ return ret
+
+
+def ContainerFromDicts(source, c_type, e_type):
+ """Convert a container from standard python types.
+
+ This method converts a container with standard Python types to objects. If
+ the container is a dict, we don't touch the keys, only the values.
+
+ @type source: None, dict or sequence (see L{_SEQUENCE_TYPES})
+ @param source: Input data
+ @type c_type: type class
+ @param c_type: Desired type for returned container
+ @type e_type: element type class
+ @param e_type: Item type for elements in returned container (must have a
+ C{FromDict} class method)
+
+ """
+ if not isinstance(c_type, type):
+ raise TypeError("Container type '%s' is not a type" % type(c_type))
+
+ if source is None:
+ source = c_type()
+
+ if c_type is dict:
+ ret = dict([(k, e_type.FromDict(v)) for k, v in source.items()])
+ elif c_type in _SEQUENCE_TYPES:
+ ret = c_type(map(e_type.FromDict, source))
+ else:
+ raise TypeError("Unknown container type '%s'" % c_type)
+
+ return ret
slotted = AutoSlotted()
self.assertEqual(slotted.__slots__, AutoSlotted.SLOTS)
+
+class TestContainerToDicts(unittest.TestCase):
+ def testUnknownType(self):
+ for value in [None, 19410, "xyz"]:
+ try:
+ objectutils.ContainerToDicts(value)
+ except TypeError, err:
+ self.assertTrue(str(err).startswith("Unknown container type"))
+ else:
+ self.fail("Exception was not raised")
+
+ def testEmptyDict(self):
+ value = {}
+ self.assertFalse(type(value) in objectutils._SEQUENCE_TYPES)
+ self.assertEqual(objectutils.ContainerToDicts(value), {})
+
+ def testEmptySequences(self):
+ for cls in [list, tuple, set, frozenset]:
+ self.assertEqual(objectutils.ContainerToDicts(cls()), [])
+
+
+class _FakeWithFromDict:
+ def FromDict(self, _):
+ raise NotImplemented
+
+
+class TestContainerFromDicts(unittest.TestCase):
+ def testUnknownType(self):
+ for cls in [str, int, bool]:
+ try:
+ objectutils.ContainerFromDicts(None, cls, NotImplemented)
+ except TypeError, err:
+ self.assertTrue(str(err).startswith("Unknown container type"))
+ else:
+ self.fail("Exception was not raised")
+
+ try:
+ objectutils.ContainerFromDicts(None, cls(), NotImplemented)
+ except TypeError, err:
+ self.assertTrue(str(err).endswith("is not a type"))
+ else:
+ self.fail("Exception was not raised")
+
+ def testEmptyDict(self):
+ value = {}
+ self.assertFalse(type(value) in objectutils._SEQUENCE_TYPES)
+ self.assertEqual(objectutils.ContainerFromDicts(value, dict,
+ NotImplemented),
+ {})
+
+ def testEmptySequences(self):
+ for cls in [list, tuple, set, frozenset]:
+ self.assertEqual(objectutils.ContainerFromDicts([], cls,
+ _FakeWithFromDict),
+ cls())
+
+
if __name__ == "__main__":
testutils.GanetiTestProgram()