/usr/share/pyshared/axiom/slotmachine.py is in python-axiom 0.6.0-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | # -*- test-case-name: axiom.test.test_slotmachine -*-
hyper = super
_NOSLOT = object()
class Allowed(object):
"""
An attribute that's allowed to be set.
"""
def __init__(self, name, default=_NOSLOT):
self.name = name
self.default = default
def __get__(self, oself, otype=None):
if otype is not None and oself is None:
return self
if self.name in oself.__dict__:
return oself.__dict__[self.name]
if self.default is not _NOSLOT:
return self.default
raise AttributeError("%r object did not have attribute %r" %(oself.__class__.__name__, self.name))
def __delete__(self, oself):
if self.name not in oself.__dict__:
# Returning rather than raising here because that's what
# member_descriptor does, and Axiom relies upon that behavior.
## raise AttributeError('%r object has no attribute %r' %
## (oself.__class__.__name__, self.name))
return
del oself.__dict__[self.name]
def __set__(self, oself, value):
oself.__dict__[self.name] = value
class _SlotMetaMachine(type):
def __new__(meta, name, bases, dictionary):
dictionary['__name__'] = name
slots = list(meta.determineSchema(dictionary))
for slot in slots:
for base in bases:
defval = getattr(base, slot, _NOSLOT)
if defval is not _NOSLOT:
break
dictionary[slot] = Allowed(slot, defval)
nt = type.__new__(meta, name, bases, dictionary)
return nt
def determineSchema(meta, dictionary):
return dictionary.get("slots", [])
determineSchema = classmethod(determineSchema)
class DescriptorWithDefault(object):
def __init__(self, default, original):
self.original = original
self.default = default
def __get__(self, oself, type=None):
if type is not None:
if oself is None:
return self.default
return getattr(oself, self.original, self.default)
def __set__(self, oself, value):
setattr(oself, self.original, value)
def __delete__(self, oself):
delattr(oself, self.original)
class Attribute(object):
def __init__(self, doc=''):
self.doc = doc
def requiredSlots(self, modname, classname, attrname):
self.name = attrname
yield attrname
def __get__(self, oself, type=None):
assert oself is None, "%s: should be masked" % (self.name,)
return self
_RAISE = object()
class SetOnce(Attribute):
def __init__(self, doc='', default=_RAISE):
Attribute.__init__(self)
if default is _RAISE:
self.default = ()
else:
self.default = (default,)
def requiredSlots(self, modname, classname, attrname):
self.name = attrname
t = self.trueattr = ('_' + self.name)
yield t
def __set__(self, iself, value):
if not hasattr(iself, self.trueattr):
setattr(iself, self.trueattr, value)
else:
raise AttributeError('%s.%s may only be set once' % (
type(iself).__name__, self.name))
def __get__(self, iself, type=None):
if type is not None and iself is None:
return self
return getattr(iself, self.trueattr, *self.default)
class SchemaMetaMachine(_SlotMetaMachine):
def determineSchema(meta, dictionary):
attrs = dictionary['__attributes__'] = []
name = dictionary['__name__']
moduleName = dictionary['__module__']
dictitems = dictionary.items()
dictitems.sort()
for k, v in dictitems:
if isinstance(v, Attribute):
attrs.append((k, v))
for slot in v.requiredSlots(moduleName, name, k):
if slot == k:
del dictionary[k]
yield slot
determineSchema = classmethod(determineSchema)
class _Strict(object):
"""
I disallow all attributes from being set that do not have an explicit
data descriptor.
"""
def __setattr__(self, name, value):
"""
Like PyObject_GenericSetAttr, but call descriptors only.
"""
try:
allowed = type(self).__dict__['_Strict__setattr__allowed']
except KeyError:
allowed = type(self)._Strict__setattr__allowed = {}
for cls in type(self).__mro__:
for attrName, slot in cls.__dict__.iteritems():
if attrName in allowed:
# It was found earlier in the mro, overriding
# whatever this is. Ignore it and move on.
continue
setter = getattr(slot, '__set__', _NOSLOT)
if setter is not _NOSLOT:
# It is a data descriptor, so remember the setter
# for it in the cache.
allowed[attrName] = setter
else:
# It is something else, so remember None for it in
# the cache to indicate it cannot have its value
# set.
allowed[attrName] = None
try:
setter = allowed[name]
except KeyError:
pass
else:
if setter is not None:
setter(self, value)
return
# It wasn't found in the setter cache or it was found to be None,
# indicating a non-data descriptor which cannot be set.
raise AttributeError(
"%r can't set attribute %r" % (self.__class__.__name__, name))
class SchemaMachine(_Strict):
__metaclass__ = SchemaMetaMachine
class SlotMachine(_Strict):
__metaclass__ = _SlotMetaMachine
|