X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/d984846ddf447c4eab67bd112cb5a52456f3fd3b..6bb65e3a3d84fb9ea3daeae596bbc9463edda8b8:/lib/objects.py diff --git a/lib/objects.py b/lib/objects.py index e7eb537..7fb7d5b 100644 --- a/lib/objects.py +++ b/lib/objects.py @@ -26,11 +26,12 @@ pass to and from external parties. """ -# pylint: disable-msg=E0203 +# pylint: disable-msg=E0203,W0201 # E0203: Access to member %r before its definition, since we use # objects.py which doesn't explicitely initialise its members +# W0201: Attribute '%s' defined outside __init__ import ConfigParser import re @@ -47,7 +48,7 @@ __all__ = ["ConfigObject", "ConfigData", "NIC", "Disk", "Instance", _TIMESTAMPS = ["ctime", "mtime"] _UUID = ["uuid"] -def FillDict(defaults_dict, custom_dict, skip_keys=[]): +def FillDict(defaults_dict, custom_dict, skip_keys=None): """Basic function to apply settings on top a default dict. @type defaults_dict: dict @@ -62,11 +63,12 @@ def FillDict(defaults_dict, custom_dict, skip_keys=[]): """ ret_dict = copy.deepcopy(defaults_dict) ret_dict.update(custom_dict) - for k in skip_keys: - try: - del ret_dict[k] - except KeyError: - pass + if skip_keys: + for k in skip_keys: + try: + del ret_dict[k] + except KeyError: + pass return ret_dict @@ -107,16 +109,27 @@ class ConfigObject(object): setattr(self, k, v) def __getattr__(self, name): - if name not in self.__slots__: + if name not in self._all_slots(): raise AttributeError("Invalid object attribute %s.%s" % (type(self).__name__, name)) return None def __setstate__(self, state): + slots = self._all_slots() for name in state: - if name in self.__slots__: + if name in slots: setattr(self, name, state[name]) + @classmethod + def _all_slots(cls): + """Compute the list of all declared slots for a class. + + """ + slots = [] + for parent in cls.__mro__: + slots.extend(getattr(parent, "__slots__", [])) + return slots + def ToDict(self): """Convert to a dict holding only standard python types. @@ -128,7 +141,7 @@ class ConfigObject(object): """ result = {} - for name in self.__slots__: + for name in self._all_slots(): value = getattr(self, name, None) if value is not None: result[name] = value @@ -153,7 +166,7 @@ class ConfigObject(object): raise errors.ConfigurationError("Invalid object passed to FromDict:" " expected dict, got %s" % type(val)) val_str = dict([(str(k), v) for k, v in val.iteritems()]) - obj = cls(**val_str) + obj = cls(**val_str) # pylint: disable-msg=W0142 return obj @staticmethod @@ -221,7 +234,7 @@ class TaggableObject(ConfigObject): """An generic class supporting tags. """ - __slots__ = ConfigObject.__slots__ + ["tags"] + __slots__ = ["tags"] VALID_TAG_RE = re.compile("^[\w.+*/:@-]+$") @classmethod @@ -633,7 +646,7 @@ class Disk(ConfigObject): class Instance(TaggableObject): """Config object representing an instance.""" - __slots__ = TaggableObject.__slots__ + [ + __slots__ = [ "name", "primary_node", "os", @@ -745,7 +758,7 @@ class Instance(TaggableObject): try: idx = int(idx) return self.disks[idx] - except ValueError, err: + except (TypeError, ValueError), err: raise errors.OpPrereqError("Invalid disk index: '%s'" % str(err), errors.ECODE_INVAL) except IndexError: @@ -813,7 +826,7 @@ class OS(ConfigObject): class Node(TaggableObject): """Config object representing a node.""" - __slots__ = TaggableObject.__slots__ + [ + __slots__ = [ "name", "primary_ip", "secondary_ip", @@ -826,7 +839,7 @@ class Node(TaggableObject): class Cluster(TaggableObject): """Config object representing the cluster.""" - __slots__ = TaggableObject.__slots__ + [ + __slots__ = [ "serial_no", "rsahostkeypub", "highest_used_port",