_utilities.py 4.4 KB

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