"""typetools.py - Tools for working with Python type objects """ # Written by Nick Coghlan # Copyright (C) 2008 Python Software Foundation. from operator import (truediv, iadd, iand, idiv, ifloordiv, ilshift, imod, imul, index, ior, ipow, irshift, isub, itruediv, ixor) __all__ = ['ProxyMixin'] # Convenience functions to unwrap proxied objects def _deref(obj): return object.__getattribute__(obj, '_target') def _unwrap(obj): if isinstance(obj, ProxyMixin): return _deref(obj) return obj class ProxyMixin(object): """Mixin class to delegate method calls that bypass __getattribute__ For optimisation purposes, Python implementations are permitted to bypass the standard attribute lookup machinery for some special methods. The precise list of methods which need special treatment will be implementation specific. Inheriting from this base class will ensure that a proxy implementation will correctly delegate all of these special methods as needed.""" # Note that all operations return unwrapped objects # Binary and ternary operations automatically unwrap other ProxyBase instances # This behaviour follows the precedent set by weakref.proxy __slots__ = ['_target', '__weakref__'] def __init__(self, target): object.__setattr__(self, '_target', target) # String representations def __repr__(self): return "<%s for %r>" % (type(self).__name__, _deref(self)) def __str__(self): return str(_deref(self)) def __unicode__(self): return unicode(_deref(self)) # XXX (NGC): weakref.proxy doesn't delegate the next two methods. Why not? def __oct__(self): return oct(_deref(self)) def __hex__(self): return hex(_deref(self)) # Equality and ordering checks def __nonzero__(self): return bool(_deref(self)) def __hash__(self): return hash(_deref(self)) def __lt__(self, other): return _deref(self) < _unwrap(other) def __le__(self, other): return _deref(self) <= _unwrap(other) def __eq__(self, other): return _deref(self) == _unwrap(other) def __ne__(self, other): return _deref(self) != _unwrap(other) def __gt__(self, other): return _deref(self) > _unwrap(other) def __ge__(self, other): return _deref(self) >= _unwrap(other) def __cmp__(self, other): return cmp(_deref(self), _unwrap(other)) # Callables def __call__(self, *args, **kwds): return _deref(self)(*args, **kwds) # Attribute access and manipulation def __getattribute__(self, attr): return getattr(_deref(self), attr) def __setattr__(self, attr, value): setattr(_deref(self), attr, value) def __delattr__(self, attr): delattr(_deref(self), attr) # Descriptors can't be safely proxied, so the associated special methods # __get__, __set__ and __delete__ are not implemented by this class # Container behaviour def __len__(self): return len(_deref(self)) def __getitem__(self, key): return _deref(self)[_unwrap(key)] def __setitem__(self, key, value): _deref(self)[_unwrap(key)] = _unwrap(value) def __delitem__(self, key): del _deref(self)[_unwrap(key)] def __iter__(self): return iter(_deref(self)) def __contains__(self, item): return _unwrap(item) in _deref(self) # Binary arithmetic operations with this instance on the left def __add__(self, other): return _deref(self) + _unwrap(other) def __sub__(self, other): return _deref(self) - _unwrap(other) def __mul__(self, other): return _deref(self) * _unwrap(other) def __div__(self, other): return _deref(self) / _unwrap(other) def __truediv__(self, other): return truediv(_deref(self), _unwrap(other)) def __floordiv__(self, other): return _deref(self) // _unwrap(other) def __mod__(self, other): return _deref(self) % _unwrap(other) def __divmod__(self, other): return divmod(_deref(self), _unwrap(other)) def __pow__(self, other, modulo=None): return pow(_deref(self), _unwrap(other), _unwrap(modulo)) def __lshift__(self, other): return _deref(self) << _unwrap(other) def __rshift__(self, other): return _deref(self) >> _unwrap(other) def __and__(self, other): return _deref(self) & _unwrap(other) def __xor__(self, other): return _deref(self) ^ _unwrap(other) def __or__(self, other): return _deref(self) | _unwrap(other) # Binary arithmetic operations with this instance on the right def __radd__(self, other): return _unwrap(other) + _deref(self) def __rsub__(self, other): return _unwrap(other) - _deref(self) def __rmul__(self, other): return _unwrap(other) * _deref(self) def __rdiv__(self, other): return _unwrap(other) / _deref(self) def __rtruediv__(self, other): return truediv(_unwrap(other), _deref(self)) def __rfloordiv__(self, other): return _unwrap(other) // _deref(self) def __rmod__(self, other): return _unwrap(other) % _deref(self) def __rdivmod__(self, other): return divmod(_unwrap(other), _deref(self)) def __rpow__(self, other): return _unwrap(other) ** _deref(self) def __rlshift__(self, other): return _unwrap(other) << _deref(self) def __rrshift__(self, other): return _unwrap(other) >> _deref(self) def __rand__(self, other): return _unwrap(other) & _deref(self) def __rxor__(self, other): return _unwrap(other) ^ _deref(self) def __ror__(self, other): return _unwrap(other) | _deref(self) # In-place assignment operations def __iadd__(self, other): return iadd(_deref(self), _unwrap(other)) def __isub__(self, other): return isub(_deref(self), _unwrap(other)) def __imul__(self, other): return imul(_deref(self), _unwrap(other)) def __idiv__(self, other): return idiv(_deref(self), _unwrap(other)) def __itruediv__(self, other): return itruediv(_deref(self), _unwrap(other)) def __ifloordiv__(self, other): return ifloordiv(_deref(self), _unwrap(other)) def __imod__(self, other): return imod(_deref(self), _unwrap(other)) def __ipow__(self, other, modulo=None): return ipow(_deref(self), _unwrap(other)) def __ilshift__(self, other): return ilshift(_deref(self), _unwrap(other)) def __irshift__(self, other): return irshift(_deref(self), _unwrap(other)) def __iand__(self, other): return iand(_deref(self), _unwrap(other)) def __ixor__(self, other): return ixor(_deref(self), _unwrap(other)) def __ior__(self, other): return ior(_deref(self), _unwrap(other)) # Unary arithmetic operations def __neg__(self): return -_deref(self) def __pos__(self): return +_deref(self) def __abs__(self): return abs(_deref(self)) def __invert__(self): return ~_deref(self) # Numeric type coercion def __complex__(self): return complex(_deref(self)) def __int__(self): return int(_deref(self)) def __long__(self): return long(_deref(self)) def __float__(self): return float(_deref(self)) def __index__(self): return index(_deref(self))