cherrypy-foundation 1.0.0a16__tar.gz → 1.0.0a17__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/.gitignore +4 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/.gitlab-ci.yml +3 -0
- {cherrypy_foundation-1.0.0a16/src/cherrypy_foundation.egg-info → cherrypy_foundation-1.0.0a17}/PKG-INFO +21 -9
- cherrypy_foundation-1.0.0a17/README.md +30 -0
- cherrypy_foundation-1.0.0a17/debian/TODO +3 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/debian/control +11 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/debian/copyright +1 -1
- cherrypy_foundation-1.0.0a17/debian/python3-cherrpy-foundation-doc.install +1 -0
- cherrypy_foundation-1.0.0a17/debian/python3-cherrpy-foundation.install +1 -0
- cherrypy_foundation-1.0.0a17/debian/rules +35 -0
- cherrypy_foundation-1.0.0a17/doc/_templates/version.html +2 -0
- cherrypy_foundation-1.0.0a17/doc/conf.py +69 -0
- cherrypy_foundation-1.0.0a17/doc/error_page.md +163 -0
- cherrypy_foundation-1.0.0a17/doc/flash.md +200 -0
- cherrypy_foundation-1.0.0a17/doc/form.md +286 -0
- cherrypy_foundation-1.0.0a17/doc/index.rst +8 -0
- cherrypy_foundation-1.0.0a17/doc/introduction.md +23 -0
- cherrypy_foundation-1.0.0a17/doc/modules.rst +10 -0
- cherrypy_foundation-1.0.0a17/doc/url.md +230 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/pyproject.toml +1 -1
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/Datatable.js +2 -2
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/__init__.py +2 -2
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/tests/test_static.py +1 -1
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/error_page.py +2 -2
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/flash.py +2 -2
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/form.py +2 -2
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/logging.py +2 -2
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/passwd.py +2 -2
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/plugins/db.py +1 -1
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/plugins/ldap.py +3 -1
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/plugins/restapi.py +1 -1
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/plugins/scheduler.py +1 -1
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/plugins/smtp.py +8 -2
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/plugins/tests/test_db.py +2 -2
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/plugins/tests/test_ldap.py +1 -1
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/plugins/tests/test_scheduler.py +1 -1
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/plugins/tests/test_scheduler_db.py +1 -1
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/plugins/tests/test_smtp.py +31 -1
- cherrypy_foundation-1.0.0a17/src/cherrypy_foundation/sessions.py +82 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tests/__init__.py +1 -1
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tests/test_error_page.py +1 -1
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tests/test_flash.py +3 -3
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tests/test_form.py +3 -3
- cherrypy_foundation-1.0.0a17/src/cherrypy_foundation/tests/test_logging.py +78 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tests/test_passwd.py +2 -2
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tests/test_url.py +2 -2
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/auth.py +31 -27
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/auth_mfa.py +87 -83
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/i18n.py +1 -1
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/jinja2.py +1 -1
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/ratelimit.py +33 -19
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/secure_headers.py +1 -1
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/sessions_timeout.py +23 -21
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/tests/test_auth.py +20 -3
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/tests/test_auth_mfa.py +6 -4
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/tests/test_i18n.py +1 -1
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/tests/test_jinja2.py +2 -2
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/tests/test_ratelimit.py +2 -2
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/tests/test_secure_headers.py +4 -4
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/url.py +2 -2
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/widgets.py +2 -2
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17/src/cherrypy_foundation.egg-info}/PKG-INFO +21 -9
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation.egg-info/SOURCES.txt +13 -1
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/tox.ini +10 -2
- cherrypy_foundation-1.0.0a16/README.md +0 -18
- cherrypy_foundation-1.0.0a16/debian/TODO +0 -2
- cherrypy_foundation-1.0.0a16/debian/python3-cherrypy-foundation.docs +0 -1
- cherrypy_foundation-1.0.0a16/debian/rules +0 -31
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/LICENSE.md +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/debian/changelog +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/debian/python3-cherrypy-foundation.links +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/debian/source/format +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/debian/upstream/metadata +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/setup.cfg +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/sonar-project.properties +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/__init__.py +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/ColorModes.jinja +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/Datatable.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/Datatable.jinja +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/Field.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/Field.jinja +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/Field.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/Fields.jinja +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/Flash.jinja +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/Icon.jinja +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/LocaleSelection.jinja +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/LocaleSelection.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/SideBySideMultiSelect.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/SideBySideMultiSelect.jinja +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/SideBySideMultiSelect.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/Typeahead.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/Typeahead.jinja +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/Typeahead.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/tests/__init__.py +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/bootstrap-icons/bootstrap-icons.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/bootstrap-icons/bootstrap-icons.min.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/bootstrap-icons/fonts/bootstrap-icons.woff +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2 +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/bootstrap5/css/bootstrap.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/bootstrap5/css/bootstrap.css.map +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/bootstrap5/css/bootstrap.min.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/bootstrap5/css/bootstrap.min.css.map +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/bootstrap5/js/bootstrap.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/bootstrap5/js/bootstrap.js.map +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/bootstrap5/js/bootstrap.min.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/bootstrap5/js/bootstrap.min.js.map +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/bootstrap5/js/color-modes.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables/css/dataTables.dataTables.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables/css/dataTables.dataTables.min.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables/images/sort_asc.png +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables/images/sort_asc_disabled.png +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables/images/sort_both.png +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables/images/sort_desc.png +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables/images/sort_desc_disabled.png +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables/js/dataTables.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables/js/dataTables.min.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/Buttons/css/buttons.dataTables.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/Buttons/css/buttons.dataTables.min.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/Buttons/js/buttons.html5.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/Buttons/js/buttons.html5.min.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/Buttons/js/dataTables.buttons.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/Buttons/js/dataTables.buttons.min.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/FixedHeader/css/fixedHeader.dataTables.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/FixedHeader/css/fixedHeader.dataTables.min.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/FixedHeader/js/dataTables.fixedHeader.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/FixedHeader/js/dataTables.fixedHeader.min.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/JSZip/jszip.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/JSZip/jszip.min.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/Responsive/css/responsive.dataTables.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/Responsive/css/responsive.dataTables.min.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/Responsive/js/dataTables.responsive.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/Responsive/js/dataTables.responsive.min.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/pdfmake/build/pdfmake.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/pdfmake/build/pdfmake.min.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/pdfmake/build/vfs_fonts.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/rowgroup/css/rowGroup.dataTables.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/rowgroup/css/rowGroup.dataTables.min.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/rowgroup/js/dataTables.rowGroup.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/datatables-extensions/rowgroup/js/dataTables.rowGroup.min.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/jquery/jquery.min.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/multi/LICENSE +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/multi/README.md +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/multi/multi.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/multi/multi.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/popper/popper.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/popper/popper.min.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/typeahead/jquery.typeahead.min.css +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/components/vendor/typeahead/jquery.typeahead.min.js +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/plugins/__init__.py +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/plugins/tests/__init__.py +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tests/templates/test_flash.html +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tests/templates/test_form.html +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tests/templates/test_url.html +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/__init__.py +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/tests/__init__.py +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/tests/components/Button.jinja +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/tests/locales/de/LC_MESSAGES/messages.mo +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/tests/locales/de/LC_MESSAGES/messages.po +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/tests/locales/fr/LC_MESSAGES/messages.mo +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/tests/locales/fr/LC_MESSAGES/messages.po +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/tests/locales/messages.pot +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/tests/templates/test_jinja2.html +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/tests/templates/test_jinjax.html +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation/tools/tests/templates/test_jinjax_i18n.html +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation.egg-info/dependency_links.txt +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation.egg-info/requires.txt +0 -0
- {cherrypy_foundation-1.0.0a16 → cherrypy_foundation-1.0.0a17}/src/cherrypy_foundation.egg-info/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cherrypy-foundation
|
|
3
|
-
Version: 1.0.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 1.0.0a17
|
|
4
|
+
Summary: Cherrypy-foundation
|
|
5
5
|
Author-email: Patrik Dufresne <patrik@ikus-soft.com>
|
|
6
6
|
License: GPLv3
|
|
7
7
|
Project-URL: Homepage, https://gitlab.com/ikus-soft/cherrypy-foundation
|
|
@@ -48,12 +48,24 @@ Dynamic: license-file
|
|
|
48
48
|
<a href="https://sonar.ikus-soft.com/dashboard?id=cherrypy-foundation"><img alt="Coverage" src="https://sonar.ikus-soft.com/api/project_badges/measure?project=cherrypy-foundation&metric=coverage"></a>
|
|
49
49
|
</p>
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
building web applications with CherryPy. It offers built-in integrations
|
|
53
|
-
with SQLAlchemy for database access, Jinja2 for templating, WTForms for
|
|
54
|
-
form handling, and Bootstrap for UI components, helping streamline
|
|
55
|
-
application development.
|
|
51
|
+
Cherrypy-foundation is a comprehensive toolkit that accelerates web application development with CherryPy. It provides a curated collection of utilities and integrations that handle common web development tasks, allowing you to focus on building your application's unique features.
|
|
56
52
|
|
|
57
|
-
|
|
53
|
+
## What's Included
|
|
58
54
|
|
|
59
|
-
|
|
55
|
+
- **Database Integration**: Seamless SQLAlchemy integration for database operations
|
|
56
|
+
- **Template Engine**: Jinja2 and JinjaX support for flexible, component-based templating
|
|
57
|
+
- **Form Handling**: Enhanced WTForms integration with automatic validation and Bootstrap rendering
|
|
58
|
+
- **URL Management**: Flexible URL generation with `url_for` utility
|
|
59
|
+
- **Error Handling**: Smart error pages that adapt to response content type (HTML, JSON, plain text)
|
|
60
|
+
- **UI Components**: Bootstrap-ready components for rapid interface development
|
|
61
|
+
|
|
62
|
+
## Who Is This For?
|
|
63
|
+
|
|
64
|
+
Cherrypy-foundation is designed for developers who:
|
|
65
|
+
|
|
66
|
+
- Want to build modern web applications with CherryPy without reinventing the wheel
|
|
67
|
+
- Need a lightweight alternative to full-stack frameworks while maintaining flexibility
|
|
68
|
+
- Prefer convention over configuration but value customization options
|
|
69
|
+
- Want battle-tested components that integrate seamlessly with CherryPy's architecture
|
|
70
|
+
|
|
71
|
+
This documentation will guide you through all available features, from basic utilities to advanced integrations, with practical examples to help you get started quickly.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Cherrypy-foundation
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/license-GPL--3.0-orange"></a>
|
|
5
|
+
<a href="https://gitlab.com/ikus-soft/cherrypy-foundation/pipelines"><img alt="Build" src="https://gitlab.com/ikus-soft/cherrypy-foundation/badges/master/pipeline.svg"></a>
|
|
6
|
+
<a href="https://sonar.ikus-soft.com/dashboard?id=cherrypy-foundation"><img alt="Quality Gate" src="https://sonar.ikus-soft.com/api/project_badges/measure?project=cherrypy-foundation&metric=alert_status"></a>
|
|
7
|
+
<a href="https://sonar.ikus-soft.com/dashboard?id=cherrypy-foundation"><img alt="Coverage" src="https://sonar.ikus-soft.com/api/project_badges/measure?project=cherrypy-foundation&metric=coverage"></a>
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
Cherrypy-foundation is a comprehensive toolkit that accelerates web application development with CherryPy. It provides a curated collection of utilities and integrations that handle common web development tasks, allowing you to focus on building your application's unique features.
|
|
11
|
+
|
|
12
|
+
## What's Included
|
|
13
|
+
|
|
14
|
+
- **Database Integration**: Seamless SQLAlchemy integration for database operations
|
|
15
|
+
- **Template Engine**: Jinja2 and JinjaX support for flexible, component-based templating
|
|
16
|
+
- **Form Handling**: Enhanced WTForms integration with automatic validation and Bootstrap rendering
|
|
17
|
+
- **URL Management**: Flexible URL generation with `url_for` utility
|
|
18
|
+
- **Error Handling**: Smart error pages that adapt to response content type (HTML, JSON, plain text)
|
|
19
|
+
- **UI Components**: Bootstrap-ready components for rapid interface development
|
|
20
|
+
|
|
21
|
+
## Who Is This For?
|
|
22
|
+
|
|
23
|
+
Cherrypy-foundation is designed for developers who:
|
|
24
|
+
|
|
25
|
+
- Want to build modern web applications with CherryPy without reinventing the wheel
|
|
26
|
+
- Need a lightweight alternative to full-stack frameworks while maintaining flexibility
|
|
27
|
+
- Prefer convention over configuration but value customization options
|
|
28
|
+
- Want battle-tested components that integrate seamlessly with CherryPy's architecture
|
|
29
|
+
|
|
30
|
+
This documentation will guide you through all available features, from basic utilities to advanced integrations, with practical examples to help you get started quickly.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
- Symlink for all vendor files - bootstrap, jquery, etc.
|
|
2
|
+
- How to run the unit test with the symlink files
|
|
3
|
+
- symlink for sphinxdoc warning: ignoring unknown JavaScript code: debian/python3-cherrypy-foundation/usr/share/doc/python3-cherrypy-foundation/_static/scripts/fontawesome.js
|
|
@@ -9,9 +9,13 @@ Build-Depends:
|
|
|
9
9
|
pybuild-plugin-pyproject,
|
|
10
10
|
python3,
|
|
11
11
|
python3-all-dev,
|
|
12
|
+
python3-myst-parser,
|
|
12
13
|
python3-pip,
|
|
14
|
+
python3-pydata-sphinx-theme,
|
|
13
15
|
python3-setuptools,
|
|
14
16
|
python3-setuptools-scm,
|
|
17
|
+
python3-sphinx,
|
|
18
|
+
sphinx-common,
|
|
15
19
|
# Optional dependencies to execute the test test.
|
|
16
20
|
chromium-driver <!nocheck>,
|
|
17
21
|
libjs-bootstrap5 <!nocheck>,
|
|
@@ -61,3 +65,10 @@ Description: Common utilities and integrations for building CherryPy web applica
|
|
|
61
65
|
with SQLAlchemy for database access, Jinja2 for templating, WTForms for
|
|
62
66
|
form handling, and Bootstrap for UI components, helping streamline
|
|
63
67
|
application development.
|
|
68
|
+
|
|
69
|
+
Package: python3-cherrypy-foundation-doc
|
|
70
|
+
Section: doc
|
|
71
|
+
Architecture: all
|
|
72
|
+
Depends: ${sphinxdoc:Depends}, ${misc:Depends}
|
|
73
|
+
Description: Documentation for cherrypy-foundation
|
|
74
|
+
This package contains the HTML documentation for cherrypy-foundation.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
build/html/* usr/share/doc/python3-cherrypy-foundation-doc
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
usr/lib/python3*/*
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/make -f
|
|
2
|
+
|
|
3
|
+
include /usr/share/dpkg/pkg-info.mk
|
|
4
|
+
|
|
5
|
+
export SETUPTOOLS_SCM_PRETEND_VERSION_FOR_CHERRYPY_FOUNDATION := $(DEB_VERSION_UPSTREAM)
|
|
6
|
+
|
|
7
|
+
# Force use of pyproject.toml
|
|
8
|
+
export PYBUILD_SYSTEM=pyproject
|
|
9
|
+
|
|
10
|
+
%:
|
|
11
|
+
dh $@ --with python3,sphinxdoc --buildsystem=pybuild --test-tox
|
|
12
|
+
|
|
13
|
+
# Generate documentation
|
|
14
|
+
execute_after_dh_auto_build:
|
|
15
|
+
ifeq (,$(findstring nodoc, $(DEB_BUILD_OPTIONS)))
|
|
16
|
+
PYTHONPATH=. python3 -m sphinx -N -b html doc build/html
|
|
17
|
+
endif
|
|
18
|
+
|
|
19
|
+
# For testing, we need a timezone
|
|
20
|
+
override_dh_auto_test:
|
|
21
|
+
TZ=UTC dh_auto_test
|
|
22
|
+
|
|
23
|
+
# Remove tests files
|
|
24
|
+
execute_after_dh_auto_install:
|
|
25
|
+
find debian/tmp/usr/lib/python$(PYTHON3_DEFAULT)/dist-packages/cherrypy_foundation -type d -name "tests" -exec rm -rf {} +
|
|
26
|
+
|
|
27
|
+
execute_before_dh_auto_clean:
|
|
28
|
+
rm -rf *.egg-info
|
|
29
|
+
# Clean Sphinx build artifacts
|
|
30
|
+
rm -rf build/html docs/_build
|
|
31
|
+
|
|
32
|
+
# Generate orig.tar.gz
|
|
33
|
+
gentarball:
|
|
34
|
+
git archive --format=tar HEAD --prefix=$(DEB_SOURCE)-$(DEB_VERSION_UPSTREAM)/ | gzip -9 > ../$(DEB_SOURCE)_$(DEB_VERSION_UPSTREAM).orig.tar.gz
|
|
35
|
+
mk-origtargz --compression gzip ../$(DEB_SOURCE)_$(DEB_VERSION_UPSTREAM).orig.tar.gz
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Configuration file for the Sphinx documentation builder.
|
|
2
|
+
#
|
|
3
|
+
# This file only contains a selection of the most common options. For a full
|
|
4
|
+
# list see the documentation:
|
|
5
|
+
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
|
6
|
+
|
|
7
|
+
# -- Path setup --------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
# If extensions (or modules to document with autodoc) are in another directory,
|
|
10
|
+
# add these directories to sys.path here. If the directory is relative to the
|
|
11
|
+
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
|
12
|
+
#
|
|
13
|
+
# import os
|
|
14
|
+
# import sys
|
|
15
|
+
# sys.path.insert(0, os.path.abspath('.'))
|
|
16
|
+
|
|
17
|
+
# -- Project information -----------------------------------------------------
|
|
18
|
+
|
|
19
|
+
project = 'Cherrypy-foundation'
|
|
20
|
+
copyright = 'Copyright (C) 2026 IKUS Software'
|
|
21
|
+
author = 'Patrik Dufresne'
|
|
22
|
+
|
|
23
|
+
# -- General configuration ---------------------------------------------------
|
|
24
|
+
|
|
25
|
+
# Add any Sphinx extension module names here, as strings. They can be
|
|
26
|
+
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
|
27
|
+
# ones.
|
|
28
|
+
extensions = [
|
|
29
|
+
'myst_parser',
|
|
30
|
+
'sphinx.ext.autosectionlabel',
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
autosectionlabel_prefix_document = True
|
|
34
|
+
|
|
35
|
+
# Enable anchors for cross references
|
|
36
|
+
myst_heading_anchors = 2
|
|
37
|
+
|
|
38
|
+
# Add any paths that contain templates here, relative to this directory.
|
|
39
|
+
templates_path = ['_templates']
|
|
40
|
+
|
|
41
|
+
# List of patterns, relative to source directory, that match files and
|
|
42
|
+
# directories to ignore when looking for source files.
|
|
43
|
+
# This pattern also affects html_static_path and html_extra_path.
|
|
44
|
+
exclude_patterns = []
|
|
45
|
+
|
|
46
|
+
# -- Options for HTML output -------------------------------------------------
|
|
47
|
+
|
|
48
|
+
# The theme to use for HTML and HTML Help pages. See the documentation for
|
|
49
|
+
# a list of builtin themes.
|
|
50
|
+
#
|
|
51
|
+
html_theme = 'pydata_sphinx_theme'
|
|
52
|
+
# Ref: https://alabaster.readthedocs.io/en/latest/customization.html#theme-options
|
|
53
|
+
html_theme_options = {
|
|
54
|
+
"footer_start": ["copyright"],
|
|
55
|
+
"footer_end": ["version"],
|
|
56
|
+
'use_edit_page_button': True,
|
|
57
|
+
}
|
|
58
|
+
html_context = {
|
|
59
|
+
"gitlab_user": "ikus-soft",
|
|
60
|
+
"gitlab_repo": "cherrypy-foundation",
|
|
61
|
+
"gitlab_version": "main",
|
|
62
|
+
"doc_path": "doc",
|
|
63
|
+
}
|
|
64
|
+
html_show_sourcelink = False
|
|
65
|
+
|
|
66
|
+
# Add any paths that contain custom static files (such as style sheets) here,
|
|
67
|
+
# relative to this directory. They are copied after the builtin static files,
|
|
68
|
+
# so a file named "default.css" will overwrite the builtin "default.css".
|
|
69
|
+
#html_static_path = ['_static']
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Error Pages
|
|
2
|
+
|
|
3
|
+
The `error_page` utility replaces CherryPy's default error pages with a more flexible error handler.
|
|
4
|
+
It generates error responses based on the response `Content-Type`, returning either:
|
|
5
|
+
|
|
6
|
+
- an HTML page (default),
|
|
7
|
+
- a JSON error response for `application/json`
|
|
8
|
+
- plain text for `text/plain`.
|
|
9
|
+
|
|
10
|
+
If available, the HTML error page is rendered using Jinja2 with a template named `error_page.html`.
|
|
11
|
+
|
|
12
|
+
⚠️ **Note:** For 404 errors, the error handler sanitizes the error message to avoid leaking path information. A generic message is returned instead of exposing the requested path.
|
|
13
|
+
|
|
14
|
+
## Setup
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
from cherrypy_foundation.error_page import error_page
|
|
18
|
+
|
|
19
|
+
cherrypy.config.update({
|
|
20
|
+
'error_page.default': error_page,
|
|
21
|
+
})
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Features
|
|
25
|
+
|
|
26
|
+
### Content Negotiation
|
|
27
|
+
|
|
28
|
+
The error handler automatically detects the expected response format:
|
|
29
|
+
|
|
30
|
+
**HTML Response** (default for browsers):
|
|
31
|
+
```http
|
|
32
|
+
GET /invalid-page HTTP/1.1
|
|
33
|
+
Accept: text/html
|
|
34
|
+
|
|
35
|
+
HTTP/1.1 404 Not Found
|
|
36
|
+
Content-Type: text/html
|
|
37
|
+
|
|
38
|
+
<!DOCTYPE html>
|
|
39
|
+
<html>
|
|
40
|
+
<head><title>404 Not Found</title></head>
|
|
41
|
+
<body>
|
|
42
|
+
<h2>404 Not Found</h2>
|
|
43
|
+
<p>Nothing matches the given URI</p>
|
|
44
|
+
</body>
|
|
45
|
+
</html>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**JSON Response** (for API clients):
|
|
49
|
+
```http
|
|
50
|
+
GET /api/invalid HTTP/1.1
|
|
51
|
+
Accept: application/json
|
|
52
|
+
|
|
53
|
+
HTTP/1.1 404 Not Found
|
|
54
|
+
Content-Type: application/json
|
|
55
|
+
|
|
56
|
+
{"message": "Nothing matches the given URI", "status": "404 Not Found"}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Plain Text Response**:
|
|
60
|
+
```http
|
|
61
|
+
GET /invalid HTTP/1.1
|
|
62
|
+
Accept: text/plain
|
|
63
|
+
|
|
64
|
+
HTTP/1.1 404 Not Found
|
|
65
|
+
Content-Type: text/plain
|
|
66
|
+
|
|
67
|
+
Nothing matches the given URI
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Server Error Logging
|
|
71
|
+
|
|
72
|
+
All internal server error 500 are automatically logged with full traceback information:
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
@cherrypy.expose
|
|
76
|
+
def broken(self):
|
|
77
|
+
raise ValueError("Something went wrong!")
|
|
78
|
+
|
|
79
|
+
# Logs: error page status=500 Internal Server Error message=ValueError: Something went wrong!
|
|
80
|
+
# [full traceback]
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Custom Error Pages with Jinja2
|
|
84
|
+
|
|
85
|
+
To use custom error page templates, create an `error_page.html` template in your Jinja2 environment:
|
|
86
|
+
|
|
87
|
+
The following variables are available in the `error_page.html` template:
|
|
88
|
+
|
|
89
|
+
- `status` (str): HTTP status code and message (e.g., "404 Not Found")
|
|
90
|
+
- `message` (str): Detailed error message
|
|
91
|
+
- `traceback` (str): Stack trace (only for server errors when debug mode is enabled)
|
|
92
|
+
- `version` (str): CherryPy version
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
```html
|
|
96
|
+
<!DOCTYPE html>
|
|
97
|
+
<html lang="en">
|
|
98
|
+
<head>
|
|
99
|
+
<meta charset="utf-8">
|
|
100
|
+
<title>{{ status }}</title>
|
|
101
|
+
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
|
|
102
|
+
</head>
|
|
103
|
+
<body>
|
|
104
|
+
<div class="container mt-5">
|
|
105
|
+
<div class="alert alert-danger">
|
|
106
|
+
<h1>{{ status }}</h1>
|
|
107
|
+
<p>{{ message }}</p>
|
|
108
|
+
|
|
109
|
+
{% if traceback %}
|
|
110
|
+
<details>
|
|
111
|
+
<summary>Technical Details</summary>
|
|
112
|
+
<pre>{{ traceback }}</pre>
|
|
113
|
+
</details>
|
|
114
|
+
{% endif %}
|
|
115
|
+
</div>
|
|
116
|
+
</div>
|
|
117
|
+
</body>
|
|
118
|
+
</html>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Complete Example
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
import cherrypy
|
|
125
|
+
from cherrypy_foundation.error_page import error_page
|
|
126
|
+
|
|
127
|
+
# Setup Jinja2
|
|
128
|
+
env = cherrypy.tools.jinja2.create_env(
|
|
129
|
+
package_name=__package__,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# Configure error handler
|
|
133
|
+
cherrypy.config.update({
|
|
134
|
+
'error_page.default': error_page,
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
@cherrypy.tools.jinja2(env=env)
|
|
138
|
+
class Root:
|
|
139
|
+
|
|
140
|
+
@cherrypy.expose
|
|
141
|
+
@cherrypy.tools.jinja2(template='index.html')
|
|
142
|
+
def index(self):
|
|
143
|
+
return {}
|
|
144
|
+
|
|
145
|
+
@cherrypy.expose
|
|
146
|
+
def not_found(self):
|
|
147
|
+
# Will trigger 404 error page
|
|
148
|
+
raise cherrypy.NotFound()
|
|
149
|
+
|
|
150
|
+
@cherrypy.expose
|
|
151
|
+
def server_error(self):
|
|
152
|
+
# Will trigger 500 error page with logging
|
|
153
|
+
raise ValueError("Database connection failed")
|
|
154
|
+
|
|
155
|
+
@cherrypy.expose
|
|
156
|
+
@cherrypy.tools.json_out()
|
|
157
|
+
def api_endpoint(self):
|
|
158
|
+
# API errors will return JSON
|
|
159
|
+
raise cherrypy.HTTPError(400, "Invalid request parameters")
|
|
160
|
+
|
|
161
|
+
if __name__ == '__main__':
|
|
162
|
+
cherrypy.quickstart(Root())
|
|
163
|
+
```
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# Flash Messages
|
|
2
|
+
|
|
3
|
+
Flash messages are used to display informational, warning, or error messages to the user.
|
|
4
|
+
They are especially useful for reporting success or validation errors after form submissions.
|
|
5
|
+
|
|
6
|
+
⚠️ **Important:** Flash messages require the CherryPy **sessions tool** to be enabled, as messages are stored in the user session.
|
|
7
|
+
|
|
8
|
+
## How It Works
|
|
9
|
+
|
|
10
|
+
1. **Storage**: Flash messages are stored in the user's session under the `flash` key
|
|
11
|
+
2. **Retrieval**: `get_flashed_messages()` retrieves all messages and clears them from the session
|
|
12
|
+
3. **One-time display**: Messages are automatically removed after being retrieved, ensuring they only display once
|
|
13
|
+
|
|
14
|
+
This makes flash messages perfect for post-redirect-get patterns where you want to show a message after a form submission.
|
|
15
|
+
|
|
16
|
+
## Setup
|
|
17
|
+
|
|
18
|
+
### 1. Enable Sessions and Configure Jinja2
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
import cherrypy
|
|
22
|
+
from cherrypy_foundation.flash import get_flashed_messages
|
|
23
|
+
|
|
24
|
+
# Create Jinja2 environment with get_flashed_messages available
|
|
25
|
+
env = cherrypy.tools.jinja2.create_env(
|
|
26
|
+
package_name=__package__,
|
|
27
|
+
globals={'get_flashed_messages': get_flashed_messages},
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
@cherrypy.tools.sessions(locking='explicit') # Required for flash messages
|
|
31
|
+
@cherrypy.tools.jinja2(env=env)
|
|
32
|
+
class Root:
|
|
33
|
+
pass
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 2. Display Messages in Templates
|
|
37
|
+
|
|
38
|
+
Call `get_flashed_messages()` in your Jinja2 template to retrieve and display flash messages:
|
|
39
|
+
|
|
40
|
+
```html
|
|
41
|
+
<!DOCTYPE html>
|
|
42
|
+
<html lang="en">
|
|
43
|
+
<head>
|
|
44
|
+
<title>My Page</title>
|
|
45
|
+
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
|
|
46
|
+
</head>
|
|
47
|
+
<body>
|
|
48
|
+
<!-- Display flash messages -->
|
|
49
|
+
{% for message in get_flashed_messages() %}
|
|
50
|
+
<div class="alert alert-{{ message.level }} alert-dismissible fade show">
|
|
51
|
+
{{ message.message }}
|
|
52
|
+
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
|
53
|
+
</div>
|
|
54
|
+
{% endfor %}
|
|
55
|
+
|
|
56
|
+
<!-- Page content -->
|
|
57
|
+
<h1>Welcome!</h1>
|
|
58
|
+
</body>
|
|
59
|
+
</html>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Usage
|
|
63
|
+
|
|
64
|
+
### Adding Flash Messages
|
|
65
|
+
|
|
66
|
+
Use the `flash()` function to add messages in your handler:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from cherrypy_foundation.flash import flash
|
|
70
|
+
|
|
71
|
+
@cherrypy.expose
|
|
72
|
+
def save_profile(self, **kwargs):
|
|
73
|
+
# Save user profile...
|
|
74
|
+
flash('Profile updated successfully!', level='success')
|
|
75
|
+
raise cherrypy.HTTPRedirect('/profile')
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Message Levels
|
|
79
|
+
|
|
80
|
+
Flash messages support four severity levels:
|
|
81
|
+
|
|
82
|
+
- `info` - Informational messages (default)
|
|
83
|
+
- `success` - Success confirmations
|
|
84
|
+
- `warning` - Warning messages
|
|
85
|
+
- `error` - Error messages
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
flash('Account created successfully', level='success')
|
|
89
|
+
flash('Please verify your email address', level='info')
|
|
90
|
+
flash('Your session will expire in 5 minutes', level='warning')
|
|
91
|
+
flash('Failed to save changes', level='error')
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### HTML Markup Support
|
|
95
|
+
|
|
96
|
+
Flash messages support both plain strings and HTML markup:
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from markupsafe import Markup
|
|
100
|
+
|
|
101
|
+
# Plain text
|
|
102
|
+
flash('Simple message', level='info')
|
|
103
|
+
|
|
104
|
+
# HTML markup (safe HTML)
|
|
105
|
+
flash(Markup('Click <a href="/help">here</a> for help'), level='info')
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Using the JinjaX Flash Component
|
|
109
|
+
|
|
110
|
+
If you have JinjaX installed, you can use the built-in `<Flash />` component for easier rendering:
|
|
111
|
+
|
|
112
|
+
```html
|
|
113
|
+
<!DOCTYPE html>
|
|
114
|
+
<html lang="en">
|
|
115
|
+
<head>
|
|
116
|
+
<title>My Page</title>
|
|
117
|
+
</head>
|
|
118
|
+
<body>
|
|
119
|
+
<Flash
|
|
120
|
+
messages="{{ get_flashed_messages() }}"
|
|
121
|
+
class="mb-2"
|
|
122
|
+
style="min-height: 100px"
|
|
123
|
+
/>
|
|
124
|
+
|
|
125
|
+
<h1>Welcome!</h1>
|
|
126
|
+
</body>
|
|
127
|
+
</html>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The `<Flash />` component automatically handles:
|
|
131
|
+
- Rendering messages with appropriate Bootstrap alert classes
|
|
132
|
+
- Dismiss buttons for each message
|
|
133
|
+
- Custom styling via `class` and `style` attributes
|
|
134
|
+
|
|
135
|
+
## Complete Example
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
import cherrypy
|
|
139
|
+
import cherrypy_foundation.tools.jinja2
|
|
140
|
+
from cherrypy_foundation.flash import flash, get_flashed_messages
|
|
141
|
+
|
|
142
|
+
# Setup Jinja2
|
|
143
|
+
env = cherrypy.tools.jinja2.create_env(
|
|
144
|
+
package_name=__package__,
|
|
145
|
+
globals={'get_flashed_messages': get_flashed_messages},
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
@cherrypy.tools.sessions(locking='explicit')
|
|
149
|
+
@cherrypy.tools.jinja2(env=env)
|
|
150
|
+
class Root:
|
|
151
|
+
|
|
152
|
+
@cherrypy.expose
|
|
153
|
+
@cherrypy.tools.jinja2(template='index.html')
|
|
154
|
+
def index(self):
|
|
155
|
+
return {}
|
|
156
|
+
|
|
157
|
+
@cherrypy.expose
|
|
158
|
+
def submit(self, name=None):
|
|
159
|
+
if not name:
|
|
160
|
+
flash('Name is required', level='error')
|
|
161
|
+
else:
|
|
162
|
+
flash(f'Welcome, {name}!', level='success')
|
|
163
|
+
|
|
164
|
+
raise cherrypy.HTTPRedirect('/')
|
|
165
|
+
|
|
166
|
+
if __name__ == '__main__':
|
|
167
|
+
cherrypy.quickstart(Root())
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Template: `form.html`**
|
|
171
|
+
|
|
172
|
+
```html
|
|
173
|
+
<!DOCTYPE html>
|
|
174
|
+
<html lang="en">
|
|
175
|
+
<head>
|
|
176
|
+
<title>Registration Form</title>
|
|
177
|
+
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
|
|
178
|
+
</head>
|
|
179
|
+
<body>
|
|
180
|
+
<div class="container mt-5">
|
|
181
|
+
<!-- Flash messages -->
|
|
182
|
+
{% for message in get_flashed_messages() %}
|
|
183
|
+
<div class="alert alert-{{ message.level }} alert-dismissible">
|
|
184
|
+
{{ message.message }}
|
|
185
|
+
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
|
186
|
+
</div>
|
|
187
|
+
{% endfor %}
|
|
188
|
+
|
|
189
|
+
<!-- Form -->
|
|
190
|
+
<form method="post" action="/submit">
|
|
191
|
+
<div class="mb-3">
|
|
192
|
+
<label for="name" class="form-label">Name</label>
|
|
193
|
+
<input type="text" class="form-control" id="name" name="name">
|
|
194
|
+
</div>
|
|
195
|
+
<button type="submit" class="btn btn-primary">Submit</button>
|
|
196
|
+
</form>
|
|
197
|
+
</div>
|
|
198
|
+
</body>
|
|
199
|
+
</html>
|
|
200
|
+
```
|