def getslot(o, n): #{{{ slots = ogetattr(o, '__slots__') if isclass(o): raise TypeError("Can only retrieve instance slots") if n not in slots: raise AttributeError("'%s' instance has no slot attribute '%s'" %(o.__class__.__name__, n)) return ogetattr(o, n)
def proxy(obj, ret_proxy=(), wref=False): #{{{ class ObjectProxy(Proxy): __slots__ = () __metaclass__ = MetaProxy class proxyattr(object): proxyobj = obj return_proxy = ret_proxy weakref = wref if not isclass(obj): inst = ObjectProxy() return inst return ObjectProxy
def staticsequence(name, pcls, **options): #{{{ n = options.get('n', 1) h = options.get('hashable', True) assert n >= 1, "cannot create static sequence type with less than 1 element" assert isclass(pcls), "cannot create static sequence from non-class" BaseSeq = proxy(pcls) class StaticSequence(BaseSeq): #{{{ __slots__ = () def __init__(self, *args): #{{{ if not args: raise TypeError("'%s' object cannot be empty" %name) if len(args) == 1 and n > 1: args = args[0] exec compile('args = (%s) = args' %', '.join('v%i' %i for i in xrange(n)), '<string>', 'exec') in locals() super(StaticSequence, self).__init__(args) if h: hash(self) # Throw error if not hashable # End def #}}} def __repr__(self): #{{{ return ' '.join([name, str(self)]) # End def #}}} def __setattr__(self, n, val): #{{{ raise AttributeError("'%s' object cannot set attribute '%s'" %(name, n)) # End def #}}} def __delattr__(self, n): #{{{ raise AttributeError("'%s' object cannot delete attribute '%s'" %(name, n)) # End def #}}} def __eq__(self, obj): #{{{ if not isinstance(obj, self.__class__): try: obj = self.__class__(obj) except TypeError: return False return super(StaticSequence, self).__eq__(obj) # End def #}}} def __ne__(self, obj): #{{{ return not self.__eq__(obj) # End def #}}} # End class #}}} StaticSequence.__name__ = name return StaticSequence
def __iter__(self): #{{{ obj = self._obj def get_clsnames(obj): #{{{ for cls in reversed(mro(obj)): for k, v in cls.__dict__.iteritems(): yield k if k == '__slots__': for k in v: yield k # End def #}}} is_cls = isclass(obj) cls = obj if is_cls else obj.__class__ names = set(k for k in get_clsnames(cls)) if not is_cls: try: slots = getattr(cls, '__slots__') except AttributeError: names.update(getattr(obj, '__dict__', {}).iterkeys()) return (n for n in names if hasattr(obj, n))
def __new__(cls, classname, bases, clsdict): #{{{ if not isbasemetaclass(bases, cls): return super(MetaProxy, cls).__new__(cls, classname, bases, clsdict) proxyattr = clsdict.pop('proxyattr') curobj = proxyattr.proxyobj retproxy = proxyattr.return_proxy if not isinstance(retproxy, tuple): retproxy = tuple(retproxy) can_weakref = proxyattr.weakref clsproxy = isclass(curobj) proxyinst = None if clsproxy: proxyinst = {} # Set setattr temp_attr = {} def __setattr__(self, name, val): #{{{ try: obj = _ga(self, '__proxyinst__') except KeyError: obj = curobj if clsproxy and obj is curobj: sid = id(self) vars = temp_attr.setdefault(sid, {}) vars[name] = val else: try: setattr(obj, name, val) except AttributeError: _sa(self, name, val) # End def #}}} def __delattr__(self, name): #{{{ try: obj = _ga(self, '__proxyinst__') except KeyError: obj = curobj if clsproxy and obj is curobj: sid = id(self) vars = temp_attr.setdefault(sid, {}) try: vars.pop(name) except KeyError: raise AttributeError() else: try: delattr(obj, name) except AttributeError: if name in dir(self): _da(self, name) else: raise # End def #}}} clsdict['__setattr__'] = __setattr__ clsdict['__delattr__'] = __delattr__ instblock = ('__new__', '__init__', '__getattribute__', '__setattr__', '__delattr__') instblock_retproxy = instblock + retproxy block = ('__class__', '__slots__', '__proxyinst__') + instblock # Set getattribute def __getattribute__(self, name): #{{{ sid = id(self) if proxyinst is None: obj = curobj else: obj = proxyinst.get(sid, curobj) # obj = _ga(self, '__proxyinst__') if clsproxy: if obj is curobj: vars = temp_attr.setdefault(sid, {}) if name in vars: return vars[name] if name == '__class__' and not clsproxy: return _ga(obj, name) try: ret = _ga(self, name) except AttributeError: ret = _ga(obj, name) return ret # End def #}}} clsdict['__getattribute__'] = __getattribute__ clsdict['__proxyinst__'] = property(lambda s: curobj) if clsproxy: # proxyinst = {} def __init__(self, *args, **kwargs): #{{{ sid = id(self) proxyinst[sid] = inst = curobj(*args, **kwargs) vars = temp_attr.setdefault(sid, {}) pi = vars.popitem while vars: setattr(self, *pi()) temp_attr.pop(sid) # End def #}}} clsdict['__init__'] = __init__ clsdict['__proxyinst__'] = property(lambda s: proxyinst[id(s)]) if can_weakref: objslots = getattr(curobj, '__slots__', None) curslots = clsdict['__slots__'] if not isbuiltin(curobj) and (objslots is None or '__weakref__' in objslots): clsdict['__slots__'] += curslots + ('__weakref__',) attrblock = block if clsproxy else instblock for n in dir(curobj): if n in attrblock: continue attr = getattr(curobj, n) if iscallable(attr) and not isclass(attr): res = None if isclassmethod(attr): res = _mkproxycallable(attr, n, clsproxy, retproxy, classmethod) elif isfunction(attr): res = _mkproxycallable(attr,n, clsproxy, retproxy, staticmethod) else: res = _mkproxycallable(attr, n, clsproxy, retproxy, usewraps=False) clsdict[n] = res else: clsdict[n] = attr if clsproxy: classname = curobj.__name__ return super(MetaProxy, cls).__new__(cls, classname, bases, clsdict)