cone.app 2.2.0__tar.gz → 2.2.1__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 (165) hide show
  1. {cone_app-2.2.0 → cone_app-2.2.1}/CHANGES.rst +10 -0
  2. {cone_app-2.2.0 → cone_app-2.2.1}/PKG-INFO +11 -1
  3. {cone_app-2.2.0 → cone_app-2.2.1}/pyproject.toml +1 -1
  4. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/actions.py +0 -5
  5. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/utils.py +6 -3
  6. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_utils.py +16 -0
  7. {cone_app-2.2.0 → cone_app-2.2.1}/.gitignore +0 -0
  8. {cone_app-2.2.0 → cone_app-2.2.1}/LICENSE.rst +0 -0
  9. {cone_app-2.2.0 → cone_app-2.2.1}/README.rst +0 -0
  10. {cone_app-2.2.0 → cone_app-2.2.1}/TODO.rst +0 -0
  11. {cone_app-2.2.0 → cone_app-2.2.1}/biome.json +0 -0
  12. {cone_app-2.2.0 → cone_app-2.2.1}/constraints.txt +0 -0
  13. {cone_app-2.2.0 → cone_app-2.2.1}/include.mk +0 -0
  14. {cone_app-2.2.0 → cone_app-2.2.1}/requirements.txt +0 -0
  15. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/__init__.py +0 -0
  16. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/__init__.py +0 -0
  17. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/ajax.py +0 -0
  18. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/authoring.py +0 -0
  19. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/batch.py +0 -0
  20. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/content.py +0 -0
  21. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/contents.py +0 -0
  22. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/contextmenu.py +0 -0
  23. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/copysupport.py +0 -0
  24. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/exception.py +0 -0
  25. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/form.py +0 -0
  26. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/layout.py +0 -0
  27. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/login.py +0 -0
  28. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/order.py +0 -0
  29. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/referencebrowser.py +0 -0
  30. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/resources.py +0 -0
  31. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/search.py +0 -0
  32. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/settings.py +0 -0
  33. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/sharing.py +0 -0
  34. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/bootstrap/css/bootstrap.css +0 -0
  35. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/bootstrap/css/bootstrap.min.css +0 -0
  36. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/bootstrap/icons/bootstrap-icons.css +0 -0
  37. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/bootstrap/icons/bootstrap-icons.json +0 -0
  38. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/bootstrap/icons/bootstrap-icons.min.css +0 -0
  39. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/bootstrap/icons/bootstrap-icons.scss +0 -0
  40. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/bootstrap/icons/fonts/bootstrap-icons.woff +0 -0
  41. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/bootstrap/icons/fonts/bootstrap-icons.woff2 +0 -0
  42. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/bootstrap/js/bootstrap.bundle.js +0 -0
  43. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/bootstrap/js/bootstrap.bundle.min.js +0 -0
  44. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/bootstrap/js/popper.min.js +0 -0
  45. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/cone/cone.app.css +0 -0
  46. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/cone/cone.app.js +0 -0
  47. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/cone/cone.app.min.css +0 -0
  48. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/cone/cone.app.min.js +0 -0
  49. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/cone/cone.app.print.css +0 -0
  50. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/cone/favicon.ico +0 -0
  51. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/cone/flags/de.svg +0 -0
  52. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/cone/flags/en.svg +0 -0
  53. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/cone/flags/fr.svg +0 -0
  54. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/cone/flags/it.svg +0 -0
  55. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/jquery/jquery-4.0.0.js +0 -0
  56. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/static/jquery/jquery-4.0.0.min.js +0 -0
  57. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/table.py +0 -0
  58. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/action_download.pt +0 -0
  59. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/action_dropdown.pt +0 -0
  60. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/add_dropdown.pt +0 -0
  61. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/batch.pt +0 -0
  62. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/batched_items.pt +0 -0
  63. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/batched_items_footer.pt +0 -0
  64. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/batched_items_header.pt +0 -0
  65. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/button_action.pt +0 -0
  66. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/byline.pt +0 -0
  67. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/colortoggler.pt +0 -0
  68. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/content_form.pt +0 -0
  69. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/contextmenu.pt +0 -0
  70. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/contextmenu_dropdown.pt +0 -0
  71. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/default_root.pt +0 -0
  72. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/footer.pt +0 -0
  73. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/insufficient_privileges.pt +0 -0
  74. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/language.pt +0 -0
  75. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/layout.pt +0 -0
  76. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/link_action.pt +0 -0
  77. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/listing.pt +0 -0
  78. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/livesearch.pt +0 -0
  79. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/logo.pt +0 -0
  80. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/main.pt +0 -0
  81. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/mainmenu.pt +0 -0
  82. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/navtree.pt +0 -0
  83. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/navtree_recue.pt +0 -0
  84. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/not_found.pt +0 -0
  85. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/pathbar.pt +0 -0
  86. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/personaltools.pt +0 -0
  87. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/referencebrowser.pt +0 -0
  88. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/referencebrowser_pathbar.pt +0 -0
  89. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/resources.pt +0 -0
  90. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/settings.pt +0 -0
  91. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/settings_form.pt +0 -0
  92. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/settings_sidebar.pt +0 -0
  93. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/sharing.pt +0 -0
  94. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/table.pt +0 -0
  95. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/unauthorized.pt +0 -0
  96. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/templates/wf_dropdown.pt +0 -0
  97. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/translation.py +0 -0
  98. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/browser/workflow.py +0 -0
  99. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/compat.py +0 -0
  100. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/configure.zcml +0 -0
  101. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/interfaces.py +0 -0
  102. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/locale/cone.app.pot +0 -0
  103. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/locale/de/LC_MESSAGES/cone.app.mo +0 -0
  104. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/locale/de/LC_MESSAGES/cone.app.po +0 -0
  105. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/locale/en/LC_MESSAGES/cone.app.mo +0 -0
  106. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/locale/en/LC_MESSAGES/cone.app.po +0 -0
  107. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/model.py +0 -0
  108. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/origin.py +0 -0
  109. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/security.py +0 -0
  110. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/__init__.py +0 -0
  111. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/data/ugm/groups +0 -0
  112. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/data/ugm/roles +0 -0
  113. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/data/ugm/userdata/groups/group1 +0 -0
  114. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/data/ugm/userdata/users/admin +0 -0
  115. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/data/ugm/userdata/users/editor +0 -0
  116. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/data/ugm/userdata/users/manager +0 -0
  117. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/data/ugm/userdata/users/max +0 -0
  118. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/data/ugm/userdata/users/sepp +0 -0
  119. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/data/ugm/userdata/users/viewer +0 -0
  120. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/data/ugm/users +0 -0
  121. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/dummy_action.pt +0 -0
  122. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/dummy_batched_items.pt +0 -0
  123. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/dummy_form.yaml +0 -0
  124. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/dummy_main.pt +0 -0
  125. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/dummy_workflow.zcml +0 -0
  126. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/mock.py +0 -0
  127. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/static/print1.css +0 -0
  128. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/static/print2.css +0 -0
  129. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/static/script1.js +0 -0
  130. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/static/script2.js +0 -0
  131. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/static/style1.css +0 -0
  132. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/testing/static/style2.css +0 -0
  133. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_app.py +0 -0
  134. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser.py +0 -0
  135. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_actions.py +0 -0
  136. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_ajax.py +0 -0
  137. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_authoring.py +0 -0
  138. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_batch.py +0 -0
  139. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_content.py +0 -0
  140. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_contents.py +0 -0
  141. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_contextmenu.py +0 -0
  142. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_copysupport.py +0 -0
  143. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_exception.py +0 -0
  144. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_form.py +0 -0
  145. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_layout.py +0 -0
  146. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_login.py +0 -0
  147. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_order.py +0 -0
  148. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_referencebrowser.py +0 -0
  149. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_resources.py +0 -0
  150. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_search.py +0 -0
  151. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_settings.py +0 -0
  152. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_sharing.py +0 -0
  153. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_table.py +0 -0
  154. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_translation.py +0 -0
  155. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_browser_workflow.py +0 -0
  156. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_model.py +0 -0
  157. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_origin.py +0 -0
  158. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_security.py +0 -0
  159. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_testing.py +0 -0
  160. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_ugm.py +0 -0
  161. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_utils.py +0 -0
  162. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/tests/test_workflow.py +0 -0
  163. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/ugm.py +0 -0
  164. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/utils.py +0 -0
  165. {cone_app-2.2.0 → cone_app-2.2.1}/src/cone/app/workflow.py +0 -0
@@ -1,6 +1,16 @@
1
1
  Changes
2
2
  =======
3
3
 
4
+ 2.2.1 (2026-11-09)
5
+ ------------------
6
+
7
+ - ``request_property`` keeps the instance in its cache entry. The cache key is
8
+ built from ``id(self)``, and since ``cone.tile`` renders a copy of the tile on
9
+ every call, a tile rendered later in the same request could get the address
10
+ of a collected one and read its cached value.
11
+ [rnix]
12
+
13
+
4
14
  2.2.0 (2026-11-09)
5
15
  ------------------
6
16
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: cone.app
3
- Version: 2.2.0
3
+ Version: 2.2.1
4
4
  Summary: Web application stub
5
5
  Project-URL: Homepage, http://github.com/conestack/cone.app
6
6
  Author-email: Cone Contributors <dev@conestack.org>
@@ -104,6 +104,16 @@ Contributors
104
104
  Changes
105
105
  =======
106
106
 
107
+ 2.2.1 (2026-11-09)
108
+ ------------------
109
+
110
+ - ``request_property`` keeps the instance in its cache entry. The cache key is
111
+ built from ``id(self)``, and since ``cone.tile`` renders a copy of the tile on
112
+ every call, a tile rendered later in the same request could get the address
113
+ of a collected one and read its cached value.
114
+ [rnix]
115
+
116
+
107
117
  2.2.0 (2026-11-09)
108
118
  ------------------
109
119
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "cone.app"
7
- version = "2.2.0"
7
+ version = "2.2.1"
8
8
  description = "Web application stub"
9
9
  dynamic = ["readme"]
10
10
  requires-python = ">=3.10"
@@ -118,11 +118,6 @@ class Action:
118
118
  ⚠ **Not called ``bind``**: ``LinkAction.bind`` is the ajax event and
119
119
  several actions set it to ``None``, so a method of that name would be
120
120
  a string on half of them.
121
-
122
- ⚠ Do not add a ``request_property`` to an action. Its cache key is
123
- built from ``id(self)``, and two bound copies of one render can land on
124
- the same address once the first is collected - the second would then
125
- read the first's answer.
126
121
  """
127
122
  action = copy.copy(self)
128
123
  action.model = model
@@ -110,10 +110,13 @@ def request_property(func):
110
110
  def wrapper(self):
111
111
  cache_key = f'{id(self)!s}.{self.__class__.__name__}.{func.__name__}'
112
112
  try:
113
- return self.request.environ[cache_key]
113
+ return self.request.environ[cache_key][1]
114
114
  except KeyError:
115
- val = self.request.environ[cache_key] = func(self)
116
- return val
115
+ # Holding the instance keeps its id, and so the cache key, from
116
+ # being reused by another object while the request lives.
117
+ value = func(self)
118
+ self.request.environ[cache_key] = (self, value)
119
+ return value
117
120
 
118
121
  wrapper.__doc__ = func.__doc__
119
122
  return property(wrapper)
@@ -116,6 +116,22 @@ class TestBrowserUtils(TileTestCase):
116
116
  self.assertEqual(rpuc.cached_attr, 'cached attribute')
117
117
  self.assertEqual(counter['computed'], 1)
118
118
 
119
+ def test_request_property_per_instance(self):
120
+ class RequestPropertyUsingClass:
121
+ def __init__(self, request, value):
122
+ self.request = request
123
+ self.value = value
124
+
125
+ @request_property
126
+ def cached_attr(self):
127
+ return self.value
128
+
129
+ request = self.layer.new_request()
130
+ # Each instance is collected right away, so the next one usually gets
131
+ # its address and thus its id.
132
+ for value in range(100):
133
+ self.assertEqual(RequestPropertyUsingClass(request, value).cached_attr, value)
134
+
119
135
  def test_client_error_message(self):
120
136
  request = self.layer.new_request()
121
137
  try:
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