diff --git a/lib/objects.py b/lib/objects.py index 76ca042c4fc8bb353654db5514707b3aceae0e7a..7fb7d5be6ed872ddb90cb71eccb4497749992d27 100644 --- a/lib/objects.py +++ b/lib/objects.py @@ -109,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. @@ -130,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 diff --git a/lib/opcodes.py b/lib/opcodes.py index 3aed41e0cd75e2bb41958bbfd9b37e8f7fc75da8..2520101dc462ab5ce2aed4fd47b95f8047bcf819 100644 --- a/lib/opcodes.py +++ b/lib/opcodes.py @@ -52,8 +52,9 @@ class BaseOpCode(object): __slots__ attribute for this class. """ + slots = self._all_slots() for key in kwargs: - if key not in self.__slots__: + if key not in slots: raise TypeError("Object %s doesn't support the parameter '%s'" % (self.__class__.__name__, key)) setattr(self, key, kwargs[key]) @@ -69,7 +70,7 @@ class BaseOpCode(object): """ state = {} - for name in self.__slots__: + for name in self._all_slots(): if hasattr(self, name): state[name] = getattr(self, name) return state @@ -88,13 +89,23 @@ class BaseOpCode(object): raise ValueError("Invalid data to __setstate__: expected dict, got %s" % type(state)) - for name in self.__slots__: + for name in self._all_slots(): if name not in state: delattr(self, name) for name in state: 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 + class OpCode(BaseOpCode): """Abstract OpCode. diff --git a/tools/cfgshell b/tools/cfgshell index 57ed0bd7f51a70a4812af8d10cf8e1fbc4b49880..3c53d819b6a7808f85f3b8aed68eb3593b0691fb 100755 --- a/tools/cfgshell +++ b/tools/cfgshell @@ -93,7 +93,9 @@ class ConfigShell(cmd.Cmd): dirs = [] entries = [] if isinstance(obj, objects.ConfigObject): - for name in obj.__slots__: + # pylint: disable-msg=W0212 + # yes, we're using a protected member + for name in obj._all_slots(): child = getattr(obj, name, None) if isinstance(child, (list, dict, tuple, objects.ConfigObject)): dirs.append(name)