bustapi 0.14.0__tar.gz → 0.14.2__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.
- {bustapi-0.14.0 → bustapi-0.14.2}/.gitignore +2 -1
- {bustapi-0.14.0 → bustapi-0.14.2}/CHANGELOG.md +11 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/Cargo.lock +8 -174
- {bustapi-0.14.0 → bustapi-0.14.2}/Cargo.toml +1 -1
- {bustapi-0.14.0 → bustapi-0.14.2}/PKG-INFO +1 -1
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/changelog.md +11 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/pyproject.toml +1 -1
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/__init__.py +1 -1
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/app.py +32 -1
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/auth/login.py +5 -1
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/core/helpers.py +2 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/routing/decorators.py +40 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/sessions.py +3 -1
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_async_login.py +28 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_issue_29.py +49 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/- +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/.github/FUNDING.yml +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/.github/workflows/ci-multiplatform.yml +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/.github/workflows/ci.yml +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/.github/workflows/docs.yml +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/.github/workflows/manual-publish.yml +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/.python-version +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/AGENT_KNOWLEDGE.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/Dockerfile +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/LICENSE +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/README.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/benchmarks/CACHE_BENCHMARK.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/benchmarks/README.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/benchmarks/app.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/benchmarks/benchmark_all.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/benchmarks/benchmark_avg.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/benchmarks/benchmark_cache.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/benchmarks/benchmark_combined.png +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/benchmarks/bustapi.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/benchmarks/bustapi_bench.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/benchmarks/bustapi_internal.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/benchmarks/comparison_bench.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/benchmarks/comprehensive_benchmark.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/benchmarks/gen_graph.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/benchmarks/quick_bench.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/benchmarks/resource_bench.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/benchmarks/rps_comparison.png +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/benchmarks/run_comparison_auto.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/benchmarks/ws_benchmark.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/advanced/async.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/advanced/blueprints.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/advanced/dependency_injection.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/advanced/deployment.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/advanced/middleware.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/advanced/security.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/advanced/validation.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/api-reference.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/assets/logo.png +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/complete-api-reference.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/deployment-performance-guide.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/deployment.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/examples-guide.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/index.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/installation.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/overrides/.gitkeep +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/quickstart.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/release_track.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/advanced/async_support.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/advanced/blueprints.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/advanced/dependency_injection.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/advanced/middleware.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/advanced/validation.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/api/all.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/api/app.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/api/context.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/api/utilities.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/assets/logo.png +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/changelog.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/core_concepts/request_data.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/core_concepts/responses.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/core_concepts/routing.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/core_concepts/templates.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/examples/index.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/getting_started/index.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/getting_started/quickstart.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/index.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/script.js +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/site/style.css +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/stylesheets/extra.css +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/user-guide/authentication.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/user-guide/caching.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/user-guide/cli.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/user-guide/database.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/user-guide/documentation.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/user-guide/error_handling.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/user-guide/jwt.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/user-guide/logging.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/user-guide/multiprocessing.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/user-guide/request_data.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/user-guide/responses.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/user-guide/routing.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/user-guide/sessions.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/user-guide/static_files.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/user-guide/templates.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/user-guide/turbo-routes.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/user-guide/video-streaming.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/docs/websockets.md +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/advanced/08_auto_docs.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/advanced/12_test_modes.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/advanced/13_error_handling.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/advanced/14_middleware.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/advanced/16_middleware_session.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/advanced/20_file_uploads.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/advanced/24_body_and_depends.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/advanced/27_video_stream.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/advanced/28_websocket.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/advanced/29_turbo_websocket.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/basics/01_hello_world.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/basics/02_parameters.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/basics/03_async.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/basics/04_request_data.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/basics/19_all_types.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/database/07_database_raw.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/database/10_database_sqlmodel.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/routing/06_blueprints.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/routing/09_complex_routing.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/routing/21_path_validation.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/routing/22_path_docs.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/routing/23_query_validation.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/routing/blueprint_with_jwt.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/security/10_rate_limit_demo.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/security/11_security_demo.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/security/17_jwt_auth.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/security/17_safe_features.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/security/18_jwt_cookies.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/security/18_safe_advanced.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/security/18_session_login.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/templates/05_templates.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/templates/26_complex_template.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/templates/templates/index.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/turbo/cache_test.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/turbo/fair_benchmark.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/turbo/typed_turbo_example.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/ws/app.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/ws/templates/index.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/ws/websockets_demo.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/examples/ws/ws_limit.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/mkdocs.yml +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/auth/__init__.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/auth/csrf.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/auth/decorators.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/auth/password.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/auth/tokens.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/auth/user.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/cli/__init__.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/cli/main.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/context.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/core/__init__.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/core/asgi.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/core/exceptions.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/core/logging.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/dependencies.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/dispatch.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/documentation/__init__.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/documentation/generator.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/extraction.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/fastapi_compat.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/hooks.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/http/__init__.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/http/request.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/http/response.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/jwt.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/logging.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/middleware.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/multiprocess.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/params.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/py.typed +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/responses.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/routing/__init__.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/routing/blueprints.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/safe/__init__.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/safe/concurrency.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/safe/types.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/security/__init__.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/security/extension.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/security/rate_limit.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/server/__init__.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/server/runner.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/server/wsgi.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/templating/__init__.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/templating/engine.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/templating/mixin.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/testing/__init__.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/testing/client.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/utils.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/python/bustapi/websocket.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/run_all_examples.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/scratch/test_abort.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/scratch/test_headers.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/bindings/app.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/bindings/converters.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/bindings/handlers.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/bindings/mod.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/bindings/request.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/bindings/typed_turbo.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/bindings/websocket.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/crypto.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/jwt.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/lib.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/logger.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/rate_limiter.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/request/methods.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/request/mod.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/request/tests.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/response/builders.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/response/methods.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/response/mod.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/router/handlers.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/router/matching.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/router/middleware.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/router/mod.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/router/tests.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/server/handlers.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/server/mod.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/server/startup.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/server/stream.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/static_files.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/templating.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/watcher.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/websocket/config.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/websocket/mod.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/websocket/session.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/src/websocket/turbo.rs +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/static/style.css +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/templates/base.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/templates/complex.html +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/docs_test_all.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/docs_test_api_reference.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/docs_test_installation.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/docs_test_quickstart.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/docs_test_simple.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_050_features.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_async_hooks.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_auth.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_discussion_21.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_discussion_22.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_discussion_28.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_examples.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_hot_reload.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_issue_18.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_issue_23.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_issue_24.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_jwt.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_jwt_cookies.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_login_manager.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_middleware.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_multiprocess_stability.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_new_examples.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_orm_conflict.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_path_standalone.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_path_validation.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_rate_limit_rust.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_safe.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_security_unit.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_sessions.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/test_zero_copy.py +0 -0
- {bustapi-0.14.0 → bustapi-0.14.2}/tests/verify_router.py +0 -0
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented here.
|
|
4
4
|
|
|
5
|
+
## [0.14.2] - 2026-06-18
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- **Template `url_for` Availability**: `url_for` is now automatically injected into the Jinja2 template context within `render_template()`, matching Flask's built-in behaviour. Previously, `{{ url_for('endpoint') }}` would raise `'url_for' is undefined` in templates unless manually added via a context processor.
|
|
9
|
+
|
|
10
|
+
## [0.14.1] - 2026-06-17
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **Auth Login**: Resolved `RuntimeWarning: coroutine 'load_user' was never awaited` when using an asynchronous `user_loader` callback with `login_user(user_id)`. The loader's return value is now correctly run/awaited synchronously.
|
|
14
|
+
- **Session Expiration**: Replaced deprecated `datetime.utcnow()` with timezone-aware `datetime.now(timezone.utc)` to avoid future Python compatibility deprecation warnings.
|
|
15
|
+
|
|
5
16
|
## [0.14.0] - 2026-06-17
|
|
6
17
|
|
|
7
18
|
### Added
|
|
@@ -432,7 +432,7 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
|
|
432
432
|
|
|
433
433
|
[[package]]
|
|
434
434
|
name = "bustapi_core"
|
|
435
|
-
version = "0.14.
|
|
435
|
+
version = "0.14.2"
|
|
436
436
|
dependencies = [
|
|
437
437
|
"actix-files",
|
|
438
438
|
"actix-http",
|
|
@@ -992,16 +992,14 @@ dependencies = [
|
|
|
992
992
|
|
|
993
993
|
[[package]]
|
|
994
994
|
name = "getrandom"
|
|
995
|
-
version = "0.4.
|
|
995
|
+
version = "0.4.3"
|
|
996
996
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
997
|
-
checksum = "
|
|
997
|
+
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
|
998
998
|
dependencies = [
|
|
999
999
|
"cfg-if",
|
|
1000
1000
|
"libc",
|
|
1001
1001
|
"r-efi 6.0.0",
|
|
1002
1002
|
"rand_core 0.10.1",
|
|
1003
|
-
"wasip2",
|
|
1004
|
-
"wasip3",
|
|
1005
1003
|
]
|
|
1006
1004
|
|
|
1007
1005
|
[[package]]
|
|
@@ -1039,15 +1037,6 @@ version = "0.14.5"
|
|
|
1039
1037
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1040
1038
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
|
1041
1039
|
|
|
1042
|
-
[[package]]
|
|
1043
|
-
name = "hashbrown"
|
|
1044
|
-
version = "0.15.5"
|
|
1045
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1046
|
-
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
|
1047
|
-
dependencies = [
|
|
1048
|
-
"foldhash",
|
|
1049
|
-
]
|
|
1050
|
-
|
|
1051
1040
|
[[package]]
|
|
1052
1041
|
name = "hashbrown"
|
|
1053
1042
|
version = "0.17.1"
|
|
@@ -1228,12 +1217,6 @@ dependencies = [
|
|
|
1228
1217
|
"zerovec",
|
|
1229
1218
|
]
|
|
1230
1219
|
|
|
1231
|
-
[[package]]
|
|
1232
|
-
name = "id-arena"
|
|
1233
|
-
version = "2.3.0"
|
|
1234
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1235
|
-
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
|
|
1236
|
-
|
|
1237
1220
|
[[package]]
|
|
1238
1221
|
name = "ident_case"
|
|
1239
1222
|
version = "1.0.1"
|
|
@@ -1275,8 +1258,6 @@ checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
|
|
1275
1258
|
dependencies = [
|
|
1276
1259
|
"equivalent",
|
|
1277
1260
|
"hashbrown 0.17.1",
|
|
1278
|
-
"serde",
|
|
1279
|
-
"serde_core",
|
|
1280
1261
|
]
|
|
1281
1262
|
|
|
1282
1263
|
[[package]]
|
|
@@ -1367,12 +1348,6 @@ version = "1.5.0"
|
|
|
1367
1348
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1368
1349
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|
1369
1350
|
|
|
1370
|
-
[[package]]
|
|
1371
|
-
name = "leb128fmt"
|
|
1372
|
-
version = "0.1.0"
|
|
1373
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1374
|
-
checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
|
1375
|
-
|
|
1376
1351
|
[[package]]
|
|
1377
1352
|
name = "libc"
|
|
1378
1353
|
version = "0.2.186"
|
|
@@ -1486,9 +1461,9 @@ dependencies = [
|
|
|
1486
1461
|
|
|
1487
1462
|
[[package]]
|
|
1488
1463
|
name = "minijinja"
|
|
1489
|
-
version = "2.
|
|
1464
|
+
version = "2.21.0"
|
|
1490
1465
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1491
|
-
checksum = "
|
|
1466
|
+
checksum = "cb3d648e68cea56d9858d535ee28f9538404e2dd8cb08ed0bd05dca379477f39"
|
|
1492
1467
|
dependencies = [
|
|
1493
1468
|
"memo-map",
|
|
1494
1469
|
"serde",
|
|
@@ -1702,16 +1677,6 @@ dependencies = [
|
|
|
1702
1677
|
"zerocopy",
|
|
1703
1678
|
]
|
|
1704
1679
|
|
|
1705
|
-
[[package]]
|
|
1706
|
-
name = "prettyplease"
|
|
1707
|
-
version = "0.2.37"
|
|
1708
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1709
|
-
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
|
1710
|
-
dependencies = [
|
|
1711
|
-
"proc-macro2",
|
|
1712
|
-
"syn",
|
|
1713
|
-
]
|
|
1714
|
-
|
|
1715
1680
|
[[package]]
|
|
1716
1681
|
name = "proc-macro2"
|
|
1717
1682
|
version = "1.0.106"
|
|
@@ -1832,7 +1797,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
1832
1797
|
checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
|
|
1833
1798
|
dependencies = [
|
|
1834
1799
|
"chacha20",
|
|
1835
|
-
"getrandom 0.4.
|
|
1800
|
+
"getrandom 0.4.3",
|
|
1836
1801
|
"rand_core 0.10.1",
|
|
1837
1802
|
]
|
|
1838
1803
|
|
|
@@ -2162,7 +2127,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
2162
2127
|
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
|
2163
2128
|
dependencies = [
|
|
2164
2129
|
"fastrand",
|
|
2165
|
-
"getrandom 0.4.
|
|
2130
|
+
"getrandom 0.4.3",
|
|
2166
2131
|
"once_cell",
|
|
2167
2132
|
"rustix",
|
|
2168
2133
|
"windows-sys 0.61.2",
|
|
@@ -2438,16 +2403,7 @@ version = "1.0.4+wasi-0.2.12"
|
|
|
2438
2403
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2439
2404
|
checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487"
|
|
2440
2405
|
dependencies = [
|
|
2441
|
-
"wit-bindgen
|
|
2442
|
-
]
|
|
2443
|
-
|
|
2444
|
-
[[package]]
|
|
2445
|
-
name = "wasip3"
|
|
2446
|
-
version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
|
|
2447
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2448
|
-
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
|
|
2449
|
-
dependencies = [
|
|
2450
|
-
"wit-bindgen 0.51.0",
|
|
2406
|
+
"wit-bindgen",
|
|
2451
2407
|
]
|
|
2452
2408
|
|
|
2453
2409
|
[[package]]
|
|
@@ -2495,40 +2451,6 @@ dependencies = [
|
|
|
2495
2451
|
"unicode-ident",
|
|
2496
2452
|
]
|
|
2497
2453
|
|
|
2498
|
-
[[package]]
|
|
2499
|
-
name = "wasm-encoder"
|
|
2500
|
-
version = "0.244.0"
|
|
2501
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2502
|
-
checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
|
|
2503
|
-
dependencies = [
|
|
2504
|
-
"leb128fmt",
|
|
2505
|
-
"wasmparser",
|
|
2506
|
-
]
|
|
2507
|
-
|
|
2508
|
-
[[package]]
|
|
2509
|
-
name = "wasm-metadata"
|
|
2510
|
-
version = "0.244.0"
|
|
2511
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2512
|
-
checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
|
|
2513
|
-
dependencies = [
|
|
2514
|
-
"anyhow",
|
|
2515
|
-
"indexmap",
|
|
2516
|
-
"wasm-encoder",
|
|
2517
|
-
"wasmparser",
|
|
2518
|
-
]
|
|
2519
|
-
|
|
2520
|
-
[[package]]
|
|
2521
|
-
name = "wasmparser"
|
|
2522
|
-
version = "0.244.0"
|
|
2523
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2524
|
-
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
|
|
2525
|
-
dependencies = [
|
|
2526
|
-
"bitflags",
|
|
2527
|
-
"hashbrown 0.15.5",
|
|
2528
|
-
"indexmap",
|
|
2529
|
-
"semver",
|
|
2530
|
-
]
|
|
2531
|
-
|
|
2532
2454
|
[[package]]
|
|
2533
2455
|
name = "winapi-util"
|
|
2534
2456
|
version = "0.1.11"
|
|
@@ -2762,100 +2684,12 @@ version = "0.53.1"
|
|
|
2762
2684
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2763
2685
|
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
|
|
2764
2686
|
|
|
2765
|
-
[[package]]
|
|
2766
|
-
name = "wit-bindgen"
|
|
2767
|
-
version = "0.51.0"
|
|
2768
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2769
|
-
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
|
|
2770
|
-
dependencies = [
|
|
2771
|
-
"wit-bindgen-rust-macro",
|
|
2772
|
-
]
|
|
2773
|
-
|
|
2774
2687
|
[[package]]
|
|
2775
2688
|
name = "wit-bindgen"
|
|
2776
2689
|
version = "0.57.1"
|
|
2777
2690
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2778
2691
|
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
|
2779
2692
|
|
|
2780
|
-
[[package]]
|
|
2781
|
-
name = "wit-bindgen-core"
|
|
2782
|
-
version = "0.51.0"
|
|
2783
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2784
|
-
checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
|
|
2785
|
-
dependencies = [
|
|
2786
|
-
"anyhow",
|
|
2787
|
-
"heck",
|
|
2788
|
-
"wit-parser",
|
|
2789
|
-
]
|
|
2790
|
-
|
|
2791
|
-
[[package]]
|
|
2792
|
-
name = "wit-bindgen-rust"
|
|
2793
|
-
version = "0.51.0"
|
|
2794
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2795
|
-
checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
|
|
2796
|
-
dependencies = [
|
|
2797
|
-
"anyhow",
|
|
2798
|
-
"heck",
|
|
2799
|
-
"indexmap",
|
|
2800
|
-
"prettyplease",
|
|
2801
|
-
"syn",
|
|
2802
|
-
"wasm-metadata",
|
|
2803
|
-
"wit-bindgen-core",
|
|
2804
|
-
"wit-component",
|
|
2805
|
-
]
|
|
2806
|
-
|
|
2807
|
-
[[package]]
|
|
2808
|
-
name = "wit-bindgen-rust-macro"
|
|
2809
|
-
version = "0.51.0"
|
|
2810
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2811
|
-
checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
|
|
2812
|
-
dependencies = [
|
|
2813
|
-
"anyhow",
|
|
2814
|
-
"prettyplease",
|
|
2815
|
-
"proc-macro2",
|
|
2816
|
-
"quote",
|
|
2817
|
-
"syn",
|
|
2818
|
-
"wit-bindgen-core",
|
|
2819
|
-
"wit-bindgen-rust",
|
|
2820
|
-
]
|
|
2821
|
-
|
|
2822
|
-
[[package]]
|
|
2823
|
-
name = "wit-component"
|
|
2824
|
-
version = "0.244.0"
|
|
2825
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2826
|
-
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
|
|
2827
|
-
dependencies = [
|
|
2828
|
-
"anyhow",
|
|
2829
|
-
"bitflags",
|
|
2830
|
-
"indexmap",
|
|
2831
|
-
"log",
|
|
2832
|
-
"serde",
|
|
2833
|
-
"serde_derive",
|
|
2834
|
-
"serde_json",
|
|
2835
|
-
"wasm-encoder",
|
|
2836
|
-
"wasm-metadata",
|
|
2837
|
-
"wasmparser",
|
|
2838
|
-
"wit-parser",
|
|
2839
|
-
]
|
|
2840
|
-
|
|
2841
|
-
[[package]]
|
|
2842
|
-
name = "wit-parser"
|
|
2843
|
-
version = "0.244.0"
|
|
2844
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
2845
|
-
checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
|
|
2846
|
-
dependencies = [
|
|
2847
|
-
"anyhow",
|
|
2848
|
-
"id-arena",
|
|
2849
|
-
"indexmap",
|
|
2850
|
-
"log",
|
|
2851
|
-
"semver",
|
|
2852
|
-
"serde",
|
|
2853
|
-
"serde_derive",
|
|
2854
|
-
"serde_json",
|
|
2855
|
-
"unicode-xid",
|
|
2856
|
-
"wasmparser",
|
|
2857
|
-
]
|
|
2858
|
-
|
|
2859
2693
|
[[package]]
|
|
2860
2694
|
name = "writeable"
|
|
2861
2695
|
version = "0.6.3"
|
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented here.
|
|
4
4
|
|
|
5
|
+
## [0.14.2] - 2026-06-18
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- **Template `url_for` Availability**: `url_for` is now automatically injected into the Jinja2 template context within `render_template()`, matching Flask's built-in behaviour. Previously, `{{ url_for('endpoint') }}` would raise `'url_for' is undefined` in templates unless manually added via a context processor.
|
|
9
|
+
|
|
10
|
+
## [0.14.1] - 2026-06-17
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **Auth Login**: Resolved `RuntimeWarning: coroutine 'load_user' was never awaited` when using an asynchronous `user_loader` callback with `login_user(user_id)`. The loader's return value is now correctly run/awaited synchronously.
|
|
14
|
+
- **Session Expiration**: Replaced deprecated `datetime.utcnow()` with timezone-aware `datetime.now(timezone.utc)` to avoid future Python compatibility deprecation warnings.
|
|
15
|
+
|
|
5
16
|
## [0.14.0] - 2026-06-17
|
|
6
17
|
|
|
7
18
|
### Added
|
|
@@ -82,7 +82,9 @@ class BustAPI(
|
|
|
82
82
|
self.teardown_request_funcs: List[Callable] = []
|
|
83
83
|
self.teardown_appcontext_funcs: List[Callable] = []
|
|
84
84
|
self.blueprints: Dict[str, Blueprint] = {}
|
|
85
|
-
|
|
85
|
+
from .routing.decorators import Map
|
|
86
|
+
|
|
87
|
+
self.url_map = Map()
|
|
86
88
|
self._url_rules: List[Dict[str, Any]] = []
|
|
87
89
|
self.path_validators: Dict[tuple, Dict[str, Any]] = {}
|
|
88
90
|
self.query_validators: Dict[tuple, Dict[str, tuple]] = {}
|
|
@@ -237,13 +239,42 @@ class BustAPI(
|
|
|
237
239
|
|
|
238
240
|
def _dispatch_not_found(self, rust_request, params=None):
|
|
239
241
|
from .core.exceptions import NotFound
|
|
242
|
+
from .utils import async_to_sync
|
|
240
243
|
|
|
241
244
|
try:
|
|
242
245
|
request = Request._from_rust_request(rust_request)
|
|
243
246
|
request.app = self
|
|
244
247
|
token = _request_ctx.set(request)
|
|
245
248
|
try:
|
|
249
|
+
session = None
|
|
250
|
+
if self.secret_key:
|
|
251
|
+
session = self.session_interface.open_session(self, request)
|
|
252
|
+
request.session = session
|
|
253
|
+
|
|
254
|
+
bp = (
|
|
255
|
+
self.blueprints.get(request.blueprint)
|
|
256
|
+
if request.blueprint
|
|
257
|
+
else None
|
|
258
|
+
)
|
|
259
|
+
before_funcs = (
|
|
260
|
+
bp.before_request_funcs if bp else []
|
|
261
|
+
) + self.before_request_funcs
|
|
262
|
+
if before_funcs:
|
|
263
|
+
for before_func in before_funcs:
|
|
264
|
+
res = before_func()
|
|
265
|
+
if inspect.isawaitable(res):
|
|
266
|
+
res = async_to_sync(res)
|
|
267
|
+
if res is not None:
|
|
268
|
+
response = self._make_response(res)
|
|
269
|
+
if session:
|
|
270
|
+
self.session_interface.save_session(
|
|
271
|
+
self, session, response
|
|
272
|
+
)
|
|
273
|
+
return self._response_to_rust_format(response)
|
|
274
|
+
|
|
246
275
|
response = self._handle_exception(NotFound())
|
|
276
|
+
if session is not None:
|
|
277
|
+
self.session_interface.save_session(self, session, response)
|
|
247
278
|
return self._response_to_rust_format(response)
|
|
248
279
|
finally:
|
|
249
280
|
_request_ctx.reset(token)
|
|
@@ -162,7 +162,11 @@ def login_user(user, remember: bool = False, fresh: bool = True) -> bool:
|
|
|
162
162
|
|
|
163
163
|
try:
|
|
164
164
|
res = login_manager._user_loader_callback(user_id)
|
|
165
|
-
if
|
|
165
|
+
if inspect.isawaitable(res):
|
|
166
|
+
from ..utils import async_to_sync
|
|
167
|
+
|
|
168
|
+
loaded_user = async_to_sync(res)
|
|
169
|
+
else:
|
|
166
170
|
loaded_user = res
|
|
167
171
|
except Exception:
|
|
168
172
|
pass
|
|
@@ -356,6 +356,8 @@ def render_template(template_name: str, **context) -> Response:
|
|
|
356
356
|
context["current_app"] = _current_app
|
|
357
357
|
except RuntimeError:
|
|
358
358
|
pass
|
|
359
|
+
if "url_for" not in context:
|
|
360
|
+
context["url_for"] = url_for
|
|
359
361
|
|
|
360
362
|
# Run template context processors
|
|
361
363
|
try:
|
|
@@ -7,6 +7,46 @@ import re
|
|
|
7
7
|
from typing import Any, Callable, Optional
|
|
8
8
|
|
|
9
9
|
|
|
10
|
+
class Map:
|
|
11
|
+
"""
|
|
12
|
+
Flask-compatible url_map class to store and iterate rules.
|
|
13
|
+
Allows multiple rules for the same path pattern (e.g. GET and POST on same path).
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self):
|
|
17
|
+
self._rules = []
|
|
18
|
+
|
|
19
|
+
def __setitem__(self, key, value):
|
|
20
|
+
self._rules.append((key, value))
|
|
21
|
+
|
|
22
|
+
def items(self):
|
|
23
|
+
return self._rules
|
|
24
|
+
|
|
25
|
+
def __iter__(self):
|
|
26
|
+
return iter(r for r, _ in self._rules)
|
|
27
|
+
|
|
28
|
+
def __contains__(self, key):
|
|
29
|
+
return any(r == key for r, _ in self._rules)
|
|
30
|
+
|
|
31
|
+
def __getitem__(self, key):
|
|
32
|
+
for r, val in reversed(self._rules):
|
|
33
|
+
if r == key:
|
|
34
|
+
return val
|
|
35
|
+
raise KeyError(key)
|
|
36
|
+
|
|
37
|
+
def get(self, key, default=None):
|
|
38
|
+
try:
|
|
39
|
+
return self[key]
|
|
40
|
+
except KeyError:
|
|
41
|
+
return default
|
|
42
|
+
|
|
43
|
+
def clear(self):
|
|
44
|
+
self._rules.clear()
|
|
45
|
+
|
|
46
|
+
def __len__(self):
|
|
47
|
+
return len(self._rules)
|
|
48
|
+
|
|
49
|
+
|
|
10
50
|
class RouteRegistration:
|
|
11
51
|
"""Mixin providing Flask-compatible route decorators."""
|
|
12
52
|
|
|
@@ -128,7 +128,9 @@ class SecureCookieSessionInterface(SessionInterface):
|
|
|
128
128
|
expires = None
|
|
129
129
|
max_age = None
|
|
130
130
|
if session.permanent and app.permanent_session_lifetime:
|
|
131
|
-
|
|
131
|
+
from datetime import timezone
|
|
132
|
+
|
|
133
|
+
expires = datetime.now(timezone.utc) + app.permanent_session_lifetime
|
|
132
134
|
max_age = int(app.permanent_session_lifetime.total_seconds())
|
|
133
135
|
|
|
134
136
|
response.set_cookie(
|
|
@@ -78,5 +78,33 @@ def test_sync_user_loader_still_works():
|
|
|
78
78
|
assert response.json == {"id": 1, "name": "Sync User"}
|
|
79
79
|
|
|
80
80
|
|
|
81
|
+
def test_login_user_with_async_user_loader():
|
|
82
|
+
app = BustAPI()
|
|
83
|
+
app.secret_key = "test-secret"
|
|
84
|
+
login_manager = LoginManager(app)
|
|
85
|
+
|
|
86
|
+
async def get_user_from_db(user_id):
|
|
87
|
+
await asyncio.sleep(0.001)
|
|
88
|
+
if user_id == "42":
|
|
89
|
+
return User(42, "Direct Async User")
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
@login_manager.user_loader
|
|
93
|
+
async def load_user(user_id):
|
|
94
|
+
return await get_user_from_db(user_id)
|
|
95
|
+
|
|
96
|
+
@app.route("/login-raw")
|
|
97
|
+
def login_raw():
|
|
98
|
+
# Call login_user with raw ID
|
|
99
|
+
login_user("42")
|
|
100
|
+
# Check if the resolved user is loaded immediately
|
|
101
|
+
return {"id": current_user.id, "name": current_user.name}
|
|
102
|
+
|
|
103
|
+
client = BustTestClient(app)
|
|
104
|
+
response = client.get("/login-raw")
|
|
105
|
+
assert response.status_code == 200
|
|
106
|
+
assert response.json == {"id": 42, "name": "Direct Async User"}
|
|
107
|
+
|
|
108
|
+
|
|
81
109
|
if __name__ == "__main__":
|
|
82
110
|
pytest.main([__file__])
|
|
@@ -117,3 +117,52 @@ def test_blueprint_advanced_features():
|
|
|
117
117
|
res = client.get("/trigger_401")
|
|
118
118
|
assert res.status_code == 401
|
|
119
119
|
assert res.json["error"] == "app_401"
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def test_blueprint_multiple_methods_for_same_rule():
|
|
123
|
+
app = BustAPI()
|
|
124
|
+
app.secret_key = "test-secret-key"
|
|
125
|
+
|
|
126
|
+
unblocked_routes = ["/auth/login"]
|
|
127
|
+
|
|
128
|
+
@app.before_request
|
|
129
|
+
def login_before_visit():
|
|
130
|
+
from bustapi import redirect, request, session
|
|
131
|
+
|
|
132
|
+
if not (
|
|
133
|
+
"user_id" in session
|
|
134
|
+
or request.path in unblocked_routes
|
|
135
|
+
or request.path.startswith("/static")
|
|
136
|
+
):
|
|
137
|
+
session["came_from"] = request.path
|
|
138
|
+
return redirect(url_for("auth.login"))
|
|
139
|
+
|
|
140
|
+
auth = Blueprint("auth", __name__, url_prefix="/auth")
|
|
141
|
+
|
|
142
|
+
@auth.get("/login", endpoint="login")
|
|
143
|
+
def login_get():
|
|
144
|
+
return "GET Login Page"
|
|
145
|
+
|
|
146
|
+
@auth.post("/login")
|
|
147
|
+
def login_post():
|
|
148
|
+
return "POST Login Page"
|
|
149
|
+
|
|
150
|
+
app.register_blueprint(auth)
|
|
151
|
+
|
|
152
|
+
from bustapi.testing import BustTestClient
|
|
153
|
+
|
|
154
|
+
with BustTestClient(app) as client:
|
|
155
|
+
# GET / should redirect to /auth/login
|
|
156
|
+
res = client.get("/")
|
|
157
|
+
assert res.status_code == 302
|
|
158
|
+
assert res.headers["Location"] == "/auth/login"
|
|
159
|
+
|
|
160
|
+
# GET /auth/login should load fine (200)
|
|
161
|
+
res_login_get = client.get("/auth/login")
|
|
162
|
+
assert res_login_get.status_code == 200
|
|
163
|
+
assert res_login_get.get_data(as_text=True) == "GET Login Page"
|
|
164
|
+
|
|
165
|
+
# POST /auth/login should load fine (200)
|
|
166
|
+
res_login_post = client.post("/auth/login")
|
|
167
|
+
assert res_login_post.status_code == 200
|
|
168
|
+
assert res_login_post.get_data(as_text=True) == "POST Login Page"
|
|
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
|