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.
- xlwings_server/.env.template +145 -0
- xlwings_server/__init__.py +12 -0
- xlwings_server/_version.py +34 -0
- xlwings_server/auth/__init__.py +0 -0
- xlwings_server/auth/custom/__init__.py +26 -0
- xlwings_server/auth/entraid/__init__.py +131 -0
- xlwings_server/auth/entraid/jwks.py +10 -0
- xlwings_server/azure_functions_templates/.funcignore +28 -0
- xlwings_server/azure_functions_templates/function_app.py +28 -0
- xlwings_server/azure_functions_templates/host.json +22 -0
- xlwings_server/azure_functions_templates/local.settings.json +8 -0
- xlwings_server/build_utils/__init__.py +9 -0
- xlwings_server/build_utils/static_file_hasher.py +212 -0
- xlwings_server/cli.py +1592 -0
- xlwings_server/config.py +228 -0
- xlwings_server/custom_functions/__init__.py +8 -0
- xlwings_server/custom_functions/examples.py +177 -0
- xlwings_server/custom_scripts/__init__.py +8 -0
- xlwings_server/custom_scripts/examples.py +94 -0
- xlwings_server/databases.py +19 -0
- xlwings_server/dependencies.py +126 -0
- xlwings_server/docker_templates/.dockerignore +15 -0
- xlwings_server/docker_templates/Dockerfile +60 -0
- xlwings_server/docker_templates/docker-compose.yaml +32 -0
- xlwings_server/hotreload.py +59 -0
- xlwings_server/main.py +242 -0
- xlwings_server/models/__init__.py +14 -0
- xlwings_server/models/user.py +53 -0
- xlwings_server/object_handles.py +142 -0
- xlwings_server/routers/__init__.py +0 -0
- xlwings_server/routers/manifest.py +82 -0
- xlwings_server/routers/root.py +16 -0
- xlwings_server/routers/socketio.py +69 -0
- xlwings_server/routers/taskpane.py +12 -0
- xlwings_server/routers/xlwings.py +197 -0
- xlwings_server/security_headers.json +53 -0
- xlwings_server/serializers/__init__.py +25 -0
- xlwings_server/serializers/default_serializer.py +19 -0
- xlwings_server/serializers/dictionary_serializer.py +25 -0
- xlwings_server/serializers/framework.py +50 -0
- xlwings_server/serializers/numpy_serializer.py +26 -0
- xlwings_server/serializers/pandas_serializer.py +95 -0
- xlwings_server/static/css/core.css +28 -0
- xlwings_server/static/css/style.css +0 -0
- xlwings_server/static/images/favicon.png +0 -0
- xlwings_server/static/images/xlwings-16.png +0 -0
- xlwings_server/static/images/xlwings-32.png +0 -0
- xlwings_server/static/images/xlwings-64.png +0 -0
- xlwings_server/static/images/xlwings-80.png +0 -0
- xlwings_server/static/js/auth.js +13 -0
- xlwings_server/static/js/config.js +4 -0
- xlwings_server/static/js/core/alpinejs-csp-boilerplate.js +11 -0
- xlwings_server/static/js/core/bootstrap-customizations.js +7 -0
- xlwings_server/static/js/core/custom-functions-code.js +296 -0
- xlwings_server/static/js/core/examples.js +62 -0
- xlwings_server/static/js/core/hotreload.js +3 -0
- xlwings_server/static/js/core/htmx-handlers.js +86 -0
- xlwings_server/static/js/core/officejs-history-fix-part1.js +3 -0
- xlwings_server/static/js/core/officejs-history-fix-part2.js +2 -0
- xlwings_server/static/js/core/reload-custom-functions.js +79 -0
- xlwings_server/static/js/core/socketio-handlers.js +34 -0
- xlwings_server/static/js/core/xlwings-alert.js +22 -0
- xlwings_server/static/js/core/xlwingsjs/alert.js +85 -0
- xlwings_server/static/js/core/xlwingsjs/auth.js +63 -0
- xlwings_server/static/js/core/xlwingsjs/sheet-buttons.js +133 -0
- xlwings_server/static/js/core/xlwingsjs/utils.js +119 -0
- xlwings_server/static/js/core/xlwingsjs/wasm.js +131 -0
- xlwings_server/static/js/core/xlwingsjs/xlwings.js +1060 -0
- xlwings_server/static/js/main.js +0 -0
- xlwings_server/static/js/ribbon.js +17 -0
- xlwings_server/static/vendor/@alpinejs/LICENSE +21 -0
- xlwings_server/static/vendor/@alpinejs/csp/dist/cdn.min.js +7 -0
- xlwings_server/static/vendor/@microsoft/office-js/LICENSE.md +76 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/af-za/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/agaveerrorux.js +18 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/agavedefaulticon32x32.png +0 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/agavedefaulticon96x96.png +0 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/businessbarclose_16x16x32.png +0 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/dropdownarrow_16x16x32.png +0 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/ellipsis_16x16x32.png +0 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/miniinfoblue_16x16x32.png +0 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/moe_default_icon.png +0 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/moe_status_icons.png +0 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/office.png +0 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/images/refresh_16x16x32.png +0 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/index.html +16 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/agaveerrorux/style/agaveerrorux.css +482 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/am-et/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ar-ae/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ar-bh/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ar-dz/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ar-eg/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ar-iq/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ar-jo/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ar-kw/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ar-lb/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ar-ly/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ar-ma/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ar-om/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ar-qa/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ar-sa/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ar-sy/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ar-tn/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ar-ye/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ariatelemetry/aria-web-telemetry-2.8.0.min.js +2 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ariatelemetry/aria-web-telemetry-2.9.0.min.js +2 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ariatelemetry/aria-web-telemetry.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/az-latn-az/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/be-by/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/bg-bg/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/bn-in/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/bs-latn-ba/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ca-es/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/cs-cz/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/cy-gb/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/da-dk/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/de-at/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/de-ch/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/de-de/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/de-li/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/de-lu/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/el-gr/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/en-029/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/en-au/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/en-bz/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/en-ca/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/en-gb/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/en-ie/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/en-in/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/en-jm/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/en-my/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/en-nz/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/en-ph/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/en-sg/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/en-tt/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/en-us/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/en-za/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/en-zw/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-ar/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-bo/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-cl/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-co/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-cr/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-do/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-ec/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-es/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-gt/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-hn/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-mx/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-ni/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-pa/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-pe/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-pr/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-py/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-sv/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-us/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-uy/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es-ve/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/es6-promise.js +5 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/et-ee/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/eu-es/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/excel-15.01.js +11 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/excel-15.02.js +11 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/excel-15.js +11 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/excel-mac-16.00-core.js +11 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/excel-mac-16.00.js +25 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/excel-web-16.00-core.js +11 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/excel-web-16.00.js +25 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/excel-win32-16.00.js +19 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/excel-win32-16.01-core.js +11 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/excel-win32-16.01.js +25 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/excel-winrt-16.00.js +25 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/excelios-15.js +11 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/excelwebapp-15.01.js +11 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/excelwebapp-15.02.js +11 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/excelwebapp-15.js +11 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/fa-ir/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/fi-fi/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/fil-ph/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/fr-be/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/fr-ca/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/fr-ch/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/fr-fr/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/fr-lu/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/fr-mc/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ga-ie/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/gl-es/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/gu-in/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/he-il/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/hi-in/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/hr-ba/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/hr-hr/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/html2canvas.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/hu-hu/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/hy-am/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/id-id/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/is-is/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/it-ch/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/it-it/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ja-jp/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ka-ge/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/kk-kz/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/km-kh/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/kn-in/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ko-kr/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/lb-lu/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/lo-la/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/lt-lt/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/lv-lv/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/mk-mk/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ml-in/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/mn-mn/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/mr-in/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ms-bn/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ms-my/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/mt-mt/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/nb-no/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ne-np/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/nl-be/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/nl-nl/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/nn-no/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/o15apptofilemappingtable.js +11 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/office-vsdoc.js +28596 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/office.js +84 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/pl-pl/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/pt-br/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/pt-pt/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ro-ro/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ru-ru/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/si-lk/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/sk-sk/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/sl-si/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/sq-al/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/sr-cyrl-cs/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/sr-cyrl-rs/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/sr-latn-cs/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/sr-latn-rs/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/sv-fi/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/sv-se/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/sw-ke/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ta-in/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/te-in/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/telemetry/oteljs.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/telemetry/oteljs_agave.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/th-th/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/tr-tr/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/uk-ua/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/ur-pk/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/vi-vn/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/webauth/webauth.browserauth.js +77 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/webauth/webauth.implicit.js +35 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/zh-cn/office_strings.js +1 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/zh-hk/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/zh-mo/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/zh-sg/office_strings.js +8 -0
- xlwings_server/static/vendor/@microsoft/office-js/dist/zh-tw/office_strings.js +1 -0
- xlwings_server/static/vendor/axios/dist/axios.min.js +3 -0
- xlwings_server/static/vendor/axios/dist/axios.min.js.map +1 -0
- xlwings_server/static/vendor/bootstrap/LICENSE +21 -0
- xlwings_server/static/vendor/bootstrap/dist/js/bootstrap.bundle.min.js +7 -0
- xlwings_server/static/vendor/bootstrap/dist/js/bootstrap.bundle.min.js.map +1 -0
- xlwings_server/static/vendor/bootstrap-xlwings/dist/bootstrap-xlwings.min.css +12 -0
- xlwings_server/static/vendor/bootstrap-xlwings/dist/bootstrap-xlwings.min.css.map +1 -0
- xlwings_server/static/vendor/htmx-ext-head-support/head-support.js +144 -0
- xlwings_server/static/vendor/htmx-ext-loading-states/loading-states.js +184 -0
- xlwings_server/static/vendor/htmx.org/LICENSE +13 -0
- xlwings_server/static/vendor/htmx.org/dist/htmx.min.js +1 -0
- xlwings_server/static/vendor/socket.io/LICENSE +22 -0
- xlwings_server/static/vendor/socket.io/client-dist/socket.io.min.js +7 -0
- xlwings_server/static/vendor/socket.io/client-dist/socket.io.min.js.map +1 -0
- xlwings_server/templates/_book.html +8 -0
- xlwings_server/templates/alert_base.html +16 -0
- xlwings_server/templates/base.html +117 -0
- xlwings_server/templates/examples/alpine/README.md +26 -0
- xlwings_server/templates/examples/alpine/taskpane.html +47 -0
- xlwings_server/templates/examples/auth/README.md +38 -0
- xlwings_server/templates/examples/auth/protected.html +8 -0
- xlwings_server/templates/examples/auth/public.html +11 -0
- xlwings_server/templates/examples/excel_object_model/README.md +49 -0
- xlwings_server/templates/examples/excel_object_model/add_name_form.html +27 -0
- xlwings_server/templates/examples/hello_world/README.md +9 -0
- xlwings_server/templates/examples/hello_world/taskpane_hello.html +24 -0
- xlwings_server/templates/examples/htmx_form/README.md +44 -0
- xlwings_server/templates/examples/htmx_form/_greeting.html +6 -0
- xlwings_server/templates/examples/htmx_form/taskpane_htmx_form.html +21 -0
- xlwings_server/templates/examples/live_form_validation/README.md +60 -0
- xlwings_server/templates/examples/live_form_validation/add_name_form.html +33 -0
- xlwings_server/templates/examples/multi_app/README.md +34 -0
- xlwings_server/templates/examples/multi_app/taskpane1.html +7 -0
- xlwings_server/templates/examples/multi_app/taskpane2.html +7 -0
- xlwings_server/templates/examples/multi_app/taskpane_loader.html +5 -0
- xlwings_server/templates/examples/navigation/README.md +28 -0
- xlwings_server/templates/examples/navigation/_navigation.html +16 -0
- xlwings_server/templates/examples/navigation/taskpane_one.html +8 -0
- xlwings_server/templates/examples/navigation/taskpane_three.html +8 -0
- xlwings_server/templates/examples/navigation/taskpane_two.html +8 -0
- xlwings_server/templates/examples/pictures/README.md +42 -0
- xlwings_server/templates/examples/pictures/_picture.html +4 -0
- xlwings_server/templates/examples/pictures/taskpane_pictures.html +26 -0
- xlwings_server/templates/manifest.xml +155 -0
- xlwings_server/templates/taskpane.html +1 -0
- xlwings_server/templates/xlwings_alert.html +27 -0
- xlwings_server/templates.py +61 -0
- xlwings_server/utils.py +32 -0
- xlwings_server/wasm/__init__.py +0 -0
- xlwings_server/wasm/config.py +24 -0
- xlwings_server/wasm/main.py +236 -0
- xlwings_server/wasm/requirements.txt +5 -0
- xlwings_server-1.1.0.dist-info/METADATA +61 -0
- xlwings_server-1.1.0.dist-info/RECORD +313 -0
- xlwings_server-1.1.0.dist-info/WHEEL +4 -0
- xlwings_server-1.1.0.dist-info/entry_points.txt +2 -0
- xlwings_server-1.1.0.dist-info/licenses/LICENSE.md +223 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Pictures via htmx and Bootstrap dropdown
|
|
2
|
+
|
|
3
|
+
This sample populates a Bootstrap dropdown (see https://getbootstrap.com/docs/5.3/components/dropdowns/#single-button) with the names of the png pictures in the `app/static/images/ribbon/examples` directory.
|
|
4
|
+
When you select a picture name from the dropdown, it displays it below.
|
|
5
|
+
|
|
6
|
+
To try it out, replace `app/routers/taskpane.py` with the following code:
|
|
7
|
+
|
|
8
|
+
```python
|
|
9
|
+
from fastapi import APIRouter, Form, Request
|
|
10
|
+
|
|
11
|
+
from ..config import settings
|
|
12
|
+
from ..templates import TemplateResponse
|
|
13
|
+
|
|
14
|
+
router = APIRouter(prefix=settings.app_path)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@router.get("/taskpane")
|
|
18
|
+
@router.get("/taskpane.html")
|
|
19
|
+
async def taskpane(request: Request):
|
|
20
|
+
directory = settings.static_dir / "images" / "ribbon" / "examples"
|
|
21
|
+
picture_names = []
|
|
22
|
+
for path in directory.glob("*.png"):
|
|
23
|
+
picture_names.append(path.name)
|
|
24
|
+
return TemplateResponse(
|
|
25
|
+
request=request,
|
|
26
|
+
name="examples/pictures/taskpane_pictures.html",
|
|
27
|
+
context={"picture_names": picture_names},
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@router.post("/picture")
|
|
32
|
+
async def picture(request: Request, picture_name: str = Form(None)):
|
|
33
|
+
return TemplateResponse(
|
|
34
|
+
request=request,
|
|
35
|
+
name="examples/pictures/_picture.html",
|
|
36
|
+
context={"picture_name": picture_name},
|
|
37
|
+
)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This sample also depends on:
|
|
41
|
+
|
|
42
|
+
- pictures in `app/static/images/ribbon/examples`
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block content %}
|
|
4
|
+
<div class="container-fluid pt-3 ps-3">
|
|
5
|
+
<h1>A picture is worth a thousand words</h1>
|
|
6
|
+
<div class="dropdown">
|
|
7
|
+
<button class="btn btn-primary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
|
8
|
+
Select a picture
|
|
9
|
+
</button>
|
|
10
|
+
<ul class="dropdown-menu">
|
|
11
|
+
{% for name in picture_names %}
|
|
12
|
+
<li>
|
|
13
|
+
<a
|
|
14
|
+
class="dropdown-item"
|
|
15
|
+
hx-post="{{ url_for('picture') }}"
|
|
16
|
+
hx-target="#picture"
|
|
17
|
+
hx-vals='{"picture_name": "{{ name }}"}'
|
|
18
|
+
>{{ name }}</a
|
|
19
|
+
>
|
|
20
|
+
</li>
|
|
21
|
+
{% endfor %}
|
|
22
|
+
</ul>
|
|
23
|
+
</div>
|
|
24
|
+
<div id="picture" class="mt-4"></div>
|
|
25
|
+
</div>
|
|
26
|
+
{% endblock content %}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
2
|
+
<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1"
|
|
3
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
4
|
+
xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0"
|
|
5
|
+
xmlns:ov="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="TaskPaneApp">
|
|
6
|
+
<Id>{{ manifest_id }}</Id>
|
|
7
|
+
<Version>1.0.0.0</Version>
|
|
8
|
+
<ProviderName>xlwings</ProviderName>
|
|
9
|
+
<DefaultLocale>en-US</DefaultLocale>
|
|
10
|
+
<DisplayName DefaultValue="{{ settings.project_name }}{{ ' [' + settings.environment + ']' if settings.environment != 'prod'}}" />
|
|
11
|
+
<Description DefaultValue="{{ settings.project_name }}{{ ' [' + settings.environment + ']' if settings.environment != 'prod'}}" />
|
|
12
|
+
<IconUrl DefaultValue="{{ base_url }}{{ settings.static_url_path }}/images/xlwings-32.png" />
|
|
13
|
+
<HighResolutionIconUrl DefaultValue="{{ base_url }}{{ settings.static_url_path }}/images/xlwings-64.png" />
|
|
14
|
+
<SupportUrl DefaultValue="https://www.xlwings.org/contact" />
|
|
15
|
+
<AppDomains>
|
|
16
|
+
<AppDomain>{{ base_url_with_app_path }}</AppDomain>
|
|
17
|
+
</AppDomains>
|
|
18
|
+
<Hosts>
|
|
19
|
+
<Host Name="Workbook" />
|
|
20
|
+
</Hosts>
|
|
21
|
+
<!-- SharedRuntime for Custom Functions -->
|
|
22
|
+
<Requirements>
|
|
23
|
+
<Sets DefaultMinVersion="1.1">
|
|
24
|
+
<Set Name="SharedRuntime" MinVersion="1.1" />
|
|
25
|
+
</Sets>
|
|
26
|
+
</Requirements>
|
|
27
|
+
<DefaultSettings>
|
|
28
|
+
<SourceLocation DefaultValue="{{ base_url_with_app_path }}/taskpane.html" />
|
|
29
|
+
</DefaultSettings>
|
|
30
|
+
<Permissions>ReadWriteDocument</Permissions>
|
|
31
|
+
<VersionOverrides xmlns="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="VersionOverridesV1_0">
|
|
32
|
+
<Hosts>
|
|
33
|
+
<Host xsi:type="Workbook">
|
|
34
|
+
<!-- Custom Functions -->
|
|
35
|
+
<Runtimes>
|
|
36
|
+
<Runtime resid="Taskpane.Url" lifetime="long" />
|
|
37
|
+
</Runtimes>
|
|
38
|
+
<AllFormFactors>
|
|
39
|
+
<ExtensionPoint xsi:type="CustomFunctions">
|
|
40
|
+
<Script>
|
|
41
|
+
<SourceLocation resid="Functions.Script.Url" />
|
|
42
|
+
</Script>
|
|
43
|
+
<Page>
|
|
44
|
+
<SourceLocation resid="Taskpane.Url" />
|
|
45
|
+
</Page>
|
|
46
|
+
<Metadata>
|
|
47
|
+
<SourceLocation resid="Functions.Metadata.Url" />
|
|
48
|
+
</Metadata>
|
|
49
|
+
{% if settings.functions_namespace or settings.environment != 'prod' %}
|
|
50
|
+
<Namespace resid="Functions.Namespace" />
|
|
51
|
+
{% endif %}
|
|
52
|
+
</ExtensionPoint>
|
|
53
|
+
</AllFormFactors>
|
|
54
|
+
|
|
55
|
+
<DesktopFormFactor>
|
|
56
|
+
<!-- FunctionFile is used to bind functions directly to Ribbon buttons -->
|
|
57
|
+
<FunctionFile resid="Taskpane.Url" />
|
|
58
|
+
<ExtensionPoint xsi:type="PrimaryCommandSurface">
|
|
59
|
+
<CustomTab id="MyTab">
|
|
60
|
+
<Group id="MyCommandsGroup">
|
|
61
|
+
<Label resid="MyCommandsGroup.Label" />
|
|
62
|
+
<Icon>
|
|
63
|
+
<bt:Image size="16" resid="Icon.16x16" />
|
|
64
|
+
<bt:Image size="32" resid="Icon.32x32" />
|
|
65
|
+
<bt:Image size="80" resid="Icon.80x80" />
|
|
66
|
+
</Icon>
|
|
67
|
+
|
|
68
|
+
<!-- Ribbon button that calls a function -->
|
|
69
|
+
<Control xsi:type="Button" id="MyFunctionButton">
|
|
70
|
+
<!-- Label for your button. resid must point to a ShortString resource -->
|
|
71
|
+
<Label resid="MyFunctionButton.Label" />
|
|
72
|
+
<Supertip>
|
|
73
|
+
<!-- ToolTip title. resid must point to a ShortString resource -->
|
|
74
|
+
<Title resid="MyFunctionButton.Label" />
|
|
75
|
+
<!-- ToolTip description. resid must point to a LongString resource -->
|
|
76
|
+
<Description resid="MyFunctionButton.Tooltip" />
|
|
77
|
+
</Supertip>
|
|
78
|
+
<Icon>
|
|
79
|
+
<bt:Image size="16" resid="Icon.16x16" />
|
|
80
|
+
<bt:Image size="32" resid="Icon.32x32" />
|
|
81
|
+
<bt:Image size="80" resid="Icon.80x80" />
|
|
82
|
+
</Icon>
|
|
83
|
+
<!--Action type must be ExecuteFunction -->
|
|
84
|
+
<Action xsi:type="ExecuteFunction">
|
|
85
|
+
<!-- This is the name that you use in Office.actions.associate() to connect it to a function -->
|
|
86
|
+
<FunctionName>hello-ribbon</FunctionName>
|
|
87
|
+
</Action>
|
|
88
|
+
</Control>
|
|
89
|
+
|
|
90
|
+
<!-- Ribbon button that opens the task pane -->
|
|
91
|
+
<Control xsi:type="Button" id="MyTaskpaneButton">
|
|
92
|
+
<Label resid="MyTaskpaneButton.Label" />
|
|
93
|
+
<Supertip>
|
|
94
|
+
<Title resid="MyTaskpaneButton.Label" />
|
|
95
|
+
<Description resid="MyTaskpaneButton.Tooltip" />
|
|
96
|
+
</Supertip>
|
|
97
|
+
<Icon>
|
|
98
|
+
<bt:Image size="16" resid="Icon.16x16" />
|
|
99
|
+
<bt:Image size="32" resid="Icon.32x32" />
|
|
100
|
+
<bt:Image size="80" resid="Icon.80x80" />
|
|
101
|
+
</Icon>
|
|
102
|
+
<!-- Action type must be ShowTaskpane -->
|
|
103
|
+
<Action xsi:type="ShowTaskpane">
|
|
104
|
+
<TaskpaneId>ButtonId1</TaskpaneId>
|
|
105
|
+
<!-- resid must point to a Url Resource -->
|
|
106
|
+
<SourceLocation resid="Taskpane.Url" />
|
|
107
|
+
</Action>
|
|
108
|
+
</Control>
|
|
109
|
+
</Group>
|
|
110
|
+
<Label resid="MyTab.TabLabel" />
|
|
111
|
+
</CustomTab>
|
|
112
|
+
</ExtensionPoint>
|
|
113
|
+
</DesktopFormFactor>
|
|
114
|
+
</Host>
|
|
115
|
+
</Hosts>
|
|
116
|
+
|
|
117
|
+
<Resources>
|
|
118
|
+
<bt:Images>
|
|
119
|
+
<bt:Image id="Icon.16x16" DefaultValue="{{ base_url }}{{ settings.static_url_path }}/images/xlwings-16.png" />
|
|
120
|
+
<bt:Image id="Icon.32x32" DefaultValue="{{ base_url }}{{ settings.static_url_path }}/images/xlwings-32.png" />
|
|
121
|
+
<bt:Image id="Icon.80x80" DefaultValue="{{ base_url }}{{ settings.static_url_path }}/images/xlwings-80.png" />
|
|
122
|
+
</bt:Images>
|
|
123
|
+
<bt:Urls>
|
|
124
|
+
<!-- This must point to the HTML document with the task pane -->
|
|
125
|
+
<bt:Url id="Taskpane.Url" DefaultValue="{{ base_url_with_app_path }}/taskpane.html" />
|
|
126
|
+
<bt:Url id="Functions.Script.Url" DefaultValue="{{ base_url_with_app_path }}/xlwings/custom-functions-code.js" />
|
|
127
|
+
<bt:Url id="Functions.Metadata.Url" DefaultValue="{{ base_url_with_app_path }}/xlwings/custom-functions-meta.json" />
|
|
128
|
+
</bt:Urls>
|
|
129
|
+
<bt:ShortStrings>
|
|
130
|
+
{% if settings.functions_namespace or settings.environment != 'prod' %}
|
|
131
|
+
<bt:String id="Functions.Namespace" DefaultValue="{{ settings.functions_namespace|upper }}{{ '_' if settings.functions_namespace and settings.environment != 'prod'}}{{ settings.environment|upper if settings.environment != 'prod'}}" />
|
|
132
|
+
{% endif %}
|
|
133
|
+
<bt:String id="MyTab.TabLabel" DefaultValue="{{ settings.project_name }}{{ ' [' + settings.environment + ']' if settings.environment != 'prod'}}" />
|
|
134
|
+
<bt:String id="MyCommandsGroup.Label" DefaultValue="MyGroup" />
|
|
135
|
+
<bt:String id="MyFunctionButton.Label" DefaultValue="Hello World" />
|
|
136
|
+
<bt:String id="MyTaskpaneButton.Label" DefaultValue="Show Taskpane" />
|
|
137
|
+
</bt:ShortStrings>
|
|
138
|
+
<bt:LongStrings>
|
|
139
|
+
<bt:String id="MyFunctionButton.Tooltip" DefaultValue="Click to call the hello function" />
|
|
140
|
+
<bt:String id="MyTaskpaneButton.Tooltip" DefaultValue="Click to show the task pane" />
|
|
141
|
+
</bt:LongStrings>
|
|
142
|
+
</Resources>
|
|
143
|
+
|
|
144
|
+
{% if "entraid" in settings.auth_providers %}
|
|
145
|
+
<WebApplicationInfo>
|
|
146
|
+
<Id>{{ settings.auth_entraid_client_id }}</Id>
|
|
147
|
+
<Resource>api://{{ base_url_with_app_path|replace("https://", "") }}/{{ settings.auth_entraid_client_id }}</Resource>
|
|
148
|
+
<Scopes>
|
|
149
|
+
<Scope>openid</Scope>
|
|
150
|
+
<Scope>profile</Scope>
|
|
151
|
+
</Scopes>
|
|
152
|
+
</WebApplicationInfo>
|
|
153
|
+
{% endif %}
|
|
154
|
+
</VersionOverrides>
|
|
155
|
+
</OfficeApp>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{% extends "alert_base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block content %}
|
|
4
|
+
<div id="callback" data-callback="{{ callback }}"></div>
|
|
5
|
+
<div class="container-fluid">
|
|
6
|
+
<div class="d-flex flex-column pb-3 px-2 vh-100">
|
|
7
|
+
<h1 class="pt-4">{{ title }}</h1>
|
|
8
|
+
<p>{{ prompt|replace("\n", "<br>"|safe) }}</p>
|
|
9
|
+
<div class="mt-auto">
|
|
10
|
+
<div class="float-end">
|
|
11
|
+
{% if "ok" in buttons %}
|
|
12
|
+
<button id="ok" type="button" class="btn btn-primary btn-xl-alert">OK</button>
|
|
13
|
+
{% endif %}
|
|
14
|
+
{% if "yes" in buttons %}
|
|
15
|
+
<button id="yes" type="button" class="btn btn-primary btn-xl-alert">Yes</button>
|
|
16
|
+
{% endif %}
|
|
17
|
+
{% if "no" in buttons %}
|
|
18
|
+
<button id="no" type="button" class="btn btn-outline-secondary btn-xl-alert">No</button>
|
|
19
|
+
{% endif %}
|
|
20
|
+
{% if "cancel" in buttons %}
|
|
21
|
+
<button id="cancel" type="button" class="btn btn-outline-secondary btn-xl-alert">Cancel</button>
|
|
22
|
+
{% endif %}
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
{% endblock content %}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typing
|
|
4
|
+
|
|
5
|
+
from fastapi import Request
|
|
6
|
+
from jinja2 import ChoiceLoader, FileSystemLoader
|
|
7
|
+
from jinja2_fragments.fastapi import Jinja2Blocks
|
|
8
|
+
from starlette.background import BackgroundTask
|
|
9
|
+
|
|
10
|
+
from xlwings_server.config import PACKAGE_DIR, PROJECT_DIR, settings
|
|
11
|
+
|
|
12
|
+
# Create Jinja2 loader that checks dist templates first (if exists),
|
|
13
|
+
# then project templates, then package templates
|
|
14
|
+
loaders = []
|
|
15
|
+
dist_templates = PROJECT_DIR / "dist" / "templates"
|
|
16
|
+
if dist_templates.exists() and settings.environment != "dev":
|
|
17
|
+
loaders.append(FileSystemLoader(dist_templates))
|
|
18
|
+
loaders.extend(
|
|
19
|
+
[
|
|
20
|
+
FileSystemLoader(PROJECT_DIR / "templates"),
|
|
21
|
+
FileSystemLoader(PACKAGE_DIR / "templates"),
|
|
22
|
+
]
|
|
23
|
+
)
|
|
24
|
+
loader = ChoiceLoader(loaders)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
templates = Jinja2Blocks(
|
|
28
|
+
directory=PROJECT_DIR / "templates",
|
|
29
|
+
loader=loader,
|
|
30
|
+
trim_blocks=True,
|
|
31
|
+
lstrip_blocks=True,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# Align with FastAPIs changes to the function signature
|
|
36
|
+
def TemplateResponse(
|
|
37
|
+
request: Request,
|
|
38
|
+
name: str,
|
|
39
|
+
context: dict[str, typing.Any] | None = None,
|
|
40
|
+
status_code: int = 200,
|
|
41
|
+
headers: typing.Mapping[str, str] | None = None,
|
|
42
|
+
media_type: str | None = None,
|
|
43
|
+
background: BackgroundTask | None = None,
|
|
44
|
+
block_names: str | list[str] | None = None,
|
|
45
|
+
**kwargs: typing.Any,
|
|
46
|
+
):
|
|
47
|
+
if context is None:
|
|
48
|
+
context = {}
|
|
49
|
+
context["request"] = request
|
|
50
|
+
context["settings"] = settings
|
|
51
|
+
return templates.TemplateResponse(
|
|
52
|
+
name,
|
|
53
|
+
context,
|
|
54
|
+
status_code,
|
|
55
|
+
headers,
|
|
56
|
+
media_type,
|
|
57
|
+
background,
|
|
58
|
+
block_name=block_names if isinstance(block_names, str) else None,
|
|
59
|
+
block_names=block_names if isinstance(block_names, list) else [],
|
|
60
|
+
**kwargs,
|
|
61
|
+
)
|
xlwings_server/utils.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
import redis
|
|
4
|
+
|
|
5
|
+
from . import object_handles
|
|
6
|
+
from .config import settings
|
|
7
|
+
from .routers import socketio as socketio_router, xlwings as xlwings_router
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
async def trigger_script(script, **options):
|
|
13
|
+
sid = xlwings_router.socketio_id_context.get()
|
|
14
|
+
if not isinstance(script, str):
|
|
15
|
+
script = script.__name__
|
|
16
|
+
await socketio_router.sio.emit(
|
|
17
|
+
"xlwings:trigger-script",
|
|
18
|
+
{"script_name": script, **options},
|
|
19
|
+
to=sid,
|
|
20
|
+
)
|
|
21
|
+
logger.info(f"Script '{script}' triggered for sid '{sid}' with config: {options}")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
async def clear_object_cache():
|
|
25
|
+
if settings.object_cache_url:
|
|
26
|
+
redis_client: redis.Redis = xlwings_router.redis_client_context.get()
|
|
27
|
+
keys = redis_client.scan_iter(match="object:*")
|
|
28
|
+
for key in keys:
|
|
29
|
+
redis_client.delete(key)
|
|
30
|
+
logger.info("Cleared all keys starting with 'object:' from the Redis cache")
|
|
31
|
+
else:
|
|
32
|
+
object_handles.cache = {}
|
|
File without changes
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from dotenv import load_dotenv
|
|
4
|
+
|
|
5
|
+
load_dotenv(".env")
|
|
6
|
+
|
|
7
|
+
# xlwings depends on this, so set before importing xlwings
|
|
8
|
+
os.environ["XLWINGS_ON_SERVER"] = "true"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def read_bool(env_name: str, default: str = "false") -> bool:
|
|
12
|
+
return os.getenv(env_name, default).lower() == "true"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Settings:
|
|
16
|
+
enable_examples: bool = read_bool("XLWINGS_ENABLE_EXAMPLES")
|
|
17
|
+
enable_wasm: bool = True
|
|
18
|
+
enable_tests: bool = read_bool("XLWINGS_ENABLE_TESTS")
|
|
19
|
+
environment: str = os.getenv("XLWINGS_ENVIRONMENT", "prod")
|
|
20
|
+
functions_namespace: str = os.getenv("XLWINGS_FUNCTIONS_NAMESPACE", "XLWINGS")
|
|
21
|
+
is_official_lite_addin: bool = read_bool("XLWINGS_IS_OFFICIAL_LITE_ADDIN")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
settings = Settings()
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
from config import settings # noqa: F401, I001 Must be first import to load env vars
|
|
2
|
+
import platform
|
|
3
|
+
import traceback
|
|
4
|
+
import importlib.util
|
|
5
|
+
import sys
|
|
6
|
+
import contextlib
|
|
7
|
+
from io import StringIO
|
|
8
|
+
import ast
|
|
9
|
+
import inspect
|
|
10
|
+
from textwrap import dedent
|
|
11
|
+
|
|
12
|
+
import custom_functions
|
|
13
|
+
import custom_scripts
|
|
14
|
+
import js # type: ignore
|
|
15
|
+
import pyodide_js # type: ignore
|
|
16
|
+
import xlwings as xw
|
|
17
|
+
import xlwings.server
|
|
18
|
+
from pyodide.ffi import to_js # type: ignore
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
import matplotlib as mpl
|
|
22
|
+
|
|
23
|
+
mpl.use("agg")
|
|
24
|
+
except ImportError:
|
|
25
|
+
mpl = None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# xlwings <0.33.13 doesn't have custom_scripts_meta
|
|
29
|
+
if not hasattr(xlwings.server, "custom_scripts_meta"):
|
|
30
|
+
xlwings.server.custom_scripts_meta = lambda module: []
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class HtmlOutput:
|
|
34
|
+
def __init__(self, div_id):
|
|
35
|
+
self.div_id = div_id
|
|
36
|
+
self.buffer = StringIO()
|
|
37
|
+
|
|
38
|
+
def write(self, text):
|
|
39
|
+
self.buffer.write(text)
|
|
40
|
+
content = self.buffer.getvalue()
|
|
41
|
+
div = js.document.getElementById(self.div_id)
|
|
42
|
+
if div:
|
|
43
|
+
js.document.getElementById(self.div_id).innerHTML = f"<pre>{content}</pre>"
|
|
44
|
+
# Scroll to bottom
|
|
45
|
+
outputContainer = js.document.querySelector("#output-container")
|
|
46
|
+
if outputContainer:
|
|
47
|
+
outputContainer.scrollTop = outputContainer.scrollHeight
|
|
48
|
+
|
|
49
|
+
def flush(self):
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
if settings.is_official_lite_addin:
|
|
54
|
+
html_output = HtmlOutput("output")
|
|
55
|
+
try:
|
|
56
|
+
import pyodide_http # type: ignore
|
|
57
|
+
except ImportError:
|
|
58
|
+
pyodide_http = None
|
|
59
|
+
if pyodide_http:
|
|
60
|
+
pyodide_http.patch_all() # Fixes pd.read_csv()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# Print Python and Pyodide versions
|
|
64
|
+
def print_versions():
|
|
65
|
+
if settings.is_official_lite_addin:
|
|
66
|
+
html_output = HtmlOutput("output")
|
|
67
|
+
with (
|
|
68
|
+
contextlib.redirect_stdout(html_output),
|
|
69
|
+
contextlib.redirect_stderr(html_output),
|
|
70
|
+
):
|
|
71
|
+
print(
|
|
72
|
+
f"Python {platform.python_version()}|Pyodide {pyodide_js.version}|xlwings {xw.__version__}"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def create_module_from_string(module_string, module_name, html_output=None):
|
|
77
|
+
spec = importlib.util.spec_from_loader(
|
|
78
|
+
module_name,
|
|
79
|
+
loader=None,
|
|
80
|
+
)
|
|
81
|
+
module = importlib.util.module_from_spec(spec)
|
|
82
|
+
if html_output:
|
|
83
|
+
with (
|
|
84
|
+
contextlib.redirect_stdout(html_output),
|
|
85
|
+
contextlib.redirect_stderr(html_output),
|
|
86
|
+
):
|
|
87
|
+
exec(module_string, module.__dict__)
|
|
88
|
+
else:
|
|
89
|
+
exec(module_string, module.__dict__)
|
|
90
|
+
sys.modules[module_name] = module
|
|
91
|
+
return module
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
async def custom_functions_call(data):
|
|
95
|
+
if settings.is_official_lite_addin:
|
|
96
|
+
import main_editor
|
|
97
|
+
|
|
98
|
+
module = main_editor
|
|
99
|
+
else:
|
|
100
|
+
module = custom_functions
|
|
101
|
+
|
|
102
|
+
data = data.to_py()
|
|
103
|
+
try:
|
|
104
|
+
if settings.is_official_lite_addin:
|
|
105
|
+
with (
|
|
106
|
+
contextlib.redirect_stdout(html_output),
|
|
107
|
+
contextlib.redirect_stderr(html_output),
|
|
108
|
+
):
|
|
109
|
+
result = await xlwings.server.custom_functions_call(
|
|
110
|
+
data,
|
|
111
|
+
module=module,
|
|
112
|
+
)
|
|
113
|
+
else:
|
|
114
|
+
result = await xlwings.server.custom_functions_call(
|
|
115
|
+
data,
|
|
116
|
+
module=module,
|
|
117
|
+
)
|
|
118
|
+
except Exception as e:
|
|
119
|
+
result = {"error": str(e), "details": traceback.format_exc()}
|
|
120
|
+
# Note: converts None to undefined
|
|
121
|
+
return to_js(result, dict_converter=js.Object.fromEntries)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
async def custom_scripts_call(data, script_name):
|
|
125
|
+
if settings.is_official_lite_addin:
|
|
126
|
+
import main_editor
|
|
127
|
+
|
|
128
|
+
module = main_editor
|
|
129
|
+
else:
|
|
130
|
+
module = custom_scripts
|
|
131
|
+
|
|
132
|
+
book = xw.Book(json=data.to_py())
|
|
133
|
+
try:
|
|
134
|
+
if settings.is_official_lite_addin:
|
|
135
|
+
with (
|
|
136
|
+
contextlib.redirect_stdout(html_output),
|
|
137
|
+
contextlib.redirect_stderr(html_output),
|
|
138
|
+
):
|
|
139
|
+
book = await xlwings.server.custom_scripts_call(
|
|
140
|
+
module=module,
|
|
141
|
+
script_name=script_name,
|
|
142
|
+
typehint_to_value={xw.Book: book},
|
|
143
|
+
)
|
|
144
|
+
else:
|
|
145
|
+
book = await xlwings.server.custom_scripts_call(
|
|
146
|
+
module=module,
|
|
147
|
+
script_name=script_name,
|
|
148
|
+
typehint_to_value={xw.Book: book},
|
|
149
|
+
)
|
|
150
|
+
result = book.json()
|
|
151
|
+
return to_js(result, dict_converter=js.Object.fromEntries)
|
|
152
|
+
except Exception as e:
|
|
153
|
+
error_traceback = traceback.format_exc()
|
|
154
|
+
if settings.is_official_lite_addin:
|
|
155
|
+
error_output = HtmlOutput(
|
|
156
|
+
"output"
|
|
157
|
+
) # Clear output before writing out an error
|
|
158
|
+
error_output.write(f'<span style="color: red">{error_traceback}</span>')
|
|
159
|
+
return to_js({"actions": []}, dict_converter=js.Object.fromEntries)
|
|
160
|
+
else:
|
|
161
|
+
result = {"error": str(e), "details": error_traceback}
|
|
162
|
+
return to_js(result, dict_converter=js.Object.fromEntries)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def custom_scripts_meta():
|
|
166
|
+
if settings.is_official_lite_addin:
|
|
167
|
+
import main_editor
|
|
168
|
+
|
|
169
|
+
module = main_editor
|
|
170
|
+
else:
|
|
171
|
+
module = custom_scripts
|
|
172
|
+
scripts_meta = xlwings.server.custom_scripts_meta(module)
|
|
173
|
+
return to_js(scripts_meta, dict_converter=js.Object.fromEntries)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def get_xlwings_scripts(code_string, script_button_text):
|
|
177
|
+
try:
|
|
178
|
+
tree = ast.parse(code_string)
|
|
179
|
+
except: # noqa: E722
|
|
180
|
+
return to_js([script_button_text])
|
|
181
|
+
xlwings_functions = []
|
|
182
|
+
|
|
183
|
+
for node in ast.walk(tree):
|
|
184
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
185
|
+
for decorator in node.decorator_list:
|
|
186
|
+
decorator_str = ast.unparse(decorator)
|
|
187
|
+
if "script" in decorator_str:
|
|
188
|
+
xlwings_functions.append(node.name)
|
|
189
|
+
break
|
|
190
|
+
|
|
191
|
+
# If currently selected script is still here, return it at beginning
|
|
192
|
+
if script_button_text in xlwings_functions:
|
|
193
|
+
remaining = [x for x in xlwings_functions if x != script_button_text]
|
|
194
|
+
return to_js([script_button_text] + remaining)
|
|
195
|
+
|
|
196
|
+
return to_js(xlwings_functions)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
html_output = HtmlOutput("output")
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def custom_functions_meta(module_string):
|
|
203
|
+
try:
|
|
204
|
+
module = create_module_from_string(module_string, "main")
|
|
205
|
+
except Exception as e: # noqa: E722
|
|
206
|
+
js.console.log(f"Parsing error [custom_functions_meta]: {e}")
|
|
207
|
+
return to_js({}, dict_converter=js.Object.fromEntries)
|
|
208
|
+
return to_js(
|
|
209
|
+
xlwings.server.custom_functions_meta(module),
|
|
210
|
+
dict_converter=js.Object.fromEntries,
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def custom_functions_code(module_string):
|
|
215
|
+
try:
|
|
216
|
+
module = create_module_from_string(module_string, "main")
|
|
217
|
+
except Exception as e: # noqa: E722
|
|
218
|
+
js.console.log(f"Parsing error [custom_functions_code]: {e}")
|
|
219
|
+
return ""
|
|
220
|
+
code = ""
|
|
221
|
+
for _, obj in inspect.getmembers(module):
|
|
222
|
+
if hasattr(obj, "__xlfunc__"):
|
|
223
|
+
xlfunc = obj.__xlfunc__
|
|
224
|
+
func_name = xlfunc["name"]
|
|
225
|
+
streaming = "true" if inspect.isasyncgenfunction(obj) else "false"
|
|
226
|
+
code += dedent(
|
|
227
|
+
f"""\
|
|
228
|
+
async function {func_name}() {{
|
|
229
|
+
let args = ["{func_name}", {streaming}]
|
|
230
|
+
args.push.apply(args, arguments);
|
|
231
|
+
return await base.apply(null, args);
|
|
232
|
+
}}
|
|
233
|
+
CustomFunctions.associate("{func_name.upper()}", {func_name});
|
|
234
|
+
"""
|
|
235
|
+
)
|
|
236
|
+
return code
|