xlwings-server 1.1.0__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 (313) hide show
  1. xlwings_server/.env.template +145 -0
  2. xlwings_server/__init__.py +12 -0
  3. xlwings_server/_version.py +34 -0
  4. xlwings_server/auth/__init__.py +0 -0
  5. xlwings_server/auth/custom/__init__.py +26 -0
  6. xlwings_server/auth/entraid/__init__.py +131 -0
  7. xlwings_server/auth/entraid/jwks.py +10 -0
  8. xlwings_server/azure_functions_templates/.funcignore +28 -0
  9. xlwings_server/azure_functions_templates/function_app.py +28 -0
  10. xlwings_server/azure_functions_templates/host.json +22 -0
  11. xlwings_server/azure_functions_templates/local.settings.json +8 -0
  12. xlwings_server/build_utils/__init__.py +9 -0
  13. xlwings_server/build_utils/static_file_hasher.py +212 -0
  14. xlwings_server/cli.py +1592 -0
  15. xlwings_server/config.py +228 -0
  16. xlwings_server/custom_functions/__init__.py +8 -0
  17. xlwings_server/custom_functions/examples.py +177 -0
  18. xlwings_server/custom_scripts/__init__.py +8 -0
  19. xlwings_server/custom_scripts/examples.py +94 -0
  20. xlwings_server/databases.py +19 -0
  21. xlwings_server/dependencies.py +126 -0
  22. xlwings_server/docker_templates/.dockerignore +15 -0
  23. xlwings_server/docker_templates/Dockerfile +60 -0
  24. xlwings_server/docker_templates/docker-compose.yaml +32 -0
  25. xlwings_server/hotreload.py +59 -0
  26. xlwings_server/main.py +242 -0
  27. xlwings_server/models/__init__.py +14 -0
  28. xlwings_server/models/user.py +53 -0
  29. xlwings_server/object_handles.py +142 -0
  30. xlwings_server/routers/__init__.py +0 -0
  31. xlwings_server/routers/manifest.py +82 -0
  32. xlwings_server/routers/root.py +16 -0
  33. xlwings_server/routers/socketio.py +69 -0
  34. xlwings_server/routers/taskpane.py +12 -0
  35. xlwings_server/routers/xlwings.py +197 -0
  36. xlwings_server/security_headers.json +53 -0
  37. xlwings_server/serializers/__init__.py +25 -0
  38. xlwings_server/serializers/default_serializer.py +19 -0
  39. xlwings_server/serializers/dictionary_serializer.py +25 -0
  40. xlwings_server/serializers/framework.py +50 -0
  41. xlwings_server/serializers/numpy_serializer.py +26 -0
  42. xlwings_server/serializers/pandas_serializer.py +95 -0
  43. xlwings_server/static/css/core.css +28 -0
  44. xlwings_server/static/css/style.css +0 -0
  45. xlwings_server/static/images/favicon.png +0 -0
  46. xlwings_server/static/images/xlwings-16.png +0 -0
  47. xlwings_server/static/images/xlwings-32.png +0 -0
  48. xlwings_server/static/images/xlwings-64.png +0 -0
  49. xlwings_server/static/images/xlwings-80.png +0 -0
  50. xlwings_server/static/js/auth.js +13 -0
  51. xlwings_server/static/js/config.js +4 -0
  52. xlwings_server/static/js/core/alpinejs-csp-boilerplate.js +11 -0
  53. xlwings_server/static/js/core/bootstrap-customizations.js +7 -0
  54. xlwings_server/static/js/core/custom-functions-code.js +296 -0
  55. xlwings_server/static/js/core/examples.js +62 -0
  56. xlwings_server/static/js/core/hotreload.js +3 -0
  57. xlwings_server/static/js/core/htmx-handlers.js +86 -0
  58. xlwings_server/static/js/core/officejs-history-fix-part1.js +3 -0
  59. xlwings_server/static/js/core/officejs-history-fix-part2.js +2 -0
  60. xlwings_server/static/js/core/reload-custom-functions.js +79 -0
  61. xlwings_server/static/js/core/socketio-handlers.js +34 -0
  62. xlwings_server/static/js/core/xlwings-alert.js +22 -0
  63. xlwings_server/static/js/core/xlwingsjs/alert.js +85 -0
  64. xlwings_server/static/js/core/xlwingsjs/auth.js +63 -0
  65. xlwings_server/static/js/core/xlwingsjs/sheet-buttons.js +133 -0
  66. xlwings_server/static/js/core/xlwingsjs/utils.js +119 -0
  67. xlwings_server/static/js/core/xlwingsjs/wasm.js +131 -0
  68. xlwings_server/static/js/core/xlwingsjs/xlwings.js +1060 -0
  69. xlwings_server/static/js/main.js +0 -0
  70. xlwings_server/static/js/ribbon.js +17 -0
  71. xlwings_server/static/vendor/@alpinejs/LICENSE +21 -0
  72. xlwings_server/static/vendor/@alpinejs/csp/dist/cdn.min.js +7 -0
  73. xlwings_server/static/vendor/@microsoft/office-js/LICENSE.md +76 -0
  74. xlwings_server/static/vendor/@microsoft/office-js/dist/af-za/office_strings.js +8 -0
  75. xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/agaveerrorux.js +18 -0
  76. xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/agavedefaulticon32x32.png +0 -0
  77. xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/agavedefaulticon96x96.png +0 -0
  78. xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/businessbarclose_16x16x32.png +0 -0
  79. xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/dropdownarrow_16x16x32.png +0 -0
  80. xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/ellipsis_16x16x32.png +0 -0
  81. xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/miniinfoblue_16x16x32.png +0 -0
  82. xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/moe_default_icon.png +0 -0
  83. xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/moe_status_icons.png +0 -0
  84. xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/office.png +0 -0
  85. xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/refresh_16x16x32.png +0 -0
  86. xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/index.html +16 -0
  87. xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/style/agaveerrorux.css +482 -0
  88. xlwings_server/static/vendor/@microsoft/office-js/dist/am-et/office_strings.js +1 -0
  89. xlwings_server/static/vendor/@microsoft/office-js/dist/ar-ae/office_strings.js +8 -0
  90. xlwings_server/static/vendor/@microsoft/office-js/dist/ar-bh/office_strings.js +8 -0
  91. xlwings_server/static/vendor/@microsoft/office-js/dist/ar-dz/office_strings.js +8 -0
  92. xlwings_server/static/vendor/@microsoft/office-js/dist/ar-eg/office_strings.js +8 -0
  93. xlwings_server/static/vendor/@microsoft/office-js/dist/ar-iq/office_strings.js +8 -0
  94. xlwings_server/static/vendor/@microsoft/office-js/dist/ar-jo/office_strings.js +8 -0
  95. xlwings_server/static/vendor/@microsoft/office-js/dist/ar-kw/office_strings.js +8 -0
  96. xlwings_server/static/vendor/@microsoft/office-js/dist/ar-lb/office_strings.js +8 -0
  97. xlwings_server/static/vendor/@microsoft/office-js/dist/ar-ly/office_strings.js +8 -0
  98. xlwings_server/static/vendor/@microsoft/office-js/dist/ar-ma/office_strings.js +8 -0
  99. xlwings_server/static/vendor/@microsoft/office-js/dist/ar-om/office_strings.js +8 -0
  100. xlwings_server/static/vendor/@microsoft/office-js/dist/ar-qa/office_strings.js +8 -0
  101. xlwings_server/static/vendor/@microsoft/office-js/dist/ar-sa/office_strings.js +1 -0
  102. xlwings_server/static/vendor/@microsoft/office-js/dist/ar-sy/office_strings.js +8 -0
  103. xlwings_server/static/vendor/@microsoft/office-js/dist/ar-tn/office_strings.js +8 -0
  104. xlwings_server/static/vendor/@microsoft/office-js/dist/ar-ye/office_strings.js +8 -0
  105. xlwings_server/static/vendor/@microsoft/office-js/dist/ariatelemetry/aria-web-telemetry-2.8.0.min.js +2 -0
  106. xlwings_server/static/vendor/@microsoft/office-js/dist/ariatelemetry/aria-web-telemetry-2.9.0.min.js +2 -0
  107. xlwings_server/static/vendor/@microsoft/office-js/dist/ariatelemetry/aria-web-telemetry.js +1 -0
  108. xlwings_server/static/vendor/@microsoft/office-js/dist/az-latn-az/office_strings.js +8 -0
  109. xlwings_server/static/vendor/@microsoft/office-js/dist/be-by/office_strings.js +8 -0
  110. xlwings_server/static/vendor/@microsoft/office-js/dist/bg-bg/office_strings.js +1 -0
  111. xlwings_server/static/vendor/@microsoft/office-js/dist/bn-in/office_strings.js +1 -0
  112. xlwings_server/static/vendor/@microsoft/office-js/dist/bs-latn-ba/office_strings.js +8 -0
  113. xlwings_server/static/vendor/@microsoft/office-js/dist/ca-es/office_strings.js +1 -0
  114. xlwings_server/static/vendor/@microsoft/office-js/dist/cs-cz/office_strings.js +1 -0
  115. xlwings_server/static/vendor/@microsoft/office-js/dist/cy-gb/office_strings.js +1 -0
  116. xlwings_server/static/vendor/@microsoft/office-js/dist/da-dk/office_strings.js +1 -0
  117. xlwings_server/static/vendor/@microsoft/office-js/dist/de-at/office_strings.js +8 -0
  118. xlwings_server/static/vendor/@microsoft/office-js/dist/de-ch/office_strings.js +8 -0
  119. xlwings_server/static/vendor/@microsoft/office-js/dist/de-de/office_strings.js +1 -0
  120. xlwings_server/static/vendor/@microsoft/office-js/dist/de-li/office_strings.js +8 -0
  121. xlwings_server/static/vendor/@microsoft/office-js/dist/de-lu/office_strings.js +8 -0
  122. xlwings_server/static/vendor/@microsoft/office-js/dist/el-gr/office_strings.js +1 -0
  123. xlwings_server/static/vendor/@microsoft/office-js/dist/en-029/office_strings.js +8 -0
  124. xlwings_server/static/vendor/@microsoft/office-js/dist/en-au/office_strings.js +8 -0
  125. xlwings_server/static/vendor/@microsoft/office-js/dist/en-bz/office_strings.js +8 -0
  126. xlwings_server/static/vendor/@microsoft/office-js/dist/en-ca/office_strings.js +8 -0
  127. xlwings_server/static/vendor/@microsoft/office-js/dist/en-gb/office_strings.js +8 -0
  128. xlwings_server/static/vendor/@microsoft/office-js/dist/en-ie/office_strings.js +8 -0
  129. xlwings_server/static/vendor/@microsoft/office-js/dist/en-in/office_strings.js +8 -0
  130. xlwings_server/static/vendor/@microsoft/office-js/dist/en-jm/office_strings.js +8 -0
  131. xlwings_server/static/vendor/@microsoft/office-js/dist/en-my/office_strings.js +8 -0
  132. xlwings_server/static/vendor/@microsoft/office-js/dist/en-nz/office_strings.js +8 -0
  133. xlwings_server/static/vendor/@microsoft/office-js/dist/en-ph/office_strings.js +8 -0
  134. xlwings_server/static/vendor/@microsoft/office-js/dist/en-sg/office_strings.js +8 -0
  135. xlwings_server/static/vendor/@microsoft/office-js/dist/en-tt/office_strings.js +8 -0
  136. xlwings_server/static/vendor/@microsoft/office-js/dist/en-us/office_strings.js +8 -0
  137. xlwings_server/static/vendor/@microsoft/office-js/dist/en-za/office_strings.js +8 -0
  138. xlwings_server/static/vendor/@microsoft/office-js/dist/en-zw/office_strings.js +8 -0
  139. xlwings_server/static/vendor/@microsoft/office-js/dist/es-ar/office_strings.js +8 -0
  140. xlwings_server/static/vendor/@microsoft/office-js/dist/es-bo/office_strings.js +8 -0
  141. xlwings_server/static/vendor/@microsoft/office-js/dist/es-cl/office_strings.js +8 -0
  142. xlwings_server/static/vendor/@microsoft/office-js/dist/es-co/office_strings.js +8 -0
  143. xlwings_server/static/vendor/@microsoft/office-js/dist/es-cr/office_strings.js +8 -0
  144. xlwings_server/static/vendor/@microsoft/office-js/dist/es-do/office_strings.js +8 -0
  145. xlwings_server/static/vendor/@microsoft/office-js/dist/es-ec/office_strings.js +8 -0
  146. xlwings_server/static/vendor/@microsoft/office-js/dist/es-es/office_strings.js +1 -0
  147. xlwings_server/static/vendor/@microsoft/office-js/dist/es-gt/office_strings.js +8 -0
  148. xlwings_server/static/vendor/@microsoft/office-js/dist/es-hn/office_strings.js +8 -0
  149. xlwings_server/static/vendor/@microsoft/office-js/dist/es-mx/office_strings.js +1 -0
  150. xlwings_server/static/vendor/@microsoft/office-js/dist/es-ni/office_strings.js +8 -0
  151. xlwings_server/static/vendor/@microsoft/office-js/dist/es-pa/office_strings.js +8 -0
  152. xlwings_server/static/vendor/@microsoft/office-js/dist/es-pe/office_strings.js +8 -0
  153. xlwings_server/static/vendor/@microsoft/office-js/dist/es-pr/office_strings.js +8 -0
  154. xlwings_server/static/vendor/@microsoft/office-js/dist/es-py/office_strings.js +8 -0
  155. xlwings_server/static/vendor/@microsoft/office-js/dist/es-sv/office_strings.js +8 -0
  156. xlwings_server/static/vendor/@microsoft/office-js/dist/es-us/office_strings.js +8 -0
  157. xlwings_server/static/vendor/@microsoft/office-js/dist/es-uy/office_strings.js +8 -0
  158. xlwings_server/static/vendor/@microsoft/office-js/dist/es-ve/office_strings.js +8 -0
  159. xlwings_server/static/vendor/@microsoft/office-js/dist/es6-promise.js +5 -0
  160. xlwings_server/static/vendor/@microsoft/office-js/dist/et-ee/office_strings.js +1 -0
  161. xlwings_server/static/vendor/@microsoft/office-js/dist/eu-es/office_strings.js +1 -0
  162. xlwings_server/static/vendor/@microsoft/office-js/dist/excel-15.01.js +11 -0
  163. xlwings_server/static/vendor/@microsoft/office-js/dist/excel-15.02.js +11 -0
  164. xlwings_server/static/vendor/@microsoft/office-js/dist/excel-15.js +11 -0
  165. xlwings_server/static/vendor/@microsoft/office-js/dist/excel-mac-16.00-core.js +11 -0
  166. xlwings_server/static/vendor/@microsoft/office-js/dist/excel-mac-16.00.js +25 -0
  167. xlwings_server/static/vendor/@microsoft/office-js/dist/excel-web-16.00-core.js +11 -0
  168. xlwings_server/static/vendor/@microsoft/office-js/dist/excel-web-16.00.js +25 -0
  169. xlwings_server/static/vendor/@microsoft/office-js/dist/excel-win32-16.00.js +19 -0
  170. xlwings_server/static/vendor/@microsoft/office-js/dist/excel-win32-16.01-core.js +11 -0
  171. xlwings_server/static/vendor/@microsoft/office-js/dist/excel-win32-16.01.js +25 -0
  172. xlwings_server/static/vendor/@microsoft/office-js/dist/excel-winrt-16.00.js +25 -0
  173. xlwings_server/static/vendor/@microsoft/office-js/dist/excelios-15.js +11 -0
  174. xlwings_server/static/vendor/@microsoft/office-js/dist/excelwebapp-15.01.js +11 -0
  175. xlwings_server/static/vendor/@microsoft/office-js/dist/excelwebapp-15.02.js +11 -0
  176. xlwings_server/static/vendor/@microsoft/office-js/dist/excelwebapp-15.js +11 -0
  177. xlwings_server/static/vendor/@microsoft/office-js/dist/fa-ir/office_strings.js +1 -0
  178. xlwings_server/static/vendor/@microsoft/office-js/dist/fi-fi/office_strings.js +1 -0
  179. xlwings_server/static/vendor/@microsoft/office-js/dist/fil-ph/office_strings.js +1 -0
  180. xlwings_server/static/vendor/@microsoft/office-js/dist/fr-be/office_strings.js +8 -0
  181. xlwings_server/static/vendor/@microsoft/office-js/dist/fr-ca/office_strings.js +1 -0
  182. xlwings_server/static/vendor/@microsoft/office-js/dist/fr-ch/office_strings.js +8 -0
  183. xlwings_server/static/vendor/@microsoft/office-js/dist/fr-fr/office_strings.js +1 -0
  184. xlwings_server/static/vendor/@microsoft/office-js/dist/fr-lu/office_strings.js +8 -0
  185. xlwings_server/static/vendor/@microsoft/office-js/dist/fr-mc/office_strings.js +8 -0
  186. xlwings_server/static/vendor/@microsoft/office-js/dist/ga-ie/office_strings.js +8 -0
  187. xlwings_server/static/vendor/@microsoft/office-js/dist/gl-es/office_strings.js +1 -0
  188. xlwings_server/static/vendor/@microsoft/office-js/dist/gu-in/office_strings.js +1 -0
  189. xlwings_server/static/vendor/@microsoft/office-js/dist/he-il/office_strings.js +1 -0
  190. xlwings_server/static/vendor/@microsoft/office-js/dist/hi-in/office_strings.js +1 -0
  191. xlwings_server/static/vendor/@microsoft/office-js/dist/hr-ba/office_strings.js +8 -0
  192. xlwings_server/static/vendor/@microsoft/office-js/dist/hr-hr/office_strings.js +1 -0
  193. xlwings_server/static/vendor/@microsoft/office-js/dist/html2canvas.js +8 -0
  194. xlwings_server/static/vendor/@microsoft/office-js/dist/hu-hu/office_strings.js +1 -0
  195. xlwings_server/static/vendor/@microsoft/office-js/dist/hy-am/office_strings.js +8 -0
  196. xlwings_server/static/vendor/@microsoft/office-js/dist/id-id/office_strings.js +1 -0
  197. xlwings_server/static/vendor/@microsoft/office-js/dist/is-is/office_strings.js +1 -0
  198. xlwings_server/static/vendor/@microsoft/office-js/dist/it-ch/office_strings.js +8 -0
  199. xlwings_server/static/vendor/@microsoft/office-js/dist/it-it/office_strings.js +1 -0
  200. xlwings_server/static/vendor/@microsoft/office-js/dist/ja-jp/office_strings.js +1 -0
  201. xlwings_server/static/vendor/@microsoft/office-js/dist/ka-ge/office_strings.js +8 -0
  202. xlwings_server/static/vendor/@microsoft/office-js/dist/kk-kz/office_strings.js +1 -0
  203. xlwings_server/static/vendor/@microsoft/office-js/dist/km-kh/office_strings.js +8 -0
  204. xlwings_server/static/vendor/@microsoft/office-js/dist/kn-in/office_strings.js +1 -0
  205. xlwings_server/static/vendor/@microsoft/office-js/dist/ko-kr/office_strings.js +1 -0
  206. xlwings_server/static/vendor/@microsoft/office-js/dist/lb-lu/office_strings.js +8 -0
  207. xlwings_server/static/vendor/@microsoft/office-js/dist/lo-la/office_strings.js +1 -0
  208. xlwings_server/static/vendor/@microsoft/office-js/dist/lt-lt/office_strings.js +1 -0
  209. xlwings_server/static/vendor/@microsoft/office-js/dist/lv-lv/office_strings.js +1 -0
  210. xlwings_server/static/vendor/@microsoft/office-js/dist/mk-mk/office_strings.js +8 -0
  211. xlwings_server/static/vendor/@microsoft/office-js/dist/ml-in/office_strings.js +1 -0
  212. xlwings_server/static/vendor/@microsoft/office-js/dist/mn-mn/office_strings.js +8 -0
  213. xlwings_server/static/vendor/@microsoft/office-js/dist/mr-in/office_strings.js +1 -0
  214. xlwings_server/static/vendor/@microsoft/office-js/dist/ms-bn/office_strings.js +8 -0
  215. xlwings_server/static/vendor/@microsoft/office-js/dist/ms-my/office_strings.js +1 -0
  216. xlwings_server/static/vendor/@microsoft/office-js/dist/mt-mt/office_strings.js +8 -0
  217. xlwings_server/static/vendor/@microsoft/office-js/dist/nb-no/office_strings.js +1 -0
  218. xlwings_server/static/vendor/@microsoft/office-js/dist/ne-np/office_strings.js +8 -0
  219. xlwings_server/static/vendor/@microsoft/office-js/dist/nl-be/office_strings.js +8 -0
  220. xlwings_server/static/vendor/@microsoft/office-js/dist/nl-nl/office_strings.js +1 -0
  221. xlwings_server/static/vendor/@microsoft/office-js/dist/nn-no/office_strings.js +1 -0
  222. xlwings_server/static/vendor/@microsoft/office-js/dist/o15apptofilemappingtable.js +11 -0
  223. xlwings_server/static/vendor/@microsoft/office-js/dist/office-vsdoc.js +28596 -0
  224. xlwings_server/static/vendor/@microsoft/office-js/dist/office.js +84 -0
  225. xlwings_server/static/vendor/@microsoft/office-js/dist/pl-pl/office_strings.js +1 -0
  226. xlwings_server/static/vendor/@microsoft/office-js/dist/pt-br/office_strings.js +1 -0
  227. xlwings_server/static/vendor/@microsoft/office-js/dist/pt-pt/office_strings.js +1 -0
  228. xlwings_server/static/vendor/@microsoft/office-js/dist/ro-ro/office_strings.js +1 -0
  229. xlwings_server/static/vendor/@microsoft/office-js/dist/ru-ru/office_strings.js +1 -0
  230. xlwings_server/static/vendor/@microsoft/office-js/dist/si-lk/office_strings.js +8 -0
  231. xlwings_server/static/vendor/@microsoft/office-js/dist/sk-sk/office_strings.js +1 -0
  232. xlwings_server/static/vendor/@microsoft/office-js/dist/sl-si/office_strings.js +1 -0
  233. xlwings_server/static/vendor/@microsoft/office-js/dist/sq-al/office_strings.js +8 -0
  234. xlwings_server/static/vendor/@microsoft/office-js/dist/sr-cyrl-cs/office_strings.js +1 -0
  235. xlwings_server/static/vendor/@microsoft/office-js/dist/sr-cyrl-rs/office_strings.js +1 -0
  236. xlwings_server/static/vendor/@microsoft/office-js/dist/sr-latn-cs/office_strings.js +1 -0
  237. xlwings_server/static/vendor/@microsoft/office-js/dist/sr-latn-rs/office_strings.js +1 -0
  238. xlwings_server/static/vendor/@microsoft/office-js/dist/sv-fi/office_strings.js +8 -0
  239. xlwings_server/static/vendor/@microsoft/office-js/dist/sv-se/office_strings.js +1 -0
  240. xlwings_server/static/vendor/@microsoft/office-js/dist/sw-ke/office_strings.js +1 -0
  241. xlwings_server/static/vendor/@microsoft/office-js/dist/ta-in/office_strings.js +1 -0
  242. xlwings_server/static/vendor/@microsoft/office-js/dist/te-in/office_strings.js +1 -0
  243. xlwings_server/static/vendor/@microsoft/office-js/dist/telemetry/oteljs.js +1 -0
  244. xlwings_server/static/vendor/@microsoft/office-js/dist/telemetry/oteljs_agave.js +1 -0
  245. xlwings_server/static/vendor/@microsoft/office-js/dist/th-th/office_strings.js +1 -0
  246. xlwings_server/static/vendor/@microsoft/office-js/dist/tr-tr/office_strings.js +1 -0
  247. xlwings_server/static/vendor/@microsoft/office-js/dist/uk-ua/office_strings.js +1 -0
  248. xlwings_server/static/vendor/@microsoft/office-js/dist/ur-pk/office_strings.js +1 -0
  249. xlwings_server/static/vendor/@microsoft/office-js/dist/vi-vn/office_strings.js +1 -0
  250. xlwings_server/static/vendor/@microsoft/office-js/dist/webauth/webauth.browserauth.js +77 -0
  251. xlwings_server/static/vendor/@microsoft/office-js/dist/webauth/webauth.implicit.js +35 -0
  252. xlwings_server/static/vendor/@microsoft/office-js/dist/zh-cn/office_strings.js +1 -0
  253. xlwings_server/static/vendor/@microsoft/office-js/dist/zh-hk/office_strings.js +8 -0
  254. xlwings_server/static/vendor/@microsoft/office-js/dist/zh-mo/office_strings.js +8 -0
  255. xlwings_server/static/vendor/@microsoft/office-js/dist/zh-sg/office_strings.js +8 -0
  256. xlwings_server/static/vendor/@microsoft/office-js/dist/zh-tw/office_strings.js +1 -0
  257. xlwings_server/static/vendor/axios/dist/axios.min.js +3 -0
  258. xlwings_server/static/vendor/axios/dist/axios.min.js.map +1 -0
  259. xlwings_server/static/vendor/bootstrap/LICENSE +21 -0
  260. xlwings_server/static/vendor/bootstrap/dist/js/bootstrap.bundle.min.js +7 -0
  261. xlwings_server/static/vendor/bootstrap/dist/js/bootstrap.bundle.min.js.map +1 -0
  262. xlwings_server/static/vendor/bootstrap-xlwings/dist/bootstrap-xlwings.min.css +12 -0
  263. xlwings_server/static/vendor/bootstrap-xlwings/dist/bootstrap-xlwings.min.css.map +1 -0
  264. xlwings_server/static/vendor/htmx-ext-head-support/head-support.js +144 -0
  265. xlwings_server/static/vendor/htmx-ext-loading-states/loading-states.js +184 -0
  266. xlwings_server/static/vendor/htmx.org/LICENSE +13 -0
  267. xlwings_server/static/vendor/htmx.org/dist/htmx.min.js +1 -0
  268. xlwings_server/static/vendor/socket.io/LICENSE +22 -0
  269. xlwings_server/static/vendor/socket.io/client-dist/socket.io.min.js +7 -0
  270. xlwings_server/static/vendor/socket.io/client-dist/socket.io.min.js.map +1 -0
  271. xlwings_server/templates/_book.html +8 -0
  272. xlwings_server/templates/alert_base.html +16 -0
  273. xlwings_server/templates/base.html +117 -0
  274. xlwings_server/templates/examples/alpine/README.md +26 -0
  275. xlwings_server/templates/examples/alpine/taskpane.html +47 -0
  276. xlwings_server/templates/examples/auth/README.md +38 -0
  277. xlwings_server/templates/examples/auth/protected.html +8 -0
  278. xlwings_server/templates/examples/auth/public.html +11 -0
  279. xlwings_server/templates/examples/excel_object_model/README.md +49 -0
  280. xlwings_server/templates/examples/excel_object_model/add_name_form.html +27 -0
  281. xlwings_server/templates/examples/hello_world/README.md +9 -0
  282. xlwings_server/templates/examples/hello_world/taskpane_hello.html +24 -0
  283. xlwings_server/templates/examples/htmx_form/README.md +44 -0
  284. xlwings_server/templates/examples/htmx_form/_greeting.html +6 -0
  285. xlwings_server/templates/examples/htmx_form/taskpane_htmx_form.html +21 -0
  286. xlwings_server/templates/examples/live_form_validation/README.md +60 -0
  287. xlwings_server/templates/examples/live_form_validation/add_name_form.html +33 -0
  288. xlwings_server/templates/examples/multi_app/README.md +34 -0
  289. xlwings_server/templates/examples/multi_app/taskpane1.html +7 -0
  290. xlwings_server/templates/examples/multi_app/taskpane2.html +7 -0
  291. xlwings_server/templates/examples/multi_app/taskpane_loader.html +5 -0
  292. xlwings_server/templates/examples/navigation/README.md +28 -0
  293. xlwings_server/templates/examples/navigation/_navigation.html +16 -0
  294. xlwings_server/templates/examples/navigation/taskpane_one.html +8 -0
  295. xlwings_server/templates/examples/navigation/taskpane_three.html +8 -0
  296. xlwings_server/templates/examples/navigation/taskpane_two.html +8 -0
  297. xlwings_server/templates/examples/pictures/README.md +42 -0
  298. xlwings_server/templates/examples/pictures/_picture.html +4 -0
  299. xlwings_server/templates/examples/pictures/taskpane_pictures.html +26 -0
  300. xlwings_server/templates/manifest.xml +155 -0
  301. xlwings_server/templates/taskpane.html +1 -0
  302. xlwings_server/templates/xlwings_alert.html +27 -0
  303. xlwings_server/templates.py +61 -0
  304. xlwings_server/utils.py +32 -0
  305. xlwings_server/wasm/__init__.py +0 -0
  306. xlwings_server/wasm/config.py +24 -0
  307. xlwings_server/wasm/main.py +236 -0
  308. xlwings_server/wasm/requirements.txt +5 -0
  309. xlwings_server-1.1.0.dist-info/METADATA +61 -0
  310. xlwings_server-1.1.0.dist-info/RECORD +313 -0
  311. xlwings_server-1.1.0.dist-info/WHEEL +4 -0
  312. xlwings_server-1.1.0.dist-info/entry_points.txt +2 -0
  313. xlwings_server-1.1.0.dist-info/licenses/LICENSE.md +223 -0
@@ -0,0 +1,16 @@
1
+ import logging
2
+
3
+ from fastapi import APIRouter
4
+
5
+ from ..config import settings
6
+
7
+ router = APIRouter(prefix=settings.app_path)
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ # Endpoints
13
+ @router.get("/")
14
+ async def root():
15
+ # This endpoint could be used for a health check
16
+ return {"status": "ok"}
@@ -0,0 +1,69 @@
1
+ import logging
2
+
3
+ import socketio
4
+ import xlwings as xw
5
+
6
+ # Try to import custom modules from project directory first (CLI/Azure mode)
7
+ # Fall back to package location (tests/package mode)
8
+ try:
9
+ import custom_functions
10
+ except ModuleNotFoundError:
11
+ import xlwings_server.custom_functions as custom_functions
12
+
13
+ from xlwings_server.config import PROJECT_DIR, settings
14
+ from xlwings_server.dependencies import authenticate
15
+ from xlwings_server.models import CurrentUser
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+ if settings.socketio_message_queue_url:
20
+ client_manager = socketio.AsyncRedisManager(
21
+ settings.socketio_message_queue_url, write_only=not settings.socketio_server_app
22
+ )
23
+ else:
24
+ client_manager = None
25
+
26
+
27
+ sio = socketio.AsyncServer(
28
+ async_mode="asgi",
29
+ client_manager=client_manager,
30
+ cors_allowed_origins=(
31
+ settings.cors_allow_origins[0]
32
+ if len(settings.cors_allow_origins) == 1
33
+ else settings.cors_allow_origins
34
+ ),
35
+ )
36
+
37
+
38
+ @sio.on("connect")
39
+ async def connect(sid, environ, auth):
40
+ if settings.environment == "dev" and settings.enable_hotreload:
41
+ from .. import hotreload
42
+
43
+ logging.getLogger("watchfiles").setLevel(logging.ERROR)
44
+ await hotreload.start_browser_reload_watcher(sio=sio, directory=PROJECT_DIR)
45
+ token_string = auth.get("token")
46
+ provider = auth.get("provider")
47
+ try:
48
+ current_user = await authenticate(token_string, auth_provider=provider)
49
+ await sio.save_session(sid, {"current_user": current_user})
50
+ logger.info(f"Socket.io: connect {sid}")
51
+ logger.info(f"Socket.io: User authenticated {current_user.name}")
52
+ except Exception as e:
53
+ logger.info(f"Socket.io: authentication failed for sid {sid}: {repr(e)}")
54
+ await sio.disconnect(sid)
55
+
56
+
57
+ @sio.on("disconnect")
58
+ async def disconnect(sid):
59
+ await xw.server.sio_disconnect(sid)
60
+
61
+
62
+ @sio.on("xlwings:function-call")
63
+ async def sio_function_call(sid, data):
64
+ session = await sio.get_session(sid)
65
+ current_user = session["current_user"]
66
+ logger.info(f"""Function "{data['func_name']}" called by {current_user.name}""")
67
+ await xw.server.sio_custom_function_call(
68
+ sid, data, custom_functions, current_user, sio, {CurrentUser: current_user}
69
+ )
@@ -0,0 +1,12 @@
1
+ from fastapi import APIRouter, Request
2
+
3
+ from ..config import settings
4
+ from ..templates import TemplateResponse
5
+
6
+ router = APIRouter(prefix=settings.app_path)
7
+
8
+
9
+ @router.get("/taskpane")
10
+ @router.get("/taskpane.html")
11
+ async def taskpane(request: Request):
12
+ return TemplateResponse(request=request, name=settings.taskpane_html)
@@ -0,0 +1,197 @@
1
+ import contextvars
2
+ import inspect
3
+ import logging
4
+ from pathlib import Path
5
+ from textwrap import dedent
6
+
7
+ import xlwings as xw
8
+ import xlwings.server
9
+ from fastapi import APIRouter, Body, Header, Request, Response
10
+
11
+ # Try to import custom modules from project directory first (CLI/Azure mode)
12
+ # Fall back to package location (tests/package mode)
13
+ try:
14
+ import custom_functions
15
+ except ModuleNotFoundError:
16
+ import xlwings_server.custom_functions as custom_functions
17
+
18
+ try:
19
+ import custom_scripts
20
+ except ModuleNotFoundError:
21
+ import xlwings_server.custom_scripts as custom_scripts
22
+
23
+ from xlwings_server import dependencies as dep
24
+ from xlwings_server.config import PACKAGE_DIR, settings
25
+ from xlwings_server.models import CurrentUser
26
+ from xlwings_server.templates import TemplateResponse
27
+
28
+ logger = logging.getLogger(__name__)
29
+
30
+ router = APIRouter(prefix=f"{settings.app_path}/xlwings")
31
+
32
+
33
+ def sanitize_log_input(input_string: str) -> str:
34
+ """Replaces newline and carriage return characters to prevent log injection."""
35
+ if not isinstance(input_string, str):
36
+ input_string = str(input_string)
37
+ return input_string.replace("\n", "\\n").replace("\r", "\\r")
38
+
39
+
40
+ @router.get("/alert")
41
+ async def alert(
42
+ request: Request, prompt: str, title: str, buttons: str, mode: str, callback: str
43
+ ):
44
+ """Boilerplate required by book.app.alert() and to show unhandled exceptions"""
45
+ return TemplateResponse(
46
+ request=request,
47
+ name="xlwings_alert.html",
48
+ context={
49
+ "prompt": prompt,
50
+ "title": title,
51
+ "buttons": buttons,
52
+ "mode": mode,
53
+ "callback": callback,
54
+ "settings": settings,
55
+ },
56
+ )
57
+
58
+
59
+ @router.get("/custom-functions-meta")
60
+ @router.get("/custom-functions-meta.json")
61
+ async def custom_functions_meta():
62
+ return xlwings.server.custom_functions_meta(
63
+ custom_functions, typehinted_params_to_exclude=[CurrentUser]
64
+ )
65
+
66
+
67
+ @router.get("/custom-functions-code")
68
+ @router.get("/custom-functions-code.js")
69
+ async def custom_functions_code():
70
+ custom_functions_call_path = f"{settings.app_path}/xlwings/custom-functions-call"
71
+ js = (
72
+ PACKAGE_DIR / "static" / "js" / "core" / "custom-functions-code.js"
73
+ ).read_text()
74
+ # format string would require to double all curly braces
75
+ js = js.replace("placeholder_xlwings_version", xw.__version__).replace(
76
+ "placeholder_custom_functions_call_path", custom_functions_call_path
77
+ )
78
+ for name, obj in inspect.getmembers(custom_functions):
79
+ if hasattr(obj, "__xlfunc__"):
80
+ xlfunc = obj.__xlfunc__
81
+ func_name = xlfunc["name"]
82
+ streaming = "true" if inspect.isasyncgenfunction(obj) else "false"
83
+ js += dedent(
84
+ f"""\
85
+ async function {func_name}() {{
86
+ let args = ["{func_name}", {streaming}]
87
+ args.push.apply(args, arguments);
88
+ return await base.apply(null, args);
89
+ }}
90
+ CustomFunctions.associate("{func_name.upper()}", {func_name});
91
+ """
92
+ )
93
+ return Response(
94
+ content=js,
95
+ media_type="text/javascript",
96
+ )
97
+
98
+
99
+ # ContextVars
100
+ socketio_id_context = contextvars.ContextVar("socketio_id_context")
101
+ caller_address_context = contextvars.ContextVar("caller_address_context")
102
+ redis_client_context = contextvars.ContextVar("redis_client_context")
103
+
104
+
105
+ @router.post("/custom-functions-call")
106
+ async def custom_functions_call(
107
+ current_user: dep.User,
108
+ redis_client: dep.RedisClient,
109
+ data: dict = Body,
110
+ sid: str | None = Header(default=None),
111
+ ):
112
+ # Replace newline and carriage return characters to prevent log injection
113
+ safe_func_name = sanitize_log_input(data["func_name"])
114
+ safe_user_name = sanitize_log_input(current_user.name)
115
+ logger.info(f"""Function "{safe_func_name}" called by {safe_user_name}""")
116
+ socketio_id_context.set(sid) # For utils.trigger_script()
117
+ caller_address_context.set(data["caller_address"]) # For ObjectCache converter
118
+ redis_client_context.set(redis_client) # For ObjectCache converter
119
+
120
+ rv = await xlwings.server.custom_functions_call(
121
+ data,
122
+ custom_functions,
123
+ current_user,
124
+ typehint_to_value={CurrentUser: current_user},
125
+ )
126
+ return {"result": rv}
127
+
128
+
129
+ @router.post("/custom-scripts-call/{script_name}")
130
+ async def custom_scripts_call(script_name: str, book: dep.Book, current_user: dep.User):
131
+ # Replace newline and carriage return characters to prevent log injection
132
+ safe_script_name = sanitize_log_input(script_name)
133
+ safe_user_name = sanitize_log_input(current_user.name)
134
+ logger.info(f"""Script "{safe_script_name}" called by {safe_user_name}""")
135
+ book = await xlwings.server.custom_scripts_call(
136
+ custom_scripts,
137
+ script_name,
138
+ current_user,
139
+ typehint_to_value={CurrentUser: current_user, xw.Book: book},
140
+ )
141
+ return book.json()
142
+
143
+
144
+ @router.get("/custom-scripts-meta")
145
+ @router.get("/custom-scripts-meta.json")
146
+ async def custom_scripts_meta():
147
+ return xlwings.server.custom_scripts_meta(custom_scripts)
148
+
149
+
150
+ if settings.enable_wasm:
151
+
152
+ @router.get("/pyodide.json")
153
+ async def get_pyodide_config():
154
+ # requirements.txt
155
+ packages = (
156
+ Path(settings.project_dir / "wasm" / "requirements.txt")
157
+ .read_text()
158
+ .splitlines()
159
+ )
160
+ packages = [
161
+ pkg.replace("/static", settings.static_url_path).strip()
162
+ for pkg in packages
163
+ if pkg.strip()
164
+ ]
165
+
166
+ # Files
167
+ def scan_directory(
168
+ base_dir: Path, dir_name: str, prepend_dir_name: bool = False
169
+ ) -> dict:
170
+ dir_path = Path(settings.project_dir / dir_name)
171
+ files = {}
172
+ if dir_path.exists():
173
+ for file_path in dir_path.rglob("*"):
174
+ if (
175
+ file_path.is_file()
176
+ and file_path.suffix != ".pyc"
177
+ and file_path.name != "requirements.txt"
178
+ ):
179
+ relative_path = file_path.relative_to(dir_path)
180
+ files[
181
+ f"{settings.static_url_path.replace('static', dir_name)}/{relative_path}"
182
+ ] = (
183
+ f"./{dir_name}/{relative_path}"
184
+ if prepend_dir_name
185
+ else f"./{relative_path}"
186
+ )
187
+ return files
188
+
189
+ # Scan all directories
190
+ files = {}
191
+ files.update(scan_directory(settings.project_dir, "wasm"))
192
+ for directory in ["custom_functions", "custom_scripts"]:
193
+ files.update(
194
+ scan_directory(settings.project_dir, directory, prepend_dir_name=True)
195
+ )
196
+ response = {"packages": packages, "files": files}
197
+ return response
@@ -0,0 +1,53 @@
1
+ {
2
+ "last_update_utc": "2024-09-02 21:54:45",
3
+ "headers": [
4
+ {
5
+ "name": "Cache-Control",
6
+ "value": "no-store, max-age=0"
7
+ },
8
+ {
9
+ "name": "Clear-Site-Data",
10
+ "value": "\"cache\",\"cookies\",\"storage\""
11
+ },
12
+ {
13
+ "name": "Content-Security-Policy",
14
+ "value": "default-src 'self'; form-action 'self'; object-src 'none'; frame-ancestors 'none'; upgrade-insecure-requests; block-all-mixed-content"
15
+ },
16
+ {
17
+ "name": "Cross-Origin-Embedder-Policy",
18
+ "value": "require-corp"
19
+ },
20
+ {
21
+ "name": "Cross-Origin-Opener-Policy",
22
+ "value": "same-origin"
23
+ },
24
+ {
25
+ "name": "Cross-Origin-Resource-Policy",
26
+ "value": "same-origin"
27
+ },
28
+ {
29
+ "name": "Permissions-Policy",
30
+ "value": "accelerometer=(), autoplay=(), camera=(), cross-origin-isolated=(), display-capture=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(self), usb=(), web-share=(), xr-spatial-tracking=(), clipboard-read=(), clipboard-write=(), gamepad=(), hid=(), idle-detection=(), interest-cohort=(), serial=(), unload=()"
31
+ },
32
+ {
33
+ "name": "Referrer-Policy",
34
+ "value": "no-referrer"
35
+ },
36
+ {
37
+ "name": "Strict-Transport-Security",
38
+ "value": "max-age=31536000; includeSubDomains"
39
+ },
40
+ {
41
+ "name": "X-Content-Type-Options",
42
+ "value": "nosniff"
43
+ },
44
+ {
45
+ "name": "X-Frame-Options",
46
+ "value": "deny"
47
+ },
48
+ {
49
+ "name": "X-Permitted-Cross-Domain-Policies",
50
+ "value": "none"
51
+ }
52
+ ]
53
+ }
@@ -0,0 +1,25 @@
1
+ import json
2
+
3
+ from . import (
4
+ default_serializer,
5
+ dictionary_serializer,
6
+ numpy_serializer,
7
+ pandas_serializer,
8
+ )
9
+ from .framework import Serializer, custom_encoder, serializers
10
+
11
+
12
+ def serialize(obj, serializer_name="default"):
13
+ serializer = serializers.get(type(obj), serializers.get(serializer_name))
14
+ if serializer is None:
15
+ raise ValueError(f"No serializer registered for object of type {type(obj)}")
16
+ return json.dumps(serializer.serialize(obj), default=custom_encoder)
17
+
18
+
19
+ def deserialize(payload, serializer_name="default"):
20
+ payload = json.loads(payload)
21
+ serializer_name = payload.get("serializer", serializer_name)
22
+ serializer = serializers.get(serializer_name)
23
+ if serializer is None:
24
+ raise ValueError(f"No serializer registered with name '{serializer_name}'")
25
+ return serializer.deserialize(payload)
@@ -0,0 +1,19 @@
1
+ from .framework import Serializer, custom_decoder
2
+
3
+
4
+ class DefaultSerializer(Serializer):
5
+ name = "default"
6
+
7
+ @classmethod
8
+ def serialize(cls, obj):
9
+ return {
10
+ "data": obj,
11
+ "serializer": cls.name,
12
+ }
13
+
14
+ @classmethod
15
+ def deserialize(cls, payload):
16
+ return custom_decoder(payload["data"])
17
+
18
+
19
+ DefaultSerializer.register()
@@ -0,0 +1,25 @@
1
+ from .framework import Serializer, custom_decoder
2
+
3
+
4
+ class DictionarySerializer(Serializer):
5
+ name = "custom_dict_serializer"
6
+
7
+ @classmethod
8
+ def serialize(cls, obj):
9
+ # Convert dictionary with non-string keys (e.g., datetime) to a list of
10
+ # [key, value] pairs
11
+ items = [[k, v] for k, v in obj.items()]
12
+ return {
13
+ "data": items,
14
+ "serializer": cls.name,
15
+ }
16
+
17
+ @classmethod
18
+ def deserialize(cls, payload):
19
+ # Convert back from list of pairs to dictionary
20
+ items = payload["data"]
21
+ return {custom_decoder(k): custom_decoder(v) for k, v in items}
22
+
23
+
24
+ # Register the serializer for dict type
25
+ DictionarySerializer.register(dict)
@@ -0,0 +1,50 @@
1
+ import datetime as dt
2
+
3
+ # Registry, holding type or serializer_name vs. serializer combinations
4
+ serializers = {}
5
+
6
+
7
+ # Base class
8
+ class Serializer:
9
+ @classmethod
10
+ def serialize(cls, obj):
11
+ raise NotImplementedError()
12
+
13
+ @classmethod
14
+ def deserialize(cls, payload):
15
+ raise NotImplementedError()
16
+
17
+ @classmethod
18
+ def register(cls, *types):
19
+ serializers[cls.name] = cls
20
+ for type in types:
21
+ serializers[type] = cls
22
+
23
+
24
+ # Custom encoders/decoders
25
+ def custom_encoder(obj):
26
+ if isinstance(obj, dt.datetime):
27
+ return obj.isoformat()
28
+ valid_types = tuple(cls for cls in serializers.keys() if isinstance(cls, type))
29
+ if isinstance(obj, valid_types):
30
+ serializer = serializers.get(type(obj))
31
+ if serializer:
32
+ return serializer.serialize(obj)
33
+ raise TypeError(f"Object of type {type(obj)} is not JSON serializable")
34
+
35
+
36
+ def custom_decoder(obj):
37
+ if isinstance(obj, list):
38
+ return [custom_decoder(item) for item in obj]
39
+ elif isinstance(obj, dict):
40
+ serializer = serializers.get(obj.get("serializer"))
41
+ if serializer:
42
+ return serializer.deserialize(obj)
43
+ return {key: custom_decoder(value) for key, value in obj.items()}
44
+ elif isinstance(obj, str):
45
+ try:
46
+ return dt.datetime.fromisoformat(obj)
47
+ except ValueError:
48
+ return obj
49
+ else:
50
+ return obj
@@ -0,0 +1,26 @@
1
+ try:
2
+ import numpy as np
3
+ except ImportError:
4
+ np = None
5
+
6
+ from .framework import Serializer
7
+
8
+ if np:
9
+
10
+ class NumpyArraySerializer(Serializer):
11
+ name = "np.array"
12
+
13
+ @classmethod
14
+ def serialize(cls, arr: np.ndarray):
15
+ return {
16
+ "serializer": cls.name,
17
+ "data": arr.tolist(),
18
+ "dtype": str(arr.dtype),
19
+ }
20
+
21
+ @classmethod
22
+ def deserialize(cls, payload):
23
+ arr = np.array(payload["data"], dtype=payload["dtype"])
24
+ return arr
25
+
26
+ NumpyArraySerializer.register(np.array, np.ndarray)
@@ -0,0 +1,95 @@
1
+ import uuid
2
+ from io import StringIO
3
+
4
+ try:
5
+ import pandas as pd
6
+ except ImportError:
7
+ pd = None
8
+
9
+ from .framework import Serializer
10
+
11
+ if pd:
12
+
13
+ class PandasDataFrameSerializer(Serializer):
14
+ name = "pd.DataFrame"
15
+
16
+ @classmethod
17
+ def serialize(cls, df):
18
+ serialized = {"serializer": cls.name}
19
+
20
+ if isinstance(df.index, pd.MultiIndex):
21
+ df = df.copy()
22
+ index_names = df.index.names
23
+ # Index names are often None
24
+ temp_names = [
25
+ f"_idx_{uuid.uuid4().hex[:8]}" for _ in range(len(df.index.names))
26
+ ]
27
+ index_mapping = {
28
+ temp: orig for temp, orig in zip(temp_names, index_names)
29
+ }
30
+ df.index.names = temp_names
31
+ df = df.reset_index()
32
+ serialized.update(
33
+ {
34
+ "is_multi_index": True,
35
+ "index_mapping": index_mapping,
36
+ }
37
+ )
38
+
39
+ serialized.update(
40
+ {
41
+ "serializer": cls.name,
42
+ "data": df.to_json(date_format="iso"),
43
+ "dtypes": {col: str(dtype) for col, dtype in df.dtypes.items()},
44
+ }
45
+ )
46
+
47
+ # Preserve DatetimeIndex frequency if it exists
48
+ if isinstance(df.index, pd.DatetimeIndex) and df.index.freq is not None:
49
+ serialized["index_freq"] = df.index.freq.freqstr
50
+
51
+ return serialized
52
+
53
+ @classmethod
54
+ def deserialize(cls, payload):
55
+ df = pd.read_json(StringIO(payload["data"]))
56
+
57
+ # Standard column type conversion
58
+ for col, dtype in payload["dtypes"].items():
59
+ df[col] = df[col].astype(dtype)
60
+
61
+ # Handle MultiIndex reconstruction
62
+ if payload.get("is_multi_index"):
63
+ index_mapping = payload["index_mapping"]
64
+ # Convert temporary columns back to index with original names
65
+ index_cols = list(index_mapping.keys())
66
+ df = df.set_index(index_cols)
67
+ # Restore original index names
68
+ df.index.names = list(index_mapping.values())
69
+
70
+ # Restore DatetimeIndex frequency if it was saved
71
+ if isinstance(df.index, pd.DatetimeIndex) and "index_freq" in payload:
72
+ df.index.freq = pd.tseries.frequencies.to_offset(payload["index_freq"])
73
+
74
+ return df
75
+
76
+ PandasDataFrameSerializer.register(pd.DataFrame)
77
+
78
+ class PandasSeriesSerializer(Serializer):
79
+ name = "pd.Series"
80
+
81
+ @classmethod
82
+ def serialize(cls, series):
83
+ return {
84
+ "serializer": cls.name,
85
+ "data": series.to_json(date_format="iso"),
86
+ "dtype": str(series.dtype),
87
+ }
88
+
89
+ @classmethod
90
+ def deserialize(cls, payload):
91
+ series = pd.read_json(StringIO(payload["data"]), typ="series")
92
+ series = series.astype(payload["dtype"])
93
+ return series
94
+
95
+ PandasSeriesSerializer.register(pd.Series)
@@ -0,0 +1,28 @@
1
+ /**
2
+ * These are styles required by core functionality of xlwings Server.
3
+ * For your own CSS, use style.css instead.
4
+ */
5
+
6
+ /* htmx IndicatorStyles */
7
+ .htmx-indicator {
8
+ opacity: 0;
9
+ }
10
+ .htmx-request .htmx-indicator {
11
+ opacity: 1;
12
+ transition: opacity 200ms ease-in;
13
+ }
14
+ .htmx-request.htmx-indicator {
15
+ opacity: 1;
16
+ transition: opacity 200ms ease-in;
17
+ }
18
+
19
+ /* Alpine.js */
20
+ [x-cloak] {
21
+ /* https://alpinejs.dev/directives/cloak */
22
+ display: none !important;
23
+ }
24
+
25
+ /* Custom */
26
+ .z-index-1000 {
27
+ z-index: 1000;
28
+ }
File without changes
Binary file
@@ -0,0 +1,13 @@
1
+ globalThis.getAuth = async function () {
2
+ if (config.authProviders.includes("entraid")) {
3
+ const token = await xlwings.getAccessToken();
4
+ return {
5
+ token: token,
6
+ provider: "entraid",
7
+ };
8
+ }
9
+ return {
10
+ token: "",
11
+ provider: "",
12
+ };
13
+ };
@@ -0,0 +1,4 @@
1
+ // Config
2
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#embedding_data_in_html
3
+ const configElement = document.getElementById("config");
4
+ const config = configElement ? JSON.parse(configElement.textContent) : null;
@@ -0,0 +1,11 @@
1
+ const alpineComponents = {};
2
+
3
+ document.addEventListener("alpine:init", () => {
4
+ for (let name in alpineComponents) {
5
+ Alpine.data(name, () => alpineComponents[name]);
6
+ }
7
+ });
8
+
9
+ function registerAlpineComponent(name, obj) {
10
+ alpineComponents[name] = obj;
11
+ }
@@ -0,0 +1,7 @@
1
+ // Alerts
2
+ document.body.addEventListener("close.bs.alert", function (event) {
3
+ // Prevents alerts from being removed from the DOM when closed so they can be reused
4
+ event.preventDefault();
5
+ event.target.classList.add("d-none");
6
+ return false;
7
+ });