/usr/share/pyshared/sqlobject/declarative.py is in python-sqlobject 0.12.4-2.
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 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | """
Declarative objects.
Declarative objects have a simple protocol: you can use classes in
lieu of instances and they are equivalent, and any keyword arguments
you give to the constructor will override those instance variables.
(So if a class is received, we'll simply instantiate an instance with
no arguments).
You can provide a variable __unpackargs__ (a list of strings), and if
the constructor is called with non-keyword arguments they will be
interpreted as the given keyword arguments.
If __unpackargs__ is ('*', name), then all the arguments will be put
in a variable by that name.
You can define a __classinit__(cls, new_attrs) method, which will be
called when the class is created (including subclasses). Note: you
can't use super() in __classinit__ because the class isn't bound to a
name. As an analog to __classinit__, Declarative adds
__instanceinit__ which is called with the same argument (new_attrs).
This is like __init__, but after __unpackargs__ and other factors have
been taken into account.
If __mutableattributes__ is defined as a sequence of strings, these
attributes will not be shared between superclasses and their
subclasses. E.g., if you have a class variable that contains a list
and you append to that list, changes to subclasses will effect
superclasses unless you add the attribute here.
Also defines classinstancemethod, which acts as either a class method
or an instance method depending on where it is called.
"""
import copy
import events
import itertools
counter = itertools.count()
__all__ = ('classinstancemethod', 'DeclarativeMeta', 'Declarative')
class classinstancemethod(object):
"""
Acts like a class method when called from a class, like an
instance method when called by an instance. The method should
take two arguments, 'self' and 'cls'; one of these will be None
depending on how the method was called.
"""
def __init__(self, func):
self.func = func
def __get__(self, obj, type=None):
return _methodwrapper(self.func, obj=obj, type=type)
class _methodwrapper(object):
def __init__(self, func, obj, type):
self.func = func
self.obj = obj
self.type = type
def __call__(self, *args, **kw):
assert not kw.has_key('self') and not kw.has_key('cls'), (
"You cannot use 'self' or 'cls' arguments to a "
"classinstancemethod")
return self.func(*((self.obj, self.type) + args), **kw)
def __repr__(self):
if self.obj is None:
return ('<bound class method %s.%s>'
% (self.type.__name__, self.func.func_name))
else:
return ('<bound method %s.%s of %r>'
% (self.type.__name__, self.func.func_name, self.obj))
class DeclarativeMeta(type):
def __new__(meta, class_name, bases, new_attrs):
post_funcs = []
early_funcs = []
events.send(events.ClassCreateSignal,
bases[0], class_name, bases, new_attrs,
post_funcs, early_funcs)
cls = type.__new__(meta, class_name, bases, new_attrs)
for func in early_funcs:
func(cls)
if new_attrs.has_key('__classinit__'):
cls.__classinit__ = staticmethod(cls.__classinit__.im_func)
cls.__classinit__(cls, new_attrs)
for func in post_funcs:
func(cls)
return cls
class Declarative(object):
__unpackargs__ = ()
__mutableattributes__ = ()
__metaclass__ = DeclarativeMeta
__restrict_attributes__ = None
def __classinit__(cls, new_attrs):
cls.declarative_count = counter.next()
for name in cls.__mutableattributes__:
if not new_attrs.has_key(name):
setattr(cls, copy.copy(getattr(cls, name)))
def __instanceinit__(self, new_attrs):
if self.__restrict_attributes__ is not None:
for name in new_attrs:
if name not in self.__restrict_attributes__:
raise TypeError(
'%s() got an unexpected keyword argument %r'
% (self.__class__.__name__, name))
for name, value in new_attrs.items():
setattr(self, name, value)
if not new_attrs.has_key('declarative_count'):
self.declarative_count = counter.next()
def __init__(self, *args, **kw):
if self.__unpackargs__ and self.__unpackargs__[0] == '*':
assert len(self.__unpackargs__) == 2, \
"When using __unpackargs__ = ('*', varname), you must only provide a single variable name (you gave %r)" % self.__unpackargs__
name = self.__unpackargs__[1]
if kw.has_key(name):
raise TypeError(
"keyword parameter '%s' was given by position and name"
% name)
kw[name] = args
else:
if len(args) > len(self.__unpackargs__):
raise TypeError(
'%s() takes at most %i arguments (%i given)'
% (self.__class__.__name__,
len(self.__unpackargs__),
len(args)))
for name, arg in zip(self.__unpackargs__, args):
if kw.has_key(name):
raise TypeError(
"keyword parameter '%s' was given by position and name"
% name)
kw[name] = arg
if kw.has_key('__alsocopy'):
for name, value in kw['__alsocopy'].items():
if not kw.has_key(name):
if name in self.__mutableattributes__:
value = copy.copy(value)
kw[name] = value
del kw['__alsocopy']
self.__instanceinit__(kw)
def __call__(self, *args, **kw):
kw['__alsocopy'] = self.__dict__
return self.__class__(*args, **kw)
def singleton(self, cls):
if self:
return self
name = '_%s__singleton' % cls.__name__
if not hasattr(cls, name):
setattr(cls, name, cls(declarative_count=cls.declarative_count))
return getattr(cls, name)
singleton = classinstancemethod(singleton)
def __repr__(self, cls):
if self:
name = '%s object' % self.__class__.__name__
v = self.__dict__.copy()
else:
name = '%s class' % cls.__name__
v = cls.__dict__.copy()
if v.has_key('declarative_count'):
name = '%s %i' % (name, v['declarative_count'])
del v['declarative_count']
# @@: simplifying repr:
#v = {}
names = v.keys()
args = []
for n in self._repr_vars(names):
args.append('%s=%r' % (n, v[n]))
if not args:
return '<%s>' % name
else:
return '<%s %s>' % (name, ' '.join(args))
def _repr_vars(dictNames):
names = [n for n in dictNames
if not n.startswith('_')
and n != 'declarative_count']
names.sort()
return names
_repr_vars = staticmethod(_repr_vars)
__repr__ = classinstancemethod(__repr__)
def setup_attributes(cls, new_attrs):
for name, value in new_attrs.items():
if hasattr(value, '__addtoclass__'):
value.__addtoclass__(cls, name)
|