wrapt 2.2.2rc1__tar.gz → 2.2.2rc2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. {wrapt-2.2.2rc1/src/wrapt.egg-info → wrapt-2.2.2rc2}/PKG-INFO +1 -1
  2. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt/__init__.py +1 -1
  3. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt/caching.py +13 -1
  4. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2/src/wrapt.egg-info}/PKG-INFO +1 -1
  5. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_lru_cache.py +155 -0
  6. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/LICENSE +0 -0
  7. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/MANIFEST.in +0 -0
  8. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/README.md +0 -0
  9. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/RELEASE.rst +0 -0
  10. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/pyproject.toml +0 -0
  11. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/setup.cfg +0 -0
  12. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/setup.py +0 -0
  13. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt/__wrapt__.py +0 -0
  14. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt/_wrappers.c +0 -0
  15. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt/arguments.py +0 -0
  16. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt/decorators.py +0 -0
  17. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt/importer.py +0 -0
  18. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt/patches.py +0 -0
  19. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt/proxies.py +0 -0
  20. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt/signature.py +0 -0
  21. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt/synchronization.py +0 -0
  22. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt/weakrefs.py +0 -0
  23. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt/wrappers.py +0 -0
  24. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt-stubs/__init__.pyi +0 -0
  25. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt.egg-info/SOURCES.txt +0 -0
  26. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt.egg-info/dependency_links.txt +0 -0
  27. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt.egg-info/not-zip-safe +0 -0
  28. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt.egg-info/requires.txt +0 -0
  29. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/src/wrapt.egg-info/top_level.txt +0 -0
  30. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/conftest.py +0 -0
  31. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/compat.py +0 -0
  32. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/module1.py +0 -0
  33. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/module2.py +0 -0
  34. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_adapter.py +0 -0
  35. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_adapter_py3.py +0 -0
  36. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_adapter_py33.py +0 -0
  37. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_annotations.py +0 -0
  38. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_attribute_wrapper.py +0 -0
  39. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_auto_object_proxy.py +0 -0
  40. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_callable_binding_no_args.py +0 -0
  41. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_callable_object_proxy.py +0 -0
  42. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_class.py +0 -0
  43. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_class_py37.py +0 -0
  44. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_copy.py +0 -0
  45. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_decorator_state.py +0 -0
  46. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_decorators.py +0 -0
  47. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_deferred_patching.py +0 -0
  48. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_descriptor_get_class_access.py +0 -0
  49. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_descriptors_py36.py +0 -0
  50. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_enabled_bool_error.py +0 -0
  51. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_entry_points.py +0 -0
  52. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_formatargspec_py35.py +0 -0
  53. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_formatargspec_py38.py +0 -0
  54. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_function.py +0 -0
  55. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_function_wrapper.py +0 -0
  56. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_inheritance_py37.py +0 -0
  57. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_inner_classmethod.py +0 -0
  58. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_inner_staticmethod.py +0 -0
  59. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_inplace_operators.py +0 -0
  60. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_instancemethod.py +0 -0
  61. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_lazy_object_proxy.py +0 -0
  62. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_memoize.py +0 -0
  63. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_monkey_patching.py +0 -0
  64. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_nested_function.py +0 -0
  65. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_object_proxy.py +0 -0
  66. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_object_proxy_hook.py +0 -0
  67. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_object_proxy_self_dict.py +0 -0
  68. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_object_proxy_type_checks.py +0 -0
  69. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_outer_classmethod.py +0 -0
  70. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_outer_staticmethod.py +0 -0
  71. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_pickle.py +0 -0
  72. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_post_import_hooks.py +0 -0
  73. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_pyerr_clear_propagation.py +0 -0
  74. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_resolve_path.py +0 -0
  75. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_runtime_type_hints.py +0 -0
  76. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_synchronized_async.py +0 -0
  77. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_synchronized_lock.py +0 -0
  78. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_synchronized_markers.py +0 -0
  79. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_type_module_attribute.py +0 -0
  80. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_update_attributes.py +0 -0
  81. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_weak_function_proxy.py +0 -0
  82. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/core/test_with_signature.py +0 -0
  83. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_auto_object_proxy_t1.out +0 -0
  84. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_auto_object_proxy_t1.py +0 -0
  85. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_decorator_t1.out +0 -0
  86. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_decorator_t1.py +0 -0
  87. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_cls_t1.out +0 -0
  88. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_cls_t1.py +0 -0
  89. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_cls_t2.out +0 -0
  90. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_cls_t2.py +0 -0
  91. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_cls_t3.out +0 -0
  92. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_cls_t3.py +0 -0
  93. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_cls_t4.out +0 -0
  94. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_cls_t4.py +0 -0
  95. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_cls_t5.out +0 -0
  96. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_cls_t5.py +0 -0
  97. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_cls_t6.out +0 -0
  98. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_cls_t6.py +0 -0
  99. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_cls_t7.out +0 -0
  100. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_cls_t7.py +0 -0
  101. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_cls_t8.out +0 -0
  102. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_cls_t8.py +0 -0
  103. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_fn_t1.out +0 -0
  104. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_fn_t1.py +0 -0
  105. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_fn_t2.out +0 -0
  106. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_fn_t2.py +0 -0
  107. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_fn_t3.out +0 -0
  108. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_fn_t3.py +0 -0
  109. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_fn_t4.out +0 -0
  110. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_fn_t4.py +0 -0
  111. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_fn_t5.out +0 -0
  112. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_fn_t5.py +0 -0
  113. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_fn_t6.out +0 -0
  114. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_fn_t6.py +0 -0
  115. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_fn_t7.out +0 -0
  116. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_function_wrapper_fn_t7.py +0 -0
  117. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_object_proxy_arithmetic_t1.out +0 -0
  118. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_object_proxy_arithmetic_t1.py +0 -0
  119. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_object_proxy_container_t1.out +0 -0
  120. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_object_proxy_container_t1.py +0 -0
  121. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_object_proxy_context_t1.out +0 -0
  122. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_object_proxy_context_t1.py +0 -0
  123. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_partial_callable_t1.out +0 -0
  124. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_partial_callable_t1.py +0 -0
  125. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_patch_function_wrapper_t1.out +0 -0
  126. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_patch_function_wrapper_t1.py +0 -0
  127. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_patching_primitives_t1.out +0 -0
  128. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_patching_primitives_t1.py +0 -0
  129. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_post_import_hooks_t1.out +0 -0
  130. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_post_import_hooks_t1.py +0 -0
  131. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_synchronized_lock_t1.out +0 -0
  132. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_synchronized_lock_t1.py +0 -0
  133. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_transient_function_wrapper_t1.out +0 -0
  134. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_transient_function_wrapper_t1.py +0 -0
  135. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_weak_function_proxy_t1.out +0 -0
  136. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_weak_function_proxy_t1.py +0 -0
  137. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_wrap_function_wrapper_t1.out +0 -0
  138. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_wrap_function_wrapper_t1.py +0 -0
  139. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_wrap_function_wrapper_t2.out +0 -0
  140. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_wrap_function_wrapper_t2.py +0 -0
  141. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_wrap_function_wrapper_t3.out +0 -0
  142. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_wrap_function_wrapper_t3.py +0 -0
  143. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_wrap_function_wrapper_t4.out +0 -0
  144. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_wrap_function_wrapper_t4.py +0 -0
  145. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_wrap_function_wrapper_t5.out +0 -0
  146. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_wrap_function_wrapper_t5.py +0 -0
  147. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_wrap_function_wrapper_t6.out +0 -0
  148. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_wrap_function_wrapper_t6.py +0 -0
  149. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_wrap_function_wrapper_t7.out +0 -0
  150. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_wrap_function_wrapper_t7.py +0 -0
  151. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_wrap_function_wrapper_t8.out +0 -0
  152. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tests/mypy/mypy_wrap_function_wrapper_t8.py +0 -0
  153. {wrapt-2.2.2rc1 → wrapt-2.2.2rc2}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wrapt
3
- Version: 2.2.2rc1
3
+ Version: 2.2.2rc2
4
4
  Summary: Module for decorators, wrappers and monkey patching.
5
5
  Author-email: Graham Dumpleton <Graham.Dumpleton@gmail.com>
6
6
  License-Expression: BSD-2-Clause
@@ -13,7 +13,7 @@ def _format_version(parts):
13
13
  )
14
14
 
15
15
 
16
- __version_info__ = ("2", "2", "2", "rc1")
16
+ __version_info__ = ("2", "2", "2", "rc2")
17
17
  __version__ = _format_version(__version_info__)
18
18
 
19
19
  from .__wrapt__ import (
@@ -71,7 +71,19 @@ class _BoundLRUCacheFunctionWrapper(BoundFunctionWrapper):
71
71
  self.__wrapped__
72
72
  )
73
73
 
74
- setattr(instance, cache_attr, cache)
74
+ # If the instance the method is bound to is a wrapt
75
+ # object proxy, a plain setattr() would fall through and
76
+ # store the cache on the wrapped object rather than the
77
+ # proxy. Proxies expose __self_setattr__() which stores
78
+ # the attribute on the proxy itself, so use it when it is
79
+ # available and fall back to setattr() otherwise.
80
+
81
+ set_attr = getattr(instance, "__self_setattr__", None)
82
+
83
+ if set_attr is not None:
84
+ set_attr(cache_attr, cache)
85
+ else:
86
+ setattr(instance, cache_attr, cache)
75
87
 
76
88
  return cache(*args, **kwargs)
77
89
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wrapt
3
- Version: 2.2.2rc1
3
+ Version: 2.2.2rc2
4
4
  Summary: Module for decorators, wrappers and monkey patching.
5
5
  Author-email: Graham Dumpleton <Graham.Dumpleton@gmail.com>
6
6
  License-Expression: BSD-2-Clause
@@ -267,6 +267,161 @@ class TestStaticMethod(unittest.TestCase):
267
267
  self.assertEqual(info.misses, 1)
268
268
 
269
269
 
270
+ class OverrideBase:
271
+ def __init__(self):
272
+ self.base_calls = 0
273
+ self.derived_calls = 0
274
+
275
+ @wrapt.lru_cache
276
+ def compute(self, x):
277
+ self.base_calls += 1
278
+ return x * 2
279
+
280
+
281
+ class OverrideDerived(OverrideBase):
282
+ @wrapt.lru_cache
283
+ def compute(self, x):
284
+ self.derived_calls += 1
285
+ return super().compute(x) + 1
286
+
287
+
288
+ class TestOverriddenMethodWithSuper(unittest.TestCase):
289
+ def test_super_call_returns_correct_result(self):
290
+ obj = OverrideDerived()
291
+ self.assertEqual(obj.compute(10), 21)
292
+
293
+ def test_super_call_does_not_recurse(self):
294
+ # Regression test: a subclass method decorated with lru_cache that
295
+ # called the base method via super() used to recurse forever because
296
+ # the base and derived methods shared a single per-instance cache
297
+ # slot derived from the method name alone.
298
+ obj = OverrideDerived()
299
+ try:
300
+ result = obj.compute(10)
301
+ except RecursionError:
302
+ self.fail("super() call recursed instead of reaching base method")
303
+ self.assertEqual(result, 21)
304
+
305
+ def test_both_bodies_execute_once(self):
306
+ obj = OverrideDerived()
307
+ obj.compute(10)
308
+ self.assertEqual(obj.derived_calls, 1)
309
+ self.assertEqual(obj.base_calls, 1)
310
+
311
+ def test_base_and_derived_cached_independently(self):
312
+ obj = OverrideDerived()
313
+ obj.compute(10)
314
+ obj.compute(10)
315
+ # Second call is served from both caches, so neither body re-runs.
316
+ self.assertEqual(obj.derived_calls, 1)
317
+ self.assertEqual(obj.base_calls, 1)
318
+ info = obj.compute.cache_info()
319
+ self.assertEqual(info.hits, 1)
320
+ self.assertEqual(info.misses, 1)
321
+
322
+ def test_base_class_instance_unaffected(self):
323
+ obj = OverrideBase()
324
+ self.assertEqual(obj.compute(10), 20)
325
+ self.assertEqual(obj.base_calls, 1)
326
+ self.assertEqual(obj.derived_calls, 0)
327
+
328
+ def test_separate_instances_have_separate_caches(self):
329
+ obj1 = OverrideDerived()
330
+ obj2 = OverrideDerived()
331
+ obj1.compute(10)
332
+ obj2.compute(10)
333
+ self.assertEqual(obj1.derived_calls, 1)
334
+ self.assertEqual(obj2.derived_calls, 1)
335
+ self.assertEqual(obj1.base_calls, 1)
336
+ self.assertEqual(obj2.base_calls, 1)
337
+
338
+
339
+ class ProxyWrapped:
340
+ def __init__(self, a):
341
+ self.a = a
342
+
343
+
344
+ class ProxyCached(wrapt.ObjectProxy):
345
+ @wrapt.lru_cache
346
+ def compute(self, x):
347
+ return self.a + x
348
+
349
+
350
+ class ProxyCachedWithState(wrapt.ObjectProxy):
351
+ def __init__(self, wrapped, factor):
352
+ super().__init__(wrapped)
353
+ self._self_factor = factor
354
+
355
+ @wrapt.lru_cache
356
+ def compute(self, x):
357
+ return self._self_factor * x
358
+
359
+
360
+ class SlottedWrapped:
361
+ __slots__ = ("a",)
362
+
363
+ def __init__(self, a):
364
+ self.a = a
365
+
366
+
367
+ class TestObjectProxySubclass(unittest.TestCase):
368
+ def test_returns_correct_result(self):
369
+ obj = ProxyCached(ProxyWrapped(1))
370
+ self.assertEqual(obj.compute(10), 11)
371
+
372
+ def test_caching(self):
373
+ obj = ProxyCached(ProxyWrapped(1))
374
+ obj.compute(10)
375
+ obj.compute(10)
376
+ info = obj.compute.cache_info()
377
+ self.assertEqual(info.hits, 1)
378
+ self.assertEqual(info.misses, 1)
379
+
380
+ def test_cache_not_stored_on_wrapped_object(self):
381
+ wrapped = ProxyWrapped(1)
382
+ obj = ProxyCached(wrapped)
383
+ obj.compute(10)
384
+ cache_attrs = [k for k in vars(wrapped) if k.startswith("_lru_cache_")]
385
+ self.assertEqual(cache_attrs, [])
386
+
387
+ def test_per_proxy_state_not_shared_for_same_wrapped_object(self):
388
+ # Two proxies over the same wrapped object must keep independent
389
+ # per-instance caches keyed to their own proxy state, not a single
390
+ # cache stored on the shared wrapped object.
391
+ wrapped = ProxyWrapped(1)
392
+ obj1 = ProxyCachedWithState(wrapped, 2)
393
+ obj2 = ProxyCachedWithState(wrapped, 10)
394
+ self.assertEqual(obj1.compute(5), 10)
395
+ self.assertEqual(obj2.compute(5), 50)
396
+
397
+ def test_proxy_garbage_collected_with_long_lived_wrapped(self):
398
+ # The cache must be stored on the proxy, not the wrapped object, so
399
+ # a proxy is not kept alive by a wrapped object that outlives it.
400
+ registry = []
401
+
402
+ def make_and_use():
403
+ backing = ProxyWrapped(7)
404
+ registry.append(backing)
405
+ proxy = ProxyCached(backing)
406
+ proxy.compute(4)
407
+ return weakref.ref(proxy)
408
+
409
+ ref = make_and_use()
410
+ gc.collect()
411
+ self.assertIsNone(ref())
412
+
413
+ def test_wrapped_object_without_dict(self):
414
+ # A wrapped object that does not accept arbitrary attributes (for
415
+ # example one using __slots__) must not cause the cache storage to
416
+ # fail, since the cache is stored on the proxy.
417
+ obj = ProxyCached(SlottedWrapped(1))
418
+ self.assertEqual(obj.compute(10), 11)
419
+ self.assertEqual(obj.compute(10), 11)
420
+ info = obj.compute.cache_info()
421
+ self.assertEqual(info.hits, 1)
422
+ self.assertEqual(info.misses, 1)
423
+
424
+
270
425
  class TestIntrospection(unittest.TestCase):
271
426
  def test_function_name(self):
272
427
  self.assertEqual(cached_function.__name__, "cached_function")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes