gooderp18绿色标准版
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

271 lines
10KB

  1. # Part of Odoo. See LICENSE file for full copyright and licensing details.
  2. from __future__ import annotations
  3. import typing
  4. from inspect import Parameter, getsourcefile, signature
  5. from decorator import decorator
  6. __all__ = [
  7. 'classproperty',
  8. 'conditional',
  9. 'lazy',
  10. 'lazy_classproperty',
  11. 'lazy_property',
  12. 'synchronized',
  13. ]
  14. T = typing.TypeVar("T")
  15. if typing.TYPE_CHECKING:
  16. from collections.abc import Callable
  17. class lazy_property(typing.Generic[T]):
  18. """ Decorator for a lazy property of an object, i.e., an object attribute
  19. that is determined by the result of a method call evaluated once. To
  20. reevaluate the property, simply delete the attribute on the object, and
  21. get it again.
  22. """
  23. def __init__(self, fget: Callable[[typing.Any], T]):
  24. assert not fget.__name__.startswith('__'),\
  25. "lazy_property does not support mangled names"
  26. self.fget = fget
  27. @typing.overload
  28. def __get__(self, obj: None, cls: typing.Any, /) -> typing.Any: ...
  29. @typing.overload
  30. def __get__(self, obj: object, cls: typing.Any, /) -> T: ...
  31. def __get__(self, obj, cls, /):
  32. if obj is None:
  33. return self
  34. value = self.fget(obj)
  35. setattr(obj, self.fget.__name__, value)
  36. return value
  37. @property
  38. def __doc__(self):
  39. return self.fget.__doc__
  40. @staticmethod
  41. def reset_all(obj) -> None:
  42. """ Reset all lazy properties on the instance `obj`. """
  43. cls = type(obj)
  44. obj_dict = vars(obj)
  45. for name in list(obj_dict):
  46. if isinstance(getattr(cls, name, None), lazy_property):
  47. obj_dict.pop(name)
  48. def conditional(condition, decorator):
  49. """ Decorator for a conditionally applied decorator.
  50. Example::
  51. @conditional(get_config('use_cache'), ormcache)
  52. def fn():
  53. pass
  54. """
  55. if condition:
  56. return decorator
  57. else:
  58. return lambda fn: fn
  59. def filter_kwargs(func: Callable, kwargs: dict[str, typing.Any]) -> dict[str, typing.Any]:
  60. """ Filter the given keyword arguments to only return the kwargs
  61. that binds to the function's signature.
  62. """
  63. leftovers = set(kwargs)
  64. for p in signature(func).parameters.values():
  65. if p.kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY):
  66. leftovers.discard(p.name)
  67. elif p.kind == Parameter.VAR_KEYWORD: # **kwargs
  68. leftovers.clear()
  69. break
  70. if not leftovers:
  71. return kwargs
  72. return {key: kwargs[key] for key in kwargs if key not in leftovers}
  73. def synchronized(lock_attr: str = '_lock'):
  74. @decorator
  75. def locked(func, inst, *args, **kwargs):
  76. with getattr(inst, lock_attr):
  77. return func(inst, *args, **kwargs)
  78. return locked
  79. locked = synchronized()
  80. def frame_codeinfo(fframe, back=0):
  81. """ Return a (filename, line) pair for a previous frame .
  82. @return (filename, lineno) where lineno is either int or string==''
  83. """
  84. try:
  85. if not fframe:
  86. return "<unknown>", ''
  87. for i in range(back):
  88. fframe = fframe.f_back
  89. try:
  90. fname = getsourcefile(fframe)
  91. except TypeError:
  92. fname = '<builtin>'
  93. lineno = fframe.f_lineno or ''
  94. return fname, lineno
  95. except Exception:
  96. return "<unknown>", ''
  97. class classproperty(typing.Generic[T]):
  98. def __init__(self, fget: Callable[[typing.Any], T]) -> None:
  99. self.fget = classmethod(fget)
  100. def __get__(self, cls, owner: type | None = None, /) -> T:
  101. return self.fget.__get__(None, owner)()
  102. @property
  103. def __doc__(self):
  104. return self.fget.__doc__
  105. class lazy_classproperty(classproperty[T], typing.Generic[T]):
  106. """ Similar to :class:`lazy_property`, but for classes. """
  107. def __get__(self, cls, owner: type | None = None, /) -> T:
  108. val = super().__get__(cls, owner)
  109. setattr(owner, self.fget.__name__, val)
  110. return val
  111. class lazy(object):
  112. """ A proxy to the (memoized) result of a lazy evaluation:
  113. .. code-block::
  114. foo = lazy(func, arg) # func(arg) is not called yet
  115. bar = foo + 1 # eval func(arg) and add 1
  116. baz = foo + 2 # use result of func(arg) and add 2
  117. """
  118. __slots__ = ['_func', '_args', '_kwargs', '_cached_value']
  119. def __init__(self, func, *args, **kwargs):
  120. # bypass own __setattr__
  121. object.__setattr__(self, '_func', func)
  122. object.__setattr__(self, '_args', args)
  123. object.__setattr__(self, '_kwargs', kwargs)
  124. @property
  125. def _value(self):
  126. if self._func is not None:
  127. value = self._func(*self._args, **self._kwargs)
  128. object.__setattr__(self, '_func', None)
  129. object.__setattr__(self, '_args', None)
  130. object.__setattr__(self, '_kwargs', None)
  131. object.__setattr__(self, '_cached_value', value)
  132. return self._cached_value
  133. def __getattr__(self, name): return getattr(self._value, name)
  134. def __setattr__(self, name, value): return setattr(self._value, name, value)
  135. def __delattr__(self, name): return delattr(self._value, name)
  136. def __repr__(self):
  137. return repr(self._value) if self._func is None else object.__repr__(self)
  138. def __str__(self): return str(self._value)
  139. def __bytes__(self): return bytes(self._value)
  140. def __format__(self, format_spec): return format(self._value, format_spec)
  141. def __lt__(self, other): return other > self._value
  142. def __le__(self, other): return other >= self._value
  143. def __eq__(self, other): return other == self._value
  144. def __ne__(self, other): return other != self._value
  145. def __gt__(self, other): return other < self._value
  146. def __ge__(self, other): return other <= self._value
  147. def __hash__(self): return hash(self._value)
  148. def __bool__(self): return bool(self._value)
  149. def __call__(self, *args, **kwargs): return self._value(*args, **kwargs)
  150. def __len__(self): return len(self._value)
  151. def __getitem__(self, key): return self._value[key]
  152. def __missing__(self, key): return self._value.__missing__(key)
  153. def __setitem__(self, key, value): self._value[key] = value
  154. def __delitem__(self, key): del self._value[key]
  155. def __iter__(self): return iter(self._value)
  156. def __reversed__(self): return reversed(self._value)
  157. def __contains__(self, key): return key in self._value
  158. def __add__(self, other): return self._value.__add__(other)
  159. def __sub__(self, other): return self._value.__sub__(other)
  160. def __mul__(self, other): return self._value.__mul__(other)
  161. def __matmul__(self, other): return self._value.__matmul__(other)
  162. def __truediv__(self, other): return self._value.__truediv__(other)
  163. def __floordiv__(self, other): return self._value.__floordiv__(other)
  164. def __mod__(self, other): return self._value.__mod__(other)
  165. def __divmod__(self, other): return self._value.__divmod__(other)
  166. def __pow__(self, other): return self._value.__pow__(other)
  167. def __lshift__(self, other): return self._value.__lshift__(other)
  168. def __rshift__(self, other): return self._value.__rshift__(other)
  169. def __and__(self, other): return self._value.__and__(other)
  170. def __xor__(self, other): return self._value.__xor__(other)
  171. def __or__(self, other): return self._value.__or__(other)
  172. def __radd__(self, other): return self._value.__radd__(other)
  173. def __rsub__(self, other): return self._value.__rsub__(other)
  174. def __rmul__(self, other): return self._value.__rmul__(other)
  175. def __rmatmul__(self, other): return self._value.__rmatmul__(other)
  176. def __rtruediv__(self, other): return self._value.__rtruediv__(other)
  177. def __rfloordiv__(self, other): return self._value.__rfloordiv__(other)
  178. def __rmod__(self, other): return self._value.__rmod__(other)
  179. def __rdivmod__(self, other): return self._value.__rdivmod__(other)
  180. def __rpow__(self, other): return self._value.__rpow__(other)
  181. def __rlshift__(self, other): return self._value.__rlshift__(other)
  182. def __rrshift__(self, other): return self._value.__rrshift__(other)
  183. def __rand__(self, other): return self._value.__rand__(other)
  184. def __rxor__(self, other): return self._value.__rxor__(other)
  185. def __ror__(self, other): return self._value.__ror__(other)
  186. def __iadd__(self, other): return self._value.__iadd__(other)
  187. def __isub__(self, other): return self._value.__isub__(other)
  188. def __imul__(self, other): return self._value.__imul__(other)
  189. def __imatmul__(self, other): return self._value.__imatmul__(other)
  190. def __itruediv__(self, other): return self._value.__itruediv__(other)
  191. def __ifloordiv__(self, other): return self._value.__ifloordiv__(other)
  192. def __imod__(self, other): return self._value.__imod__(other)
  193. def __ipow__(self, other): return self._value.__ipow__(other)
  194. def __ilshift__(self, other): return self._value.__ilshift__(other)
  195. def __irshift__(self, other): return self._value.__irshift__(other)
  196. def __iand__(self, other): return self._value.__iand__(other)
  197. def __ixor__(self, other): return self._value.__ixor__(other)
  198. def __ior__(self, other): return self._value.__ior__(other)
  199. def __neg__(self): return self._value.__neg__()
  200. def __pos__(self): return self._value.__pos__()
  201. def __abs__(self): return self._value.__abs__()
  202. def __invert__(self): return self._value.__invert__()
  203. def __complex__(self): return complex(self._value)
  204. def __int__(self): return int(self._value)
  205. def __float__(self): return float(self._value)
  206. def __index__(self): return self._value.__index__()
  207. def __round__(self): return self._value.__round__()
  208. def __trunc__(self): return self._value.__trunc__()
  209. def __floor__(self): return self._value.__floor__()
  210. def __ceil__(self): return self._value.__ceil__()
  211. def __enter__(self): return self._value.__enter__()
  212. def __exit__(self, exc_type, exc_value, traceback):
  213. return self._value.__exit__(exc_type, exc_value, traceback)
  214. def __await__(self): return self._value.__await__()
  215. def __aiter__(self): return self._value.__aiter__()
  216. def __anext__(self): return self._value.__anext__()
  217. def __aenter__(self): return self._value.__aenter__()
  218. def __aexit__(self, exc_type, exc_value, traceback):
  219. return self._value.__aexit__(exc_type, exc_value, traceback)
上海开阖软件有限公司 沪ICP备12045867号-1