1from weakref import ref 2 3from blinker._saferef import BoundMethodWeakref 4 5 6try: 7 callable 8except NameError: 9 def callable(object): 10 return hasattr(object, '__call__') 11 12 13try: 14 from collections import defaultdict 15except: 16 class defaultdict(dict): 17 18 def __init__(self, default_factory=None, *a, **kw): 19 if (default_factory is not None and 20 not hasattr(default_factory, '__call__')): 21 raise TypeError('first argument must be callable') 22 dict.__init__(self, *a, **kw) 23 self.default_factory = default_factory 24 25 def __getitem__(self, key): 26 try: 27 return dict.__getitem__(self, key) 28 except KeyError: 29 return self.__missing__(key) 30 31 def __missing__(self, key): 32 if self.default_factory is None: 33 raise KeyError(key) 34 self[key] = value = self.default_factory() 35 return value 36 37 def __reduce__(self): 38 if self.default_factory is None: 39 args = tuple() 40 else: 41 args = self.default_factory, 42 return type(self), args, None, None, self.items() 43 44 def copy(self): 45 return self.__copy__() 46 47 def __copy__(self): 48 return type(self)(self.default_factory, self) 49 50 def __deepcopy__(self, memo): 51 import copy 52 return type(self)(self.default_factory, 53 copy.deepcopy(self.items())) 54 55 def __repr__(self): 56 return 'defaultdict(%s, %s)' % (self.default_factory, 57 dict.__repr__(self)) 58 59 60try: 61 from contextlib import contextmanager 62except ImportError: 63 def contextmanager(fn): 64 def oops(*args, **kw): 65 raise RuntimeError("Python 2.5 or above is required to use " 66 "context managers.") 67 oops.__name__ = fn.__name__ 68 return oops 69 70class _symbol(object): 71 72 def __init__(self, name): 73 """Construct a new named symbol.""" 74 self.__name__ = self.name = name 75 76 def __reduce__(self): 77 return symbol, (self.name,) 78 79 def __repr__(self): 80 return self.name 81_symbol.__name__ = 'symbol' 82 83 84class symbol(object): 85 """A constant symbol. 86 87 >>> symbol('foo') is symbol('foo') 88 True 89 >>> symbol('foo') 90 foo 91 92 A slight refinement of the MAGICCOOKIE=object() pattern. The primary 93 advantage of symbol() is its repr(). They are also singletons. 94 95 Repeated calls of symbol('name') will all return the same instance. 96 97 """ 98 symbols = {} 99 100 def __new__(cls, name): 101 try: 102 return cls.symbols[name] 103 except KeyError: 104 return cls.symbols.setdefault(name, _symbol(name)) 105 106 107try: 108 text = (str, unicode) 109except NameError: 110 text = str 111 112 113def hashable_identity(obj): 114 if hasattr(obj, '__func__'): 115 return (id(obj.__func__), id(obj.__self__)) 116 elif hasattr(obj, 'im_func'): 117 return (id(obj.im_func), id(obj.im_self)) 118 elif isinstance(obj, text): 119 return obj 120 else: 121 return id(obj) 122 123 124WeakTypes = (ref, BoundMethodWeakref) 125 126 127class annotatable_weakref(ref): 128 """A weakref.ref that supports custom instance attributes.""" 129 130 131def reference(object, callback=None, **annotations): 132 """Return an annotated weak ref.""" 133 if callable(object): 134 weak = callable_reference(object, callback) 135 else: 136 weak = annotatable_weakref(object, callback) 137 for key, value in annotations.items(): 138 setattr(weak, key, value) 139 return weak 140 141 142def callable_reference(object, callback=None): 143 """Return an annotated weak ref, supporting bound instance methods.""" 144 if hasattr(object, 'im_self') and object.im_self is not None: 145 return BoundMethodWeakref(target=object, on_delete=callback) 146 elif hasattr(object, '__self__') and object.__self__ is not None: 147 return BoundMethodWeakref(target=object, on_delete=callback) 148 return annotatable_weakref(object, callback) 149 150 151class lazy_property(object): 152 """A @property that is only evaluated once.""" 153 154 def __init__(self, deferred): 155 self._deferred = deferred 156 self.__doc__ = deferred.__doc__ 157 158 def __get__(self, obj, cls): 159 if obj is None: 160 return self 161 value = self._deferred(obj) 162 setattr(obj, self._deferred.__name__, value) 163 return value 164