rafa-engineering 0.0.1b1__py3-none-any.whl

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 (320) hide show
  1. rafa/__init__.py +463 -0
  2. rafa/actions/__init__.py +42 -0
  3. rafa/actions/decorators.py +204 -0
  4. rafa/actions/results.py +533 -0
  5. rafa/agent/__init__.py +40 -0
  6. rafa/agent/install.py +428 -0
  7. rafa/agent/scaffold.py +163 -0
  8. rafa/agent/skill/SKILL.md +156 -0
  9. rafa/agent/skill/references/access-and-permissions.md +126 -0
  10. rafa/agent/skill/references/actions.md +157 -0
  11. rafa/agent/skill/references/common-mistakes.md +274 -0
  12. rafa/agent/skill/references/entities-and-hierarchy.md +190 -0
  13. rafa/agent/skill/references/fields-and-layout.md +218 -0
  14. rafa/agent/skill/references/jobs-and-progress.md +105 -0
  15. rafa/agent/skill/references/maps-3d-documents-chats.md +175 -0
  16. rafa/agent/skill/references/testing-and-checking.md +187 -0
  17. rafa/agent/skill/references/validation-and-conditions.md +176 -0
  18. rafa/agent/skill/references/views-and-results.md +206 -0
  19. rafa/agent/templates/README.md.tmpl +34 -0
  20. rafa/agent/templates/gitignore.tmpl +5 -0
  21. rafa/agent/templates/package/__init__.py.tmpl +1 -0
  22. rafa/agent/templates/package/controller.py.tmpl +59 -0
  23. rafa/agent/templates/package/parametrization.py.tmpl +32 -0
  24. rafa/agent/templates/pyproject.toml.tmpl +20 -0
  25. rafa/agent/templates/tests/test_app.py.tmpl +44 -0
  26. rafa/auth.py +72 -0
  27. rafa/chat/__init__.py +26 -0
  28. rafa/chat/execution.py +221 -0
  29. rafa/chat/model.py +194 -0
  30. rafa/chat/service.py +353 -0
  31. rafa/chat/store.py +196 -0
  32. rafa/cli.py +541 -0
  33. rafa/cli_access.py +402 -0
  34. rafa/cli_agent.py +193 -0
  35. rafa/cli_dev.py +223 -0
  36. rafa/core/__init__.py +6 -0
  37. rafa/core/access.py +2915 -0
  38. rafa/core/app_roles.py +276 -0
  39. rafa/core/application.py +2717 -0
  40. rafa/core/calculations.py +253 -0
  41. rafa/core/controller.py +614 -0
  42. rafa/core/entity.py +419 -0
  43. rafa/core/field_permissions.py +146 -0
  44. rafa/core/jobs/__init__.py +0 -0
  45. rafa/core/jobs/execution.py +238 -0
  46. rafa/core/jobs/messages.py +218 -0
  47. rafa/core/jobs/model.py +242 -0
  48. rafa/core/jobs/progress.py +248 -0
  49. rafa/core/jobs/service.py +988 -0
  50. rafa/core/jobs/store.py +412 -0
  51. rafa/core/jobs/wire.py +73 -0
  52. rafa/core/parametrization.py +712 -0
  53. rafa/core/params.py +481 -0
  54. rafa/core/registry.py +215 -0
  55. rafa/core/services/__init__.py +42 -0
  56. rafa/core/services/_common.py +53 -0
  57. rafa/core/services/calculations.py +436 -0
  58. rafa/core/services/edit_locks.py +78 -0
  59. rafa/core/services/entities.py +754 -0
  60. rafa/core/services/revisions.py +200 -0
  61. rafa/core/services/summaries.py +113 -0
  62. rafa/core/steps.py +141 -0
  63. rafa/core/storage.py +370 -0
  64. rafa/core/summary.py +344 -0
  65. rafa/demo.py +88 -0
  66. rafa/documents/__init__.py +65 -0
  67. rafa/documents/_common.py +123 -0
  68. rafa/documents/_sandbox.py +607 -0
  69. rafa/documents/excel.py +264 -0
  70. rafa/documents/images.py +246 -0
  71. rafa/documents/pdf.py +83 -0
  72. rafa/documents/word.py +235 -0
  73. rafa/exceptions.py +257 -0
  74. rafa/fields/__init__.py +98 -0
  75. rafa/fields/autocomplete.py +128 -0
  76. rafa/fields/base.py +412 -0
  77. rafa/fields/buttons.py +181 -0
  78. rafa/fields/chat.py +160 -0
  79. rafa/fields/color.py +109 -0
  80. rafa/fields/containers.py +809 -0
  81. rafa/fields/date.py +249 -0
  82. rafa/fields/file.py +430 -0
  83. rafa/fields/geo.py +535 -0
  84. rafa/fields/geometry_select.py +275 -0
  85. rafa/fields/hidden.py +61 -0
  86. rafa/fields/layout.py +331 -0
  87. rafa/fields/multiselect.py +159 -0
  88. rafa/fields/numeric.py +524 -0
  89. rafa/fields/options.py +390 -0
  90. rafa/fields/output.py +149 -0
  91. rafa/fields/relationships.py +385 -0
  92. rafa/fields/text.py +221 -0
  93. rafa/geo.py +313 -0
  94. rafa/geometry/__init__.py +107 -0
  95. rafa/geometry/material.py +215 -0
  96. rafa/geometry/models.py +221 -0
  97. rafa/geometry/objects.py +1126 -0
  98. rafa/geometry/transform.py +177 -0
  99. rafa/geometry/vector.py +195 -0
  100. rafa/geometry/wire.py +278 -0
  101. rafa/layout/__init__.py +71 -0
  102. rafa/layout/base.py +46 -0
  103. rafa/layout/chat.py +43 -0
  104. rafa/layout/children.py +27 -0
  105. rafa/layout/containers.py +141 -0
  106. rafa/layout/elements.py +105 -0
  107. rafa/layout/geo.py +33 -0
  108. rafa/layout/inputs.py +173 -0
  109. rafa/map_tiles.py +268 -0
  110. rafa/messages.py +211 -0
  111. rafa/persistence/__init__.py +6 -0
  112. rafa/persistence/access_models.py +224 -0
  113. rafa/persistence/chat_models.py +93 -0
  114. rafa/persistence/deletion.py +198 -0
  115. rafa/persistence/dialects.py +96 -0
  116. rafa/persistence/edit_locks.py +322 -0
  117. rafa/persistence/files.py +486 -0
  118. rafa/persistence/job_models.py +207 -0
  119. rafa/persistence/models.py +361 -0
  120. rafa/persistence/params_json.py +154 -0
  121. rafa/persistence/repository.py +930 -0
  122. rafa/persistence/retention.py +507 -0
  123. rafa/persistence/session.py +302 -0
  124. rafa/persistence/storage_models.py +76 -0
  125. rafa/persistence/transfer.py +238 -0
  126. rafa/persistence/types.py +56 -0
  127. rafa/project.py +158 -0
  128. rafa/project_dependencies.py +233 -0
  129. rafa/server/__init__.py +0 -0
  130. rafa/server/api.py +45 -0
  131. rafa/server/auth.py +393 -0
  132. rafa/server/controllers.py +87 -0
  133. rafa/server/dependencies.py +112 -0
  134. rafa/server/dev.py +80 -0
  135. rafa/server/logs.py +80 -0
  136. rafa/server/main.py +511 -0
  137. rafa/server/middleware.py +229 -0
  138. rafa/server/oidc.py +525 -0
  139. rafa/server/params.py +101 -0
  140. rafa/server/purge.py +87 -0
  141. rafa/server/routes/__init__.py +1 -0
  142. rafa/server/routes/_common.py +80 -0
  143. rafa/server/routes/access.py +328 -0
  144. rafa/server/routes/admin.py +318 -0
  145. rafa/server/routes/calculations.py +268 -0
  146. rafa/server/routes/chats.py +188 -0
  147. rafa/server/routes/edit_locks.py +125 -0
  148. rafa/server/routes/entities.py +289 -0
  149. rafa/server/routes/jobs.py +389 -0
  150. rafa/server/routes/navigation.py +86 -0
  151. rafa/server/routes/revisions.py +86 -0
  152. rafa/server/routes/types.py +84 -0
  153. rafa/server/schemas.py +1151 -0
  154. rafa/server/security.py +454 -0
  155. rafa/server/themes.py +326 -0
  156. rafa/server/web/assets/ActionButton-Bf4Edlki.js +1 -0
  157. rafa/server/web/assets/ActionButton.vue_vue_type_script_setup_true_lang-D4XFensL.js +1 -0
  158. rafa/server/web/assets/ActionButtonInput-Fh_nzqPc.js +1 -0
  159. rafa/server/web/assets/ActionJobButton.vue_vue_type_script_setup_true_lang-DoDkgjyF.js +1 -0
  160. rafa/server/web/assets/AutocompleteInput-BZX1zQNq.js +1 -0
  161. rafa/server/web/assets/BooleanInput-Bwk7TmkZ.js +1 -0
  162. rafa/server/web/assets/BufferGeometryUtils-DCeCGp_k.js +1 -0
  163. rafa/server/web/assets/ChatPanel-CRGfj0rM.js +5 -0
  164. rafa/server/web/assets/ChatPanel-DV8X386K.css +1 -0
  165. rafa/server/web/assets/ChildrenView-BoHMn59N.js +1 -0
  166. rafa/server/web/assets/ColorInput-BPm4Z_Jb.js +1 -0
  167. rafa/server/web/assets/Column-BeMEmV70.js +1 -0
  168. rafa/server/web/assets/DateInput-BCCGUhNt.css +1 -0
  169. rafa/server/web/assets/DateInput-DoB9qbsx.js +1 -0
  170. rafa/server/web/assets/DynamicArrayInput-DMMS0Z-7.css +1 -0
  171. rafa/server/web/assets/DynamicArrayInput-_ZexTyhi.js +1 -0
  172. rafa/server/web/assets/EntityInput-DtkTtCvs.js +1 -0
  173. rafa/server/web/assets/FieldShell.vue_vue_type_script_setup_true_lang-D1Iio9Vx.js +1 -0
  174. rafa/server/web/assets/FileUpload-D0temXG6.js +1 -0
  175. rafa/server/web/assets/FlowList-BFQbYe4d.js +1 -0
  176. rafa/server/web/assets/FlowList-BJJKReYx.css +1 -0
  177. rafa/server/web/assets/GeoInput-B8mK3_to.js +1 -0
  178. rafa/server/web/assets/GeometrySelectInput-C-dllULO.js +1 -0
  179. rafa/server/web/assets/InlineMarkdown-273vK7EL.css +1 -0
  180. rafa/server/web/assets/InlineMarkdown-DZ6hRlXd.js +1 -0
  181. rafa/server/web/assets/ItemFields.vue_vue_type_script_setup_true_lang-oM-9Jbkr.js +1 -0
  182. rafa/server/web/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  183. rafa/server/web/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  184. rafa/server/web/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  185. rafa/server/web/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  186. rafa/server/web/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  187. rafa/server/web/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  188. rafa/server/web/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  189. rafa/server/web/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  190. rafa/server/web/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  191. rafa/server/web/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  192. rafa/server/web/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  193. rafa/server/web/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  194. rafa/server/web/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  195. rafa/server/web/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  196. rafa/server/web/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  197. rafa/server/web/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  198. rafa/server/web/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  199. rafa/server/web/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  200. rafa/server/web/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  201. rafa/server/web/assets/LineBreak-aRafznt0.js +1 -0
  202. rafa/server/web/assets/MapSelectInput-DSHaB30s.js +1 -0
  203. rafa/server/web/assets/MediaEmbed-BJ439byk.js +1 -0
  204. rafa/server/web/assets/Metric-CZNGA3xN.js +1 -0
  205. rafa/server/web/assets/MetricCard.vue_vue_type_script_setup_true_lang-C9JQb8Wv.js +1 -0
  206. rafa/server/web/assets/MultiFileInput-ZXboXAai.js +1 -0
  207. rafa/server/web/assets/NodeList.vue_vue_type_script_setup_true_lang-QazaRbQq.js +1 -0
  208. rafa/server/web/assets/NumberInput-C2W5shMF.js +1 -0
  209. rafa/server/web/assets/NumberInput-ClGTeHqr.css +1 -0
  210. rafa/server/web/assets/OutputText-BCN_LkxG.js +1 -0
  211. rafa/server/web/assets/Page-CaGMez-_.js +1 -0
  212. rafa/server/web/assets/Region.vue_vue_type_script_setup_true_lang-C5zmYcwf.js +1 -0
  213. rafa/server/web/assets/Row-Svp3fhrJ.js +1 -0
  214. rafa/server/web/assets/Section-Bxqg4axO.js +1 -0
  215. rafa/server/web/assets/SelectInput-3bMoZmLo.js +1 -0
  216. rafa/server/web/assets/Tab-DmT7FFbM.js +1 -0
  217. rafa/server/web/assets/TableInput-B6pu8pc-.css +1 -0
  218. rafa/server/web/assets/TableInput-DRy1zZlo.js +1 -0
  219. rafa/server/web/assets/Tabs-D_ly_8Cg.js +1 -0
  220. rafa/server/web/assets/TextBlock-DCx1b51J.js +1 -0
  221. rafa/server/web/assets/TextInput-ChR21tIl.js +1 -0
  222. rafa/server/web/assets/View-5zkwqki7.js +7 -0
  223. rafa/server/web/assets/View-B5J19S_i.css +1 -0
  224. rafa/server/web/assets/Workspace-BHmWCHUw.js +1 -0
  225. rafa/server/web/assets/Workspace-kQMd1Tiw.css +1 -0
  226. rafa/server/web/assets/_commonjsHelpers-CqkleIqs.js +1 -0
  227. rafa/server/web/assets/buildModel-FvbW_vi8.js +1 -0
  228. rafa/server/web/assets/fileRecords-J4dDztnY.js +1 -0
  229. rafa/server/web/assets/geometryPick-D2JWx8eh.js +1 -0
  230. rafa/server/web/assets/geometryScene-DBVxLCLP.js +4012 -0
  231. rafa/server/web/assets/index-BDd7wfsC.css +1 -0
  232. rafa/server/web/assets/index-BR16ovZa.js +81 -0
  233. rafa/server/web/assets/inter-cyrillic-400-normal-obahsSVq.woff2 +0 -0
  234. rafa/server/web/assets/inter-cyrillic-500-normal-BasfLYem.woff2 +0 -0
  235. rafa/server/web/assets/inter-cyrillic-600-normal-CWCymEST.woff2 +0 -0
  236. rafa/server/web/assets/inter-cyrillic-700-normal-CjBOestx.woff2 +0 -0
  237. rafa/server/web/assets/inter-cyrillic-ext-400-normal-BQZuk6qB.woff2 +0 -0
  238. rafa/server/web/assets/inter-cyrillic-ext-500-normal-B0yAr1jD.woff2 +0 -0
  239. rafa/server/web/assets/inter-cyrillic-ext-600-normal-Dfes3d0z.woff2 +0 -0
  240. rafa/server/web/assets/inter-cyrillic-ext-700-normal-BjwYoWNd.woff2 +0 -0
  241. rafa/server/web/assets/inter-greek-400-normal-B4URO6DV.woff2 +0 -0
  242. rafa/server/web/assets/inter-greek-500-normal-BIZE56-Y.woff2 +0 -0
  243. rafa/server/web/assets/inter-greek-600-normal-plRanbMR.woff2 +0 -0
  244. rafa/server/web/assets/inter-greek-700-normal-C3JjAnD8.woff2 +0 -0
  245. rafa/server/web/assets/inter-greek-ext-400-normal-DGGRlc-M.woff2 +0 -0
  246. rafa/server/web/assets/inter-greek-ext-500-normal-C4iEst2y.woff2 +0 -0
  247. rafa/server/web/assets/inter-greek-ext-600-normal-DRtmH8MT.woff2 +0 -0
  248. rafa/server/web/assets/inter-greek-ext-700-normal-qfdV9bQt.woff2 +0 -0
  249. rafa/server/web/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
  250. rafa/server/web/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
  251. rafa/server/web/assets/inter-latin-600-normal-LgqL8muc.woff2 +0 -0
  252. rafa/server/web/assets/inter-latin-700-normal-Yt3aPRUw.woff2 +0 -0
  253. rafa/server/web/assets/inter-latin-ext-400-normal-C1nco2VV.woff2 +0 -0
  254. rafa/server/web/assets/inter-latin-ext-500-normal-CV4jyFjo.woff2 +0 -0
  255. rafa/server/web/assets/inter-latin-ext-600-normal-D2bJ5OIk.woff2 +0 -0
  256. rafa/server/web/assets/inter-latin-ext-700-normal-Ca8adRJv.woff2 +0 -0
  257. rafa/server/web/assets/inter-vietnamese-400-normal-DMkecbls.woff2 +0 -0
  258. rafa/server/web/assets/inter-vietnamese-500-normal-DOriooB6.woff2 +0 -0
  259. rafa/server/web/assets/inter-vietnamese-600-normal-Cc8MFFhd.woff2 +0 -0
  260. rafa/server/web/assets/inter-vietnamese-700-normal-DlLaEgI2.woff2 +0 -0
  261. rafa/server/web/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
  262. rafa/server/web/assets/jetbrains-mono-cyrillic-500-normal-DmUKJPL_.woff2 +0 -0
  263. rafa/server/web/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
  264. rafa/server/web/assets/jetbrains-mono-greek-500-normal-JpySY46c.woff2 +0 -0
  265. rafa/server/web/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
  266. rafa/server/web/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
  267. rafa/server/web/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
  268. rafa/server/web/assets/jetbrains-mono-latin-ext-500-normal-Cut-4mMH.woff2 +0 -0
  269. rafa/server/web/assets/katex-BYjW4tYw.css +1 -0
  270. rafa/server/web/assets/katex-DhXJpUyf.js +261 -0
  271. rafa/server/web/assets/leafletChunk-wTN8pUxY.js +1 -0
  272. rafa/server/web/assets/leafletChunk-ySJ7tiBZ.css +1 -0
  273. rafa/server/web/assets/leafletMap-sOqlnmE2.js +2 -0
  274. rafa/server/web/assets/listbox-CB4ZAfo3.js +1 -0
  275. rafa/server/web/assets/loadGltf-3B6-WLUM.js +1 -0
  276. rafa/server/web/assets/loadIfc-XWq_7Qp9.js +6 -0
  277. rafa/server/web/assets/mapSelect-3T3UH25p.js +3 -0
  278. rafa/server/web/assets/material-symbols-outlined-latin-400-normal-C-3S2fI8.woff2 +0 -0
  279. rafa/server/web/assets/plotly.min-CSPuXaX0.js +3789 -0
  280. rafa/server/web/assets/web-ifc-BDaIXFUT.wasm +0 -0
  281. rafa/server/web/favicon.svg +1 -0
  282. rafa/server/web/index.html +20 -0
  283. rafa/server/web/theme-init.js +33 -0
  284. rafa/server/web/web-view-frame.html +154 -0
  285. rafa/server/worker_process.py +320 -0
  286. rafa/server/workers.py +473 -0
  287. rafa/settings.py +586 -0
  288. rafa/testing/__init__.py +397 -0
  289. rafa/testing/checks.py +803 -0
  290. rafa/testing/pytest_plugin.py +50 -0
  291. rafa/testing/screenshot.py +508 -0
  292. rafa/themes/__init__.py +11 -0
  293. rafa/themes/colors.py +181 -0
  294. rafa/themes/css.py +109 -0
  295. rafa/themes/files.py +143 -0
  296. rafa/themes/model.py +423 -0
  297. rafa/themes/tokens.py +124 -0
  298. rafa/ui/__init__.py +75 -0
  299. rafa/ui/adapters/__init__.py +31 -0
  300. rafa/ui/adapters/cli.py +652 -0
  301. rafa/ui/application.py +667 -0
  302. rafa/ui/context.py +153 -0
  303. rafa/ui/protocols.py +681 -0
  304. rafa/utils/__init__.py +29 -0
  305. rafa/utils/dicts.py +37 -0
  306. rafa/utils/memoization.py +312 -0
  307. rafa/utils/migrations.py +316 -0
  308. rafa/validation/__init__.py +22 -0
  309. rafa/validation/callbacks.py +187 -0
  310. rafa/validation/lookup.py +807 -0
  311. rafa/views/__init__.py +91 -0
  312. rafa/views/decorators.py +290 -0
  313. rafa/views/maps.py +990 -0
  314. rafa/views/results.py +1428 -0
  315. rafa/views/safe_html.py +100 -0
  316. rafa_engineering-0.0.1b1.dist-info/METADATA +175 -0
  317. rafa_engineering-0.0.1b1.dist-info/RECORD +320 -0
  318. rafa_engineering-0.0.1b1.dist-info/WHEEL +4 -0
  319. rafa_engineering-0.0.1b1.dist-info/entry_points.txt +5 -0
  320. rafa_engineering-0.0.1b1.dist-info/licenses/LICENSE +121 -0
rafa/__init__.py ADDED
@@ -0,0 +1,463 @@
1
+ """
2
+ Rafa - an application framework for engineering web applications.
3
+
4
+ This module exports the public API for building applications. Names that were public
5
+ earlier but are not in ``__all__`` any more still import, with a ``DeprecationWarning`` that
6
+ names their new home (see ``_MOVED``).
7
+
8
+ Examples
9
+ --------
10
+ >>> from rafa import (
11
+ ... Application,
12
+ ... Controller,
13
+ ... Parametrization,
14
+ ... Tab,
15
+ ... Section,
16
+ ... NumberField,
17
+ ... TextField,
18
+ ... OptionField,
19
+ ... DateField,
20
+ ... Table,
21
+ ... DynamicArray,
22
+ ... Lookup,
23
+ ... view,
24
+ ... action,
25
+ ... HTMLResult,
26
+ ... SuccessResult,
27
+ ... format_html,
28
+ ... )
29
+ >>>
30
+ >>> class BeamParametrization(Parametrization):
31
+ ... geometry = Tab("Geometry")
32
+ ... geometry.width = NumberField(label="Width", default=0.3)
33
+ ...
34
+ >>> class BeamController(Controller):
35
+ ... label = "Beam"
36
+ ... parametrization = BeamParametrization
37
+ ...
38
+ ... @view("Overview")
39
+ ... def overview(self, params, entity, **kwargs):
40
+ ... # format_html escapes the values: a name like "<B1>" shows as typed
41
+ ... return HTMLResult(
42
+ ... format_html("<h2>{}</h2><p>Width: {} m</p>", entity.name, params.geometry.width)
43
+ ... )
44
+ ...
45
+ ... @action("Calculate")
46
+ ... def calculate(self, params, entity, **kwargs):
47
+ ... return SuccessResult(message="Done!")
48
+ >>>
49
+ >>> app = Application("sqlite:///app.db")
50
+ >>> app.register(BeamController)
51
+ """
52
+
53
+ import warnings as _warnings
54
+ from importlib import import_module as _import_module
55
+ from importlib.metadata import PackageNotFoundError
56
+ from importlib.metadata import version as _package_version
57
+ from typing import Any as _Any
58
+
59
+ # Actions
60
+ from rafa.actions.decorators import action
61
+ from rafa.actions.results import (
62
+ ActionResult,
63
+ ErrorResult,
64
+ FileResult,
65
+ OptimizationColumn,
66
+ OptimizationResult,
67
+ OptimizationResultElement,
68
+ SetParamsResult,
69
+ SuccessResult,
70
+ )
71
+
72
+ # Auth
73
+ from rafa.auth import LOCAL_USER, User
74
+
75
+ # Chats
76
+ from rafa.chat.model import ChatMessage, ChatReply, ChatSuggestion, ChatTurn, Conversation
77
+
78
+ # Core
79
+ from rafa.core.access import Role
80
+ from rafa.core.app_roles import AppRole, Permission
81
+ from rafa.core.application import Application
82
+ from rafa.core.calculations import CalculationLimitError
83
+ from rafa.core.controller import CalculationContext, Controller
84
+ from rafa.core.entity import Entity
85
+ from rafa.core.jobs.model import Job
86
+ from rafa.core.jobs.progress import CalculationStopped, Progress, ProgressUpdate
87
+ from rafa.core.parametrization import Parametrization
88
+ from rafa.core.params import MutableParams, Params
89
+ from rafa.core.services import DeletedEntity
90
+ from rafa.core.steps import StepCheck
91
+ from rafa.core.storage import Storage, StorageLimitError
92
+ from rafa.core.summary import SummaryItem, SummaryValue
93
+
94
+ # Exceptions
95
+ from rafa.exceptions import (
96
+ CircularRelationshipError,
97
+ ConflictError,
98
+ EditLockedError,
99
+ EntityNotFoundError,
100
+ InputsLockedError,
101
+ InputViolation,
102
+ InvalidParamsError,
103
+ JobNotFoundError,
104
+ MigrationError,
105
+ NotFoundError,
106
+ PermissionDeniedError,
107
+ RafaError,
108
+ StaleRevisionError,
109
+ UserError,
110
+ )
111
+
112
+ # Fields
113
+ from rafa.fields.autocomplete import AutocompleteField
114
+ from rafa.fields.base import Field, FieldError
115
+ from rafa.fields.buttons import (
116
+ ActionButtonField,
117
+ DownloadButtonField,
118
+ OptimizationButtonField,
119
+ SetParamsButtonField,
120
+ )
121
+ from rafa.fields.chat import ChatField
122
+ from rafa.fields.color import ColorField
123
+ from rafa.fields.containers import DynamicArray, Table
124
+ from rafa.fields.date import DateField
125
+ from rafa.fields.file import FileField, FileValue, MultiFileField
126
+ from rafa.fields.geo import GeoPointField, GeoPolygonField, GeoPolylineField, MapSelectField
127
+ from rafa.fields.geometry_select import GeometryMultiSelectField, GeometrySelectField
128
+ from rafa.fields.hidden import HiddenField
129
+ from rafa.fields.layout import Image, LineBreak, Section, Step, Tab, Text
130
+ from rafa.fields.multiselect import MultiSelectField
131
+ from rafa.fields.numeric import IntegerField, NumberField
132
+ from rafa.fields.options import BooleanField, OptionField, OptionListElement
133
+ from rafa.fields.output import OutputField
134
+ from rafa.fields.relationships import (
135
+ ChildEntityMultiSelectField,
136
+ ChildEntityOptionField,
137
+ EntityField,
138
+ EntityMultiSelectField,
139
+ SiblingEntityMultiSelectField,
140
+ SiblingEntityOptionField,
141
+ )
142
+ from rafa.fields.text import TextAreaField, TextField
143
+
144
+ # Geo
145
+ from rafa.geo import GeoPath, GeoPoint, rd_to_wgs, wgs_to_rd
146
+
147
+ # Geometry (the objects are in rafa.geometry)
148
+ from rafa.geometry.models import IFCResult
149
+ from rafa.messages import Message, Messages, Status
150
+
151
+ # Persistence
152
+ from rafa.persistence.repository import CascadeMode
153
+
154
+ # Themes
155
+ from rafa.themes.model import Brand, FontFace, Fonts, Theme, ThemeError
156
+
157
+ # Utils
158
+ from rafa.utils.memoization import LRUCache, memoize
159
+ from rafa.utils.migrations import MigrationRegistry, ParamsMigrator
160
+
161
+ # Validation
162
+ from rafa.validation.lookup import (
163
+ And,
164
+ Condition,
165
+ IsEqual,
166
+ IsFalse,
167
+ IsNotEqual,
168
+ IsNotNone,
169
+ IsTrue,
170
+ Lookup,
171
+ LookupExpression,
172
+ Not,
173
+ Or,
174
+ RowLookup,
175
+ resolve_lookup,
176
+ )
177
+
178
+ # Views
179
+ from rafa.views.decorators import ViewLocation, ViewSpeed, metric, view
180
+ from rafa.views.maps import (
181
+ GeoJSONResult,
182
+ MapCircle,
183
+ MapFeature,
184
+ MapLabel,
185
+ MapLegend,
186
+ MapLine,
187
+ MapPoint,
188
+ MapPolygon,
189
+ MapPolyline,
190
+ MapResult,
191
+ map_features,
192
+ require_mapyta,
193
+ )
194
+ from rafa.views.results import (
195
+ ALL,
196
+ DataItem,
197
+ DataResult,
198
+ ErrorViewResult,
199
+ GeometryResult,
200
+ HTMLResult,
201
+ ImageResult,
202
+ MetricResult,
203
+ PDFResult,
204
+ PlotlyResult,
205
+ TableCell,
206
+ TableColumn,
207
+ TableResult,
208
+ ViewResult,
209
+ WebResult,
210
+ math_html,
211
+ )
212
+ from rafa.views.results import (
213
+ DataViewResult as DataViewResult, # older name of DataResult
214
+ )
215
+ from rafa.views.results import (
216
+ HTMLViewResult as HTMLViewResult, # older name of HTMLResult
217
+ )
218
+ from rafa.views.safe_html import SafeHTML, format_html, html_escape
219
+
220
+ try:
221
+ __version__ = _package_version("rafa-engineering")
222
+ except PackageNotFoundError: # pragma: no cover - only when running from an uninstalled tree
223
+ __version__ = "0.0.0+unknown"
224
+
225
+ __all__ = [
226
+ "__version__",
227
+ # Core
228
+ "Application",
229
+ "User",
230
+ "LOCAL_USER",
231
+ "Role",
232
+ "Permission",
233
+ "AppRole",
234
+ "Controller",
235
+ "CalculationContext",
236
+ "StepCheck",
237
+ "Progress",
238
+ "ProgressUpdate",
239
+ "CalculationStopped",
240
+ "Messages",
241
+ "Message",
242
+ "Status",
243
+ "Job",
244
+ "Entity",
245
+ "Parametrization",
246
+ "Params",
247
+ "MutableParams",
248
+ "SummaryItem",
249
+ "SummaryValue",
250
+ "Storage",
251
+ # Exceptions
252
+ "RafaError",
253
+ "NotFoundError",
254
+ "EntityNotFoundError",
255
+ "ConflictError",
256
+ "StaleRevisionError",
257
+ "InputsLockedError",
258
+ "EditLockedError",
259
+ "JobNotFoundError",
260
+ "InvalidParamsError",
261
+ "CalculationLimitError",
262
+ "CircularRelationshipError",
263
+ "MigrationError",
264
+ "InputViolation",
265
+ "UserError",
266
+ "PermissionDeniedError",
267
+ "StorageLimitError",
268
+ # Fields - Base
269
+ "Field",
270
+ "FieldError",
271
+ # Fields - Numeric
272
+ "NumberField",
273
+ "IntegerField",
274
+ # Fields - Text
275
+ "TextField",
276
+ "TextAreaField",
277
+ # Fields - Date
278
+ "DateField",
279
+ # Fields - Options
280
+ "BooleanField",
281
+ "OptionField",
282
+ "OptionListElement",
283
+ # Fields - Containers
284
+ "Table",
285
+ "DynamicArray",
286
+ # Fields - Output
287
+ "OutputField",
288
+ # Fields - Multi-select
289
+ "MultiSelectField",
290
+ # Fields - Hidden
291
+ "HiddenField",
292
+ # Fields - Autocomplete
293
+ "AutocompleteField",
294
+ # Fields - Color
295
+ "ColorField",
296
+ # Fields - File
297
+ "FileField",
298
+ "FileValue",
299
+ "MultiFileField",
300
+ # Fields - Geo
301
+ "GeoPointField",
302
+ "GeoPolylineField",
303
+ "GeoPolygonField",
304
+ "MapSelectField",
305
+ # Fields - Buttons
306
+ "ActionButtonField",
307
+ "DownloadButtonField",
308
+ "SetParamsButtonField",
309
+ "OptimizationButtonField",
310
+ # Fields - Chat
311
+ "ChatField",
312
+ # Fields - Relationships
313
+ "EntityField",
314
+ "EntityMultiSelectField",
315
+ "ChildEntityOptionField",
316
+ "ChildEntityMultiSelectField",
317
+ "SiblingEntityOptionField",
318
+ "SiblingEntityMultiSelectField",
319
+ # Fields - Selection in a geometry view
320
+ "GeometrySelectField",
321
+ "GeometryMultiSelectField",
322
+ # Fields - Layout
323
+ "Tab",
324
+ "Step",
325
+ "Section",
326
+ "Text",
327
+ "LineBreak",
328
+ "Image",
329
+ # Validation
330
+ "Lookup",
331
+ "LookupExpression",
332
+ "RowLookup",
333
+ "resolve_lookup",
334
+ # Visibility operators
335
+ "And",
336
+ "Or",
337
+ "Not",
338
+ "IsTrue",
339
+ "IsFalse",
340
+ "IsNotNone",
341
+ "IsEqual",
342
+ "IsNotEqual",
343
+ "Condition",
344
+ # Geo
345
+ "GeoPoint",
346
+ "GeoPath",
347
+ "rd_to_wgs",
348
+ "wgs_to_rd",
349
+ # Persistence
350
+ "CascadeMode",
351
+ "DeletedEntity",
352
+ # Themes
353
+ "Theme",
354
+ "Brand",
355
+ "Fonts",
356
+ "FontFace",
357
+ "ThemeError",
358
+ # Utils - Memoization
359
+ "LRUCache",
360
+ "memoize",
361
+ # Utils - Migrations
362
+ "MigrationRegistry",
363
+ "ParamsMigrator",
364
+ # Actions
365
+ "action",
366
+ "ActionResult",
367
+ "SuccessResult",
368
+ "ErrorResult",
369
+ "FileResult",
370
+ "SetParamsResult",
371
+ "OptimizationResult",
372
+ "OptimizationResultElement",
373
+ "OptimizationColumn",
374
+ # Chats
375
+ "ChatMessage",
376
+ "ChatReply",
377
+ "ChatSuggestion",
378
+ "ChatTurn",
379
+ "Conversation",
380
+ # Views
381
+ "view",
382
+ "metric",
383
+ "ViewLocation",
384
+ "ViewSpeed",
385
+ "ViewResult",
386
+ "HTMLResult",
387
+ "math_html",
388
+ "format_html",
389
+ "html_escape",
390
+ "SafeHTML",
391
+ "DataResult",
392
+ "DataItem",
393
+ "ErrorViewResult",
394
+ "MetricResult",
395
+ "PlotlyResult",
396
+ "GeometryResult",
397
+ "IFCResult",
398
+ "TableResult",
399
+ "TableCell",
400
+ "TableColumn",
401
+ "ImageResult",
402
+ "PDFResult",
403
+ "WebResult",
404
+ "ALL",
405
+ # Views - Maps
406
+ "MapResult",
407
+ "GeoJSONResult",
408
+ "MapFeature",
409
+ "MapPoint",
410
+ "MapLine",
411
+ "MapPolyline",
412
+ "MapPolygon",
413
+ "MapCircle",
414
+ "MapLabel",
415
+ "MapLegend",
416
+ "map_features",
417
+ "require_mapyta",
418
+ ]
419
+
420
+ # Names that left the top-level API: still importable, with a DeprecationWarning.
421
+ # name -> (module, attribute)
422
+ _MOVED: dict[str, tuple[str, str]] = {
423
+ # The protocol layer for other front ends; the web app does not use it
424
+ **{
425
+ name: ("rafa.ui", name)
426
+ for name in (
427
+ "UIContext",
428
+ "FormRenderer",
429
+ "ViewRenderer",
430
+ "ActionHandler",
431
+ "EntityBrowser",
432
+ "NotificationHandler",
433
+ "UIApplication",
434
+ "DefaultUIContext",
435
+ )
436
+ },
437
+ # Internals of conditions, caching, validation and the decorators
438
+ "LookupContext": ("rafa.validation.lookup", "LookupContext"),
439
+ "resolve_visibility": ("rafa.validation.lookup", "resolve_visibility"),
440
+ "evaluate_condition": ("rafa.validation.lookup", "evaluate_condition"),
441
+ "get_view_cache": ("rafa.utils.memoization", "get_view_cache"),
442
+ "ActionDefinition": ("rafa.actions", "ActionDefinition"),
443
+ "ViewDefinition": ("rafa.views", "ViewDefinition"),
444
+ "ValidationResult": ("rafa.fields", "ValidationResult"),
445
+ # Renamed: pydantic has a ValidationError too
446
+ "ValidationError": ("rafa", "FieldError"),
447
+ }
448
+
449
+
450
+ def __getattr__(name: str) -> _Any:
451
+ """Import a name that moved out of the top-level API, with a DeprecationWarning."""
452
+ if name not in _MOVED:
453
+ raise AttributeError(f"module 'rafa' has no attribute {name!r}")
454
+ module, attribute = _MOVED[name]
455
+ new = f"{module}.{attribute}" if module != "rafa" else f"rafa.{attribute}"
456
+ _warnings.warn(
457
+ f"rafa.{name} is deprecated; import {new} instead.",
458
+ DeprecationWarning,
459
+ stacklevel=2,
460
+ )
461
+ if module == "rafa":
462
+ return globals()[attribute]
463
+ return getattr(_import_module(module), attribute)
@@ -0,0 +1,42 @@
1
+ """
2
+ Action system for buttons and user interactions.
3
+
4
+ Actions are button-triggered operations defined on Controllers
5
+ that execute backend logic and return results to the UI.
6
+ """
7
+
8
+ from rafa.actions.decorators import (
9
+ ActionDefinition,
10
+ ActionLocation,
11
+ action,
12
+ get_action_definition,
13
+ is_action,
14
+ )
15
+ from rafa.actions.results import (
16
+ ActionResult,
17
+ ErrorResult,
18
+ FileResult,
19
+ OptimizationColumn,
20
+ OptimizationResult,
21
+ OptimizationResultElement,
22
+ SetParamsResult,
23
+ SuccessResult,
24
+ )
25
+
26
+ __all__ = [
27
+ # Decorators
28
+ "action",
29
+ "ActionDefinition",
30
+ "ActionLocation",
31
+ "is_action",
32
+ "get_action_definition",
33
+ # Results
34
+ "ActionResult",
35
+ "SuccessResult",
36
+ "ErrorResult",
37
+ "FileResult",
38
+ "SetParamsResult",
39
+ "OptimizationResult",
40
+ "OptimizationResultElement",
41
+ "OptimizationColumn",
42
+ ]
@@ -0,0 +1,204 @@
1
+ """
2
+ Action decorators for defining button-triggered operations on Controllers.
3
+ """
4
+
5
+ from collections.abc import Callable
6
+ from dataclasses import dataclass
7
+ from functools import wraps
8
+ from typing import Any, Literal, TypeVar, get_args
9
+
10
+ from rafa.actions.results import ActionResult
11
+ from rafa.core.calculations import check_timeout
12
+
13
+ ActionLocation = Literal["sidebar", "inspector"]
14
+ """Where an action button is placed in the workspace."""
15
+
16
+ ACTION_LOCATIONS: tuple[str, ...] = get_args(ActionLocation)
17
+
18
+
19
+ @dataclass
20
+ class ActionDefinition:
21
+ """
22
+ Metadata about an action method.
23
+
24
+ Stored on the method and used by the runtime to:
25
+ - Register actions for an entity type
26
+ - Display buttons in the UI
27
+ - Handle confirmation dialogs
28
+
29
+ Attributes
30
+ ----------
31
+ label : str
32
+ Button label shown in UI.
33
+ method_name : str
34
+ Name of the decorated method.
35
+ description : str | None
36
+ Tooltip text.
37
+ confirmation_message : str | None
38
+ If set, shows confirmation dialog before executing.
39
+ dangerous : bool
40
+ If True, button gets warning styling (e.g., red color).
41
+ icon : str | None
42
+ Icon name (e.g., "play", "bolt").
43
+ location : ActionLocation
44
+ ``"sidebar"`` (in the inputs panel, below the inputs) or ``"inspector"`` (in the
45
+ results panel, below the results).
46
+ validate_inputs : bool
47
+ Only run when every input is valid (default). ``False`` for actions that repair
48
+ the inputs, such as "reset to defaults".
49
+ timeout : float | None
50
+ Time limit in seconds; ``None`` uses the application's, ``0`` means none.
51
+ permission : str
52
+ What a user's role must allow to run it: ``"edit"`` (default, Editor), ``"read"``
53
+ (Viewer too, e.g. an export) or ``"manage"`` (Project admin). A ``SetParamsResult``
54
+ is saved only for an Editor.
55
+ locks_inputs : bool
56
+ Whether the entity's inputs are locked while the action is queued or running (D37):
57
+ saves, restores and other actions that save inputs are refused. Only for actions
58
+ whose ``permission`` is not ``"read"``. Default True.
59
+ """
60
+
61
+ label: str
62
+ method_name: str
63
+ description: str | None
64
+ confirmation_message: str | None
65
+ dangerous: bool
66
+ icon: str | None = None
67
+ location: ActionLocation = "sidebar"
68
+ validate_inputs: bool = True
69
+ timeout: float | None = None
70
+ permission: str = "edit"
71
+ locks_inputs: bool = True
72
+
73
+ @property
74
+ def locks(self) -> bool:
75
+ """Whether running it locks the inputs: ``locks_inputs`` and not a ``read`` action."""
76
+ return self.locks_inputs and self.permission != "read"
77
+
78
+
79
+ A = TypeVar("A", bound=Callable[..., ActionResult])
80
+
81
+
82
+ def action(
83
+ label: str,
84
+ *,
85
+ description: str | None = None,
86
+ confirmation_message: str | None = None,
87
+ dangerous: bool = False,
88
+ icon: str | None = None,
89
+ location: ActionLocation = "sidebar",
90
+ validate_inputs: bool = True,
91
+ timeout: float | None = None,
92
+ permission: str = "edit",
93
+ locks_inputs: bool = True,
94
+ ) -> Callable[[A], A]:
95
+ """
96
+ Decorator to mark a method as an action.
97
+
98
+ Actions are button-triggered operations that execute backend logic
99
+ and return a result to the UI.
100
+
101
+ Parameters
102
+ ----------
103
+ label : str
104
+ Button label shown in UI.
105
+ description : str | None, optional
106
+ Tooltip/help text.
107
+ confirmation_message : str | None, optional
108
+ If set, shows "Are you sure?" dialog with this message.
109
+ dangerous : bool, optional
110
+ If True, button gets warning styling. Default False.
111
+ icon : str | None, optional
112
+ Icon name (Material Symbols, e.g. ``"bolt"``).
113
+ location : {"sidebar", "inspector"}, optional
114
+ ``"sidebar"`` puts the button in the inputs panel, below the inputs;
115
+ ``"inspector"`` in the results panel, below the results. Default ``"sidebar"``.
116
+ validate_inputs : bool, optional
117
+ Only run when every input is valid; otherwise the action returns an
118
+ ``ErrorResult`` that lists the invalid fields. Default True. Set it to False for
119
+ actions that repair the inputs, such as "reset to defaults".
120
+ timeout : float | None, optional
121
+ Seconds the action may calculate. On the server it is then stopped (D37) and
122
+ returns an ``ErrorResult`` "No result within … s."; its ``SetParamsResult`` is never
123
+ saved. ``None`` (default) uses the application's limit
124
+ (``RAFA_CALCULATION_TIMEOUT`` on the server), ``0`` means no limit.
125
+ permission : str, optional
126
+ What a user's role must allow to run the action (access control, D36):
127
+ ``"edit"`` (default: Editors and Project admins), ``"read"`` (Viewers too; for
128
+ actions that change nothing, such as an export) or ``"manage"`` (Project admins).
129
+ Whatever it allows, a ``SetParamsResult`` is saved only for an Editor. The
130
+ controller's ``check_definition()`` refuses other names.
131
+ locks_inputs : bool, optional
132
+ Lock the entity's inputs while the action is queued or running (default True): on
133
+ the server, saves, restores and other actions that save inputs are refused (409)
134
+ until it ends, so it never saves over a change made meanwhile, nor another over
135
+ its own. ``False`` for an action that never saves inputs (no ``SetParamsResult``,
136
+ no save through ``kwargs["app"]``). Actions with ``permission="read"`` never lock.
137
+
138
+ Returns
139
+ -------
140
+ Callable
141
+ Decorator function.
142
+
143
+ Raises
144
+ ------
145
+ ValueError
146
+ If ``location`` is not one of the supported locations, ``timeout`` is
147
+ negative, or ``locks_inputs`` is not a bool.
148
+ """
149
+ check_timeout(timeout, f"@action({label!r})")
150
+ if not isinstance(locks_inputs, bool):
151
+ raise ValueError(
152
+ f"@action({label!r}): locks_inputs must be True or False, got {locks_inputs!r}"
153
+ )
154
+ if location not in ACTION_LOCATIONS:
155
+ raise ValueError(
156
+ f"@action({label!r}): unknown location {location!r}. "
157
+ f"Use one of: {', '.join(ACTION_LOCATIONS)}"
158
+ )
159
+
160
+ def decorator(func: A) -> A:
161
+ # Create action definition
162
+ action_def = ActionDefinition(
163
+ label=label,
164
+ method_name=func.__name__,
165
+ description=description,
166
+ confirmation_message=confirmation_message,
167
+ dangerous=dangerous,
168
+ icon=icon,
169
+ location=location,
170
+ validate_inputs=validate_inputs,
171
+ timeout=timeout,
172
+ permission=permission,
173
+ locks_inputs=locks_inputs,
174
+ )
175
+
176
+ # Attach metadata to function
177
+ func._action_definition = action_def
178
+
179
+ @wraps(func)
180
+ def wrapper(*args: Any, **kwargs: Any) -> ActionResult:
181
+ result = func(*args, **kwargs)
182
+ if not isinstance(result, ActionResult):
183
+ raise TypeError(
184
+ f"Action '{func.__name__}' must return an ActionResult, "
185
+ f"got {type(result).__name__}"
186
+ )
187
+ return result
188
+
189
+ # Preserve metadata on wrapper
190
+ wrapper._action_definition = action_def # type: ignore[attr-defined]
191
+
192
+ return wrapper # type: ignore[return-value]
193
+
194
+ return decorator
195
+
196
+
197
+ def is_action(obj: Any) -> bool:
198
+ """Check if an object is an action method."""
199
+ return callable(obj) and hasattr(obj, "_action_definition")
200
+
201
+
202
+ def get_action_definition(method: Callable[..., Any]) -> ActionDefinition | None:
203
+ """Get the ActionDefinition for an action method."""
204
+ return getattr(method, "_action_definition", None)