cherrypy-foundation 1.0.0a3__tar.gz → 1.0.0a5__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.0a3/src/cherrypy_foundation.egg-info → cherrypy_foundation-1.0.0a5}/PKG-INFO +1 -1
- cherrypy_foundation-1.0.0a5/src/cherrypy_foundation/tests/templates/test_url.html +14 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tests/test_form.py +0 -3
- cherrypy_foundation-1.0.0a5/src/cherrypy_foundation/tests/test_url.py +165 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/url.py +29 -22
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5/src/cherrypy_foundation.egg-info}/PKG-INFO +1 -1
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation.egg-info/SOURCES.txt +2 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/.gitignore +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/.gitlab-ci.yml +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/LICENSE.md +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/README.md +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/pyproject.toml +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/setup.cfg +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/sonar-project.properties +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/__init__.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/ColorModes.jinja +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/Datatable.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/Datatable.jinja +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/Datatable.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/Field.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/Field.jinja +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/Field.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/Fields.jinja +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/Icon.jinja +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/SideBySideMultiSelect.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/SideBySideMultiSelect.jinja +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/SideBySideMultiSelect.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/Typeahead.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/Typeahead.jinja +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/Typeahead.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/__init__.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/tests/__init__.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/tests/test_static.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/bootstrap-icons/bootstrap-icons.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/bootstrap-icons/bootstrap-icons.min.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/bootstrap-icons/fonts/bootstrap-icons.woff +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2 +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/bootstrap5/css/bootstrap.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/bootstrap5/css/bootstrap.css.map +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/bootstrap5/css/bootstrap.min.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/bootstrap5/css/bootstrap.min.css.map +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/bootstrap5/js/bootstrap.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/bootstrap5/js/bootstrap.js.map +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/bootstrap5/js/bootstrap.min.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/bootstrap5/js/bootstrap.min.js.map +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/bootstrap5/js/color-modes.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables/css/dataTables.dataTables.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables/css/dataTables.dataTables.min.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables/images/sort_asc.png +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables/images/sort_asc_disabled.png +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables/images/sort_both.png +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables/images/sort_desc.png +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables/images/sort_desc_disabled.png +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables/js/dataTables.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables/js/dataTables.min.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/Buttons/css/buttons.dataTables.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/Buttons/css/buttons.dataTables.min.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/Buttons/js/buttons.html5.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/Buttons/js/buttons.html5.min.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/Buttons/js/dataTables.buttons.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/Buttons/js/dataTables.buttons.min.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/FixedHeader/css/fixedHeader.dataTables.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/FixedHeader/css/fixedHeader.dataTables.min.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/FixedHeader/js/dataTables.fixedHeader.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/FixedHeader/js/dataTables.fixedHeader.min.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/JSZip/jszip.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/JSZip/jszip.min.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/Responsive/css/responsive.dataTables.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/Responsive/css/responsive.dataTables.min.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/Responsive/js/dataTables.responsive.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/Responsive/js/dataTables.responsive.min.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/pdfmake/build/pdfmake.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/pdfmake/build/pdfmake.min.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/pdfmake/build/vfs_fonts.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/rowgroup/css/rowGroup.dataTables.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/rowgroup/css/rowGroup.dataTables.min.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/rowgroup/js/dataTables.rowGroup.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/datatables-extensions/rowgroup/js/dataTables.rowGroup.min.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/jquery/jquery.min.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/multi/LICENSE +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/multi/README.md +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/multi/multi.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/multi/multi.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/popper/popper.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/popper/popper.min.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/typeahead/jquery.typeahead.min.css +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/components/vendor/typeahead/jquery.typeahead.min.js +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/error_page.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/flash.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/form.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/logging.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/passwd.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/plugins/__init__.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/plugins/db.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/plugins/ldap.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/plugins/restapi.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/plugins/scheduler.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/plugins/smtp.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/plugins/tests/__init__.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/plugins/tests/test_db.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/plugins/tests/test_ldap.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/plugins/tests/test_scheduler.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/plugins/tests/test_smtp.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tests/__init__.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tests/templates/test_form.html +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tests/test_error_page.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tests/test_passwd.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/__init__.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/auth.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/auth_mfa.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/errors.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/i18n.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/jinja2.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/ratelimit.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/secure_headers.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/sessions_timeout.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/tests/__init__.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/tests/components/Button.jinja +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/tests/locales/en/LC_MESSAGES/messages.mo +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/tests/locales/en/LC_MESSAGES/messages.po +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/tests/locales/fr/LC_MESSAGES/messages.mo +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/tests/locales/fr/LC_MESSAGES/messages.po +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/tests/locales/messages.pot +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/tests/templates/test_jinja2.html +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/tests/templates/test_jinja2_i18n.html +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/tests/templates/test_jinjax.html +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/tests/test_auth.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/tests/test_auth_mfa.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/tests/test_i18n.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/tests/test_jinja2.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/tests/test_ratelimit.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/widgets.py +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation.egg-info/dependency_links.txt +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation.egg-info/requires.txt +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation.egg-info/top_level.txt +0 -0
- {cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/tox.ini +0 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<html>
|
|
2
|
+
<head>
|
|
3
|
+
<title>test-url</title>
|
|
4
|
+
</head>
|
|
5
|
+
<body>
|
|
6
|
+
Empty: {{ url_for("", **kwargs) }}<br/>
|
|
7
|
+
Dot: {{ url_for(".", **kwargs) }}<br/>
|
|
8
|
+
Dot page: {{ url_for(".", "my-page", **kwargs) }}<br/>
|
|
9
|
+
Slash: {{ url_for("/", **kwargs) }}<br/>
|
|
10
|
+
Page: {{ url_for("my-page", **kwargs) }}<br/>
|
|
11
|
+
Slash page: {{ url_for("/my-page", **kwargs) }}<br/>
|
|
12
|
+
Query: {{ url_for("my-page", foo='1', bar='test with space', **kwargs) }}<br/>
|
|
13
|
+
</body>
|
|
14
|
+
</html>
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# CherryPy Foundation
|
|
2
|
+
# Copyright (C) 2025 IKUS Software
|
|
3
|
+
#
|
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
# (at your option) any later version.
|
|
8
|
+
#
|
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
# GNU General Public License for more details.
|
|
13
|
+
#
|
|
14
|
+
# You should have received a copy of the GNU General Public License
|
|
15
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
16
|
+
|
|
17
|
+
import cherrypy
|
|
18
|
+
from cherrypy.test import helper
|
|
19
|
+
|
|
20
|
+
import cherrypy_foundation.tools.jinja2 # noqa
|
|
21
|
+
|
|
22
|
+
from ..url import url_for
|
|
23
|
+
|
|
24
|
+
env = cherrypy.tools.jinja2.create_env(
|
|
25
|
+
package_name=__package__,
|
|
26
|
+
globals={
|
|
27
|
+
'url_for': url_for,
|
|
28
|
+
},
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class SubPage:
|
|
33
|
+
|
|
34
|
+
@cherrypy.expose
|
|
35
|
+
@cherrypy.tools.jinja2(template='test_url.html')
|
|
36
|
+
def index(self, **kwargs):
|
|
37
|
+
_relative = cherrypy.request.headers.get('-Relative')
|
|
38
|
+
return {'kwargs': {'_relative': _relative or None}}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@cherrypy.tools.proxy(base='https://www.example.com')
|
|
42
|
+
class ProxiedPage:
|
|
43
|
+
|
|
44
|
+
@cherrypy.expose
|
|
45
|
+
@cherrypy.tools.jinja2(template='test_url.html')
|
|
46
|
+
def index(self, **kwargs):
|
|
47
|
+
_relative = cherrypy.request.headers.get('-Relative')
|
|
48
|
+
return {'kwargs': {'_relative': _relative or None}}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@cherrypy.tools.jinja2(env=env)
|
|
52
|
+
class Root:
|
|
53
|
+
sub_page = SubPage()
|
|
54
|
+
proxied = ProxiedPage()
|
|
55
|
+
|
|
56
|
+
@cherrypy.expose
|
|
57
|
+
@cherrypy.tools.jinja2(template='test_url.html')
|
|
58
|
+
def index(self, **kwargs):
|
|
59
|
+
_relative = cherrypy.request.headers.get('-Relative')
|
|
60
|
+
return {'kwargs': {'_relative': _relative or None}}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class UrlTest(helper.CPWebCase):
|
|
64
|
+
default_lang = None
|
|
65
|
+
interactive = False
|
|
66
|
+
|
|
67
|
+
@classmethod
|
|
68
|
+
def setup_server(cls):
|
|
69
|
+
cherrypy.tree.mount(Root(), '/')
|
|
70
|
+
|
|
71
|
+
def test_url_for(self):
|
|
72
|
+
self.assertEqual(url_for("foo", "bar"), 'http://127.0.0.1:54583/foo/bar')
|
|
73
|
+
self.assertEqual(url_for("foo", "bar", _relative='server'), '/foo/bar')
|
|
74
|
+
# Outside a request, relative url doesn't make alot of sens.
|
|
75
|
+
self.assertEqual(url_for("foo", "bar", _relative=1), '127.0.0.1:54583/foo/bar')
|
|
76
|
+
self.assertEqual(url_for("foo", "bar", _base='http://test.com'), 'http://test.com/foo/bar')
|
|
77
|
+
self.assertEqual(
|
|
78
|
+
url_for("mailto:myuser@test.com", subject='Enter you subject', _base=''),
|
|
79
|
+
'mailto:myuser@test.com?subject=Enter%20you%20subject',
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
def test_get_page(self):
|
|
83
|
+
# Given a form
|
|
84
|
+
# When querying the page that include this form
|
|
85
|
+
self.getPage("/")
|
|
86
|
+
self.assertStatus(200)
|
|
87
|
+
# Then each field is render properly.
|
|
88
|
+
# 1. Check title
|
|
89
|
+
self.assertInBody('test-url')
|
|
90
|
+
# 2. Check user field
|
|
91
|
+
self.assertInBody(f'Empty: http://{self.HOST}:{self.PORT}/')
|
|
92
|
+
self.assertInBody(f'Dot: http://{self.HOST}:{self.PORT}/')
|
|
93
|
+
self.assertInBody(f'Dot page: http://{self.HOST}:{self.PORT}/my-page')
|
|
94
|
+
self.assertInBody(f'Slash: http://{self.HOST}:{self.PORT}/')
|
|
95
|
+
self.assertInBody(f'Page: http://{self.HOST}:{self.PORT}/my-page')
|
|
96
|
+
self.assertInBody(f'Slash page: http://{self.HOST}:{self.PORT}/my-page')
|
|
97
|
+
self.assertInBody(f'Query: http://{self.HOST}:{self.PORT}/my-page?bar=test+with+space&foo=1')
|
|
98
|
+
|
|
99
|
+
def test_get_page_relative_true(self):
|
|
100
|
+
# Given a form
|
|
101
|
+
# When querying the page that include this form
|
|
102
|
+
self.getPage("/", headers=[('_relative', '1')])
|
|
103
|
+
self.assertStatus(200)
|
|
104
|
+
# Then each field is render properly.
|
|
105
|
+
# 1. Check title
|
|
106
|
+
self.assertInBody('test-url')
|
|
107
|
+
# 2. Check user field
|
|
108
|
+
self.assertInBody('Empty: <br/>')
|
|
109
|
+
self.assertInBody('Dot: <br/>')
|
|
110
|
+
self.assertInBody('Dot page: my-page<br/>')
|
|
111
|
+
self.assertInBody('Slash: <br/>')
|
|
112
|
+
self.assertInBody('Page: my-page<br/>')
|
|
113
|
+
self.assertInBody('Slash page: my-page<br/>')
|
|
114
|
+
self.assertInBody('Query: my-page?bar=test+with+space&foo=1<br/>')
|
|
115
|
+
|
|
116
|
+
def test_get_page_relative_server(self):
|
|
117
|
+
# Given a form
|
|
118
|
+
# When querying the page that include this form
|
|
119
|
+
self.getPage("/", headers=[('_relative', 'server')])
|
|
120
|
+
self.assertStatus(200)
|
|
121
|
+
# Then each field is render properly.
|
|
122
|
+
# 1. Check title
|
|
123
|
+
self.assertInBody('test-url')
|
|
124
|
+
# 2. Check user field
|
|
125
|
+
self.assertInBody('Empty: /<br/>')
|
|
126
|
+
self.assertInBody('Dot: /<br/>')
|
|
127
|
+
self.assertInBody('Dot page: /my-page<br/>')
|
|
128
|
+
self.assertInBody('Slash: /<br/>')
|
|
129
|
+
self.assertInBody('Page: /my-page<br/>')
|
|
130
|
+
self.assertInBody('Slash page: /my-page<br/>')
|
|
131
|
+
self.assertInBody('Query: /my-page?bar=test+with+space&foo=1<br/>')
|
|
132
|
+
|
|
133
|
+
def test_get_page_proxied(self):
|
|
134
|
+
# Given a form
|
|
135
|
+
# When querying the page that include this form
|
|
136
|
+
self.getPage("/proxied/")
|
|
137
|
+
self.assertStatus(200)
|
|
138
|
+
# Then each field is render properly.
|
|
139
|
+
# 1. Check title
|
|
140
|
+
self.assertInBody('test-url')
|
|
141
|
+
# 2. Check user field
|
|
142
|
+
self.assertInBody('Empty: https://www.example.com/')
|
|
143
|
+
self.assertInBody('Dot: https://www.example.com/proxied/')
|
|
144
|
+
self.assertInBody('Dot page: https://www.example.com/proxied/my-page<br/>')
|
|
145
|
+
self.assertInBody('Slash: https://www.example.com/')
|
|
146
|
+
self.assertInBody('Page: https://www.example.com/my-page')
|
|
147
|
+
self.assertInBody('Slash page: https://www.example.com/my-page')
|
|
148
|
+
self.assertInBody('Query: https://www.example.com/my-page?bar=test+with+space&foo=1')
|
|
149
|
+
|
|
150
|
+
def test_get_sub_page(self):
|
|
151
|
+
# Given a form
|
|
152
|
+
# When querying the page that include this form
|
|
153
|
+
self.getPage("/sub-page/")
|
|
154
|
+
self.assertStatus(200)
|
|
155
|
+
# Then each field is render properly.
|
|
156
|
+
# 1. Check title
|
|
157
|
+
self.assertInBody('test-url')
|
|
158
|
+
# 2. Check user field
|
|
159
|
+
self.assertInBody(f'Empty: http://{self.HOST}:{self.PORT}/sub-page/')
|
|
160
|
+
self.assertInBody(f'Dot: http://{self.HOST}:{self.PORT}/sub-page/')
|
|
161
|
+
self.assertInBody(f'Dot page: http://{self.HOST}:{self.PORT}/sub-page/my-page')
|
|
162
|
+
self.assertInBody(f'Slash: http://{self.HOST}:{self.PORT}/')
|
|
163
|
+
self.assertInBody(f'Page: http://{self.HOST}:{self.PORT}/my-page')
|
|
164
|
+
self.assertInBody(f'Slash page: http://{self.HOST}:{self.PORT}/my-page')
|
|
165
|
+
self.assertInBody(f'Query: http://{self.HOST}:{self.PORT}/my-page?bar=test+with+space&foo=1')
|
|
@@ -14,10 +14,12 @@
|
|
|
14
14
|
# You should have received a copy of the GNU General Public License
|
|
15
15
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
16
16
|
|
|
17
|
+
from urllib.parse import quote, urlencode, urljoin
|
|
18
|
+
|
|
17
19
|
import cherrypy
|
|
18
20
|
|
|
19
21
|
|
|
20
|
-
def url_for(*args,
|
|
22
|
+
def url_for(*args, _relative=None, _base=None, **kwargs):
|
|
21
23
|
"""
|
|
22
24
|
Generate a URL for the given endpoint/path (*args) with query params (**kwargs).
|
|
23
25
|
|
|
@@ -33,34 +35,39 @@ def url_for(*args, relative=None, **kwargs):
|
|
|
33
35
|
- Integers are appended as path segments.
|
|
34
36
|
- When path == "", existing request query parameters are merged (kwargs win).
|
|
35
37
|
"""
|
|
36
|
-
|
|
38
|
+
# Handle query-string
|
|
39
|
+
qs = [(k, v) for k, v in sorted(kwargs.items()) if v is not None]
|
|
40
|
+
|
|
41
|
+
path = []
|
|
37
42
|
for chunk in args:
|
|
38
|
-
if
|
|
39
|
-
|
|
40
|
-
path += "/"
|
|
41
|
-
path += chunk.rstrip("/")
|
|
42
|
-
elif isinstance(chunk, int):
|
|
43
|
-
path += "/"
|
|
44
|
-
path += str(chunk)
|
|
45
|
-
elif hasattr(chunk, '__url_for__') and callable(chunk.__url_for__):
|
|
46
|
-
path += "/"
|
|
47
|
-
path += str(chunk.__url_for__())
|
|
43
|
+
if hasattr(chunk, '__url_for__') and callable(chunk.__url_for__):
|
|
44
|
+
path.append(str(chunk.__url_for__()))
|
|
48
45
|
elif hasattr(chunk, 'url_for'):
|
|
49
|
-
path
|
|
50
|
-
|
|
46
|
+
path.append(str(chunk.url_for))
|
|
47
|
+
elif isinstance(chunk, str):
|
|
48
|
+
path.append(chunk)
|
|
49
|
+
elif isinstance(chunk, int):
|
|
50
|
+
path.append(str(chunk))
|
|
51
51
|
else:
|
|
52
52
|
raise ValueError('invalid positional arguments, url_for accept str, bytes, int: %r' % chunk)
|
|
53
|
+
path = '/'.join(path)
|
|
53
54
|
# When path is empty, we are browsing the same page.
|
|
54
55
|
# Let keep the original query_string to avoid loosing it.
|
|
55
|
-
if path
|
|
56
|
+
if not path:
|
|
56
57
|
params = cherrypy.request.params.copy()
|
|
57
58
|
params.update(kwargs)
|
|
58
59
|
qs = [(k, v) for k, v in sorted(params.items()) if v is not None]
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
# Outside a request, use
|
|
62
|
-
base = None
|
|
60
|
+
elif not path.startswith('.'):
|
|
61
|
+
path = urljoin('/', path)
|
|
62
|
+
# Outside a request, use cherrypy.tools.proxy config
|
|
63
63
|
if not cherrypy.request.app:
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
if _base is None:
|
|
65
|
+
_base = cherrypy.config.get('tools.proxy.base', None)
|
|
66
|
+
# Use cherrypy to build the URL
|
|
67
|
+
url = cherrypy.url(path=path, relative=_relative, base=_base)
|
|
68
|
+
# Append the query string
|
|
69
|
+
if qs and url.startswith('mailto:'):
|
|
70
|
+
return url + '?' + urlencode(qs, quote_via=quote)
|
|
71
|
+
elif qs:
|
|
72
|
+
return url + '?' + urlencode(qs)
|
|
73
|
+
return url
|
|
@@ -105,7 +105,9 @@ src/cherrypy_foundation/tests/__init__.py
|
|
|
105
105
|
src/cherrypy_foundation/tests/test_error_page.py
|
|
106
106
|
src/cherrypy_foundation/tests/test_form.py
|
|
107
107
|
src/cherrypy_foundation/tests/test_passwd.py
|
|
108
|
+
src/cherrypy_foundation/tests/test_url.py
|
|
108
109
|
src/cherrypy_foundation/tests/templates/test_form.html
|
|
110
|
+
src/cherrypy_foundation/tests/templates/test_url.html
|
|
109
111
|
src/cherrypy_foundation/tools/__init__.py
|
|
110
112
|
src/cherrypy_foundation/tools/auth.py
|
|
111
113
|
src/cherrypy_foundation/tools/auth_mfa.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/error_page.py
RENAMED
|
File without changes
|
{cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/flash.py
RENAMED
|
File without changes
|
|
File without changes
|
{cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/logging.py
RENAMED
|
File without changes
|
{cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/passwd.py
RENAMED
|
File without changes
|
|
File without changes
|
{cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/plugins/db.py
RENAMED
|
File without changes
|
{cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/plugins/ldap.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/plugins/smtp.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/auth.py
RENAMED
|
File without changes
|
|
File without changes
|
{cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/errors.py
RENAMED
|
File without changes
|
{cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/i18n.py
RENAMED
|
File without changes
|
{cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/tools/jinja2.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cherrypy_foundation-1.0.0a3 → cherrypy_foundation-1.0.0a5}/src/cherrypy_foundation/widgets.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|