4 # Copyright (C) 2012 Google Inc.
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 """Module for object related utils."""
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)
29 class AutoSlots(type):
30 """Meta base class for __slots__ definitions.
33 def __new__(mcs, name, bases, attrs):
34 """Called when a class should be created.
36 @param mcs: The meta class
37 @param name: Name of created class
38 @param bases: Base classes
40 @param attrs: Class attributes
43 assert "__slots__" not in attrs, \
44 "Class '%s' defines __slots__ when it should not" % name
46 attrs["__slots__"] = mcs._GetSlots(attrs)
48 return type.__new__(mcs, name, bases, attrs)
51 def _GetSlots(mcs, attrs):
52 """Used to get the list of defined slots.
54 @param attrs: The attributes of the class
57 raise NotImplementedError
60 class ValidatedSlots(object):
61 """Sets and validates slots.
66 def __init__(self, **kwargs):
67 """Constructor for BaseOpCode.
69 The constructor takes only keyword arguments and will set
70 attributes on this object based on the passed arguments. As such,
71 it means that you should not pass arguments which are not in the
72 __slots__ attribute for this class.
75 slots = self.GetAllSlots()
76 for (key, value) in kwargs.items():
78 raise TypeError("Object %s doesn't support the parameter '%s'" %
79 (self.__class__.__name__, key))
80 setattr(self, key, value)
84 """Compute the list of all declared slots for a class.
88 for parent in cls.__mro__:
89 slots.extend(getattr(parent, "__slots__", []))
93 """Validates the slots.
95 This method must be implemented by the child classes.
98 raise NotImplementedError
101 def ContainerToDicts(container):
102 """Convert the elements of a container to standard Python types.
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.
109 @type container: dict or sequence (see L{_SEQUENCE_TYPES})
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]
117 raise TypeError("Unknown container type '%s'" % type(container))
122 def ContainerFromDicts(source, c_type, e_type):
123 """Convert a container from standard python types.
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.
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)
137 if not isinstance(c_type, type):
138 raise TypeError("Container type '%s' is not a type" % type(c_type))
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))
148 raise TypeError("Unknown container type '%s'" % c_type)