summaryrefslogtreecommitdiff
path: root/venv/lib/python3.11/site-packages/litestar
diff options
context:
space:
mode:
authorcyfraeviolae <cyfraeviolae>2024-04-03 03:17:55 -0400
committercyfraeviolae <cyfraeviolae>2024-04-03 03:17:55 -0400
commit12cf076118570eebbff08c6b3090e0d4798447a1 (patch)
tree3ba25e17e3c3a5e82316558ba3864b955919ff72 /venv/lib/python3.11/site-packages/litestar
parentc45662ff3923b34614ddcc8feb9195541166dcc5 (diff)
no venv
Diffstat (limited to 'venv/lib/python3.11/site-packages/litestar')
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__init__.py33
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__main__.py10
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__pycache__/__init__.cpython-311.pycbin1138 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__pycache__/__main__.cpython-311.pycbin553 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__pycache__/_multipart.cpython-311.pycbin8023 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__pycache__/_parsers.cpython-311.pycbin4372 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__pycache__/app.cpython-311.pycbin49769 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__pycache__/background_tasks.cpython-311.pycbin3930 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__pycache__/concurrency.cpython-311.pycbin5261 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__pycache__/constants.cpython-311.pycbin3442 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__pycache__/controller.cpython-311.pycbin9719 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__pycache__/data_extractors.cpython-311.pycbin23608 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__pycache__/di.cpython-311.pycbin4721 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__pycache__/enums.cpython-311.pycbin3804 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__pycache__/file_system.cpython-311.pycbin7946 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__pycache__/pagination.cpython-311.pycbin11801 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__pycache__/params.cpython-311.pycbin16001 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__pycache__/router.cpython-311.pycbin19576 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__pycache__/status_codes.cpython-311.pycbin6311 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/__pycache__/typing.cpython-311.pycbin35878 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_asgi/__init__.py3
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_asgi/__pycache__/__init__.cpython-311.pycbin289 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_asgi/__pycache__/asgi_router.cpython-311.pycbin9201 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_asgi/__pycache__/utils.cpython-311.pycbin2149 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_asgi/asgi_router.py184
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__init__.py6
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/__init__.cpython-311.pycbin614 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/mapping.cpython-311.pycbin8784 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/traversal.cpython-311.pycbin7826 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/types.cpython-311.pycbin2798 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/validate.cpython-311.pycbin2362 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/mapping.py221
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/traversal.py170
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/types.py85
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/validate.py47
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_asgi/utils.py44
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_kwargs/__init__.py3
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/__init__.cpython-311.pycbin278 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/cleanup.cpython-311.pycbin6544 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/dependencies.cpython-311.pycbin5733 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/extractors.cpython-311.pycbin20001 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/kwargs_model.cpython-311.pycbin22080 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/parameter_definition.cpython-311.pycbin3656 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_kwargs/cleanup.py117
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_kwargs/dependencies.py119
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_kwargs/extractors.py492
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_kwargs/kwargs_model.py479
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_kwargs/parameter_definition.py81
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_layers/__init__.py0
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_layers/__pycache__/__init__.cpython-311.pycbin200 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_layers/__pycache__/utils.cpython-311.pycbin2457 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_layers/utils.py34
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_multipart.py163
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/__init__.py0
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/__init__.cpython-311.pycbin201 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/datastructures.cpython-311.pycbin10400 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/parameters.cpython-311.pycbin12657 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/path_item.cpython-311.pycbin7273 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/plugin.cpython-311.pycbin4935 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/request_body.cpython-311.pycbin2364 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/responses.cpython-311.pycbin17560 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/utils.cpython-311.pycbin2389 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/datastructures.py179
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/parameters.py233
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/path_item.py137
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/plugin.py75
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/request_body.py51
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/responses.py335
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__init__.py7
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/__init__.cpython-311.pycbin377 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/constrained_fields.cpython-311.pycbin4245 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/examples.cpython-311.pycbin4767 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/schema.cpython-311.pycbin33741 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/utils.cpython-311.pycbin6005 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/constrained_fields.py91
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/examples.py84
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__init__.py16
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/__init__.cpython-311.pycbin689 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/dataclass.cpython-311.pycbin2889 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/pagination.cpython-311.pycbin3789 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/struct.cpython-311.pycbin3411 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/typed_dict.cpython-311.pycbin2197 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/dataclass.py36
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/pagination.py60
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/struct.py44
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/typed_dict.py24
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/schema.py616
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/utils.py114
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__init__.py0
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__pycache__/__init__.cpython-311.pycbin222 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__pycache__/converter.cpython-311.pycbin15770 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__pycache__/schema_parsing.cpython-311.pycbin8656 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__pycache__/types.cpython-311.pycbin14996 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/converter.py308
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/schema_parsing.py150
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/types.py308
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_openapi/utils.py46
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_parsers.py67
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_signature/__init__.py3
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_signature/__pycache__/__init__.cpython-311.pycbin277 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_signature/__pycache__/model.cpython-311.pycbin15312 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_signature/__pycache__/types.cpython-311.pycbin1054 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_signature/__pycache__/utils.cpython-311.pycbin3189 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_signature/model.py316
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_signature/types.py11
-rw-r--r--venv/lib/python3.11/site-packages/litestar/_signature/utils.py58
-rw-r--r--venv/lib/python3.11/site-packages/litestar/app.py880
-rw-r--r--venv/lib/python3.11/site-packages/litestar/background_tasks.py74
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/__init__.py5
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/__pycache__/__init__.cpython-311.pycbin423 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/__pycache__/plugin.cpython-311.pycbin23104 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/__pycache__/subscriber.cpython-311.pycbin8595 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/backends/__init__.py0
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/__init__.cpython-311.pycbin210 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/asyncpg.cpython-311.pycbin6422 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/base.cpython-311.pycbin2607 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/memory.cpython-311.pycbin5024 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/psycopg.cpython-311.pycbin5220 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/redis.cpython-311.pycbin17950 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/backends/_redis_flushall_streams.lua15
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/backends/_redis_pubsub_publish.lua5
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/backends/_redis_xadd_expire.lua13
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/backends/asyncpg.py90
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/backends/base.py41
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/backends/memory.py84
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/backends/psycopg.py54
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/backends/redis.py277
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/plugin.py359
-rw-r--r--venv/lib/python3.11/site-packages/litestar/channels/subscriber.py135
-rw-r--r--venv/lib/python3.11/site-packages/litestar/cli/__init__.py29
-rw-r--r--venv/lib/python3.11/site-packages/litestar/cli/__pycache__/__init__.cpython-311.pycbin1276 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/cli/__pycache__/_utils.cpython-311.pycbin34239 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/cli/__pycache__/main.cpython-311.pycbin2459 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/cli/_utils.py562
-rw-r--r--venv/lib/python3.11/site-packages/litestar/cli/commands/__init__.py0
-rw-r--r--venv/lib/python3.11/site-packages/litestar/cli/commands/__pycache__/__init__.cpython-311.pycbin205 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/cli/commands/__pycache__/core.cpython-311.pycbin16664 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/cli/commands/__pycache__/schema.cpython-311.pycbin4442 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/cli/commands/__pycache__/sessions.cpython-311.pycbin3813 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/cli/commands/core.py335
-rw-r--r--venv/lib/python3.11/site-packages/litestar/cli/commands/schema.py82
-rw-r--r--venv/lib/python3.11/site-packages/litestar/cli/commands/sessions.py58
-rw-r--r--venv/lib/python3.11/site-packages/litestar/cli/main.py37
-rw-r--r--venv/lib/python3.11/site-packages/litestar/concurrency.py109
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/__init__.py0
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/__pycache__/__init__.cpython-311.pycbin199 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/__pycache__/allowed_hosts.cpython-311.pycbin2360 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/__pycache__/app.cpython-311.pycbin10063 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/__pycache__/compression.cpython-311.pycbin3757 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/__pycache__/cors.cpython-311.pycbin7425 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/__pycache__/csrf.cpython-311.pycbin2257 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/__pycache__/response_cache.cpython-311.pycbin4460 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/allowed_hosts.py43
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/app.py223
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/compression.py83
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/cors.py147
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/csrf.py42
-rw-r--r--venv/lib/python3.11/site-packages/litestar/config/response_cache.py81
-rw-r--r--venv/lib/python3.11/site-packages/litestar/connection/__init__.py37
-rw-r--r--venv/lib/python3.11/site-packages/litestar/connection/__pycache__/__init__.cpython-311.pycbin2206 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/connection/__pycache__/base.cpython-311.pycbin15545 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/connection/__pycache__/request.cpython-311.pycbin12711 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/connection/__pycache__/websocket.cpython-311.pycbin17142 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/connection/base.py345
-rw-r--r--venv/lib/python3.11/site-packages/litestar/connection/request.py263
-rw-r--r--venv/lib/python3.11/site-packages/litestar/connection/websocket.py343
-rw-r--r--venv/lib/python3.11/site-packages/litestar/constants.py57
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/__init__.py0
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/__init__.cpython-311.pycbin200 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/jinja.cpython-311.pycbin5921 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/mako.cpython-311.pycbin7742 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/minijinja.cpython-311.pycbin11427 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/minijnja.cpython-311.pycbin871 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/piccolo.cpython-311.pycbin6290 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/attrs/__init__.py3
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/attrs/__pycache__/__init__.cpython-311.pycbin297 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/attrs/__pycache__/attrs_schema_plugin.cpython-311.pycbin3570 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/attrs/attrs_schema_plugin.py49
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/htmx/__init__.py0
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/__init__.cpython-311.pycbin205 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/_utils.cpython-311.pycbin6781 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/request.cpython-311.pycbin7932 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/response.cpython-311.pycbin11070 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/types.cpython-311.pycbin2382 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/htmx/_utils.py148
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/htmx/request.py113
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/htmx/response.py200
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/htmx/types.py54
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/jinja.py114
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/jwt/__init__.py32
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/__init__.cpython-311.pycbin1090 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/jwt_auth.cpython-311.pycbin481 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/jwt_token.cpython-311.pycbin354 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/middleware.cpython-311.pycbin432 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/jwt/jwt_auth.py5
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/jwt/jwt_token.py5
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/jwt/middleware.py5
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/mako.py146
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/minijinja.py216
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/minijnja.py18
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__init__.py4
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/__init__.cpython-311.pycbin395 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/_utils.cpython-311.pycbin1365 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/config.cpython-311.pycbin4141 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/middleware.cpython-311.pycbin3440 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/_utils.py31
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/config.py102
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/middleware.py60
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/piccolo.py107
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__init__.py5
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/__init__.cpython-311.pycbin447 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/config.cpython-311.pycbin3378 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/controller.cpython-311.pycbin2540 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/middleware.cpython-311.pycbin11494 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/prometheus/config.py64
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/prometheus/controller.py53
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/prometheus/middleware.py181
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__init__.py69
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/__init__.cpython-311.pycbin3609 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/config.cpython-311.pycbin207 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_di_plugin.cpython-311.pycbin2541 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_dto_factory.cpython-311.pycbin6096 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_init_plugin.cpython-311.pycbin11810 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_schema_plugin.cpython-311.pycbin14566 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/utils.cpython-311.pycbin10487 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/config.py0
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_di_plugin.py26
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_dto_factory.py110
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_init_plugin.py182
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_schema_plugin.py317
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/utils.py214
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/repository/__init__.py20
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/__init__.cpython-311.pycbin1212 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/exceptions.cpython-311.pycbin1258 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/filters.cpython-311.pycbin1242 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/handlers.cpython-311.pycbin1248 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/testing.cpython-311.pycbin1269 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/repository/abc/__init__.py20
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/repository/abc/__pycache__/__init__.cpython-311.pycbin1231 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/repository/exceptions.py20
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/repository/filters.py20
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/repository/handlers.py20
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/repository/testing.py20
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__init__.py0
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/__init__.cpython-311.pycbin211 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/base.cpython-311.pycbin1044 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/dto.cpython-311.pycbin412 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/types.cpython-311.pycbin487 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/base.py38
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/dto.py5
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/__init__.py28
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/__pycache__/__init__.cpython-311.pycbin895 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/__pycache__/serialization.cpython-311.pycbin414 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/__init__.py23
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/__pycache__/__init__.cpython-311.pycbin734 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/__pycache__/plugin.cpython-311.pycbin403 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__init__.py16
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/__init__.cpython-311.pycbin720 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/asyncio.cpython-311.pycbin1166 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/common.cpython-311.pycbin684 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/compat.cpython-311.pycbin1819 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/engine.cpython-311.pycbin388 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/sync.cpython-311.pycbin1136 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/asyncio.py24
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/common.py15
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/compat.py22
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/engine.py5
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/sync.py24
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/plugin.py5
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/serialization.py5
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__init__.py11
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/__init__.cpython-311.pycbin525 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/_async.cpython-311.pycbin389 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/_sync.cpython-311.pycbin389 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/_util.cpython-311.pycbin446 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/types.cpython-311.pycbin501 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/_async.py5
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/_sync.py7
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/_util.py8
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/types.py15
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/types.py11
-rw-r--r--venv/lib/python3.11/site-packages/litestar/controller.py262
-rw-r--r--venv/lib/python3.11/site-packages/litestar/data_extractors.py443
-rw-r--r--venv/lib/python3.11/site-packages/litestar/datastructures/__init__.py39
-rw-r--r--venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/__init__.cpython-311.pycbin1221 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/cookie.cpython-311.pycbin5293 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/headers.cpython-311.pycbin30616 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/multi_dicts.cpython-311.pycbin6713 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/response_header.cpython-311.pycbin2338 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/state.cpython-311.pycbin13750 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/upload_file.cpython-311.pycbin4572 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/url.cpython-311.pycbin10120 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/datastructures/cookie.py112
-rw-r--r--venv/lib/python3.11/site-packages/litestar/datastructures/headers.py534
-rw-r--r--venv/lib/python3.11/site-packages/litestar/datastructures/multi_dicts.py106
-rw-r--r--venv/lib/python3.11/site-packages/litestar/datastructures/response_header.py125
-rw-r--r--venv/lib/python3.11/site-packages/litestar/datastructures/state.py313
-rw-r--r--venv/lib/python3.11/site-packages/litestar/datastructures/upload_file.py101
-rw-r--r--venv/lib/python3.11/site-packages/litestar/datastructures/url.py262
-rw-r--r--venv/lib/python3.11/site-packages/litestar/di.py117
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/__init__.py20
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/__pycache__/__init__.cpython-311.pycbin767 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/__pycache__/_backend.cpython-311.pycbin37072 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/__pycache__/_codegen_backend.cpython-311.pycbin25679 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/__pycache__/_types.cpython-311.pycbin6040 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/__pycache__/base_dto.cpython-311.pycbin17356 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/__pycache__/config.cpython-311.pycbin2105 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/__pycache__/data_structures.cpython-311.pycbin5659 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/__pycache__/dataclass_dto.cpython-311.pycbin3798 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/__pycache__/field.cpython-311.pycbin2083 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/__pycache__/msgspec_dto.cpython-311.pycbin3747 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/__pycache__/types.cpython-311.pycbin645 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/_backend.py911
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/_codegen_backend.py541
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/_types.py148
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/base_dto.py313
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/config.py66
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/data_structures.py116
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/dataclass_dto.py58
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/field.py50
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/msgspec_dto.py54
-rw-r--r--venv/lib/python3.11/site-packages/litestar/dto/types.py13
-rw-r--r--venv/lib/python3.11/site-packages/litestar/enums.py90
-rw-r--r--venv/lib/python3.11/site-packages/litestar/events/__init__.py4
-rw-r--r--venv/lib/python3.11/site-packages/litestar/events/__pycache__/__init__.cpython-311.pycbin418 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/events/__pycache__/emitter.cpython-311.pycbin7064 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/events/__pycache__/listener.cpython-311.pycbin3902 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/events/emitter.py134
-rw-r--r--venv/lib/python3.11/site-packages/litestar/events/listener.py76
-rw-r--r--venv/lib/python3.11/site-packages/litestar/exceptions/__init__.py42
-rw-r--r--venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/__init__.cpython-311.pycbin1358 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/base_exceptions.cpython-311.pycbin4054 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/dto_exceptions.cpython-311.pycbin916 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/http_exceptions.cpython-311.pycbin7746 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/websocket_exceptions.cpython-311.pycbin2405 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/exceptions/base_exceptions.py57
-rw-r--r--venv/lib/python3.11/site-packages/litestar/exceptions/dto_exceptions.py13
-rw-r--r--venv/lib/python3.11/site-packages/litestar/exceptions/http_exceptions.py154
-rw-r--r--venv/lib/python3.11/site-packages/litestar/exceptions/websocket_exceptions.py40
-rw-r--r--venv/lib/python3.11/site-packages/litestar/file_system.py154
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/__init__.py29
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/__init__.cpython-311.pycbin919 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/asgi_handlers.cpython-311.pycbin5223 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/base.cpython-311.pycbin30837 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/asgi_handlers.py90
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/base.py577
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__init__.py15
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/__init__.cpython-311.pycbin584 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/_utils.cpython-311.pycbin9051 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/base.cpython-311.pycbin32501 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/decorators.cpython-311.pycbin58348 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/_utils.py221
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/base.py591
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/decorators.py1096
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__init__.py16
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/__init__.cpython-311.pycbin670 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/_utils.cpython-311.pycbin10594 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/listener.cpython-311.pycbin18940 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/route_handler.cpython-311.pycbin6002 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/_utils.py154
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/listener.py417
-rw-r--r--venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/route_handler.py99
-rw-r--r--venv/lib/python3.11/site-packages/litestar/logging/__init__.py3
-rw-r--r--venv/lib/python3.11/site-packages/litestar/logging/__pycache__/__init__.cpython-311.pycbin361 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/logging/__pycache__/_utils.cpython-311.pycbin1193 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/logging/__pycache__/config.cpython-311.pycbin21378 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/logging/__pycache__/picologging.cpython-311.pycbin2270 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/logging/__pycache__/standard.cpython-311.pycbin3336 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/logging/_utils.py22
-rw-r--r--venv/lib/python3.11/site-packages/litestar/logging/config.py509
-rw-r--r--venv/lib/python3.11/site-packages/litestar/logging/picologging.py39
-rw-r--r--venv/lib/python3.11/site-packages/litestar/logging/standard.py47
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/__init__.py17
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/__init__.cpython-311.pycbin577 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/_utils.cpython-311.pycbin3337 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/allowed_hosts.cpython-311.pycbin5598 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/authentication.cpython-311.pycbin5305 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/base.cpython-311.pycbin7186 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/cors.cpython-311.pycbin5093 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/csrf.cpython-311.pycbin9676 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/logging.cpython-311.pycbin16532 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/rate_limit.cpython-311.pycbin14990 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/response_cache.cpython-311.pycbin4386 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/_utils.py69
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/allowed_hosts.py79
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/authentication.py108
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/base.py151
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/compression/__init__.py4
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/__init__.cpython-311.pycbin441 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/brotli_facade.cpython-311.pycbin3028 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/facade.cpython-311.pycbin2116 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/gzip_facade.cpython-311.pycbin2152 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/middleware.cpython-311.pycbin8351 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/compression/brotli_facade.py51
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/compression/facade.py47
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/compression/gzip_facade.py32
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/compression/middleware.py191
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/cors.py84
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/csrf.py190
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/exceptions/__init__.py3
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/exceptions/__pycache__/__init__.cpython-311.pycbin336 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/exceptions/__pycache__/_debug_response.cpython-311.pycbin10669 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/exceptions/__pycache__/middleware.cpython-311.pycbin15666 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/exceptions/_debug_response.py210
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/exceptions/middleware.py316
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/exceptions/templates/body.html20
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/exceptions/templates/frame.html12
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/exceptions/templates/scripts.js27
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/exceptions/templates/styles.css121
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/logging.py360
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/rate_limit.py275
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/response_cache.py58
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/session/__init__.py3
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/session/__pycache__/__init__.cpython-311.pycbin287 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/session/__pycache__/base.cpython-311.pycbin11124 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/session/__pycache__/client_side.cpython-311.pycbin15608 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/session/__pycache__/server_side.cpython-311.pycbin12648 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/session/base.py256
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/session/client_side.py264
-rw-r--r--venv/lib/python3.11/site-packages/litestar/middleware/session/server_side.py219
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/__init__.py5
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/__pycache__/__init__.cpython-311.pycbin426 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/__pycache__/config.cpython-311.pycbin6524 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/__pycache__/controller.cpython-311.pycbin26502 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/__pycache__/datastructures.cpython-311.pycbin1507 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/config.py153
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/controller.py604
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/datastructures.py29
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__init__.py68
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/__init__.cpython-311.pycbin2323 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/base.cpython-311.pycbin4264 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/callback.cpython-311.pycbin627 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/components.cpython-311.pycbin3028 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/contact.cpython-311.pycbin931 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/discriminator.cpython-311.pycbin1378 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/encoding.cpython-311.pycbin1375 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/enums.cpython-311.pycbin1663 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/example.cpython-311.pycbin977 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/external_documentation.cpython-311.pycbin928 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/header.cpython-311.pycbin2591 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/info.cpython-311.pycbin1534 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/license.cpython-311.pycbin922 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/link.cpython-311.pycbin2021 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/media_type.cpython-311.pycbin1556 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/oauth_flow.cpython-311.pycbin1049 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/oauth_flows.cpython-311.pycbin1193 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/open_api.cpython-311.pycbin2562 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/operation.cpython-311.pycbin2460 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/parameter.cpython-311.pycbin2260 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/path_item.cpython-311.pycbin2175 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/paths.cpython-311.pycbin480 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/reference.cpython-311.pycbin1588 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/request_body.cpython-311.pycbin1132 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/response.cpython-311.pycbin1603 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/responses.cpython-311.pycbin633 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/schema.cpython-311.pycbin8205 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/security_requirement.cpython-311.pycbin430 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/security_scheme.cpython-311.pycbin2235 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/server.cpython-311.pycbin1127 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/server_variable.cpython-311.pycbin1002 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/tag.cpython-311.pycbin1327 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/xml.cpython-311.pycbin1308 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/base.py56
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/callback.py24
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/components.py72
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/contact.py21
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/discriminator.py25
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/encoding.py67
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/enums.py41
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/example.py33
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/external_documentation.py21
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/header.py121
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/info.py50
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/license.py28
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/link.py66
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/media_type.py51
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/oauth_flow.py36
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/oauth_flows.py28
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/open_api.py87
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/operation.py105
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/parameter.py136
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/path_item.py78
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/paths.py27
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/reference.py38
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/request_body.py38
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/response.py48
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/responses.py44
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/schema.py652
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/security_requirement.py30
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/security_scheme.py69
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/server.py34
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/server_variable.py32
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/tag.py32
-rw-r--r--venv/lib/python3.11/site-packages/litestar/openapi/spec/xml.py44
-rw-r--r--venv/lib/python3.11/site-packages/litestar/pagination.py342
-rw-r--r--venv/lib/python3.11/site-packages/litestar/params.py383
-rw-r--r--venv/lib/python3.11/site-packages/litestar/plugins/__init__.py23
-rw-r--r--venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/__init__.cpython-311.pycbin658 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/base.cpython-311.pycbin17349 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/core.cpython-311.pycbin1880 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/sqlalchemy.cpython-311.pycbin1365 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/structlog.cpython-311.pycbin3356 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/plugins/base.py323
-rw-r--r--venv/lib/python3.11/site-packages/litestar/plugins/core.py31
-rw-r--r--venv/lib/python3.11/site-packages/litestar/plugins/sqlalchemy.py54
-rw-r--r--venv/lib/python3.11/site-packages/litestar/plugins/structlog.py56
-rw-r--r--venv/lib/python3.11/site-packages/litestar/py.typed0
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/__init__.py14
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/__pycache__/__init__.cpython-311.pycbin609 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/__pycache__/_exceptions.cpython-311.pycbin1069 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/__pycache__/_filters.cpython-311.pycbin4350 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/__pycache__/exceptions.cpython-311.pycbin585 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/__pycache__/filters.cpython-311.pycbin898 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/__pycache__/handlers.cpython-311.pycbin1250 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/_exceptions.py15
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/_filters.py117
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/abc/__init__.py7
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/abc/__pycache__/__init__.cpython-311.pycbin373 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/abc/__pycache__/_async.cpython-311.pycbin13618 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/abc/__pycache__/_sync.cpython-311.pycbin13523 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/abc/_async.py303
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/abc/_sync.py305
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/exceptions.py7
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/filters.py37
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/handlers.py37
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/testing/__init__.py0
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/testing/__pycache__/__init__.cpython-311.pycbin211 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/testing/__pycache__/generic_mock_repository.cpython-311.pycbin32712 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/repository/testing/generic_mock_repository.py784
-rw-r--r--venv/lib/python3.11/site-packages/litestar/response/__init__.py16
-rw-r--r--venv/lib/python3.11/site-packages/litestar/response/__pycache__/__init__.cpython-311.pycbin624 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/response/__pycache__/base.cpython-311.pycbin21052 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/response/__pycache__/file.cpython-311.pycbin18534 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/response/__pycache__/redirect.cpython-311.pycbin7754 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/response/__pycache__/sse.cpython-311.pycbin11135 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/response/__pycache__/streaming.cpython-311.pycbin11735 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/response/__pycache__/template.cpython-311.pycbin7553 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/response/base.py459
-rw-r--r--venv/lib/python3.11/site-packages/litestar/response/file.py386
-rw-r--r--venv/lib/python3.11/site-packages/litestar/response/redirect.py169
-rw-r--r--venv/lib/python3.11/site-packages/litestar/response/sse.py180
-rw-r--r--venv/lib/python3.11/site-packages/litestar/response/streaming.py239
-rw-r--r--venv/lib/python3.11/site-packages/litestar/response/template.py162
-rw-r--r--venv/lib/python3.11/site-packages/litestar/router.py338
-rw-r--r--venv/lib/python3.11/site-packages/litestar/routes/__init__.py6
-rw-r--r--venv/lib/python3.11/site-packages/litestar/routes/__pycache__/__init__.cpython-311.pycbin461 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/routes/__pycache__/asgi.cpython-311.pycbin2874 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/routes/__pycache__/base.cpython-311.pycbin10362 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/routes/__pycache__/http.cpython-311.pycbin17069 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/routes/__pycache__/websocket.cpython-311.pycbin4417 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/routes/asgi.py54
-rw-r--r--venv/lib/python3.11/site-packages/litestar/routes/base.py195
-rw-r--r--venv/lib/python3.11/site-packages/litestar/routes/http.py327
-rw-r--r--venv/lib/python3.11/site-packages/litestar/routes/websocket.py86
-rw-r--r--venv/lib/python3.11/site-packages/litestar/security/__init__.py3
-rw-r--r--venv/lib/python3.11/site-packages/litestar/security/__pycache__/__init__.cpython-311.pycbin300 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/security/__pycache__/base.cpython-311.pycbin8315 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/security/base.py183
-rw-r--r--venv/lib/python3.11/site-packages/litestar/security/jwt/__init__.py23
-rw-r--r--venv/lib/python3.11/site-packages/litestar/security/jwt/__pycache__/__init__.cpython-311.pycbin733 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/security/jwt/__pycache__/auth.cpython-311.pycbin26027 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/security/jwt/__pycache__/middleware.cpython-311.pycbin8900 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/security/jwt/__pycache__/token.cpython-311.pycbin7141 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/security/jwt/auth.py691
-rw-r--r--venv/lib/python3.11/site-packages/litestar/security/jwt/middleware.py188
-rw-r--r--venv/lib/python3.11/site-packages/litestar/security/jwt/token.py119
-rw-r--r--venv/lib/python3.11/site-packages/litestar/security/session_auth/__init__.py4
-rw-r--r--venv/lib/python3.11/site-packages/litestar/security/session_auth/__pycache__/__init__.cpython-311.pycbin430 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/security/session_auth/__pycache__/auth.cpython-311.pycbin6483 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/security/session_auth/__pycache__/middleware.cpython-311.pycbin6705 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/security/session_auth/auth.py137
-rw-r--r--venv/lib/python3.11/site-packages/litestar/security/session_auth/middleware.py125
-rw-r--r--venv/lib/python3.11/site-packages/litestar/serialization/__init__.py19
-rw-r--r--venv/lib/python3.11/site-packages/litestar/serialization/__pycache__/__init__.cpython-311.pycbin553 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/serialization/__pycache__/msgspec_hooks.cpython-311.pycbin11120 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/serialization/msgspec_hooks.py261
-rw-r--r--venv/lib/python3.11/site-packages/litestar/static_files/__init__.py4
-rw-r--r--venv/lib/python3.11/site-packages/litestar/static_files/__pycache__/__init__.cpython-311.pycbin443 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/static_files/__pycache__/base.cpython-311.pycbin7052 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/static_files/__pycache__/config.cpython-311.pycbin10192 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/static_files/base.py141
-rw-r--r--venv/lib/python3.11/site-packages/litestar/static_files/config.py224
-rw-r--r--venv/lib/python3.11/site-packages/litestar/status_codes.py321
-rw-r--r--venv/lib/python3.11/site-packages/litestar/stores/__init__.py0
-rw-r--r--venv/lib/python3.11/site-packages/litestar/stores/__pycache__/__init__.cpython-311.pycbin199 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/stores/__pycache__/base.cpython-311.pycbin7661 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/stores/__pycache__/file.cpython-311.pycbin9799 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/stores/__pycache__/memory.cpython-311.pycbin7029 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/stores/__pycache__/redis.cpython-311.pycbin10088 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/stores/__pycache__/registry.cpython-311.pycbin3347 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/stores/base.py145
-rw-r--r--venv/lib/python3.11/site-packages/litestar/stores/file.py170
-rw-r--r--venv/lib/python3.11/site-packages/litestar/stores/memory.py115
-rw-r--r--venv/lib/python3.11/site-packages/litestar/stores/redis.py204
-rw-r--r--venv/lib/python3.11/site-packages/litestar/stores/registry.py64
-rw-r--r--venv/lib/python3.11/site-packages/litestar/template/__init__.py4
-rw-r--r--venv/lib/python3.11/site-packages/litestar/template/__pycache__/__init__.cpython-311.pycbin429 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/template/__pycache__/base.cpython-311.pycbin8587 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/template/__pycache__/config.cpython-311.pycbin3508 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/template/base.py187
-rw-r--r--venv/lib/python3.11/site-packages/litestar/template/config.py57
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/__init__.py16
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/__pycache__/__init__.cpython-311.pycbin825 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/__pycache__/helpers.cpython-311.pycbin30082 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/__pycache__/life_span_handler.cpython-311.pycbin5410 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/__pycache__/request_factory.cpython-311.pycbin22745 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/__pycache__/transport.cpython-311.pycbin12285 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/__pycache__/websocket_test_session.cpython-311.pycbin13624 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/client/__init__.py36
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/client/__pycache__/__init__.cpython-311.pycbin2091 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/client/__pycache__/async_client.cpython-311.pycbin17343 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/client/__pycache__/base.cpython-311.pycbin9397 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/client/__pycache__/sync_client.cpython-311.pycbin19167 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/client/async_client.py534
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/client/base.py180
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/client/sync_client.py593
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/helpers.py561
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/life_span_handler.py78
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/request_factory.py565
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/transport.py192
-rw-r--r--venv/lib/python3.11/site-packages/litestar/testing/websocket_test_session.py248
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/__init__.py169
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/__pycache__/__init__.cpython-311.pycbin4089 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/__pycache__/asgi_types.cpython-311.pycbin14027 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/__pycache__/builtin_types.cpython-311.pycbin946 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/__pycache__/callable_types.cpython-311.pycbin3380 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/__pycache__/composite_types.cpython-311.pycbin2623 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/__pycache__/empty.cpython-311.pycbin854 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/__pycache__/file_types.cpython-311.pycbin3731 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/__pycache__/helper_types.cpython-311.pycbin1673 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/__pycache__/internal_types.cpython-311.pycbin2912 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/__pycache__/protocols.cpython-311.pycbin4503 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/__pycache__/serialization.cpython-311.pycbin2826 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/asgi_types.py343
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/builtin_types.py25
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/callable_types.py40
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/composite_types.py56
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/empty.py16
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/file_types.py106
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/helper_types.py47
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/internal_types.py58
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/protocols.py113
-rw-r--r--venv/lib/python3.11/site-packages/litestar/types/serialization.py59
-rw-r--r--venv/lib/python3.11/site-packages/litestar/typing.py636
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/__init__.py86
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/__pycache__/__init__.cpython-311.pycbin2776 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/__pycache__/compat.cpython-311.pycbin1318 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/__pycache__/dataclass.cpython-311.pycbin5552 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/__pycache__/deprecation.cpython-311.pycbin4935 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/__pycache__/empty.cpython-311.pycbin1119 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/__pycache__/helpers.cpython-311.pycbin3766 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/__pycache__/module_loader.cpython-311.pycbin4182 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/__pycache__/path.cpython-311.pycbin1378 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/__pycache__/predicates.cpython-311.pycbin13096 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/__pycache__/sequence.cpython-311.pycbin1693 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/__pycache__/signature.cpython-311.pycbin12352 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/__pycache__/sync.cpython-311.pycbin4474 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/__pycache__/typing.cpython-311.pycbin11547 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/__pycache__/version.cpython-311.pycbin3395 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/__pycache__/warnings.cpython-311.pycbin2914 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/compat.py27
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/dataclass.py115
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/deprecation.py111
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/empty.py26
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/helpers.py103
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/module_loader.py92
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/path.py35
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/predicates.py339
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/scope/__init__.py62
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/scope/__pycache__/__init__.cpython-311.pycbin2727 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/scope/__pycache__/state.cpython-311.pycbin6672 -> 0 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/scope/state.py158
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/sequence.py28
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/signature.py267
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/sync.py79
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/typing.py284
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/version.py62
-rw-r--r--venv/lib/python3.11/site-packages/litestar/utils/warnings.py51
678 files changed, 0 insertions, 44681 deletions
diff --git a/venv/lib/python3.11/site-packages/litestar/__init__.py b/venv/lib/python3.11/site-packages/litestar/__init__.py
deleted file mode 100644
index 3235113..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__init__.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from litestar.app import Litestar
-from litestar.connection import Request, WebSocket
-from litestar.controller import Controller
-from litestar.enums import HttpMethod, MediaType
-from litestar.handlers import asgi, delete, get, head, patch, post, put, route, websocket, websocket_listener
-from litestar.response import Response
-from litestar.router import Router
-from litestar.utils.version import get_version
-
-__version__ = get_version()
-
-
-__all__ = (
- "Controller",
- "HttpMethod",
- "Litestar",
- "MediaType",
- "Request",
- "Response",
- "Router",
- "WebSocket",
- "__version__",
- "asgi",
- "delete",
- "get",
- "head",
- "patch",
- "post",
- "put",
- "route",
- "websocket",
- "websocket_listener",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/__main__.py b/venv/lib/python3.11/site-packages/litestar/__main__.py
deleted file mode 100644
index 92f2d86..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__main__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from litestar.cli.main import litestar_group
-
-
-def run_cli() -> None:
- """Application Entrypoint."""
- litestar_group()
-
-
-if __name__ == "__main__":
- run_cli()
diff --git a/venv/lib/python3.11/site-packages/litestar/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 5a8d532..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/__pycache__/__main__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/__pycache__/__main__.cpython-311.pyc
deleted file mode 100644
index 874c61f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__pycache__/__main__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/__pycache__/_multipart.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/__pycache__/_multipart.cpython-311.pyc
deleted file mode 100644
index 62b625c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__pycache__/_multipart.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/__pycache__/_parsers.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/__pycache__/_parsers.cpython-311.pyc
deleted file mode 100644
index 0ea2061..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__pycache__/_parsers.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/__pycache__/app.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/__pycache__/app.cpython-311.pyc
deleted file mode 100644
index 833a1a8..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__pycache__/app.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/__pycache__/background_tasks.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/__pycache__/background_tasks.cpython-311.pyc
deleted file mode 100644
index 750190c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__pycache__/background_tasks.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/__pycache__/concurrency.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/__pycache__/concurrency.cpython-311.pyc
deleted file mode 100644
index e3f82cf..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__pycache__/concurrency.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/__pycache__/constants.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/__pycache__/constants.cpython-311.pyc
deleted file mode 100644
index a95a8b4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__pycache__/constants.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/__pycache__/controller.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/__pycache__/controller.cpython-311.pyc
deleted file mode 100644
index 4c7556c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__pycache__/controller.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/__pycache__/data_extractors.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/__pycache__/data_extractors.cpython-311.pyc
deleted file mode 100644
index 379a991..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__pycache__/data_extractors.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/__pycache__/di.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/__pycache__/di.cpython-311.pyc
deleted file mode 100644
index 224cd6a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__pycache__/di.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/__pycache__/enums.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/__pycache__/enums.cpython-311.pyc
deleted file mode 100644
index de5d781..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__pycache__/enums.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/__pycache__/file_system.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/__pycache__/file_system.cpython-311.pyc
deleted file mode 100644
index fef4f7e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__pycache__/file_system.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/__pycache__/pagination.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/__pycache__/pagination.cpython-311.pyc
deleted file mode 100644
index 99feb13..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__pycache__/pagination.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/__pycache__/params.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/__pycache__/params.cpython-311.pyc
deleted file mode 100644
index 6fb5e43..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__pycache__/params.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/__pycache__/router.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/__pycache__/router.cpython-311.pyc
deleted file mode 100644
index 26d45d8..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__pycache__/router.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/__pycache__/status_codes.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/__pycache__/status_codes.cpython-311.pyc
deleted file mode 100644
index b18ebee..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__pycache__/status_codes.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/__pycache__/typing.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/__pycache__/typing.cpython-311.pyc
deleted file mode 100644
index 98e4dd1..0000000
--- a/venv/lib/python3.11/site-packages/litestar/__pycache__/typing.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_asgi/__init__.py b/venv/lib/python3.11/site-packages/litestar/_asgi/__init__.py
deleted file mode 100644
index 4cb42ad..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_asgi/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from litestar._asgi.asgi_router import ASGIRouter
-
-__all__ = ("ASGIRouter",)
diff --git a/venv/lib/python3.11/site-packages/litestar/_asgi/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_asgi/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 9b12b52..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_asgi/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_asgi/__pycache__/asgi_router.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_asgi/__pycache__/asgi_router.cpython-311.pyc
deleted file mode 100644
index 75c2cdb..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_asgi/__pycache__/asgi_router.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_asgi/__pycache__/utils.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_asgi/__pycache__/utils.cpython-311.pyc
deleted file mode 100644
index 2e9f267..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_asgi/__pycache__/utils.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_asgi/asgi_router.py b/venv/lib/python3.11/site-packages/litestar/_asgi/asgi_router.py
deleted file mode 100644
index ebafaf0..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_asgi/asgi_router.py
+++ /dev/null
@@ -1,184 +0,0 @@
-from __future__ import annotations
-
-import re
-from collections import defaultdict
-from functools import lru_cache
-from traceback import format_exc
-from typing import TYPE_CHECKING, Any, Pattern
-
-from litestar._asgi.routing_trie import validate_node
-from litestar._asgi.routing_trie.mapping import add_route_to_trie
-from litestar._asgi.routing_trie.traversal import parse_path_to_route
-from litestar._asgi.routing_trie.types import create_node
-from litestar._asgi.utils import get_route_handlers
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.utils import normalize_path
-
-__all__ = ("ASGIRouter",)
-
-
-if TYPE_CHECKING:
- from litestar._asgi.routing_trie.types import RouteTrieNode
- from litestar.app import Litestar
- from litestar.routes import ASGIRoute, HTTPRoute, WebSocketRoute
- from litestar.routes.base import BaseRoute
- from litestar.types import (
- ASGIApp,
- LifeSpanReceive,
- LifeSpanSend,
- LifeSpanShutdownCompleteEvent,
- LifeSpanShutdownFailedEvent,
- LifeSpanStartupCompleteEvent,
- LifeSpanStartupFailedEvent,
- Method,
- Receive,
- RouteHandlerType,
- Scope,
- Send,
- )
-
-
-class ASGIRouter:
- """Litestar ASGI router.
-
- Handling both the ASGI lifespan events and routing of connection requests.
- """
-
- __slots__ = (
- "_mount_paths_regex",
- "_mount_routes",
- "_plain_routes",
- "_registered_routes",
- "_static_routes",
- "app",
- "root_route_map_node",
- "route_handler_index",
- "route_mapping",
- )
-
- def __init__(self, app: Litestar) -> None:
- """Initialize ``ASGIRouter``.
-
- Args:
- app: The Litestar app instance
- """
- self._mount_paths_regex: Pattern | None = None
- self._mount_routes: dict[str, RouteTrieNode] = {}
- self._plain_routes: set[str] = set()
- self._registered_routes: set[HTTPRoute | WebSocketRoute | ASGIRoute] = set()
- self.app = app
- self.root_route_map_node: RouteTrieNode = create_node()
- self.route_handler_index: dict[str, RouteHandlerType] = {}
- self.route_mapping: dict[str, list[BaseRoute]] = defaultdict(list)
-
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
- """ASGI callable.
-
- The main entry point to the Router class.
- """
- scope.setdefault("path_params", {})
-
- path = scope["path"]
- if root_path := scope.get("root_path", ""):
- path = path.split(root_path, maxsplit=1)[-1]
- normalized_path = normalize_path(path)
-
- asgi_app, scope["route_handler"], scope["path"], scope["path_params"] = self.handle_routing(
- path=normalized_path, method=scope.get("method")
- )
- await asgi_app(scope, receive, send)
-
- @lru_cache(1024) # noqa: B019
- def handle_routing(self, path: str, method: Method | None) -> tuple[ASGIApp, RouteHandlerType, str, dict[str, Any]]:
- """Handle routing for a given path / method combo. This method is meant to allow easy caching.
-
- Args:
- path: The path of the request.
- method: The scope's method, if any.
-
- Returns:
- A tuple composed of the ASGIApp of the route, the route handler instance, the resolved and normalized path and any parsed path params.
- """
- return parse_path_to_route(
- mount_paths_regex=self._mount_paths_regex,
- mount_routes=self._mount_routes,
- path=path,
- plain_routes=self._plain_routes,
- root_node=self.root_route_map_node,
- method=method,
- )
-
- def _store_handler_to_route_mapping(self, route: BaseRoute) -> None:
- """Store the mapping of route handlers to routes and to route handler names.
-
- Args:
- route: A Route instance.
-
- Returns:
- None
- """
-
- for handler in get_route_handlers(route):
- if handler.name in self.route_handler_index and str(self.route_handler_index[handler.name]) != str(handler):
- raise ImproperlyConfiguredException(
- f"route handler names must be unique - {handler.name} is not unique."
- )
- identifier = handler.name or str(handler)
- self.route_mapping[identifier].append(route)
- self.route_handler_index[identifier] = handler
-
- def construct_routing_trie(self) -> None:
- """Create a map of the app's routes.
-
- This map is used in the asgi router to route requests.
- """
- new_routes = [route for route in self.app.routes if route not in self._registered_routes]
- for route in new_routes:
- add_route_to_trie(
- app=self.app,
- mount_routes=self._mount_routes,
- plain_routes=self._plain_routes,
- root_node=self.root_route_map_node,
- route=route,
- )
- self._store_handler_to_route_mapping(route)
- self._registered_routes.add(route)
-
- validate_node(node=self.root_route_map_node)
- if self._mount_routes:
- self._mount_paths_regex = re.compile("|".join(sorted(set(self._mount_routes)))) # pyright: ignore
-
- async def lifespan(self, receive: LifeSpanReceive, send: LifeSpanSend) -> None:
- """Handle the ASGI "lifespan" event on application startup and shutdown.
-
- Args:
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None.
- """
-
- message = await receive()
- shutdown_event: LifeSpanShutdownCompleteEvent = {"type": "lifespan.shutdown.complete"}
- startup_event: LifeSpanStartupCompleteEvent = {"type": "lifespan.startup.complete"}
-
- try:
- async with self.app.lifespan():
- await send(startup_event)
- message = await receive()
-
- except BaseException as e:
- formatted_exception = format_exc()
- failure_message: LifeSpanStartupFailedEvent | LifeSpanShutdownFailedEvent
-
- if message["type"] == "lifespan.startup":
- failure_message = {"type": "lifespan.startup.failed", "message": formatted_exception}
- else:
- failure_message = {"type": "lifespan.shutdown.failed", "message": formatted_exception}
-
- await send(failure_message)
-
- raise e
-
- await send(shutdown_event)
diff --git a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__init__.py b/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__init__.py
deleted file mode 100644
index 948e394..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from litestar._asgi.routing_trie.mapping import add_route_to_trie
-from litestar._asgi.routing_trie.traversal import parse_path_to_route
-from litestar._asgi.routing_trie.types import RouteTrieNode
-from litestar._asgi.routing_trie.validate import validate_node
-
-__all__ = ("RouteTrieNode", "add_route_to_trie", "parse_path_to_route", "validate_node")
diff --git a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index f8658f9..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/mapping.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/mapping.cpython-311.pyc
deleted file mode 100644
index 73323bf..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/mapping.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/traversal.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/traversal.cpython-311.pyc
deleted file mode 100644
index 9ed2983..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/traversal.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/types.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/types.cpython-311.pyc
deleted file mode 100644
index 5247c5b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/types.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/validate.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/validate.cpython-311.pyc
deleted file mode 100644
index 57fdcdd..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/__pycache__/validate.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/mapping.py b/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/mapping.py
deleted file mode 100644
index 7a56b97..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/mapping.py
+++ /dev/null
@@ -1,221 +0,0 @@
-from __future__ import annotations
-
-from pathlib import Path
-from typing import TYPE_CHECKING, Any, cast
-
-from litestar._asgi.routing_trie.types import (
- ASGIHandlerTuple,
- PathParameterSentinel,
- create_node,
-)
-from litestar._asgi.utils import wrap_in_exception_handler
-from litestar.types.internal_types import PathParameterDefinition
-
-__all__ = ("add_mount_route", "add_route_to_trie", "build_route_middleware_stack", "configure_node")
-
-
-if TYPE_CHECKING:
- from litestar._asgi.routing_trie.types import RouteTrieNode
- from litestar.app import Litestar
- from litestar.routes import ASGIRoute, HTTPRoute, WebSocketRoute
- from litestar.types import ASGIApp, RouteHandlerType
-
-
-def add_mount_route(
- current_node: RouteTrieNode,
- mount_routes: dict[str, RouteTrieNode],
- root_node: RouteTrieNode,
- route: ASGIRoute,
-) -> RouteTrieNode:
- """Add a node for a mount route.
-
- Args:
- current_node: The current trie node that is being mapped.
- mount_routes: A dictionary mapping static routes to trie nodes.
- root_node: The root trie node.
- route: The route that is being added.
-
- Returns:
- A trie node.
- """
-
- # we need to ensure that we can traverse the map both through the full path key, e.g. "/my-route/sub-path" and
- # via the components keys ["my-route, "sub-path"]
- if route.path not in current_node.children:
- root_node = current_node
- for component in route.path_components:
- if component not in current_node.children:
- current_node.children[component] = create_node() # type: ignore[index]
- current_node = current_node.children[component] # type: ignore[index]
-
- current_node.is_mount = True
- current_node.is_static = route.route_handler.is_static
-
- if route.path != "/":
- mount_routes[route.path] = root_node.children[route.path] = current_node
- else:
- mount_routes[route.path] = current_node
-
- return current_node
-
-
-def add_route_to_trie(
- app: Litestar,
- mount_routes: dict[str, RouteTrieNode],
- plain_routes: set[str],
- root_node: RouteTrieNode,
- route: HTTPRoute | WebSocketRoute | ASGIRoute,
-) -> RouteTrieNode:
- """Add a new route path (e.g. '/foo/bar/{param:int}') into the route_map tree.
-
- Inserts non-parameter paths ('plain routes') off the tree's root
- node. For paths containing parameters, splits the path on '/' and
- nests each path segment under the previous segment's node (see
- prefix tree / trie).
-
- Args:
- app: The Litestar app instance.
- mount_routes: A dictionary mapping static routes to trie nodes.
- plain_routes: A set of routes that do not have path parameters.
- root_node: The root trie node.
- route: The route that is being added.
-
- Returns:
- A RouteTrieNode instance.
- """
- current_node = root_node
-
- has_path_parameters = bool(route.path_parameters)
-
- if (route_handler := getattr(route, "route_handler", None)) and getattr(route_handler, "is_mount", False):
- current_node = add_mount_route(
- current_node=current_node,
- mount_routes=mount_routes,
- root_node=root_node,
- route=cast("ASGIRoute", route),
- )
-
- elif not has_path_parameters:
- plain_routes.add(route.path)
- if route.path not in root_node.children:
- current_node.children[route.path] = create_node()
- current_node = root_node.children[route.path]
-
- else:
- for component in route.path_components:
- if isinstance(component, PathParameterDefinition):
- current_node.is_path_param_node = True
- next_node_key: type[PathParameterSentinel] | str = PathParameterSentinel
-
- else:
- next_node_key = component
-
- if next_node_key not in current_node.children:
- current_node.children[next_node_key] = create_node()
-
- current_node.child_keys = set(current_node.children.keys())
- current_node = current_node.children[next_node_key]
-
- if isinstance(component, PathParameterDefinition) and component.type is Path:
- current_node.is_path_type = True
-
- configure_node(route=route, app=app, node=current_node)
- return current_node
-
-
-def configure_node(
- app: Litestar,
- route: HTTPRoute | WebSocketRoute | ASGIRoute,
- node: RouteTrieNode,
-) -> None:
- """Set required attributes and route handlers on route_map tree node.
-
- Args:
- app: The Litestar app instance.
- route: The route that is being added.
- node: The trie node being configured.
-
- Returns:
- None
- """
- from litestar.routes import HTTPRoute, WebSocketRoute
-
- if not node.path_parameters:
- node.path_parameters = {}
-
- if isinstance(route, HTTPRoute):
- for method, handler_mapping in route.route_handler_map.items():
- handler, _ = handler_mapping
- node.asgi_handlers[method] = ASGIHandlerTuple(
- asgi_app=build_route_middleware_stack(app=app, route=route, route_handler=handler),
- handler=handler,
- )
- node.path_parameters[method] = route.path_parameters
-
- elif isinstance(route, WebSocketRoute):
- node.asgi_handlers["websocket"] = ASGIHandlerTuple(
- asgi_app=build_route_middleware_stack(app=app, route=route, route_handler=route.route_handler),
- handler=route.route_handler,
- )
- node.path_parameters["websocket"] = route.path_parameters
-
- else:
- node.asgi_handlers["asgi"] = ASGIHandlerTuple(
- asgi_app=build_route_middleware_stack(app=app, route=route, route_handler=route.route_handler),
- handler=route.route_handler,
- )
- node.path_parameters["asgi"] = route.path_parameters
- node.is_asgi = True
-
-
-def build_route_middleware_stack(
- app: Litestar,
- route: HTTPRoute | WebSocketRoute | ASGIRoute,
- route_handler: RouteHandlerType,
-) -> ASGIApp:
- """Construct a middleware stack that serves as the point of entry for each route.
-
- Args:
- app: The Litestar app instance.
- route: The route that is being added.
- route_handler: The route handler that is being wrapped.
-
- Returns:
- An ASGIApp that is composed of a "stack" of middlewares.
- """
- from litestar.middleware.allowed_hosts import AllowedHostsMiddleware
- from litestar.middleware.compression import CompressionMiddleware
- from litestar.middleware.csrf import CSRFMiddleware
- from litestar.middleware.response_cache import ResponseCacheMiddleware
- from litestar.routes import HTTPRoute
-
- # we wrap the route.handle method in the ExceptionHandlerMiddleware
- asgi_handler = wrap_in_exception_handler(
- app=route.handle, # type: ignore[arg-type]
- exception_handlers=route_handler.resolve_exception_handlers(),
- )
-
- if app.csrf_config:
- asgi_handler = CSRFMiddleware(app=asgi_handler, config=app.csrf_config)
-
- if app.compression_config:
- asgi_handler = CompressionMiddleware(app=asgi_handler, config=app.compression_config)
-
- if isinstance(route, HTTPRoute) and any(r.cache for r in route.route_handlers):
- asgi_handler = ResponseCacheMiddleware(app=asgi_handler, config=app.response_cache_config)
-
- if app.allowed_hosts:
- asgi_handler = AllowedHostsMiddleware(app=asgi_handler, config=app.allowed_hosts)
-
- for middleware in route_handler.resolve_middleware():
- if hasattr(middleware, "__iter__"):
- handler, kwargs = cast("tuple[Any, dict[str, Any]]", middleware)
- asgi_handler = handler(app=asgi_handler, **kwargs)
- else:
- asgi_handler = middleware(app=asgi_handler) # type: ignore[call-arg]
-
- # we wrap the entire stack again in ExceptionHandlerMiddleware
- return wrap_in_exception_handler(
- app=cast("ASGIApp", asgi_handler),
- exception_handlers=route_handler.resolve_exception_handlers(),
- ) # pyright: ignore
diff --git a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/traversal.py b/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/traversal.py
deleted file mode 100644
index b7788bd..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/traversal.py
+++ /dev/null
@@ -1,170 +0,0 @@
-from __future__ import annotations
-
-from functools import lru_cache
-from typing import TYPE_CHECKING, Any, Pattern
-
-from litestar._asgi.routing_trie.types import PathParameterSentinel
-from litestar.exceptions import MethodNotAllowedException, NotFoundException
-from litestar.utils import normalize_path
-
-__all__ = ("parse_node_handlers", "parse_path_params", "parse_path_to_route", "traverse_route_map")
-
-
-if TYPE_CHECKING:
- from litestar._asgi.routing_trie.types import ASGIHandlerTuple, RouteTrieNode
- from litestar.types import ASGIApp, Method, RouteHandlerType
- from litestar.types.internal_types import PathParameterDefinition
-
-
-def traverse_route_map(
- root_node: RouteTrieNode,
- path: str,
-) -> tuple[RouteTrieNode, list[str], str]:
- """Traverses the application route mapping and retrieves the correct node for the request url.
-
- Args:
- root_node: The root trie node.
- path: The request's path.
-
- Raises:
- NotFoundException: If no correlating node is found.
-
- Returns:
- A tuple containing the target RouteMapNode and a list containing all path parameter values.
- """
- current_node = root_node
- path_params: list[str] = []
- path_components = [p for p in path.split("/") if p]
-
- for i, component in enumerate(path_components):
- if component in current_node.child_keys:
- current_node = current_node.children[component]
- continue
-
- if current_node.is_path_param_node:
- current_node = current_node.children[PathParameterSentinel]
-
- if current_node.is_path_type:
- path_params.append(normalize_path("/".join(path_components[i:])))
- break
-
- path_params.append(component)
- continue
-
- raise NotFoundException()
-
- if not current_node.asgi_handlers:
- raise NotFoundException()
-
- return current_node, path_params, path
-
-
-def parse_node_handlers(
- node: RouteTrieNode,
- method: Method | None,
-) -> ASGIHandlerTuple:
- """Retrieve the handler tuple from the node.
-
- Args:
- node: The trie node to parse.
- method: The scope's method.
-
- Raises:
- KeyError: If no matching method is found.
-
- Returns:
- An ASGI Handler tuple.
- """
-
- if node.is_asgi:
- return node.asgi_handlers["asgi"]
- if method:
- return node.asgi_handlers[method]
- return node.asgi_handlers["websocket"]
-
-
-@lru_cache(1024)
-def parse_path_params(
- parameter_definitions: tuple[PathParameterDefinition, ...], path_param_values: tuple[str, ...]
-) -> dict[str, Any]:
- """Parse path parameters into a dictionary of values.
-
- Args:
- parameter_definitions: The parameter definitions tuple from the route.
- path_param_values: The string values extracted from the url
-
- Raises:
- ValueError: If any of path parameters can not be parsed into a value.
-
- Returns:
- A dictionary of parsed path parameters.
- """
- return {
- param_definition.name: param_definition.parser(value) if param_definition.parser else value
- for param_definition, value in zip(parameter_definitions, path_param_values)
- }
-
-
-def parse_path_to_route(
- method: Method | None,
- mount_paths_regex: Pattern | None,
- mount_routes: dict[str, RouteTrieNode],
- path: str,
- plain_routes: set[str],
- root_node: RouteTrieNode,
-) -> tuple[ASGIApp, RouteHandlerType, str, dict[str, Any]]:
- """Given a scope object, retrieve the asgi_handlers and is_mount boolean values from correct trie node.
-
- Args:
- method: The scope's method, if any.
- root_node: The root trie node.
- path: The path to resolve scope instance.
- plain_routes: The set of plain routes.
- mount_routes: Mapping of mount routes to trie nodes.
- mount_paths_regex: A compiled regex to match the mount routes.
-
- Raises:
- MethodNotAllowedException: if no matching method is found.
- NotFoundException: If no correlating node is found or if path params can not be parsed into values according to the node definition.
-
- Returns:
- A tuple containing the stack of middlewares and the route handler that is wrapped by it.
- """
-
- try:
- if path in plain_routes:
- asgi_app, handler = parse_node_handlers(node=root_node.children[path], method=method)
- return asgi_app, handler, path, {}
-
- if mount_paths_regex and (match := mount_paths_regex.search(path)):
- mount_path = path[match.start() : match.end()]
- mount_node = mount_routes[mount_path]
- remaining_path = path[match.end() :]
- # since we allow regular handlers under static paths, we must validate that the request does not match
- # any such handler.
- children = [sub_route for sub_route in mount_node.children or [] if sub_route != mount_path]
- if not children or all(sub_route not in path for sub_route in children): # type: ignore[operator]
- asgi_app, handler = parse_node_handlers(node=mount_node, method=method)
- remaining_path = remaining_path or "/"
- if not mount_node.is_static:
- remaining_path = remaining_path if remaining_path.endswith("/") else f"{remaining_path}/"
- return asgi_app, handler, remaining_path, {}
-
- node, path_parameters, path = traverse_route_map(
- root_node=root_node,
- path=path,
- )
- asgi_app, handler = parse_node_handlers(node=node, method=method)
- key = method or ("asgi" if node.is_asgi else "websocket")
- parsed_path_parameters = parse_path_params(node.path_parameters[key], tuple(path_parameters))
-
- return (
- asgi_app,
- handler,
- path,
- parsed_path_parameters,
- )
- except KeyError as e:
- raise MethodNotAllowedException() from e
- except ValueError as e:
- raise NotFoundException() from e
diff --git a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/types.py b/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/types.py
deleted file mode 100644
index d1fc368..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/types.py
+++ /dev/null
@@ -1,85 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING, Literal, NamedTuple
-
-__all__ = ("ASGIHandlerTuple", "PathParameterSentinel", "RouteTrieNode", "create_node")
-
-
-if TYPE_CHECKING:
- from litestar.types import ASGIApp, Method, RouteHandlerType
- from litestar.types.internal_types import PathParameterDefinition
-
-
-class PathParameterSentinel:
- """Sentinel class designating a path parameter."""
-
-
-class ASGIHandlerTuple(NamedTuple):
- """Encapsulation of a route handler node."""
-
- asgi_app: ASGIApp
- """An ASGI stack, composed of a handler function and layers of middleware that wrap it."""
- handler: RouteHandlerType
- """The route handler instance."""
-
-
-@dataclass(unsafe_hash=True)
-class RouteTrieNode:
- """A radix trie node."""
-
- __slots__ = (
- "asgi_handlers",
- "child_keys",
- "children",
- "is_asgi",
- "is_mount",
- "is_static",
- "is_path_param_node",
- "is_path_type",
- "path_parameters",
- )
-
- asgi_handlers: dict[Method | Literal["websocket", "asgi"], ASGIHandlerTuple]
- """A mapping of ASGI handlers stored on the node."""
- child_keys: set[str | type[PathParameterSentinel]]
- """
- A set containing the child keys, same as the children dictionary - but as a set, which offers faster lookup.
- """
- children: dict[str | type[PathParameterSentinel], RouteTrieNode]
- """A dictionary mapping path components or using the PathParameterSentinel class to child nodes."""
- is_path_param_node: bool
- """Designates the node as having a path parameter."""
- is_path_type: bool
- """Designates the node as having a 'path' type path parameter."""
- is_asgi: bool
- """Designate the node as having an `asgi` type handler."""
- is_mount: bool
- """Designate the node as being a mount route."""
- is_static: bool
- """Designate the node as being a static mount route."""
- path_parameters: dict[Method | Literal["websocket"] | Literal["asgi"], tuple[PathParameterDefinition, ...]]
- """A list of tuples containing path parameter definitions.
-
- This is used for parsing extracted path parameter values.
- """
-
-
-def create_node() -> RouteTrieNode:
- """Create a RouteMapNode instance.
-
- Returns:
- A route map node instance.
- """
-
- return RouteTrieNode(
- asgi_handlers={},
- child_keys=set(),
- children={},
- is_path_param_node=False,
- is_asgi=False,
- is_mount=False,
- is_static=False,
- is_path_type=False,
- path_parameters={},
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/validate.py b/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/validate.py
deleted file mode 100644
index 5c29fac..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/validate.py
+++ /dev/null
@@ -1,47 +0,0 @@
-from __future__ import annotations
-
-from itertools import chain
-from typing import TYPE_CHECKING
-
-from litestar.exceptions import ImproperlyConfiguredException
-
-__all__ = ("validate_node",)
-
-
-if TYPE_CHECKING:
- from litestar._asgi.routing_trie.types import RouteTrieNode
-
-
-def validate_node(node: RouteTrieNode) -> None:
- """Recursively traverses the trie from the given node upwards.
-
- Args:
- node: A trie node.
-
- Raises:
- ImproperlyConfiguredException
-
- Returns:
- None
- """
- if node.is_asgi and bool(set(node.asgi_handlers).difference({"asgi"})):
- raise ImproperlyConfiguredException("ASGI handlers must have a unique path not shared by other route handlers.")
-
- if (
- node.is_mount
- and node.children
- and any(
- chain.from_iterable(
- list(child.path_parameters.values())
- if isinstance(child.path_parameters, dict)
- else child.path_parameters
- for child in node.children.values()
- )
- )
- ):
- raise ImproperlyConfiguredException("Path parameters are not allowed under a static or mount route.")
-
- for child in node.children.values():
- if child is node:
- continue
- validate_node(node=child)
diff --git a/venv/lib/python3.11/site-packages/litestar/_asgi/utils.py b/venv/lib/python3.11/site-packages/litestar/_asgi/utils.py
deleted file mode 100644
index c4111e0..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_asgi/utils.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, cast
-
-__all__ = ("get_route_handlers", "wrap_in_exception_handler")
-
-
-if TYPE_CHECKING:
- from litestar.routes import ASGIRoute, HTTPRoute, WebSocketRoute
- from litestar.routes.base import BaseRoute
- from litestar.types import ASGIApp, ExceptionHandlersMap, RouteHandlerType
-
-
-def wrap_in_exception_handler(app: ASGIApp, exception_handlers: ExceptionHandlersMap) -> ASGIApp:
- """Wrap the given ASGIApp in an instance of ExceptionHandlerMiddleware.
-
- Args:
- app: The ASGI app that is being wrapped.
- exception_handlers: A mapping of exceptions to handler functions.
-
- Returns:
- A wrapped ASGIApp.
- """
- from litestar.middleware.exceptions import ExceptionHandlerMiddleware
-
- return ExceptionHandlerMiddleware(app=app, exception_handlers=exception_handlers, debug=None)
-
-
-def get_route_handlers(route: BaseRoute) -> list[RouteHandlerType]:
- """Retrieve handler(s) as a list for given route.
-
- Args:
- route: The route from which the route handlers are extracted.
-
- Returns:
- The route handlers defined on the route.
- """
- route_handlers: list[RouteHandlerType] = []
- if hasattr(route, "route_handlers"):
- route_handlers.extend(cast("HTTPRoute", route).route_handlers)
- else:
- route_handlers.append(cast("WebSocketRoute | ASGIRoute", route).route_handler)
-
- return route_handlers
diff --git a/venv/lib/python3.11/site-packages/litestar/_kwargs/__init__.py b/venv/lib/python3.11/site-packages/litestar/_kwargs/__init__.py
deleted file mode 100644
index af8ad36..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_kwargs/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from .kwargs_model import KwargsModel
-
-__all__ = ("KwargsModel",)
diff --git a/venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index b61cc1b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/cleanup.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/cleanup.cpython-311.pyc
deleted file mode 100644
index a084eb5..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/cleanup.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/dependencies.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/dependencies.cpython-311.pyc
deleted file mode 100644
index b0f49a4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/dependencies.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/extractors.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/extractors.cpython-311.pyc
deleted file mode 100644
index 35a6e40..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/extractors.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/kwargs_model.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/kwargs_model.cpython-311.pyc
deleted file mode 100644
index 17029de..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/kwargs_model.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/parameter_definition.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/parameter_definition.cpython-311.pyc
deleted file mode 100644
index 10753dc..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_kwargs/__pycache__/parameter_definition.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_kwargs/cleanup.py b/venv/lib/python3.11/site-packages/litestar/_kwargs/cleanup.py
deleted file mode 100644
index 8839d36..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_kwargs/cleanup.py
+++ /dev/null
@@ -1,117 +0,0 @@
-from __future__ import annotations
-
-from inspect import Traceback, isasyncgen
-from typing import TYPE_CHECKING, Any, AsyncGenerator, Awaitable, Callable, Generator
-
-from anyio import create_task_group
-
-from litestar.utils import ensure_async_callable
-from litestar.utils.compat import async_next
-
-__all__ = ("DependencyCleanupGroup",)
-
-
-if TYPE_CHECKING:
- from litestar.types import AnyGenerator
-
-
-class DependencyCleanupGroup:
- """Wrapper for generator based dependencies.
-
- Simplify cleanup by wrapping :func:`next` / :func:`anext` calls and providing facilities to
- :meth:`throw <generator.throw>` / :meth:`athrow <agen.athrow>` into all generators consecutively. An instance of
- this class can be used as a contextmanager, which will automatically throw any exceptions into its generators. All
- exceptions caught in this manner will be re-raised after they have been thrown in the generators.
- """
-
- __slots__ = ("_generators", "_closed")
-
- def __init__(self, generators: list[AnyGenerator] | None = None) -> None:
- """Initialize ``DependencyCleanupGroup``.
-
- Args:
- generators: An optional list of generators to be called at cleanup
- """
- self._generators = generators or []
- self._closed = False
-
- def add(self, generator: Generator[Any, None, None] | AsyncGenerator[Any, None]) -> None:
- """Add a new generator to the group.
-
- Args:
- generator: The generator to add
-
- Returns:
- None
- """
- if self._closed:
- raise RuntimeError("Cannot call cleanup on a closed DependencyCleanupGroup")
- self._generators.append(generator)
-
- @staticmethod
- def _wrap_next(generator: AnyGenerator) -> Callable[[], Awaitable[None]]:
- if isasyncgen(generator):
-
- async def wrapped_async() -> None:
- await async_next(generator, None)
-
- return wrapped_async
-
- def wrapped() -> None:
- next(generator, None) # type: ignore[arg-type]
-
- return ensure_async_callable(wrapped)
-
- async def cleanup(self) -> None:
- """Execute cleanup by calling :func:`next` / :func:`anext` on all generators.
-
- If there are multiple generators to be called, they will be executed in a :class:`anyio.TaskGroup`.
-
- Returns:
- None
- """
- if self._closed:
- raise RuntimeError("Cannot call cleanup on a closed DependencyCleanupGroup")
-
- self._closed = True
-
- if not self._generators:
- return
-
- if len(self._generators) == 1:
- await self._wrap_next(self._generators[0])()
- return
-
- async with create_task_group() as task_group:
- for generator in self._generators:
- task_group.start_soon(self._wrap_next(generator))
-
- async def __aenter__(self) -> None:
- """Support the async contextmanager protocol to allow for easier catching and throwing of exceptions into the
- generators.
- """
-
- async def __aexit__(
- self,
- exc_type: type[BaseException] | None,
- exc_val: BaseException | None,
- exc_tb: Traceback | None,
- ) -> None:
- """If an exception was raised within the contextmanager block, throw it into all generators."""
- if exc_val:
- await self.throw(exc_val)
-
- async def throw(self, exc: BaseException) -> None:
- """Throw an exception in all generators sequentially.
-
- Args:
- exc: Exception to throw
- """
- for gen in self._generators:
- try:
- if isasyncgen(gen):
- await gen.athrow(exc)
- else:
- gen.throw(exc) # type: ignore[union-attr]
- except (StopIteration, StopAsyncIteration):
- continue
diff --git a/venv/lib/python3.11/site-packages/litestar/_kwargs/dependencies.py b/venv/lib/python3.11/site-packages/litestar/_kwargs/dependencies.py
deleted file mode 100644
index 88ffb07..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_kwargs/dependencies.py
+++ /dev/null
@@ -1,119 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any
-
-from litestar.utils.compat import async_next
-
-__all__ = ("Dependency", "create_dependency_batches", "map_dependencies_recursively", "resolve_dependency")
-
-
-if TYPE_CHECKING:
- from litestar._kwargs.cleanup import DependencyCleanupGroup
- from litestar.connection import ASGIConnection
- from litestar.di import Provide
-
-
-class Dependency:
- """Dependency graph of a given combination of ``Route`` + ``RouteHandler``"""
-
- __slots__ = ("key", "provide", "dependencies")
-
- def __init__(self, key: str, provide: Provide, dependencies: list[Dependency]) -> None:
- """Initialize a dependency.
-
- Args:
- key: The dependency key
- provide: Provider
- dependencies: List of child nodes
- """
- self.key = key
- self.provide = provide
- self.dependencies = dependencies
-
- def __eq__(self, other: Any) -> bool:
- # check if memory address is identical, otherwise compare attributes
- return other is self or (isinstance(other, self.__class__) and other.key == self.key)
-
- def __hash__(self) -> int:
- return hash(self.key)
-
-
-async def resolve_dependency(
- dependency: Dependency,
- connection: ASGIConnection,
- kwargs: dict[str, Any],
- cleanup_group: DependencyCleanupGroup,
-) -> None:
- """Resolve a given instance of :class:`Dependency <litestar._kwargs.Dependency>`.
-
- All required sub dependencies must already
- be resolved into the kwargs. The result of the dependency will be stored in the kwargs.
-
- Args:
- dependency: An instance of :class:`Dependency <litestar._kwargs.Dependency>`
- connection: An instance of :class:`Request <litestar.connection.Request>` or
- :class:`WebSocket <litestar.connection.WebSocket>`.
- kwargs: Any kwargs to pass to the dependency, the result will be stored here as well.
- cleanup_group: DependencyCleanupGroup to which generators returned by ``dependency`` will be added
- """
- signature_model = dependency.provide.signature_model
- dependency_kwargs = (
- signature_model.parse_values_from_connection_kwargs(connection=connection, **kwargs)
- if signature_model._fields
- else {}
- )
- value = await dependency.provide(**dependency_kwargs)
-
- if dependency.provide.has_sync_generator_dependency:
- cleanup_group.add(value)
- value = next(value)
- elif dependency.provide.has_async_generator_dependency:
- cleanup_group.add(value)
- value = await async_next(value)
-
- kwargs[dependency.key] = value
-
-
-def create_dependency_batches(expected_dependencies: set[Dependency]) -> list[set[Dependency]]:
- """Calculate batches for all dependencies, recursively.
-
- Args:
- expected_dependencies: A set of all direct :class:`Dependencies <litestar._kwargs.Dependency>`.
-
- Returns:
- A list of batches.
- """
- dependencies_to: dict[Dependency, set[Dependency]] = {}
- for dependency in expected_dependencies:
- if dependency not in dependencies_to:
- map_dependencies_recursively(dependency, dependencies_to)
-
- batches = []
- while dependencies_to:
- current_batch = {
- dependency
- for dependency, remaining_sub_dependencies in dependencies_to.items()
- if not remaining_sub_dependencies
- }
-
- for dependency in current_batch:
- del dependencies_to[dependency]
- for others_dependencies in dependencies_to.values():
- others_dependencies.discard(dependency)
-
- batches.append(current_batch)
-
- return batches
-
-
-def map_dependencies_recursively(dependency: Dependency, dependencies_to: dict[Dependency, set[Dependency]]) -> None:
- """Recursively map dependencies to their sub dependencies.
-
- Args:
- dependency: The current dependency to map.
- dependencies_to: A map of dependency to its sub dependencies.
- """
- dependencies_to[dependency] = set(dependency.dependencies)
- for sub in dependency.dependencies:
- if sub not in dependencies_to:
- map_dependencies_recursively(sub, dependencies_to)
diff --git a/venv/lib/python3.11/site-packages/litestar/_kwargs/extractors.py b/venv/lib/python3.11/site-packages/litestar/_kwargs/extractors.py
deleted file mode 100644
index e3b347e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_kwargs/extractors.py
+++ /dev/null
@@ -1,492 +0,0 @@
-from __future__ import annotations
-
-from collections import defaultdict
-from functools import lru_cache, partial
-from typing import TYPE_CHECKING, Any, Callable, Coroutine, Mapping, NamedTuple, cast
-
-from litestar._multipart import parse_multipart_form
-from litestar._parsers import (
- parse_query_string,
- parse_url_encoded_form_data,
-)
-from litestar.datastructures import Headers
-from litestar.datastructures.upload_file import UploadFile
-from litestar.datastructures.url import URL
-from litestar.enums import ParamType, RequestEncodingType
-from litestar.exceptions import ValidationException
-from litestar.params import BodyKwarg
-from litestar.types import Empty
-from litestar.utils.predicates import is_non_string_sequence
-from litestar.utils.scope.state import ScopeState
-
-if TYPE_CHECKING:
- from litestar._kwargs import KwargsModel
- from litestar._kwargs.parameter_definition import ParameterDefinition
- from litestar.connection import ASGIConnection, Request
- from litestar.dto import AbstractDTO
- from litestar.typing import FieldDefinition
-
-
-__all__ = (
- "body_extractor",
- "cookies_extractor",
- "create_connection_value_extractor",
- "create_data_extractor",
- "create_multipart_extractor",
- "create_query_default_dict",
- "create_url_encoded_data_extractor",
- "headers_extractor",
- "json_extractor",
- "msgpack_extractor",
- "parse_connection_headers",
- "parse_connection_query_params",
- "query_extractor",
- "request_extractor",
- "scope_extractor",
- "socket_extractor",
- "state_extractor",
-)
-
-
-class ParamMappings(NamedTuple):
- alias_and_key_tuples: list[tuple[str, str]]
- alias_defaults: dict[str, Any]
- alias_to_param: dict[str, ParameterDefinition]
-
-
-def _create_param_mappings(expected_params: set[ParameterDefinition]) -> ParamMappings:
- alias_and_key_tuples = []
- alias_defaults = {}
- alias_to_params: dict[str, ParameterDefinition] = {}
- for param in expected_params:
- alias = param.field_alias
- if param.param_type == ParamType.HEADER:
- alias = alias.lower()
-
- alias_and_key_tuples.append((alias, param.field_name))
-
- if not (param.is_required or param.default is Ellipsis):
- alias_defaults[alias] = param.default
-
- alias_to_params[alias] = param
-
- return ParamMappings(
- alias_and_key_tuples=alias_and_key_tuples,
- alias_defaults=alias_defaults,
- alias_to_param=alias_to_params,
- )
-
-
-def create_connection_value_extractor(
- kwargs_model: KwargsModel,
- connection_key: str,
- expected_params: set[ParameterDefinition],
- parser: Callable[[ASGIConnection, KwargsModel], Mapping[str, Any]] | None = None,
-) -> Callable[[dict[str, Any], ASGIConnection], None]:
- """Create a kwargs extractor function.
-
- Args:
- kwargs_model: The KwargsModel instance.
- connection_key: The attribute key to use.
- expected_params: The set of expected params.
- parser: An optional parser function.
-
- Returns:
- An extractor function.
- """
-
- alias_and_key_tuples, alias_defaults, alias_to_params = _create_param_mappings(expected_params)
-
- def extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
- data = parser(connection, kwargs_model) if parser else getattr(connection, connection_key, {})
-
- try:
- connection_mapping: dict[str, Any] = {
- key: data[alias] if alias in data else alias_defaults[alias] for alias, key in alias_and_key_tuples
- }
- values.update(connection_mapping)
- except KeyError as e:
- param = alias_to_params[e.args[0]]
- path = URL.from_components(
- path=connection.url.path,
- query=connection.url.query,
- )
- raise ValidationException(
- f"Missing required {param.param_type.value} parameter {param.field_alias!r} for path {path}"
- ) from e
-
- return extractor
-
-
-@lru_cache(1024)
-def create_query_default_dict(
- parsed_query: tuple[tuple[str, str], ...], sequence_query_parameter_names: tuple[str, ...]
-) -> defaultdict[str, list[str] | str]:
- """Transform a list of tuples into a default dict. Ensures non-list values are not wrapped in a list.
-
- Args:
- parsed_query: The parsed query list of tuples.
- sequence_query_parameter_names: A set of query parameters that should be wrapped in list.
-
- Returns:
- A default dict
- """
- output: defaultdict[str, list[str] | str] = defaultdict(list)
-
- for k, v in parsed_query:
- if k in sequence_query_parameter_names:
- output[k].append(v) # type: ignore[union-attr]
- else:
- output[k] = v
-
- return output
-
-
-def parse_connection_query_params(connection: ASGIConnection, kwargs_model: KwargsModel) -> dict[str, Any]:
- """Parse query params and cache the result in scope.
-
- Args:
- connection: The ASGI connection instance.
- kwargs_model: The KwargsModel instance.
-
- Returns:
- A dictionary of parsed values.
- """
- parsed_query = (
- connection._parsed_query
- if connection._parsed_query is not Empty
- else parse_query_string(connection.scope.get("query_string", b""))
- )
- ScopeState.from_scope(connection.scope).parsed_query = parsed_query
- return create_query_default_dict(
- parsed_query=parsed_query,
- sequence_query_parameter_names=kwargs_model.sequence_query_parameter_names,
- )
-
-
-def parse_connection_headers(connection: ASGIConnection, _: KwargsModel) -> Headers:
- """Parse header parameters and cache the result in scope.
-
- Args:
- connection: The ASGI connection instance.
- _: The KwargsModel instance.
-
- Returns:
- A Headers instance
- """
- return Headers.from_scope(connection.scope)
-
-
-def state_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
- """Extract the app state from the connection and insert it to the kwargs injected to the handler.
-
- Args:
- connection: The ASGI connection instance.
- values: The kwargs that are extracted from the connection and will be injected into the handler.
-
- Returns:
- None
- """
- values["state"] = connection.app.state._state
-
-
-def headers_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
- """Extract the headers from the connection and insert them to the kwargs injected to the handler.
-
- Args:
- connection: The ASGI connection instance.
- values: The kwargs that are extracted from the connection and will be injected into the handler.
-
- Returns:
- None
- """
- # TODO: This should be removed in 3.0 and instead Headers should be injected
- # directly. We are only keeping this one around to not break things
- values["headers"] = dict(connection.headers.items())
-
-
-def cookies_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
- """Extract the cookies from the connection and insert them to the kwargs injected to the handler.
-
- Args:
- connection: The ASGI connection instance.
- values: The kwargs that are extracted from the connection and will be injected into the handler.
-
- Returns:
- None
- """
- values["cookies"] = connection.cookies
-
-
-def query_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
- """Extract the query params from the connection and insert them to the kwargs injected to the handler.
-
- Args:
- connection: The ASGI connection instance.
- values: The kwargs that are extracted from the connection and will be injected into the handler.
-
- Returns:
- None
- """
- values["query"] = connection.query_params
-
-
-def scope_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
- """Extract the scope from the connection and insert it into the kwargs injected to the handler.
-
- Args:
- connection: The ASGI connection instance.
- values: The kwargs that are extracted from the connection and will be injected into the handler.
-
- Returns:
- None
- """
- values["scope"] = connection.scope
-
-
-def request_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
- """Set the connection instance as the 'request' value in the kwargs injected to the handler.
-
- Args:
- connection: The ASGI connection instance.
- values: The kwargs that are extracted from the connection and will be injected into the handler.
-
- Returns:
- None
- """
- values["request"] = connection
-
-
-def socket_extractor(values: dict[str, Any], connection: ASGIConnection) -> None:
- """Set the connection instance as the 'socket' value in the kwargs injected to the handler.
-
- Args:
- connection: The ASGI connection instance.
- values: The kwargs that are extracted from the connection and will be injected into the handler.
-
- Returns:
- None
- """
- values["socket"] = connection
-
-
-def body_extractor(
- values: dict[str, Any],
- connection: Request[Any, Any, Any],
-) -> None:
- """Extract the body from the request instance.
-
- Notes:
- - this extractor sets a Coroutine as the value in the kwargs. These are resolved at a later stage.
-
- Args:
- connection: The ASGI connection instance.
- values: The kwargs that are extracted from the connection and will be injected into the handler.
-
- Returns:
- The Body value.
- """
- values["body"] = connection.body()
-
-
-async def json_extractor(connection: Request[Any, Any, Any]) -> Any:
- """Extract the data from request and insert it into the kwargs injected to the handler.
-
- Notes:
- - this extractor sets a Coroutine as the value in the kwargs. These are resolved at a later stage.
-
- Args:
- connection: The ASGI connection instance.
-
- Returns:
- The JSON value.
- """
- if not await connection.body():
- return Empty
- return await connection.json()
-
-
-async def msgpack_extractor(connection: Request[Any, Any, Any]) -> Any:
- """Extract the data from request and insert it into the kwargs injected to the handler.
-
- Notes:
- - this extractor sets a Coroutine as the value in the kwargs. These are resolved at a later stage.
-
- Args:
- connection: The ASGI connection instance.
-
- Returns:
- The MessagePack value.
- """
- if not await connection.body():
- return Empty
- return await connection.msgpack()
-
-
-async def _extract_multipart(
- connection: Request[Any, Any, Any],
- body_kwarg_multipart_form_part_limit: int | None,
- field_definition: FieldDefinition,
- is_data_optional: bool,
- data_dto: type[AbstractDTO] | None,
-) -> Any:
- multipart_form_part_limit = (
- body_kwarg_multipart_form_part_limit
- if body_kwarg_multipart_form_part_limit is not None
- else connection.app.multipart_form_part_limit
- )
- connection.scope["_form"] = form_values = ( # type: ignore[typeddict-unknown-key]
- connection.scope["_form"] # type: ignore[typeddict-item]
- if "_form" in connection.scope
- else parse_multipart_form(
- body=await connection.body(),
- boundary=connection.content_type[-1].get("boundary", "").encode(),
- multipart_form_part_limit=multipart_form_part_limit,
- type_decoders=connection.route_handler.resolve_type_decoders(),
- )
- )
-
- if field_definition.is_non_string_sequence:
- values = list(form_values.values())
- if field_definition.has_inner_subclass_of(UploadFile) and isinstance(values[0], list):
- return values[0]
-
- return values
-
- if field_definition.is_simple_type and field_definition.annotation is UploadFile and form_values:
- return next(v for v in form_values.values() if isinstance(v, UploadFile))
-
- if not form_values and is_data_optional:
- return None
-
- if data_dto:
- return data_dto(connection).decode_builtins(form_values)
-
- for name, tp in field_definition.get_type_hints().items():
- value = form_values.get(name)
- if value is not None and is_non_string_sequence(tp) and not isinstance(value, list):
- form_values[name] = [value]
-
- return form_values
-
-
-def create_multipart_extractor(
- field_definition: FieldDefinition, is_data_optional: bool, data_dto: type[AbstractDTO] | None
-) -> Callable[[ASGIConnection[Any, Any, Any, Any]], Coroutine[Any, Any, Any]]:
- """Create a multipart form-data extractor.
-
- Args:
- field_definition: A FieldDefinition instance.
- is_data_optional: Boolean dictating whether the field is optional.
- data_dto: A data DTO type, if configured for handler.
-
- Returns:
- An extractor function.
- """
- body_kwarg_multipart_form_part_limit: int | None = None
- if field_definition.kwarg_definition and isinstance(field_definition.kwarg_definition, BodyKwarg):
- body_kwarg_multipart_form_part_limit = field_definition.kwarg_definition.multipart_form_part_limit
-
- extract_multipart = partial(
- _extract_multipart,
- body_kwarg_multipart_form_part_limit=body_kwarg_multipart_form_part_limit,
- is_data_optional=is_data_optional,
- data_dto=data_dto,
- field_definition=field_definition,
- )
-
- return cast("Callable[[ASGIConnection[Any, Any, Any, Any]], Coroutine[Any, Any, Any]]", extract_multipart)
-
-
-def create_url_encoded_data_extractor(
- is_data_optional: bool, data_dto: type[AbstractDTO] | None
-) -> Callable[[ASGIConnection[Any, Any, Any, Any]], Coroutine[Any, Any, Any]]:
- """Create extractor for url encoded form-data.
-
- Args:
- is_data_optional: Boolean dictating whether the field is optional.
- data_dto: A data DTO type, if configured for handler.
-
- Returns:
- An extractor function.
- """
-
- async def extract_url_encoded_extractor(
- connection: Request[Any, Any, Any],
- ) -> Any:
- connection.scope["_form"] = form_values = ( # type: ignore[typeddict-unknown-key]
- connection.scope["_form"] # type: ignore[typeddict-item]
- if "_form" in connection.scope
- else parse_url_encoded_form_data(await connection.body())
- )
-
- if not form_values and is_data_optional:
- return None
-
- return data_dto(connection).decode_builtins(form_values) if data_dto else form_values
-
- return cast(
- "Callable[[ASGIConnection[Any, Any, Any, Any]], Coroutine[Any, Any, Any]]", extract_url_encoded_extractor
- )
-
-
-def create_data_extractor(kwargs_model: KwargsModel) -> Callable[[dict[str, Any], ASGIConnection], None]:
- """Create an extractor for a request's body.
-
- Args:
- kwargs_model: The KwargsModel instance.
-
- Returns:
- An extractor for the request's body.
- """
-
- if kwargs_model.expected_form_data:
- media_type, field_definition = kwargs_model.expected_form_data
-
- if media_type == RequestEncodingType.MULTI_PART:
- data_extractor = create_multipart_extractor(
- field_definition=field_definition,
- is_data_optional=kwargs_model.is_data_optional,
- data_dto=kwargs_model.expected_data_dto,
- )
- else:
- data_extractor = create_url_encoded_data_extractor(
- is_data_optional=kwargs_model.is_data_optional,
- data_dto=kwargs_model.expected_data_dto,
- )
- elif kwargs_model.expected_msgpack_data:
- data_extractor = cast(
- "Callable[[ASGIConnection[Any, Any, Any, Any]], Coroutine[Any, Any, Any]]", msgpack_extractor
- )
- elif kwargs_model.expected_data_dto:
- data_extractor = create_dto_extractor(data_dto=kwargs_model.expected_data_dto)
- else:
- data_extractor = cast(
- "Callable[[ASGIConnection[Any, Any, Any, Any]], Coroutine[Any, Any, Any]]", json_extractor
- )
-
- def extractor(
- values: dict[str, Any],
- connection: ASGIConnection[Any, Any, Any, Any],
- ) -> None:
- values["data"] = data_extractor(connection)
-
- return extractor
-
-
-def create_dto_extractor(
- data_dto: type[AbstractDTO],
-) -> Callable[[ASGIConnection[Any, Any, Any, Any]], Coroutine[Any, Any, Any]]:
- """Create a DTO data extractor.
-
-
- Returns:
- An extractor function.
- """
-
- async def dto_extractor(connection: Request[Any, Any, Any]) -> Any:
- if not (body := await connection.body()):
- return Empty
- return data_dto(connection).decode_bytes(body)
-
- return dto_extractor # type:ignore[return-value]
diff --git a/venv/lib/python3.11/site-packages/litestar/_kwargs/kwargs_model.py b/venv/lib/python3.11/site-packages/litestar/_kwargs/kwargs_model.py
deleted file mode 100644
index 01ed2e5..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_kwargs/kwargs_model.py
+++ /dev/null
@@ -1,479 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any, Callable
-
-from anyio import create_task_group
-
-from litestar._kwargs.cleanup import DependencyCleanupGroup
-from litestar._kwargs.dependencies import (
- Dependency,
- create_dependency_batches,
- resolve_dependency,
-)
-from litestar._kwargs.extractors import (
- body_extractor,
- cookies_extractor,
- create_connection_value_extractor,
- create_data_extractor,
- headers_extractor,
- parse_connection_headers,
- parse_connection_query_params,
- query_extractor,
- request_extractor,
- scope_extractor,
- socket_extractor,
- state_extractor,
-)
-from litestar._kwargs.parameter_definition import (
- ParameterDefinition,
- create_parameter_definition,
- merge_parameter_sets,
-)
-from litestar.constants import RESERVED_KWARGS
-from litestar.enums import ParamType, RequestEncodingType
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.params import BodyKwarg, ParameterKwarg
-from litestar.typing import FieldDefinition
-from litestar.utils.helpers import get_exception_group
-
-__all__ = ("KwargsModel",)
-
-
-if TYPE_CHECKING:
- from litestar._signature import SignatureModel
- from litestar.connection import ASGIConnection
- from litestar.di import Provide
- from litestar.dto import AbstractDTO
- from litestar.utils.signature import ParsedSignature
-
-_ExceptionGroup = get_exception_group()
-
-
-class KwargsModel:
- """Model required kwargs for a given RouteHandler and its dependencies.
-
- This is done once and is memoized during application bootstrap, ensuring minimal runtime overhead.
- """
-
- __slots__ = (
- "dependency_batches",
- "expected_cookie_params",
- "expected_data_dto",
- "expected_form_data",
- "expected_header_params",
- "expected_msgpack_data",
- "expected_path_params",
- "expected_query_params",
- "expected_reserved_kwargs",
- "extractors",
- "has_kwargs",
- "is_data_optional",
- "sequence_query_parameter_names",
- )
-
- def __init__(
- self,
- *,
- expected_cookie_params: set[ParameterDefinition],
- expected_data_dto: type[AbstractDTO] | None,
- expected_dependencies: set[Dependency],
- expected_form_data: tuple[RequestEncodingType | str, FieldDefinition] | None,
- expected_header_params: set[ParameterDefinition],
- expected_msgpack_data: FieldDefinition | None,
- expected_path_params: set[ParameterDefinition],
- expected_query_params: set[ParameterDefinition],
- expected_reserved_kwargs: set[str],
- is_data_optional: bool,
- sequence_query_parameter_names: set[str],
- ) -> None:
- """Initialize ``KwargsModel``.
-
- Args:
- expected_cookie_params: Any expected cookie parameter kwargs
- expected_dependencies: Any expected dependency kwargs
- expected_form_data: Any expected form data kwargs
- expected_header_params: Any expected header parameter kwargs
- expected_msgpack_data: Any expected MessagePack data kwargs
- expected_path_params: Any expected path parameter kwargs
- expected_query_params: Any expected query parameter kwargs
- expected_reserved_kwargs: Any expected reserved kwargs, e.g. 'state'
- expected_data_dto: A data DTO, if defined
- is_data_optional: Treat data as optional
- sequence_query_parameter_names: Any query parameters that are sequences
- """
- self.expected_cookie_params = expected_cookie_params
- self.expected_form_data = expected_form_data
- self.expected_header_params = expected_header_params
- self.expected_msgpack_data = expected_msgpack_data
- self.expected_path_params = expected_path_params
- self.expected_query_params = expected_query_params
- self.expected_reserved_kwargs = expected_reserved_kwargs
- self.expected_data_dto = expected_data_dto
- self.sequence_query_parameter_names = tuple(sequence_query_parameter_names)
-
- self.has_kwargs = (
- expected_cookie_params
- or expected_dependencies
- or expected_form_data
- or expected_msgpack_data
- or expected_header_params
- or expected_path_params
- or expected_query_params
- or expected_reserved_kwargs
- or expected_data_dto
- )
-
- self.is_data_optional = is_data_optional
- self.extractors = self._create_extractors()
- self.dependency_batches = create_dependency_batches(expected_dependencies)
-
- def _create_extractors(self) -> list[Callable[[dict[str, Any], ASGIConnection], None]]:
- reserved_kwargs_extractors: dict[str, Callable[[dict[str, Any], ASGIConnection], None]] = {
- "data": create_data_extractor(self),
- "state": state_extractor,
- "scope": scope_extractor,
- "request": request_extractor,
- "socket": socket_extractor,
- "headers": headers_extractor,
- "cookies": cookies_extractor,
- "query": query_extractor,
- "body": body_extractor, # type: ignore[dict-item]
- }
-
- extractors: list[Callable[[dict[str, Any], ASGIConnection], None]] = [
- reserved_kwargs_extractors[reserved_kwarg] for reserved_kwarg in self.expected_reserved_kwargs
- ]
-
- if self.expected_header_params:
- extractors.append(
- create_connection_value_extractor(
- connection_key="headers",
- expected_params=self.expected_header_params,
- kwargs_model=self,
- parser=parse_connection_headers,
- ),
- )
-
- if self.expected_path_params:
- extractors.append(
- create_connection_value_extractor(
- connection_key="path_params",
- expected_params=self.expected_path_params,
- kwargs_model=self,
- ),
- )
-
- if self.expected_cookie_params:
- extractors.append(
- create_connection_value_extractor(
- connection_key="cookies",
- expected_params=self.expected_cookie_params,
- kwargs_model=self,
- ),
- )
-
- if self.expected_query_params:
- extractors.append(
- create_connection_value_extractor(
- connection_key="query_params",
- expected_params=self.expected_query_params,
- kwargs_model=self,
- parser=parse_connection_query_params,
- ),
- )
- return extractors
-
- @classmethod
- def _get_param_definitions(
- cls,
- path_parameters: set[str],
- layered_parameters: dict[str, FieldDefinition],
- dependencies: dict[str, Provide],
- field_definitions: dict[str, FieldDefinition],
- ) -> tuple[set[ParameterDefinition], set[Dependency]]:
- """Get parameter_definitions for the construction of KwargsModel instance.
-
- Args:
- path_parameters: Any expected path parameters.
- layered_parameters: A string keyed dictionary of layered parameters.
- dependencies: A string keyed dictionary mapping dependency providers.
- field_definitions: The SignatureModel fields.
-
- Returns:
- A Tuple of sets
- """
- expected_dependencies = {
- cls._create_dependency_graph(key=key, dependencies=dependencies)
- for key in dependencies
- if key in field_definitions
- }
- ignored_keys = {*RESERVED_KWARGS, *(dependency.key for dependency in expected_dependencies)}
-
- param_definitions = {
- *(
- create_parameter_definition(
- field_definition=field_definition,
- field_name=field_name,
- path_parameters=path_parameters,
- )
- for field_name, field_definition in layered_parameters.items()
- if field_name not in ignored_keys and field_name not in field_definitions
- ),
- *(
- create_parameter_definition(
- field_definition=field_definition,
- field_name=field_name,
- path_parameters=path_parameters,
- )
- for field_name, field_definition in field_definitions.items()
- if field_name not in ignored_keys and field_name not in layered_parameters
- ),
- }
-
- for field_name, field_definition in (
- (k, v) for k, v in field_definitions.items() if k not in ignored_keys and k in layered_parameters
- ):
- layered_parameter = layered_parameters[field_name]
- field = field_definition if field_definition.is_parameter_field else layered_parameter
- default = field_definition.default if field_definition.has_default else layered_parameter.default
-
- param_definitions.add(
- create_parameter_definition(
- field_definition=FieldDefinition.from_kwarg(
- name=field.name,
- default=default,
- inner_types=field.inner_types,
- annotation=field.annotation,
- kwarg_definition=field.kwarg_definition,
- extra=field.extra,
- ),
- field_name=field_name,
- path_parameters=path_parameters,
- )
- )
-
- return param_definitions, expected_dependencies
-
- @classmethod
- def create_for_signature_model(
- cls,
- signature_model: type[SignatureModel],
- parsed_signature: ParsedSignature,
- dependencies: dict[str, Provide],
- path_parameters: set[str],
- layered_parameters: dict[str, FieldDefinition],
- ) -> KwargsModel:
- """Pre-determine what parameters are required for a given combination of route + route handler. It is executed
- during the application bootstrap process.
-
- Args:
- signature_model: A :class:`SignatureModel <litestar._signature.SignatureModel>` subclass.
- parsed_signature: A :class:`ParsedSignature <litestar._signature.ParsedSignature>` instance.
- dependencies: A string keyed dictionary mapping dependency providers.
- path_parameters: Any expected path parameters.
- layered_parameters: A string keyed dictionary of layered parameters.
-
- Returns:
- An instance of KwargsModel
- """
-
- field_definitions = signature_model._fields
-
- cls._validate_raw_kwargs(
- path_parameters=path_parameters,
- dependencies=dependencies,
- field_definitions=field_definitions,
- layered_parameters=layered_parameters,
- )
-
- param_definitions, expected_dependencies = cls._get_param_definitions(
- path_parameters=path_parameters,
- layered_parameters=layered_parameters,
- dependencies=dependencies,
- field_definitions=field_definitions,
- )
-
- expected_reserved_kwargs = {field_name for field_name in field_definitions if field_name in RESERVED_KWARGS}
- expected_path_parameters = {p for p in param_definitions if p.param_type == ParamType.PATH}
- expected_header_parameters = {p for p in param_definitions if p.param_type == ParamType.HEADER}
- expected_cookie_parameters = {p for p in param_definitions if p.param_type == ParamType.COOKIE}
- expected_query_parameters = {p for p in param_definitions if p.param_type == ParamType.QUERY}
- sequence_query_parameter_names = {p.field_alias for p in expected_query_parameters if p.is_sequence}
-
- expected_form_data: tuple[RequestEncodingType | str, FieldDefinition] | None = None
- expected_msgpack_data: FieldDefinition | None = None
- expected_data_dto: type[AbstractDTO] | None = None
- data_field_definition = field_definitions.get("data")
-
- media_type: RequestEncodingType | str | None = None
- if data_field_definition:
- if isinstance(data_field_definition.kwarg_definition, BodyKwarg):
- media_type = data_field_definition.kwarg_definition.media_type
-
- if media_type in (RequestEncodingType.MULTI_PART, RequestEncodingType.URL_ENCODED):
- expected_form_data = (media_type, data_field_definition)
- expected_data_dto = signature_model._data_dto
- elif signature_model._data_dto:
- expected_data_dto = signature_model._data_dto
- elif media_type == RequestEncodingType.MESSAGEPACK:
- expected_msgpack_data = data_field_definition
-
- for dependency in expected_dependencies:
- dependency_kwargs_model = cls.create_for_signature_model(
- signature_model=dependency.provide.signature_model,
- parsed_signature=parsed_signature,
- dependencies=dependencies,
- path_parameters=path_parameters,
- layered_parameters=layered_parameters,
- )
- expected_path_parameters = merge_parameter_sets(
- expected_path_parameters, dependency_kwargs_model.expected_path_params
- )
- expected_query_parameters = merge_parameter_sets(
- expected_query_parameters, dependency_kwargs_model.expected_query_params
- )
- expected_cookie_parameters = merge_parameter_sets(
- expected_cookie_parameters, dependency_kwargs_model.expected_cookie_params
- )
- expected_header_parameters = merge_parameter_sets(
- expected_header_parameters, dependency_kwargs_model.expected_header_params
- )
-
- if "data" in expected_reserved_kwargs and "data" in dependency_kwargs_model.expected_reserved_kwargs:
- cls._validate_dependency_data(
- expected_form_data=expected_form_data,
- dependency_kwargs_model=dependency_kwargs_model,
- )
-
- expected_reserved_kwargs.update(dependency_kwargs_model.expected_reserved_kwargs)
- sequence_query_parameter_names.update(dependency_kwargs_model.sequence_query_parameter_names)
-
- return KwargsModel(
- expected_cookie_params=expected_cookie_parameters,
- expected_dependencies=expected_dependencies,
- expected_data_dto=expected_data_dto,
- expected_form_data=expected_form_data,
- expected_header_params=expected_header_parameters,
- expected_msgpack_data=expected_msgpack_data,
- expected_path_params=expected_path_parameters,
- expected_query_params=expected_query_parameters,
- expected_reserved_kwargs=expected_reserved_kwargs,
- is_data_optional=field_definitions["data"].is_optional if "data" in expected_reserved_kwargs else False,
- sequence_query_parameter_names=sequence_query_parameter_names,
- )
-
- def to_kwargs(self, connection: ASGIConnection) -> dict[str, Any]:
- """Return a dictionary of kwargs. Async values, i.e. CoRoutines, are not resolved to ensure this function is
- sync.
-
- Args:
- connection: An instance of :class:`Request <litestar.connection.Request>` or
- :class:`WebSocket <litestar.connection.WebSocket>`.
-
- Returns:
- A string keyed dictionary of kwargs expected by the handler function and its dependencies.
- """
- output: dict[str, Any] = {}
-
- for extractor in self.extractors:
- extractor(output, connection)
-
- return output
-
- async def resolve_dependencies(self, connection: ASGIConnection, kwargs: dict[str, Any]) -> DependencyCleanupGroup:
- """Resolve all dependencies into the kwargs, recursively.
-
- Args:
- connection: An instance of :class:`Request <litestar.connection.Request>` or
- :class:`WebSocket <litestar.connection.WebSocket>`.
- kwargs: Kwargs to pass to dependencies.
- """
- cleanup_group = DependencyCleanupGroup()
- for batch in self.dependency_batches:
- if len(batch) == 1:
- await resolve_dependency(next(iter(batch)), connection, kwargs, cleanup_group)
- else:
- try:
- async with create_task_group() as task_group:
- for dependency in batch:
- task_group.start_soon(resolve_dependency, dependency, connection, kwargs, cleanup_group)
- except _ExceptionGroup as excgroup:
- raise excgroup.exceptions[0] from excgroup # type: ignore[attr-defined]
-
- return cleanup_group
-
- @classmethod
- def _create_dependency_graph(cls, key: str, dependencies: dict[str, Provide]) -> Dependency:
- """Create a graph like structure of dependencies, with each dependency including its own dependencies as a
- list.
- """
- provide = dependencies[key]
- sub_dependency_keys = [k for k in provide.signature_model._fields if k in dependencies]
- return Dependency(
- key=key,
- provide=provide,
- dependencies=[cls._create_dependency_graph(key=k, dependencies=dependencies) for k in sub_dependency_keys],
- )
-
- @classmethod
- def _validate_dependency_data(
- cls,
- expected_form_data: tuple[RequestEncodingType | str, FieldDefinition] | None,
- dependency_kwargs_model: KwargsModel,
- ) -> None:
- """Validate that the 'data' kwarg is compatible across dependencies."""
- if bool(expected_form_data) != bool(dependency_kwargs_model.expected_form_data):
- raise ImproperlyConfiguredException(
- "Dependencies have incompatible 'data' kwarg types: one expects JSON and the other expects form-data"
- )
- if expected_form_data and dependency_kwargs_model.expected_form_data:
- local_media_type = expected_form_data[0]
- dependency_media_type = dependency_kwargs_model.expected_form_data[0]
- if local_media_type != dependency_media_type:
- raise ImproperlyConfiguredException(
- "Dependencies have incompatible form-data encoding: one expects url-encoded and the other expects multi-part"
- )
-
- @classmethod
- def _validate_raw_kwargs(
- cls,
- path_parameters: set[str],
- dependencies: dict[str, Provide],
- field_definitions: dict[str, FieldDefinition],
- layered_parameters: dict[str, FieldDefinition],
- ) -> None:
- """Validate that there are no ambiguous kwargs, that is, kwargs declared using the same key in different
- places.
- """
- dependency_keys = set(dependencies.keys())
-
- parameter_names = {
- *(
- k
- for k, f in field_definitions.items()
- if isinstance(f.kwarg_definition, ParameterKwarg)
- and (f.kwarg_definition.header or f.kwarg_definition.query or f.kwarg_definition.cookie)
- ),
- *list(layered_parameters.keys()),
- }
-
- intersection = (
- path_parameters.intersection(dependency_keys)
- or path_parameters.intersection(parameter_names)
- or dependency_keys.intersection(parameter_names)
- )
- if intersection:
- raise ImproperlyConfiguredException(
- f"Kwarg resolution ambiguity detected for the following keys: {', '.join(intersection)}. "
- f"Make sure to use distinct keys for your dependencies, path parameters, and aliased parameters."
- )
-
- if used_reserved_kwargs := {
- *parameter_names,
- *path_parameters,
- *dependency_keys,
- }.intersection(RESERVED_KWARGS):
- raise ImproperlyConfiguredException(
- f"Reserved kwargs ({', '.join(RESERVED_KWARGS)}) cannot be used for dependencies and parameter arguments. "
- f"The following kwargs have been used: {', '.join(used_reserved_kwargs)}"
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/_kwargs/parameter_definition.py b/venv/lib/python3.11/site-packages/litestar/_kwargs/parameter_definition.py
deleted file mode 100644
index 02b09fc..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_kwargs/parameter_definition.py
+++ /dev/null
@@ -1,81 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any, NamedTuple
-
-from litestar.enums import ParamType
-from litestar.params import ParameterKwarg
-
-if TYPE_CHECKING:
- from litestar.typing import FieldDefinition
-
-__all__ = ("ParameterDefinition", "create_parameter_definition", "merge_parameter_sets")
-
-
-class ParameterDefinition(NamedTuple):
- """Tuple defining a kwarg representing a request parameter."""
-
- default: Any
- field_alias: str
- field_name: str
- is_required: bool
- is_sequence: bool
- param_type: ParamType
-
-
-def create_parameter_definition(
- field_definition: FieldDefinition,
- field_name: str,
- path_parameters: set[str],
-) -> ParameterDefinition:
- """Create a ParameterDefinition for the given FieldDefinition.
-
- Args:
- field_definition: FieldDefinition instance.
- field_name: The field's name.
- path_parameters: A set of path parameter names.
-
- Returns:
- A ParameterDefinition tuple.
- """
- default = field_definition.default if field_definition.has_default else None
- kwarg_definition = (
- field_definition.kwarg_definition if isinstance(field_definition.kwarg_definition, ParameterKwarg) else None
- )
-
- field_alias = kwarg_definition.query if kwarg_definition and kwarg_definition.query else field_name
- param_type = ParamType.QUERY
-
- if field_name in path_parameters:
- field_alias = field_name
- param_type = ParamType.PATH
- elif kwarg_definition and kwarg_definition.header:
- field_alias = kwarg_definition.header
- param_type = ParamType.HEADER
- elif kwarg_definition and kwarg_definition.cookie:
- field_alias = kwarg_definition.cookie
- param_type = ParamType.COOKIE
-
- return ParameterDefinition(
- param_type=param_type,
- field_name=field_name,
- field_alias=field_alias,
- default=default,
- is_required=field_definition.is_required
- and default is None
- and not field_definition.is_optional
- and not field_definition.is_any,
- is_sequence=field_definition.is_non_string_sequence,
- )
-
-
-def merge_parameter_sets(first: set[ParameterDefinition], second: set[ParameterDefinition]) -> set[ParameterDefinition]:
- """Given two sets of parameter definitions, coming from different dependencies for example, merge them into a single
- set.
- """
- result: set[ParameterDefinition] = first.intersection(second)
- difference = first.symmetric_difference(second)
- for param in difference:
- # add the param if it's either required or no-other param in difference is the same but required
- if param.is_required or not any(p.field_alias == param.field_alias and p.is_required for p in difference):
- result.add(param)
- return result
diff --git a/venv/lib/python3.11/site-packages/litestar/_layers/__init__.py b/venv/lib/python3.11/site-packages/litestar/_layers/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_layers/__init__.py
+++ /dev/null
diff --git a/venv/lib/python3.11/site-packages/litestar/_layers/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_layers/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 7b7425e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_layers/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_layers/__pycache__/utils.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_layers/__pycache__/utils.cpython-311.pyc
deleted file mode 100644
index d772e10..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_layers/__pycache__/utils.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_layers/utils.py b/venv/lib/python3.11/site-packages/litestar/_layers/utils.py
deleted file mode 100644
index 61afd61..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_layers/utils.py
+++ /dev/null
@@ -1,34 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Mapping, Sequence
-
-from litestar.datastructures.cookie import Cookie
-from litestar.datastructures.response_header import ResponseHeader
-
-__all__ = ("narrow_response_cookies", "narrow_response_headers")
-
-
-if TYPE_CHECKING:
- from litestar.types.composite_types import ResponseCookies, ResponseHeaders
-
-
-def narrow_response_headers(headers: ResponseHeaders | None) -> Sequence[ResponseHeader] | None:
- """Given :class:`.types.ResponseHeaders` as a :class:`typing.Mapping`, create a list of
- :class:`.datastructures.response_header.ResponseHeader` from it, otherwise return ``headers`` unchanged
- """
- return (
- tuple(ResponseHeader(name=name, value=value) for name, value in headers.items())
- if isinstance(headers, Mapping)
- else headers
- )
-
-
-def narrow_response_cookies(cookies: ResponseCookies | None) -> Sequence[Cookie] | None:
- """Given :class:`.types.ResponseCookies` as a :class:`typing.Mapping`, create a list of
- :class:`.datastructures.cookie.Cookie` from it, otherwise return ``cookies`` unchanged
- """
- return (
- tuple(Cookie(key=key, value=value) for key, value in cookies.items())
- if isinstance(cookies, Mapping)
- else cookies
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/_multipart.py b/venv/lib/python3.11/site-packages/litestar/_multipart.py
deleted file mode 100644
index 55b3620..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_multipart.py
+++ /dev/null
@@ -1,163 +0,0 @@
-"""The contents of this file were adapted from sanic.
-
-MIT License
-
-Copyright (c) 2016-present Sanic Community
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-from __future__ import annotations
-
-import re
-from collections import defaultdict
-from email.utils import decode_rfc2231
-from typing import TYPE_CHECKING, Any
-from urllib.parse import unquote
-
-from litestar.datastructures.upload_file import UploadFile
-from litestar.exceptions import ValidationException
-
-__all__ = ("parse_body", "parse_content_header", "parse_multipart_form")
-
-
-if TYPE_CHECKING:
- from litestar.types import TypeDecodersSequence
-
-_token = r"([\w!#$%&'*+\-.^_`|~]+)" # noqa: S105
-_quoted = r'"([^"]*)"'
-_param = re.compile(rf";\s*{_token}=(?:{_token}|{_quoted})", re.ASCII)
-_firefox_quote_escape = re.compile(r'\\"(?!; |\s*$)')
-
-
-def parse_content_header(value: str) -> tuple[str, dict[str, str]]:
- """Parse content-type and content-disposition header values.
-
- Args:
- value: A header string value to parse.
-
- Returns:
- A tuple containing the normalized header string and a dictionary of parameters.
- """
- value = _firefox_quote_escape.sub("%22", value)
- pos = value.find(";")
- if pos == -1:
- options: dict[str, str] = {}
- else:
- options = {
- m.group(1).lower(): m.group(2) or m.group(3).replace("%22", '"') for m in _param.finditer(value[pos:])
- }
- value = value[:pos]
- return value.strip().lower(), options
-
-
-def parse_body(body: bytes, boundary: bytes, multipart_form_part_limit: int) -> list[bytes]:
- """Split the body using the boundary
- and validate the number of form parts is within the allowed limit.
-
- Args:
- body: The form body.
- boundary: The boundary used to separate form components.
- multipart_form_part_limit: The limit of allowed form components
-
- Returns:
- A list of form components.
- """
- if not (body and boundary):
- return []
-
- form_parts = body.split(boundary, multipart_form_part_limit + 3)[1:-1]
-
- if len(form_parts) > multipart_form_part_limit:
- raise ValidationException(
- f"number of multipart components exceeds the allowed limit of {multipart_form_part_limit}, "
- f"this potentially indicates a DoS attack"
- )
-
- return form_parts
-
-
-def parse_multipart_form(
- body: bytes,
- boundary: bytes,
- multipart_form_part_limit: int = 1000,
- type_decoders: TypeDecodersSequence | None = None,
-) -> dict[str, Any]:
- """Parse multipart form data.
-
- Args:
- body: Body of the request.
- boundary: Boundary of the multipart message.
- multipart_form_part_limit: Limit of the number of parts allowed.
- type_decoders: A sequence of type decoders to use.
-
- Returns:
- A dictionary of parsed results.
- """
-
- fields: defaultdict[str, list[Any]] = defaultdict(list)
-
- for form_part in parse_body(body=body, boundary=boundary, multipart_form_part_limit=multipart_form_part_limit):
- file_name = None
- content_type = "text/plain"
- content_charset = "utf-8"
- field_name = None
- line_index = 2
- line_end_index = 0
- headers: list[tuple[str, str]] = []
-
- while line_end_index != -1:
- line_end_index = form_part.find(b"\r\n", line_index)
- form_line = form_part[line_index:line_end_index].decode("utf-8")
-
- if not form_line:
- break
-
- line_index = line_end_index + 2
- colon_index = form_line.index(":")
- current_idx = colon_index + 2
- form_header_field = form_line[:colon_index].lower()
- form_header_value, form_parameters = parse_content_header(form_line[current_idx:])
-
- if form_header_field == "content-disposition":
- field_name = form_parameters.get("name")
- file_name = form_parameters.get("filename")
-
- if file_name is None and (filename_with_asterisk := form_parameters.get("filename*")):
- encoding, _, value = decode_rfc2231(filename_with_asterisk)
- file_name = unquote(value, encoding=encoding or content_charset)
-
- elif form_header_field == "content-type":
- content_type = form_header_value
- content_charset = form_parameters.get("charset", "utf-8")
- headers.append((form_header_field, form_header_value))
-
- if field_name:
- post_data = form_part[line_index:-4].lstrip(b"\r\n")
- if file_name:
- form_file = UploadFile(
- content_type=content_type, filename=file_name, file_data=post_data, headers=dict(headers)
- )
- fields[field_name].append(form_file)
- elif post_data:
- fields[field_name].append(post_data.decode(content_charset))
- else:
- fields[field_name].append(None)
-
- return {k: v if len(v) > 1 else v[0] for k, v in fields.items()}
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/__init__.py b/venv/lib/python3.11/site-packages/litestar/_openapi/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/__init__.py
+++ /dev/null
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index e090039..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/datastructures.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/datastructures.cpython-311.pyc
deleted file mode 100644
index 9dd5b10..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/datastructures.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/parameters.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/parameters.cpython-311.pyc
deleted file mode 100644
index 1a17187..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/parameters.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/path_item.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/path_item.cpython-311.pyc
deleted file mode 100644
index a440e7d..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/path_item.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/plugin.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/plugin.cpython-311.pyc
deleted file mode 100644
index 13b3ab3..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/plugin.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/request_body.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/request_body.cpython-311.pyc
deleted file mode 100644
index 2f093bf..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/request_body.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/responses.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/responses.cpython-311.pyc
deleted file mode 100644
index 10d877b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/responses.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/utils.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/utils.cpython-311.pyc
deleted file mode 100644
index 97c7c13..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/__pycache__/utils.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/datastructures.py b/venv/lib/python3.11/site-packages/litestar/_openapi/datastructures.py
deleted file mode 100644
index d97c8db..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/datastructures.py
+++ /dev/null
@@ -1,179 +0,0 @@
-from __future__ import annotations
-
-from collections import defaultdict
-from typing import TYPE_CHECKING, Iterator, Sequence
-
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.openapi.spec import Reference, Schema
-
-if TYPE_CHECKING:
- from litestar.openapi import OpenAPIConfig
- from litestar.plugins import OpenAPISchemaPluginProtocol
-
-
-class RegisteredSchema:
- """Object to store a schema and any references to it."""
-
- def __init__(self, key: tuple[str, ...], schema: Schema, references: list[Reference]) -> None:
- """Create a new RegisteredSchema object.
-
- Args:
- key: The key used to register the schema.
- schema: The schema object.
- references: A list of references to the schema.
- """
- self.key = key
- self.schema = schema
- self.references = references
-
-
-class SchemaRegistry:
- """A registry for object schemas.
-
- This class is used to store schemas that we reference from other parts of the spec.
-
- Its main purpose is to allow us to generate the components/schemas section of the spec once we have
- collected all the schemas that should be included.
-
- This allows us to determine a path to the schema in the components/schemas section of the spec that
- is unique and as short as possible.
- """
-
- def __init__(self) -> None:
- self._schema_key_map: dict[tuple[str, ...], RegisteredSchema] = {}
- self._schema_reference_map: dict[int, RegisteredSchema] = {}
- self._model_name_groups: defaultdict[str, list[RegisteredSchema]] = defaultdict(list)
-
- def get_schema_for_key(self, key: tuple[str, ...]) -> Schema:
- """Get a registered schema by its key.
-
- Args:
- key: The key to the schema to get.
-
- Returns:
- A RegisteredSchema object.
- """
- if key not in self._schema_key_map:
- self._schema_key_map[key] = registered_schema = RegisteredSchema(key, Schema(), [])
- self._model_name_groups[key[-1]].append(registered_schema)
- return self._schema_key_map[key].schema
-
- def get_reference_for_key(self, key: tuple[str, ...]) -> Reference | None:
- """Get a reference to a registered schema by its key.
-
- Args:
- key: The key to the schema to get.
-
- Returns:
- A Reference object.
- """
- if key not in self._schema_key_map:
- return None
- registered_schema = self._schema_key_map[key]
- reference = Reference(f"#/components/schemas/{'_'.join(key)}")
- registered_schema.references.append(reference)
- self._schema_reference_map[id(reference)] = registered_schema
- return reference
-
- def from_reference(self, reference: Reference) -> RegisteredSchema:
- """Get a registered schema by its reference.
-
- Args:
- reference: The reference to the schema to get.
-
- Returns:
- A RegisteredSchema object.
- """
- return self._schema_reference_map[id(reference)]
-
- def __iter__(self) -> Iterator[RegisteredSchema]:
- """Iterate over the registered schemas."""
- return iter(self._schema_key_map.values())
-
- @staticmethod
- def set_reference_paths(name: str, registered_schema: RegisteredSchema) -> None:
- """Set the reference paths for a registered schema."""
- for reference in registered_schema.references:
- reference.ref = f"#/components/schemas/{name}"
-
- @staticmethod
- def remove_common_prefix(tuples: list[tuple[str, ...]]) -> list[tuple[str, ...]]:
- """Remove the common prefix from a list of tuples.
-
- Args:
- tuples: A list of tuples to remove the common prefix from.
-
- Returns:
- A list of tuples with the common prefix removed.
- """
-
- def longest_common_prefix(tuples_: list[tuple[str, ...]]) -> tuple[str, ...]:
- """Find the longest common prefix of a list of tuples.
-
- Args:
- tuples_: A list of tuples to find the longest common prefix of.
-
- Returns:
- The longest common prefix of the tuples.
- """
- prefix_ = tuples_[0]
- for t in tuples_:
- # Compare the current prefix with each tuple and shorten it
- prefix_ = prefix_[: min(len(prefix_), len(t))]
- for i in range(len(prefix_)):
- if prefix_[i] != t[i]:
- prefix_ = prefix_[:i]
- break
- return prefix_
-
- prefix = longest_common_prefix(tuples)
- prefix_length = len(prefix)
- return [t[prefix_length:] for t in tuples]
-
- def generate_components_schemas(self) -> dict[str, Schema]:
- """Generate the components/schemas section of the spec.
-
- Returns:
- A dictionary of schemas.
- """
- components_schemas: dict[str, Schema] = {}
-
- for name, name_group in self._model_name_groups.items():
- if len(name_group) == 1:
- self.set_reference_paths(name, name_group[0])
- components_schemas[name] = name_group[0].schema
- continue
-
- full_keys = [registered_schema.key for registered_schema in name_group]
- names = ["_".join(k) for k in self.remove_common_prefix(full_keys)]
- for name_, registered_schema in zip(names, name_group):
- self.set_reference_paths(name_, registered_schema)
- components_schemas[name_] = registered_schema.schema
-
- # Sort them by name to ensure they're always generated in the same order.
- return {name: components_schemas[name] for name in sorted(components_schemas.keys())}
-
-
-class OpenAPIContext:
- def __init__(
- self,
- openapi_config: OpenAPIConfig,
- plugins: Sequence[OpenAPISchemaPluginProtocol],
- ) -> None:
- self.openapi_config = openapi_config
- self.plugins = plugins
- self.operation_ids: set[str] = set()
- self.schema_registry = SchemaRegistry()
-
- def add_operation_id(self, operation_id: str) -> None:
- """Add an operation ID to the context.
-
- Args:
- operation_id: Operation ID to add.
- """
- if operation_id in self.operation_ids:
- raise ImproperlyConfiguredException(
- "operation_ids must be unique, "
- f"please ensure the value of 'operation_id' is either not set or unique for {operation_id}"
- )
- self.operation_ids.add(operation_id)
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/parameters.py b/venv/lib/python3.11/site-packages/litestar/_openapi/parameters.py
deleted file mode 100644
index c3da5c4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/parameters.py
+++ /dev/null
@@ -1,233 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING
-
-from litestar._openapi.schema_generation import SchemaCreator
-from litestar._openapi.schema_generation.utils import get_formatted_examples
-from litestar.constants import RESERVED_KWARGS
-from litestar.enums import ParamType
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.openapi.spec.parameter import Parameter
-from litestar.openapi.spec.schema import Schema
-from litestar.params import DependencyKwarg, ParameterKwarg
-from litestar.types import Empty
-from litestar.typing import FieldDefinition
-
-if TYPE_CHECKING:
- from litestar._openapi.datastructures import OpenAPIContext
- from litestar.handlers.base import BaseRouteHandler
- from litestar.openapi.spec import Reference
- from litestar.types.internal_types import PathParameterDefinition
-
-__all__ = ("create_parameters_for_handler",)
-
-
-class ParameterCollection:
- """Facilitates conditional deduplication of parameters.
-
- If multiple parameters with the same name are produced for a handler, the condition is ignored if the two
- ``Parameter`` instances are the same (the first is retained and any duplicates are ignored). If the ``Parameter``
- instances are not the same, an exception is raised.
- """
-
- def __init__(self, route_handler: BaseRouteHandler) -> None:
- """Initialize ``ParameterCollection``.
-
- Args:
- route_handler: Associated route handler
- """
- self.route_handler = route_handler
- self._parameters: dict[tuple[str, str], Parameter] = {}
-
- def add(self, parameter: Parameter) -> None:
- """Add a ``Parameter`` to the collection.
-
- If an existing parameter with the same name and type already exists, the
- parameter is ignored.
-
- If an existing parameter with the same name but different type exists, raises
- ``ImproperlyConfiguredException``.
- """
-
- if (parameter.name, parameter.param_in) not in self._parameters:
- # because we are defining routes as unique per path, we have to handle here a situation when there is an optional
- # path parameter. e.g. get(path=["/", "/{param:str}"]). When parsing the parameter for path, the route handler
- # would still have a kwarg called param:
- # def handler(param: str | None) -> ...
- if parameter.param_in != ParamType.QUERY or all(
- f"{{{parameter.name}:" not in path for path in self.route_handler.paths
- ):
- self._parameters[(parameter.name, parameter.param_in)] = parameter
- return
-
- pre_existing = self._parameters[(parameter.name, parameter.param_in)]
- if parameter == pre_existing:
- return
-
- raise ImproperlyConfiguredException(
- f"OpenAPI schema generation for handler `{self.route_handler}` detected multiple parameters named "
- f"'{parameter.name}' with different types."
- )
-
- def list(self) -> list[Parameter]:
- """Return a list of all ``Parameter``'s in the collection."""
- return list(self._parameters.values())
-
-
-class ParameterFactory:
- """Factory for creating OpenAPI Parameters for a given route handler."""
-
- def __init__(
- self,
- context: OpenAPIContext,
- route_handler: BaseRouteHandler,
- path_parameters: tuple[PathParameterDefinition, ...],
- ) -> None:
- """Initialize ParameterFactory.
-
- Args:
- context: The OpenAPI context.
- route_handler: The route handler.
- path_parameters: The path parameters for the route.
- """
- self.context = context
- self.schema_creator = SchemaCreator.from_openapi_context(self.context, prefer_alias=True)
- self.route_handler = route_handler
- self.parameters = ParameterCollection(route_handler)
- self.dependency_providers = route_handler.resolve_dependencies()
- self.layered_parameters = route_handler.resolve_layered_parameters()
- self.path_parameters_names = {p.name for p in path_parameters}
-
- def create_parameter(self, field_definition: FieldDefinition, parameter_name: str) -> Parameter:
- """Create an OpenAPI Parameter instance for a field definition.
-
- Args:
- field_definition: The field definition.
- parameter_name: The name of the parameter.
- """
-
- result: Schema | Reference | None = None
- kwarg_definition = (
- field_definition.kwarg_definition if isinstance(field_definition.kwarg_definition, ParameterKwarg) else None
- )
-
- if parameter_name in self.path_parameters_names:
- param_in = ParamType.PATH
- is_required = True
- result = self.schema_creator.for_field_definition(field_definition)
- elif kwarg_definition and kwarg_definition.header:
- parameter_name = kwarg_definition.header
- param_in = ParamType.HEADER
- is_required = field_definition.is_required
- elif kwarg_definition and kwarg_definition.cookie:
- parameter_name = kwarg_definition.cookie
- param_in = ParamType.COOKIE
- is_required = field_definition.is_required
- else:
- is_required = field_definition.is_required
- param_in = ParamType.QUERY
- parameter_name = kwarg_definition.query if kwarg_definition and kwarg_definition.query else parameter_name
-
- if not result:
- result = self.schema_creator.for_field_definition(field_definition)
-
- schema = result if isinstance(result, Schema) else self.context.schema_registry.from_reference(result).schema
-
- examples_list = kwarg_definition.examples or [] if kwarg_definition else []
- examples = get_formatted_examples(field_definition, examples_list)
-
- return Parameter(
- description=schema.description,
- name=parameter_name,
- param_in=param_in,
- required=is_required,
- schema=result,
- examples=examples or None,
- )
-
- def get_layered_parameter(self, field_name: str, field_definition: FieldDefinition) -> Parameter:
- """Create a parameter for a field definition that has a KwargDefinition defined on the layers.
-
- Args:
- field_name: The name of the field.
- field_definition: The field definition.
- """
- layer_field = self.layered_parameters[field_name]
-
- field = field_definition if field_definition.is_parameter_field else layer_field
- default = layer_field.default if field_definition.has_default else field_definition.default
- annotation = field_definition.annotation if field_definition is not Empty else layer_field.annotation
-
- parameter_name = field_name
- if isinstance(field.kwarg_definition, ParameterKwarg):
- parameter_name = (
- field.kwarg_definition.query
- or field.kwarg_definition.header
- or field.kwarg_definition.cookie
- or field_name
- )
-
- field_definition = FieldDefinition.from_kwarg(
- inner_types=field.inner_types,
- default=default,
- extra=field.extra,
- annotation=annotation,
- kwarg_definition=field.kwarg_definition,
- name=field_name,
- )
- return self.create_parameter(field_definition=field_definition, parameter_name=parameter_name)
-
- def create_parameters_for_field_definitions(self, fields: dict[str, FieldDefinition]) -> None:
- """Add Parameter models to the handler's collection for the given field definitions.
-
- Args:
- fields: The field definitions.
- """
- unique_handler_fields = (
- (k, v) for k, v in fields.items() if k not in RESERVED_KWARGS and k not in self.layered_parameters
- )
- unique_layered_fields = (
- (k, v) for k, v in self.layered_parameters.items() if k not in RESERVED_KWARGS and k not in fields
- )
- intersection_fields = (
- (k, v) for k, v in fields.items() if k not in RESERVED_KWARGS and k in self.layered_parameters
- )
-
- for field_name, field_definition in unique_handler_fields:
- if (
- isinstance(field_definition.kwarg_definition, DependencyKwarg)
- and field_name not in self.dependency_providers
- ):
- # never document explicit dependencies
- continue
-
- if provider := self.dependency_providers.get(field_name):
- self.create_parameters_for_field_definitions(fields=provider.parsed_fn_signature.parameters)
- else:
- self.parameters.add(self.create_parameter(field_definition=field_definition, parameter_name=field_name))
-
- for field_name, field_definition in unique_layered_fields:
- self.parameters.add(self.create_parameter(field_definition=field_definition, parameter_name=field_name))
-
- for field_name, field_definition in intersection_fields:
- self.parameters.add(self.get_layered_parameter(field_name=field_name, field_definition=field_definition))
-
- def create_parameters_for_handler(self) -> list[Parameter]:
- """Create a list of path/query/header Parameter models for the given PathHandler."""
- handler_fields = self.route_handler.parsed_fn_signature.parameters
- self.create_parameters_for_field_definitions(handler_fields)
- return self.parameters.list()
-
-
-def create_parameters_for_handler(
- context: OpenAPIContext,
- route_handler: BaseRouteHandler,
- path_parameters: tuple[PathParameterDefinition, ...],
-) -> list[Parameter]:
- """Create a list of path/query/header Parameter models for the given PathHandler."""
- factory = ParameterFactory(
- context=context,
- route_handler=route_handler,
- path_parameters=path_parameters,
- )
- return factory.create_parameters_for_handler()
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/path_item.py b/venv/lib/python3.11/site-packages/litestar/_openapi/path_item.py
deleted file mode 100644
index 74a04ce..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/path_item.py
+++ /dev/null
@@ -1,137 +0,0 @@
-from __future__ import annotations
-
-from inspect import cleandoc
-from typing import TYPE_CHECKING
-
-from litestar._openapi.parameters import create_parameters_for_handler
-from litestar._openapi.request_body import create_request_body
-from litestar._openapi.responses import create_responses_for_handler
-from litestar._openapi.utils import SEPARATORS_CLEANUP_PATTERN
-from litestar.enums import HttpMethod
-from litestar.openapi.spec import Operation, PathItem
-from litestar.utils.helpers import unwrap_partial
-
-if TYPE_CHECKING:
- from litestar._openapi.datastructures import OpenAPIContext
- from litestar.handlers.http_handlers import HTTPRouteHandler
- from litestar.routes import HTTPRoute
-
-__all__ = ("create_path_item_for_route",)
-
-
-class PathItemFactory:
- """Factory for creating a PathItem instance for a given route."""
-
- def __init__(self, openapi_context: OpenAPIContext, route: HTTPRoute) -> None:
- self.context = openapi_context
- self.route = route
- self._path_item = PathItem()
-
- def create_path_item(self) -> PathItem:
- """Create a PathItem for the given route parsing all http_methods into Operation Models.
-
- Returns:
- A PathItem instance.
- """
- for http_method, handler_tuple in self.route.route_handler_map.items():
- route_handler, _ = handler_tuple
-
- if not route_handler.resolve_include_in_schema():
- continue
-
- operation = self.create_operation_for_handler_method(route_handler, HttpMethod(http_method))
-
- setattr(self._path_item, http_method.lower(), operation)
-
- return self._path_item
-
- def create_operation_for_handler_method(
- self, route_handler: HTTPRouteHandler, http_method: HttpMethod
- ) -> Operation:
- """Create an Operation instance for a given route handler and http method.
-
- Args:
- route_handler: A route handler instance.
- http_method: An HttpMethod enum value.
-
- Returns:
- An Operation instance.
- """
- operation_id = self.create_operation_id(route_handler, http_method)
- parameters = create_parameters_for_handler(self.context, route_handler, self.route.path_parameters)
- signature_fields = route_handler.parsed_fn_signature.parameters
-
- request_body = None
- if data_field := signature_fields.get("data"):
- request_body = create_request_body(
- self.context, route_handler.handler_id, route_handler.resolve_data_dto(), data_field
- )
-
- raises_validation_error = bool(data_field or self._path_item.parameters or parameters)
- responses = create_responses_for_handler(
- self.context, route_handler, raises_validation_error=raises_validation_error
- )
-
- return route_handler.operation_class(
- operation_id=operation_id,
- tags=route_handler.resolve_tags() or None,
- summary=route_handler.summary or SEPARATORS_CLEANUP_PATTERN.sub("", route_handler.handler_name.title()),
- description=self.create_description_for_handler(route_handler),
- deprecated=route_handler.deprecated,
- responses=responses,
- request_body=request_body,
- parameters=parameters or None, # type: ignore[arg-type]
- security=route_handler.resolve_security() or None,
- )
-
- def create_operation_id(self, route_handler: HTTPRouteHandler, http_method: HttpMethod) -> str:
- """Create an operation id for a given route handler and http method.
-
- Adds the operation id to the context's operation id set, where it is checked for uniqueness.
-
- Args:
- route_handler: A route handler instance.
- http_method: An HttpMethod enum value.
-
- Returns:
- An operation id string.
- """
- if isinstance(route_handler.operation_id, str):
- operation_id = route_handler.operation_id
- elif callable(route_handler.operation_id):
- operation_id = route_handler.operation_id(route_handler, http_method, self.route.path_components)
- else:
- operation_id = self.context.openapi_config.operation_id_creator(
- route_handler, http_method, self.route.path_components
- )
- self.context.add_operation_id(operation_id)
- return operation_id
-
- def create_description_for_handler(self, route_handler: HTTPRouteHandler) -> str | None:
- """Produce the operation description for a route handler.
-
- Args:
- route_handler: A route handler instance.
-
- Returns:
- An optional description string
- """
- handler_description = route_handler.description
- if handler_description is None and self.context.openapi_config.use_handler_docstrings:
- fn = unwrap_partial(route_handler.fn)
- return cleandoc(fn.__doc__) if fn.__doc__ else None
- return handler_description
-
-
-def create_path_item_for_route(openapi_context: OpenAPIContext, route: HTTPRoute) -> PathItem:
- """Create a PathItem for the given route parsing all http_methods into Operation Models.
-
- Args:
- openapi_context: The OpenAPIContext instance.
- route: The route to create a PathItem for.
-
- Returns:
- A PathItem instance.
- """
- path_item_factory = PathItemFactory(openapi_context, route)
- return path_item_factory.create_path_item()
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/plugin.py b/venv/lib/python3.11/site-packages/litestar/_openapi/plugin.py
deleted file mode 100644
index 9bdbdec..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/plugin.py
+++ /dev/null
@@ -1,75 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING
-
-from litestar._openapi.datastructures import OpenAPIContext
-from litestar._openapi.path_item import create_path_item_for_route
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.plugins import InitPluginProtocol
-from litestar.plugins.base import ReceiveRoutePlugin
-from litestar.routes import HTTPRoute
-
-if TYPE_CHECKING:
- from litestar.app import Litestar
- from litestar.config.app import AppConfig
- from litestar.openapi.config import OpenAPIConfig
- from litestar.openapi.spec import OpenAPI
- from litestar.routes import BaseRoute
-
-
-class OpenAPIPlugin(InitPluginProtocol, ReceiveRoutePlugin):
- __slots__ = (
- "app",
- "included_routes",
- "_openapi_config",
- "_openapi_schema",
- )
-
- def __init__(self, app: Litestar) -> None:
- self.app = app
- self.included_routes: dict[str, HTTPRoute] = {}
- self._openapi_config: OpenAPIConfig | None = None
- self._openapi_schema: OpenAPI | None = None
-
- def _build_openapi_schema(self) -> OpenAPI:
- openapi_config = self.openapi_config
-
- if openapi_config.create_examples:
- from litestar._openapi.schema_generation.examples import ExampleFactory
-
- ExampleFactory.seed_random(openapi_config.random_seed)
-
- openapi = openapi_config.to_openapi_schema()
- context = OpenAPIContext(openapi_config=openapi_config, plugins=self.app.plugins.openapi)
- openapi.paths = {
- route.path_format or "/": create_path_item_for_route(context, route)
- for route in self.included_routes.values()
- }
- openapi.components.schemas = context.schema_registry.generate_components_schemas()
- return openapi
-
- def provide_openapi(self) -> OpenAPI:
- if not self._openapi_schema:
- self._openapi_schema = self._build_openapi_schema()
- return self._openapi_schema
-
- def on_app_init(self, app_config: AppConfig) -> AppConfig:
- if app_config.openapi_config:
- self._openapi_config = app_config.openapi_config
- app_config.route_handlers.append(self.openapi_config.openapi_controller)
- return app_config
-
- @property
- def openapi_config(self) -> OpenAPIConfig:
- if not self._openapi_config:
- raise ImproperlyConfiguredException("OpenAPIConfig not initialized")
- return self._openapi_config
-
- def receive_route(self, route: BaseRoute) -> None:
- if not isinstance(route, HTTPRoute):
- return
-
- if any(route_handler.resolve_include_in_schema() for route_handler, _ in route.route_handler_map.values()):
- # Force recompute the schema if a new route is added
- self._openapi_schema = None
- self.included_routes[route.path] = route
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/request_body.py b/venv/lib/python3.11/site-packages/litestar/_openapi/request_body.py
deleted file mode 100644
index 7a5cf37..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/request_body.py
+++ /dev/null
@@ -1,51 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING
-
-from litestar._openapi.schema_generation import SchemaCreator
-from litestar.enums import RequestEncodingType
-from litestar.openapi.spec.media_type import OpenAPIMediaType
-from litestar.openapi.spec.request_body import RequestBody
-from litestar.params import BodyKwarg
-
-__all__ = ("create_request_body",)
-
-
-if TYPE_CHECKING:
- from litestar._openapi.datastructures import OpenAPIContext
- from litestar.dto import AbstractDTO
- from litestar.typing import FieldDefinition
-
-
-def create_request_body(
- context: OpenAPIContext,
- handler_id: str,
- resolved_data_dto: type[AbstractDTO] | None,
- data_field: FieldDefinition,
-) -> RequestBody:
- """Create a RequestBody instance for the given route handler's data field.
-
- Args:
- context: The OpenAPIContext instance.
- handler_id: The handler id.
- resolved_data_dto: The resolved data dto.
- data_field: The data field.
-
- Returns:
- A RequestBody instance.
- """
- media_type: RequestEncodingType | str = RequestEncodingType.JSON
- schema_creator = SchemaCreator.from_openapi_context(context, prefer_alias=True)
- if isinstance(data_field.kwarg_definition, BodyKwarg) and data_field.kwarg_definition.media_type:
- media_type = data_field.kwarg_definition.media_type
-
- if resolved_data_dto:
- schema = resolved_data_dto.create_openapi_schema(
- field_definition=data_field,
- handler_id=handler_id,
- schema_creator=schema_creator,
- )
- else:
- schema = schema_creator.for_field_definition(data_field)
-
- return RequestBody(required=True, content={media_type: OpenAPIMediaType(schema=schema)})
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/responses.py b/venv/lib/python3.11/site-packages/litestar/_openapi/responses.py
deleted file mode 100644
index 6b0f312..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/responses.py
+++ /dev/null
@@ -1,335 +0,0 @@
-from __future__ import annotations
-
-import contextlib
-import re
-from copy import copy
-from dataclasses import asdict
-from http import HTTPStatus
-from operator import attrgetter
-from typing import TYPE_CHECKING, Any, Iterator
-
-from litestar._openapi.schema_generation import SchemaCreator
-from litestar._openapi.schema_generation.utils import get_formatted_examples
-from litestar.enums import MediaType
-from litestar.exceptions import HTTPException, ValidationException
-from litestar.openapi.spec import Example, OpenAPIResponse, Reference
-from litestar.openapi.spec.enums import OpenAPIFormat, OpenAPIType
-from litestar.openapi.spec.header import OpenAPIHeader
-from litestar.openapi.spec.media_type import OpenAPIMediaType
-from litestar.openapi.spec.schema import Schema
-from litestar.response import (
- File,
- Redirect,
- Stream,
- Template,
-)
-from litestar.response import (
- Response as LitestarResponse,
-)
-from litestar.response.base import ASGIResponse
-from litestar.types.builtin_types import NoneType
-from litestar.typing import FieldDefinition
-from litestar.utils import get_enum_string_value, get_name
-
-if TYPE_CHECKING:
- from litestar._openapi.datastructures import OpenAPIContext
- from litestar.datastructures.cookie import Cookie
- from litestar.handlers.http_handlers import HTTPRouteHandler
- from litestar.openapi.spec.responses import Responses
-
-
-__all__ = ("create_responses_for_handler",)
-
-CAPITAL_LETTERS_PATTERN = re.compile(r"(?=[A-Z])")
-
-
-def pascal_case_to_text(string: str) -> str:
- """Given a 'PascalCased' string, return its split form- 'Pascal Cased'."""
- return " ".join(re.split(CAPITAL_LETTERS_PATTERN, string)).strip()
-
-
-def create_cookie_schema(cookie: Cookie) -> Schema:
- """Given a Cookie instance, return its corresponding OpenAPI schema.
-
- Args:
- cookie: Cookie
-
- Returns:
- Schema
- """
- cookie_copy = copy(cookie)
- cookie_copy.value = "<string>"
- value = cookie_copy.to_header(header="")
- return Schema(description=cookie.description or "", example=value)
-
-
-class ResponseFactory:
- """Factory for creating a Response instance for a given route handler."""
-
- def __init__(self, context: OpenAPIContext, route_handler: HTTPRouteHandler) -> None:
- """Initialize the factory.
-
- Args:
- context: An OpenAPIContext instance.
- route_handler: An HTTPRouteHandler instance.
- """
- self.context = context
- self.route_handler = route_handler
- self.field_definition = route_handler.parsed_fn_signature.return_type
- self.schema_creator = SchemaCreator.from_openapi_context(context, prefer_alias=False)
-
- def create_responses(self, raises_validation_error: bool) -> Responses | None:
- """Create the schema for responses, if any.
-
- Args:
- raises_validation_error: Boolean flag indicating whether the handler raises a ValidationException.
-
- Returns:
- Responses
- """
- responses: Responses = {
- str(self.route_handler.status_code): self.create_success_response(),
- }
-
- exceptions = list(self.route_handler.raises or [])
- if raises_validation_error and ValidationException not in exceptions:
- exceptions.append(ValidationException)
-
- for status_code, response in create_error_responses(exceptions=exceptions):
- responses[status_code] = response
-
- for status_code, response in self.create_additional_responses():
- responses[status_code] = response
-
- return responses or None
-
- def create_description(self) -> str:
- """Create the description for a success response."""
- default_descriptions: dict[Any, str] = {
- Stream: "Stream Response",
- Redirect: "Redirect Response",
- File: "File Download",
- }
- return (
- self.route_handler.response_description
- or default_descriptions.get(self.field_definition.annotation)
- or HTTPStatus(self.route_handler.status_code).description
- )
-
- def create_success_response(self) -> OpenAPIResponse:
- """Create the schema for a success response."""
- if self.field_definition.is_subclass_of((NoneType, ASGIResponse)):
- response = OpenAPIResponse(content=None, description=self.create_description())
- elif self.field_definition.is_subclass_of(Redirect):
- response = self.create_redirect_response()
- elif self.field_definition.is_subclass_of((File, Stream)):
- response = self.create_file_response()
- else:
- media_type = self.route_handler.media_type
-
- if dto := self.route_handler.resolve_return_dto():
- result = dto.create_openapi_schema(
- field_definition=self.field_definition,
- handler_id=self.route_handler.handler_id,
- schema_creator=self.schema_creator,
- )
- else:
- if self.field_definition.is_subclass_of(Template):
- field_def = FieldDefinition.from_annotation(str)
- media_type = media_type or MediaType.HTML
- elif self.field_definition.is_subclass_of(LitestarResponse):
- field_def = (
- self.field_definition.inner_types[0]
- if self.field_definition.inner_types
- else FieldDefinition.from_annotation(Any)
- )
- media_type = media_type or MediaType.JSON
- else:
- field_def = self.field_definition
-
- result = self.schema_creator.for_field_definition(field_def)
-
- schema = (
- result if isinstance(result, Schema) else self.context.schema_registry.from_reference(result).schema
- )
- schema.content_encoding = self.route_handler.content_encoding
- schema.content_media_type = self.route_handler.content_media_type
- response = OpenAPIResponse(
- content={get_enum_string_value(media_type): OpenAPIMediaType(schema=result)},
- description=self.create_description(),
- )
- self.set_success_response_headers(response)
- return response
-
- def create_redirect_response(self) -> OpenAPIResponse:
- """Create the schema for a redirect response."""
- return OpenAPIResponse(
- content=None,
- description=self.create_description(),
- headers={
- "location": OpenAPIHeader(
- schema=Schema(type=OpenAPIType.STRING), description="target path for the redirect"
- )
- },
- )
-
- def create_file_response(self) -> OpenAPIResponse:
- """Create the schema for a file/stream response."""
- return OpenAPIResponse(
- content={
- self.route_handler.media_type: OpenAPIMediaType(
- schema=Schema(
- type=OpenAPIType.STRING,
- content_encoding=self.route_handler.content_encoding,
- content_media_type=self.route_handler.content_media_type or "application/octet-stream",
- ),
- )
- },
- description=self.create_description(),
- headers={
- "content-length": OpenAPIHeader(
- schema=Schema(type=OpenAPIType.STRING), description="File size in bytes"
- ),
- "last-modified": OpenAPIHeader(
- schema=Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.DATE_TIME),
- description="Last modified data-time in RFC 2822 format",
- ),
- "etag": OpenAPIHeader(schema=Schema(type=OpenAPIType.STRING), description="Entity tag"),
- },
- )
-
- def set_success_response_headers(self, response: OpenAPIResponse) -> None:
- """Set the schema for success response headers, if any."""
-
- if response.headers is None:
- response.headers = {}
-
- if not self.schema_creator.generate_examples:
- schema_creator = self.schema_creator
- else:
- schema_creator = SchemaCreator.from_openapi_context(self.context, generate_examples=False)
-
- for response_header in self.route_handler.resolve_response_headers():
- header = OpenAPIHeader()
- for attribute_name, attribute_value in (
- (k, v) for k, v in asdict(response_header).items() if v is not None
- ):
- if attribute_name == "value":
- header.schema = schema_creator.for_field_definition(
- FieldDefinition.from_annotation(type(attribute_value))
- )
- elif attribute_name != "documentation_only":
- setattr(header, attribute_name, attribute_value)
-
- response.headers[response_header.name] = header
-
- if cookies := self.route_handler.resolve_response_cookies():
- response.headers["Set-Cookie"] = OpenAPIHeader(
- schema=Schema(
- all_of=[create_cookie_schema(cookie=cookie) for cookie in sorted(cookies, key=attrgetter("key"))]
- )
- )
-
- def create_additional_responses(self) -> Iterator[tuple[str, OpenAPIResponse]]:
- """Create the schema for additional responses, if any."""
- if not self.route_handler.responses:
- return
-
- for status_code, additional_response in self.route_handler.responses.items():
- schema_creator = SchemaCreator.from_openapi_context(
- self.context,
- prefer_alias=False,
- generate_examples=additional_response.generate_examples,
- )
- field_def = FieldDefinition.from_annotation(additional_response.data_container)
-
- examples: dict[str, Example | Reference] | None = (
- dict(get_formatted_examples(field_def, additional_response.examples))
- if additional_response.examples
- else None
- )
-
- content: dict[str, OpenAPIMediaType] | None
- if additional_response.data_container is not None:
- schema = schema_creator.for_field_definition(field_def)
- content = {additional_response.media_type: OpenAPIMediaType(schema=schema, examples=examples)}
- else:
- content = None
-
- yield (
- str(status_code),
- OpenAPIResponse(
- description=additional_response.description,
- content=content,
- ),
- )
-
-
-def create_error_responses(exceptions: list[type[HTTPException]]) -> Iterator[tuple[str, OpenAPIResponse]]:
- """Create the schema for error responses, if any."""
- grouped_exceptions: dict[int, list[type[HTTPException]]] = {}
- for exc in exceptions:
- if not grouped_exceptions.get(exc.status_code):
- grouped_exceptions[exc.status_code] = []
- grouped_exceptions[exc.status_code].append(exc)
- for status_code, exception_group in grouped_exceptions.items():
- exceptions_schemas = []
- group_description: str = ""
- for exc in exception_group:
- example_detail = ""
- if hasattr(exc, "detail") and exc.detail:
- group_description = exc.detail
- example_detail = exc.detail
-
- if not example_detail:
- with contextlib.suppress(Exception):
- example_detail = HTTPStatus(status_code).phrase
-
- exceptions_schemas.append(
- Schema(
- type=OpenAPIType.OBJECT,
- required=["detail", "status_code"],
- properties={
- "status_code": Schema(type=OpenAPIType.INTEGER),
- "detail": Schema(type=OpenAPIType.STRING),
- "extra": Schema(
- type=[OpenAPIType.NULL, OpenAPIType.OBJECT, OpenAPIType.ARRAY],
- additional_properties=Schema(),
- ),
- },
- description=pascal_case_to_text(get_name(exc)),
- examples=[{"status_code": status_code, "detail": example_detail, "extra": {}}],
- )
- )
- if len(exceptions_schemas) > 1: # noqa: SIM108
- schema = Schema(one_of=exceptions_schemas)
- else:
- schema = exceptions_schemas[0]
-
- if not group_description:
- with contextlib.suppress(Exception):
- group_description = HTTPStatus(status_code).description
-
- yield (
- str(status_code),
- OpenAPIResponse(
- description=group_description,
- content={MediaType.JSON: OpenAPIMediaType(schema=schema)},
- ),
- )
-
-
-def create_responses_for_handler(
- context: OpenAPIContext, route_handler: HTTPRouteHandler, raises_validation_error: bool
-) -> Responses | None:
- """Create the schema for responses, if any.
-
- Args:
- context: An OpenAPIContext instance.
- route_handler: An HTTPRouteHandler instance.
- raises_validation_error: Boolean flag indicating whether the handler raises a ValidationException.
-
- Returns:
- Responses
- """
- return ResponseFactory(context, route_handler).create_responses(raises_validation_error=raises_validation_error)
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__init__.py b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__init__.py
deleted file mode 100644
index 8b9183e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from .plugins import openapi_schema_plugins
-from .schema import SchemaCreator
-
-__all__ = (
- "SchemaCreator",
- "openapi_schema_plugins",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 60cdb7e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/constrained_fields.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/constrained_fields.cpython-311.pyc
deleted file mode 100644
index 156b683..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/constrained_fields.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/examples.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/examples.cpython-311.pyc
deleted file mode 100644
index 1d1a327..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/examples.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/schema.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/schema.cpython-311.pyc
deleted file mode 100644
index c382161..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/schema.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/utils.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/utils.cpython-311.pyc
deleted file mode 100644
index 8f1ed6b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/__pycache__/utils.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/constrained_fields.py b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/constrained_fields.py
deleted file mode 100644
index 80f355d..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/constrained_fields.py
+++ /dev/null
@@ -1,91 +0,0 @@
-from __future__ import annotations
-
-from datetime import date, datetime, timezone
-from re import Pattern
-from typing import TYPE_CHECKING
-
-from litestar.openapi.spec.enums import OpenAPIFormat, OpenAPIType
-from litestar.openapi.spec.schema import Schema
-
-if TYPE_CHECKING:
- from decimal import Decimal
-
- from litestar.params import KwargDefinition
-
-__all__ = (
- "create_date_constrained_field_schema",
- "create_numerical_constrained_field_schema",
- "create_string_constrained_field_schema",
-)
-
-
-def create_numerical_constrained_field_schema(
- field_type: type[int] | type[float] | type[Decimal],
- kwarg_definition: KwargDefinition,
-) -> Schema:
- """Create Schema from Constrained Int/Float/Decimal field."""
- schema = Schema(type=OpenAPIType.INTEGER if issubclass(field_type, int) else OpenAPIType.NUMBER)
- if kwarg_definition.le is not None:
- schema.maximum = float(kwarg_definition.le)
- if kwarg_definition.lt is not None:
- schema.exclusive_maximum = float(kwarg_definition.lt)
- if kwarg_definition.ge is not None:
- schema.minimum = float(kwarg_definition.ge)
- if kwarg_definition.gt is not None:
- schema.exclusive_minimum = float(kwarg_definition.gt)
- if kwarg_definition.multiple_of is not None:
- schema.multiple_of = float(kwarg_definition.multiple_of)
- return schema
-
-
-def create_date_constrained_field_schema(
- field_type: type[date] | type[datetime],
- kwarg_definition: KwargDefinition,
-) -> Schema:
- """Create Schema from Constrained Date Field."""
- schema = Schema(
- type=OpenAPIType.STRING, format=OpenAPIFormat.DATE if issubclass(field_type, date) else OpenAPIFormat.DATE_TIME
- )
- for kwarg_definition_attr, schema_attr in [
- ("le", "maximum"),
- ("lt", "exclusive_maximum"),
- ("ge", "minimum"),
- ("gt", "exclusive_minimum"),
- ]:
- if attr := getattr(kwarg_definition, kwarg_definition_attr):
- setattr(
- schema,
- schema_attr,
- datetime.combine(
- datetime.fromtimestamp(attr, tz=timezone.utc) if isinstance(attr, (float, int)) else attr,
- datetime.min.time(),
- tzinfo=timezone.utc,
- ).timestamp(),
- )
-
- return schema
-
-
-def create_string_constrained_field_schema(
- field_type: type[str] | type[bytes],
- kwarg_definition: KwargDefinition,
-) -> Schema:
- """Create Schema from Constrained Str/Bytes field."""
- schema = Schema(type=OpenAPIType.STRING)
- if issubclass(field_type, bytes):
- schema.content_encoding = "utf-8"
- if kwarg_definition.min_length:
- schema.min_length = kwarg_definition.min_length
- if kwarg_definition.max_length:
- schema.max_length = kwarg_definition.max_length
- if kwarg_definition.pattern:
- schema.pattern = (
- kwarg_definition.pattern.pattern # type: ignore[attr-defined]
- if isinstance(kwarg_definition.pattern, Pattern) # type: ignore[unreachable]
- else kwarg_definition.pattern
- )
- if kwarg_definition.lower_case:
- schema.description = "must be in lower case"
- if kwarg_definition.upper_case:
- schema.description = "must be in upper case"
- return schema
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/examples.py b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/examples.py
deleted file mode 100644
index 49edf72..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/examples.py
+++ /dev/null
@@ -1,84 +0,0 @@
-from __future__ import annotations
-
-import typing
-from dataclasses import replace
-from decimal import Decimal
-from enum import Enum
-from typing import TYPE_CHECKING, Any
-
-import msgspec
-from polyfactory.exceptions import ParameterException
-from polyfactory.factories import DataclassFactory
-from polyfactory.field_meta import FieldMeta, Null
-from polyfactory.utils.helpers import unwrap_annotation
-from polyfactory.utils.predicates import is_union
-from typing_extensions import get_args
-
-from litestar.contrib.pydantic.utils import is_pydantic_model_instance
-from litestar.openapi.spec import Example
-from litestar.types import Empty
-
-if TYPE_CHECKING:
- from litestar.typing import FieldDefinition
-
-
-class ExampleFactory(DataclassFactory[Example]):
- __model__ = Example
- __random_seed__ = 10
-
-
-def _normalize_example_value(value: Any) -> Any:
- """Normalize the example value to make it look a bit prettier."""
- # if UnsetType is part of the union, then it might get chosen as the value
- # but that will not be properly serialized by msgspec unless it is for a field
- # in a msgspec Struct
- if is_union(value):
- args = list(get_args(value))
- try:
- args.remove(msgspec.UnsetType)
- value = typing.Union[tuple(args)] # pyright: ignore
- except ValueError:
- # UnsetType not part of the Union
- pass
-
- value = unwrap_annotation(annotation=value, random=ExampleFactory.__random__)
- if isinstance(value, (Decimal, float)):
- value = round(float(value), 2)
- if isinstance(value, Enum):
- value = value.value
- if is_pydantic_model_instance(value):
- from litestar.contrib.pydantic import _model_dump
-
- value = _model_dump(value)
- if isinstance(value, (list, set)):
- value = [_normalize_example_value(v) for v in value]
- if isinstance(value, dict):
- for k, v in value.items():
- value[k] = _normalize_example_value(v)
- return value
-
-
-def _create_field_meta(field: FieldDefinition) -> FieldMeta:
- return FieldMeta.from_type(
- annotation=field.annotation,
- default=field.default if field.default is not Empty else Null,
- name=field.name,
- random=ExampleFactory.__random__,
- )
-
-
-def create_examples_for_field(field: FieldDefinition) -> list[Example]:
- """Create an OpenAPI Example instance.
-
- Args:
- field: A signature field.
-
- Returns:
- A list including a single example.
- """
- try:
- field_meta = _create_field_meta(replace(field, annotation=_normalize_example_value(field.annotation)))
- value = ExampleFactory.get_field_value(field_meta)
- return [Example(description=f"Example {field.name} value", value=value)]
- except ParameterException:
- return []
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__init__.py b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__init__.py
deleted file mode 100644
index 1b12b1e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from .dataclass import DataclassSchemaPlugin
-from .pagination import PaginationSchemaPlugin
-from .struct import StructSchemaPlugin
-from .typed_dict import TypedDictSchemaPlugin
-
-__all__ = ("openapi_schema_plugins",)
-
-# NOTE: The Pagination type plugin has to come before the Dataclass plugin since the Pagination
-# classes are dataclasses, but we want to handle them differently from how dataclasses are normally
-# handled.
-openapi_schema_plugins = [
- PaginationSchemaPlugin(),
- StructSchemaPlugin(),
- DataclassSchemaPlugin(),
- TypedDictSchemaPlugin(),
-]
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index f022bdd..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/dataclass.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/dataclass.cpython-311.pyc
deleted file mode 100644
index 7cbfe6f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/dataclass.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/pagination.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/pagination.cpython-311.pyc
deleted file mode 100644
index 0bc4add..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/pagination.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/struct.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/struct.cpython-311.pyc
deleted file mode 100644
index cef9d12..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/struct.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/typed_dict.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/typed_dict.cpython-311.pyc
deleted file mode 100644
index 3d534ba..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/__pycache__/typed_dict.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/dataclass.py b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/dataclass.py
deleted file mode 100644
index fb5da35..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/dataclass.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import MISSING, fields
-from typing import TYPE_CHECKING
-
-from litestar.plugins import OpenAPISchemaPlugin
-from litestar.typing import FieldDefinition
-from litestar.utils.predicates import is_optional_union
-
-if TYPE_CHECKING:
- from litestar._openapi.schema_generation import SchemaCreator
- from litestar.openapi.spec import Schema
-
-
-class DataclassSchemaPlugin(OpenAPISchemaPlugin):
- def is_plugin_supported_field(self, field_definition: FieldDefinition) -> bool:
- return field_definition.is_dataclass_type
-
- def to_openapi_schema(self, field_definition: FieldDefinition, schema_creator: SchemaCreator) -> Schema:
- type_hints = field_definition.get_type_hints(include_extras=True, resolve_generics=True)
- dataclass_fields = fields(field_definition.type_)
- return schema_creator.create_component_schema(
- field_definition,
- required=sorted(
- field.name
- for field in dataclass_fields
- if (
- field.default is MISSING
- and field.default_factory is MISSING
- and not is_optional_union(type_hints[field.name])
- )
- ),
- property_fields={
- field.name: FieldDefinition.from_kwarg(type_hints[field.name], field.name) for field in dataclass_fields
- },
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/pagination.py b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/pagination.py
deleted file mode 100644
index 9b4f6c6..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/pagination.py
+++ /dev/null
@@ -1,60 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING
-
-from litestar.openapi.spec import OpenAPIType, Schema
-from litestar.pagination import ClassicPagination, CursorPagination, OffsetPagination
-from litestar.plugins import OpenAPISchemaPlugin
-
-if TYPE_CHECKING:
- from litestar._openapi.schema_generation import SchemaCreator
- from litestar.typing import FieldDefinition
-
-
-class PaginationSchemaPlugin(OpenAPISchemaPlugin):
- def is_plugin_supported_field(self, field_definition: FieldDefinition) -> bool:
- return field_definition.origin in (ClassicPagination, CursorPagination, OffsetPagination)
-
- def to_openapi_schema(self, field_definition: FieldDefinition, schema_creator: SchemaCreator) -> Schema:
- if field_definition.origin is ClassicPagination:
- return Schema(
- type=OpenAPIType.OBJECT,
- properties={
- "items": Schema(
- type=OpenAPIType.ARRAY,
- items=schema_creator.for_field_definition(field_definition.inner_types[0]),
- ),
- "page_size": Schema(type=OpenAPIType.INTEGER, description="Number of items per page."),
- "current_page": Schema(type=OpenAPIType.INTEGER, description="Current page number."),
- "total_pages": Schema(type=OpenAPIType.INTEGER, description="Total number of pages."),
- },
- )
-
- if field_definition.origin is OffsetPagination:
- return Schema(
- type=OpenAPIType.OBJECT,
- properties={
- "items": Schema(
- type=OpenAPIType.ARRAY,
- items=schema_creator.for_field_definition(field_definition.inner_types[0]),
- ),
- "limit": Schema(type=OpenAPIType.INTEGER, description="Maximal number of items to send."),
- "offset": Schema(type=OpenAPIType.INTEGER, description="Offset from the beginning of the query."),
- "total": Schema(type=OpenAPIType.INTEGER, description="Total number of items."),
- },
- )
-
- cursor_schema = schema_creator.not_generating_examples.for_field_definition(field_definition.inner_types[0])
- cursor_schema.description = "Unique ID, designating the last identifier in the given data set. This value can be used to request the 'next' batch of records."
-
- return Schema(
- type=OpenAPIType.OBJECT,
- properties={
- "items": Schema(
- type=OpenAPIType.ARRAY,
- items=schema_creator.for_field_definition(field_definition=field_definition.inner_types[1]),
- ),
- "cursor": cursor_schema,
- "results_per_page": Schema(type=OpenAPIType.INTEGER, description="Maximal number of items to send."),
- },
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/struct.py b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/struct.py
deleted file mode 100644
index aabfdb3..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/struct.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING
-
-from msgspec import Struct
-from msgspec.structs import fields
-
-from litestar.plugins import OpenAPISchemaPlugin
-from litestar.types.empty import Empty
-from litestar.typing import FieldDefinition
-from litestar.utils.predicates import is_optional_union
-
-if TYPE_CHECKING:
- from msgspec.structs import FieldInfo
-
- from litestar._openapi.schema_generation import SchemaCreator
- from litestar.openapi.spec import Schema
-
-
-class StructSchemaPlugin(OpenAPISchemaPlugin):
- def is_plugin_supported_field(self, field_definition: FieldDefinition) -> bool:
- return not field_definition.is_union and field_definition.is_subclass_of(Struct)
-
- def to_openapi_schema(self, field_definition: FieldDefinition, schema_creator: SchemaCreator) -> Schema:
- def is_field_required(field: FieldInfo) -> bool:
- return field.required or field.default_factory is Empty
-
- type_hints = field_definition.get_type_hints(include_extras=True, resolve_generics=True)
- struct_fields = fields(field_definition.type_)
-
- return schema_creator.create_component_schema(
- field_definition,
- required=sorted(
- [
- field.encode_name
- for field in struct_fields
- if is_field_required(field=field) and not is_optional_union(type_hints[field.name])
- ]
- ),
- property_fields={
- field.encode_name: FieldDefinition.from_kwarg(type_hints[field.name], field.encode_name)
- for field in struct_fields
- },
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/typed_dict.py b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/typed_dict.py
deleted file mode 100644
index ef34e2b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/plugins/typed_dict.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING
-
-from litestar.plugins import OpenAPISchemaPlugin
-from litestar.typing import FieldDefinition
-
-if TYPE_CHECKING:
- from litestar._openapi.schema_generation import SchemaCreator
- from litestar.openapi.spec import Schema
-
-
-class TypedDictSchemaPlugin(OpenAPISchemaPlugin):
- def is_plugin_supported_field(self, field_definition: FieldDefinition) -> bool:
- return field_definition.is_typeddict_type
-
- def to_openapi_schema(self, field_definition: FieldDefinition, schema_creator: SchemaCreator) -> Schema:
- type_hints = field_definition.get_type_hints(include_extras=True, resolve_generics=True)
-
- return schema_creator.create_component_schema(
- field_definition,
- required=sorted(getattr(field_definition.type_, "__required_keys__", [])),
- property_fields={k: FieldDefinition.from_kwarg(v, k) for k, v in type_hints.items()},
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/schema.py b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/schema.py
deleted file mode 100644
index 0b7d6c6..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/schema.py
+++ /dev/null
@@ -1,616 +0,0 @@
-from __future__ import annotations
-
-from collections import deque
-from copy import copy
-from datetime import date, datetime, time, timedelta
-from decimal import Decimal
-from enum import Enum, EnumMeta
-from ipaddress import IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network
-from pathlib import Path
-from typing import (
- TYPE_CHECKING,
- Any,
- DefaultDict,
- Deque,
- Dict,
- FrozenSet,
- Hashable,
- Iterable,
- List,
- Literal,
- Mapping,
- MutableMapping,
- MutableSequence,
- OrderedDict,
- Pattern,
- Sequence,
- Set,
- Tuple,
- Union,
- cast,
-)
-from uuid import UUID
-
-from typing_extensions import Self, get_args
-
-from litestar._openapi.datastructures import SchemaRegistry
-from litestar._openapi.schema_generation.constrained_fields import (
- create_date_constrained_field_schema,
- create_numerical_constrained_field_schema,
- create_string_constrained_field_schema,
-)
-from litestar._openapi.schema_generation.utils import (
- _get_normalized_schema_key,
- _should_create_enum_schema,
- _should_create_literal_schema,
- _type_or_first_not_none_inner_type,
- get_json_schema_formatted_examples,
-)
-from litestar.datastructures import UploadFile
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.openapi.spec.enums import OpenAPIFormat, OpenAPIType
-from litestar.openapi.spec.schema import Schema, SchemaDataContainer
-from litestar.params import BodyKwarg, ParameterKwarg
-from litestar.plugins import OpenAPISchemaPlugin
-from litestar.types import Empty
-from litestar.types.builtin_types import NoneType
-from litestar.typing import FieldDefinition
-from litestar.utils.helpers import get_name
-from litestar.utils.predicates import (
- is_class_and_subclass,
- is_undefined_sentinel,
-)
-from litestar.utils.typing import (
- get_origin_or_inner_type,
- make_non_optional_union,
-)
-
-if TYPE_CHECKING:
- from litestar._openapi.datastructures import OpenAPIContext
- from litestar.openapi.spec import Example, Reference
- from litestar.plugins import OpenAPISchemaPluginProtocol
-
-KWARG_DEFINITION_ATTRIBUTE_TO_OPENAPI_PROPERTY_MAP: dict[str, str] = {
- "content_encoding": "content_encoding",
- "default": "default",
- "description": "description",
- "enum": "enum",
- "examples": "examples",
- "external_docs": "external_docs",
- "format": "format",
- "ge": "minimum",
- "gt": "exclusive_minimum",
- "le": "maximum",
- "lt": "exclusive_maximum",
- "max_items": "max_items",
- "max_length": "max_length",
- "min_items": "min_items",
- "min_length": "min_length",
- "multiple_of": "multiple_of",
- "pattern": "pattern",
- "title": "title",
- "read_only": "read_only",
-}
-
-TYPE_MAP: dict[type[Any] | None | Any, Schema] = {
- Decimal: Schema(type=OpenAPIType.NUMBER),
- DefaultDict: Schema(type=OpenAPIType.OBJECT),
- Deque: Schema(type=OpenAPIType.ARRAY),
- Dict: Schema(type=OpenAPIType.OBJECT),
- FrozenSet: Schema(type=OpenAPIType.ARRAY),
- IPv4Address: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.IPV4),
- IPv4Interface: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.IPV4),
- IPv4Network: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.IPV4),
- IPv6Address: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.IPV6),
- IPv6Interface: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.IPV6),
- IPv6Network: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.IPV6),
- Iterable: Schema(type=OpenAPIType.ARRAY),
- List: Schema(type=OpenAPIType.ARRAY),
- Mapping: Schema(type=OpenAPIType.OBJECT),
- MutableMapping: Schema(type=OpenAPIType.OBJECT),
- MutableSequence: Schema(type=OpenAPIType.ARRAY),
- None: Schema(type=OpenAPIType.NULL),
- NoneType: Schema(type=OpenAPIType.NULL),
- OrderedDict: Schema(type=OpenAPIType.OBJECT),
- Path: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.URI),
- Pattern: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.REGEX),
- Sequence: Schema(type=OpenAPIType.ARRAY),
- Set: Schema(type=OpenAPIType.ARRAY),
- Tuple: Schema(type=OpenAPIType.ARRAY),
- UUID: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.UUID),
- bool: Schema(type=OpenAPIType.BOOLEAN),
- bytearray: Schema(type=OpenAPIType.STRING),
- bytes: Schema(type=OpenAPIType.STRING),
- date: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.DATE),
- datetime: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.DATE_TIME),
- deque: Schema(type=OpenAPIType.ARRAY),
- dict: Schema(type=OpenAPIType.OBJECT),
- float: Schema(type=OpenAPIType.NUMBER),
- frozenset: Schema(type=OpenAPIType.ARRAY),
- int: Schema(type=OpenAPIType.INTEGER),
- list: Schema(type=OpenAPIType.ARRAY),
- set: Schema(type=OpenAPIType.ARRAY),
- str: Schema(type=OpenAPIType.STRING),
- time: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.DURATION),
- timedelta: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.DURATION),
- tuple: Schema(type=OpenAPIType.ARRAY),
-}
-
-
-def _types_in_list(lst: list[Any]) -> list[OpenAPIType] | OpenAPIType:
- """Extract unique OpenAPITypes present in the values of a list.
-
- Args:
- lst: A list of values
-
- Returns:
- OpenAPIType in the given list. If more then one exists, return
- a list of OpenAPITypes.
- """
- schema_types: list[OpenAPIType] = []
- for item in lst:
- schema_type = TYPE_MAP[type(item)].type
- if isinstance(schema_type, OpenAPIType):
- schema_types.append(schema_type)
- else:
- raise RuntimeError("Unexpected type for schema item") # pragma: no cover
- schema_types = list(set(schema_types))
- return schema_types[0] if len(schema_types) == 1 else schema_types
-
-
-def _get_type_schema_name(field_definition: FieldDefinition) -> str:
- """Extract the schema name from a data container.
-
- Args:
- field_definition: A field definition instance.
-
- Returns:
- A string
- """
-
- if name := getattr(field_definition.annotation, "__schema_name__", None):
- return cast("str", name)
-
- name = get_name(field_definition.annotation)
- if field_definition.inner_types:
- inner_parts = ", ".join(_get_type_schema_name(t) for t in field_definition.inner_types)
- return f"{name}[{inner_parts}]"
-
- return name
-
-
-def create_enum_schema(annotation: EnumMeta, include_null: bool = False) -> Schema:
- """Create a schema instance for an enum.
-
- Args:
- annotation: An enum.
- include_null: Whether to include null as a possible value.
-
- Returns:
- A schema instance.
- """
- enum_values: list[str | int | None] = [v.value for v in annotation] # type: ignore[var-annotated]
- if include_null and None not in enum_values:
- enum_values.append(None)
- return Schema(type=_types_in_list(enum_values), enum=enum_values)
-
-
-def _iter_flat_literal_args(annotation: Any) -> Iterable[Any]:
- """Iterate over the flattened arguments of a Literal.
-
- Args:
- annotation: An Literal annotation.
-
- Yields:
- The flattened arguments of the Literal.
- """
- for arg in get_args(annotation):
- if get_origin_or_inner_type(arg) is Literal:
- yield from _iter_flat_literal_args(arg)
- else:
- yield arg.value if isinstance(arg, Enum) else arg
-
-
-def create_literal_schema(annotation: Any, include_null: bool = False) -> Schema:
- """Create a schema instance for a Literal.
-
- Args:
- annotation: An Literal annotation.
- include_null: Whether to include null as a possible value.
-
- Returns:
- A schema instance.
- """
- args = list(_iter_flat_literal_args(annotation))
- if include_null and None not in args:
- args.append(None)
- schema = Schema(type=_types_in_list(args))
- if len(args) > 1:
- schema.enum = args
- else:
- schema.const = args[0]
- return schema
-
-
-def create_schema_for_annotation(annotation: Any) -> Schema:
- """Get a schema from the type mapping - if possible.
-
- Args:
- annotation: A type annotation.
-
- Returns:
- A schema instance or None.
- """
-
- return copy(TYPE_MAP[annotation]) if annotation in TYPE_MAP else Schema()
-
-
-class SchemaCreator:
- __slots__ = ("generate_examples", "plugins", "prefer_alias", "schema_registry")
-
- def __init__(
- self,
- generate_examples: bool = False,
- plugins: Iterable[OpenAPISchemaPluginProtocol] | None = None,
- prefer_alias: bool = True,
- schema_registry: SchemaRegistry | None = None,
- ) -> None:
- """Instantiate a SchemaCreator.
-
- Args:
- generate_examples: Whether to generate examples if none are given.
- plugins: A list of plugins.
- prefer_alias: Whether to prefer the alias name for the schema.
- schema_registry: A SchemaRegistry instance.
- """
- self.generate_examples = generate_examples
- self.plugins = plugins if plugins is not None else []
- self.prefer_alias = prefer_alias
- self.schema_registry = schema_registry or SchemaRegistry()
-
- @classmethod
- def from_openapi_context(cls, context: OpenAPIContext, prefer_alias: bool = True, **kwargs: Any) -> Self:
- kwargs.setdefault("generate_examples", context.openapi_config.create_examples)
- kwargs.setdefault("plugins", context.plugins)
- kwargs.setdefault("schema_registry", context.schema_registry)
- return cls(**kwargs, prefer_alias=prefer_alias)
-
- @property
- def not_generating_examples(self) -> SchemaCreator:
- """Return a SchemaCreator with generate_examples set to False."""
- if not self.generate_examples:
- return self
- return type(self)(generate_examples=False, plugins=self.plugins, prefer_alias=False)
-
- @staticmethod
- def plugin_supports_field(plugin: OpenAPISchemaPluginProtocol, field: FieldDefinition) -> bool:
- if predicate := getattr(plugin, "is_plugin_supported_field", None):
- return predicate(field) # type: ignore[no-any-return]
- return plugin.is_plugin_supported_type(field.annotation)
-
- def get_plugin_for(self, field_definition: FieldDefinition) -> OpenAPISchemaPluginProtocol | None:
- return next(
- (plugin for plugin in self.plugins if self.plugin_supports_field(plugin, field_definition)),
- None,
- )
-
- def is_constrained_field(self, field_definition: FieldDefinition) -> bool:
- """Return if the field is constrained, taking into account constraints defined by plugins"""
- return (
- isinstance(field_definition.kwarg_definition, (ParameterKwarg, BodyKwarg))
- and field_definition.kwarg_definition.is_constrained
- ) or any(
- p.is_constrained_field(field_definition)
- for p in self.plugins
- if isinstance(p, OpenAPISchemaPlugin) and p.is_plugin_supported_field(field_definition)
- )
-
- def is_undefined(self, value: Any) -> bool:
- """Return if the field is undefined, taking into account undefined types defined by plugins"""
- return is_undefined_sentinel(value) or any(
- p.is_undefined_sentinel(value) for p in self.plugins if isinstance(p, OpenAPISchemaPlugin)
- )
-
- def for_field_definition(self, field_definition: FieldDefinition) -> Schema | Reference:
- """Create a Schema for a given FieldDefinition.
-
- Args:
- field_definition: A signature field instance.
-
- Returns:
- A schema instance.
- """
-
- result: Schema | Reference
-
- if plugin_for_annotation := self.get_plugin_for(field_definition):
- result = self.for_plugin(field_definition, plugin_for_annotation)
- elif _should_create_enum_schema(field_definition):
- annotation = _type_or_first_not_none_inner_type(field_definition)
- result = create_enum_schema(annotation, include_null=field_definition.is_optional)
- elif _should_create_literal_schema(field_definition):
- annotation = (
- make_non_optional_union(field_definition.annotation)
- if field_definition.is_optional
- else field_definition.annotation
- )
- result = create_literal_schema(annotation, include_null=field_definition.is_optional)
- elif field_definition.is_optional:
- result = self.for_optional_field(field_definition)
- elif field_definition.is_union:
- result = self.for_union_field(field_definition)
- elif field_definition.is_type_var:
- result = self.for_typevar()
- elif field_definition.inner_types and not field_definition.is_generic:
- result = self.for_object_type(field_definition)
- elif self.is_constrained_field(field_definition):
- result = self.for_constrained_field(field_definition)
- elif field_definition.is_subclass_of(UploadFile):
- result = self.for_upload_file(field_definition)
- else:
- result = create_schema_for_annotation(field_definition.annotation)
-
- return self.process_schema_result(field_definition, result) if isinstance(result, Schema) else result
-
- @staticmethod
- def for_upload_file(field_definition: FieldDefinition) -> Schema:
- """Create schema for UploadFile.
-
- Args:
- field_definition: A field definition instance.
-
- Returns:
- A Schema instance.
- """
-
- property_key = "file"
- schema = Schema(
- type=OpenAPIType.STRING,
- content_media_type="application/octet-stream",
- format=OpenAPIFormat.BINARY,
- )
-
- # If the type is `dict[str, UploadFile]`, then it's the same as a `list[UploadFile]`
- # but we will internally convert that into a `dict[str, UploadFile]`.
- if field_definition.is_non_string_sequence or field_definition.is_mapping:
- property_key = "files"
- schema = Schema(type=OpenAPIType.ARRAY, items=schema)
-
- # If the uploadfile is annotated directly on the handler, then the
- # 'properties' needs to be created. Else, the 'properties' will be
- # created by the corresponding plugin.
- is_defined_on_handler = field_definition.name == "data" and isinstance(
- field_definition.kwarg_definition, BodyKwarg
- )
- if is_defined_on_handler:
- return Schema(type=OpenAPIType.OBJECT, properties={property_key: schema})
-
- return schema
-
- @staticmethod
- def for_typevar() -> Schema:
- """Create a schema for a TypeVar.
-
- Returns:
- A schema instance.
- """
-
- return Schema(type=OpenAPIType.OBJECT)
-
- def for_optional_field(self, field_definition: FieldDefinition) -> Schema:
- """Create a Schema for an optional FieldDefinition.
-
- Args:
- field_definition: A signature field instance.
-
- Returns:
- A schema instance.
- """
- schema_or_reference = self.for_field_definition(
- FieldDefinition.from_kwarg(
- annotation=make_non_optional_union(field_definition.annotation),
- name=field_definition.name,
- default=field_definition.default,
- )
- )
- if isinstance(schema_or_reference, Schema) and isinstance(schema_or_reference.one_of, list):
- result = schema_or_reference.one_of
- else:
- result = [schema_or_reference]
-
- return Schema(one_of=[Schema(type=OpenAPIType.NULL), *result])
-
- def for_union_field(self, field_definition: FieldDefinition) -> Schema:
- """Create a Schema for a union FieldDefinition.
-
- Args:
- field_definition: A signature field instance.
-
- Returns:
- A schema instance.
- """
- inner_types = (f for f in (field_definition.inner_types or []) if not self.is_undefined(f.annotation))
- values = list(map(self.for_field_definition, inner_types))
- return Schema(one_of=values)
-
- def for_object_type(self, field_definition: FieldDefinition) -> Schema:
- """Create schema for object types (dict, Mapping, list, Sequence etc.) types.
-
- Args:
- field_definition: A signature field instance.
-
- Returns:
- A schema instance.
- """
- if field_definition.has_inner_subclass_of(UploadFile):
- return self.for_upload_file(field_definition)
-
- if field_definition.is_mapping:
- return Schema(
- type=OpenAPIType.OBJECT,
- additional_properties=(
- self.for_field_definition(field_definition.inner_types[1])
- if field_definition.inner_types and len(field_definition.inner_types) == 2
- else None
- ),
- )
-
- if field_definition.is_non_string_sequence or field_definition.is_non_string_iterable:
- # filters out ellipsis from tuple[int, ...] type annotations
- inner_types = (f for f in field_definition.inner_types if f.annotation is not Ellipsis)
- items = list(map(self.for_field_definition, inner_types or ()))
-
- return Schema(
- type=OpenAPIType.ARRAY,
- items=Schema(one_of=items) if len(items) > 1 else items[0],
- )
-
- raise ImproperlyConfiguredException( # pragma: no cover
- f"Parameter '{field_definition.name}' with type '{field_definition.annotation}' could not be mapped to an Open API type. "
- f"This can occur if a user-defined generic type is resolved as a parameter. If '{field_definition.name}' should "
- "not be documented as a parameter, annotate it using the `Dependency` function, e.g., "
- f"`{field_definition.name}: ... = Dependency(...)`."
- )
-
- def for_plugin(self, field_definition: FieldDefinition, plugin: OpenAPISchemaPluginProtocol) -> Schema | Reference:
- """Create a schema using a plugin.
-
- Args:
- field_definition: A signature field instance.
- plugin: A plugin for the field type.
-
- Returns:
- A schema instance.
- """
- key = _get_normalized_schema_key(field_definition.annotation)
- if (ref := self.schema_registry.get_reference_for_key(key)) is not None:
- return ref
-
- schema = plugin.to_openapi_schema(field_definition=field_definition, schema_creator=self)
- if isinstance(schema, SchemaDataContainer): # pragma: no cover
- return self.for_field_definition(
- FieldDefinition.from_kwarg(
- annotation=schema.data_container,
- name=field_definition.name,
- default=field_definition.default,
- extra=field_definition.extra,
- kwarg_definition=field_definition.kwarg_definition,
- )
- )
- return schema
-
- def for_constrained_field(self, field: FieldDefinition) -> Schema:
- """Create Schema for Pydantic Constrained fields (created using constr(), conint() and so forth, or by subclassing
- Constrained*)
-
- Args:
- field: A signature field instance.
-
- Returns:
- A schema instance.
- """
- kwarg_definition = cast(Union[ParameterKwarg, BodyKwarg], field.kwarg_definition)
- if any(is_class_and_subclass(field.annotation, t) for t in (int, float, Decimal)):
- return create_numerical_constrained_field_schema(field.annotation, kwarg_definition)
- if any(is_class_and_subclass(field.annotation, t) for t in (str, bytes)): # type: ignore[arg-type]
- return create_string_constrained_field_schema(field.annotation, kwarg_definition)
- if any(is_class_and_subclass(field.annotation, t) for t in (date, datetime)):
- return create_date_constrained_field_schema(field.annotation, kwarg_definition)
- return self.for_collection_constrained_field(field)
-
- def for_collection_constrained_field(self, field_definition: FieldDefinition) -> Schema:
- """Create Schema from Constrained List/Set field.
-
- Args:
- field_definition: A signature field instance.
-
- Returns:
- A schema instance.
- """
- schema = Schema(type=OpenAPIType.ARRAY)
- kwarg_definition = cast(Union[ParameterKwarg, BodyKwarg], field_definition.kwarg_definition)
- if kwarg_definition.min_items:
- schema.min_items = kwarg_definition.min_items
- if kwarg_definition.max_items:
- schema.max_items = kwarg_definition.max_items
- if any(is_class_and_subclass(field_definition.annotation, t) for t in (set, frozenset)): # type: ignore[arg-type]
- schema.unique_items = True
-
- item_creator = self.not_generating_examples
- if field_definition.inner_types:
- items = list(map(item_creator.for_field_definition, field_definition.inner_types))
- schema.items = Schema(one_of=items) if len(items) > 1 else items[0]
- else:
- schema.items = item_creator.for_field_definition(
- FieldDefinition.from_kwarg(
- field_definition.annotation.item_type, f"{field_definition.annotation.__name__}Field"
- )
- )
- return schema
-
- def process_schema_result(self, field: FieldDefinition, schema: Schema) -> Schema | Reference:
- if field.kwarg_definition and field.is_const and field.has_default and schema.const is None:
- schema.const = field.default
-
- if field.kwarg_definition:
- for kwarg_definition_key, schema_key in KWARG_DEFINITION_ATTRIBUTE_TO_OPENAPI_PROPERTY_MAP.items():
- if (value := getattr(field.kwarg_definition, kwarg_definition_key, Empty)) and (
- not isinstance(value, Hashable) or not self.is_undefined(value)
- ):
- if schema_key == "examples":
- value = get_json_schema_formatted_examples(cast("list[Example]", value))
-
- # we only want to transfer values from the `KwargDefinition` to `Schema` if the schema object
- # doesn't already have a value for that property. For example, if a field is a constrained date,
- # by this point, we have already set the `exclusive_minimum` and/or `exclusive_maximum` fields
- # to floating point timestamp values on the schema object. However, the original `date` objects
- # that define those constraints on `KwargDefinition` are still `date` objects. We don't want to
- # overwrite them here.
- if getattr(schema, schema_key, None) is None:
- setattr(schema, schema_key, value)
-
- if not schema.examples and self.generate_examples:
- from litestar._openapi.schema_generation.examples import create_examples_for_field
-
- schema.examples = get_json_schema_formatted_examples(create_examples_for_field(field))
-
- if schema.title and schema.type == OpenAPIType.OBJECT:
- key = _get_normalized_schema_key(field.annotation)
- return self.schema_registry.get_reference_for_key(key) or schema
- return schema
-
- def create_component_schema(
- self,
- type_: FieldDefinition,
- /,
- required: list[str],
- property_fields: Mapping[str, FieldDefinition],
- openapi_type: OpenAPIType = OpenAPIType.OBJECT,
- title: str | None = None,
- examples: list[Any] | None = None,
- ) -> Schema:
- """Create a schema for the components/schemas section of the OpenAPI spec.
-
- These are schemas that can be referenced by other schemas in the document, including self references.
-
- To support self referencing schemas, the schema is added to the registry before schemas for its properties
- are created. This allows the schema to be referenced by its properties.
-
- Args:
- type_: ``FieldDefinition`` instance of the type to create a schema for.
- required: A list of required fields.
- property_fields: Mapping of name to ``FieldDefinition`` instances for the properties of the schema.
- openapi_type: The OpenAPI type, defaults to ``OpenAPIType.OBJECT``.
- title: The schema title, generated if not provided.
- examples: A mapping of example names to ``Example`` instances, not required.
-
- Returns:
- A schema instance.
- """
- schema = self.schema_registry.get_schema_for_key(_get_normalized_schema_key(type_.annotation))
- schema.title = title or _get_type_schema_name(type_)
- schema.required = required
- schema.type = openapi_type
- schema.properties = {k: self.for_field_definition(v) for k, v in property_fields.items()}
- schema.examples = examples
- return schema
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/utils.py b/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/utils.py
deleted file mode 100644
index 7ce27ca..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/schema_generation/utils.py
+++ /dev/null
@@ -1,114 +0,0 @@
-from __future__ import annotations
-
-from enum import Enum
-from typing import TYPE_CHECKING, Any, Mapping, _GenericAlias # type: ignore[attr-defined]
-
-from litestar.utils.helpers import get_name
-
-if TYPE_CHECKING:
- from collections.abc import Sequence
-
- from litestar.openapi.spec import Example
- from litestar.typing import FieldDefinition
-
-__all__ = (
- "_type_or_first_not_none_inner_type",
- "_should_create_enum_schema",
- "_should_create_literal_schema",
- "_get_normalized_schema_key",
-)
-
-
-def _type_or_first_not_none_inner_type(field_definition: FieldDefinition) -> Any:
- """Get the first inner type that is not None.
-
- This is a narrow focussed utility to be used when we know that a field definition either represents
- a single type, or a single type in a union with `None`, and we want the single type.
-
- Args:
- field_definition: A field definition instance.
-
- Returns:
- A field definition instance.
- """
- if not field_definition.is_optional:
- return field_definition.annotation
- inner = next((t for t in field_definition.inner_types if not t.is_none_type), None)
- if inner is None:
- raise ValueError("Field definition has no inner type that is not None")
- return inner.annotation
-
-
-def _should_create_enum_schema(field_definition: FieldDefinition) -> bool:
- """Predicate to determine if we should create an enum schema for the field def, or not.
-
- This returns true if the field definition is an enum, or if the field definition is a union
- of an enum and ``None``.
-
- When an annotation is ``SomeEnum | None`` we should create a schema for the enum that includes ``null``
- in the enum values.
-
- Args:
- field_definition: A field definition instance.
-
- Returns:
- A boolean
- """
- return field_definition.is_subclass_of(Enum) or (
- field_definition.is_optional
- and len(field_definition.args) == 2
- and field_definition.has_inner_subclass_of(Enum)
- )
-
-
-def _should_create_literal_schema(field_definition: FieldDefinition) -> bool:
- """Predicate to determine if we should create a literal schema for the field def, or not.
-
- This returns ``True`` if the field definition is an literal, or if the field definition is a union
- of a literal and None.
-
- When an annotation is `Literal["anything"] | None` we should create a schema for the literal that includes `null`
- in the enum values.
-
- Args:
- field_definition: A field definition instance.
-
- Returns:
- A boolean
- """
- return (
- field_definition.is_literal
- or field_definition.is_optional
- and all(inner.is_literal for inner in field_definition.inner_types if not inner.is_none_type)
- )
-
-
-def _get_normalized_schema_key(annotation: Any) -> tuple[str, ...]:
- """Create a key for a type annotation.
-
- The key should be a tuple such as ``("path", "to", "type", "TypeName")``.
-
- Args:
- annotation: a type annotation
-
- Returns:
- A tuple of strings.
- """
- module = getattr(annotation, "__module__", "")
- name = str(annotation)[len(module) + 1 :] if isinstance(annotation, _GenericAlias) else annotation.__qualname__
- name = name.replace(".<locals>.", ".")
- return *module.split("."), name
-
-
-def get_formatted_examples(field_definition: FieldDefinition, examples: Sequence[Example]) -> Mapping[str, Example]:
- """Format the examples into the OpenAPI schema format."""
-
- name = field_definition.name or get_name(field_definition.type_)
- name = name.lower()
-
- return {f"{name}-example-{i}": example for i, example in enumerate(examples, 1)}
-
-
-def get_json_schema_formatted_examples(examples: Sequence[Example]) -> list[Any]:
- """Format the examples into the JSON schema format."""
- return [example.value for example in examples]
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__init__.py b/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__init__.py
+++ /dev/null
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 7fc0cb2..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__pycache__/converter.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__pycache__/converter.cpython-311.pyc
deleted file mode 100644
index 5bc5015..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__pycache__/converter.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__pycache__/schema_parsing.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__pycache__/schema_parsing.cpython-311.pyc
deleted file mode 100644
index f6e0196..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__pycache__/schema_parsing.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__pycache__/types.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__pycache__/types.cpython-311.pyc
deleted file mode 100644
index ffe7efb..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/__pycache__/types.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/converter.py b/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/converter.py
deleted file mode 100644
index 4782dbe..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/converter.py
+++ /dev/null
@@ -1,308 +0,0 @@
-from __future__ import annotations
-
-from copy import copy
-from dataclasses import fields
-from typing import Any, TypeVar, cast
-
-from litestar._openapi.typescript_converter.schema_parsing import (
- normalize_typescript_namespace,
- parse_schema,
-)
-from litestar._openapi.typescript_converter.types import (
- TypeScriptInterface,
- TypeScriptNamespace,
- TypeScriptPrimitive,
- TypeScriptProperty,
- TypeScriptType,
- TypeScriptUnion,
-)
-from litestar.enums import HttpMethod, ParamType
-from litestar.openapi.spec import (
- Components,
- OpenAPI,
- Operation,
- Parameter,
- Reference,
- RequestBody,
- Responses,
- Schema,
-)
-
-__all__ = (
- "convert_openapi_to_typescript",
- "deref_container",
- "get_openapi_type",
- "parse_params",
- "parse_request_body",
- "parse_responses",
- "resolve_ref",
-)
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-T = TypeVar("T")
-
-
-def _deref_schema_object(value: BaseSchemaObject, components: Components) -> BaseSchemaObject:
- for field in fields(value):
- if field_value := getattr(value, field.name, None):
- if isinstance(field_value, Reference):
- setattr(
- value,
- field.name,
- deref_container(resolve_ref(field_value, components=components), components=components),
- )
- elif isinstance(field_value, (Schema, dict, list)):
- setattr(value, field.name, deref_container(field_value, components=components))
- return value
-
-
-def _deref_dict(value: dict[str, Any], components: Components) -> dict[str, Any]:
- for k, v in value.items():
- if isinstance(v, Reference):
- value[k] = deref_container(resolve_ref(v, components=components), components=components)
- elif isinstance(v, (Schema, dict, list)):
- value[k] = deref_container(v, components=components)
- return value
-
-
-def _deref_list(values: list[Any], components: Components) -> list[Any]:
- for i, value in enumerate(values):
- if isinstance(value, Reference):
- values[i] = deref_container(resolve_ref(value, components=components), components=components)
- elif isinstance(value, (Schema, (dict, list))):
- values[i] = deref_container(value, components=components)
- return values
-
-
-def deref_container(open_api_container: T, components: Components) -> T:
- """Dereference an object that may contain Reference instances.
-
- Args:
- open_api_container: Either an OpenAPI content, a dict or a list.
- components: The OpenAPI schema Components section.
-
- Returns:
- A dereferenced object.
- """
- if isinstance(open_api_container, BaseSchemaObject):
- return cast("T", _deref_schema_object(open_api_container, components))
-
- if isinstance(open_api_container, dict):
- return cast("T", _deref_dict(copy(open_api_container), components))
-
- if isinstance(open_api_container, list):
- return cast("T", _deref_list(copy(open_api_container), components))
- raise ValueError(f"unexpected container type {type(open_api_container).__name__}") # pragma: no cover
-
-
-def resolve_ref(ref: Reference, components: Components) -> Schema:
- """Resolve a reference object into the actual value it points at.
-
- Args:
- ref: A Reference instance.
- components: The OpenAPI schema Components section.
-
- Returns:
- An OpenAPI schema instance.
- """
- current: Any = components
- for path in [p for p in ref.ref.split("/") if p not in {"#", "components"}]:
- current = current[path] if isinstance(current, dict) else getattr(current, path, None)
-
- if not isinstance(current, Schema): # pragma: no cover
- raise ValueError(
- f"unexpected value type, expected schema but received {type(current).__name__ if current is not None else 'None'}"
- )
-
- return current
-
-
-def get_openapi_type(value: Reference | T, components: Components) -> T:
- """Extract or dereference an OpenAPI container type.
-
- Args:
- value: Either a reference or a container type.
- components: The OpenAPI schema Components section.
-
- Returns:
- The extracted container.
- """
- if isinstance(value, Reference):
- resolved_ref = resolve_ref(value, components=components)
- return cast("T", deref_container(open_api_container=resolved_ref, components=components))
-
- return deref_container(open_api_container=value, components=components)
-
-
-def parse_params(
- params: list[Parameter],
- components: Components,
-) -> tuple[TypeScriptInterface, ...]:
- """Parse request parameters.
-
- Args:
- params: An OpenAPI Operation parameters.
- components: The OpenAPI schema Components section.
-
- Returns:
- A tuple of resolved interfaces.
- """
- cookie_params: list[TypeScriptProperty] = []
- header_params: list[TypeScriptProperty] = []
- path_params: list[TypeScriptProperty] = []
- query_params: list[TypeScriptProperty] = []
-
- for param in params:
- if param.schema:
- schema = get_openapi_type(param.schema, components)
- ts_prop = TypeScriptProperty(
- key=normalize_typescript_namespace(param.name, allow_quoted=True),
- required=param.required,
- value=parse_schema(schema),
- )
- if param.param_in == ParamType.COOKIE:
- cookie_params.append(ts_prop)
- elif param.param_in == ParamType.HEADER:
- header_params.append(ts_prop)
- elif param.param_in == ParamType.PATH:
- path_params.append(ts_prop)
- else:
- query_params.append(ts_prop)
-
- result: list[TypeScriptInterface] = []
-
- if cookie_params:
- result.append(TypeScriptInterface("CookieParameters", tuple(cookie_params)))
- if header_params:
- result.append(TypeScriptInterface("HeaderParameters", tuple(header_params)))
- if path_params:
- result.append(TypeScriptInterface("PathParameters", tuple(path_params)))
- if query_params:
- result.append(TypeScriptInterface("QueryParameters", tuple(query_params)))
-
- return tuple(result)
-
-
-def parse_request_body(body: RequestBody, components: Components) -> TypeScriptType:
- """Parse the schema request body.
-
- Args:
- body: An OpenAPI RequestBody instance.
- components: The OpenAPI schema Components section.
-
- Returns:
- A TypeScript type.
- """
- undefined = TypeScriptPrimitive("undefined")
- if not body.content:
- return TypeScriptType("RequestBody", undefined)
-
- if content := [get_openapi_type(v.schema, components) for v in body.content.values() if v.schema]:
- schema = content[0]
- return TypeScriptType(
- "RequestBody",
- parse_schema(schema) if body.required else TypeScriptUnion((parse_schema(schema), undefined)),
- )
-
- return TypeScriptType("RequestBody", undefined)
-
-
-def parse_responses(responses: Responses, components: Components) -> tuple[TypeScriptNamespace, ...]:
- """Parse a given Operation's Responses object.
-
- Args:
- responses: An OpenAPI Responses object.
- components: The OpenAPI schema Components section.
-
- Returns:
- A tuple of namespaces, mapping response codes to data.
- """
- result: list[TypeScriptNamespace] = []
- for http_status, response in [
- (status, get_openapi_type(res, components=components)) for status, res in responses.items()
- ]:
- if response.content and (
- content := [get_openapi_type(v.schema, components) for v in response.content.values() if v.schema]
- ):
- ts_type = parse_schema(content[0])
- else:
- ts_type = TypeScriptPrimitive("undefined")
-
- containers = [
- TypeScriptType("ResponseBody", ts_type),
- TypeScriptInterface(
- "ResponseHeaders",
- tuple(
- TypeScriptProperty(
- required=get_openapi_type(header, components=components).required,
- key=normalize_typescript_namespace(key, allow_quoted=True),
- value=TypeScriptPrimitive("string"),
- )
- for key, header in response.headers.items()
- ),
- )
- if response.headers
- else None,
- ]
-
- result.append(TypeScriptNamespace(f"Http{http_status}", tuple(c for c in containers if c)))
-
- return tuple(result)
-
-
-def convert_openapi_to_typescript(openapi_schema: OpenAPI, namespace: str = "API") -> TypeScriptNamespace:
- """Convert an OpenAPI Schema instance to a TypeScript namespace. This function is the main entry point for the
- TypeScript converter.
-
- Args:
- openapi_schema: An OpenAPI Schema instance.
- namespace: The namespace to use.
-
- Returns:
- A string representing the generated types.
- """
- if not openapi_schema.paths: # pragma: no cover
- raise ValueError("OpenAPI schema has no paths")
- if not openapi_schema.components: # pragma: no cover
- raise ValueError("OpenAPI schema has no components")
-
- operations: list[TypeScriptNamespace] = []
-
- for path_item in openapi_schema.paths.values():
- shared_params = [
- get_openapi_type(p, components=openapi_schema.components) for p in (path_item.parameters or [])
- ]
- for method in HttpMethod:
- if (
- operation := cast("Operation | None", getattr(path_item, method.lower(), "None"))
- ) and operation.operation_id:
- params = parse_params(
- [
- *(
- get_openapi_type(p, components=openapi_schema.components)
- for p in (operation.parameters or [])
- ),
- *shared_params,
- ],
- components=openapi_schema.components,
- )
- request_body = (
- parse_request_body(
- get_openapi_type(operation.request_body, components=openapi_schema.components),
- components=openapi_schema.components,
- )
- if operation.request_body
- else None
- )
-
- responses = parse_responses(operation.responses or {}, components=openapi_schema.components)
-
- operations.append(
- TypeScriptNamespace(
- normalize_typescript_namespace(operation.operation_id, allow_quoted=False),
- tuple(container for container in (*params, request_body, *responses) if container),
- )
- )
-
- return TypeScriptNamespace(namespace, tuple(operations))
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/schema_parsing.py b/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/schema_parsing.py
deleted file mode 100644
index c5cbbd0..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/schema_parsing.py
+++ /dev/null
@@ -1,150 +0,0 @@
-from __future__ import annotations
-
-import re
-from typing import TYPE_CHECKING, Any, Literal, overload
-
-from litestar._openapi.typescript_converter.types import (
- TypeScriptAnonymousInterface,
- TypeScriptArray,
- TypeScriptElement,
- TypeScriptInterface,
- TypeScriptIntersection,
- TypeScriptLiteral,
- TypeScriptPrimitive,
- TypeScriptProperty,
- TypeScriptUnion,
-)
-from litestar.openapi.spec import Schema
-from litestar.openapi.spec.enums import OpenAPIType
-
-__all__ = ("create_interface", "is_schema_value", "normalize_typescript_namespace", "parse_schema", "parse_type_schema")
-
-if TYPE_CHECKING:
- from typing_extensions import TypeGuard
-
-openapi_typescript_equivalent_types = Literal[
- "string", "boolean", "number", "null", "Record<string, unknown>", "unknown[]"
-]
-
-openapi_to_typescript_type_map: dict[OpenAPIType, openapi_typescript_equivalent_types] = {
- OpenAPIType.ARRAY: "unknown[]",
- OpenAPIType.BOOLEAN: "boolean",
- OpenAPIType.INTEGER: "number",
- OpenAPIType.NULL: "null",
- OpenAPIType.NUMBER: "number",
- OpenAPIType.OBJECT: "Record<string, unknown>",
- OpenAPIType.STRING: "string",
-}
-
-invalid_namespace_re = re.compile(r"[^\w+_$]*")
-allowed_key_re = re.compile(r"[\w+_$]*")
-
-
-def normalize_typescript_namespace(value: str, allow_quoted: bool) -> str:
- """Normalize a namespace, e.g. variable name, or object key, to values supported by TS.
-
- Args:
- value: A string to normalize.
- allow_quoted: Whether to allow quoting the value.
-
- Returns:
- A normalized value
- """
- if not allow_quoted and not value[0].isalpha() and value[0] not in {"_", "$"}:
- raise ValueError(f"invalid typescript namespace {value}")
- if allow_quoted:
- return value if allowed_key_re.fullmatch(value) else f'"{value}"'
- return invalid_namespace_re.sub("", value)
-
-
-def is_schema_value(value: Any) -> TypeGuard[Schema]:
- """Typeguard for a schema value.
-
- Args:
- value: An arbitrary value
-
- Returns:
- A typeguard boolean dictating whether the passed in value is a Schema.
- """
- return isinstance(value, Schema)
-
-
-@overload
-def create_interface(properties: dict[str, Schema], required: set[str] | None) -> TypeScriptAnonymousInterface: ...
-
-
-@overload
-def create_interface(properties: dict[str, Schema], required: set[str] | None, name: str) -> TypeScriptInterface: ...
-
-
-def create_interface(
- properties: dict[str, Schema], required: set[str] | None = None, name: str | None = None
-) -> TypeScriptAnonymousInterface | TypeScriptInterface:
- """Create a typescript interface from the given schema.properties values.
-
- Args:
- properties: schema.properties mapping.
- required: An optional list of required properties.
- name: An optional string representing the interface name.
-
- Returns:
- A typescript interface or anonymous interface.
- """
- parsed_properties = tuple(
- TypeScriptProperty(
- key=normalize_typescript_namespace(key, allow_quoted=True),
- value=parse_schema(schema),
- required=key in required if required is not None else True,
- )
- for key, schema in properties.items()
- )
- return (
- TypeScriptInterface(name=name, properties=parsed_properties)
- if name is not None
- else TypeScriptAnonymousInterface(properties=parsed_properties)
- )
-
-
-def parse_type_schema(schema: Schema) -> TypeScriptPrimitive | TypeScriptLiteral | TypeScriptUnion:
- """Parse an OpenAPI schema representing a primitive type(s).
-
- Args:
- schema: An OpenAPI schema.
-
- Returns:
- A typescript type.
- """
- if schema.enum:
- return TypeScriptUnion(types=tuple(TypeScriptLiteral(value=value) for value in schema.enum))
- if schema.const:
- return TypeScriptLiteral(value=schema.const)
- if isinstance(schema.type, list):
- return TypeScriptUnion(
- tuple(TypeScriptPrimitive(openapi_to_typescript_type_map[s_type]) for s_type in schema.type)
- )
- if schema.type in openapi_to_typescript_type_map and isinstance(schema.type, OpenAPIType):
- return TypeScriptPrimitive(openapi_to_typescript_type_map[schema.type])
- raise TypeError(f"received an unexpected openapi type: {schema.type}") # pragma: no cover
-
-
-def parse_schema(schema: Schema) -> TypeScriptElement:
- """Parse an OpenAPI schema object recursively to create typescript types.
-
- Args:
- schema: An OpenAPI Schema object.
-
- Returns:
- A typescript type.
- """
- if schema.all_of:
- return TypeScriptIntersection(tuple(parse_schema(s) for s in schema.all_of if is_schema_value(s)))
- if schema.one_of:
- return TypeScriptUnion(tuple(parse_schema(s) for s in schema.one_of if is_schema_value(s)))
- if is_schema_value(schema.items):
- return TypeScriptArray(parse_schema(schema.items))
- if schema.type == OpenAPIType.OBJECT:
- return create_interface(
- properties={k: v for k, v in schema.properties.items() if is_schema_value(v)} if schema.properties else {},
- required=set(schema.required) if schema.required else None,
- )
- return parse_type_schema(schema=schema)
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/types.py b/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/types.py
deleted file mode 100644
index ff265d4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/typescript_converter/types.py
+++ /dev/null
@@ -1,308 +0,0 @@
-from __future__ import annotations
-
-from abc import ABC, abstractmethod
-from dataclasses import dataclass
-from typing import Any, Literal
-
-__all__ = (
- "TypeScriptAnonymousInterface",
- "TypeScriptArray",
- "TypeScriptConst",
- "TypeScriptContainer",
- "TypeScriptElement",
- "TypeScriptEnum",
- "TypeScriptInterface",
- "TypeScriptIntersection",
- "TypeScriptLiteral",
- "TypeScriptNamespace",
- "TypeScriptPrimitive",
- "TypeScriptProperty",
- "TypeScriptType",
- "TypeScriptUnion",
-)
-
-
-def _as_string(value: Any) -> str:
- if isinstance(value, str):
- return f'"{value}"'
-
- if isinstance(value, bool):
- return "true" if value else "false"
-
- return "null" if value is None else str(value)
-
-
-class TypeScriptElement(ABC):
- """A class representing a TypeScript type element."""
-
- @abstractmethod
- def write(self) -> str:
- """Write a typescript value corresponding to the given typescript element.
-
- Returns:
- A typescript string
- """
- raise NotImplementedError("")
-
-
-class TypeScriptContainer(TypeScriptElement):
- """A class representing a TypeScript type container."""
-
- name: str
-
- @abstractmethod
- def write(self) -> str:
- """Write a typescript value corresponding to the given typescript container.
-
- Returns:
- A typescript string
- """
- raise NotImplementedError("")
-
-
-@dataclass(unsafe_hash=True)
-class TypeScriptIntersection(TypeScriptElement):
- """A class representing a TypeScript intersection type."""
-
- types: tuple[TypeScriptElement, ...]
-
- def write(self) -> str:
- """Write a typescript intersection value.
-
- Example:
- { prop: string } & { another: number }
-
- Returns:
- A typescript string
- """
- return " & ".join(t.write() for t in self.types)
-
-
-@dataclass(unsafe_hash=True)
-class TypeScriptUnion(TypeScriptElement):
- """A class representing a TypeScript union type."""
-
- types: tuple[TypeScriptElement, ...]
-
- def write(self) -> str:
- """Write a typescript union value.
-
- Example:
- string | number
-
- Returns:
- A typescript string
- """
- return " | ".join(sorted(t.write() for t in self.types))
-
-
-@dataclass(unsafe_hash=True)
-class TypeScriptPrimitive(TypeScriptElement):
- """A class representing a TypeScript primitive type."""
-
- type: Literal[
- "string", "number", "boolean", "any", "null", "undefined", "symbol", "Record<string, unknown>", "unknown[]"
- ]
-
- def write(self) -> str:
- """Write a typescript primitive type.
-
- Example:
- null
-
- Returns:
- A typescript string
- """
- return self.type
-
-
-@dataclass(unsafe_hash=True)
-class TypeScriptLiteral(TypeScriptElement):
- """A class representing a TypeScript literal type."""
-
- value: str | int | float | bool | None
-
- def write(self) -> str:
- """Write a typescript literal type.
-
- Example:
- "someValue"
-
- Returns:
- A typescript string
- """
- return _as_string(self.value)
-
-
-@dataclass(unsafe_hash=True)
-class TypeScriptArray(TypeScriptElement):
- """A class representing a TypeScript array type."""
-
- item_type: TypeScriptElement
-
- def write(self) -> str:
- """Write a typescript array type.
-
- Example:
- number[]
-
- Returns:
- A typescript string
- """
- value = (
- f"({self.item_type.write()})"
- if isinstance(self.item_type, (TypeScriptUnion, TypeScriptIntersection))
- else self.item_type.write()
- )
- return f"{value}[]"
-
-
-@dataclass(unsafe_hash=True)
-class TypeScriptProperty(TypeScriptElement):
- """A class representing a TypeScript interface property."""
-
- required: bool
- key: str
- value: TypeScriptElement
-
- def write(self) -> str:
- """Write a typescript property. This class is used exclusively inside interfaces.
-
- Example:
- key: string;
- optional?: number;
-
- Returns:
- A typescript string
- """
- return f"{self.key}{':' if self.required else '?:'} {self.value.write()};"
-
-
-@dataclass(unsafe_hash=True)
-class TypeScriptAnonymousInterface(TypeScriptElement):
- """A class representing a TypeScript anonymous interface."""
-
- properties: tuple[TypeScriptProperty, ...]
-
- def write(self) -> str:
- """Write a typescript interface object, without a name.
-
- Example:
- {
- key: string;
- optional?: number;
- }
-
- Returns:
- A typescript string
- """
- props = "\t" + "\n\t".join([prop.write() for prop in sorted(self.properties, key=lambda prop: prop.key)])
- return f"{{\n{props}\n}}"
-
-
-@dataclass(unsafe_hash=True)
-class TypeScriptInterface(TypeScriptContainer):
- """A class representing a TypeScript interface."""
-
- name: str
- properties: tuple[TypeScriptProperty, ...]
-
- def write(self) -> str:
- """Write a typescript interface.
-
- Example:
- export interface MyInterface {
- key: string;
- optional?: number;
- };
-
- Returns:
- A typescript string
- """
- interface = TypeScriptAnonymousInterface(properties=self.properties)
- return f"export interface {self.name} {interface.write()};"
-
-
-@dataclass(unsafe_hash=True)
-class TypeScriptEnum(TypeScriptContainer):
- """A class representing a TypeScript enum."""
-
- name: str
- values: tuple[tuple[str, str], ...] | tuple[tuple[str, int | float], ...]
-
- def write(self) -> str:
- """Write a typescript enum.
-
- Example:
- export enum MyEnum {
- DOG = "canine",
- CAT = "feline",
- };
-
- Returns:
- A typescript string
- """
- members = "\t" + "\n\t".join(
- [f"{key} = {_as_string(value)}," for key, value in sorted(self.values, key=lambda member: member[0])]
- )
- return f"export enum {self.name} {{\n{members}\n}};"
-
-
-@dataclass(unsafe_hash=True)
-class TypeScriptType(TypeScriptContainer):
- """A class representing a TypeScript type."""
-
- name: str
- value: TypeScriptElement
-
- def write(self) -> str:
- """Write a typescript type.
-
- Example:
- export type MyType = number | "42";
-
- Returns:
- A typescript string
- """
- return f"export type {self.name} = {self.value.write()};"
-
-
-@dataclass(unsafe_hash=True)
-class TypeScriptConst(TypeScriptContainer):
- """A class representing a TypeScript const."""
-
- name: str
- value: TypeScriptPrimitive | TypeScriptLiteral
-
- def write(self) -> str:
- """Write a typescript const.
-
- Example:
- export const MyConst: number;
-
- Returns:
- A typescript string
- """
- return f"export const {self.name}: {self.value.write()};"
-
-
-@dataclass(unsafe_hash=True)
-class TypeScriptNamespace(TypeScriptContainer):
- """A class representing a TypeScript namespace."""
-
- name: str
- values: tuple[TypeScriptContainer, ...]
-
- def write(self) -> str:
- """Write a typescript namespace.
-
- Example:
- export MyNamespace {
- export const MyConst: number;
- }
-
- Returns:
- A typescript string
- """
- members = "\t" + "\n\n\t".join([value.write() for value in sorted(self.values, key=lambda el: el.name)])
- return f"export namespace {self.name} {{\n{members}\n}};"
diff --git a/venv/lib/python3.11/site-packages/litestar/_openapi/utils.py b/venv/lib/python3.11/site-packages/litestar/_openapi/utils.py
deleted file mode 100644
index b1950fa..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_openapi/utils.py
+++ /dev/null
@@ -1,46 +0,0 @@
-from __future__ import annotations
-
-import re
-from typing import TYPE_CHECKING
-
-from litestar.types.internal_types import PathParameterDefinition
-
-if TYPE_CHECKING:
- from litestar.handlers.http_handlers import HTTPRouteHandler
- from litestar.types import Method
-
-
-__all__ = ("default_operation_id_creator", "SEPARATORS_CLEANUP_PATTERN")
-
-SEPARATORS_CLEANUP_PATTERN = re.compile(r"[!#$%&'*+\-.^_`|~:]+")
-
-
-def default_operation_id_creator(
- route_handler: HTTPRouteHandler,
- http_method: Method,
- path_components: list[str | PathParameterDefinition],
-) -> str:
- """Create a unique 'operationId' for an OpenAPI PathItem entry.
-
- Args:
- route_handler: The HTTP Route Handler instance.
- http_method: The HTTP method for the given PathItem.
- path_components: A list of path components.
-
- Returns:
- A camelCased operationId created from the handler function name,
- http method and path components.
- """
-
- handler_namespace = (
- http_method.title() + route_handler.handler_name.title()
- if len(route_handler.http_methods) > 1
- else route_handler.handler_name.title()
- )
-
- components_namespace = ""
- for component in (c.name if isinstance(c, PathParameterDefinition) else c for c in path_components):
- if component.title() not in components_namespace:
- components_namespace += component.title()
-
- return SEPARATORS_CLEANUP_PATTERN.sub("", components_namespace + handler_namespace)
diff --git a/venv/lib/python3.11/site-packages/litestar/_parsers.py b/venv/lib/python3.11/site-packages/litestar/_parsers.py
deleted file mode 100644
index 9b9f459..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_parsers.py
+++ /dev/null
@@ -1,67 +0,0 @@
-from __future__ import annotations
-
-from collections import defaultdict
-from functools import lru_cache
-from http.cookies import _unquote as unquote_cookie
-from urllib.parse import unquote
-
-try:
- from fast_query_parsers import parse_query_string as parse_qsl
-except ImportError:
- from urllib.parse import parse_qsl as _parse_qsl
-
- def parse_qsl(qs: bytes, separator: str) -> list[tuple[str, str]]:
- return _parse_qsl(qs.decode("latin-1"), keep_blank_values=True, separator=separator)
-
-
-__all__ = ("parse_cookie_string", "parse_query_string", "parse_url_encoded_form_data")
-
-
-@lru_cache(1024)
-def parse_url_encoded_form_data(encoded_data: bytes) -> dict[str, str | list[str]]:
- """Parse an url encoded form data dict.
-
- Args:
- encoded_data: The encoded byte string.
-
- Returns:
- A parsed dict.
- """
- decoded_dict: defaultdict[str, list[str]] = defaultdict(list)
- for k, v in parse_qsl(encoded_data, separator="&"):
- decoded_dict[k].append(v)
- return {k: v if len(v) > 1 else v[0] for k, v in decoded_dict.items()}
-
-
-@lru_cache(1024)
-def parse_query_string(query_string: bytes) -> tuple[tuple[str, str], ...]:
- """Parse a query string into a tuple of key value pairs.
-
- Args:
- query_string: A query string.
-
- Returns:
- A tuple of key value pairs.
- """
- return tuple(parse_qsl(query_string, separator="&"))
-
-
-@lru_cache(1024)
-def parse_cookie_string(cookie_string: str) -> dict[str, str]:
- """Parse a cookie string into a dictionary of values.
-
- Args:
- cookie_string: A cookie string.
-
- Returns:
- A string keyed dictionary of values
- """
- cookies = [cookie.split("=", 1) if "=" in cookie else ("", cookie) for cookie in cookie_string.split(";")]
- output: dict[str, str] = {
- k: unquote(unquote_cookie(v))
- for k, v in filter(
- lambda x: x[0] or x[1],
- ((k.strip(), v.strip()) for k, v in cookies),
- )
- }
- return output
diff --git a/venv/lib/python3.11/site-packages/litestar/_signature/__init__.py b/venv/lib/python3.11/site-packages/litestar/_signature/__init__.py
deleted file mode 100644
index 418e3b5..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_signature/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from .model import SignatureModel
-
-__all__ = ("SignatureModel",)
diff --git a/venv/lib/python3.11/site-packages/litestar/_signature/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_signature/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 8282668..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_signature/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_signature/__pycache__/model.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_signature/__pycache__/model.cpython-311.pyc
deleted file mode 100644
index 9b8fbb7..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_signature/__pycache__/model.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_signature/__pycache__/types.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_signature/__pycache__/types.cpython-311.pyc
deleted file mode 100644
index 5abb937..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_signature/__pycache__/types.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_signature/__pycache__/utils.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/_signature/__pycache__/utils.cpython-311.pyc
deleted file mode 100644
index b8fcafb..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_signature/__pycache__/utils.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/_signature/model.py b/venv/lib/python3.11/site-packages/litestar/_signature/model.py
deleted file mode 100644
index 42c7994..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_signature/model.py
+++ /dev/null
@@ -1,316 +0,0 @@
-# ruff: noqa: UP006, UP007
-from __future__ import annotations
-
-import re
-from functools import partial
-from pathlib import Path, PurePath
-from typing import (
- TYPE_CHECKING,
- Any,
- Callable,
- ClassVar,
- Dict,
- Literal,
- Optional,
- Sequence,
- Set,
- Type,
- TypedDict,
- Union,
- cast,
-)
-from uuid import UUID
-
-from msgspec import NODEFAULT, Meta, Struct, ValidationError, convert, defstruct
-from msgspec.structs import asdict
-from typing_extensions import Annotated
-
-from litestar._signature.types import ExtendedMsgSpecValidationError
-from litestar._signature.utils import (
- _get_decoder_for_type,
- _normalize_annotation,
- _validate_signature_dependencies,
-)
-from litestar.datastructures.state import ImmutableState
-from litestar.datastructures.url import URL
-from litestar.dto import AbstractDTO, DTOData
-from litestar.enums import ParamType, ScopeType
-from litestar.exceptions import InternalServerException, ValidationException
-from litestar.params import KwargDefinition, ParameterKwarg
-from litestar.typing import FieldDefinition # noqa
-from litestar.utils import is_class_and_subclass
-from litestar.utils.dataclass import simple_asdict
-
-if TYPE_CHECKING:
- from typing_extensions import NotRequired
-
- from litestar.connection import ASGIConnection
- from litestar.types import AnyCallable, TypeDecodersSequence
- from litestar.utils.signature import ParsedSignature
-
-__all__ = (
- "ErrorMessage",
- "SignatureModel",
-)
-
-
-class ErrorMessage(TypedDict):
- # key may not be set in some cases, like when a query param is set but
- # doesn't match the required length during `attrs` validation
- # in this case, we don't show a key at all as it will be empty
- key: NotRequired[str]
- message: str
- source: NotRequired[Literal["body"] | ParamType]
-
-
-MSGSPEC_CONSTRAINT_FIELDS = (
- "gt",
- "ge",
- "lt",
- "le",
- "multiple_of",
- "pattern",
- "min_length",
- "max_length",
-)
-
-ERR_RE = re.compile(r"`\$\.(.+)`$")
-
-DEFAULT_TYPE_DECODERS = [
- (lambda x: is_class_and_subclass(x, (Path, PurePath, ImmutableState, UUID)), lambda t, v: t(v)),
-]
-
-
-def _deserializer(target_type: Any, value: Any, default_deserializer: Callable[[Any, Any], Any]) -> Any:
- if isinstance(value, DTOData):
- return value
-
- if isinstance(value, target_type):
- return value
-
- if decoder := getattr(target_type, "_decoder", None):
- return decoder(target_type, value)
-
- return default_deserializer(target_type, value)
-
-
-class SignatureModel(Struct):
- """Model that represents a function signature that uses a msgspec specific type or types."""
-
- _data_dto: ClassVar[Optional[Type[AbstractDTO]]]
- _dependency_name_set: ClassVar[Set[str]]
- _fields: ClassVar[Dict[str, FieldDefinition]]
- _return_annotation: ClassVar[Any]
-
- @classmethod
- def _create_exception(cls, connection: ASGIConnection, messages: list[ErrorMessage]) -> Exception:
- """Create an exception class - either a ValidationException or an InternalServerException, depending on whether
- the failure is in client provided values or injected dependencies.
-
- Args:
- connection: An ASGI connection instance.
- messages: A list of error messages.
-
- Returns:
- An Exception
- """
- method = connection.method if hasattr(connection, "method") else ScopeType.WEBSOCKET # pyright: ignore
- if client_errors := [
- err_message
- for err_message in messages
- if ("key" in err_message and err_message["key"] not in cls._dependency_name_set) or "key" not in err_message
- ]:
- path = URL.from_components(
- path=connection.url.path,
- query=connection.url.query,
- )
- return ValidationException(detail=f"Validation failed for {method} {path}", extra=client_errors)
- return InternalServerException()
-
- @classmethod
- def _build_error_message(cls, keys: Sequence[str], exc_msg: str, connection: ASGIConnection) -> ErrorMessage:
- """Build an error message.
-
- Args:
- keys: A list of keys.
- exc_msg: A message.
- connection: An ASGI connection instance.
-
- Returns:
- An ErrorMessage
- """
-
- message: ErrorMessage = {"message": exc_msg.split(" - ")[0]}
-
- if keys:
- message["key"] = key = ".".join(keys)
- if keys[0].startswith("data"):
- message["key"] = message["key"].replace("data.", "")
- message["source"] = "body"
- elif key in connection.query_params:
- message["source"] = ParamType.QUERY
-
- elif key in cls._fields and isinstance(cls._fields[key].kwarg_definition, ParameterKwarg):
- if cast(ParameterKwarg, cls._fields[key].kwarg_definition).cookie:
- message["source"] = ParamType.COOKIE
- elif cast(ParameterKwarg, cls._fields[key].kwarg_definition).header:
- message["source"] = ParamType.HEADER
- else:
- message["source"] = ParamType.QUERY
-
- return message
-
- @classmethod
- def _collect_errors(cls, deserializer: Callable[[Any, Any], Any], **kwargs: Any) -> list[tuple[str, Exception]]:
- exceptions: list[tuple[str, Exception]] = []
- for field_name in cls._fields:
- try:
- raw_value = kwargs[field_name]
- annotation = cls.__annotations__[field_name]
- convert(raw_value, type=annotation, strict=False, dec_hook=deserializer, str_keys=True)
- except Exception as e: # noqa: BLE001
- exceptions.append((field_name, e))
-
- return exceptions
-
- @classmethod
- def parse_values_from_connection_kwargs(cls, connection: ASGIConnection, **kwargs: Any) -> dict[str, Any]:
- """Extract values from the connection instance and return a dict of parsed values.
-
- Args:
- connection: The ASGI connection instance.
- **kwargs: A dictionary of kwargs.
-
- Raises:
- ValidationException: If validation failed.
- InternalServerException: If another exception has been raised.
-
- Returns:
- A dictionary of parsed values
- """
- messages: list[ErrorMessage] = []
- deserializer = partial(_deserializer, default_deserializer=connection.route_handler.default_deserializer)
- try:
- return convert(kwargs, cls, strict=False, dec_hook=deserializer, str_keys=True).to_dict()
- except ExtendedMsgSpecValidationError as e:
- for exc in e.errors:
- keys = [str(loc) for loc in exc["loc"]]
- message = cls._build_error_message(keys=keys, exc_msg=exc["msg"], connection=connection)
- messages.append(message)
- raise cls._create_exception(messages=messages, connection=connection) from e
- except ValidationError as e:
- for field_name, exc in cls._collect_errors(deserializer=deserializer, **kwargs): # type: ignore[assignment]
- match = ERR_RE.search(str(exc))
- keys = [field_name, str(match.group(1))] if match else [field_name]
- message = cls._build_error_message(keys=keys, exc_msg=str(exc), connection=connection)
- messages.append(message)
- raise cls._create_exception(messages=messages, connection=connection) from e
-
- def to_dict(self) -> dict[str, Any]:
- """Normalize access to the signature model's dictionary method, because different backends use different methods
- for this.
-
- Returns: A dictionary of string keyed values.
- """
- return asdict(self)
-
- @classmethod
- def create(
- cls,
- dependency_name_set: set[str],
- fn: AnyCallable,
- parsed_signature: ParsedSignature,
- type_decoders: TypeDecodersSequence,
- data_dto: type[AbstractDTO] | None = None,
- ) -> type[SignatureModel]:
- fn_name = (
- fn_name if (fn_name := getattr(fn, "__name__", "anonymous")) and fn_name != "<lambda>" else "anonymous"
- )
-
- dependency_names = _validate_signature_dependencies(
- dependency_name_set=dependency_name_set, fn_name=fn_name, parsed_signature=parsed_signature
- )
-
- struct_fields: list[tuple[str, Any, Any]] = []
-
- for field_definition in parsed_signature.parameters.values():
- meta_data: Meta | None = None
-
- if isinstance(field_definition.kwarg_definition, KwargDefinition):
- meta_kwargs: dict[str, Any] = {"extra": {}}
-
- kwarg_definition = simple_asdict(field_definition.kwarg_definition, exclude_empty=True)
- if min_items := kwarg_definition.pop("min_items", None):
- meta_kwargs["min_length"] = min_items
- if max_items := kwarg_definition.pop("max_items", None):
- meta_kwargs["max_length"] = max_items
-
- for k, v in kwarg_definition.items():
- if hasattr(Meta, k) and v is not None:
- meta_kwargs[k] = v
- else:
- meta_kwargs["extra"][k] = v
-
- meta_data = Meta(**meta_kwargs)
-
- annotation = cls._create_annotation(
- field_definition=field_definition,
- type_decoders=[*(type_decoders or []), *DEFAULT_TYPE_DECODERS],
- meta_data=meta_data,
- data_dto=data_dto,
- )
-
- default = field_definition.default if field_definition.has_default else NODEFAULT
- struct_fields.append((field_definition.name, annotation, default))
-
- return defstruct( # type:ignore[return-value]
- f"{fn_name}_signature_model",
- struct_fields,
- bases=(cls,),
- module=getattr(fn, "__module__", None),
- namespace={
- "_return_annotation": parsed_signature.return_type.annotation,
- "_dependency_name_set": dependency_names,
- "_fields": parsed_signature.parameters,
- "_data_dto": data_dto,
- },
- kw_only=True,
- )
-
- @classmethod
- def _create_annotation(
- cls,
- field_definition: FieldDefinition,
- type_decoders: TypeDecodersSequence,
- meta_data: Meta | None = None,
- data_dto: type[AbstractDTO] | None = None,
- ) -> Any:
- # DTOs have already validated their data, so we can just use Any here
- if field_definition.name == "data" and data_dto:
- return Any
-
- annotation = _normalize_annotation(field_definition=field_definition)
-
- if annotation is Any:
- return annotation
-
- if field_definition.is_union:
- types = [
- cls._create_annotation(
- field_definition=inner_type,
- type_decoders=type_decoders,
- meta_data=meta_data,
- )
- for inner_type in field_definition.inner_types
- if not inner_type.is_none_type
- ]
- return Optional[Union[tuple(types)]] if field_definition.is_optional else Union[tuple(types)] # pyright: ignore
-
- if decoder := _get_decoder_for_type(annotation, type_decoders=type_decoders):
- # FIXME: temporary (hopefully) hack, see: https://github.com/jcrist/msgspec/issues/497
- setattr(annotation, "_decoder", decoder)
-
- if meta_data:
- annotation = Annotated[annotation, meta_data] # pyright: ignore
-
- return annotation
diff --git a/venv/lib/python3.11/site-packages/litestar/_signature/types.py b/venv/lib/python3.11/site-packages/litestar/_signature/types.py
deleted file mode 100644
index ac174cc..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_signature/types.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import annotations
-
-from typing import Any
-
-from msgspec import ValidationError
-
-
-class ExtendedMsgSpecValidationError(ValidationError):
- def __init__(self, errors: list[dict[str, Any]]) -> None:
- self.errors = errors
- super().__init__(errors)
diff --git a/venv/lib/python3.11/site-packages/litestar/_signature/utils.py b/venv/lib/python3.11/site-packages/litestar/_signature/utils.py
deleted file mode 100644
index 8c0d15f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/_signature/utils.py
+++ /dev/null
@@ -1,58 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any, Callable
-
-from litestar.constants import SKIP_VALIDATION_NAMES
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.params import DependencyKwarg
-from litestar.types import Empty, TypeDecodersSequence
-
-if TYPE_CHECKING:
- from litestar.typing import FieldDefinition
- from litestar.utils.signature import ParsedSignature
-
-
-__all__ = ("_validate_signature_dependencies", "_normalize_annotation", "_get_decoder_for_type")
-
-
-def _validate_signature_dependencies(
- dependency_name_set: set[str], fn_name: str, parsed_signature: ParsedSignature
-) -> set[str]:
- """Validate dependencies of ``parsed_signature``.
-
- Args:
- dependency_name_set: A set of dependency names
- fn_name: A callable's name.
- parsed_signature: A parsed signature.
-
- Returns:
- A set of validated dependency names.
- """
- dependency_names: set[str] = set(dependency_name_set)
-
- for parameter in parsed_signature.parameters.values():
- if isinstance(parameter.kwarg_definition, DependencyKwarg) and parameter.name not in dependency_name_set:
- if not parameter.is_optional and parameter.default is Empty:
- raise ImproperlyConfiguredException(
- f"Explicit dependency '{parameter.name}' for '{fn_name}' has no default value, "
- f"or provided dependency."
- )
- dependency_names.add(parameter.name)
- return dependency_names
-
-
-def _normalize_annotation(field_definition: FieldDefinition) -> Any:
- if field_definition.name in SKIP_VALIDATION_NAMES or (
- isinstance(field_definition.kwarg_definition, DependencyKwarg)
- and field_definition.kwarg_definition.skip_validation
- ):
- return Any
-
- return field_definition.annotation
-
-
-def _get_decoder_for_type(target_type: Any, type_decoders: TypeDecodersSequence) -> Callable[[type, Any], Any] | None:
- return next(
- (decoder for predicate, decoder in type_decoders if predicate(target_type)),
- None,
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/app.py b/venv/lib/python3.11/site-packages/litestar/app.py
deleted file mode 100644
index e1bd989..0000000
--- a/venv/lib/python3.11/site-packages/litestar/app.py
+++ /dev/null
@@ -1,880 +0,0 @@
-from __future__ import annotations
-
-import inspect
-import logging
-import os
-from contextlib import (
- AbstractAsyncContextManager,
- AsyncExitStack,
- asynccontextmanager,
- suppress,
-)
-from datetime import date, datetime, time, timedelta
-from functools import partial
-from itertools import chain
-from pathlib import Path
-from typing import TYPE_CHECKING, Any, AsyncGenerator, Callable, Iterable, Mapping, Sequence, TypedDict, cast
-
-from litestar._asgi import ASGIRouter
-from litestar._asgi.utils import get_route_handlers, wrap_in_exception_handler
-from litestar._openapi.plugin import OpenAPIPlugin
-from litestar._openapi.schema_generation import openapi_schema_plugins
-from litestar.config.allowed_hosts import AllowedHostsConfig
-from litestar.config.app import AppConfig
-from litestar.config.response_cache import ResponseCacheConfig
-from litestar.connection import Request, WebSocket
-from litestar.datastructures.state import State
-from litestar.events.emitter import BaseEventEmitterBackend, SimpleEventEmitter
-from litestar.exceptions import (
- MissingDependencyException,
- NoRouteMatchFoundException,
-)
-from litestar.logging.config import LoggingConfig, get_logger_placeholder
-from litestar.middleware.cors import CORSMiddleware
-from litestar.openapi.config import OpenAPIConfig
-from litestar.plugins import (
- CLIPluginProtocol,
- InitPluginProtocol,
- OpenAPISchemaPluginProtocol,
- PluginProtocol,
- PluginRegistry,
- SerializationPluginProtocol,
-)
-from litestar.plugins.base import CLIPlugin
-from litestar.router import Router
-from litestar.routes import ASGIRoute, HTTPRoute, WebSocketRoute
-from litestar.static_files.base import StaticFiles
-from litestar.stores.registry import StoreRegistry
-from litestar.types import Empty, TypeDecodersSequence
-from litestar.types.internal_types import PathParameterDefinition, TemplateConfigType
-from litestar.utils import deprecated, ensure_async_callable, join_paths, unique
-from litestar.utils.dataclass import extract_dataclass_items
-from litestar.utils.predicates import is_async_callable
-from litestar.utils.warnings import warn_pdb_on_exception
-
-if TYPE_CHECKING:
- from typing_extensions import Self
-
- from litestar.config.app import ExperimentalFeatures
- from litestar.config.compression import CompressionConfig
- from litestar.config.cors import CORSConfig
- from litestar.config.csrf import CSRFConfig
- from litestar.datastructures import CacheControlHeader, ETag
- from litestar.dto import AbstractDTO
- from litestar.events.listener import EventListener
- from litestar.logging.config import BaseLoggingConfig
- from litestar.openapi.spec import SecurityRequirement
- from litestar.openapi.spec.open_api import OpenAPI
- from litestar.response import Response
- from litestar.static_files.config import StaticFilesConfig
- from litestar.stores.base import Store
- from litestar.types import (
- AfterExceptionHookHandler,
- AfterRequestHookHandler,
- AfterResponseHookHandler,
- AnyCallable,
- ASGIApp,
- BeforeMessageSendHookHandler,
- BeforeRequestHookHandler,
- ControllerRouterHandler,
- Dependencies,
- EmptyType,
- ExceptionHandlersMap,
- GetLogger,
- Guard,
- LifeSpanReceive,
- LifeSpanScope,
- LifeSpanSend,
- Logger,
- Message,
- Middleware,
- OnAppInitHandler,
- ParametersMap,
- Receive,
- ResponseCookies,
- ResponseHeaders,
- RouteHandlerType,
- Scope,
- Send,
- TypeEncodersMap,
- )
- from litestar.types.callable_types import LifespanHook
-
-
-__all__ = ("HandlerIndex", "Litestar", "DEFAULT_OPENAPI_CONFIG")
-
-DEFAULT_OPENAPI_CONFIG = OpenAPIConfig(title="Litestar API", version="1.0.0")
-"""The default OpenAPI config used if not configuration is explicitly passed to the
-:class:`Litestar <.app.Litestar>` instance constructor.
-"""
-
-
-class HandlerIndex(TypedDict):
- """Map route handler names to a mapping of paths + route handler.
-
- It's returned from the 'get_handler_index_by_name' utility method.
- """
-
- paths: list[str]
- """Full route paths to the route handler."""
- handler: RouteHandlerType
- """Route handler instance."""
- identifier: str
- """Unique identifier of the handler.
-
- Either equal to :attr`__name__ <obj.__name__>` attribute or ``__str__`` value of the handler.
- """
-
-
-class Litestar(Router):
- """The Litestar application.
-
- ``Litestar`` is the root level of the app - it has the base path of ``/`` and all root level Controllers, Routers
- and Route Handlers should be registered on it.
- """
-
- __slots__ = (
- "_lifespan_managers",
- "_server_lifespan_managers",
- "_debug",
- "_openapi_schema",
- "_static_files_config",
- "plugins",
- "after_exception",
- "allowed_hosts",
- "asgi_handler",
- "asgi_router",
- "before_send",
- "compression_config",
- "cors_config",
- "csrf_config",
- "event_emitter",
- "get_logger",
- "include_in_schema",
- "logger",
- "logging_config",
- "multipart_form_part_limit",
- "on_shutdown",
- "on_startup",
- "openapi_config",
- "request_class",
- "response_cache_config",
- "route_map",
- "signature_namespace",
- "state",
- "stores",
- "template_engine",
- "websocket_class",
- "pdb_on_exception",
- "experimental_features",
- )
-
- def __init__(
- self,
- route_handlers: Sequence[ControllerRouterHandler] | None = None,
- *,
- after_exception: Sequence[AfterExceptionHookHandler] | None = None,
- after_request: AfterRequestHookHandler | None = None,
- after_response: AfterResponseHookHandler | None = None,
- allowed_hosts: Sequence[str] | AllowedHostsConfig | None = None,
- before_request: BeforeRequestHookHandler | None = None,
- before_send: Sequence[BeforeMessageSendHookHandler] | None = None,
- cache_control: CacheControlHeader | None = None,
- compression_config: CompressionConfig | None = None,
- cors_config: CORSConfig | None = None,
- csrf_config: CSRFConfig | None = None,
- dto: type[AbstractDTO] | None | EmptyType = Empty,
- debug: bool | None = None,
- dependencies: Dependencies | None = None,
- etag: ETag | None = None,
- event_emitter_backend: type[BaseEventEmitterBackend] = SimpleEventEmitter,
- exception_handlers: ExceptionHandlersMap | None = None,
- guards: Sequence[Guard] | None = None,
- include_in_schema: bool | EmptyType = Empty,
- listeners: Sequence[EventListener] | None = None,
- logging_config: BaseLoggingConfig | EmptyType | None = Empty,
- middleware: Sequence[Middleware] | None = None,
- multipart_form_part_limit: int = 1000,
- on_app_init: Sequence[OnAppInitHandler] | None = None,
- on_shutdown: Sequence[LifespanHook] | None = None,
- on_startup: Sequence[LifespanHook] | None = None,
- openapi_config: OpenAPIConfig | None = DEFAULT_OPENAPI_CONFIG,
- opt: Mapping[str, Any] | None = None,
- parameters: ParametersMap | None = None,
- plugins: Sequence[PluginProtocol] | None = None,
- request_class: type[Request] | None = None,
- response_cache_config: ResponseCacheConfig | None = None,
- response_class: type[Response] | None = None,
- response_cookies: ResponseCookies | None = None,
- response_headers: ResponseHeaders | None = None,
- return_dto: type[AbstractDTO] | None | EmptyType = Empty,
- security: Sequence[SecurityRequirement] | None = None,
- signature_namespace: Mapping[str, Any] | None = None,
- signature_types: Sequence[Any] | None = None,
- state: State | None = None,
- static_files_config: Sequence[StaticFilesConfig] | None = None,
- stores: StoreRegistry | dict[str, Store] | None = None,
- tags: Sequence[str] | None = None,
- template_config: TemplateConfigType | None = None,
- type_decoders: TypeDecodersSequence | None = None,
- type_encoders: TypeEncodersMap | None = None,
- websocket_class: type[WebSocket] | None = None,
- lifespan: Sequence[Callable[[Litestar], AbstractAsyncContextManager] | AbstractAsyncContextManager]
- | None = None,
- pdb_on_exception: bool | None = None,
- experimental_features: Iterable[ExperimentalFeatures] | None = None,
- ) -> None:
- """Initialize a ``Litestar`` application.
-
- Args:
- after_exception: A sequence of :class:`exception hook handlers <.types.AfterExceptionHookHandler>`. This
- hook is called after an exception occurs. In difference to exception handlers, it is not meant to
- return a response - only to process the exception (e.g. log it, send it to Sentry etc.).
- after_request: A sync or async function executed after the route handler function returned and the response
- object has been resolved. Receives the response object.
- after_response: A sync or async function called after the response has been awaited. It receives the
- :class:`Request <.connection.Request>` object and should not return any values.
- allowed_hosts: A sequence of allowed hosts, or an
- :class:`AllowedHostsConfig <.config.allowed_hosts.AllowedHostsConfig>` instance. Enables the builtin
- allowed hosts middleware.
- before_request: A sync or async function called immediately before calling the route handler. Receives the
- :class:`Request <.connection.Request>` instance and any non-``None`` return value is used for the
- response, bypassing the route handler.
- before_send: A sequence of :class:`before send hook handlers <.types.BeforeMessageSendHookHandler>`. Called
- when the ASGI send function is called.
- cache_control: A ``cache-control`` header of type
- :class:`CacheControlHeader <litestar.datastructures.CacheControlHeader>` to add to route handlers of
- this app. Can be overridden by route handlers.
- compression_config: Configures compression behaviour of the application, this enabled a builtin or user
- defined Compression middleware.
- cors_config: If set, configures :class:`CORSMiddleware <.middleware.cors.CORSMiddleware>`.
- csrf_config: If set, configures :class:`CSRFMiddleware <.middleware.csrf.CSRFMiddleware>`.
- debug: If ``True``, app errors rendered as HTML with a stack trace.
- dependencies: A string keyed mapping of dependency :class:`Providers <.di.Provide>`.
- dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and
- validation of request data.
- etag: An ``etag`` header of type :class:`ETag <.datastructures.ETag>` to add to route handlers of this app.
- Can be overridden by route handlers.
- event_emitter_backend: A subclass of
- :class:`BaseEventEmitterBackend <.events.emitter.BaseEventEmitterBackend>`.
- exception_handlers: A mapping of status codes and/or exception types to handler functions.
- guards: A sequence of :class:`Guard <.types.Guard>` callables.
- include_in_schema: A boolean flag dictating whether the route handler should be documented in the OpenAPI schema.
- lifespan: A list of callables returning async context managers, wrapping the lifespan of the ASGI application
- listeners: A sequence of :class:`EventListener <.events.listener.EventListener>`.
- logging_config: A subclass of :class:`BaseLoggingConfig <.logging.config.BaseLoggingConfig>`.
- middleware: A sequence of :class:`Middleware <.types.Middleware>`.
- multipart_form_part_limit: The maximal number of allowed parts in a multipart/formdata request. This limit
- is intended to protect from DoS attacks.
- on_app_init: A sequence of :class:`OnAppInitHandler <.types.OnAppInitHandler>` instances. Handlers receive
- an instance of :class:`AppConfig <.config.app.AppConfig>` that will have been initially populated with
- the parameters passed to :class:`Litestar <litestar.app.Litestar>`, and must return an instance of same.
- If more than one handler is registered they are called in the order they are provided.
- on_shutdown: A sequence of :class:`LifespanHook <.types.LifespanHook>` called during application
- shutdown.
- on_startup: A sequence of :class:`LifespanHook <litestar.types.LifespanHook>` called during
- application startup.
- openapi_config: Defaults to :attr:`DEFAULT_OPENAPI_CONFIG`
- opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or
- wherever you have access to :class:`Request <litestar.connection.request.Request>` or
- :class:`ASGI Scope <.types.Scope>`.
- parameters: A mapping of :class:`Parameter <.params.Parameter>` definitions available to all application
- paths.
- pdb_on_exception: Drop into the PDB when an exception occurs.
- plugins: Sequence of plugins.
- request_class: An optional subclass of :class:`Request <.connection.Request>` to use for http connections.
- response_class: A custom subclass of :class:`Response <.response.Response>` to be used as the app's default
- response.
- response_cookies: A sequence of :class:`Cookie <.datastructures.Cookie>`.
- response_headers: A string keyed mapping of :class:`ResponseHeader <.datastructures.ResponseHeader>`
- response_cache_config: Configures caching behavior of the application.
- return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing
- outbound response data.
- route_handlers: A sequence of route handlers, which can include instances of
- :class:`Router <.router.Router>`, subclasses of :class:`Controller <.controller.Controller>` or any
- callable decorated by the route handler decorators.
- security: A sequence of dicts that will be added to the schema of all route handlers in the application.
- See
- :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>` for details.
- signature_namespace: A mapping of names to types for use in forward reference resolution during signature modeling.
- signature_types: A sequence of types for use in forward reference resolution during signature modeling.
- These types will be added to the signature namespace using their ``__name__`` attribute.
- state: An optional :class:`State <.datastructures.State>` for application state.
- static_files_config: A sequence of :class:`StaticFilesConfig <.static_files.StaticFilesConfig>`
- stores: Central registry of :class:`Store <.stores.base.Store>` that will be available throughout the
- application. If this is a dictionary to it will be passed to a
- :class:`StoreRegistry <.stores.registry.StoreRegistry>`. If it is a
- :class:`StoreRegistry <.stores.registry.StoreRegistry>`, this instance will be used directly.
- tags: A sequence of string tags that will be appended to the schema of all route handlers under the
- application.
- template_config: An instance of :class:`TemplateConfig <.template.TemplateConfig>`
- type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec
- hook for deserialization.
- type_encoders: A mapping of types to callables that transform them into types supported for serialization.
- websocket_class: An optional subclass of :class:`WebSocket <.connection.WebSocket>` to use for websocket
- connections.
- experimental_features: An iterable of experimental features to enable
- """
-
- if logging_config is Empty:
- logging_config = LoggingConfig()
-
- if debug is None:
- debug = os.getenv("LITESTAR_DEBUG", "0") == "1"
-
- if pdb_on_exception is None:
- pdb_on_exception = os.getenv("LITESTAR_PDB", "0") == "1"
-
- config = AppConfig(
- after_exception=list(after_exception or []),
- after_request=after_request,
- after_response=after_response,
- allowed_hosts=allowed_hosts if isinstance(allowed_hosts, AllowedHostsConfig) else list(allowed_hosts or []),
- before_request=before_request,
- before_send=list(before_send or []),
- cache_control=cache_control,
- compression_config=compression_config,
- cors_config=cors_config,
- csrf_config=csrf_config,
- debug=debug,
- dependencies=dict(dependencies or {}),
- dto=dto,
- etag=etag,
- event_emitter_backend=event_emitter_backend,
- exception_handlers=exception_handlers or {},
- guards=list(guards or []),
- include_in_schema=include_in_schema,
- lifespan=list(lifespan or []),
- listeners=list(listeners or []),
- logging_config=logging_config,
- middleware=list(middleware or []),
- multipart_form_part_limit=multipart_form_part_limit,
- on_shutdown=list(on_shutdown or []),
- on_startup=list(on_startup or []),
- openapi_config=openapi_config,
- opt=dict(opt or {}),
- parameters=parameters or {},
- pdb_on_exception=pdb_on_exception,
- plugins=self._get_default_plugins(list(plugins or [])),
- request_class=request_class,
- response_cache_config=response_cache_config or ResponseCacheConfig(),
- response_class=response_class,
- response_cookies=response_cookies or [],
- response_headers=response_headers or [],
- return_dto=return_dto,
- route_handlers=list(route_handlers) if route_handlers is not None else [],
- security=list(security or []),
- signature_namespace=dict(signature_namespace or {}),
- signature_types=list(signature_types or []),
- state=state or State(),
- static_files_config=list(static_files_config or []),
- stores=stores,
- tags=list(tags or []),
- template_config=template_config,
- type_encoders=type_encoders,
- type_decoders=type_decoders,
- websocket_class=websocket_class,
- experimental_features=list(experimental_features or []),
- )
-
- config.plugins.extend([OpenAPIPlugin(self), *openapi_schema_plugins])
-
- for handler in chain(
- on_app_init or [],
- (p.on_app_init for p in config.plugins if isinstance(p, InitPluginProtocol)),
- ):
- config = handler(config) # pyright: ignore
- self.plugins = PluginRegistry(config.plugins)
-
- self._openapi_schema: OpenAPI | None = None
- self._debug: bool = True
- self.stores: StoreRegistry = (
- config.stores if isinstance(config.stores, StoreRegistry) else StoreRegistry(config.stores)
- )
- self._lifespan_managers = config.lifespan
- for store in self.stores._stores.values():
- self._lifespan_managers.append(store)
- self._server_lifespan_managers = [p.server_lifespan for p in config.plugins or [] if isinstance(p, CLIPlugin)]
- self.experimental_features = frozenset(config.experimental_features or [])
- self.get_logger: GetLogger = get_logger_placeholder
- self.logger: Logger | None = None
- self.routes: list[HTTPRoute | ASGIRoute | WebSocketRoute] = []
- self.asgi_router = ASGIRouter(app=self)
-
- self.after_exception = [ensure_async_callable(h) for h in config.after_exception]
- self.allowed_hosts = cast("AllowedHostsConfig | None", config.allowed_hosts)
- self.before_send = [ensure_async_callable(h) for h in config.before_send]
- self.compression_config = config.compression_config
- self.cors_config = config.cors_config
- self.csrf_config = config.csrf_config
- self.event_emitter = config.event_emitter_backend(listeners=config.listeners)
- self.logging_config = config.logging_config
- self.multipart_form_part_limit = config.multipart_form_part_limit
- self.on_shutdown = config.on_shutdown
- self.on_startup = config.on_startup
- self.openapi_config = config.openapi_config
- self.request_class: type[Request] = config.request_class or Request
- self.response_cache_config = config.response_cache_config
- self.state = config.state
- self._static_files_config = config.static_files_config
- self.template_engine = config.template_config.engine_instance if config.template_config else None
- self.websocket_class: type[WebSocket] = config.websocket_class or WebSocket
- self.debug = config.debug
- self.pdb_on_exception: bool = config.pdb_on_exception
- self.include_in_schema = include_in_schema
-
- if self.pdb_on_exception:
- warn_pdb_on_exception()
-
- try:
- from starlette.exceptions import HTTPException as StarletteHTTPException
-
- from litestar.middleware.exceptions.middleware import _starlette_exception_handler
-
- config.exception_handlers.setdefault(StarletteHTTPException, _starlette_exception_handler)
- except ImportError:
- pass
-
- super().__init__(
- after_request=config.after_request,
- after_response=config.after_response,
- before_request=config.before_request,
- cache_control=config.cache_control,
- dependencies=config.dependencies,
- dto=config.dto,
- etag=config.etag,
- exception_handlers=config.exception_handlers,
- guards=config.guards,
- middleware=config.middleware,
- opt=config.opt,
- parameters=config.parameters,
- path="",
- request_class=self.request_class,
- response_class=config.response_class,
- response_cookies=config.response_cookies,
- response_headers=config.response_headers,
- return_dto=config.return_dto,
- # route handlers are registered below
- route_handlers=[],
- security=config.security,
- signature_namespace=config.signature_namespace,
- signature_types=config.signature_types,
- tags=config.tags,
- type_encoders=config.type_encoders,
- type_decoders=config.type_decoders,
- include_in_schema=config.include_in_schema,
- websocket_class=self.websocket_class,
- )
-
- for route_handler in config.route_handlers:
- self.register(route_handler)
-
- if self.logging_config:
- self.get_logger = self.logging_config.configure()
- self.logger = self.get_logger("litestar")
-
- for static_config in self._static_files_config:
- self.register(static_config.to_static_files_app())
-
- self.asgi_handler = self._create_asgi_handler()
-
- @property
- @deprecated(version="2.6.0", kind="property", info="Use create_static_files router instead")
- def static_files_config(self) -> list[StaticFilesConfig]:
- return self._static_files_config
-
- @property
- @deprecated(version="2.0", alternative="Litestar.plugins.cli", kind="property")
- def cli_plugins(self) -> list[CLIPluginProtocol]:
- return list(self.plugins.cli)
-
- @property
- @deprecated(version="2.0", alternative="Litestar.plugins.openapi", kind="property")
- def openapi_schema_plugins(self) -> list[OpenAPISchemaPluginProtocol]:
- return list(self.plugins.openapi)
-
- @property
- @deprecated(version="2.0", alternative="Litestar.plugins.serialization", kind="property")
- def serialization_plugins(self) -> list[SerializationPluginProtocol]:
- return list(self.plugins.serialization)
-
- @staticmethod
- def _get_default_plugins(plugins: list[PluginProtocol]) -> list[PluginProtocol]:
- from litestar.plugins.core import MsgspecDIPlugin
-
- plugins.append(MsgspecDIPlugin())
-
- with suppress(MissingDependencyException):
- from litestar.contrib.pydantic import (
- PydanticDIPlugin,
- PydanticInitPlugin,
- PydanticPlugin,
- PydanticSchemaPlugin,
- )
-
- pydantic_plugin_found = any(isinstance(plugin, PydanticPlugin) for plugin in plugins)
- pydantic_init_plugin_found = any(isinstance(plugin, PydanticInitPlugin) for plugin in plugins)
- pydantic_schema_plugin_found = any(isinstance(plugin, PydanticSchemaPlugin) for plugin in plugins)
- pydantic_serialization_plugin_found = any(isinstance(plugin, PydanticDIPlugin) for plugin in plugins)
- if not pydantic_plugin_found and not pydantic_init_plugin_found and not pydantic_schema_plugin_found:
- plugins.append(PydanticPlugin())
- elif not pydantic_plugin_found and pydantic_init_plugin_found and not pydantic_schema_plugin_found:
- plugins.append(PydanticSchemaPlugin())
- elif not pydantic_plugin_found and not pydantic_init_plugin_found:
- plugins.append(PydanticInitPlugin())
- if not pydantic_plugin_found and not pydantic_serialization_plugin_found:
- plugins.append(PydanticDIPlugin())
- with suppress(MissingDependencyException):
- from litestar.contrib.attrs import AttrsSchemaPlugin
-
- pre_configured = any(isinstance(plugin, AttrsSchemaPlugin) for plugin in plugins)
- if not pre_configured:
- plugins.append(AttrsSchemaPlugin())
- return plugins
-
- @property
- def debug(self) -> bool:
- return self._debug
-
- @debug.setter
- def debug(self, value: bool) -> None:
- """Sets the debug logging level for the application.
-
- When possible, it calls the `self.logging_config.set_level` method. This allows for implementation specific code and APIs to be called.
- """
- if self.logger and self.logging_config:
- self.logging_config.set_level(self.logger, logging.DEBUG if value else logging.INFO)
- elif self.logger and hasattr(self.logger, "setLevel"): # pragma: no cover
- self.logger.setLevel(logging.DEBUG if value else logging.INFO) # pragma: no cover
- if isinstance(self.logging_config, LoggingConfig):
- self.logging_config.loggers["litestar"]["level"] = "DEBUG" if value else "INFO"
- self._debug = value
-
- async def __call__(
- self,
- scope: Scope | LifeSpanScope,
- receive: Receive | LifeSpanReceive,
- send: Send | LifeSpanSend,
- ) -> None:
- """Application entry point.
-
- Lifespan events (startup / shutdown) are sent to the lifespan handler, otherwise the ASGI handler is used
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
- if scope["type"] == "lifespan":
- await self.asgi_router.lifespan(receive=receive, send=send) # type: ignore[arg-type]
- return
-
- scope["app"] = self
- scope.setdefault("state", {})
- await self.asgi_handler(scope, receive, self._wrap_send(send=send, scope=scope)) # type: ignore[arg-type]
-
- async def _call_lifespan_hook(self, hook: LifespanHook) -> None:
- ret = hook(self) if inspect.signature(hook).parameters else hook() # type: ignore[call-arg]
-
- if is_async_callable(hook): # pyright: ignore[reportGeneralTypeIssues]
- await ret
-
- @asynccontextmanager
- async def lifespan(self) -> AsyncGenerator[None, None]:
- """Context manager handling the ASGI lifespan.
-
- It will be entered when the ``lifespan`` message has been received from the
- server, and exit after the ``asgi.shutdown`` message. During this period, it is
- responsible for calling the ``on_startup``, ``on_shutdown`` hooks, as well as
- custom lifespan managers.
- """
- async with AsyncExitStack() as exit_stack:
- for hook in self.on_shutdown[::-1]:
- exit_stack.push_async_callback(partial(self._call_lifespan_hook, hook))
-
- await exit_stack.enter_async_context(self.event_emitter)
-
- for manager in self._lifespan_managers:
- if not isinstance(manager, AbstractAsyncContextManager):
- manager = manager(self)
- await exit_stack.enter_async_context(manager)
-
- for hook in self.on_startup:
- await self._call_lifespan_hook(hook)
-
- yield
-
- @property
- def openapi_schema(self) -> OpenAPI:
- """Access the OpenAPI schema of the application.
-
- Returns:
- The :class:`OpenAPI`
- <pydantic_openapi_schema.open_api.OpenAPI> instance of the
- application.
-
- Raises:
- ImproperlyConfiguredException: If the application ``openapi_config`` attribute is ``None``.
- """
- return self.plugins.get(OpenAPIPlugin).provide_openapi()
-
- @classmethod
- def from_config(cls, config: AppConfig) -> Self:
- """Initialize a ``Litestar`` application from a configuration instance.
-
- Args:
- config: An instance of :class:`AppConfig` <.config.AppConfig>
-
- Returns:
- An instance of ``Litestar`` application.
- """
- return cls(**dict(extract_dataclass_items(config)))
-
- def register(self, value: ControllerRouterHandler) -> None: # type: ignore[override]
- """Register a route handler on the app.
-
- This method can be used to dynamically add endpoints to an application.
-
- Args:
- value: An instance of :class:`Router <.router.Router>`, a subclass of
- :class:`Controller <.controller.Controller>` or any function decorated by the route handler decorators.
-
- Returns:
- None
- """
- routes = super().register(value=value)
-
- for route in routes:
- route_handlers = get_route_handlers(route)
-
- for route_handler in route_handlers:
- route_handler.on_registration(self)
-
- if isinstance(route, HTTPRoute):
- route.create_handler_map()
-
- elif isinstance(route, WebSocketRoute):
- route.handler_parameter_model = route.create_handler_kwargs_model(route.route_handler)
-
- for plugin in self.plugins.receive_route:
- plugin.receive_route(route)
-
- self.asgi_router.construct_routing_trie()
-
- def get_handler_index_by_name(self, name: str) -> HandlerIndex | None:
- """Receives a route handler name and returns an optional dictionary containing the route handler instance and
- list of paths sorted lexically.
-
- Examples:
- .. code-block:: python
-
- from litestar import Litestar, get
-
-
- @get("/", name="my-handler")
- def handler() -> None:
- pass
-
-
- app = Litestar(route_handlers=[handler])
-
- handler_index = app.get_handler_index_by_name("my-handler")
-
- # { "paths": ["/"], "handler" ... }
-
- Args:
- name: A route handler unique name.
-
- Returns:
- A :class:`HandlerIndex <.app.HandlerIndex>` instance or ``None``.
- """
- handler = self.asgi_router.route_handler_index.get(name)
- if not handler:
- return None
-
- identifier = handler.name or str(handler)
- routes = self.asgi_router.route_mapping[identifier]
- paths = sorted(unique([route.path for route in routes]))
-
- return HandlerIndex(handler=handler, paths=paths, identifier=identifier)
-
- def route_reverse(self, name: str, **path_parameters: Any) -> str:
- """Receives a route handler name, path parameter values and returns url path to the handler with filled path
- parameters.
-
- Examples:
- .. code-block:: python
-
- from litestar import Litestar, get
-
-
- @get("/group/{group_id:int}/user/{user_id:int}", name="get_membership_details")
- def get_membership_details(group_id: int, user_id: int) -> None:
- pass
-
-
- app = Litestar(route_handlers=[get_membership_details])
-
- path = app.route_reverse("get_membership_details", user_id=100, group_id=10)
-
- # /group/10/user/100
-
- Args:
- name: A route handler unique name.
- **path_parameters: Actual values for path parameters in the route.
-
- Raises:
- NoRouteMatchFoundException: If route with 'name' does not exist, path parameters are missing in
- ``**path_parameters or have wrong type``.
-
- Returns:
- A fully formatted url path.
- """
- handler_index = self.get_handler_index_by_name(name)
- if handler_index is None:
- raise NoRouteMatchFoundException(f"Route {name} can not be found")
-
- allow_str_instead = {datetime, date, time, timedelta, float, Path}
- routes = sorted(
- self.asgi_router.route_mapping[handler_index["identifier"]],
- key=lambda r: len(r.path_parameters),
- reverse=True,
- )
- passed_parameters = set(path_parameters.keys())
-
- selected_route = next(
- (
- route
- for route in routes
- if passed_parameters.issuperset({param.name for param in route.path_parameters})
- ),
- routes[-1],
- )
- output: list[str] = []
- for component in selected_route.path_components:
- if isinstance(component, PathParameterDefinition):
- val = path_parameters.get(component.name)
- if not isinstance(val, component.type) and (
- component.type not in allow_str_instead or not isinstance(val, str)
- ):
- raise NoRouteMatchFoundException(
- f"Received type for path parameter {component.name} doesn't match declared type {component.type}"
- )
- output.append(str(val))
- else:
- output.append(component)
-
- return join_paths(output)
-
- @deprecated(
- "2.6.0", info="Use create_static_files router instead of StaticFilesConfig, which works with route_reverse"
- )
- def url_for_static_asset(self, name: str, file_path: str) -> str:
- """Receives a static files handler name, an asset file path and returns resolved url path to the asset.
-
- Examples:
- .. code-block:: python
-
- from litestar import Litestar
- from litestar.static_files.config import StaticFilesConfig
-
- app = Litestar(
- static_files_config=[
- StaticFilesConfig(directories=["css"], path="/static/css", name="css")
- ]
- )
-
- path = app.url_for_static_asset("css", "main.css")
-
- # /static/css/main.css
-
- Args:
- name: A static handler unique name.
- file_path: a string containing path to an asset.
-
- Raises:
- NoRouteMatchFoundException: If static files handler with ``name`` does not exist.
-
- Returns:
- A url path to the asset.
- """
-
- handler_index = self.get_handler_index_by_name(name)
- if handler_index is None:
- raise NoRouteMatchFoundException(f"Static handler {name} can not be found")
-
- handler_fn = cast("AnyCallable", handler_index["handler"].fn)
- if not isinstance(handler_fn, StaticFiles):
- raise NoRouteMatchFoundException(f"Handler with name {name} is not a static files handler")
-
- return join_paths([handler_index["paths"][0], file_path]) # type: ignore[unreachable]
-
- @property
- def route_handler_method_view(self) -> dict[str, list[str]]:
- """Map route handlers to paths.
-
- Returns:
- A dictionary of router handlers and lists of paths as strings
- """
- route_map: dict[str, list[str]] = {
- handler: [route.path for route in routes] for handler, routes in self.asgi_router.route_mapping.items()
- }
- return route_map
-
- def _create_asgi_handler(self) -> ASGIApp:
- """Create an ASGIApp that wraps the ASGI router inside an exception handler.
-
- If CORS or TrustedHost configs are provided to the constructor, they will wrap the router as well.
- """
- asgi_handler: ASGIApp = self.asgi_router
- if self.cors_config:
- asgi_handler = CORSMiddleware(app=asgi_handler, config=self.cors_config)
-
- return wrap_in_exception_handler(
- app=asgi_handler,
- exception_handlers=self.exception_handlers or {}, # pyright: ignore
- )
-
- def _wrap_send(self, send: Send, scope: Scope) -> Send:
- """Wrap the ASGI send and handles any 'before send' hooks.
-
- Args:
- send: The ASGI send function.
- scope: The ASGI scope.
-
- Returns:
- An ASGI send function.
- """
- if self.before_send:
-
- async def wrapped_send(message: Message) -> None:
- for hook in self.before_send:
- await hook(message, scope)
- await send(message)
-
- return wrapped_send
- return send
-
- def update_openapi_schema(self) -> None:
- """Update the OpenAPI schema to reflect the route handlers registered on the app.
-
- Returns:
- None
- """
- self.plugins.get(OpenAPIPlugin)._build_openapi_schema()
-
- def emit(self, event_id: str, *args: Any, **kwargs: Any) -> None:
- """Emit an event to all attached listeners.
-
- Args:
- event_id: The ID of the event to emit, e.g ``my_event``.
- args: args to pass to the listener(s).
- kwargs: kwargs to pass to the listener(s)
-
- Returns:
- None
- """
- self.event_emitter.emit(event_id, *args, **kwargs)
diff --git a/venv/lib/python3.11/site-packages/litestar/background_tasks.py b/venv/lib/python3.11/site-packages/litestar/background_tasks.py
deleted file mode 100644
index a475836..0000000
--- a/venv/lib/python3.11/site-packages/litestar/background_tasks.py
+++ /dev/null
@@ -1,74 +0,0 @@
-from typing import Any, Callable, Iterable
-
-from anyio import create_task_group
-from typing_extensions import ParamSpec
-
-from litestar.utils.sync import ensure_async_callable
-
-__all__ = ("BackgroundTask", "BackgroundTasks")
-
-
-P = ParamSpec("P")
-
-
-class BackgroundTask:
- """A container for a 'background' task function.
-
- Background tasks are called once a Response finishes.
- """
-
- __slots__ = ("fn", "args", "kwargs")
-
- def __init__(self, fn: Callable[P, Any], *args: P.args, **kwargs: P.kwargs) -> None:
- """Initialize ``BackgroundTask``.
-
- Args:
- fn: A sync or async function to call as the background task.
- *args: Args to pass to the func.
- **kwargs: Kwargs to pass to the func
- """
- self.fn = ensure_async_callable(fn)
- self.args = args
- self.kwargs = kwargs
-
- async def __call__(self) -> None:
- """Call the wrapped function with the passed in arguments.
-
- Returns:
- None
- """
- await self.fn(*self.args, **self.kwargs)
-
-
-class BackgroundTasks:
- """A container for multiple 'background' task functions.
-
- Background tasks are called once a Response finishes.
- """
-
- __slots__ = ("tasks", "run_in_task_group")
-
- def __init__(self, tasks: Iterable[BackgroundTask], run_in_task_group: bool = False) -> None:
- """Initialize ``BackgroundTasks``.
-
- Args:
- tasks: An iterable of :class:`BackgroundTask <.background_tasks.BackgroundTask>` instances.
- run_in_task_group: If you set this value to ``True`` than the tasks will run concurrently, using
- a :class:`TaskGroup <anyio.abc.TaskGroup>`. Note: This will not preserve execution order.
- """
- self.tasks = tasks
- self.run_in_task_group = run_in_task_group
-
- async def __call__(self) -> None:
- """Call the wrapped background tasks.
-
- Returns:
- None
- """
- if self.run_in_task_group:
- async with create_task_group() as task_group:
- for task in self.tasks:
- task_group.start_soon(task)
- else:
- for task in self.tasks:
- await task()
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/__init__.py b/venv/lib/python3.11/site-packages/litestar/channels/__init__.py
deleted file mode 100644
index 0167223..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from .backends.base import ChannelsBackend
-from .plugin import ChannelsPlugin
-from .subscriber import Subscriber
-
-__all__ = ("ChannelsPlugin", "ChannelsBackend", "Subscriber")
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/channels/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index bf9d6bd..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/__pycache__/plugin.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/channels/__pycache__/plugin.cpython-311.pyc
deleted file mode 100644
index 08361dc..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/__pycache__/plugin.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/__pycache__/subscriber.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/channels/__pycache__/subscriber.cpython-311.pyc
deleted file mode 100644
index 8d609b4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/__pycache__/subscriber.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/backends/__init__.py b/venv/lib/python3.11/site-packages/litestar/channels/backends/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/backends/__init__.py
+++ /dev/null
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index ab4e477..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/asyncpg.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/asyncpg.cpython-311.pyc
deleted file mode 100644
index a577096..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/asyncpg.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/base.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/base.cpython-311.pyc
deleted file mode 100644
index 334d295..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/base.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/memory.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/memory.cpython-311.pyc
deleted file mode 100644
index 9a87da5..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/memory.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/psycopg.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/psycopg.cpython-311.pyc
deleted file mode 100644
index f663280..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/psycopg.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/redis.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/redis.cpython-311.pyc
deleted file mode 100644
index bf86a3e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/backends/__pycache__/redis.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/backends/_redis_flushall_streams.lua b/venv/lib/python3.11/site-packages/litestar/channels/backends/_redis_flushall_streams.lua
deleted file mode 100644
index a3faa6e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/backends/_redis_flushall_streams.lua
+++ /dev/null
@@ -1,15 +0,0 @@
-local key_pattern = ARGV[1]
-
-local cursor = 0
-local deleted_streams = 0
-
-repeat
- local result = redis.call('SCAN', cursor, 'MATCH', key_pattern)
- for _,key in ipairs(result[2]) do
- redis.call('DEL', key)
- deleted_streams = deleted_streams + 1
- end
- cursor = tonumber(result[1])
-until cursor == 0
-
-return deleted_streams
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/backends/_redis_pubsub_publish.lua b/venv/lib/python3.11/site-packages/litestar/channels/backends/_redis_pubsub_publish.lua
deleted file mode 100644
index 8402d08..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/backends/_redis_pubsub_publish.lua
+++ /dev/null
@@ -1,5 +0,0 @@
-local data = ARGV[1]
-
-for _, channel in ipairs(KEYS) do
- redis.call("PUBLISH", channel, data)
-end
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/backends/_redis_xadd_expire.lua b/venv/lib/python3.11/site-packages/litestar/channels/backends/_redis_xadd_expire.lua
deleted file mode 100644
index f6b322f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/backends/_redis_xadd_expire.lua
+++ /dev/null
@@ -1,13 +0,0 @@
-local data = ARGV[1]
-local limit = ARGV[2]
-local exp = ARGV[3]
-local maxlen_approx = ARGV[4]
-
-for i, key in ipairs(KEYS) do
- if maxlen_approx == 1 then
- redis.call("XADD", key, "MAXLEN", "~", limit, "*", "data", data, "channel", ARGV[i + 4])
- else
- redis.call("XADD", key, "MAXLEN", limit, "*", "data", data, "channel", ARGV[i + 4])
- end
- redis.call("PEXPIRE", key, exp)
-end
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/backends/asyncpg.py b/venv/lib/python3.11/site-packages/litestar/channels/backends/asyncpg.py
deleted file mode 100644
index 967b208..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/backends/asyncpg.py
+++ /dev/null
@@ -1,90 +0,0 @@
-from __future__ import annotations
-
-import asyncio
-from contextlib import AsyncExitStack
-from functools import partial
-from typing import AsyncGenerator, Awaitable, Callable, Iterable, overload
-
-import asyncpg
-
-from litestar.channels import ChannelsBackend
-from litestar.exceptions import ImproperlyConfiguredException
-
-
-class AsyncPgChannelsBackend(ChannelsBackend):
- _listener_conn: asyncpg.Connection
-
- @overload
- def __init__(self, dsn: str) -> None: ...
-
- @overload
- def __init__(
- self,
- *,
- make_connection: Callable[[], Awaitable[asyncpg.Connection]],
- ) -> None: ...
-
- def __init__(
- self,
- dsn: str | None = None,
- *,
- make_connection: Callable[[], Awaitable[asyncpg.Connection]] | None = None,
- ) -> None:
- if not (dsn or make_connection):
- raise ImproperlyConfiguredException("Need to specify dsn or make_connection")
-
- self._subscribed_channels: set[str] = set()
- self._exit_stack = AsyncExitStack()
- self._connect = make_connection or partial(asyncpg.connect, dsn=dsn)
- self._queue: asyncio.Queue[tuple[str, bytes]] | None = None
-
- async def on_startup(self) -> None:
- self._queue = asyncio.Queue()
- self._listener_conn = await self._connect()
-
- async def on_shutdown(self) -> None:
- await self._listener_conn.close()
- self._queue = None
-
- async def publish(self, data: bytes, channels: Iterable[str]) -> None:
- if self._queue is None:
- raise RuntimeError("Backend not yet initialized. Did you forget to call on_startup?")
-
- dec_data = data.decode("utf-8")
-
- conn = await self._connect()
- try:
- for channel in channels:
- await conn.execute("SELECT pg_notify($1, $2);", channel, dec_data)
- finally:
- await conn.close()
-
- async def subscribe(self, channels: Iterable[str]) -> None:
- for channel in set(channels) - self._subscribed_channels:
- await self._listener_conn.add_listener(channel, self._listener) # type: ignore[arg-type]
- self._subscribed_channels.add(channel)
-
- async def unsubscribe(self, channels: Iterable[str]) -> None:
- for channel in channels:
- await self._listener_conn.remove_listener(channel, self._listener) # type: ignore[arg-type]
- self._subscribed_channels = self._subscribed_channels - set(channels)
-
- async def stream_events(self) -> AsyncGenerator[tuple[str, bytes], None]:
- if self._queue is None:
- raise RuntimeError("Backend not yet initialized. Did you forget to call on_startup?")
-
- while True:
- channel, message = await self._queue.get()
- self._queue.task_done()
- # an UNLISTEN may be in transit while we're getting here, so we double-check
- # that we are actually supposed to deliver this message
- if channel in self._subscribed_channels:
- yield channel, message
-
- async def get_history(self, channel: str, limit: int | None = None) -> list[bytes]:
- raise NotImplementedError()
-
- def _listener(self, /, connection: asyncpg.Connection, pid: int, channel: str, payload: object) -> None:
- if not isinstance(payload, str):
- raise RuntimeError("Invalid data received")
- self._queue.put_nowait((channel, payload.encode("utf-8"))) # type: ignore[union-attr]
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/backends/base.py b/venv/lib/python3.11/site-packages/litestar/channels/backends/base.py
deleted file mode 100644
index ce7ee81..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/backends/base.py
+++ /dev/null
@@ -1,41 +0,0 @@
-from __future__ import annotations
-
-from abc import ABC, abstractmethod
-from typing import AsyncGenerator, Iterable
-
-
-class ChannelsBackend(ABC):
- @abstractmethod
- async def on_startup(self) -> None:
- """Called by the plugin on application startup"""
- ...
-
- @abstractmethod
- async def on_shutdown(self) -> None:
- """Called by the plugin on application shutdown"""
- ...
-
- @abstractmethod
- async def publish(self, data: bytes, channels: Iterable[str]) -> None:
- """Publish the message ``data`` to all ``channels``"""
- ...
-
- @abstractmethod
- async def subscribe(self, channels: Iterable[str]) -> None:
- """Start listening for events on ``channels``"""
- ...
-
- @abstractmethod
- async def unsubscribe(self, channels: Iterable[str]) -> None:
- """Stop listening for events on ``channels``"""
- ...
-
- @abstractmethod
- def stream_events(self) -> AsyncGenerator[tuple[str, bytes], None]:
- """Return a generator, iterating over events of subscribed channels as they become available"""
- ...
-
- @abstractmethod
- async def get_history(self, channel: str, limit: int | None = None) -> list[bytes]:
- """Return the event history of ``channel``, at most ``limit`` entries"""
- ...
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/backends/memory.py b/venv/lib/python3.11/site-packages/litestar/channels/backends/memory.py
deleted file mode 100644
index a96a66b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/backends/memory.py
+++ /dev/null
@@ -1,84 +0,0 @@
-from __future__ import annotations
-
-from asyncio import Queue
-from collections import defaultdict, deque
-from typing import Any, AsyncGenerator, Iterable
-
-from litestar.channels.backends.base import ChannelsBackend
-
-
-class MemoryChannelsBackend(ChannelsBackend):
- """An in-memory channels backend"""
-
- def __init__(self, history: int = 0) -> None:
- self._max_history_length = history
- self._channels: set[str] = set()
- self._queue: Queue[tuple[str, bytes]] | None = None
- self._history: defaultdict[str, deque[bytes]] = defaultdict(lambda: deque(maxlen=self._max_history_length))
-
- async def on_startup(self) -> None:
- self._queue = Queue()
-
- async def on_shutdown(self) -> None:
- self._queue = None
-
- async def publish(self, data: bytes, channels: Iterable[str]) -> None:
- """Publish ``data`` to ``channels``. If a channel has not yet been subscribed to,
- this will be a no-op.
-
- Args:
- data: Data to publish
- channels: Channels to publish to
-
- Returns:
- None
-
- Raises:
- RuntimeError: If ``on_startup`` has not been called yet
- """
- if not self._queue:
- raise RuntimeError("Backend not yet initialized. Did you forget to call on_startup?")
-
- for channel in channels:
- if channel not in self._channels:
- continue
-
- self._queue.put_nowait((channel, data))
- if self._max_history_length:
- for channel in channels:
- self._history[channel].append(data)
-
- async def subscribe(self, channels: Iterable[str]) -> None:
- """Subscribe to ``channels``, and enable publishing to them"""
- self._channels.update(channels)
-
- async def unsubscribe(self, channels: Iterable[str]) -> None:
- """Unsubscribe from ``channels``"""
- self._channels -= set(channels)
- try:
- for channel in channels:
- del self._history[channel]
- except KeyError:
- pass
-
- async def stream_events(self) -> AsyncGenerator[tuple[str, Any], None]:
- """Return a generator, iterating over events of subscribed channels as they become available"""
- if self._queue is None:
- raise RuntimeError("Backend not yet initialized. Did you forget to call on_startup?")
-
- while True:
- channel, message = await self._queue.get()
- self._queue.task_done()
-
- # if a message is published to a channel and the channel is then
- # unsubscribed before retrieving that message from the stream, it can still
- # end up here, so we double-check if we still are interested in this message
- if channel in self._channels:
- yield channel, message
-
- async def get_history(self, channel: str, limit: int | None = None) -> list[bytes]:
- """Return the event history of ``channel``, at most ``limit`` entries"""
- history = list(self._history[channel])
- if limit:
- history = history[-limit:]
- return history
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/backends/psycopg.py b/venv/lib/python3.11/site-packages/litestar/channels/backends/psycopg.py
deleted file mode 100644
index 14b53bc..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/backends/psycopg.py
+++ /dev/null
@@ -1,54 +0,0 @@
-from __future__ import annotations
-
-from contextlib import AsyncExitStack
-from typing import AsyncGenerator, Iterable
-
-import psycopg
-
-from .base import ChannelsBackend
-
-
-def _safe_quote(ident: str) -> str:
- return '"{}"'.format(ident.replace('"', '""')) # sourcery skip
-
-
-class PsycoPgChannelsBackend(ChannelsBackend):
- _listener_conn: psycopg.AsyncConnection
-
- def __init__(self, pg_dsn: str) -> None:
- self._pg_dsn = pg_dsn
- self._subscribed_channels: set[str] = set()
- self._exit_stack = AsyncExitStack()
-
- async def on_startup(self) -> None:
- self._listener_conn = await psycopg.AsyncConnection.connect(self._pg_dsn, autocommit=True)
- await self._exit_stack.enter_async_context(self._listener_conn)
-
- async def on_shutdown(self) -> None:
- await self._exit_stack.aclose()
-
- async def publish(self, data: bytes, channels: Iterable[str]) -> None:
- dec_data = data.decode("utf-8")
- async with await psycopg.AsyncConnection.connect(self._pg_dsn) as conn:
- for channel in channels:
- await conn.execute("SELECT pg_notify(%s, %s);", (channel, dec_data))
-
- async def subscribe(self, channels: Iterable[str]) -> None:
- for channel in set(channels) - self._subscribed_channels:
- # can't use placeholders in LISTEN
- await self._listener_conn.execute(f"LISTEN {_safe_quote(channel)};") # pyright: ignore
-
- self._subscribed_channels.add(channel)
-
- async def unsubscribe(self, channels: Iterable[str]) -> None:
- for channel in channels:
- # can't use placeholders in UNLISTEN
- await self._listener_conn.execute(f"UNLISTEN {_safe_quote(channel)};") # pyright: ignore
- self._subscribed_channels = self._subscribed_channels - set(channels)
-
- async def stream_events(self) -> AsyncGenerator[tuple[str, bytes], None]:
- async for notify in self._listener_conn.notifies():
- yield notify.channel, notify.payload.encode("utf-8")
-
- async def get_history(self, channel: str, limit: int | None = None) -> list[bytes]:
- raise NotImplementedError()
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/backends/redis.py b/venv/lib/python3.11/site-packages/litestar/channels/backends/redis.py
deleted file mode 100644
index f03c9f2..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/backends/redis.py
+++ /dev/null
@@ -1,277 +0,0 @@
-from __future__ import annotations
-
-import asyncio
-import sys
-
-if sys.version_info < (3, 9):
- import importlib_resources # pyright: ignore
-else:
- import importlib.resources as importlib_resources
-from abc import ABC
-from datetime import timedelta
-from typing import TYPE_CHECKING, Any, AsyncGenerator, Iterable, cast
-
-from litestar.channels.backends.base import ChannelsBackend
-
-if TYPE_CHECKING:
- from redis.asyncio import Redis
- from redis.asyncio.client import PubSub
-
-_resource_path = importlib_resources.files("litestar.channels.backends")
-_PUBSUB_PUBLISH_SCRIPT = (_resource_path / "_redis_pubsub_publish.lua").read_text()
-_FLUSHALL_STREAMS_SCRIPT = (_resource_path / "_redis_flushall_streams.lua").read_text()
-_XADD_EXPIRE_SCRIPT = (_resource_path / "_redis_xadd_expire.lua").read_text()
-
-
-class _LazyEvent:
- """A lazy proxy to asyncio.Event that only creates the event once it's accessed.
-
- It ensures that the Event is created within a running event loop. If it's not, there can be an issue where a future
- within the event itself is attached to a different loop.
-
- This happens in our tests and could also happen when a user creates an instance of the backend outside an event loop
- in their application.
- """
-
- def __init__(self) -> None:
- self.__event: asyncio.Event | None = None
-
- @property
- def _event(self) -> asyncio.Event:
- if self.__event is None:
- self.__event = asyncio.Event()
- return self.__event
-
- def set(self) -> None:
- self._event.set()
-
- def clear(self) -> None:
- self._event.clear()
-
- async def wait(self) -> None:
- await self._event.wait()
-
-
-class RedisChannelsBackend(ChannelsBackend, ABC):
- def __init__(self, *, redis: Redis, key_prefix: str, stream_sleep_no_subscriptions: int) -> None:
- """Base redis channels backend.
-
- Args:
- redis: A :class:`redis.asyncio.Redis` instance
- key_prefix: Key prefix to use for storing data in redis
- stream_sleep_no_subscriptions: Amount of time in milliseconds to pause the
- :meth:`stream_events` generator, should no subscribers exist
- """
- self._redis = redis
- self._key_prefix = key_prefix
- self._stream_sleep_no_subscriptions = stream_sleep_no_subscriptions
-
- def _make_key(self, channel: str) -> str:
- return f"{self._key_prefix}_{channel.upper()}"
-
-
-class RedisChannelsPubSubBackend(RedisChannelsBackend):
- def __init__(
- self, *, redis: Redis, stream_sleep_no_subscriptions: int = 1, key_prefix: str = "LITESTAR_CHANNELS"
- ) -> None:
- """Redis channels backend, `Pub/Sub <https://redis.io/docs/manual/pubsub/>`_.
-
- This backend provides low overhead and resource usage but no support for history.
-
- Args:
- redis: A :class:`redis.asyncio.Redis` instance
- key_prefix: Key prefix to use for storing data in redis
- stream_sleep_no_subscriptions: Amount of time in milliseconds to pause the
- :meth:`stream_events` generator, should no subscribers exist
- """
- super().__init__(
- redis=redis, stream_sleep_no_subscriptions=stream_sleep_no_subscriptions, key_prefix=key_prefix
- )
- self.__pub_sub: PubSub | None = None
- self._publish_script = self._redis.register_script(_PUBSUB_PUBLISH_SCRIPT)
- self._has_subscribed = _LazyEvent()
-
- @property
- def _pub_sub(self) -> PubSub:
- if self.__pub_sub is None:
- self.__pub_sub = self._redis.pubsub()
- return self.__pub_sub
-
- async def on_startup(self) -> None:
- # this method should not do anything in this case
- pass
-
- async def on_shutdown(self) -> None:
- await self._pub_sub.reset()
-
- async def subscribe(self, channels: Iterable[str]) -> None:
- """Subscribe to ``channels``, and enable publishing to them"""
- await self._pub_sub.subscribe(*channels)
- self._has_subscribed.set()
-
- async def unsubscribe(self, channels: Iterable[str]) -> None:
- """Stop listening for events on ``channels``"""
- await self._pub_sub.unsubscribe(*channels)
- # if we have no active subscriptions, or only subscriptions which are pending
- # to be unsubscribed we consider the backend to be unsubscribed from all
- # channels, so we reset the event
- if not self._pub_sub.channels.keys() - self._pub_sub.pending_unsubscribe_channels:
- self._has_subscribed.clear()
-
- async def publish(self, data: bytes, channels: Iterable[str]) -> None:
- """Publish ``data`` to ``channels``
-
- .. note::
- This operation is performed atomically, using a lua script
- """
- await self._publish_script(keys=list(set(channels)), args=[data])
-
- async def stream_events(self) -> AsyncGenerator[tuple[str, Any], None]:
- """Return a generator, iterating over events of subscribed channels as they become available.
-
- If no channels have been subscribed to yet via :meth:`subscribe`, sleep for ``stream_sleep_no_subscriptions``
- milliseconds.
- """
-
- while True:
- await self._has_subscribed.wait()
- message = await self._pub_sub.get_message(
- ignore_subscribe_messages=True, timeout=self._stream_sleep_no_subscriptions
- )
- if message is None:
- continue
-
- channel: str = message["channel"].decode()
- data: bytes = message["data"]
- # redis handles the unsubscibes with a queue; Unsubscribing doesn't mean the
- # unsubscribe will happen immediately after requesting it, so we could
- # receive a message on a channel that, from a client's perspective, it's not
- # subscribed to anymore
- if channel.encode() in self._pub_sub.channels.keys() - self._pub_sub.pending_unsubscribe_channels:
- yield channel, data
-
- async def get_history(self, channel: str, limit: int | None = None) -> list[bytes]:
- """Not implemented"""
- raise NotImplementedError()
-
-
-class RedisChannelsStreamBackend(RedisChannelsBackend):
- def __init__(
- self,
- history: int,
- *,
- redis: Redis,
- stream_sleep_no_subscriptions: int = 1,
- cap_streams_approximate: bool = True,
- stream_ttl: int | timedelta = timedelta(seconds=60),
- key_prefix: str = "LITESTAR_CHANNELS",
- ) -> None:
- """Redis channels backend, `streams <https://redis.io/docs/data-types/streams/>`_.
-
- Args:
- history: Amount of messages to keep. This will set a ``MAXLEN`` to the streams
- redis: A :class:`redis.asyncio.Redis` instance
- key_prefix: Key prefix to use for streams
- stream_sleep_no_subscriptions: Amount of time in milliseconds to pause the
- :meth:`stream_events` generator, should no subscribers exist
- cap_streams_approximate: Set the streams ``MAXLEN`` using the ``~`` approximation
- operator for improved performance
- stream_ttl: TTL of a stream in milliseconds or as a timedelta. A streams TTL will be set on each publishing
- operation using ``PEXPIRE``
- """
- super().__init__(
- redis=redis, stream_sleep_no_subscriptions=stream_sleep_no_subscriptions, key_prefix=key_prefix
- )
-
- self._history_limit = history
- self._subscribed_channels: set[str] = set()
- self._cap_streams_approximate = cap_streams_approximate
- self._stream_ttl = stream_ttl if isinstance(stream_ttl, int) else int(stream_ttl.total_seconds() * 1000)
- self._flush_all_streams_script = self._redis.register_script(_FLUSHALL_STREAMS_SCRIPT)
- self._publish_script = self._redis.register_script(_XADD_EXPIRE_SCRIPT)
- self._has_subscribed_channels = _LazyEvent()
-
- async def on_startup(self) -> None:
- """Called on application startup"""
-
- async def on_shutdown(self) -> None:
- """Called on application shutdown"""
-
- async def subscribe(self, channels: Iterable[str]) -> None:
- """Subscribe to ``channels``"""
- self._subscribed_channels.update(channels)
- self._has_subscribed_channels.set()
-
- async def unsubscribe(self, channels: Iterable[str]) -> None:
- """Unsubscribe from ``channels``"""
- self._subscribed_channels -= set(channels)
- if not len(self._subscribed_channels):
- self._has_subscribed_channels.clear()
-
- async def publish(self, data: bytes, channels: Iterable[str]) -> None:
- """Publish ``data`` to ``channels``.
-
- .. note::
- This operation is performed atomically, using a Lua script
- """
- channels = set(channels)
- await self._publish_script(
- keys=[self._make_key(key) for key in channels],
- args=[
- data,
- self._history_limit,
- self._stream_ttl,
- int(self._cap_streams_approximate),
- *channels,
- ],
- )
-
- async def _get_subscribed_channels(self) -> set[str]:
- """Get subscribed channels. If no channels are currently subscribed, wait"""
- await self._has_subscribed_channels.wait()
- return self._subscribed_channels
-
- async def stream_events(self) -> AsyncGenerator[tuple[str, Any], None]:
- """Return a generator, iterating over events of subscribed channels as they become available.
-
- If no channels have been subscribed to yet via :meth:`subscribe`, sleep for ``stream_sleep_no_subscriptions``
- milliseconds.
- """
- stream_ids: dict[str, bytes] = {}
- while True:
- # We wait for subscribed channels, because we can't pass an empty dict to
- # xread and block for subscribers
- stream_keys = [self._make_key(c) for c in await self._get_subscribed_channels()]
-
- data: list[tuple[bytes, list[tuple[bytes, dict[bytes, bytes]]]]] = await self._redis.xread(
- {key: stream_ids.get(key, 0) for key in stream_keys}, block=self._stream_sleep_no_subscriptions
- )
-
- if not data:
- continue
-
- for stream_key, channel_events in data:
- for event in channel_events:
- event_data = event[1][b"data"]
- channel_name = event[1][b"channel"].decode()
- stream_ids[stream_key.decode()] = event[0]
- yield channel_name, event_data
-
- async def get_history(self, channel: str, limit: int | None = None) -> list[bytes]:
- """Return the history of ``channels``, returning at most ``limit`` messages"""
- data: Iterable[tuple[bytes, dict[bytes, bytes]]]
- if limit:
- data = reversed(await self._redis.xrevrange(self._make_key(channel), count=limit))
- else:
- data = await self._redis.xrange(self._make_key(channel))
-
- return [event[b"data"] for _, event in data]
-
- async def flush_all(self) -> int:
- """Delete all stream keys with the ``key_prefix``.
-
- .. important::
- This method is incompatible with redis clusters
- """
- deleted_streams = await self._flush_all_streams_script(keys=[], args=[f"{self._key_prefix}*"])
- return cast("int", deleted_streams)
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/plugin.py b/venv/lib/python3.11/site-packages/litestar/channels/plugin.py
deleted file mode 100644
index 5988445..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/plugin.py
+++ /dev/null
@@ -1,359 +0,0 @@
-from __future__ import annotations
-
-import asyncio
-from asyncio import CancelledError, Queue, Task, create_task
-from contextlib import AbstractAsyncContextManager, asynccontextmanager, suppress
-from functools import partial
-from typing import TYPE_CHECKING, AsyncGenerator, Awaitable, Callable, Iterable
-
-import msgspec.json
-
-from litestar.di import Provide
-from litestar.exceptions import ImproperlyConfiguredException, LitestarException
-from litestar.handlers import WebsocketRouteHandler
-from litestar.plugins import InitPluginProtocol
-from litestar.serialization import default_serializer
-
-from .subscriber import BacklogStrategy, EventCallback, Subscriber
-
-if TYPE_CHECKING:
- from types import TracebackType
-
- from litestar.channels.backends.base import ChannelsBackend
- from litestar.config.app import AppConfig
- from litestar.connection import WebSocket
- from litestar.types import LitestarEncodableType, TypeEncodersMap
- from litestar.types.asgi_types import WebSocketMode
-
-
-class ChannelsException(LitestarException):
- pass
-
-
-class ChannelsPlugin(InitPluginProtocol, AbstractAsyncContextManager):
- def __init__(
- self,
- backend: ChannelsBackend,
- *,
- channels: Iterable[str] | None = None,
- arbitrary_channels_allowed: bool = False,
- create_ws_route_handlers: bool = False,
- ws_handler_send_history: int = 0,
- ws_handler_base_path: str = "/",
- ws_send_mode: WebSocketMode = "text",
- subscriber_max_backlog: int | None = None,
- subscriber_backlog_strategy: BacklogStrategy = "backoff",
- subscriber_class: type[Subscriber] = Subscriber,
- type_encoders: TypeEncodersMap | None = None,
- ) -> None:
- """Plugin to handle broadcasting to WebSockets with support for channels.
-
- This plugin is available as an injected dependency using the ``channels`` key.
-
- Args:
- backend: Backend to store data in
- channels: Channels to serve. If ``arbitrary_channels_allowed`` is ``False`` (the default), trying to
- subscribe to a channel not in ``channels`` will raise an exception
- arbitrary_channels_allowed: Allow the creation of channels on the fly
- create_ws_route_handlers: If ``True``, websocket route handlers will be created for all channels defined in
- ``channels``. If ``arbitrary_channels_allowed`` is ``True``, a single handler will be created instead,
- handling all channels. The handlers created will accept WebSocket connections and start sending received
- events for their respective channels.
- ws_handler_send_history: Amount of history entries to send from the generated websocket route handlers after
- a client has connected. A value of ``0`` indicates to not send a history
- ws_handler_base_path: Path prefix used for the generated route handlers
- ws_send_mode: Send mode to use for sending data through a :class:`WebSocket <.connection.WebSocket>`.
- This will be used when sending within generated route handlers or :meth:`Subscriber.run_in_background`
- subscriber_max_backlog: Maximum amount of unsent messages to be held in memory for a given subscriber. If
- that limit is reached, new messages will be treated accordingly to ``backlog_strategy``
- subscriber_backlog_strategy: Define the behaviour if ``max_backlog`` is reached for a subscriber. `
- `backoff`` will result in new messages being dropped until older ones have been processed. ``dropleft``
- will drop older messages in favour of new ones.
- subscriber_class: A :class:`Subscriber` subclass to return from :meth:`subscribe`
- type_encoders: An additional mapping of type encoders used to encode data before sending
-
- """
- self._backend = backend
- self._pub_queue: Queue[tuple[bytes, list[str]]] | None = None
- self._pub_task: Task | None = None
- self._sub_task: Task | None = None
-
- if not (channels or arbitrary_channels_allowed):
- raise ImproperlyConfiguredException("Must define either channels or set arbitrary_channels_allowed=True")
-
- # make the path absolute, so we can simply concatenate it later
- if not ws_handler_base_path.endswith("/"):
- ws_handler_base_path += "/"
-
- self._arbitrary_channels_allowed = arbitrary_channels_allowed
- self._create_route_handlers = create_ws_route_handlers
- self._handler_root_path = ws_handler_base_path
- self._socket_send_mode: WebSocketMode = ws_send_mode
- self._encode_json = msgspec.json.Encoder(
- enc_hook=partial(default_serializer, type_encoders=type_encoders)
- ).encode
- self._handler_should_send_history = bool(ws_handler_send_history)
- self._history_limit = None if ws_handler_send_history < 0 else ws_handler_send_history
- self._max_backlog = subscriber_max_backlog
- self._backlog_strategy: BacklogStrategy = subscriber_backlog_strategy
- self._subscriber_class = subscriber_class
-
- self._channels: dict[str, set[Subscriber]] = {channel: set() for channel in channels or []}
-
- def encode_data(self, data: LitestarEncodableType) -> bytes:
- """Encode data before storing it in the backend"""
- if isinstance(data, bytes):
- return data
-
- return data.encode() if isinstance(data, str) else self._encode_json(data)
-
- def on_app_init(self, app_config: AppConfig) -> AppConfig:
- """Plugin hook. Set up a ``channels`` dependency, add route handlers and register application hooks"""
- app_config.dependencies["channels"] = Provide(lambda: self, use_cache=True, sync_to_thread=False)
- app_config.lifespan.append(self)
- app_config.signature_namespace.update(ChannelsPlugin=ChannelsPlugin)
-
- if self._create_route_handlers:
- if self._arbitrary_channels_allowed:
- path = self._handler_root_path + "{channel_name:str}"
- route_handlers = [WebsocketRouteHandler(path)(self._ws_handler_func)]
- else:
- route_handlers = [
- WebsocketRouteHandler(self._handler_root_path + channel_name)(
- self._create_ws_handler_func(channel_name)
- )
- for channel_name in self._channels
- ]
- app_config.route_handlers.extend(route_handlers)
-
- return app_config
-
- def publish(self, data: LitestarEncodableType, channels: str | Iterable[str]) -> None:
- """Schedule ``data`` to be published to ``channels``.
-
- .. note::
- This is a synchronous method that returns immediately. There are no
- guarantees that when this method returns the data will have been published
- to the backend. For that, use :meth:`wait_published`
-
- """
- if isinstance(channels, str):
- channels = [channels]
- data = self.encode_data(data)
- try:
- self._pub_queue.put_nowait((data, list(channels))) # type: ignore[union-attr]
- except AttributeError as e:
- raise RuntimeError("Plugin not yet initialized. Did you forget to call on_startup?") from e
-
- async def wait_published(self, data: LitestarEncodableType, channels: str | Iterable[str]) -> None:
- """Publish ``data`` to ``channels``"""
- if isinstance(channels, str):
- channels = [channels]
- data = self.encode_data(data)
-
- await self._backend.publish(data, channels)
-
- async def subscribe(self, channels: str | Iterable[str], history: int | None = None) -> Subscriber:
- """Create a :class:`Subscriber`, providing a stream of all events in ``channels``.
-
- The created subscriber will be passive by default and has to be consumed manually,
- either by using :meth:`Subscriber.run_in_background` or iterating over events
- using :meth:`Subscriber.iter_events`.
-
- Args:
- channels: Channel(s) to subscribe to
- history: If a non-negative integer, add this amount of history entries from
- each channel to the subscriber's event stream. Note that this will wait
- until all history entries are fetched and pushed to the subscriber's
- stream. For more control use :meth:`put_subscriber_history`.
-
- Returns:
- A :class:`Subscriber`
-
- Raises:
- ChannelsException: If a channel in ``channels`` has not been declared on this backend and
- ``arbitrary_channels_allowed`` has not been set to ``True``
- """
- if isinstance(channels, str):
- channels = [channels]
-
- subscriber = self._subscriber_class(
- plugin=self,
- max_backlog=self._max_backlog,
- backlog_strategy=self._backlog_strategy,
- )
- channels_to_subscribe = set()
-
- for channel in channels:
- if channel not in self._channels:
- if not self._arbitrary_channels_allowed:
- raise ChannelsException(
- f"Unknown channel: {channel!r}. Either explicitly defined the channel or set "
- "arbitrary_channels_allowed=True"
- )
- self._channels[channel] = set()
- channel_subscribers = self._channels[channel]
- if not channel_subscribers:
- channels_to_subscribe.add(channel)
-
- channel_subscribers.add(subscriber)
-
- if channels_to_subscribe:
- await self._backend.subscribe(channels_to_subscribe)
-
- if history:
- await self.put_subscriber_history(subscriber=subscriber, limit=history, channels=channels)
-
- return subscriber
-
- async def unsubscribe(self, subscriber: Subscriber, channels: str | Iterable[str] | None = None) -> None:
- """Unsubscribe a :class:`Subscriber` from ``channels``. If the subscriber has a running sending task, it will
- be stopped.
-
- Args:
- channels: Channels to unsubscribe from. If ``None``, unsubscribe from all channels
- subscriber: :class:`Subscriber` to unsubscribe
- """
- if channels is None:
- channels = list(self._channels.keys())
- elif isinstance(channels, str):
- channels = [channels]
-
- channels_to_unsubscribe: set[str] = set()
-
- for channel in channels:
- channel_subscribers = self._channels[channel]
-
- try:
- channel_subscribers.remove(subscriber)
- except KeyError: # subscriber was not subscribed to this channel. This may happen if channels is None
- continue
-
- if not channel_subscribers:
- channels_to_unsubscribe.add(channel)
-
- if all(subscriber not in queues for queues in self._channels.values()):
- await subscriber.put(None) # this will stop any running task or generator by breaking the inner loop
- if subscriber.is_running:
- await subscriber.stop()
-
- if channels_to_unsubscribe:
- await self._backend.unsubscribe(channels_to_unsubscribe)
-
- @asynccontextmanager
- async def start_subscription(
- self, channels: str | Iterable[str], history: int | None = None
- ) -> AsyncGenerator[Subscriber, None]:
- """Create a :class:`Subscriber` and tie its subscriptions to a context manager;
- Upon exiting the context, :meth:`unsubscribe` will be called.
-
- Args:
- channels: Channel(s) to subscribe to
- history: If a non-negative integer, add this amount of history entries from
- each channel to the subscriber's event stream. Note that this will wait
- until all history entries are fetched and pushed to the subscriber's
- stream. For more control use :meth:`put_subscriber_history`.
-
- Returns:
- A :class:`Subscriber`
- """
- subscriber = await self.subscribe(channels, history=history)
-
- try:
- yield subscriber
- finally:
- await self.unsubscribe(subscriber, channels)
-
- async def put_subscriber_history(
- self, subscriber: Subscriber, channels: str | Iterable[str], limit: int | None = None
- ) -> None:
- """Fetch the history of ``channels`` from the backend and put them in the
- subscriber's stream
- """
- if isinstance(channels, str):
- channels = [channels]
-
- for channel in channels:
- history = await self._backend.get_history(channel, limit)
- for entry in history:
- await subscriber.put(entry)
-
- async def _ws_handler_func(self, channel_name: str, socket: WebSocket) -> None:
- await socket.accept()
-
- # the ternary operator triggers a mypy bug: https://github.com/python/mypy/issues/10740
- on_event: EventCallback = socket.send_text if self._socket_send_mode == "text" else socket.send_bytes # type: ignore[assignment]
-
- async with self.start_subscription(channel_name) as subscriber:
- if self._handler_should_send_history:
- await self.put_subscriber_history(subscriber, channels=channel_name, limit=self._history_limit)
-
- # use the background task, so we can block on receive(), breaking the loop when a connection closes
- async with subscriber.run_in_background(on_event):
- while (await socket.receive())["type"] != "websocket.disconnect":
- continue
-
- def _create_ws_handler_func(self, channel_name: str) -> Callable[[WebSocket], Awaitable[None]]:
- async def ws_handler_func(socket: WebSocket) -> None:
- await self._ws_handler_func(channel_name=channel_name, socket=socket)
-
- return ws_handler_func
-
- async def _pub_worker(self) -> None:
- while self._pub_queue:
- data, channels = await self._pub_queue.get()
- await self._backend.publish(data, channels)
- self._pub_queue.task_done()
-
- async def _sub_worker(self) -> None:
- async for channel, payload in self._backend.stream_events():
- for subscriber in self._channels.get(channel, []):
- subscriber.put_nowait(payload)
-
- async def _on_startup(self) -> None:
- await self._backend.on_startup()
- self._pub_queue = Queue()
- self._pub_task = create_task(self._pub_worker())
- self._sub_task = create_task(self._sub_worker())
- if self._channels:
- await self._backend.subscribe(list(self._channels))
-
- async def _on_shutdown(self) -> None:
- if self._pub_queue:
- await self._pub_queue.join()
- self._pub_queue = None
-
- await asyncio.gather(
- *[
- subscriber.stop(join=False)
- for subscribers in self._channels.values()
- for subscriber in subscribers
- if subscriber.is_running
- ]
- )
-
- if self._sub_task:
- self._sub_task.cancel()
- with suppress(CancelledError):
- await self._sub_task
- self._sub_task = None
-
- if self._pub_task:
- self._pub_task.cancel()
- with suppress(CancelledError):
- await self._pub_task
- self._sub_task = None
-
- await self._backend.on_shutdown()
-
- async def __aenter__(self) -> ChannelsPlugin:
- await self._on_startup()
- return self
-
- async def __aexit__(
- self,
- exc_type: type[BaseException] | None,
- exc_val: BaseException | None,
- exc_tb: TracebackType | None,
- ) -> None:
- await self._on_shutdown()
diff --git a/venv/lib/python3.11/site-packages/litestar/channels/subscriber.py b/venv/lib/python3.11/site-packages/litestar/channels/subscriber.py
deleted file mode 100644
index b358bc4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/channels/subscriber.py
+++ /dev/null
@@ -1,135 +0,0 @@
-from __future__ import annotations
-
-import asyncio
-from asyncio import CancelledError, Queue, QueueFull
-from collections import deque
-from contextlib import AsyncExitStack, asynccontextmanager, suppress
-from typing import TYPE_CHECKING, Any, AsyncGenerator, Awaitable, Callable, Generic, Literal, TypeVar
-
-if TYPE_CHECKING:
- from litestar.channels import ChannelsPlugin
-
-
-T = TypeVar("T")
-
-BacklogStrategy = Literal["backoff", "dropleft"]
-
-EventCallback = Callable[[bytes], Awaitable[Any]]
-
-
-class AsyncDeque(Queue, Generic[T]):
- def __init__(self, maxsize: int | None) -> None:
- self._deque_maxlen = maxsize
- super().__init__()
-
- def _init(self, maxsize: int) -> None:
- self._queue: deque[T] = deque(maxlen=self._deque_maxlen)
-
-
-class Subscriber:
- """A wrapper around a stream of events published to subscribed channels"""
-
- def __init__(
- self,
- plugin: ChannelsPlugin,
- max_backlog: int | None = None,
- backlog_strategy: BacklogStrategy = "backoff",
- ) -> None:
- self._task: asyncio.Task | None = None
- self._plugin = plugin
- self._backend = plugin._backend
- self._queue: Queue[bytes | None] | AsyncDeque[bytes | None]
-
- if max_backlog and backlog_strategy == "dropleft":
- self._queue = AsyncDeque(maxsize=max_backlog or 0)
- else:
- self._queue = Queue(maxsize=max_backlog or 0)
-
- async def put(self, item: bytes | None) -> None:
- await self._queue.put(item)
-
- def put_nowait(self, item: bytes | None) -> bool:
- """Put an item in the subscriber's stream without waiting"""
- try:
- self._queue.put_nowait(item)
- return True
- except QueueFull:
- return False
-
- @property
- def qsize(self) -> int:
- return self._queue.qsize()
-
- async def iter_events(self) -> AsyncGenerator[bytes, None]:
- """Iterate over the stream of events. If no items are available, block until
- one becomes available
- """
- while True:
- item = await self._queue.get()
- if item is None:
- self._queue.task_done()
- break
- yield item
- self._queue.task_done()
-
- @asynccontextmanager
- async def run_in_background(self, on_event: EventCallback, join: bool = True) -> AsyncGenerator[None, None]:
- """Start a task in the background that sends events from the subscriber's stream
- to ``socket`` as they become available. On exit, it will prevent the stream from
- accepting new events and wait until the currently enqueued ones are processed.
- Should the context be left with an exception, the task will be cancelled
- immediately.
-
- Args:
- on_event: Callback to invoke with the event data for every event
- join: If ``True``, wait for all items in the stream to be processed before
- stopping the worker. Note that an error occurring within the context
- will always lead to the immediate cancellation of the worker
- """
- self._start_in_background(on_event=on_event)
- async with AsyncExitStack() as exit_stack:
- exit_stack.push_async_callback(self.stop, join=False)
- yield
- exit_stack.pop_all()
- await self.stop(join=join)
-
- async def _worker(self, on_event: EventCallback) -> None:
- async for event in self.iter_events():
- await on_event(event)
-
- def _start_in_background(self, on_event: EventCallback) -> None:
- """Start a task in the background that sends events from the subscriber's stream
- to ``socket`` as they become available.
-
- Args:
- on_event: Callback to invoke with the event data for every event
- """
- if self._task is not None:
- raise RuntimeError("Subscriber is already running")
- self._task = asyncio.create_task(self._worker(on_event))
-
- @property
- def is_running(self) -> bool:
- """Return whether a sending task is currently running"""
- return self._task is not None
-
- async def stop(self, join: bool = False) -> None:
- """Stop a task was previously started with :meth:`run_in_background`. If the
- task is not yet done it will be cancelled and awaited
-
- Args:
- join: If ``True`` wait for all items to be processed before stopping the task
- """
- if not self._task:
- return
-
- if join:
- await self._queue.join()
-
- if not self._task.done():
- self._task.cancel()
-
- with suppress(CancelledError):
- await self._task
-
- self._task = None
diff --git a/venv/lib/python3.11/site-packages/litestar/cli/__init__.py b/venv/lib/python3.11/site-packages/litestar/cli/__init__.py
deleted file mode 100644
index f6c366e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/cli/__init__.py
+++ /dev/null
@@ -1,29 +0,0 @@
-"""Litestar CLI."""
-
-from __future__ import annotations
-
-from importlib.util import find_spec
-
-# Ensure `rich_click` patching occurs before we do any imports from `click`.
-if find_spec("rich_click") is not None: # pragma: no cover
- import rich_click as click
- from rich_click.cli import patch as rich_click_patch
-
- rich_click_patch()
- click.rich_click.USE_RICH_MARKUP = True
- click.rich_click.USE_MARKDOWN = False
- click.rich_click.SHOW_ARGUMENTS = True
- click.rich_click.GROUP_ARGUMENTS_OPTIONS = True
- click.rich_click.SHOW_ARGUMENTS = True
- click.rich_click.GROUP_ARGUMENTS_OPTIONS = True
- click.rich_click.STYLE_ERRORS_SUGGESTION = "magenta italic"
- click.rich_click.ERRORS_SUGGESTION = ""
- click.rich_click.ERRORS_EPILOGUE = ""
- click.rich_click.MAX_WIDTH = 80
- click.rich_click.SHOW_METAVARS_COLUMN = True
- click.rich_click.APPEND_METAVARS_HELP = True
-
-
-from .main import litestar_group
-
-__all__ = ["litestar_group"]
diff --git a/venv/lib/python3.11/site-packages/litestar/cli/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/cli/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 808a2fb..0000000
--- a/venv/lib/python3.11/site-packages/litestar/cli/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/cli/__pycache__/_utils.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/cli/__pycache__/_utils.cpython-311.pyc
deleted file mode 100644
index 4baba11..0000000
--- a/venv/lib/python3.11/site-packages/litestar/cli/__pycache__/_utils.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/cli/__pycache__/main.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/cli/__pycache__/main.cpython-311.pyc
deleted file mode 100644
index 7ede592..0000000
--- a/venv/lib/python3.11/site-packages/litestar/cli/__pycache__/main.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/cli/_utils.py b/venv/lib/python3.11/site-packages/litestar/cli/_utils.py
deleted file mode 100644
index f36cd77..0000000
--- a/venv/lib/python3.11/site-packages/litestar/cli/_utils.py
+++ /dev/null
@@ -1,562 +0,0 @@
-from __future__ import annotations
-
-import contextlib
-import importlib
-import inspect
-import os
-import re
-import sys
-from dataclasses import dataclass
-from datetime import datetime, timedelta, timezone
-from functools import wraps
-from importlib.util import find_spec
-from itertools import chain
-from os import getenv
-from pathlib import Path
-from typing import TYPE_CHECKING, Any, Callable, Generator, Iterable, Sequence, TypeVar, cast
-
-from click import ClickException, Command, Context, Group, pass_context
-from rich import get_console
-from rich.table import Table
-from typing_extensions import ParamSpec, get_type_hints
-
-from litestar import Litestar, __version__
-from litestar.middleware import DefineMiddleware
-from litestar.utils import get_name
-
-if sys.version_info >= (3, 10):
- from importlib.metadata import entry_points
-else:
- from importlib_metadata import entry_points
-
-
-if TYPE_CHECKING:
- from litestar.openapi import OpenAPIConfig
- from litestar.routes import ASGIRoute, HTTPRoute, WebSocketRoute
- from litestar.types import AnyCallable
-
-
-UVICORN_INSTALLED = find_spec("uvicorn") is not None
-JSBEAUTIFIER_INSTALLED = find_spec("jsbeautifier") is not None
-
-
-__all__ = (
- "UVICORN_INSTALLED",
- "JSBEAUTIFIER_INSTALLED",
- "LoadedApp",
- "LitestarCLIException",
- "LitestarEnv",
- "LitestarExtensionGroup",
- "LitestarGroup",
- "show_app_info",
-)
-
-
-P = ParamSpec("P")
-T = TypeVar("T")
-
-
-AUTODISCOVERY_FILE_NAMES = ["app", "application"]
-
-console = get_console()
-
-
-class LitestarCLIException(ClickException):
- """Base class for Litestar CLI exceptions."""
-
- def __init__(self, message: str) -> None:
- """Initialize exception and style error message."""
- super().__init__(message)
-
-
-@dataclass
-class LitestarEnv:
- """Information about the current Litestar environment variables."""
-
- app_path: str
- debug: bool
- app: Litestar
- cwd: Path
- host: str | None = None
- port: int | None = None
- fd: int | None = None
- uds: str | None = None
- reload: bool | None = None
- reload_dirs: tuple[str, ...] | None = None
- reload_include: tuple[str, ...] | None = None
- reload_exclude: tuple[str, ...] | None = None
- web_concurrency: int | None = None
- is_app_factory: bool = False
- certfile_path: str | None = None
- keyfile_path: str | None = None
- create_self_signed_cert: bool = False
-
- @classmethod
- def from_env(cls, app_path: str | None, app_dir: Path | None = None) -> LitestarEnv:
- """Load environment variables.
-
- If ``python-dotenv`` is installed, use it to populate environment first
- """
- cwd = Path().cwd() if app_dir is None else app_dir
- cwd_str_path = str(cwd)
- if cwd_str_path not in sys.path:
- sys.path.append(cwd_str_path)
-
- with contextlib.suppress(ImportError):
- import dotenv
-
- dotenv.load_dotenv()
- app_path = app_path or getenv("LITESTAR_APP")
- if app_path and getenv("LITESTAR_APP") is None:
- os.environ["LITESTAR_APP"] = app_path
- if app_path:
- console.print(f"Using Litestar app from env: [bright_blue]{app_path!r}")
- loaded_app = _load_app_from_path(app_path)
- else:
- loaded_app = _autodiscover_app(cwd)
-
- port = getenv("LITESTAR_PORT")
- web_concurrency = getenv("WEB_CONCURRENCY")
- uds = getenv("LITESTAR_UNIX_DOMAIN_SOCKET")
- fd = getenv("LITESTAR_FILE_DESCRIPTOR")
- reload_dirs = tuple(s.strip() for s in getenv("LITESTAR_RELOAD_DIRS", "").split(",") if s) or None
- reload_include = tuple(s.strip() for s in getenv("LITESTAR_RELOAD_INCLUDES", "").split(",") if s) or None
- reload_exclude = tuple(s.strip() for s in getenv("LITESTAR_RELOAD_EXCLUDES", "").split(",") if s) or None
-
- return cls(
- app_path=loaded_app.app_path,
- app=loaded_app.app,
- debug=_bool_from_env("LITESTAR_DEBUG"),
- host=getenv("LITESTAR_HOST"),
- port=int(port) if port else None,
- uds=uds,
- fd=int(fd) if fd else None,
- reload=_bool_from_env("LITESTAR_RELOAD"),
- reload_dirs=reload_dirs,
- reload_include=reload_include,
- reload_exclude=reload_exclude,
- web_concurrency=int(web_concurrency) if web_concurrency else None,
- is_app_factory=loaded_app.is_factory,
- cwd=cwd,
- certfile_path=getenv("LITESTAR_SSL_CERT_PATH"),
- keyfile_path=getenv("LITESTAR_SSL_KEY_PATH"),
- create_self_signed_cert=_bool_from_env("LITESTAR_CREATE_SELF_SIGNED_CERT"),
- )
-
-
-@dataclass
-class LoadedApp:
- """Information about a loaded Litestar app."""
-
- app: Litestar
- app_path: str
- is_factory: bool
-
-
-class LitestarGroup(Group):
- """:class:`click.Group` subclass that automatically injects ``app`` and ``env` kwargs into commands that request it.
-
- Use this as the ``cls`` for :class:`click.Group` if you're extending the internal CLI with a group. For ``command``s
- added directly to the root group this is not needed.
- """
-
- def __init__(
- self,
- name: str | None = None,
- commands: dict[str, Command] | Sequence[Command] | None = None,
- **attrs: Any,
- ) -> None:
- """Init ``LitestarGroup``"""
- self.group_class = LitestarGroup
- super().__init__(name=name, commands=commands, **attrs)
-
- def add_command(self, cmd: Command, name: str | None = None) -> None:
- """Add command.
-
- If necessary, inject ``app`` and ``env`` kwargs
- """
- if cmd.callback:
- cmd.callback = _inject_args(cmd.callback)
- super().add_command(cmd)
-
- def command(self, *args: Any, **kwargs: Any) -> Callable[[AnyCallable], Command] | Command: # type: ignore[override]
- # For some reason, even when copying the overloads + signature from click 1:1, mypy goes haywire
- """Add a function as a command.
-
- If necessary, inject ``app`` and ``env`` kwargs
- """
-
- def decorator(f: AnyCallable) -> Command:
- f = _inject_args(f)
- return cast("Command", Group.command(self, *args, **kwargs)(f))
-
- return decorator
-
-
-class LitestarExtensionGroup(LitestarGroup):
- """``LitestarGroup`` subclass that will load Litestar-CLI extensions from the `litestar.commands` entry_point.
-
- This group class should not be used on any group besides the root ``litestar_group``.
- """
-
- def __init__(
- self,
- name: str | None = None,
- commands: dict[str, Command] | Sequence[Command] | None = None,
- **attrs: Any,
- ) -> None:
- """Init ``LitestarExtensionGroup``"""
- super().__init__(name=name, commands=commands, **attrs)
- self._prepare_done = False
-
- for entry_point in entry_points(group="litestar.commands"):
- command = entry_point.load()
- _wrap_commands([command])
- self.add_command(command, entry_point.name)
-
- def _prepare(self, ctx: Context) -> None:
- if self._prepare_done:
- return
-
- if isinstance(ctx.obj, LitestarEnv):
- env: LitestarEnv | None = ctx.obj
- else:
- try:
- env = ctx.obj = LitestarEnv.from_env(ctx.params.get("app_path"), ctx.params.get("app_dir"))
- except LitestarCLIException:
- env = None
-
- if env:
- for plugin in env.app.plugins.cli:
- plugin.on_cli_init(self)
-
- self._prepare_done = True
-
- def make_context(
- self,
- info_name: str | None,
- args: list[str],
- parent: Context | None = None,
- **extra: Any,
- ) -> Context:
- ctx = super().make_context(info_name, args, parent, **extra)
- self._prepare(ctx)
- return ctx
-
- def list_commands(self, ctx: Context) -> list[str]:
- self._prepare(ctx)
- return super().list_commands(ctx)
-
-
-def _inject_args(func: Callable[P, T]) -> Callable[P, T]:
- """Inject the app instance into a ``Command``"""
- params = inspect.signature(func).parameters
-
- @wraps(func)
- def wrapped(ctx: Context, /, *args: P.args, **kwargs: P.kwargs) -> T:
- needs_app = "app" in params
- needs_env = "env" in params
- if needs_env or needs_app:
- # only resolve this if actually requested. Commands that don't need an env or app should be able to run
- # without
- if not isinstance(ctx.obj, LitestarEnv):
- ctx.obj = ctx.obj()
- env = ctx.ensure_object(LitestarEnv)
- if needs_app:
- kwargs["app"] = env.app
- if needs_env:
- kwargs["env"] = env
-
- if "ctx" in params:
- kwargs["ctx"] = ctx
-
- return func(*args, **kwargs)
-
- return pass_context(wrapped)
-
-
-def _wrap_commands(commands: Iterable[Command]) -> None:
- for command in commands:
- if isinstance(command, Group):
- _wrap_commands(command.commands.values())
- elif command.callback:
- command.callback = _inject_args(command.callback)
-
-
-def _bool_from_env(key: str, default: bool = False) -> bool:
- value = getenv(key)
- if not value:
- return default
- value = value.lower()
- return value in ("true", "1")
-
-
-def _load_app_from_path(app_path: str) -> LoadedApp:
- module_path, app_name = app_path.split(":")
- module = importlib.import_module(module_path)
- app = getattr(module, app_name)
- is_factory = False
- if not isinstance(app, Litestar) and callable(app):
- app = app()
- is_factory = True
- return LoadedApp(app=app, app_path=app_path, is_factory=is_factory)
-
-
-def _path_to_dotted_path(path: Path) -> str:
- if path.stem == "__init__":
- path = path.parent
- return ".".join(path.with_suffix("").parts)
-
-
-def _arbitrary_autodiscovery_paths(base_dir: Path) -> Generator[Path, None, None]:
- yield from _autodiscovery_paths(base_dir, arbitrary=False)
- for path in base_dir.iterdir():
- if path.name.startswith(".") or path.name.startswith("_"):
- continue
- if path.is_file() and path.suffix == ".py":
- yield path
-
-
-def _autodiscovery_paths(base_dir: Path, arbitrary: bool = True) -> Generator[Path, None, None]:
- for name in AUTODISCOVERY_FILE_NAMES:
- path = base_dir / name
-
- if path.exists() or path.with_suffix(".py").exists():
- yield path
- if arbitrary and path.is_dir():
- yield from _arbitrary_autodiscovery_paths(path)
-
-
-def _autodiscover_app(cwd: Path) -> LoadedApp:
- for file_path in _autodiscovery_paths(cwd):
- import_path = _path_to_dotted_path(file_path.relative_to(cwd))
- module = importlib.import_module(import_path)
-
- for attr, value in chain(
- [("app", getattr(module, "app", None)), ("application", getattr(module, "application", None))],
- module.__dict__.items(),
- ):
- if isinstance(value, Litestar):
- app_string = f"{import_path}:{attr}"
- os.environ["LITESTAR_APP"] = app_string
- console.print(f"Using Litestar app from [bright_blue]{app_string}")
- return LoadedApp(app=value, app_path=app_string, is_factory=False)
-
- if hasattr(module, "create_app"):
- app_string = f"{import_path}:create_app"
- os.environ["LITESTAR_APP"] = app_string
- console.print(f"Using Litestar factory [bright_blue]{app_string}")
- return LoadedApp(app=module.create_app(), app_path=app_string, is_factory=True)
-
- for attr, value in module.__dict__.items():
- if not callable(value):
- continue
- return_annotation = (
- get_type_hints(value, include_extras=True).get("return") if hasattr(value, "__annotations__") else None
- )
- if not return_annotation:
- continue
- if return_annotation in ("Litestar", Litestar):
- app_string = f"{import_path}:{attr}"
- os.environ["LITESTAR_APP"] = app_string
- console.print(f"Using Litestar factory [bright_blue]{app_string}")
- return LoadedApp(app=value(), app_path=f"{app_string}", is_factory=True)
-
- raise LitestarCLIException("Could not find a Litestar app or factory")
-
-
-def _format_is_enabled(value: Any) -> str:
- """Return a coloured string `"Enabled" if ``value`` is truthy, else "Disabled"."""
- return "[green]Enabled[/]" if value else "[red]Disabled[/]"
-
-
-def show_app_info(app: Litestar) -> None: # pragma: no cover
- """Display basic information about the application and its configuration."""
-
- table = Table(show_header=False)
- table.add_column("title", style="cyan")
- table.add_column("value", style="bright_blue")
-
- table.add_row("Litestar version", f"{__version__.major}.{__version__.minor}.{__version__.patch}")
- table.add_row("Debug mode", _format_is_enabled(app.debug))
- table.add_row("Python Debugger on exception", _format_is_enabled(app.pdb_on_exception))
- table.add_row("CORS", _format_is_enabled(app.cors_config))
- table.add_row("CSRF", _format_is_enabled(app.csrf_config))
- if app.allowed_hosts:
- allowed_hosts = app.allowed_hosts
-
- table.add_row("Allowed hosts", ", ".join(allowed_hosts.allowed_hosts))
-
- openapi_enabled = _format_is_enabled(app.openapi_config)
- if app.openapi_config:
- openapi_enabled += f" path=[yellow]{app.openapi_config.openapi_controller.path}"
- table.add_row("OpenAPI", openapi_enabled)
-
- table.add_row("Compression", app.compression_config.backend if app.compression_config else "[red]Disabled")
-
- if app.template_engine:
- table.add_row("Template engine", type(app.template_engine).__name__)
-
- if app.static_files_config:
- static_files_configs = app.static_files_config
- static_files_info = [
- f"path=[yellow]{static_files.path}[/] dirs=[yellow]{', '.join(map(str, static_files.directories))}[/] "
- f"html_mode={_format_is_enabled(static_files.html_mode)}"
- for static_files in static_files_configs
- ]
- table.add_row("Static files", "\n".join(static_files_info))
-
- middlewares = []
- for middleware in app.middleware:
- updated_middleware = middleware.middleware if isinstance(middleware, DefineMiddleware) else middleware
- middlewares.append(get_name(updated_middleware))
- if middlewares:
- table.add_row("Middlewares", ", ".join(middlewares))
-
- console.print(table)
-
-
-def validate_ssl_file_paths(certfile_arg: str | None, keyfile_arg: str | None) -> tuple[str, str] | tuple[None, None]:
- """Validate whether given paths exist, are not directories and were both provided or none was. Return the resolved paths.
-
- Args:
- certfile_arg: path argument for the certificate file
- keyfile_arg: path argument for the key file
-
- Returns:
- tuple of resolved paths converted to str or tuple of None's if no argument was provided
- """
- if certfile_arg is None and keyfile_arg is None:
- return (None, None)
-
- resolved_paths = []
-
- for argname, arg in {"--ssl-certfile": certfile_arg, "--ssl-keyfile": keyfile_arg}.items():
- if arg is None:
- raise LitestarCLIException(f"No value provided for {argname}")
- path = Path(arg).resolve()
- if path.is_dir():
- raise LitestarCLIException(f"Path provided for {argname} is a directory: {path}")
- if not path.exists():
- raise LitestarCLIException(f"File provided for {argname} was not found: {path}")
- resolved_paths.append(str(path))
-
- return tuple(resolved_paths) # type: ignore[return-value]
-
-
-def create_ssl_files(
- certfile_arg: str | None, keyfile_arg: str | None, common_name: str = "localhost"
-) -> tuple[str, str]:
- """Validate whether both files were provided, are not directories, their parent dirs exist and either both files exists or none does.
- If neither file exists, create a self-signed ssl certificate and a passwordless key at the location.
-
- Args:
- certfile_arg: path argument for the certificate file
- keyfile_arg: path argument for the key file
- common_name: the CN to be used as cert issuer and subject
-
- Returns:
- resolved paths of the found or generated files
- """
- resolved_paths = []
-
- for argname, arg in {"--ssl-certfile": certfile_arg, "--ssl-keyfile": keyfile_arg}.items():
- if arg is None:
- raise LitestarCLIException(f"No value provided for {argname}")
- path = Path(arg).resolve()
- if path.is_dir():
- raise LitestarCLIException(f"Path provided for {argname} is a directory: {path}")
- if not (parent_dir := path.parent).exists():
- raise LitestarCLIException(
- f"Could not create file, parent directory for {argname} doesn't exist: {parent_dir}"
- )
- resolved_paths.append(path)
-
- if (not resolved_paths[0].exists()) ^ (not resolved_paths[1].exists()):
- raise LitestarCLIException(
- "Both certificate and key file must exists or both must not exists when using --create-self-signed-cert"
- )
-
- if (not resolved_paths[0].exists()) and (not resolved_paths[1].exists()):
- _generate_self_signed_cert(resolved_paths[0], resolved_paths[1], common_name)
-
- return (str(resolved_paths[0]), str(resolved_paths[1]))
-
-
-def _generate_self_signed_cert(certfile_path: Path, keyfile_path: Path, common_name: str) -> None:
- """Create a self-signed certificate using the cryptography modules at given paths"""
- try:
- from cryptography import x509
- from cryptography.hazmat.backends import default_backend
- from cryptography.hazmat.primitives import hashes, serialization
- from cryptography.hazmat.primitives.asymmetric import rsa
- from cryptography.x509.oid import NameOID
- except ImportError as err:
- raise LitestarCLIException(
- "Cryptography must be installed when using --create-self-signed-cert\nPlease install the litestar[cryptography] extras"
- ) from err
-
- subject = x509.Name(
- [
- x509.NameAttribute(NameOID.COMMON_NAME, common_name),
- x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Development Certificate"),
- ]
- )
-
- key = rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend())
-
- cert = (
- x509.CertificateBuilder()
- .subject_name(subject)
- .issuer_name(subject)
- .public_key(key.public_key())
- .serial_number(x509.random_serial_number())
- .not_valid_before(datetime.now(tz=timezone.utc))
- .not_valid_after(datetime.now(tz=timezone.utc) + timedelta(days=365))
- .add_extension(x509.SubjectAlternativeName([x509.DNSName(common_name)]), critical=False)
- .add_extension(x509.ExtendedKeyUsage([x509.OID_SERVER_AUTH]), critical=False)
- .sign(key, hashes.SHA256(), default_backend())
- )
-
- with certfile_path.open("wb") as cert_file:
- cert_file.write(cert.public_bytes(serialization.Encoding.PEM))
-
- with keyfile_path.open("wb") as key_file:
- key_file.write(
- key.private_bytes(
- encoding=serialization.Encoding.PEM,
- format=serialization.PrivateFormat.TraditionalOpenSSL,
- encryption_algorithm=serialization.NoEncryption(),
- )
- )
-
-
-def remove_routes_with_patterns(
- routes: list[HTTPRoute | ASGIRoute | WebSocketRoute], patterns: tuple[str, ...]
-) -> list[HTTPRoute | ASGIRoute | WebSocketRoute]:
- regex_routes = []
- valid_patterns = []
- for pattern in patterns:
- try:
- check_pattern = re.compile(pattern)
- valid_patterns.append(check_pattern)
- except re.error as e:
- console.print(f"Error: {e}. Invalid regex pattern supplied: '{pattern}'. Omitting from querying results.")
-
- for route in routes:
- checked_pattern_route_matches = []
- for pattern_compile in valid_patterns:
- matches = pattern_compile.match(route.path)
- checked_pattern_route_matches.append(matches)
-
- if not any(checked_pattern_route_matches):
- regex_routes.append(route)
-
- return regex_routes
-
-
-def remove_default_schema_routes(
- routes: list[HTTPRoute | ASGIRoute | WebSocketRoute], openapi_config: OpenAPIConfig
-) -> list[HTTPRoute | ASGIRoute | WebSocketRoute]:
- schema_path = openapi_config.openapi_controller.path
- return remove_routes_with_patterns(routes, (schema_path,))
diff --git a/venv/lib/python3.11/site-packages/litestar/cli/commands/__init__.py b/venv/lib/python3.11/site-packages/litestar/cli/commands/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/venv/lib/python3.11/site-packages/litestar/cli/commands/__init__.py
+++ /dev/null
diff --git a/venv/lib/python3.11/site-packages/litestar/cli/commands/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/cli/commands/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index af651ad..0000000
--- a/venv/lib/python3.11/site-packages/litestar/cli/commands/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/cli/commands/__pycache__/core.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/cli/commands/__pycache__/core.cpython-311.pyc
deleted file mode 100644
index 6f44d52..0000000
--- a/venv/lib/python3.11/site-packages/litestar/cli/commands/__pycache__/core.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/cli/commands/__pycache__/schema.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/cli/commands/__pycache__/schema.cpython-311.pyc
deleted file mode 100644
index d6d7532..0000000
--- a/venv/lib/python3.11/site-packages/litestar/cli/commands/__pycache__/schema.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/cli/commands/__pycache__/sessions.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/cli/commands/__pycache__/sessions.cpython-311.pyc
deleted file mode 100644
index bebfa1a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/cli/commands/__pycache__/sessions.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/cli/commands/core.py b/venv/lib/python3.11/site-packages/litestar/cli/commands/core.py
deleted file mode 100644
index 5b55253..0000000
--- a/venv/lib/python3.11/site-packages/litestar/cli/commands/core.py
+++ /dev/null
@@ -1,335 +0,0 @@
-from __future__ import annotations
-
-import inspect
-import multiprocessing
-import os
-import subprocess
-import sys
-from contextlib import AbstractContextManager, ExitStack, contextmanager
-from typing import TYPE_CHECKING, Any, Iterator
-
-import click
-from click import Context, command, option
-from rich.tree import Tree
-
-from litestar.app import DEFAULT_OPENAPI_CONFIG
-from litestar.cli._utils import (
- UVICORN_INSTALLED,
- LitestarEnv,
- console,
- create_ssl_files,
- remove_default_schema_routes,
- remove_routes_with_patterns,
- show_app_info,
- validate_ssl_file_paths,
-)
-from litestar.routes import ASGIRoute, HTTPRoute, WebSocketRoute
-from litestar.utils.helpers import unwrap_partial
-
-__all__ = ("info_command", "routes_command", "run_command")
-
-if TYPE_CHECKING:
- from litestar import Litestar
-
-
-@contextmanager
-def _server_lifespan(app: Litestar) -> Iterator[None]:
- """Context manager handling the ASGI server lifespan.
-
- It will be entered just before the ASGI server is started through the CLI.
- """
- with ExitStack() as exit_stack:
- for manager in app._server_lifespan_managers:
- if not isinstance(manager, AbstractContextManager):
- manager = manager(app) # type: ignore[assignment]
- exit_stack.enter_context(manager) # type: ignore[arg-type]
-
- yield
-
-
-def _convert_uvicorn_args(args: dict[str, Any]) -> list[str]:
- process_args = []
- for arg, value in args.items():
- if isinstance(value, bool):
- if value:
- process_args.append(f"--{arg}")
- elif isinstance(value, tuple):
- process_args.extend(f"--{arg}={item}" for item in value)
- else:
- process_args.append(f"--{arg}={value}")
-
- return process_args
-
-
-def _run_uvicorn_in_subprocess(
- *,
- env: LitestarEnv,
- host: str | None,
- port: int | None,
- workers: int | None,
- reload: bool,
- reload_dirs: tuple[str, ...] | None,
- reload_include: tuple[str, ...] | None,
- reload_exclude: tuple[str, ...] | None,
- fd: int | None,
- uds: str | None,
- certfile_path: str | None,
- keyfile_path: str | None,
-) -> None:
- process_args: dict[str, Any] = {
- "reload": reload,
- "host": host,
- "port": port,
- "workers": workers,
- "factory": env.is_app_factory,
- }
- if fd is not None:
- process_args["fd"] = fd
- if uds is not None:
- process_args["uds"] = uds
- if reload_dirs:
- process_args["reload-dir"] = reload_dirs
- if reload_include:
- process_args["reload-include"] = reload_include
- if reload_exclude:
- process_args["reload-exclude"] = reload_exclude
- if certfile_path is not None:
- process_args["ssl-certfile"] = certfile_path
- if keyfile_path is not None:
- process_args["ssl-keyfile"] = keyfile_path
- subprocess.run(
- [sys.executable, "-m", "uvicorn", env.app_path, *_convert_uvicorn_args(process_args)], # noqa: S603
- check=True,
- )
-
-
-@command(name="version")
-@option("-s", "--short", help="Exclude release level and serial information", is_flag=True, default=False)
-def version_command(short: bool) -> None:
- """Show the currently installed Litestar version."""
- from litestar import __version__
-
- click.echo(__version__.formatted(short=short))
-
-
-@command(name="info")
-def info_command(app: Litestar) -> None:
- """Show information about the detected Litestar app."""
-
- show_app_info(app)
-
-
-@command(name="run")
-@option("-r", "--reload", help="Reload server on changes", default=False, is_flag=True)
-@option("-R", "--reload-dir", help="Directories to watch for file changes", multiple=True)
-@option(
- "-I", "--reload-include", help="Glob patterns for files to include when watching for file changes", multiple=True
-)
-@option(
- "-E", "--reload-exclude", help="Glob patterns for files to exclude when watching for file changes", multiple=True
-)
-@option("-p", "--port", help="Serve under this port", type=int, default=8000, show_default=True)
-@option(
- "-W",
- "--wc",
- "--web-concurrency",
- help="The number of HTTP workers to launch",
- type=click.IntRange(min=1, max=multiprocessing.cpu_count() + 1),
- show_default=True,
- default=1,
-)
-@option("-H", "--host", help="Server under this host", default="127.0.0.1", show_default=True)
-@option(
- "-F",
- "--fd",
- "--file-descriptor",
- help="Bind to a socket from this file descriptor.",
- type=int,
- default=None,
- show_default=True,
-)
-@option("-U", "--uds", "--unix-domain-socket", help="Bind to a UNIX domain socket.", default=None, show_default=True)
-@option("-d", "--debug", help="Run app in debug mode", is_flag=True)
-@option("-P", "--pdb", "--use-pdb", help="Drop into PDB on an exception", is_flag=True)
-@option("--ssl-certfile", help="Location of the SSL cert file", default=None)
-@option("--ssl-keyfile", help="Location of the SSL key file", default=None)
-@option(
- "--create-self-signed-cert",
- help="If certificate and key are not found at specified locations, create a self-signed certificate and a key",
- is_flag=True,
-)
-def run_command(
- reload: bool,
- port: int,
- wc: int,
- host: str,
- fd: int | None,
- uds: str | None,
- debug: bool,
- reload_dir: tuple[str, ...],
- reload_include: tuple[str, ...],
- reload_exclude: tuple[str, ...],
- pdb: bool,
- ssl_certfile: str | None,
- ssl_keyfile: str | None,
- create_self_signed_cert: bool,
- ctx: Context,
-) -> None:
- """Run a Litestar app; requires ``uvicorn``.
-
- The app can be either passed as a module path in the form of <module name>.<submodule>:<app instance or factory>,
- set as an environment variable LITESTAR_APP with the same format or automatically discovered from one of these
- canonical paths: app.py, asgi.py, application.py or app/__init__.py. When auto-discovering application factories,
- functions with the name ``create_app`` are considered, or functions that are annotated as returning a ``Litestar``
- instance.
- """
-
- if debug:
- os.environ["LITESTAR_DEBUG"] = "1"
-
- if pdb:
- os.environ["LITESTAR_PDB"] = "1"
-
- if not UVICORN_INSTALLED:
- console.print(
- r"uvicorn is not installed. Please install the standard group, litestar\[standard], to use this command."
- )
- sys.exit(1)
-
- if callable(ctx.obj):
- ctx.obj = ctx.obj()
- else:
- if debug:
- ctx.obj.app.debug = True
- if pdb:
- ctx.obj.app.pdb_on_exception = True
-
- env: LitestarEnv = ctx.obj
- app = env.app
-
- reload_dirs = env.reload_dirs or reload_dir
- reload_include = env.reload_include or reload_include
- reload_exclude = env.reload_exclude or reload_exclude
-
- host = env.host or host
- port = env.port if env.port is not None else port
- fd = env.fd if env.fd is not None else fd
- uds = env.uds or uds
- reload = env.reload or reload or bool(reload_dirs) or bool(reload_include) or bool(reload_exclude)
- workers = env.web_concurrency or wc
-
- ssl_certfile = ssl_certfile or env.certfile_path
- ssl_keyfile = ssl_keyfile or env.keyfile_path
- create_self_signed_cert = create_self_signed_cert or env.create_self_signed_cert
-
- certfile_path, keyfile_path = (
- create_ssl_files(ssl_certfile, ssl_keyfile, host)
- if create_self_signed_cert
- else validate_ssl_file_paths(ssl_certfile, ssl_keyfile)
- )
-
- console.rule("[yellow]Starting server process", align="left")
-
- show_app_info(app)
- with _server_lifespan(app):
- if workers == 1 and not reload:
- import uvicorn
-
- # A guard statement at the beginning of this function prevents uvicorn from being unbound
- # See "reportUnboundVariable in:
- # https://microsoft.github.io/pyright/#/configuration?id=type-check-diagnostics-settings
- uvicorn.run( # pyright: ignore
- app=env.app_path,
- host=host,
- port=port,
- fd=fd,
- uds=uds,
- factory=env.is_app_factory,
- ssl_certfile=certfile_path,
- ssl_keyfile=keyfile_path,
- )
- else:
- # invoke uvicorn in a subprocess to be able to use the --reload flag. see
- # https://github.com/litestar-org/litestar/issues/1191 and https://github.com/encode/uvicorn/issues/1045
- if sys.gettrace() is not None:
- console.print(
- "[yellow]Debugger detected. Breakpoints might not work correctly inside route handlers when running"
- " with the --reload or --workers options[/]"
- )
-
- _run_uvicorn_in_subprocess(
- env=env,
- host=host,
- port=port,
- workers=workers,
- reload=reload,
- reload_dirs=reload_dirs,
- reload_include=reload_include,
- reload_exclude=reload_exclude,
- fd=fd,
- uds=uds,
- certfile_path=certfile_path,
- keyfile_path=keyfile_path,
- )
-
-
-@command(name="routes")
-@option("--schema", help="Include schema routes", is_flag=True, default=False)
-@option("--exclude", help="routes to exclude via regex", type=str, is_flag=False, multiple=True)
-def routes_command(app: Litestar, exclude: tuple[str, ...], schema: bool) -> None: # pragma: no cover
- """Display information about the application's routes."""
-
- sorted_routes = sorted(app.routes, key=lambda r: r.path)
- if not schema:
- openapi_config = app.openapi_config or DEFAULT_OPENAPI_CONFIG
- sorted_routes = remove_default_schema_routes(sorted_routes, openapi_config)
- if exclude is not None:
- sorted_routes = remove_routes_with_patterns(sorted_routes, exclude)
-
- console.print(_RouteTree(sorted_routes))
-
-
-class _RouteTree(Tree):
- def __init__(self, routes: list[HTTPRoute | ASGIRoute | WebSocketRoute]) -> None:
- super().__init__("", hide_root=True)
- self._routes = routes
- self._build()
-
- def _build(self) -> None:
- for route in self._routes:
- if isinstance(route, HTTPRoute):
- self._handle_http_route(route)
- elif isinstance(route, WebSocketRoute):
- self._handle_websocket_route(route)
- else:
- self._handle_asgi_route(route)
-
- def _handle_asgi_like_route(self, route: ASGIRoute | WebSocketRoute, route_type: str) -> None:
- branch = self.add(f"[green]{route.path}[/green] ({route_type})")
- branch.add(f"[blue]{route.route_handler.name or route.route_handler.handler_name}[/blue]")
-
- def _handle_asgi_route(self, route: ASGIRoute) -> None:
- self._handle_asgi_like_route(route, route_type="ASGI")
-
- def _handle_websocket_route(self, route: WebSocketRoute) -> None:
- self._handle_asgi_like_route(route, route_type="WS")
-
- def _handle_http_route(self, route: HTTPRoute) -> None:
- branch = self.add(f"[green]{route.path}[/green] (HTTP)")
- for handler in route.route_handlers:
- handler_info = [
- f"[blue]{handler.name or handler.handler_name}[/blue]",
- ]
-
- if inspect.iscoroutinefunction(unwrap_partial(handler.fn)):
- handler_info.append("[magenta]async[/magenta]")
- else:
- handler_info.append("[yellow]sync[/yellow]")
-
- handler_info.append(f'[cyan]{", ".join(sorted(handler.http_methods))}[/cyan]')
-
- if len(handler.paths) > 1:
- for path in handler.paths:
- branch.add(" ".join([f"[green]{path}[green]", *handler_info]))
- else:
- branch.add(" ".join(handler_info))
diff --git a/venv/lib/python3.11/site-packages/litestar/cli/commands/schema.py b/venv/lib/python3.11/site-packages/litestar/cli/commands/schema.py
deleted file mode 100644
index a323bc7..0000000
--- a/venv/lib/python3.11/site-packages/litestar/cli/commands/schema.py
+++ /dev/null
@@ -1,82 +0,0 @@
-from pathlib import Path
-
-import msgspec
-from click import Path as ClickPath
-from click import group, option
-from yaml import dump as dump_yaml
-
-from litestar import Litestar
-from litestar._openapi.typescript_converter.converter import (
- convert_openapi_to_typescript,
-)
-from litestar.cli._utils import JSBEAUTIFIER_INSTALLED, LitestarCLIException, LitestarGroup
-from litestar.serialization import encode_json, get_serializer
-
-__all__ = ("generate_openapi_schema", "generate_typescript_specs", "schema_group")
-
-
-@group(cls=LitestarGroup, name="schema")
-def schema_group() -> None:
- """Manage server-side OpenAPI schemas."""
-
-
-def _generate_openapi_schema(app: Litestar, output: Path) -> None:
- """Generate an OpenAPI Schema."""
- serializer = get_serializer(app.type_encoders)
- if output.suffix in (".yml", ".yaml"):
- content = dump_yaml(
- msgspec.to_builtins(app.openapi_schema.to_schema(), enc_hook=serializer),
- default_flow_style=False,
- encoding="utf-8",
- )
- else:
- content = msgspec.json.format(
- encode_json(app.openapi_schema.to_schema(), serializer=serializer),
- indent=4,
- )
-
- try:
- output.write_bytes(content)
- except OSError as e: # pragma: no cover
- raise LitestarCLIException(f"failed to write schema to path {output}") from e
-
-
-@schema_group.command("openapi") # type: ignore[misc]
-@option(
- "--output",
- help="output file path",
- type=ClickPath(dir_okay=False, path_type=Path),
- default=Path("openapi_schema.json"),
- show_default=True,
-)
-def generate_openapi_schema(app: Litestar, output: Path) -> None:
- """Generate an OpenAPI Schema."""
- _generate_openapi_schema(app, output)
-
-
-@schema_group.command("typescript") # type: ignore[misc]
-@option(
- "--output",
- help="output file path",
- type=ClickPath(dir_okay=False, path_type=Path),
- default=Path("api-specs.ts"),
- show_default=True,
-)
-@option("--namespace", help="namespace to use for the typescript specs", type=str, default="API")
-def generate_typescript_specs(app: Litestar, output: Path, namespace: str) -> None:
- """Generate TypeScript specs from the OpenAPI schema."""
- if JSBEAUTIFIER_INSTALLED: # pragma: no cover
- from jsbeautifier import Beautifier
-
- beautifier = Beautifier()
- else:
- beautifier = None
- try:
- specs = convert_openapi_to_typescript(app.openapi_schema, namespace)
- # beautifier will be defined if JSBEAUTIFIER_INSTALLED is True
- specs_output = (
- beautifier.beautify(specs.write()) if JSBEAUTIFIER_INSTALLED and beautifier else specs.write() # pyright: ignore
- )
- output.write_text(specs_output)
- except OSError as e: # pragma: no cover
- raise LitestarCLIException(f"failed to write schema to path {output}") from e
diff --git a/venv/lib/python3.11/site-packages/litestar/cli/commands/sessions.py b/venv/lib/python3.11/site-packages/litestar/cli/commands/sessions.py
deleted file mode 100644
index f048dd1..0000000
--- a/venv/lib/python3.11/site-packages/litestar/cli/commands/sessions.py
+++ /dev/null
@@ -1,58 +0,0 @@
-from click import argument, group
-from rich.prompt import Confirm
-
-from litestar import Litestar
-from litestar.cli._utils import LitestarCLIException, LitestarGroup, console
-from litestar.middleware import DefineMiddleware
-from litestar.middleware.session import SessionMiddleware
-from litestar.middleware.session.server_side import ServerSideSessionBackend
-from litestar.utils import is_class_and_subclass
-
-__all__ = ("clear_sessions_command", "delete_session_command", "get_session_backend", "sessions_group")
-
-
-def get_session_backend(app: Litestar) -> ServerSideSessionBackend:
- """Get the session backend used by a ``Litestar`` app."""
- for middleware in app.middleware:
- if isinstance(middleware, DefineMiddleware):
- if not is_class_and_subclass(middleware.middleware, SessionMiddleware):
- continue
- backend = middleware.kwargs["backend"]
- if not isinstance(backend, ServerSideSessionBackend):
- raise LitestarCLIException("Only server-side backends are supported")
- return backend
- raise LitestarCLIException("Session middleware not installed")
-
-
-@group(cls=LitestarGroup, name="sessions")
-def sessions_group() -> None:
- """Manage server-side sessions."""
-
-
-@sessions_group.command("delete") # type: ignore[misc]
-@argument("session-id")
-def delete_session_command(session_id: str, app: Litestar) -> None:
- """Delete a specific session."""
- import anyio
-
- backend = get_session_backend(app)
- store = backend.config.get_store_from_app(app)
-
- if Confirm.ask(f"Delete session {session_id!r}?"):
- anyio.run(backend.delete, session_id, store)
- console.print(f"[green]Deleted session {session_id!r}")
-
-
-@sessions_group.command("clear") # type: ignore[misc]
-def clear_sessions_command(app: Litestar) -> None:
- """Delete all sessions."""
- import anyio
-
- backend = get_session_backend(app)
- store = backend.config.get_store_from_app(app)
- if not hasattr(store, "delete_all"):
- raise LitestarCLIException(f"{type(store)} does not support clearing all sessions")
-
- if Confirm.ask("[red]Delete all sessions?"):
- anyio.run(store.delete_all) # pyright: ignore
- console.print("[green]All active sessions deleted")
diff --git a/venv/lib/python3.11/site-packages/litestar/cli/main.py b/venv/lib/python3.11/site-packages/litestar/cli/main.py
deleted file mode 100644
index 32505f6..0000000
--- a/venv/lib/python3.11/site-packages/litestar/cli/main.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from __future__ import annotations
-
-from pathlib import Path
-
-from click import Context, group, option, pass_context
-from click import Path as ClickPath
-
-from ._utils import LitestarEnv, LitestarExtensionGroup
-from .commands import core, schema, sessions
-
-__all__ = ("litestar_group",)
-
-
-@group(cls=LitestarExtensionGroup, context_settings={"help_option_names": ["-h", "--help"]})
-@option("--app", "app_path", help="Module path to a Litestar application")
-@option(
- "--app-dir",
- help="Look for APP in the specified directory, by adding this to the PYTHONPATH. Defaults to the current working directory.",
- default=None,
- type=ClickPath(dir_okay=True, file_okay=False, path_type=Path),
- show_default=False,
-)
-@pass_context
-def litestar_group(ctx: Context, app_path: str | None, app_dir: Path | None = None) -> None:
- """Litestar CLI."""
- if ctx.obj is None: # env has not been loaded yet, so we can lazy load it
- ctx.obj = lambda: LitestarEnv.from_env(app_path, app_dir=app_dir)
-
-
-# add sub commands here
-
-litestar_group.add_command(core.info_command)
-litestar_group.add_command(core.run_command)
-litestar_group.add_command(core.routes_command)
-litestar_group.add_command(core.version_command)
-litestar_group.add_command(sessions.sessions_group)
-litestar_group.add_command(schema.schema_group)
diff --git a/venv/lib/python3.11/site-packages/litestar/concurrency.py b/venv/lib/python3.11/site-packages/litestar/concurrency.py
deleted file mode 100644
index 90eadbf..0000000
--- a/venv/lib/python3.11/site-packages/litestar/concurrency.py
+++ /dev/null
@@ -1,109 +0,0 @@
-from __future__ import annotations
-
-import asyncio
-import contextvars
-from functools import partial
-from typing import TYPE_CHECKING, Callable, TypeVar
-
-import sniffio
-from typing_extensions import ParamSpec
-
-if TYPE_CHECKING:
- from concurrent.futures import ThreadPoolExecutor
-
- import trio
-
-
-T = TypeVar("T")
-P = ParamSpec("P")
-
-
-__all__ = (
- "sync_to_thread",
- "set_asyncio_executor",
- "get_asyncio_executor",
- "set_trio_capacity_limiter",
- "get_trio_capacity_limiter",
-)
-
-
-class _State:
- EXECUTOR: ThreadPoolExecutor | None = None
- LIMITER: trio.CapacityLimiter | None = None
-
-
-async def _run_sync_asyncio(fn: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> T:
- ctx = contextvars.copy_context()
- bound_fn = partial(ctx.run, fn, *args, **kwargs)
- return await asyncio.get_running_loop().run_in_executor(get_asyncio_executor(), bound_fn) # pyright: ignore
-
-
-async def _run_sync_trio(fn: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> T:
- import trio
-
- return await trio.to_thread.run_sync(partial(fn, *args, **kwargs), limiter=get_trio_capacity_limiter())
-
-
-async def sync_to_thread(fn: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> T:
- """Run the synchronous callable ``fn`` asynchronously in a worker thread.
-
- When called from asyncio, uses :meth:`asyncio.loop.run_in_executor` to
- run the callable. No executor is specified by default so the current loop's executor
- is used. A specific executor can be set using
- :func:`~litestar.concurrency.set_asyncio_executor`. This does not affect the loop's
- default executor.
-
- When called from trio, uses :func:`trio.to_thread.run_sync` to run the callable. No
- capacity limiter is specified by default, but one can be set using
- :func:`~litestar.concurrency.set_trio_capacity_limiter`. This does not affect trio's
- default capacity limiter.
- """
- if (library := sniffio.current_async_library()) == "asyncio":
- return await _run_sync_asyncio(fn, *args, **kwargs)
-
- if library == "trio":
- return await _run_sync_trio(fn, *args, **kwargs)
-
- raise RuntimeError("Unsupported async library or not in async context")
-
-
-def set_asyncio_executor(executor: ThreadPoolExecutor | None) -> None:
- """Set the executor in which synchronous callables will be run within an asyncio
- context
- """
- try:
- sniffio.current_async_library()
- except sniffio.AsyncLibraryNotFoundError:
- pass
- else:
- raise RuntimeError("Cannot set executor from running loop")
-
- _State.EXECUTOR = executor
-
-
-def get_asyncio_executor() -> ThreadPoolExecutor | None:
- """Get the executor in which synchronous callables will be run within an asyncio
- context
- """
- return _State.EXECUTOR
-
-
-def set_trio_capacity_limiter(limiter: trio.CapacityLimiter | None) -> None:
- """Set the capacity limiter used when running synchronous callable within a trio
- context
- """
- try:
- sniffio.current_async_library()
- except sniffio.AsyncLibraryNotFoundError:
- pass
- else:
- raise RuntimeError("Cannot set limiter while in async context")
-
- _State.LIMITER = limiter
-
-
-def get_trio_capacity_limiter() -> trio.CapacityLimiter | None:
- """Get the capacity limiter used when running synchronous callable within a trio
- context
- """
- return _State.LIMITER
diff --git a/venv/lib/python3.11/site-packages/litestar/config/__init__.py b/venv/lib/python3.11/site-packages/litestar/config/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/venv/lib/python3.11/site-packages/litestar/config/__init__.py
+++ /dev/null
diff --git a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index c6ef8a3..0000000
--- a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/allowed_hosts.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/allowed_hosts.cpython-311.pyc
deleted file mode 100644
index f340305..0000000
--- a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/allowed_hosts.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/app.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/app.cpython-311.pyc
deleted file mode 100644
index a84a2f7..0000000
--- a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/app.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/compression.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/compression.cpython-311.pyc
deleted file mode 100644
index b6d9382..0000000
--- a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/compression.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/cors.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/cors.cpython-311.pyc
deleted file mode 100644
index 9965625..0000000
--- a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/cors.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/csrf.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/csrf.cpython-311.pyc
deleted file mode 100644
index 5056590..0000000
--- a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/csrf.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/response_cache.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/config/__pycache__/response_cache.cpython-311.pyc
deleted file mode 100644
index 0ca0cf9..0000000
--- a/venv/lib/python3.11/site-packages/litestar/config/__pycache__/response_cache.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/config/allowed_hosts.py b/venv/lib/python3.11/site-packages/litestar/config/allowed_hosts.py
deleted file mode 100644
index 4c8e6ac..0000000
--- a/venv/lib/python3.11/site-packages/litestar/config/allowed_hosts.py
+++ /dev/null
@@ -1,43 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass, field
-from typing import TYPE_CHECKING
-
-from litestar.exceptions import ImproperlyConfiguredException
-
-__all__ = ("AllowedHostsConfig",)
-
-
-if TYPE_CHECKING:
- from litestar.types import Scopes
-
-
-@dataclass
-class AllowedHostsConfig:
- """Configuration for allowed hosts protection.
-
- To enable allowed hosts protection, pass an instance of this class to the :class:`Litestar <litestar.app.Litestar>`
- constructor using the ``allowed_hosts`` key.
- """
-
- allowed_hosts: list[str] = field(default_factory=lambda: ["*"])
- """A list of trusted hosts.
-
- Use ``*.`` to allow all hosts, or prefix domains with ``*.`` to allow all sub domains.
- """
- exclude: str | list[str] | None = field(default=None)
- """A pattern or list of patterns to skip in the Allowed Hosts middleware."""
- exclude_opt_key: str | None = field(default=None)
- """An identifier to use on routes to disable hosts check for a particular route."""
- scopes: Scopes | None = field(default=None)
- """ASGI scopes processed by the middleware, if None both ``http`` and ``websocket`` will be processed."""
- www_redirect: bool = field(default=True)
- """A boolean dictating whether to redirect requests that start with ``www.`` and otherwise match a trusted host."""
-
- def __post_init__(self) -> None:
- """Ensure that the trusted hosts have correct domain wildcards."""
- for host in self.allowed_hosts:
- if host != "*" and "*" in host and not host.startswith("*."):
- raise ImproperlyConfiguredException(
- "domain wildcards can only appear in the beginning of the domain, e.g. ``*.example.com``"
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/config/app.py b/venv/lib/python3.11/site-packages/litestar/config/app.py
deleted file mode 100644
index 0acefb1..0000000
--- a/venv/lib/python3.11/site-packages/litestar/config/app.py
+++ /dev/null
@@ -1,223 +0,0 @@
-from __future__ import annotations
-
-import enum
-from dataclasses import dataclass, field
-from typing import TYPE_CHECKING, Any, Callable
-
-from litestar.config.allowed_hosts import AllowedHostsConfig
-from litestar.config.response_cache import ResponseCacheConfig
-from litestar.datastructures import State
-from litestar.events.emitter import SimpleEventEmitter
-from litestar.types.empty import Empty
-
-if TYPE_CHECKING:
- from contextlib import AbstractAsyncContextManager
-
- from litestar import Litestar, Response
- from litestar.config.compression import CompressionConfig
- from litestar.config.cors import CORSConfig
- from litestar.config.csrf import CSRFConfig
- from litestar.connection import Request, WebSocket
- from litestar.datastructures import CacheControlHeader, ETag
- from litestar.di import Provide
- from litestar.dto import AbstractDTO
- from litestar.events.emitter import BaseEventEmitterBackend
- from litestar.events.listener import EventListener
- from litestar.logging.config import BaseLoggingConfig
- from litestar.openapi.config import OpenAPIConfig
- from litestar.openapi.spec import SecurityRequirement
- from litestar.plugins import PluginProtocol
- from litestar.static_files.config import StaticFilesConfig
- from litestar.stores.base import Store
- from litestar.stores.registry import StoreRegistry
- from litestar.types import (
- AfterExceptionHookHandler,
- AfterRequestHookHandler,
- AfterResponseHookHandler,
- AnyCallable,
- BeforeMessageSendHookHandler,
- BeforeRequestHookHandler,
- ControllerRouterHandler,
- ExceptionHandlersMap,
- Guard,
- Middleware,
- ParametersMap,
- ResponseCookies,
- ResponseHeaders,
- TypeEncodersMap,
- )
- from litestar.types.callable_types import LifespanHook
- from litestar.types.composite_types import TypeDecodersSequence
- from litestar.types.empty import EmptyType
- from litestar.types.internal_types import TemplateConfigType
-
-
-__all__ = (
- "AppConfig",
- "ExperimentalFeatures",
-)
-
-
-@dataclass
-class AppConfig:
- """The parameters provided to the ``Litestar`` app are used to instantiate an instance, and then the instance is
- passed to any callbacks registered to ``on_app_init`` in the order they are provided.
-
- The final attribute values are used to instantiate the application object.
- """
-
- after_exception: list[AfterExceptionHookHandler] = field(default_factory=list)
- """An application level :class:`exception hook handler <.types.AfterExceptionHookHandler>` or list thereof.
-
- This hook is called after an exception occurs. In difference to exception handlers, it is not meant to return a
- response - only to process the exception (e.g. log it, send it to Sentry etc.).
- """
- after_request: AfterRequestHookHandler | None = field(default=None)
- """A sync or async function executed after the route handler function returned and the response object has been
- resolved.
-
- Receives the response object which may be any subclass of :class:`Response <.response.Response>`.
- """
- after_response: AfterResponseHookHandler | None = field(default=None)
- """A sync or async function called after the response has been awaited. It receives the
- :class:`Request <.connection.Request>` object and should not return any values.
- """
- allowed_hosts: list[str] | AllowedHostsConfig | None = field(default=None)
- """If set enables the builtin allowed hosts middleware."""
- before_request: BeforeRequestHookHandler | None = field(default=None)
- """A sync or async function called immediately before calling the route handler. Receives the
- :class:`Request <.connection.Request>` instance and any non-``None`` return value is used for the response,
- bypassing the route handler.
- """
- before_send: list[BeforeMessageSendHookHandler] = field(default_factory=list)
- """An application level :class:`before send hook handler <.types.BeforeMessageSendHookHandler>` or list thereof.
-
- This hook is called when the ASGI send function is called.
- """
- cache_control: CacheControlHeader | None = field(default=None)
- """A ``cache-control`` header of type :class:`CacheControlHeader <.datastructures.CacheControlHeader>` to add to
- route handlers of this app.
-
- Can be overridden by route handlers.
- """
- compression_config: CompressionConfig | None = field(default=None)
- """Configures compression behaviour of the application, this enabled a builtin or user defined Compression
- middleware.
- """
- cors_config: CORSConfig | None = field(default=None)
- """If set this enables the builtin CORS middleware."""
- csrf_config: CSRFConfig | None = field(default=None)
- """If set this enables the builtin CSRF middleware."""
- debug: bool = field(default=False)
- """If ``True``, app errors rendered as HTML with a stack trace."""
- dependencies: dict[str, Provide | AnyCallable] = field(default_factory=dict)
- """A string keyed dictionary of dependency :class:`Provider <.di.Provide>` instances."""
- dto: type[AbstractDTO] | None | EmptyType = field(default=Empty)
- """:class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and validation of request data."""
- etag: ETag | None = field(default=None)
- """An ``etag`` header of type :class:`ETag <.datastructures.ETag>` to add to route handlers of this app.
-
- Can be overridden by route handlers.
- """
- event_emitter_backend: type[BaseEventEmitterBackend] = field(default=SimpleEventEmitter)
- """A subclass of :class:`BaseEventEmitterBackend <.events.emitter.BaseEventEmitterBackend>`."""
- exception_handlers: ExceptionHandlersMap = field(default_factory=dict)
- """A dictionary that maps handler functions to status codes and/or exception types."""
- guards: list[Guard] = field(default_factory=list)
- """A list of :class:`Guard <.types.Guard>` callables."""
- include_in_schema: bool | EmptyType = field(default=Empty)
- """A boolean flag dictating whether the route handler should be documented in the OpenAPI schema"""
- lifespan: list[Callable[[Litestar], AbstractAsyncContextManager] | AbstractAsyncContextManager] = field(
- default_factory=list
- )
- """A list of callables returning async context managers, wrapping the lifespan of the ASGI application"""
- listeners: list[EventListener] = field(default_factory=list)
- """A list of :class:`EventListener <.events.listener.EventListener>`."""
- logging_config: BaseLoggingConfig | None = field(default=None)
- """An instance of :class:`BaseLoggingConfig <.logging.config.BaseLoggingConfig>` subclass."""
- middleware: list[Middleware] = field(default_factory=list)
- """A list of :class:`Middleware <.types.Middleware>`."""
- on_shutdown: list[LifespanHook] = field(default_factory=list)
- """A list of :class:`LifespanHook <.types.LifespanHook>` called during application shutdown."""
- on_startup: list[LifespanHook] = field(default_factory=list)
- """A list of :class:`LifespanHook <.types.LifespanHook>` called during application startup."""
- openapi_config: OpenAPIConfig | None = field(default=None)
- """Defaults to :data:`DEFAULT_OPENAPI_CONFIG <litestar.app.DEFAULT_OPENAPI_CONFIG>`"""
- opt: dict[str, Any] = field(default_factory=dict)
- """A string keyed dictionary of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or
- wherever you have access to :class:`Request <.connection.Request>` or :class:`ASGI Scope <litestar.types.Scope>`.
-
- Can be overridden by routers and router handlers.
- """
- parameters: ParametersMap = field(default_factory=dict)
- """A mapping of :class:`Parameter <.params.Parameter>` definitions available to all application paths."""
- pdb_on_exception: bool = field(default=False)
- """Drop into the PDB on an exception"""
- plugins: list[PluginProtocol] = field(default_factory=list)
- """List of :class:`SerializationPluginProtocol <.plugins.SerializationPluginProtocol>`."""
- request_class: type[Request] | None = field(default=None)
- """An optional subclass of :class:`Request <.connection.Request>` to use for http connections."""
- response_class: type[Response] | None = field(default=None)
- """A custom subclass of :class:`Response <.response.Response>` to be used as the app's default response."""
- response_cookies: ResponseCookies = field(default_factory=list)
- """A list of :class:`Cookie <.datastructures.Cookie>`."""
- response_headers: ResponseHeaders = field(default_factory=list)
- """A string keyed dictionary mapping :class:`ResponseHeader <.datastructures.ResponseHeader>`."""
- response_cache_config: ResponseCacheConfig = field(default_factory=ResponseCacheConfig)
- """Configures caching behavior of the application."""
- return_dto: type[AbstractDTO] | None | EmptyType = field(default=Empty)
- """:class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing outbound response
- data.
- """
- route_handlers: list[ControllerRouterHandler] = field(default_factory=list)
- """A required list of route handlers, which can include instances of :class:`Router <.router.Router>`,
- subclasses of :class:`Controller <.controller.Controller>` or any function decorated by the route handler
- decorators.
- """
- security: list[SecurityRequirement] = field(default_factory=list)
- """A list of dictionaries that will be added to the schema of all route handlers in the application. See
- :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>` for details.
- """
- signature_namespace: dict[str, Any] = field(default_factory=dict)
- """A mapping of names to types for use in forward reference resolution during signature modeling."""
- signature_types: list[Any] = field(default_factory=list)
- """A sequence of types for use in forward reference resolution during signature modeling.
-
- These types will be added to the signature namespace using their ``__name__`` attribute.
- """
- state: State = field(default_factory=State)
- """A :class:`State` <.datastructures.State>` instance holding application state."""
- static_files_config: list[StaticFilesConfig] = field(default_factory=list)
- """An instance or list of :class:`StaticFilesConfig <.static_files.StaticFilesConfig>`."""
- stores: StoreRegistry | dict[str, Store] | None = None
- """Central registry of :class:`Store <.stores.base.Store>` to be made available and be used throughout the
- application. Can be either a dictionary mapping strings to :class:`Store <.stores.base.Store>` instances, or an
- instance of :class:`StoreRegistry <.stores.registry.StoreRegistry>`.
- """
- tags: list[str] = field(default_factory=list)
- """A list of string tags that will be appended to the schema of all route handlers under the application."""
- template_config: TemplateConfigType | None = field(default=None)
- """An instance of :class:`TemplateConfig <.template.TemplateConfig>`."""
- type_decoders: TypeDecodersSequence | None = field(default=None)
- """A sequence of tuples, each composed of a predicate testing for type identity and a msgspec hook for deserialization."""
- type_encoders: TypeEncodersMap | None = field(default=None)
- """A mapping of types to callables that transform them into types supported for serialization."""
- websocket_class: type[WebSocket] | None = field(default=None)
- """An optional subclass of :class:`WebSocket <.connection.WebSocket>` to use for websocket connections."""
- multipart_form_part_limit: int = field(default=1000)
- """The maximal number of allowed parts in a multipart/formdata request. This limit is intended to protect from
- DoS attacks."""
- experimental_features: list[ExperimentalFeatures] | None = None
-
- def __post_init__(self) -> None:
- """Normalize the allowed hosts to be a config or None.
-
- Returns:
- Optional config.
- """
- if self.allowed_hosts and isinstance(self.allowed_hosts, list):
- self.allowed_hosts = AllowedHostsConfig(allowed_hosts=self.allowed_hosts)
-
-
-class ExperimentalFeatures(str, enum.Enum):
- DTO_CODEGEN = "DTO_CODEGEN"
diff --git a/venv/lib/python3.11/site-packages/litestar/config/compression.py b/venv/lib/python3.11/site-packages/litestar/config/compression.py
deleted file mode 100644
index c339329..0000000
--- a/venv/lib/python3.11/site-packages/litestar/config/compression.py
+++ /dev/null
@@ -1,83 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass, field
-from typing import TYPE_CHECKING, Any, Literal
-
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.middleware.compression import CompressionMiddleware
-from litestar.middleware.compression.gzip_facade import GzipCompression
-
-if TYPE_CHECKING:
- from litestar.middleware.compression.facade import CompressionFacade
-
-__all__ = ("CompressionConfig",)
-
-
-@dataclass
-class CompressionConfig:
- """Configuration for response compression.
-
- To enable response compression, pass an instance of this class to the :class:`Litestar <.app.Litestar>` constructor
- using the ``compression_config`` key.
- """
-
- backend: Literal["gzip", "brotli"] | str
- """The backend to use.
-
- If the value given is `gzip` or `brotli`, then the builtin gzip and brotli compression is used.
- """
- minimum_size: int = field(default=500)
- """Minimum response size (bytes) to enable compression, affects all backends."""
- gzip_compress_level: int = field(default=9)
- """Range ``[0-9]``, see :doc:`python:library/gzip`."""
- brotli_quality: int = field(default=5)
- """Range ``[0-11]``, Controls the compression-speed vs compression-density tradeoff.
-
- The higher the quality, the slower the compression.
- """
- brotli_mode: Literal["generic", "text", "font"] = "text"
- """``MODE_GENERIC``, ``MODE_TEXT`` (for UTF-8 format text input, default) or ``MODE_FONT`` (for WOFF 2.0)."""
- brotli_lgwin: int = field(default=22)
- """Base 2 logarithm of size.
-
- Range is 10 to 24. Defaults to 22.
- """
- brotli_lgblock: Literal[0, 16, 17, 18, 19, 20, 21, 22, 23, 24] = 0
- """Base 2 logarithm of the maximum input block size.
-
- Range is ``16`` to ``24``. If set to ``0``, the value will be set based on the quality. Defaults to ``0``.
- """
- brotli_gzip_fallback: bool = True
- """Use GZIP if Brotli is not supported."""
- middleware_class: type[CompressionMiddleware] = CompressionMiddleware
- """Middleware class to use, should be a subclass of :class:`CompressionMiddleware`."""
- exclude: str | list[str] | None = None
- """A pattern or list of patterns to skip in the compression middleware."""
- exclude_opt_key: str | None = None
- """An identifier to use on routes to disable compression for a particular route."""
- compression_facade: type[CompressionFacade] = GzipCompression
- """The compression facade to use for the actual compression."""
- backend_config: Any = None
- """Configuration specific to the backend."""
- gzip_fallback: bool = True
- """Use GZIP as a fallback if the provided backend is not supported by the client."""
-
- def __post_init__(self) -> None:
- if self.minimum_size <= 0:
- raise ImproperlyConfiguredException("minimum_size must be greater than 0")
-
- if self.backend == "gzip":
- if self.gzip_compress_level < 0 or self.gzip_compress_level > 9:
- raise ImproperlyConfiguredException("gzip_compress_level must be a value between 0 and 9")
- elif self.backend == "brotli":
- # Brotli is not guaranteed to be installed.
- from litestar.middleware.compression.brotli_facade import BrotliCompression
-
- if self.brotli_quality < 0 or self.brotli_quality > 11:
- raise ImproperlyConfiguredException("brotli_quality must be a value between 0 and 11")
-
- if self.brotli_lgwin < 10 or self.brotli_lgwin > 24:
- raise ImproperlyConfiguredException("brotli_lgwin must be a value between 10 and 24")
-
- self.gzip_fallback = self.brotli_gzip_fallback
- self.compression_facade = BrotliCompression
diff --git a/venv/lib/python3.11/site-packages/litestar/config/cors.py b/venv/lib/python3.11/site-packages/litestar/config/cors.py
deleted file mode 100644
index d3e2ccf..0000000
--- a/venv/lib/python3.11/site-packages/litestar/config/cors.py
+++ /dev/null
@@ -1,147 +0,0 @@
-from __future__ import annotations
-
-import re
-from dataclasses import dataclass, field
-from functools import cached_property
-from typing import TYPE_CHECKING, Literal, Pattern
-
-from litestar.constants import DEFAULT_ALLOWED_CORS_HEADERS
-
-__all__ = ("CORSConfig",)
-
-
-if TYPE_CHECKING:
- from litestar.types import Method
-
-
-@dataclass
-class CORSConfig:
- """Configuration for CORS (Cross-Origin Resource Sharing).
-
- To enable CORS, pass an instance of this class to the :class:`Litestar <litestar.app.Litestar>` constructor using the
- 'cors_config' key.
- """
-
- allow_origins: list[str] = field(default_factory=lambda: ["*"])
- """List of origins that are allowed.
-
- Can use '*' in any component of the path, e.g. 'domain.*'. Sets the 'Access-Control-Allow-Origin' header.
- """
- allow_methods: list[Literal["*"] | Method] = field(default_factory=lambda: ["*"])
- """List of allowed HTTP methods.
-
- Sets the 'Access-Control-Allow-Methods' header.
- """
- allow_headers: list[str] = field(default_factory=lambda: ["*"])
- """List of allowed headers.
-
- Sets the 'Access-Control-Allow-Headers' header.
- """
- allow_credentials: bool = field(default=False)
- """Boolean dictating whether or not to set the 'Access-Control-Allow-Credentials' header."""
- allow_origin_regex: str | None = field(default=None)
- """Regex to match origins against."""
- expose_headers: list[str] = field(default_factory=list)
- """List of headers that are exposed via the 'Access-Control-Expose-Headers' header."""
- max_age: int = field(default=600)
- """Response caching TTL in seconds, defaults to 600.
-
- Sets the 'Access-Control-Max-Age' header.
- """
-
- def __post_init__(self) -> None:
- self.allow_headers = [v.lower() for v in self.allow_headers]
-
- @cached_property
- def allowed_origins_regex(self) -> Pattern[str]:
- """Get or create a compiled regex for allowed origins.
-
- Returns:
- A compiled regex of the allowed path.
- """
- origins = self.allow_origins
- if self.allow_origin_regex:
- origins.append(self.allow_origin_regex)
- return re.compile("|".join([origin.replace("*.", r".*\.") for origin in origins]))
-
- @cached_property
- def is_allow_all_origins(self) -> bool:
- """Get a cached boolean flag dictating whether all origins are allowed.
-
- Returns:
- Boolean dictating whether all origins are allowed.
- """
- return "*" in self.allow_origins
-
- @cached_property
- def is_allow_all_methods(self) -> bool:
- """Get a cached boolean flag dictating whether all methods are allowed.
-
- Returns:
- Boolean dictating whether all methods are allowed.
- """
- return "*" in self.allow_methods
-
- @cached_property
- def is_allow_all_headers(self) -> bool:
- """Get a cached boolean flag dictating whether all headers are allowed.
-
- Returns:
- Boolean dictating whether all headers are allowed.
- """
- return "*" in self.allow_headers
-
- @cached_property
- def preflight_headers(self) -> dict[str, str]:
- """Get cached pre-flight headers.
-
- Returns:
- A dictionary of headers to set on the response object.
- """
- headers: dict[str, str] = {"Access-Control-Max-Age": str(self.max_age)}
- if self.is_allow_all_origins:
- headers["Access-Control-Allow-Origin"] = "*"
- else:
- headers["Vary"] = "Origin"
- if self.allow_credentials:
- headers["Access-Control-Allow-Credentials"] = str(self.allow_credentials).lower()
- if not self.is_allow_all_headers:
- headers["Access-Control-Allow-Headers"] = ", ".join(
- sorted(set(self.allow_headers) | DEFAULT_ALLOWED_CORS_HEADERS) # pyright: ignore
- )
- if self.allow_methods:
- headers["Access-Control-Allow-Methods"] = ", ".join(
- sorted(
- {"DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"}
- if self.is_allow_all_methods
- else set(self.allow_methods)
- )
- )
- return headers
-
- @cached_property
- def simple_headers(self) -> dict[str, str]:
- """Get cached simple headers.
-
- Returns:
- A dictionary of headers to set on the response object.
- """
- simple_headers = {}
- if self.is_allow_all_origins:
- simple_headers["Access-Control-Allow-Origin"] = "*"
- if self.allow_credentials:
- simple_headers["Access-Control-Allow-Credentials"] = "true"
- if self.expose_headers:
- simple_headers["Access-Control-Expose-Headers"] = ", ".join(sorted(set(self.expose_headers)))
- return simple_headers
-
- def is_origin_allowed(self, origin: str) -> bool:
- """Check whether a given origin is allowed.
-
- Args:
- origin: An origin header value.
-
- Returns:
- Boolean determining whether an origin is allowed.
- """
- return bool(self.is_allow_all_origins or self.allowed_origins_regex.fullmatch(origin))
diff --git a/venv/lib/python3.11/site-packages/litestar/config/csrf.py b/venv/lib/python3.11/site-packages/litestar/config/csrf.py
deleted file mode 100644
index 5094a5b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/config/csrf.py
+++ /dev/null
@@ -1,42 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass, field
-from typing import TYPE_CHECKING, Literal
-
-__all__ = ("CSRFConfig",)
-
-
-if TYPE_CHECKING:
- from litestar.types import Method
-
-
-@dataclass
-class CSRFConfig:
- """Configuration for CSRF (Cross Site Request Forgery) protection.
-
- To enable CSRF protection, pass an instance of this class to the :class:`Litestar <litestar.app.Litestar>` constructor using
- the 'csrf_config' key.
- """
-
- secret: str
- """A string that is used to create an HMAC to sign the CSRF token."""
- cookie_name: str = field(default="csrftoken")
- """The CSRF cookie name."""
- cookie_path: str = field(default="/")
- """The CSRF cookie path."""
- header_name: str = field(default="x-csrftoken")
- """The header that will be expected in each request."""
- cookie_secure: bool = field(default=False)
- """A boolean value indicating whether to set the ``Secure`` attribute on the cookie."""
- cookie_httponly: bool = field(default=False)
- """A boolean value indicating whether to set the ``HttpOnly`` attribute on the cookie."""
- cookie_samesite: Literal["lax", "strict", "none"] = field(default="lax")
- """The value to set in the ``SameSite`` attribute of the cookie."""
- cookie_domain: str | None = field(default=None)
- """Specifies which hosts can receive the cookie."""
- safe_methods: set[Method] = field(default_factory=lambda: {"GET", "HEAD"})
- """A set of "safe methods" that can set the cookie."""
- exclude: str | list[str] | None = field(default=None)
- """A pattern or list of patterns to skip in the CSRF middleware."""
- exclude_from_csrf_key: str = "exclude_from_csrf"
- """An identifier to use on routes to disable CSRF for a particular route."""
diff --git a/venv/lib/python3.11/site-packages/litestar/config/response_cache.py b/venv/lib/python3.11/site-packages/litestar/config/response_cache.py
deleted file mode 100644
index 4f1dfe9..0000000
--- a/venv/lib/python3.11/site-packages/litestar/config/response_cache.py
+++ /dev/null
@@ -1,81 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass, field
-from typing import TYPE_CHECKING, Any, Callable, final
-from urllib.parse import urlencode
-
-from litestar.status_codes import (
- HTTP_200_OK,
- HTTP_300_MULTIPLE_CHOICES,
- HTTP_301_MOVED_PERMANENTLY,
- HTTP_308_PERMANENT_REDIRECT,
-)
-
-if TYPE_CHECKING:
- from litestar import Litestar
- from litestar.connection import Request
- from litestar.stores.base import Store
- from litestar.types import CacheKeyBuilder, HTTPScope
-
-__all__ = ("ResponseCacheConfig", "default_cache_key_builder", "CACHE_FOREVER")
-
-
-@final
-class CACHE_FOREVER: # noqa: N801
- """Sentinel value indicating that a cached response should be stored without an expiration, explicitly skipping the
- default expiration
- """
-
-
-def default_cache_key_builder(request: Request[Any, Any, Any]) -> str:
- """Given a request object, returns a cache key by combining
- the request method and path with the sorted query params.
-
- Args:
- request: request used to generate cache key.
-
- Returns:
- A combination of url path and query parameters
- """
- query_params: list[tuple[str, Any]] = list(request.query_params.dict().items())
- query_params.sort(key=lambda x: x[0])
- return request.method + request.url.path + urlencode(query_params, doseq=True)
-
-
-def default_do_cache_predicate(_: HTTPScope, status_code: int) -> bool:
- """Given a status code, returns a boolean indicating whether the response should be cached.
-
- Args:
- _: ASGI scope.
- status_code: status code of the response.
-
- Returns:
- A boolean indicating whether the response should be cached.
- """
- return HTTP_200_OK <= status_code < HTTP_300_MULTIPLE_CHOICES or status_code in (
- HTTP_301_MOVED_PERMANENTLY,
- HTTP_308_PERMANENT_REDIRECT,
- )
-
-
-@dataclass
-class ResponseCacheConfig:
- """Configuration for response caching.
-
- To enable response caching, pass an instance of this class to :class:`Litestar <.app.Litestar>` using the
- ``response_cache_config`` key.
- """
-
- default_expiration: int | None = 60
- """Default cache expiration in seconds used when a route handler is configured with ``cache=True``."""
- key_builder: CacheKeyBuilder = field(default=default_cache_key_builder)
- """:class:`CacheKeyBuilder <.types.CacheKeyBuilder>`. Defaults to :func:`default_cache_key_builder`."""
- store: str = "response_cache"
- """Name of the :class:`Store <.stores.base.Store>` to use."""
- cache_response_filter: Callable[[HTTPScope, int], bool] = field(default=default_do_cache_predicate)
- """A callable that receives connection scope and a status code, and returns a boolean indicating whether the
- response should be cached."""
-
- def get_store_from_app(self, app: Litestar) -> Store:
- """Get the store defined in :attr:`store` from an :class:`Litestar <.app.Litestar>` instance."""
- return app.stores.get(self.store)
diff --git a/venv/lib/python3.11/site-packages/litestar/connection/__init__.py b/venv/lib/python3.11/site-packages/litestar/connection/__init__.py
deleted file mode 100644
index 6922e79..0000000
--- a/venv/lib/python3.11/site-packages/litestar/connection/__init__.py
+++ /dev/null
@@ -1,37 +0,0 @@
-"""Some code in this module was adapted from https://github.com/encode/starlette/blob/master/starlette/requests.py and
-https://github.com/encode/starlette/blob/master/starlette/websockets.py.
-
-Copyright © 2018, [Encode OSS Ltd](https://www.encode.io/).
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""
-
-from litestar.connection.base import ASGIConnection
-from litestar.connection.request import Request
-from litestar.connection.websocket import WebSocket
-
-__all__ = ("ASGIConnection", "Request", "WebSocket")
diff --git a/venv/lib/python3.11/site-packages/litestar/connection/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/connection/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 89cb4db..0000000
--- a/venv/lib/python3.11/site-packages/litestar/connection/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/connection/__pycache__/base.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/connection/__pycache__/base.cpython-311.pyc
deleted file mode 100644
index f1eff74..0000000
--- a/venv/lib/python3.11/site-packages/litestar/connection/__pycache__/base.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/connection/__pycache__/request.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/connection/__pycache__/request.cpython-311.pyc
deleted file mode 100644
index f047a18..0000000
--- a/venv/lib/python3.11/site-packages/litestar/connection/__pycache__/request.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/connection/__pycache__/websocket.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/connection/__pycache__/websocket.cpython-311.pyc
deleted file mode 100644
index 49e294c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/connection/__pycache__/websocket.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/connection/base.py b/venv/lib/python3.11/site-packages/litestar/connection/base.py
deleted file mode 100644
index d14c662..0000000
--- a/venv/lib/python3.11/site-packages/litestar/connection/base.py
+++ /dev/null
@@ -1,345 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any, Generic, TypeVar, cast
-
-from litestar._parsers import parse_cookie_string, parse_query_string
-from litestar.datastructures.headers import Headers
-from litestar.datastructures.multi_dicts import MultiDict
-from litestar.datastructures.state import State
-from litestar.datastructures.url import URL, Address, make_absolute_url
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.types.empty import Empty
-from litestar.utils.empty import value_or_default
-from litestar.utils.scope.state import ScopeState
-
-if TYPE_CHECKING:
- from typing import NoReturn
-
- from litestar.app import Litestar
- from litestar.types import DataContainerType, EmptyType
- from litestar.types.asgi_types import Message, Receive, Scope, Send
- from litestar.types.protocols import Logger
-
-__all__ = ("ASGIConnection", "empty_receive", "empty_send")
-
-UserT = TypeVar("UserT")
-AuthT = TypeVar("AuthT")
-HandlerT = TypeVar("HandlerT")
-StateT = TypeVar("StateT", bound=State)
-
-
-async def empty_receive() -> NoReturn: # pragma: no cover
- """Raise a ``RuntimeError``.
-
- Serves as a placeholder ``send`` function.
-
- Raises:
- RuntimeError
- """
- raise RuntimeError()
-
-
-async def empty_send(_: Message) -> NoReturn: # pragma: no cover
- """Raise a ``RuntimeError``.
-
- Serves as a placeholder ``send`` function.
-
- Args:
- _: An ASGI message
-
- Raises:
- RuntimeError
- """
- raise RuntimeError()
-
-
-class ASGIConnection(Generic[HandlerT, UserT, AuthT, StateT]):
- """The base ASGI connection container."""
-
- __slots__ = (
- "scope",
- "receive",
- "send",
- "_base_url",
- "_url",
- "_parsed_query",
- "_cookies",
- "_server_extensions",
- "_connection_state",
- )
-
- scope: Scope
- """The ASGI scope attached to the connection."""
- receive: Receive
- """The ASGI receive function."""
- send: Send
- """The ASGI send function."""
-
- def __init__(self, scope: Scope, receive: Receive = empty_receive, send: Send = empty_send) -> None:
- """Initialize ``ASGIConnection``.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
- """
- self.scope = scope
- self.receive = receive
- self.send = send
- self._connection_state = ScopeState.from_scope(scope)
- self._base_url: URL | EmptyType = Empty
- self._url: URL | EmptyType = Empty
- self._parsed_query: tuple[tuple[str, str], ...] | EmptyType = Empty
- self._cookies: dict[str, str] | EmptyType = Empty
- self._server_extensions = scope.get("extensions") or {} # extensions may be None
-
- @property
- def app(self) -> Litestar:
- """Return the ``app`` for this connection.
-
- Returns:
- The :class:`Litestar <litestar.app.Litestar>` application instance
- """
- return self.scope["app"]
-
- @property
- def route_handler(self) -> HandlerT:
- """Return the ``route_handler`` for this connection.
-
- Returns:
- The target route handler instance.
- """
- return cast("HandlerT", self.scope["route_handler"])
-
- @property
- def state(self) -> StateT:
- """Return the ``State`` of this connection.
-
- Returns:
- A State instance constructed from the scope["state"] value.
- """
- return cast("StateT", State(self.scope.get("state")))
-
- @property
- def url(self) -> URL:
- """Return the URL of this connection's ``Scope``.
-
- Returns:
- A URL instance constructed from the request's scope.
- """
- if self._url is Empty:
- if (url := self._connection_state.url) is not Empty:
- self._url = url
- else:
- self._connection_state.url = self._url = URL.from_scope(self.scope)
-
- return self._url
-
- @property
- def base_url(self) -> URL:
- """Return the base URL of this connection's ``Scope``.
-
- Returns:
- A URL instance constructed from the request's scope, representing only the base part
- (host + domain + prefix) of the request.
- """
- if self._base_url is Empty:
- if (base_url := self._connection_state.base_url) is not Empty:
- self._base_url = base_url
- else:
- scope = cast(
- "Scope",
- {
- **self.scope,
- "path": "/",
- "query_string": b"",
- "root_path": self.scope.get("app_root_path") or self.scope.get("root_path", ""),
- },
- )
- self._connection_state.base_url = self._base_url = URL.from_scope(scope)
- return self._base_url
-
- @property
- def headers(self) -> Headers:
- """Return the headers of this connection's ``Scope``.
-
- Returns:
- A Headers instance with the request's scope["headers"] value.
- """
- return Headers.from_scope(self.scope)
-
- @property
- def query_params(self) -> MultiDict[Any]:
- """Return the query parameters of this connection's ``Scope``.
-
- Returns:
- A normalized dict of query parameters. Multiple values for the same key are returned as a list.
- """
- if self._parsed_query is Empty:
- if (parsed_query := self._connection_state.parsed_query) is not Empty:
- self._parsed_query = parsed_query
- else:
- self._connection_state.parsed_query = self._parsed_query = parse_query_string(
- self.scope.get("query_string", b"")
- )
- return MultiDict(self._parsed_query)
-
- @property
- def path_params(self) -> dict[str, Any]:
- """Return the ``path_params`` of this connection's ``Scope``.
-
- Returns:
- A string keyed dictionary of path parameter values.
- """
- return self.scope["path_params"]
-
- @property
- def cookies(self) -> dict[str, str]:
- """Return the ``cookies`` of this connection's ``Scope``.
-
- Returns:
- Returns any cookies stored in the header as a parsed dictionary.
- """
- if self._cookies is Empty:
- if (cookies := self._connection_state.cookies) is not Empty:
- self._cookies = cookies
- else:
- self._connection_state.cookies = self._cookies = (
- parse_cookie_string(cookie_header) if (cookie_header := self.headers.get("cookie")) else {}
- )
- return self._cookies
-
- @property
- def client(self) -> Address | None:
- """Return the ``client`` data of this connection's ``Scope``.
-
- Returns:
- A two tuple of the host name and port number.
- """
- client = self.scope.get("client")
- return Address(*client) if client else None
-
- @property
- def auth(self) -> AuthT:
- """Return the ``auth`` data of this connection's ``Scope``.
-
- Raises:
- ImproperlyConfiguredException: If ``auth`` is not set in scope via an ``AuthMiddleware``, raises an exception
-
- Returns:
- A type correlating to the generic variable Auth.
- """
- if "auth" not in self.scope:
- raise ImproperlyConfiguredException("'auth' is not defined in scope, install an AuthMiddleware to set it")
-
- return cast("AuthT", self.scope["auth"])
-
- @property
- def user(self) -> UserT:
- """Return the ``user`` data of this connection's ``Scope``.
-
- Raises:
- ImproperlyConfiguredException: If ``user`` is not set in scope via an ``AuthMiddleware``, raises an exception
-
- Returns:
- A type correlating to the generic variable User.
- """
- if "user" not in self.scope:
- raise ImproperlyConfiguredException("'user' is not defined in scope, install an AuthMiddleware to set it")
-
- return cast("UserT", self.scope["user"])
-
- @property
- def session(self) -> dict[str, Any]:
- """Return the session for this connection if a session was previously set in the ``Scope``
-
- Returns:
- A dictionary representing the session value - if existing.
-
- Raises:
- ImproperlyConfiguredException: if session is not set in scope.
- """
- if "session" not in self.scope:
- raise ImproperlyConfiguredException(
- "'session' is not defined in scope, install a SessionMiddleware to set it"
- )
-
- return cast("dict[str, Any]", self.scope["session"])
-
- @property
- def logger(self) -> Logger:
- """Return the ``Logger`` instance for this connection.
-
- Returns:
- A ``Logger`` instance.
-
- Raises:
- ImproperlyConfiguredException: if ``log_config`` has not been passed to the Litestar constructor.
- """
- return self.app.get_logger()
-
- def set_session(self, value: dict[str, Any] | DataContainerType | EmptyType) -> None:
- """Set the session in the connection's ``Scope``.
-
- If the :class:`SessionMiddleware <.middleware.session.base.SessionMiddleware>` is enabled, the session will be added
- to the response as a cookie header.
-
- Args:
- value: Dictionary or pydantic model instance for the session data.
-
- Returns:
- None
- """
- self.scope["session"] = value
-
- def clear_session(self) -> None:
- """Remove the session from the connection's ``Scope``.
-
- If the :class:`Litestar SessionMiddleware <.middleware.session.base.SessionMiddleware>` is enabled, this will cause
- the session data to be cleared.
-
- Returns:
- None.
- """
- self.scope["session"] = Empty
- self._connection_state.session_id = Empty
-
- def get_session_id(self) -> str | None:
- return value_or_default(value=self._connection_state.session_id, default=None)
-
- def url_for(self, name: str, **path_parameters: Any) -> str:
- """Return the url for a given route handler name.
-
- Args:
- name: The ``name`` of the request route handler.
- **path_parameters: Values for path parameters in the route
-
- Raises:
- NoRouteMatchFoundException: If route with ``name`` does not exist, path parameters are missing or have a
- wrong type.
-
- Returns:
- A string representing the absolute url of the route handler.
- """
- litestar_instance = self.scope["app"]
- url_path = litestar_instance.route_reverse(name, **path_parameters)
-
- return make_absolute_url(url_path, self.base_url)
-
- def url_for_static_asset(self, name: str, file_path: str) -> str:
- """Receives a static files handler name, an asset file path and returns resolved absolute url to the asset.
-
- Args:
- name: A static handler unique name.
- file_path: a string containing path to an asset.
-
- Raises:
- NoRouteMatchFoundException: If static files handler with ``name`` does not exist.
-
- Returns:
- A string representing absolute url to the asset.
- """
- litestar_instance = self.scope["app"]
- url_path = litestar_instance.url_for_static_asset(name, file_path)
-
- return make_absolute_url(url_path, self.base_url)
diff --git a/venv/lib/python3.11/site-packages/litestar/connection/request.py b/venv/lib/python3.11/site-packages/litestar/connection/request.py
deleted file mode 100644
index 254c315..0000000
--- a/venv/lib/python3.11/site-packages/litestar/connection/request.py
+++ /dev/null
@@ -1,263 +0,0 @@
-from __future__ import annotations
-
-import warnings
-from typing import TYPE_CHECKING, Any, AsyncGenerator, Generic
-
-from litestar._multipart import parse_content_header, parse_multipart_form
-from litestar._parsers import parse_url_encoded_form_data
-from litestar.connection.base import (
- ASGIConnection,
- AuthT,
- StateT,
- UserT,
- empty_receive,
- empty_send,
-)
-from litestar.datastructures.headers import Accept
-from litestar.datastructures.multi_dicts import FormMultiDict
-from litestar.enums import ASGIExtension, RequestEncodingType
-from litestar.exceptions import (
- InternalServerException,
- LitestarException,
- LitestarWarning,
-)
-from litestar.serialization import decode_json, decode_msgpack
-from litestar.types import Empty
-
-__all__ = ("Request",)
-
-
-if TYPE_CHECKING:
- from litestar.handlers.http_handlers import HTTPRouteHandler # noqa: F401
- from litestar.types.asgi_types import HTTPScope, Method, Receive, Scope, Send
- from litestar.types.empty import EmptyType
-
-
-SERVER_PUSH_HEADERS = {
- "accept",
- "accept-encoding",
- "accept-language",
- "cache-control",
- "user-agent",
-}
-
-
-class Request(Generic[UserT, AuthT, StateT], ASGIConnection["HTTPRouteHandler", UserT, AuthT, StateT]):
- """The Litestar Request class."""
-
- __slots__ = (
- "_json",
- "_form",
- "_body",
- "_msgpack",
- "_content_type",
- "_accept",
- "is_connected",
- "supports_push_promise",
- )
-
- scope: HTTPScope # pyright: ignore
- """The ASGI scope attached to the connection."""
- receive: Receive
- """The ASGI receive function."""
- send: Send
- """The ASGI send function."""
-
- def __init__(self, scope: Scope, receive: Receive = empty_receive, send: Send = empty_send) -> None:
- """Initialize ``Request``.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
- """
- super().__init__(scope, receive, send)
- self.is_connected: bool = True
- self._body: bytes | EmptyType = Empty
- self._form: dict[str, str | list[str]] | EmptyType = Empty
- self._json: Any = Empty
- self._msgpack: Any = Empty
- self._content_type: tuple[str, dict[str, str]] | EmptyType = Empty
- self._accept: Accept | EmptyType = Empty
- self.supports_push_promise = ASGIExtension.SERVER_PUSH in self._server_extensions
-
- @property
- def method(self) -> Method:
- """Return the request method.
-
- Returns:
- The request :class:`Method <litestar.types.Method>`
- """
- return self.scope["method"]
-
- @property
- def content_type(self) -> tuple[str, dict[str, str]]:
- """Parse the request's 'Content-Type' header, returning the header value and any options as a dictionary.
-
- Returns:
- A tuple with the parsed value and a dictionary containing any options send in it.
- """
- if self._content_type is Empty:
- if (content_type := self._connection_state.content_type) is not Empty:
- self._content_type = content_type
- else:
- self._content_type = self._connection_state.content_type = parse_content_header(
- self.headers.get("Content-Type", "")
- )
- return self._content_type
-
- @property
- def accept(self) -> Accept:
- """Parse the request's 'Accept' header, returning an :class:`Accept <litestar.datastructures.headers.Accept>` instance.
-
- Returns:
- An :class:`Accept <litestar.datastructures.headers.Accept>` instance, representing the list of acceptable media types.
- """
- if self._accept is Empty:
- if (accept := self._connection_state.accept) is not Empty:
- self._accept = accept
- else:
- self._accept = self._connection_state.accept = Accept(self.headers.get("Accept", "*/*"))
- return self._accept
-
- async def json(self) -> Any:
- """Retrieve the json request body from the request.
-
- Returns:
- An arbitrary value
- """
- if self._json is Empty:
- if (json_ := self._connection_state.json) is not Empty:
- self._json = json_
- else:
- body = await self.body()
- self._json = self._connection_state.json = decode_json(
- body or b"null", type_decoders=self.route_handler.resolve_type_decoders()
- )
- return self._json
-
- async def msgpack(self) -> Any:
- """Retrieve the MessagePack request body from the request.
-
- Returns:
- An arbitrary value
- """
- if self._msgpack is Empty:
- if (msgpack := self._connection_state.msgpack) is not Empty:
- self._msgpack = msgpack
- else:
- body = await self.body()
- self._msgpack = self._connection_state.msgpack = decode_msgpack(
- body or b"\xc0", type_decoders=self.route_handler.resolve_type_decoders()
- )
- return self._msgpack
-
- async def stream(self) -> AsyncGenerator[bytes, None]:
- """Return an async generator that streams chunks of bytes.
-
- Returns:
- An async generator.
-
- Raises:
- RuntimeError: if the stream is already consumed
- """
- if self._body is Empty:
- if not self.is_connected:
- raise InternalServerException("stream consumed")
- while event := await self.receive():
- if event["type"] == "http.request":
- if event["body"]:
- yield event["body"]
-
- if not event.get("more_body", False):
- break
-
- if event["type"] == "http.disconnect":
- raise InternalServerException("client disconnected prematurely")
-
- self.is_connected = False
- yield b""
-
- else:
- yield self._body
- yield b""
- return
-
- async def body(self) -> bytes:
- """Return the body of the request.
-
- Returns:
- A byte-string representing the body of the request.
- """
- if self._body is Empty:
- if (body := self._connection_state.body) is not Empty:
- self._body = body
- else:
- self._body = self._connection_state.body = b"".join([c async for c in self.stream()])
- return self._body
-
- async def form(self) -> FormMultiDict:
- """Retrieve form data from the request. If the request is either a 'multipart/form-data' or an
- 'application/x-www-form- urlencoded', return a FormMultiDict instance populated with the values sent in the
- request, otherwise, an empty instance.
-
- Returns:
- A FormMultiDict instance
- """
- if self._form is Empty:
- if (form := self._connection_state.form) is not Empty:
- self._form = form
- else:
- content_type, options = self.content_type
- if content_type == RequestEncodingType.MULTI_PART:
- self._form = parse_multipart_form(
- body=await self.body(),
- boundary=options.get("boundary", "").encode(),
- multipart_form_part_limit=self.app.multipart_form_part_limit,
- )
- elif content_type == RequestEncodingType.URL_ENCODED:
- self._form = parse_url_encoded_form_data(
- await self.body(),
- )
- else:
- self._form = {}
-
- self._connection_state.form = self._form
-
- return FormMultiDict(self._form)
-
- async def send_push_promise(self, path: str, raise_if_unavailable: bool = False) -> None:
- """Send a push promise.
-
- This method requires the `http.response.push` extension to be sent from the ASGI server.
-
- Args:
- path: Path to send the promise to.
- raise_if_unavailable: Raise an exception if server push is not supported by
- the server
-
- Returns:
- None
- """
- if not self.supports_push_promise:
- if raise_if_unavailable:
- raise LitestarException("Attempted to send a push promise but the server does not support it")
-
- warnings.warn(
- "Attempted to send a push promise but the server does not support it. In a future version, this will "
- "raise an exception. To enable this behaviour in the current version, set raise_if_unavailable=True. "
- "To prevent this behaviour, make sure that the server you are using supports the 'http.response.push' "
- "ASGI extension, or check this dynamically via "
- ":attr:`~litestar.connection.Request.supports_push_promise`",
- stacklevel=2,
- category=LitestarWarning,
- )
-
- return
-
- raw_headers = [
- (header_name.encode("latin-1"), value.encode("latin-1"))
- for header_name in (self.headers.keys() & SERVER_PUSH_HEADERS)
- for value in self.headers.getall(header_name, [])
- ]
- await self.send({"type": "http.response.push", "path": path, "headers": raw_headers})
diff --git a/venv/lib/python3.11/site-packages/litestar/connection/websocket.py b/venv/lib/python3.11/site-packages/litestar/connection/websocket.py
deleted file mode 100644
index 0c7bc04..0000000
--- a/venv/lib/python3.11/site-packages/litestar/connection/websocket.py
+++ /dev/null
@@ -1,343 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any, AsyncGenerator, Generic, Literal, cast, overload
-
-from litestar.connection.base import (
- ASGIConnection,
- AuthT,
- StateT,
- UserT,
- empty_receive,
- empty_send,
-)
-from litestar.datastructures.headers import Headers
-from litestar.exceptions import WebSocketDisconnect
-from litestar.serialization import decode_json, decode_msgpack, default_serializer, encode_json, encode_msgpack
-from litestar.status_codes import WS_1000_NORMAL_CLOSURE
-
-__all__ = ("WebSocket",)
-
-
-if TYPE_CHECKING:
- from litestar.handlers.websocket_handlers import WebsocketRouteHandler # noqa: F401
- from litestar.types import Message, Serializer, WebSocketScope
- from litestar.types.asgi_types import (
- Receive,
- ReceiveMessage,
- Scope,
- Send,
- WebSocketAcceptEvent,
- WebSocketCloseEvent,
- WebSocketDisconnectEvent,
- WebSocketMode,
- WebSocketReceiveEvent,
- WebSocketSendEvent,
- )
-
-DISCONNECT_MESSAGE = "connection is disconnected"
-
-
-class WebSocket(Generic[UserT, AuthT, StateT], ASGIConnection["WebsocketRouteHandler", UserT, AuthT, StateT]):
- """The Litestar WebSocket class."""
-
- __slots__ = ("connection_state",)
-
- scope: WebSocketScope # pyright: ignore
- """The ASGI scope attached to the connection."""
- receive: Receive
- """The ASGI receive function."""
- send: Send
- """The ASGI send function."""
-
- def __init__(self, scope: Scope, receive: Receive = empty_receive, send: Send = empty_send) -> None:
- """Initialize ``WebSocket``.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
- """
- super().__init__(scope, self.receive_wrapper(receive), self.send_wrapper(send))
- self.connection_state: Literal["init", "connect", "receive", "disconnect"] = "init"
-
- def receive_wrapper(self, receive: Receive) -> Receive:
- """Wrap ``receive`` to set 'self.connection_state' and validate events.
-
- Args:
- receive: The ASGI receive function.
-
- Returns:
- An ASGI receive function.
- """
-
- async def wrapped_receive() -> ReceiveMessage:
- if self.connection_state == "disconnect":
- raise WebSocketDisconnect(detail=DISCONNECT_MESSAGE)
- message = await receive()
- if message["type"] == "websocket.connect":
- self.connection_state = "connect"
- elif message["type"] == "websocket.receive":
- self.connection_state = "receive"
- else:
- self.connection_state = "disconnect"
- return message
-
- return wrapped_receive
-
- def send_wrapper(self, send: Send) -> Send:
- """Wrap ``send`` to ensure that state is not disconnected.
-
- Args:
- send: The ASGI send function.
-
- Returns:
- An ASGI send function.
- """
-
- async def wrapped_send(message: Message) -> None:
- if self.connection_state == "disconnect":
- raise WebSocketDisconnect(detail=DISCONNECT_MESSAGE) # pragma: no cover
- await send(message)
-
- return wrapped_send
-
- async def accept(
- self,
- subprotocols: str | None = None,
- headers: Headers | dict[str, Any] | list[tuple[bytes, bytes]] | None = None,
- ) -> None:
- """Accept the incoming connection. This method should be called before receiving data.
-
- Args:
- subprotocols: Websocket sub-protocol to use.
- headers: Headers to set on the data sent.
-
- Returns:
- None
- """
- if self.connection_state == "init":
- await self.receive()
- _headers: list[tuple[bytes, bytes]] = headers if isinstance(headers, list) else []
-
- if isinstance(headers, dict):
- _headers = Headers(headers=headers).to_header_list()
-
- if isinstance(headers, Headers):
- _headers = headers.to_header_list()
-
- event: WebSocketAcceptEvent = {
- "type": "websocket.accept",
- "subprotocol": subprotocols,
- "headers": _headers,
- }
- await self.send(event)
-
- async def close(self, code: int = WS_1000_NORMAL_CLOSURE, reason: str | None = None) -> None:
- """Send an 'websocket.close' event.
-
- Args:
- code: Status code.
- reason: Reason for closing the connection
-
- Returns:
- None
- """
- event: WebSocketCloseEvent = {"type": "websocket.close", "code": code, "reason": reason or ""}
- await self.send(event)
-
- @overload
- async def receive_data(self, mode: Literal["text"]) -> str: ...
-
- @overload
- async def receive_data(self, mode: Literal["binary"]) -> bytes: ...
-
- async def receive_data(self, mode: WebSocketMode) -> str | bytes:
- """Receive an 'websocket.receive' event and returns the data stored on it.
-
- Args:
- mode: The respective event key to use.
-
- Returns:
- The event's data.
- """
- if self.connection_state == "init":
- await self.accept()
- event = cast("WebSocketReceiveEvent | WebSocketDisconnectEvent", await self.receive())
- if event["type"] == "websocket.disconnect":
- raise WebSocketDisconnect(detail="disconnect event", code=event["code"])
- return event.get("text") or "" if mode == "text" else event.get("bytes") or b""
-
- @overload
- def iter_data(self, mode: Literal["text"]) -> AsyncGenerator[str, None]: ...
-
- @overload
- def iter_data(self, mode: Literal["binary"]) -> AsyncGenerator[bytes, None]: ...
-
- async def iter_data(self, mode: WebSocketMode = "text") -> AsyncGenerator[str | bytes, None]:
- """Continuously receive data and yield it
-
- Args:
- mode: Socket mode to use. Either ``text`` or ``binary``
- """
- try:
- while True:
- yield await self.receive_data(mode)
- except WebSocketDisconnect:
- pass
-
- async def receive_text(self) -> str:
- """Receive data as text.
-
- Returns:
- A string.
- """
- return await self.receive_data(mode="text")
-
- async def receive_bytes(self) -> bytes:
- """Receive data as bytes.
-
- Returns:
- A byte-string.
- """
- return await self.receive_data(mode="binary")
-
- async def receive_json(self, mode: WebSocketMode = "text") -> Any:
- """Receive data and decode it as JSON.
-
- Args:
- mode: Either ``text`` or ``binary``.
-
- Returns:
- An arbitrary value
- """
- data = await self.receive_data(mode=mode)
- return decode_json(value=data, type_decoders=self.route_handler.resolve_type_decoders())
-
- async def receive_msgpack(self) -> Any:
- """Receive data and decode it as MessagePack.
-
- Note that since MessagePack is a binary format, this method will always receive
- data in ``binary`` mode.
-
- Returns:
- An arbitrary value
- """
- data = await self.receive_data(mode="binary")
- return decode_msgpack(value=data, type_decoders=self.route_handler.resolve_type_decoders())
-
- async def iter_json(self, mode: WebSocketMode = "text") -> AsyncGenerator[Any, None]:
- """Continuously receive data and yield it, decoding it as JSON in the process.
-
- Args:
- mode: Socket mode to use. Either ``text`` or ``binary``
- """
- async for data in self.iter_data(mode):
- yield decode_json(value=data, type_decoders=self.route_handler.resolve_type_decoders())
-
- async def iter_msgpack(self) -> AsyncGenerator[Any, None]:
- """Continuously receive data and yield it, decoding it as MessagePack in the
- process.
-
- Note that since MessagePack is a binary format, this method will always receive
- data in ``binary`` mode.
-
- """
- async for data in self.iter_data(mode="binary"):
- yield decode_msgpack(value=data, type_decoders=self.route_handler.resolve_type_decoders())
-
- async def send_data(self, data: str | bytes, mode: WebSocketMode = "text", encoding: str = "utf-8") -> None:
- """Send a 'websocket.send' event.
-
- Args:
- data: Data to send.
- mode: The respective event key to use.
- encoding: Encoding to use when converting bytes / str.
-
- Returns:
- None
- """
- if self.connection_state == "init": # pragma: no cover
- await self.accept()
- event: WebSocketSendEvent = {"type": "websocket.send", "bytes": None, "text": None}
- if mode == "binary":
- event["bytes"] = data if isinstance(data, bytes) else data.encode(encoding)
- else:
- event["text"] = data if isinstance(data, str) else data.decode(encoding)
- await self.send(event)
-
- @overload
- async def send_text(self, data: bytes, encoding: str = "utf-8") -> None: ...
-
- @overload
- async def send_text(self, data: str) -> None: ...
-
- async def send_text(self, data: str | bytes, encoding: str = "utf-8") -> None:
- """Send data using the ``text`` key of the send event.
-
- Args:
- data: Data to send
- encoding: Encoding to use for binary data.
-
- Returns:
- None
- """
- await self.send_data(data=data, encoding=encoding)
-
- @overload
- async def send_bytes(self, data: bytes) -> None: ...
-
- @overload
- async def send_bytes(self, data: str, encoding: str = "utf-8") -> None: ...
-
- async def send_bytes(self, data: str | bytes, encoding: str = "utf-8") -> None:
- """Send data using the ``bytes`` key of the send event.
-
- Args:
- data: Data to send
- encoding: Encoding to use for binary data.
-
- Returns:
- None
- """
- await self.send_data(data=data, mode="binary", encoding=encoding)
-
- async def send_json(
- self,
- data: Any,
- mode: WebSocketMode = "text",
- encoding: str = "utf-8",
- serializer: Serializer = default_serializer,
- ) -> None:
- """Send data as JSON.
-
- Args:
- data: A value to serialize.
- mode: Either ``text`` or ``binary``.
- encoding: Encoding to use for binary data.
- serializer: A serializer function.
-
- Returns:
- None
- """
- await self.send_data(data=encode_json(data, serializer), mode=mode, encoding=encoding)
-
- async def send_msgpack(
- self,
- data: Any,
- encoding: str = "utf-8",
- serializer: Serializer = default_serializer,
- ) -> None:
- """Send data as MessagePack.
-
- Note that since MessagePack is a binary format, this method will always send
- data in ``binary`` mode.
-
- Args:
- data: A value to serialize.
- encoding: Encoding to use for binary data.
- serializer: A serializer function.
-
- Returns:
- None
- """
- await self.send_data(data=encode_msgpack(data, serializer), mode="binary", encoding=encoding)
diff --git a/venv/lib/python3.11/site-packages/litestar/constants.py b/venv/lib/python3.11/site-packages/litestar/constants.py
deleted file mode 100644
index 930296c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/constants.py
+++ /dev/null
@@ -1,57 +0,0 @@
-from dataclasses import MISSING
-from inspect import Signature
-from typing import Any, Final
-
-from msgspec import UnsetType
-
-from litestar.enums import MediaType
-from litestar.types import Empty
-from litestar.utils.deprecation import warn_deprecation
-
-DEFAULT_ALLOWED_CORS_HEADERS: Final = {"Accept", "Accept-Language", "Content-Language", "Content-Type"}
-DEFAULT_CHUNK_SIZE: Final = 1024 * 128 # 128KB
-HTTP_DISCONNECT: Final = "http.disconnect"
-HTTP_RESPONSE_BODY: Final = "http.response.body"
-HTTP_RESPONSE_START: Final = "http.response.start"
-ONE_MEGABYTE: Final = 1024 * 1024
-OPENAPI_NOT_INITIALIZED: Final = "Litestar has not been instantiated with OpenAPIConfig"
-REDIRECT_STATUS_CODES: Final = {301, 302, 303, 307, 308}
-REDIRECT_ALLOWED_MEDIA_TYPES: Final = {MediaType.TEXT, MediaType.HTML, MediaType.JSON}
-RESERVED_KWARGS: Final = {"state", "headers", "cookies", "request", "socket", "data", "query", "scope", "body"}
-SKIP_VALIDATION_NAMES: Final = {"request", "socket", "scope", "receive", "send"}
-UNDEFINED_SENTINELS: Final = {Signature.empty, Empty, Ellipsis, MISSING, UnsetType}
-WEBSOCKET_CLOSE: Final = "websocket.close"
-WEBSOCKET_DISCONNECT: Final = "websocket.disconnect"
-
-
-# deprecated constants
-_SCOPE_STATE_CSRF_TOKEN_KEY = "csrf_token" # noqa: S105 # possible hardcoded password
-_SCOPE_STATE_DEPENDENCY_CACHE: Final = "dependency_cache"
-_SCOPE_STATE_NAMESPACE: Final = "__litestar__"
-_SCOPE_STATE_RESPONSE_COMPRESSED: Final = "response_compressed"
-_SCOPE_STATE_DO_CACHE: Final = "do_cache"
-_SCOPE_STATE_IS_CACHED: Final = "is_cached"
-
-_deprecated_names = {
- "SCOPE_STATE_CSRF_TOKEN_KEY": _SCOPE_STATE_CSRF_TOKEN_KEY,
- "SCOPE_STATE_DEPENDENCY_CACHE": _SCOPE_STATE_DEPENDENCY_CACHE,
- "SCOPE_STATE_NAMESPACE": _SCOPE_STATE_NAMESPACE,
- "SCOPE_STATE_RESPONSE_COMPRESSED": _SCOPE_STATE_RESPONSE_COMPRESSED,
- "SCOPE_STATE_DO_CACHE": _SCOPE_STATE_DO_CACHE,
- "SCOPE_STATE_IS_CACHED": _SCOPE_STATE_IS_CACHED,
-}
-
-
-def __getattr__(name: str) -> Any:
- if name in _deprecated_names:
- warn_deprecation(
- deprecated_name=f"litestar.constants.{name}",
- version="2.4",
- kind="import",
- removal_in="3.0",
- info=f"'{name}' from 'litestar.constants' is deprecated and will be removed in 3.0. "
- "Direct access to Litestar scope state is not recommended.",
- )
-
- return globals()["_deprecated_names"][name]
- raise AttributeError(f"module {__name__} has no attribute {name}") # pragma: no cover
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/__init__.py b/venv/lib/python3.11/site-packages/litestar/contrib/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/__init__.py
+++ /dev/null
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index fc2f5bc..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/jinja.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/jinja.cpython-311.pyc
deleted file mode 100644
index f58d015..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/jinja.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/mako.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/mako.cpython-311.pyc
deleted file mode 100644
index 09bede9..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/mako.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/minijinja.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/minijinja.cpython-311.pyc
deleted file mode 100644
index 05ada30..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/minijinja.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/minijnja.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/minijnja.cpython-311.pyc
deleted file mode 100644
index 3006e82..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/minijnja.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/piccolo.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/piccolo.cpython-311.pyc
deleted file mode 100644
index 20ea290..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/piccolo.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/attrs/__init__.py b/venv/lib/python3.11/site-packages/litestar/contrib/attrs/__init__.py
deleted file mode 100644
index ddd2a3f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/attrs/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from .attrs_schema_plugin import AttrsSchemaPlugin
-
-__all__ = ("AttrsSchemaPlugin",)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/attrs/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/attrs/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index a224be6..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/attrs/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/attrs/__pycache__/attrs_schema_plugin.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/attrs/__pycache__/attrs_schema_plugin.cpython-311.pyc
deleted file mode 100644
index 730252a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/attrs/__pycache__/attrs_schema_plugin.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/attrs/attrs_schema_plugin.py b/venv/lib/python3.11/site-packages/litestar/contrib/attrs/attrs_schema_plugin.py
deleted file mode 100644
index cf67fe4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/attrs/attrs_schema_plugin.py
+++ /dev/null
@@ -1,49 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any
-
-from litestar.exceptions import MissingDependencyException
-from litestar.plugins import OpenAPISchemaPluginProtocol
-from litestar.typing import FieldDefinition
-from litestar.utils import is_attrs_class, is_optional_union
-
-try:
- import attr
- import attrs
-except ImportError as e:
- raise MissingDependencyException("attrs") from e
-
-if TYPE_CHECKING:
- from litestar._openapi.schema_generation import SchemaCreator
- from litestar.openapi.spec import Schema
-
-
-class AttrsSchemaPlugin(OpenAPISchemaPluginProtocol):
- @staticmethod
- def is_plugin_supported_type(value: Any) -> bool:
- return is_attrs_class(value) or is_attrs_class(type(value))
-
- def to_openapi_schema(self, field_definition: FieldDefinition, schema_creator: SchemaCreator) -> Schema:
- """Given a type annotation, transform it into an OpenAPI schema class.
-
- Args:
- field_definition: FieldDefinition instance.
- schema_creator: An instance of the schema creator class
-
- Returns:
- An :class:`OpenAPI <litestar.openapi.spec.schema.Schema>` instance.
- """
-
- type_hints = field_definition.get_type_hints(include_extras=True, resolve_generics=True)
- attr_fields = attr.fields_dict(field_definition.type_)
- return schema_creator.create_component_schema(
- field_definition,
- required=sorted(
- field_name
- for field_name, attribute in attr_fields.items()
- if attribute.default is attrs.NOTHING and not is_optional_union(type_hints[field_name])
- ),
- property_fields={
- field_name: FieldDefinition.from_kwarg(type_hints[field_name], field_name) for field_name in attr_fields
- },
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__init__.py b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__init__.py
+++ /dev/null
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 31d4982..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/_utils.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/_utils.cpython-311.pyc
deleted file mode 100644
index d860774..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/_utils.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/request.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/request.cpython-311.pyc
deleted file mode 100644
index 65b99d9..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/request.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/response.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/response.cpython-311.pyc
deleted file mode 100644
index 0bb64b8..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/response.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/types.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/types.cpython-311.pyc
deleted file mode 100644
index 0af7128..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/types.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/_utils.py b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/_utils.py
deleted file mode 100644
index 894fd25..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/_utils.py
+++ /dev/null
@@ -1,148 +0,0 @@
-from __future__ import annotations
-
-from enum import Enum
-from typing import TYPE_CHECKING, Any, Callable, cast
-from urllib.parse import quote
-
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.serialization import encode_json
-
-__all__ = (
- "HTMXHeaders",
- "get_headers",
- "get_location_headers",
- "get_push_url_header",
- "get_redirect_header",
- "get_refresh_header",
- "get_replace_url_header",
- "get_reswap_header",
- "get_retarget_header",
- "get_trigger_event_headers",
-)
-
-
-if TYPE_CHECKING:
- from litestar.contrib.htmx.types import (
- EventAfterType,
- HtmxHeaderType,
- LocationType,
- PushUrlType,
- ReSwapMethod,
- TriggerEventType,
- )
-
-HTMX_STOP_POLLING = 286
-
-
-class HTMXHeaders(str, Enum):
- """Enum for HTMX Headers"""
-
- REDIRECT = "HX-Redirect"
- REFRESH = "HX-Refresh"
- PUSH_URL = "HX-Push-Url"
- REPLACE_URL = "HX-Replace-Url"
- RE_SWAP = "HX-Reswap"
- RE_TARGET = "HX-Retarget"
- LOCATION = "HX-Location"
-
- TRIGGER_EVENT = "HX-Trigger"
- TRIGGER_AFTER_SETTLE = "HX-Trigger-After-Settle"
- TRIGGER_AFTER_SWAP = "HX-Trigger-After-Swap"
-
- REQUEST = "HX-Request"
- BOOSTED = "HX-Boosted"
- CURRENT_URL = "HX-Current-URL"
- HISTORY_RESTORE_REQUEST = "HX-History-Restore-Request"
- PROMPT = "HX-Prompt"
- TARGET = "HX-Target"
- TRIGGER_ID = "HX-Trigger" # noqa: PIE796
- TRIGGER_NAME = "HX-Trigger-Name"
- TRIGGERING_EVENT = "Triggering-Event"
-
-
-def get_trigger_event_headers(trigger_event: TriggerEventType) -> dict[str, Any]:
- """Return headers for trigger event response."""
- after_params: dict[EventAfterType, str] = {
- "receive": HTMXHeaders.TRIGGER_EVENT.value,
- "settle": HTMXHeaders.TRIGGER_AFTER_SETTLE.value,
- "swap": HTMXHeaders.TRIGGER_AFTER_SWAP.value,
- }
-
- if trigger_header := after_params.get(trigger_event["after"]):
- return {trigger_header: encode_json({trigger_event["name"]: trigger_event["params"] or {}}).decode()}
-
- raise ImproperlyConfiguredException(
- "invalid value for 'after' param- allowed values are 'receive', 'settle' or 'swap'."
- )
-
-
-def get_redirect_header(url: str) -> dict[str, Any]:
- """Return headers for redirect response."""
- return {HTMXHeaders.REDIRECT.value: quote(url, safe="/#%[]=:;$&()+,!?*@'~"), "Location": ""}
-
-
-def get_push_url_header(url: PushUrlType) -> dict[str, Any]:
- """Return headers for push url to browser history response."""
- if isinstance(url, str):
- url = url if url != "False" else "false"
- elif isinstance(url, bool):
- url = "false"
-
- return {HTMXHeaders.PUSH_URL.value: url}
-
-
-def get_replace_url_header(url: PushUrlType) -> dict[str, Any]:
- """Return headers for replace url in browser tab response."""
- url = (url if url != "False" else "false") if isinstance(url, str) else "false"
- return {HTMXHeaders.REPLACE_URL: url}
-
-
-def get_refresh_header(refresh: bool) -> dict[str, Any]:
- """Return headers for client refresh response."""
- return {HTMXHeaders.REFRESH.value: "true" if refresh else ""}
-
-
-def get_reswap_header(method: ReSwapMethod) -> dict[str, Any]:
- """Return headers for change swap method response."""
- return {HTMXHeaders.RE_SWAP.value: method}
-
-
-def get_retarget_header(target: str) -> dict[str, Any]:
- """Return headers for change target element response."""
- return {HTMXHeaders.RE_TARGET.value: target}
-
-
-def get_location_headers(location: LocationType) -> dict[str, Any]:
- """Return headers for redirect without page-reload response."""
- if spec := {key: value for key, value in location.items() if value}:
- return {HTMXHeaders.LOCATION.value: encode_json(spec).decode()}
- raise ValueError("redirect_to is required parameter.")
-
-
-def get_headers(hx_headers: HtmxHeaderType) -> dict[str, Any]:
- """Return headers for HTMX responses."""
- if not hx_headers:
- raise ValueError("Value for hx_headers cannot be None.")
- htmx_headers_dict: dict[str, Callable] = {
- "redirect": get_redirect_header,
- "refresh": get_refresh_header,
- "push_url": get_push_url_header,
- "replace_url": get_replace_url_header,
- "re_swap": get_reswap_header,
- "re_target": get_retarget_header,
- "trigger_event": get_trigger_event_headers,
- "location": get_location_headers,
- }
-
- header: dict[str, Any] = {}
- response: dict[str, Any]
- key: str
- value: Any
-
- for key, value in hx_headers.items():
- if key in ["redirect", "refresh", "location", "replace_url"]:
- return cast("dict[str, Any]", htmx_headers_dict[key](value))
- if value is not None:
- response = htmx_headers_dict[key](value)
- header.update(response)
- return header
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/request.py b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/request.py
deleted file mode 100644
index b4fad18..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/request.py
+++ /dev/null
@@ -1,113 +0,0 @@
-from __future__ import annotations
-
-from contextlib import suppress
-from functools import cached_property
-from typing import TYPE_CHECKING, Any
-from urllib.parse import unquote, urlsplit, urlunsplit
-
-from litestar import Request
-from litestar.connection.base import empty_receive, empty_send
-from litestar.contrib.htmx._utils import HTMXHeaders
-from litestar.exceptions import SerializationException
-from litestar.serialization import decode_json
-
-__all__ = ("HTMXDetails", "HTMXRequest")
-
-
-if TYPE_CHECKING:
- from litestar.types import Receive, Scope, Send
-
-
-class HTMXDetails:
- """HTMXDetails holds all the values sent by HTMX client in headers and provide convenient properties."""
-
- def __init__(self, request: Request) -> None:
- """Initialize :class:`HTMXDetails`"""
- self.request = request
-
- def _get_header_value(self, name: HTMXHeaders) -> str | None:
- """Parse request header
-
- Check for uri encoded header and unquotes it in readable format.
- """
-
- if value := self.request.headers.get(name.value.lower()):
- is_uri_encoded = self.request.headers.get(f"{name.value.lower()}-uri-autoencoded") == "true"
- return unquote(value) if is_uri_encoded else value
- return None
-
- def __bool__(self) -> bool:
- """Check if request is sent by an HTMX client."""
- return self._get_header_value(HTMXHeaders.REQUEST) == "true"
-
- @cached_property
- def boosted(self) -> bool:
- """Check if request is boosted."""
- return self._get_header_value(HTMXHeaders.BOOSTED) == "true"
-
- @cached_property
- def current_url(self) -> str | None:
- """Current url value sent by HTMX client."""
- return self._get_header_value(HTMXHeaders.CURRENT_URL)
-
- @cached_property
- def current_url_abs_path(self) -> str | None:
- """Current url abs path value, to get query and path parameter sent by HTMX client."""
- if self.current_url:
- split = urlsplit(self.current_url)
- if split.scheme == self.request.scope["scheme"] and split.netloc == self.request.headers.get("host"):
- return str(urlunsplit(split._replace(scheme="", netloc="")))
- return None
- return self.current_url
-
- @cached_property
- def history_restore_request(self) -> bool:
- """If True then, request is for history restoration after a miss in the local history cache."""
- return self._get_header_value(HTMXHeaders.HISTORY_RESTORE_REQUEST) == "true"
-
- @cached_property
- def prompt(self) -> str | None:
- """User Response to prompt.
-
- .. code-block:: html
-
- <button hx-delete="/account" hx-prompt="Enter your account name to confirm deletion">Delete My Account</button>
- """
- return self._get_header_value(HTMXHeaders.PROMPT)
-
- @cached_property
- def target(self) -> str | None:
- """ID of the target element if provided on the element."""
- return self._get_header_value(HTMXHeaders.TARGET)
-
- @cached_property
- def trigger(self) -> str | None:
- """ID of the triggered element if provided on the element."""
- return self._get_header_value(HTMXHeaders.TRIGGER_ID)
-
- @cached_property
- def trigger_name(self) -> str | None:
- """Name of the triggered element if provided on the element."""
- return self._get_header_value(HTMXHeaders.TRIGGER_NAME)
-
- @cached_property
- def triggering_event(self) -> Any:
- """Name of the triggered event.
-
- This value is added by ``event-header`` extension of HTMX to the ``Triggering-Event`` header to requests.
- """
- if value := self._get_header_value(HTMXHeaders.TRIGGERING_EVENT):
- with suppress(SerializationException):
- return decode_json(value=value, type_decoders=self.request.route_handler.resolve_type_decoders())
- return None
-
-
-class HTMXRequest(Request):
- """HTMX Request class to work with HTMX client."""
-
- __slots__ = ("htmx",)
-
- def __init__(self, scope: Scope, receive: Receive = empty_receive, send: Send = empty_send) -> None:
- """Initialize :class:`HTMXRequest`"""
- super().__init__(scope=scope, receive=receive, send=send)
- self.htmx = HTMXDetails(self)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/response.py b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/response.py
deleted file mode 100644
index 0a56e1f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/response.py
+++ /dev/null
@@ -1,200 +0,0 @@
-from __future__ import annotations
-
-from typing import Any, Generic, TypeVar
-from urllib.parse import quote
-
-from litestar import Response
-from litestar.contrib.htmx._utils import HTMX_STOP_POLLING, get_headers
-from litestar.contrib.htmx.types import (
- EventAfterType,
- HtmxHeaderType,
- LocationType,
- PushUrlType,
- ReSwapMethod,
- TriggerEventType,
-)
-from litestar.response import Template
-from litestar.status_codes import HTTP_200_OK
-
-__all__ = (
- "ClientRedirect",
- "ClientRefresh",
- "HTMXTemplate",
- "HXLocation",
- "HXStopPolling",
- "PushUrl",
- "ReplaceUrl",
- "Reswap",
- "Retarget",
- "TriggerEvent",
-)
-
-
-# HTMX defined HTTP status code.
-# Response carrying this status code will ask client to stop Polling.
-T = TypeVar("T")
-
-
-class HXStopPolling(Response):
- """Stop HTMX client from Polling."""
-
- def __init__(self) -> None:
- """Initialize"""
- super().__init__(content=None)
- self.status_code = HTMX_STOP_POLLING
-
-
-class ClientRedirect(Response):
- """HTMX Response class to support client side redirect."""
-
- def __init__(self, redirect_to: str) -> None:
- """Set status code to 200 (required by HTMX), and pass redirect url."""
- super().__init__(content=None, headers=get_headers(hx_headers=HtmxHeaderType(redirect=redirect_to)))
- del self.headers["Location"]
-
-
-class ClientRefresh(Response):
- """Response to support HTMX client page refresh"""
-
- def __init__(self) -> None:
- """Set Status code to 200 and set headers."""
- super().__init__(content=None, headers=get_headers(hx_headers=HtmxHeaderType(refresh=True)))
-
-
-class PushUrl(Generic[T], Response[T]):
- """Response to push new url into the history stack."""
-
- def __init__(self, content: T, push_url: PushUrlType, **kwargs: Any) -> None:
- """Initialize PushUrl."""
- super().__init__(
- content=content,
- status_code=HTTP_200_OK,
- headers=get_headers(hx_headers=HtmxHeaderType(push_url=push_url)),
- **kwargs,
- )
-
-
-class ReplaceUrl(Generic[T], Response[T]):
- """Response to replace url in the Browser Location bar."""
-
- def __init__(self, content: T, replace_url: PushUrlType, **kwargs: Any) -> None:
- """Initialize ReplaceUrl."""
- super().__init__(
- content=content,
- status_code=HTTP_200_OK,
- headers=get_headers(hx_headers=HtmxHeaderType(replace_url=replace_url)),
- **kwargs,
- )
-
-
-class Reswap(Generic[T], Response[T]):
- """Response to specify how the response will be swapped."""
-
- def __init__(
- self,
- content: T,
- method: ReSwapMethod,
- **kwargs: Any,
- ) -> None:
- """Initialize Reswap."""
- super().__init__(content=content, headers=get_headers(hx_headers=HtmxHeaderType(re_swap=method)), **kwargs)
-
-
-class Retarget(Generic[T], Response[T]):
- """Response to target different element on the page."""
-
- def __init__(self, content: T, target: str, **kwargs: Any) -> None:
- """Initialize Retarget."""
- super().__init__(content=content, headers=get_headers(hx_headers=HtmxHeaderType(re_target=target)), **kwargs)
-
-
-class TriggerEvent(Generic[T], Response[T]):
- """Trigger Client side event."""
-
- def __init__(
- self,
- content: T,
- name: str,
- after: EventAfterType,
- params: dict[str, Any] | None = None,
- **kwargs: Any,
- ) -> None:
- """Initialize TriggerEvent."""
- event = TriggerEventType(name=name, params=params, after=after)
- headers = get_headers(hx_headers=HtmxHeaderType(trigger_event=event))
- super().__init__(content=content, headers=headers, **kwargs)
-
-
-class HXLocation(Response):
- """Client side redirect without full page reload."""
-
- def __init__(
- self,
- redirect_to: str,
- source: str | None = None,
- event: str | None = None,
- target: str | None = None,
- swap: ReSwapMethod | None = None,
- hx_headers: dict[str, Any] | None = None,
- values: dict[str, str] | None = None,
- **kwargs: Any,
- ) -> None:
- """Initialize HXLocation, Set status code to 200 (required by HTMX),
- and pass redirect url.
- """
- super().__init__(
- content=None,
- headers={"Location": quote(redirect_to, safe="/#%[]=:;$&()+,!?*@'~")},
- **kwargs,
- )
- spec: dict[str, Any] = get_headers(
- hx_headers=HtmxHeaderType(
- location=LocationType(
- path=str(self.headers.get("Location")),
- source=source,
- event=event,
- target=target,
- swap=swap,
- values=values,
- hx_headers=hx_headers,
- )
- )
- )
- del self.headers["Location"]
- self.headers.update(spec)
-
-
-class HTMXTemplate(Template):
- """HTMX template wrapper"""
-
- def __init__(
- self,
- push_url: PushUrlType | None = None,
- re_swap: ReSwapMethod | None = None,
- re_target: str | None = None,
- trigger_event: str | None = None,
- params: dict[str, Any] | None = None,
- after: EventAfterType | None = None,
- **kwargs: Any,
- ) -> None:
- """Create HTMXTemplate response.
-
- Args:
- push_url: Either a string value specifying a URL to push to browser history or ``False`` to prevent HTMX client from
- pushing a url to browser history.
- re_swap: Method value to instruct HTMX which swapping method to use.
- re_target: Value for 'id of target element' to apply changes to.
- trigger_event: Event name to trigger.
- params: Dictionary of parameters if any required with trigger event parameter.
- after: Changes to apply after ``receive``, ``settle`` or ``swap`` event.
- **kwargs: Additional arguments to pass to ``Template``.
- """
- super().__init__(**kwargs)
-
- event: TriggerEventType | None = None
- if trigger_event:
- event = TriggerEventType(name=str(trigger_event), params=params, after=after)
-
- self.headers.update(
- get_headers(HtmxHeaderType(push_url=push_url, re_swap=re_swap, re_target=re_target, trigger_event=event))
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/types.py b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/types.py
deleted file mode 100644
index aa8f9cd..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/htmx/types.py
+++ /dev/null
@@ -1,54 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any, Literal, TypedDict, Union
-
-__all__ = (
- "HtmxHeaderType",
- "LocationType",
- "TriggerEventType",
-)
-
-if TYPE_CHECKING:
- from typing_extensions import Required
-
-
-EventAfterType = Literal["receive", "settle", "swap", None]
-
-PushUrlType = Union[str, bool]
-
-ReSwapMethod = Literal[
- "innerHTML", "outerHTML", "beforebegin", "afterbegin", "beforeend", "afterend", "delete", "none", None
-]
-
-
-class LocationType(TypedDict):
- """Type for HX-Location header."""
-
- path: Required[str]
- source: str | None
- event: str | None
- target: str | None
- swap: ReSwapMethod | None
- values: dict[str, str] | None
- hx_headers: dict[str, Any] | None
-
-
-class TriggerEventType(TypedDict):
- """Type for HX-Trigger header."""
-
- name: Required[str]
- params: dict[str, Any] | None
- after: EventAfterType | None
-
-
-class HtmxHeaderType(TypedDict, total=False):
- """Type for hx_headers parameter in get_headers()."""
-
- location: LocationType | None
- redirect: str | None
- refresh: bool
- push_url: PushUrlType | None
- replace_url: PushUrlType | None
- re_swap: ReSwapMethod | None
- re_target: str | None
- trigger_event: TriggerEventType | None
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/jinja.py b/venv/lib/python3.11/site-packages/litestar/contrib/jinja.py
deleted file mode 100644
index 4e8057b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/jinja.py
+++ /dev/null
@@ -1,114 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any, Mapping, TypeVar
-
-from typing_extensions import ParamSpec
-
-from litestar.exceptions import ImproperlyConfiguredException, MissingDependencyException, TemplateNotFoundException
-from litestar.template.base import (
- TemplateCallableType,
- TemplateEngineProtocol,
- csrf_token,
- url_for,
- url_for_static_asset,
-)
-
-try:
- from jinja2 import Environment, FileSystemLoader, pass_context
- from jinja2 import TemplateNotFound as JinjaTemplateNotFound
-except ImportError as e:
- raise MissingDependencyException("jinja2", extra="jinja") from e
-
-if TYPE_CHECKING:
- from pathlib import Path
-
- from jinja2 import Template as JinjaTemplate
-
-__all__ = ("JinjaTemplateEngine",)
-
-P = ParamSpec("P")
-T = TypeVar("T")
-
-
-class JinjaTemplateEngine(TemplateEngineProtocol["JinjaTemplate", Mapping[str, Any]]):
- """The engine instance."""
-
- def __init__(
- self,
- directory: Path | list[Path] | None = None,
- engine_instance: Environment | None = None,
- ) -> None:
- """Jinja-based TemplateEngine.
-
- Args:
- directory: Direct path or list of directory paths from which to serve templates.
- engine_instance: A jinja Environment instance.
- """
-
- super().__init__(directory, engine_instance)
- if directory and engine_instance:
- raise ImproperlyConfiguredException("You must provide either a directory or a jinja2 Environment instance.")
- if directory:
- loader = FileSystemLoader(searchpath=directory)
- self.engine = Environment(loader=loader, autoescape=True)
- elif engine_instance:
- self.engine = engine_instance
- self.register_template_callable(key="url_for_static_asset", template_callable=url_for_static_asset)
- self.register_template_callable(key="csrf_token", template_callable=csrf_token)
- self.register_template_callable(key="url_for", template_callable=url_for)
-
- def get_template(self, template_name: str) -> JinjaTemplate:
- """Retrieve a template by matching its name (dotted path) with files in the directory or directories provided.
-
- Args:
- template_name: A dotted path
-
- Returns:
- JinjaTemplate instance
-
- Raises:
- TemplateNotFoundException: if no template is found.
- """
- try:
- return self.engine.get_template(name=template_name)
- except JinjaTemplateNotFound as exc:
- raise TemplateNotFoundException(template_name=template_name) from exc
-
- def register_template_callable(
- self, key: str, template_callable: TemplateCallableType[Mapping[str, Any], P, T]
- ) -> None:
- """Register a callable on the template engine.
-
- Args:
- key: The callable key, i.e. the value to use inside the template to call the callable.
- template_callable: A callable to register.
-
- Returns:
- None
- """
- self.engine.globals[key] = pass_context(template_callable)
-
- def render_string(self, template_string: str, context: Mapping[str, Any]) -> str:
- """Render a template from a string with the given context.
-
- Args:
- template_string: The template string to render.
- context: A dictionary of variables to pass to the template.
-
- Returns:
- The rendered template as a string.
- """
- template = self.engine.from_string(template_string)
- return template.render(context)
-
- @classmethod
- def from_environment(cls, jinja_environment: Environment) -> JinjaTemplateEngine:
- """Create a JinjaTemplateEngine from an existing jinja Environment instance.
-
- Args:
- jinja_environment (jinja2.environment.Environment): A jinja Environment instance.
-
- Returns:
- JinjaTemplateEngine instance
- """
- return cls(directory=None, engine_instance=jinja_environment)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__init__.py b/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__init__.py
deleted file mode 100644
index 70a4f75..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__init__.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from litestar.contrib.jwt.jwt_auth import (
- BaseJWTAuth,
- JWTAuth,
- JWTCookieAuth,
- OAuth2Login,
- OAuth2PasswordBearerAuth,
-)
-from litestar.contrib.jwt.jwt_token import Token
-from litestar.contrib.jwt.middleware import (
- JWTAuthenticationMiddleware,
- JWTCookieAuthenticationMiddleware,
-)
-from litestar.utils import warn_deprecation
-
-__all__ = (
- "BaseJWTAuth",
- "JWTAuth",
- "JWTAuthenticationMiddleware",
- "JWTCookieAuth",
- "JWTCookieAuthenticationMiddleware",
- "OAuth2Login",
- "OAuth2PasswordBearerAuth",
- "Token",
-)
-
-warn_deprecation(
- deprecated_name="litestar.contrib.jwt",
- version="2.3.2",
- kind="import",
- removal_in="3.0",
- info="importing from 'litestar.contrib.jwt' is deprecated, please import from 'litestar.security.jwt' instead",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 1515862..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/jwt_auth.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/jwt_auth.cpython-311.pyc
deleted file mode 100644
index 44907f6..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/jwt_auth.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/jwt_token.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/jwt_token.cpython-311.pyc
deleted file mode 100644
index 2ffdb24..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/jwt_token.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/middleware.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/middleware.cpython-311.pyc
deleted file mode 100644
index 334e3fa..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/middleware.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/jwt/jwt_auth.py b/venv/lib/python3.11/site-packages/litestar/contrib/jwt/jwt_auth.py
deleted file mode 100644
index e8ffb48..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/jwt/jwt_auth.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from __future__ import annotations
-
-from litestar.security.jwt.auth import BaseJWTAuth, JWTAuth, JWTCookieAuth, OAuth2Login, OAuth2PasswordBearerAuth
-
-__all__ = ("BaseJWTAuth", "JWTAuth", "JWTCookieAuth", "OAuth2Login", "OAuth2PasswordBearerAuth")
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/jwt/jwt_token.py b/venv/lib/python3.11/site-packages/litestar/contrib/jwt/jwt_token.py
deleted file mode 100644
index 882373f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/jwt/jwt_token.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from __future__ import annotations
-
-from litestar.security.jwt.token import Token
-
-__all__ = ("Token",)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/jwt/middleware.py b/venv/lib/python3.11/site-packages/litestar/contrib/jwt/middleware.py
deleted file mode 100644
index e0ad413..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/jwt/middleware.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from __future__ import annotations
-
-from litestar.security.jwt.middleware import JWTAuthenticationMiddleware, JWTCookieAuthenticationMiddleware
-
-__all__ = ("JWTAuthenticationMiddleware", "JWTCookieAuthenticationMiddleware")
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/mako.py b/venv/lib/python3.11/site-packages/litestar/contrib/mako.py
deleted file mode 100644
index 9cb4c47..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/mako.py
+++ /dev/null
@@ -1,146 +0,0 @@
-from __future__ import annotations
-
-from functools import partial
-from typing import TYPE_CHECKING, Any, Mapping, TypeVar
-
-from typing_extensions import ParamSpec
-
-from litestar.exceptions import ImproperlyConfiguredException, MissingDependencyException, TemplateNotFoundException
-from litestar.template.base import (
- TemplateCallableType,
- TemplateEngineProtocol,
- TemplateProtocol,
- csrf_token,
- url_for,
- url_for_static_asset,
-)
-
-try:
- from mako.exceptions import TemplateLookupException as MakoTemplateNotFound # type: ignore[import-untyped]
- from mako.lookup import TemplateLookup # type: ignore[import-untyped]
- from mako.template import Template as _MakoTemplate # type: ignore[import-untyped]
-except ImportError as e:
- raise MissingDependencyException("mako") from e
-
-if TYPE_CHECKING:
- from pathlib import Path
-
-__all__ = ("MakoTemplate", "MakoTemplateEngine")
-
-P = ParamSpec("P")
-T = TypeVar("T")
-
-
-class MakoTemplate(TemplateProtocol):
- """Mako template, implementing ``TemplateProtocol``"""
-
- def __init__(self, template: _MakoTemplate, template_callables: list[tuple[str, TemplateCallableType]]) -> None:
- """Initialize a template.
-
- Args:
- template: Base ``MakoTemplate`` used by the underlying mako-engine
- template_callables: List of callables passed to the template
- """
- super().__init__()
- self.template = template
- self.template_callables = template_callables
-
- def render(self, *args: Any, **kwargs: Any) -> str:
- """Render a template.
-
- Args:
- args: Positional arguments passed to the engines ``render`` function
- kwargs: Keyword arguments passed to the engines ``render`` function
-
- Returns:
- Rendered template as a string
- """
- for callable_key, template_callable in self.template_callables:
- kwargs_copy = {**kwargs}
- kwargs[callable_key] = partial(template_callable, kwargs_copy)
-
- return str(self.template.render(*args, **kwargs))
-
-
-class MakoTemplateEngine(TemplateEngineProtocol[MakoTemplate, Mapping[str, Any]]):
- """Mako-based TemplateEngine."""
-
- def __init__(self, directory: Path | list[Path] | None = None, engine_instance: Any | None = None) -> None:
- """Initialize template engine.
-
- Args:
- directory: Direct path or list of directory paths from which to serve templates.
- engine_instance: A mako TemplateLookup instance.
- """
- super().__init__(directory, engine_instance)
- if directory and engine_instance:
- raise ImproperlyConfiguredException("You must provide either a directory or a mako TemplateLookup.")
- if directory:
- self.engine = TemplateLookup(
- directories=directory if isinstance(directory, (list, tuple)) else [directory], default_filters=["h"]
- )
- elif engine_instance:
- self.engine = engine_instance
-
- self._template_callables: list[tuple[str, TemplateCallableType]] = []
- self.register_template_callable(key="url_for_static_asset", template_callable=url_for_static_asset)
- self.register_template_callable(key="csrf_token", template_callable=csrf_token)
- self.register_template_callable(key="url_for", template_callable=url_for)
-
- def get_template(self, template_name: str) -> MakoTemplate:
- """Retrieve a template by matching its name (dotted path) with files in the directory or directories provided.
-
- Args:
- template_name: A dotted path
-
- Returns:
- MakoTemplate instance
-
- Raises:
- TemplateNotFoundException: if no template is found.
- """
- try:
- return MakoTemplate(
- template=self.engine.get_template(template_name), template_callables=self._template_callables
- )
- except MakoTemplateNotFound as exc:
- raise TemplateNotFoundException(template_name=template_name) from exc
-
- def register_template_callable(
- self, key: str, template_callable: TemplateCallableType[Mapping[str, Any], P, T]
- ) -> None:
- """Register a callable on the template engine.
-
- Args:
- key: The callable key, i.e. the value to use inside the template to call the callable.
- template_callable: A callable to register.
-
- Returns:
- None
- """
- self._template_callables.append((key, template_callable))
-
- def render_string(self, template_string: str, context: Mapping[str, Any]) -> str: # pyright: ignore
- """Render a template from a string with the given context.
-
- Args:
- template_string: The template string to render.
- context: A dictionary of variables to pass to the template.
-
- Returns:
- The rendered template as a string.
- """
- template = _MakoTemplate(template_string) # noqa: S702
- return template.render(**context) # type: ignore[no-any-return]
-
- @classmethod
- def from_template_lookup(cls, template_lookup: TemplateLookup) -> MakoTemplateEngine:
- """Create a template engine from an existing mako TemplateLookup instance.
-
- Args:
- template_lookup: A mako TemplateLookup instance.
-
- Returns:
- MakoTemplateEngine instance
- """
- return cls(directory=None, engine_instance=template_lookup)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/minijinja.py b/venv/lib/python3.11/site-packages/litestar/contrib/minijinja.py
deleted file mode 100644
index 6007a18..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/minijinja.py
+++ /dev/null
@@ -1,216 +0,0 @@
-from __future__ import annotations
-
-import functools
-from pathlib import Path
-from typing import TYPE_CHECKING, Any, Mapping, Protocol, TypeVar, cast
-
-from typing_extensions import ParamSpec
-
-from litestar.exceptions import ImproperlyConfiguredException, MissingDependencyException, TemplateNotFoundException
-from litestar.template.base import (
- TemplateCallableType,
- TemplateEngineProtocol,
- TemplateProtocol,
- csrf_token,
- url_for,
- url_for_static_asset,
-)
-from litestar.utils.deprecation import warn_deprecation
-
-try:
- from minijinja import Environment # type:ignore[import-untyped]
- from minijinja import TemplateError as MiniJinjaTemplateNotFound
-except ImportError as e:
- raise MissingDependencyException("minijinja") from e
-
-if TYPE_CHECKING:
- from typing import Callable
-
- C = TypeVar("C", bound="Callable")
-
- def pass_state(func: C) -> C: ...
-
-else:
- from minijinja import pass_state
-
-__all__ = (
- "MiniJinjaTemplateEngine",
- "StateProtocol",
-)
-
-P = ParamSpec("P")
-T = TypeVar("T")
-
-
-class StateProtocol(Protocol):
- auto_escape: str | None
- current_block: str | None
- env: Environment
- name: str
-
- def lookup(self, key: str) -> Any | None: ...
-
-
-def _transform_state(func: TemplateCallableType[Mapping[str, Any], P, T]) -> TemplateCallableType[StateProtocol, P, T]:
- """Transform a template callable to receive a ``StateProtocol`` instance as first argument.
-
- This is for wrapping callables like ``url_for()`` that receive a mapping as first argument so they can be used
- with minijinja which passes a ``StateProtocol`` instance as first argument.
- """
-
- @functools.wraps(func)
- @pass_state
- def wrapped(state: StateProtocol, /, *args: P.args, **kwargs: P.kwargs) -> T:
- template_context = {"request": state.lookup("request"), "csrf_input": state.lookup("csrf_input")}
- return func(template_context, *args, **kwargs)
-
- return wrapped
-
-
-class MiniJinjaTemplate(TemplateProtocol):
- """Initialize a template.
-
- Args:
- template: Base ``MiniJinjaTemplate`` used by the underlying minijinja engine
- """
-
- def __init__(self, engine: Environment, template_name: str) -> None:
- super().__init__()
- self.engine = engine
- self.template_name = template_name
-
- def render(self, *args: Any, **kwargs: Any) -> str:
- """Render a template.
-
- Args:
- args: Positional arguments passed to the engines ``render`` function
- kwargs: Keyword arguments passed to the engines ``render`` function
-
- Returns:
- Rendered template as a string
- """
- try:
- return str(self.engine.render_template(self.template_name, *args, **kwargs))
- except MiniJinjaTemplateNotFound as err:
- raise TemplateNotFoundException(template_name=self.template_name) from err
-
-
-class MiniJinjaTemplateEngine(TemplateEngineProtocol["MiniJinjaTemplate", StateProtocol]):
- """The engine instance."""
-
- def __init__(self, directory: Path | list[Path] | None = None, engine_instance: Environment | None = None) -> None:
- """Minijinja based TemplateEngine.
-
- Args:
- directory: Direct path or list of directory paths from which to serve templates.
- engine_instance: A Minijinja Environment instance.
- """
- super().__init__(directory, engine_instance)
- if directory and engine_instance:
- raise ImproperlyConfiguredException(
- "You must provide either a directory or a minijinja Environment instance."
- )
- if directory:
-
- def _loader(name: str) -> str:
- """Load a template from a directory.
-
- Args:
- name: The name of the template
-
- Returns:
- The template as a string
-
- Raises:
- TemplateNotFoundException: if no template is found.
- """
- directories = directory if isinstance(directory, list) else [directory]
-
- for d in directories:
- template_path = Path(d) / name # pyright: ignore[reportGeneralTypeIssues]
- if template_path.exists():
- return template_path.read_text()
- raise TemplateNotFoundException(template_name=name)
-
- self.engine = Environment(loader=_loader)
- elif engine_instance:
- self.engine = engine_instance
- else:
- raise ImproperlyConfiguredException(
- "You must provide either a directory or a minijinja Environment instance."
- )
-
- self.register_template_callable("url_for", _transform_state(url_for))
- self.register_template_callable("csrf_token", _transform_state(csrf_token))
- self.register_template_callable("url_for_static_asset", _transform_state(url_for_static_asset))
-
- def get_template(self, template_name: str) -> MiniJinjaTemplate:
- """Retrieve a template by matching its name (dotted path) with files in the directory or directories provided.
-
- Args:
- template_name: A dotted path
-
- Returns:
- MiniJinjaTemplate instance
-
- Raises:
- TemplateNotFoundException: if no template is found.
- """
- return MiniJinjaTemplate(self.engine, template_name)
-
- def register_template_callable(
- self, key: str, template_callable: TemplateCallableType[StateProtocol, P, T]
- ) -> None:
- """Register a callable on the template engine.
-
- Args:
- key: The callable key, i.e. the value to use inside the template to call the callable.
- template_callable: A callable to register.
-
- Returns:
- None
- """
- self.engine.add_global(key, pass_state(template_callable))
-
- def render_string(self, template_string: str, context: Mapping[str, Any]) -> str:
- """Render a template from a string with the given context.
-
- Args:
- template_string: The template string to render.
- context: A dictionary of variables to pass to the template.
-
- Returns:
- The rendered template as a string.
- """
- return self.engine.render_str(template_string, **context) # type: ignore[no-any-return]
-
- @classmethod
- def from_environment(cls, minijinja_environment: Environment) -> MiniJinjaTemplateEngine:
- """Create a MiniJinjaTemplateEngine from an existing minijinja Environment instance.
-
- Args:
- minijinja_environment (Environment): A minijinja Environment instance.
-
- Returns:
- MiniJinjaTemplateEngine instance
- """
- return cls(directory=None, engine_instance=minijinja_environment)
-
-
-@pass_state
-def _minijinja_from_state(func: Callable, state: StateProtocol, *args: Any, **kwargs: Any) -> str: # pragma: no cover
- template_context = {"request": state.lookup("request"), "csrf_input": state.lookup("csrf_input")}
- return cast(str, func(template_context, *args, **kwargs))
-
-
-def __getattr__(name: str) -> Any:
- if name == "minijinja_from_state":
- warn_deprecation(
- "2.3.0",
- "minijinja_from_state",
- "import",
- removal_in="3.0.0",
- alternative="Use a callable that receives the minijinja State object as first argument.",
- )
- return _minijinja_from_state
- raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/minijnja.py b/venv/lib/python3.11/site-packages/litestar/contrib/minijnja.py
deleted file mode 100644
index 13c295a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/minijnja.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from __future__ import annotations
-
-from typing import Any
-
-from litestar.utils.deprecation import warn_deprecation
-
-from . import minijinja as _minijinja
-
-
-def __getattr__(name: str) -> Any:
- warn_deprecation(
- "2.3.0",
- "contrib.minijnja",
- "import",
- removal_in="3.0.0",
- alternative="contrib.minijinja",
- )
- return getattr(_minijinja, name)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__init__.py b/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__init__.py
deleted file mode 100644
index 3f93611..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from .config import OpenTelemetryConfig
-from .middleware import OpenTelemetryInstrumentationMiddleware
-
-__all__ = ("OpenTelemetryConfig", "OpenTelemetryInstrumentationMiddleware")
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 799a915..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/_utils.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/_utils.cpython-311.pyc
deleted file mode 100644
index c401f9c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/_utils.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/config.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/config.cpython-311.pyc
deleted file mode 100644
index b41bc7e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/config.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/middleware.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/middleware.cpython-311.pyc
deleted file mode 100644
index 291b510..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/middleware.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/_utils.py b/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/_utils.py
deleted file mode 100644
index 0ba7cb9..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/_utils.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any
-
-from litestar.exceptions import MissingDependencyException
-
-__all__ = ("get_route_details_from_scope",)
-
-
-try:
- import opentelemetry # noqa: F401
-except ImportError as e:
- raise MissingDependencyException("opentelemetry") from e
-
-from opentelemetry.semconv.trace import SpanAttributes
-
-if TYPE_CHECKING:
- from litestar.types import Scope
-
-
-def get_route_details_from_scope(scope: Scope) -> tuple[str, dict[Any, str]]:
- """Retrieve the span name and attributes from the ASGI scope.
-
- Args:
- scope: The ASGI scope instance.
-
- Returns:
- A tuple of the span name and a dict of attrs.
- """
- route_handler_fn_name = scope["route_handler"].handler_name
- return route_handler_fn_name, {SpanAttributes.HTTP_ROUTE: route_handler_fn_name}
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/config.py b/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/config.py
deleted file mode 100644
index c0cce8a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/config.py
+++ /dev/null
@@ -1,102 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass, field
-from typing import TYPE_CHECKING, Any, Callable
-
-from litestar.contrib.opentelemetry._utils import get_route_details_from_scope
-from litestar.contrib.opentelemetry.middleware import (
- OpenTelemetryInstrumentationMiddleware,
-)
-from litestar.exceptions import MissingDependencyException
-from litestar.middleware.base import DefineMiddleware
-
-__all__ = ("OpenTelemetryConfig",)
-
-
-try:
- import opentelemetry # noqa: F401
-except ImportError as e:
- raise MissingDependencyException("opentelemetry") from e
-
-
-from opentelemetry.trace import Span, TracerProvider # pyright: ignore
-
-if TYPE_CHECKING:
- from opentelemetry.metrics import Meter, MeterProvider
-
- from litestar.types import Scope, Scopes
-
-OpenTelemetryHookHandler = Callable[[Span, dict], None]
-
-
-@dataclass
-class OpenTelemetryConfig:
- """Configuration class for the OpenTelemetry middleware.
-
- Consult the [OpenTelemetry ASGI documentation](https://opentelemetry-python-contrib.readthedocs.io/en/latest/instrumentation/asgi/asgi.html) for more info about the configuration options.
- """
-
- scope_span_details_extractor: Callable[[Scope], tuple[str, dict[str, Any]]] = field(
- default=get_route_details_from_scope
- )
- """Callback which should return a string and a tuple, representing the desired default span name and a dictionary
- with any additional span attributes to set.
- """
- server_request_hook_handler: OpenTelemetryHookHandler | None = field(default=None)
- """Optional callback which is called with the server span and ASGI scope object for every incoming request."""
- client_request_hook_handler: OpenTelemetryHookHandler | None = field(default=None)
- """Optional callback which is called with the internal span and an ASGI scope which is sent as a dictionary for when
- the method receive is called.
- """
- client_response_hook_handler: OpenTelemetryHookHandler | None = field(default=None)
- """Optional callback which is called with the internal span and an ASGI event which is sent as a dictionary for when
- the method send is called.
- """
- meter_provider: MeterProvider | None = field(default=None)
- """Optional meter provider to use.
-
- If omitted the current globally configured one is used.
- """
- tracer_provider: TracerProvider | None = field(default=None)
- """Optional tracer provider to use.
-
- If omitted the current globally configured one is used.
- """
- meter: Meter | None = field(default=None)
- """Optional meter to use.
-
- If omitted the provided meter provider or the global one will be used.
- """
- exclude: str | list[str] | None = field(default=None)
- """A pattern or list of patterns to skip in the Allowed Hosts middleware."""
- exclude_opt_key: str | None = field(default=None)
- """An identifier to use on routes to disable hosts check for a particular route."""
- exclude_urls_env_key: str = "LITESTAR"
- """Key to use when checking whether a list of excluded urls is passed via ENV.
-
- OpenTelemetry supports excluding urls by passing an env in the format '{exclude_urls_env_key}_EXCLUDED_URLS'. With
- the default being ``LITESTAR_EXCLUDED_URLS``.
- """
- scopes: Scopes | None = field(default=None)
- """ASGI scopes processed by the middleware, if None both ``http`` and ``websocket`` will be processed."""
- middleware_class: type[OpenTelemetryInstrumentationMiddleware] = field(
- default=OpenTelemetryInstrumentationMiddleware
- )
- """The middleware class to use.
-
- Should be a subclass of OpenTelemetry
- InstrumentationMiddleware][litestar.contrib.opentelemetry.OpenTelemetryInstrumentationMiddleware].
- """
-
- @property
- def middleware(self) -> DefineMiddleware:
- """Create an instance of :class:`DefineMiddleware <litestar.middleware.base.DefineMiddleware>` that wraps with.
-
- [OpenTelemetry
- InstrumentationMiddleware][litestar.contrib.opentelemetry.OpenTelemetryInstrumentationMiddleware] or a subclass
- of this middleware.
-
- Returns:
- An instance of ``DefineMiddleware``.
- """
- return DefineMiddleware(self.middleware_class, config=self)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/middleware.py b/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/middleware.py
deleted file mode 100644
index 762bae9..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/middleware.py
+++ /dev/null
@@ -1,60 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING
-
-from litestar.exceptions import MissingDependencyException
-from litestar.middleware.base import AbstractMiddleware
-
-__all__ = ("OpenTelemetryInstrumentationMiddleware",)
-
-
-try:
- import opentelemetry # noqa: F401
-except ImportError as e:
- raise MissingDependencyException("opentelemetry") from e
-
-from opentelemetry.instrumentation.asgi import OpenTelemetryMiddleware
-from opentelemetry.util.http import get_excluded_urls
-
-if TYPE_CHECKING:
- from litestar.contrib.opentelemetry import OpenTelemetryConfig
- from litestar.types import ASGIApp, Receive, Scope, Send
-
-
-class OpenTelemetryInstrumentationMiddleware(AbstractMiddleware):
- """OpenTelemetry Middleware."""
-
- __slots__ = ("open_telemetry_middleware",)
-
- def __init__(self, app: ASGIApp, config: OpenTelemetryConfig) -> None:
- """Middleware that adds OpenTelemetry instrumentation to the application.
-
- Args:
- app: The ``next`` ASGI app to call.
- config: An instance of :class:`OpenTelemetryConfig <.contrib.opentelemetry.OpenTelemetryConfig>`
- """
- super().__init__(app=app, scopes=config.scopes, exclude=config.exclude, exclude_opt_key=config.exclude_opt_key)
- self.open_telemetry_middleware = OpenTelemetryMiddleware(
- app=app,
- client_request_hook=config.client_request_hook_handler,
- client_response_hook=config.client_response_hook_handler,
- default_span_details=config.scope_span_details_extractor,
- excluded_urls=get_excluded_urls(config.exclude_urls_env_key),
- meter=config.meter,
- meter_provider=config.meter_provider,
- server_request_hook=config.server_request_hook_handler,
- tracer_provider=config.tracer_provider,
- )
-
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
- """ASGI callable.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
- await self.open_telemetry_middleware(scope, receive, send) # type: ignore[arg-type] # pyright: ignore[reportGeneralTypeIssues]
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/piccolo.py b/venv/lib/python3.11/site-packages/litestar/contrib/piccolo.py
deleted file mode 100644
index 73bd271..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/piccolo.py
+++ /dev/null
@@ -1,107 +0,0 @@
-from __future__ import annotations
-
-import warnings
-from dataclasses import replace
-from decimal import Decimal
-from typing import Any, Generator, Generic, List, Optional, TypeVar
-
-from msgspec import Meta
-from typing_extensions import Annotated
-
-from litestar.dto import AbstractDTO, DTOField, Mark
-from litestar.dto.data_structures import DTOFieldDefinition
-from litestar.exceptions import LitestarWarning, MissingDependencyException
-from litestar.types import Empty
-from litestar.typing import FieldDefinition
-from litestar.utils import warn_deprecation
-
-try:
- from piccolo.columns import Column, column_types
- from piccolo.table import Table
-except ImportError as e:
- raise MissingDependencyException("piccolo") from e
-
-
-T = TypeVar("T", bound=Table)
-
-__all__ = ("PiccoloDTO",)
-
-
-def __getattr__(name: str) -> Any:
- warn_deprecation(
- deprecated_name=f"litestar.contrib.piccolo.{name}",
- version="2.3.2",
- kind="import",
- removal_in="3.0.0",
- info="importing from 'litestar.contrib.piccolo' is deprecated and will be removed in 3.0, please import from 'litestar_piccolo' package directly instead",
- )
- return getattr(name, name)
-
-
-def _parse_piccolo_type(column: Column, extra: dict[str, Any]) -> FieldDefinition:
- is_optional = not column._meta.required
-
- if isinstance(column, (column_types.Decimal, column_types.Numeric)):
- column_type: Any = Decimal
- meta = Meta(extra=extra)
- elif isinstance(column, (column_types.Email, column_types.Varchar)):
- column_type = str
- if is_optional:
- meta = Meta(extra=extra)
- warnings.warn(
- f"Dropping max_length constraint for column {column!r} because the " "column is optional",
- category=LitestarWarning,
- stacklevel=2,
- )
- else:
- meta = Meta(max_length=column.length, extra=extra)
- elif isinstance(column, column_types.Array):
- column_type = List[column.base_column.value_type] # type: ignore[name-defined]
- meta = Meta(extra=extra)
- elif isinstance(column, (column_types.JSON, column_types.JSONB)):
- column_type = str
- meta = Meta(extra={**extra, "format": "json"})
- elif isinstance(column, column_types.Text):
- column_type = str
- meta = Meta(extra={**extra, "format": "text-area"})
- else:
- column_type = column.value_type
- meta = Meta(extra=extra)
-
- if is_optional:
- column_type = Optional[column_type]
-
- return FieldDefinition.from_annotation(Annotated[column_type, meta])
-
-
-def _create_column_extra(column: Column) -> dict[str, Any]:
- extra: dict[str, Any] = {}
-
- if column._meta.help_text:
- extra["description"] = column._meta.help_text
-
- if column._meta.get_choices_dict():
- extra["enum"] = column._meta.get_choices_dict()
-
- return extra
-
-
-class PiccoloDTO(AbstractDTO[T], Generic[T]):
- @classmethod
- def generate_field_definitions(cls, model_type: type[Table]) -> Generator[DTOFieldDefinition, None, None]:
- for column in model_type._meta.columns:
- mark = Mark.WRITE_ONLY if column._meta.secret else Mark.READ_ONLY if column._meta.primary_key else None
- yield replace(
- DTOFieldDefinition.from_field_definition(
- field_definition=_parse_piccolo_type(column, _create_column_extra(column)),
- dto_field=DTOField(mark=mark),
- model_name=model_type.__name__,
- default_factory=None,
- ),
- default=Empty if column._meta.required else None,
- name=column._meta.name,
- )
-
- @classmethod
- def detect_nested_field(cls, field_definition: FieldDefinition) -> bool:
- return field_definition.is_subclass_of(Table)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__init__.py b/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__init__.py
deleted file mode 100644
index 1ccb494..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from .config import PrometheusConfig
-from .controller import PrometheusController
-from .middleware import PrometheusMiddleware
-
-__all__ = ("PrometheusMiddleware", "PrometheusConfig", "PrometheusController")
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index c6c5558..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/config.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/config.cpython-311.pyc
deleted file mode 100644
index a998104..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/config.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/controller.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/controller.cpython-311.pyc
deleted file mode 100644
index 012b4be..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/controller.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/middleware.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/middleware.cpython-311.pyc
deleted file mode 100644
index 2c08508..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/middleware.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/config.py b/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/config.py
deleted file mode 100644
index b77dab0..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/config.py
+++ /dev/null
@@ -1,64 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass, field
-from typing import TYPE_CHECKING, Callable, Mapping, Sequence
-
-from litestar.contrib.prometheus.middleware import (
- PrometheusMiddleware,
-)
-from litestar.exceptions import MissingDependencyException
-from litestar.middleware.base import DefineMiddleware
-
-__all__ = ("PrometheusConfig",)
-
-
-try:
- import prometheus_client # noqa: F401
-except ImportError as e:
- raise MissingDependencyException("prometheus_client", "prometheus-client", "prometheus") from e
-
-
-if TYPE_CHECKING:
- from litestar.connection.request import Request
- from litestar.types import Method, Scopes
-
-
-@dataclass
-class PrometheusConfig:
- """Configuration class for the PrometheusConfig middleware."""
-
- app_name: str = field(default="litestar")
- """The name of the application to use in the metrics."""
- prefix: str = "litestar"
- """The prefix to use for the metrics."""
- labels: Mapping[str, str | Callable] | None = field(default=None)
- """A mapping of labels to add to the metrics. The values can be either a string or a callable that returns a string."""
- exemplars: Callable[[Request], dict] | None = field(default=None)
- """A callable that returns a list of exemplars to add to the metrics. Only supported in opementrics-text exposition format."""
- buckets: list[str | float] | None = field(default=None)
- """A list of buckets to use for the histogram."""
- excluded_http_methods: Method | Sequence[Method] | None = field(default=None)
- """A list of http methods to exclude from the metrics."""
- exclude_unhandled_paths: bool = field(default=False)
- """Whether to ignore requests for unhandled paths from the metrics."""
- exclude: str | list[str] | None = field(default=None)
- """A pattern or list of patterns for routes to exclude from the metrics."""
- exclude_opt_key: str | None = field(default=None)
- """A key or list of keys in ``opt`` with which a route handler can "opt-out" of the middleware."""
- scopes: Scopes | None = field(default=None)
- """ASGI scopes processed by the middleware, if None both ``http`` and ``websocket`` will be processed."""
- middleware_class: type[PrometheusMiddleware] = field(default=PrometheusMiddleware)
- """The middleware class to use.
- """
-
- @property
- def middleware(self) -> DefineMiddleware:
- """Create an instance of :class:`DefineMiddleware <litestar.middleware.base.DefineMiddleware>` that wraps with.
-
- [PrometheusMiddleware][litestar.contrib.prometheus.PrometheusMiddleware]. or a subclass
- of this middleware.
-
- Returns:
- An instance of ``DefineMiddleware``.
- """
- return DefineMiddleware(self.middleware_class, config=self)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/controller.py b/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/controller.py
deleted file mode 100644
index 15f5bf1..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/controller.py
+++ /dev/null
@@ -1,53 +0,0 @@
-from __future__ import annotations
-
-import os
-
-from litestar import Controller, get
-from litestar.exceptions import MissingDependencyException
-from litestar.response import Response
-
-try:
- import prometheus_client # noqa: F401
-except ImportError as e:
- raise MissingDependencyException("prometheus_client", "prometheus-client", "prometheus") from e
-
-from prometheus_client import (
- CONTENT_TYPE_LATEST,
- REGISTRY,
- CollectorRegistry,
- generate_latest,
- multiprocess,
-)
-from prometheus_client.openmetrics.exposition import (
- CONTENT_TYPE_LATEST as OPENMETRICS_CONTENT_TYPE_LATEST,
-)
-from prometheus_client.openmetrics.exposition import (
- generate_latest as openmetrics_generate_latest,
-)
-
-__all__ = [
- "PrometheusController",
-]
-
-
-class PrometheusController(Controller):
- """Controller for Prometheus endpoints."""
-
- path: str = "/metrics"
- """The path to expose the metrics on."""
- openmetrics_format: bool = False
- """Whether to expose the metrics in OpenMetrics format."""
-
- @get()
- async def get(self) -> Response:
- registry = REGISTRY
- if "prometheus_multiproc_dir" in os.environ or "PROMETHEUS_MULTIPROC_DIR" in os.environ:
- registry = CollectorRegistry()
- multiprocess.MultiProcessCollector(registry) # type: ignore[no-untyped-call]
-
- if self.openmetrics_format:
- headers = {"Content-Type": OPENMETRICS_CONTENT_TYPE_LATEST}
- return Response(openmetrics_generate_latest(registry), status_code=200, headers=headers) # type: ignore[no-untyped-call]
-
- headers = {"Content-Type": CONTENT_TYPE_LATEST}
- return Response(generate_latest(registry), status_code=200, headers=headers)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/middleware.py b/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/middleware.py
deleted file mode 100644
index 50bc7cb..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/middleware.py
+++ /dev/null
@@ -1,181 +0,0 @@
-from __future__ import annotations
-
-import time
-from functools import wraps
-from typing import TYPE_CHECKING, Any, Callable, ClassVar, cast
-
-from litestar.connection.request import Request
-from litestar.enums import ScopeType
-from litestar.exceptions import MissingDependencyException
-from litestar.middleware.base import AbstractMiddleware
-
-__all__ = ("PrometheusMiddleware",)
-
-from litestar.status_codes import HTTP_500_INTERNAL_SERVER_ERROR
-
-try:
- import prometheus_client # noqa: F401
-except ImportError as e:
- raise MissingDependencyException("prometheus_client", "prometheus-client", "prometheus") from e
-
-from prometheus_client import Counter, Gauge, Histogram
-
-if TYPE_CHECKING:
- from prometheus_client.metrics import MetricWrapperBase
-
- from litestar.contrib.prometheus import PrometheusConfig
- from litestar.types import ASGIApp, Message, Receive, Scope, Send
-
-
-class PrometheusMiddleware(AbstractMiddleware):
- """Prometheus Middleware."""
-
- _metrics: ClassVar[dict[str, MetricWrapperBase]] = {}
-
- def __init__(self, app: ASGIApp, config: PrometheusConfig) -> None:
- """Middleware that adds Prometheus instrumentation to the application.
-
- Args:
- app: The ``next`` ASGI app to call.
- config: An instance of :class:`PrometheusConfig <.contrib.prometheus.PrometheusConfig>`
- """
- super().__init__(app=app, scopes=config.scopes, exclude=config.exclude, exclude_opt_key=config.exclude_opt_key)
- self._config = config
- self._kwargs: dict[str, Any] = {}
-
- if self._config.buckets is not None:
- self._kwargs["buckets"] = self._config.buckets
-
- def request_count(self, labels: dict[str, str | int | float]) -> Counter:
- metric_name = f"{self._config.prefix}_requests_total"
-
- if metric_name not in PrometheusMiddleware._metrics:
- PrometheusMiddleware._metrics[metric_name] = Counter(
- name=metric_name,
- documentation="Total requests",
- labelnames=[*labels.keys()],
- )
-
- return cast("Counter", PrometheusMiddleware._metrics[metric_name])
-
- def request_time(self, labels: dict[str, str | int | float]) -> Histogram:
- metric_name = f"{self._config.prefix}_request_duration_seconds"
-
- if metric_name not in PrometheusMiddleware._metrics:
- PrometheusMiddleware._metrics[metric_name] = Histogram(
- name=metric_name,
- documentation="Request duration, in seconds",
- labelnames=[*labels.keys()],
- **self._kwargs,
- )
- return cast("Histogram", PrometheusMiddleware._metrics[metric_name])
-
- def requests_in_progress(self, labels: dict[str, str | int | float]) -> Gauge:
- metric_name = f"{self._config.prefix}_requests_in_progress"
-
- if metric_name not in PrometheusMiddleware._metrics:
- PrometheusMiddleware._metrics[metric_name] = Gauge(
- name=metric_name,
- documentation="Total requests currently in progress",
- labelnames=[*labels.keys()],
- multiprocess_mode="livesum",
- )
- return cast("Gauge", PrometheusMiddleware._metrics[metric_name])
-
- def requests_error_count(self, labels: dict[str, str | int | float]) -> Counter:
- metric_name = f"{self._config.prefix}_requests_error_total"
-
- if metric_name not in PrometheusMiddleware._metrics:
- PrometheusMiddleware._metrics[metric_name] = Counter(
- name=metric_name,
- documentation="Total errors in requests",
- labelnames=[*labels.keys()],
- )
- return cast("Counter", PrometheusMiddleware._metrics[metric_name])
-
- def _get_extra_labels(self, request: Request[Any, Any, Any]) -> dict[str, str]:
- """Get extra labels provided by the config and if they are callable, parse them.
-
- Args:
- request: The request object.
-
- Returns:
- A dictionary of extra labels.
- """
-
- return {k: str(v(request) if callable(v) else v) for k, v in (self._config.labels or {}).items()}
-
- def _get_default_labels(self, request: Request[Any, Any, Any]) -> dict[str, str | int | float]:
- """Get default label values from the request.
-
- Args:
- request: The request object.
-
- Returns:
- A dictionary of default labels.
- """
-
- return {
- "method": request.method if request.scope["type"] == ScopeType.HTTP else request.scope["type"],
- "path": request.url.path,
- "status_code": 200,
- "app_name": self._config.app_name,
- }
-
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
- """ASGI callable.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
-
- request = Request[Any, Any, Any](scope, receive)
-
- if self._config.excluded_http_methods and request.method in self._config.excluded_http_methods:
- await self.app(scope, receive, send)
- return
-
- labels = {**self._get_default_labels(request), **self._get_extra_labels(request)}
-
- request_span = {"start_time": time.perf_counter(), "end_time": 0, "duration": 0, "status_code": 200}
-
- wrapped_send = self._get_wrapped_send(send, request_span)
-
- self.requests_in_progress(labels).labels(*labels.values()).inc()
-
- try:
- await self.app(scope, receive, wrapped_send)
- finally:
- extra: dict[str, Any] = {}
- if self._config.exemplars:
- extra["exemplar"] = self._config.exemplars(request)
-
- self.requests_in_progress(labels).labels(*labels.values()).dec()
-
- labels["status_code"] = request_span["status_code"]
- label_values = [*labels.values()]
-
- if request_span["status_code"] >= HTTP_500_INTERNAL_SERVER_ERROR:
- self.requests_error_count(labels).labels(*label_values).inc(**extra)
-
- self.request_count(labels).labels(*label_values).inc(**extra)
- self.request_time(labels).labels(*label_values).observe(request_span["duration"], **extra)
-
- def _get_wrapped_send(self, send: Send, request_span: dict[str, float]) -> Callable:
- @wraps(send)
- async def wrapped_send(message: Message) -> None:
- if message["type"] == "http.response.start":
- request_span["status_code"] = message["status"]
-
- if message["type"] == "http.response.body":
- end = time.perf_counter()
- request_span["duration"] = end - request_span["start_time"]
- request_span["end_time"] = end
- await send(message)
-
- return wrapped_send
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__init__.py b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__init__.py
deleted file mode 100644
index 9bab707..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__init__.py
+++ /dev/null
@@ -1,69 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any
-
-from litestar.plugins import InitPluginProtocol
-
-from .pydantic_di_plugin import PydanticDIPlugin
-from .pydantic_dto_factory import PydanticDTO
-from .pydantic_init_plugin import PydanticInitPlugin
-from .pydantic_schema_plugin import PydanticSchemaPlugin
-
-if TYPE_CHECKING:
- from pydantic import BaseModel
- from pydantic.v1 import BaseModel as BaseModelV1
-
- from litestar.config.app import AppConfig
-
-__all__ = (
- "PydanticDTO",
- "PydanticInitPlugin",
- "PydanticSchemaPlugin",
- "PydanticPlugin",
- "PydanticDIPlugin",
-)
-
-
-def _model_dump(model: BaseModel | BaseModelV1, *, by_alias: bool = False) -> dict[str, Any]:
- return (
- model.model_dump(mode="json", by_alias=by_alias) # pyright: ignore
- if hasattr(model, "model_dump")
- else {k: v.decode() if isinstance(v, bytes) else v for k, v in model.dict(by_alias=by_alias).items()}
- )
-
-
-def _model_dump_json(model: BaseModel | BaseModelV1, by_alias: bool = False) -> str:
- return (
- model.model_dump_json(by_alias=by_alias) # pyright: ignore
- if hasattr(model, "model_dump_json")
- else model.json(by_alias=by_alias) # pyright: ignore
- )
-
-
-class PydanticPlugin(InitPluginProtocol):
- """A plugin that provides Pydantic integration."""
-
- __slots__ = ("prefer_alias",)
-
- def __init__(self, prefer_alias: bool = False) -> None:
- """Initialize ``PydanticPlugin``.
-
- Args:
- prefer_alias: OpenAPI and ``type_encoders`` will export by alias
- """
- self.prefer_alias = prefer_alias
-
- def on_app_init(self, app_config: AppConfig) -> AppConfig:
- """Configure application for use with Pydantic.
-
- Args:
- app_config: The :class:`AppConfig <.config.app.AppConfig>` instance.
- """
- app_config.plugins.extend(
- [
- PydanticInitPlugin(prefer_alias=self.prefer_alias),
- PydanticSchemaPlugin(prefer_alias=self.prefer_alias),
- PydanticDIPlugin(),
- ]
- )
- return app_config
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index a62eb0f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/config.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/config.cpython-311.pyc
deleted file mode 100644
index 5515df6..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/config.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_di_plugin.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_di_plugin.cpython-311.pyc
deleted file mode 100644
index f8c4e00..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_di_plugin.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_dto_factory.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_dto_factory.cpython-311.pyc
deleted file mode 100644
index 490108e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_dto_factory.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_init_plugin.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_init_plugin.cpython-311.pyc
deleted file mode 100644
index 13788d4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_init_plugin.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_schema_plugin.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_schema_plugin.cpython-311.pyc
deleted file mode 100644
index 8b0946b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_schema_plugin.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/utils.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/utils.cpython-311.pyc
deleted file mode 100644
index dbb0e54..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/utils.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/config.py b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/config.py
deleted file mode 100644
index e69de29..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/config.py
+++ /dev/null
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_di_plugin.py b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_di_plugin.py
deleted file mode 100644
index 2096fd4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_di_plugin.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from __future__ import annotations
-
-import inspect
-from inspect import Signature
-from typing import Any
-
-from litestar.contrib.pydantic.utils import is_pydantic_model_class
-from litestar.plugins import DIPlugin
-
-
-class PydanticDIPlugin(DIPlugin):
- def has_typed_init(self, type_: Any) -> bool:
- return is_pydantic_model_class(type_)
-
- def get_typed_init(self, type_: Any) -> tuple[Signature, dict[str, Any]]:
- try:
- model_fields = dict(type_.model_fields)
- except AttributeError:
- model_fields = {k: model_field.field_info for k, model_field in type_.__fields__.items()}
-
- parameters = [
- inspect.Parameter(name=field_name, kind=inspect.Parameter.KEYWORD_ONLY, annotation=Any)
- for field_name in model_fields
- ]
- type_hints = {field_name: Any for field_name in model_fields}
- return Signature(parameters), type_hints
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_dto_factory.py b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_dto_factory.py
deleted file mode 100644
index d61f95d..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_dto_factory.py
+++ /dev/null
@@ -1,110 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import replace
-from typing import TYPE_CHECKING, Collection, Generic, TypeVar
-
-from typing_extensions import TypeAlias, override
-
-from litestar.contrib.pydantic.utils import is_pydantic_undefined
-from litestar.dto.base_dto import AbstractDTO
-from litestar.dto.data_structures import DTOFieldDefinition
-from litestar.dto.field import DTO_FIELD_META_KEY, DTOField
-from litestar.exceptions import MissingDependencyException, ValidationException
-from litestar.types.empty import Empty
-
-if TYPE_CHECKING:
- from typing import Any, Generator
-
- from litestar.typing import FieldDefinition
-
-try:
- import pydantic as _ # noqa: F401
-except ImportError as e:
- raise MissingDependencyException("pydantic") from e
-
-
-try:
- import pydantic as pydantic_v2
- from pydantic import ValidationError as ValidationErrorV2
- from pydantic import v1 as pydantic_v1
- from pydantic.v1 import ValidationError as ValidationErrorV1
-
- ModelType: TypeAlias = "pydantic_v1.BaseModel | pydantic_v2.BaseModel"
-
-except ImportError:
- import pydantic as pydantic_v1 # type: ignore[no-redef]
-
- pydantic_v2 = Empty # type: ignore[assignment]
- from pydantic import ValidationError as ValidationErrorV1 # type: ignore[assignment]
-
- ValidationErrorV2 = ValidationErrorV1 # type: ignore[assignment, misc]
- ModelType = "pydantic_v1.BaseModel" # type: ignore[misc]
-
-
-T = TypeVar("T", bound="ModelType | Collection[ModelType]")
-
-
-__all__ = ("PydanticDTO",)
-
-
-class PydanticDTO(AbstractDTO[T], Generic[T]):
- """Support for domain modelling with Pydantic."""
-
- @override
- def decode_builtins(self, value: dict[str, Any]) -> Any:
- try:
- return super().decode_builtins(value)
- except (ValidationErrorV2, ValidationErrorV1) as ex:
- raise ValidationException(extra=ex.errors()) from ex
-
- @override
- def decode_bytes(self, value: bytes) -> Any:
- try:
- return super().decode_bytes(value)
- except (ValidationErrorV2, ValidationErrorV1) as ex:
- raise ValidationException(extra=ex.errors()) from ex
-
- @classmethod
- def generate_field_definitions(
- cls, model_type: type[pydantic_v1.BaseModel | pydantic_v2.BaseModel]
- ) -> Generator[DTOFieldDefinition, None, None]:
- model_field_definitions = cls.get_model_type_hints(model_type)
-
- model_fields: dict[str, pydantic_v1.fields.FieldInfo | pydantic_v2.fields.FieldInfo]
- try:
- model_fields = dict(model_type.model_fields) # type: ignore[union-attr]
- except AttributeError:
- model_fields = {
- k: model_field.field_info
- for k, model_field in model_type.__fields__.items() # type: ignore[union-attr]
- }
-
- for field_name, field_info in model_fields.items():
- field_definition = model_field_definitions[field_name]
- dto_field = (field_definition.extra or {}).pop(DTO_FIELD_META_KEY, DTOField())
-
- if not is_pydantic_undefined(field_info.default):
- default = field_info.default
- elif field_definition.is_optional:
- default = None
- else:
- default = Empty
-
- yield replace(
- DTOFieldDefinition.from_field_definition(
- field_definition=field_definition,
- dto_field=dto_field,
- model_name=model_type.__name__,
- default_factory=field_info.default_factory
- if field_info.default_factory and not is_pydantic_undefined(field_info.default_factory)
- else None,
- ),
- default=default,
- name=field_name,
- )
-
- @classmethod
- def detect_nested_field(cls, field_definition: FieldDefinition) -> bool:
- if pydantic_v2 is not Empty: # type: ignore[comparison-overlap]
- return field_definition.is_subclass_of((pydantic_v1.BaseModel, pydantic_v2.BaseModel))
- return field_definition.is_subclass_of(pydantic_v1.BaseModel) # type: ignore[unreachable]
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_init_plugin.py b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_init_plugin.py
deleted file mode 100644
index 1261cd8..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_init_plugin.py
+++ /dev/null
@@ -1,182 +0,0 @@
-from __future__ import annotations
-
-from contextlib import suppress
-from typing import TYPE_CHECKING, Any, Callable, TypeVar, cast
-from uuid import UUID
-
-from msgspec import ValidationError
-from typing_extensions import Buffer, TypeGuard
-
-from litestar._signature.types import ExtendedMsgSpecValidationError
-from litestar.contrib.pydantic.utils import is_pydantic_constrained_field
-from litestar.exceptions import MissingDependencyException
-from litestar.plugins import InitPluginProtocol
-from litestar.typing import _KWARG_META_EXTRACTORS
-from litestar.utils import is_class_and_subclass
-
-try:
- # check if we have pydantic v2 installed, and try to import both versions
- import pydantic as pydantic_v2
- from pydantic import v1 as pydantic_v1
-except ImportError:
- # check if pydantic 1 is installed and import it
- try:
- import pydantic as pydantic_v1 # type: ignore[no-redef]
-
- pydantic_v2 = None # type: ignore[assignment]
- except ImportError as e:
- raise MissingDependencyException("pydantic") from e
-
-
-if TYPE_CHECKING:
- from litestar.config.app import AppConfig
-
-
-T = TypeVar("T")
-
-
-def _dec_pydantic_v1(model_type: type[pydantic_v1.BaseModel], value: Any) -> pydantic_v1.BaseModel:
- try:
- return model_type.parse_obj(value)
- except pydantic_v1.ValidationError as e:
- raise ExtendedMsgSpecValidationError(errors=cast("list[dict[str, Any]]", e.errors())) from e
-
-
-def _dec_pydantic_v2(model_type: type[pydantic_v2.BaseModel], value: Any) -> pydantic_v2.BaseModel:
- try:
- return model_type.model_validate(value, strict=False)
- except pydantic_v2.ValidationError as e:
- raise ExtendedMsgSpecValidationError(errors=cast("list[dict[str, Any]]", e.errors())) from e
-
-
-def _dec_pydantic_uuid(
- uuid_type: type[pydantic_v1.UUID1] | type[pydantic_v1.UUID3] | type[pydantic_v1.UUID4] | type[pydantic_v1.UUID5],
- value: Any,
-) -> (
- type[pydantic_v1.UUID1] | type[pydantic_v1.UUID3] | type[pydantic_v1.UUID4] | type[pydantic_v1.UUID5]
-): # pragma: no cover
- if isinstance(value, str):
- value = uuid_type(value)
-
- elif isinstance(value, Buffer):
- value = bytes(value)
- try:
- value = uuid_type(value.decode())
- except ValueError:
- # 16 bytes in big-endian order as the bytes argument fail
- # the above check
- value = uuid_type(bytes=value)
- elif isinstance(value, UUID):
- value = uuid_type(str(value))
-
- if not isinstance(value, uuid_type):
- raise ValidationError(f"Invalid UUID: {value!r}")
-
- if value._required_version != value.version:
- raise ValidationError(f"Invalid UUID version: {value!r}")
-
- return cast(
- "type[pydantic_v1.UUID1] | type[pydantic_v1.UUID3] | type[pydantic_v1.UUID4] | type[pydantic_v1.UUID5]", value
- )
-
-
-def _is_pydantic_v1_uuid(value: Any) -> bool: # pragma: no cover
- return is_class_and_subclass(value, (pydantic_v1.UUID1, pydantic_v1.UUID3, pydantic_v1.UUID4, pydantic_v1.UUID5))
-
-
-_base_encoders: dict[Any, Callable[[Any], Any]] = {
- pydantic_v1.EmailStr: str,
- pydantic_v1.NameEmail: str,
- pydantic_v1.ByteSize: lambda val: val.real,
-}
-
-if pydantic_v2 is not None: # pragma: no cover
- _base_encoders.update(
- {
- pydantic_v2.EmailStr: str,
- pydantic_v2.NameEmail: str,
- pydantic_v2.ByteSize: lambda val: val.real,
- }
- )
-
-
-def is_pydantic_v1_model_class(annotation: Any) -> TypeGuard[type[pydantic_v1.BaseModel]]:
- return is_class_and_subclass(annotation, pydantic_v1.BaseModel)
-
-
-def is_pydantic_v2_model_class(annotation: Any) -> TypeGuard[type[pydantic_v2.BaseModel]]:
- return is_class_and_subclass(annotation, pydantic_v2.BaseModel)
-
-
-class ConstrainedFieldMetaExtractor:
- @staticmethod
- def matches(annotation: Any, name: str | None, default: Any) -> bool:
- return is_pydantic_constrained_field(annotation)
-
- @staticmethod
- def extract(annotation: Any, default: Any) -> Any:
- return [annotation]
-
-
-class PydanticInitPlugin(InitPluginProtocol):
- __slots__ = ("prefer_alias",)
-
- def __init__(self, prefer_alias: bool = False) -> None:
- self.prefer_alias = prefer_alias
-
- @classmethod
- def encoders(cls, prefer_alias: bool = False) -> dict[Any, Callable[[Any], Any]]:
- encoders = {**_base_encoders, **cls._create_pydantic_v1_encoders(prefer_alias)}
- if pydantic_v2 is not None: # pragma: no cover
- encoders.update(cls._create_pydantic_v2_encoders(prefer_alias))
- return encoders
-
- @classmethod
- def decoders(cls) -> list[tuple[Callable[[Any], bool], Callable[[Any, Any], Any]]]:
- decoders: list[tuple[Callable[[Any], bool], Callable[[Any, Any], Any]]] = [
- (is_pydantic_v1_model_class, _dec_pydantic_v1)
- ]
-
- if pydantic_v2 is not None: # pragma: no cover
- decoders.append((is_pydantic_v2_model_class, _dec_pydantic_v2))
-
- decoders.append((_is_pydantic_v1_uuid, _dec_pydantic_uuid))
-
- return decoders
-
- @staticmethod
- def _create_pydantic_v1_encoders(prefer_alias: bool = False) -> dict[Any, Callable[[Any], Any]]: # pragma: no cover
- return {
- pydantic_v1.BaseModel: lambda model: {
- k: v.decode() if isinstance(v, bytes) else v for k, v in model.dict(by_alias=prefer_alias).items()
- },
- pydantic_v1.SecretField: str,
- pydantic_v1.StrictBool: int,
- pydantic_v1.color.Color: str,
- pydantic_v1.ConstrainedBytes: lambda val: val.decode("utf-8"),
- pydantic_v1.ConstrainedDate: lambda val: val.isoformat(),
- pydantic_v1.AnyUrl: str,
- }
-
- @staticmethod
- def _create_pydantic_v2_encoders(prefer_alias: bool = False) -> dict[Any, Callable[[Any], Any]]:
- encoders: dict[Any, Callable[[Any], Any]] = {
- pydantic_v2.BaseModel: lambda model: model.model_dump(mode="json", by_alias=prefer_alias),
- pydantic_v2.types.SecretStr: lambda val: "**********" if val else "",
- pydantic_v2.types.SecretBytes: lambda val: "**********" if val else "",
- pydantic_v2.AnyUrl: str,
- }
-
- with suppress(ImportError):
- from pydantic_extra_types import color
-
- encoders[color.Color] = str
-
- return encoders
-
- def on_app_init(self, app_config: AppConfig) -> AppConfig:
- app_config.type_encoders = {**self.encoders(self.prefer_alias), **(app_config.type_encoders or {})}
- app_config.type_decoders = [*self.decoders(), *(app_config.type_decoders or [])]
-
- _KWARG_META_EXTRACTORS.add(ConstrainedFieldMetaExtractor)
- return app_config
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_schema_plugin.py b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_schema_plugin.py
deleted file mode 100644
index 2c189e4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_schema_plugin.py
+++ /dev/null
@@ -1,317 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any, Optional
-
-from typing_extensions import Annotated
-
-from litestar.contrib.pydantic.utils import (
- create_field_definitions_for_computed_fields,
- is_pydantic_2_model,
- is_pydantic_constrained_field,
- is_pydantic_model_class,
- is_pydantic_undefined,
- pydantic_get_type_hints_with_generics_resolved,
- pydantic_unwrap_and_get_origin,
-)
-from litestar.exceptions import MissingDependencyException
-from litestar.openapi.spec import OpenAPIFormat, OpenAPIType, Schema
-from litestar.plugins import OpenAPISchemaPlugin
-from litestar.types import Empty
-from litestar.typing import FieldDefinition
-from litestar.utils import is_class_and_subclass, is_generic
-
-try:
- # check if we have pydantic v2 installed, and try to import both versions
- import pydantic as pydantic_v2
- from pydantic import v1 as pydantic_v1
-except ImportError:
- # check if pydantic 1 is installed and import it
- try:
- import pydantic as pydantic_v1 # type: ignore[no-redef]
-
- pydantic_v2 = None # type: ignore[assignment]
- except ImportError as e:
- raise MissingDependencyException("pydantic") from e
-
-if TYPE_CHECKING:
- from litestar._openapi.schema_generation.schema import SchemaCreator
-
-PYDANTIC_TYPE_MAP: dict[type[Any] | None | Any, Schema] = {
- pydantic_v1.ByteSize: Schema(type=OpenAPIType.INTEGER),
- pydantic_v1.EmailStr: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.EMAIL),
- pydantic_v1.IPvAnyAddress: Schema(
- one_of=[
- Schema(
- type=OpenAPIType.STRING,
- format=OpenAPIFormat.IPV4,
- description="IPv4 address",
- ),
- Schema(
- type=OpenAPIType.STRING,
- format=OpenAPIFormat.IPV6,
- description="IPv6 address",
- ),
- ]
- ),
- pydantic_v1.IPvAnyInterface: Schema(
- one_of=[
- Schema(
- type=OpenAPIType.STRING,
- format=OpenAPIFormat.IPV4,
- description="IPv4 interface",
- ),
- Schema(
- type=OpenAPIType.STRING,
- format=OpenAPIFormat.IPV6,
- description="IPv6 interface",
- ),
- ]
- ),
- pydantic_v1.IPvAnyNetwork: Schema(
- one_of=[
- Schema(
- type=OpenAPIType.STRING,
- format=OpenAPIFormat.IPV4,
- description="IPv4 network",
- ),
- Schema(
- type=OpenAPIType.STRING,
- format=OpenAPIFormat.IPV6,
- description="IPv6 network",
- ),
- ]
- ),
- pydantic_v1.Json: Schema(type=OpenAPIType.OBJECT, format=OpenAPIFormat.JSON_POINTER),
- pydantic_v1.NameEmail: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.EMAIL, description="Name and email"),
- # removed in v2
- pydantic_v1.PyObject: Schema(
- type=OpenAPIType.STRING,
- description="dot separated path identifying a python object, e.g. 'decimal.Decimal'",
- ),
- # annotated in v2
- pydantic_v1.UUID1: Schema(
- type=OpenAPIType.STRING,
- format=OpenAPIFormat.UUID,
- description="UUID1 string",
- ),
- pydantic_v1.UUID3: Schema(
- type=OpenAPIType.STRING,
- format=OpenAPIFormat.UUID,
- description="UUID3 string",
- ),
- pydantic_v1.UUID4: Schema(
- type=OpenAPIType.STRING,
- format=OpenAPIFormat.UUID,
- description="UUID4 string",
- ),
- pydantic_v1.UUID5: Schema(
- type=OpenAPIType.STRING,
- format=OpenAPIFormat.UUID,
- description="UUID5 string",
- ),
- pydantic_v1.DirectoryPath: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.URI_REFERENCE),
- pydantic_v1.AnyUrl: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.URL),
- pydantic_v1.AnyHttpUrl: Schema(
- type=OpenAPIType.STRING, format=OpenAPIFormat.URL, description="must be a valid HTTP based URL"
- ),
- pydantic_v1.FilePath: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.URI_REFERENCE),
- pydantic_v1.HttpUrl: Schema(
- type=OpenAPIType.STRING,
- format=OpenAPIFormat.URL,
- description="must be a valid HTTP based URL",
- max_length=2083,
- ),
- pydantic_v1.RedisDsn: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.URI, description="redis DSN"),
- pydantic_v1.PostgresDsn: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.URI, description="postgres DSN"),
- pydantic_v1.SecretBytes: Schema(type=OpenAPIType.STRING),
- pydantic_v1.SecretStr: Schema(type=OpenAPIType.STRING),
- pydantic_v1.StrictBool: Schema(type=OpenAPIType.BOOLEAN),
- pydantic_v1.StrictBytes: Schema(type=OpenAPIType.STRING),
- pydantic_v1.StrictFloat: Schema(type=OpenAPIType.NUMBER),
- pydantic_v1.StrictInt: Schema(type=OpenAPIType.INTEGER),
- pydantic_v1.StrictStr: Schema(type=OpenAPIType.STRING),
- pydantic_v1.NegativeFloat: Schema(type=OpenAPIType.NUMBER, exclusive_maximum=0.0),
- pydantic_v1.NegativeInt: Schema(type=OpenAPIType.INTEGER, exclusive_maximum=0),
- pydantic_v1.NonNegativeInt: Schema(type=OpenAPIType.INTEGER, minimum=0),
- pydantic_v1.NonPositiveFloat: Schema(type=OpenAPIType.NUMBER, maximum=0.0),
- pydantic_v1.PaymentCardNumber: Schema(type=OpenAPIType.STRING, min_length=12, max_length=19),
- pydantic_v1.PositiveFloat: Schema(type=OpenAPIType.NUMBER, exclusive_minimum=0.0),
- pydantic_v1.PositiveInt: Schema(type=OpenAPIType.INTEGER, exclusive_minimum=0),
-}
-
-if pydantic_v2 is not None: # pragma: no cover
- PYDANTIC_TYPE_MAP.update(
- {
- pydantic_v2.SecretStr: Schema(type=OpenAPIType.STRING),
- pydantic_v2.SecretBytes: Schema(type=OpenAPIType.STRING),
- pydantic_v2.ByteSize: Schema(type=OpenAPIType.INTEGER),
- pydantic_v2.EmailStr: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.EMAIL),
- pydantic_v2.IPvAnyAddress: Schema(
- one_of=[
- Schema(
- type=OpenAPIType.STRING,
- format=OpenAPIFormat.IPV4,
- description="IPv4 address",
- ),
- Schema(
- type=OpenAPIType.STRING,
- format=OpenAPIFormat.IPV6,
- description="IPv6 address",
- ),
- ]
- ),
- pydantic_v2.IPvAnyInterface: Schema(
- one_of=[
- Schema(
- type=OpenAPIType.STRING,
- format=OpenAPIFormat.IPV4,
- description="IPv4 interface",
- ),
- Schema(
- type=OpenAPIType.STRING,
- format=OpenAPIFormat.IPV6,
- description="IPv6 interface",
- ),
- ]
- ),
- pydantic_v2.IPvAnyNetwork: Schema(
- one_of=[
- Schema(
- type=OpenAPIType.STRING,
- format=OpenAPIFormat.IPV4,
- description="IPv4 network",
- ),
- Schema(
- type=OpenAPIType.STRING,
- format=OpenAPIFormat.IPV6,
- description="IPv6 network",
- ),
- ]
- ),
- pydantic_v2.Json: Schema(type=OpenAPIType.OBJECT, format=OpenAPIFormat.JSON_POINTER),
- pydantic_v2.NameEmail: Schema(
- type=OpenAPIType.STRING, format=OpenAPIFormat.EMAIL, description="Name and email"
- ),
- pydantic_v2.AnyUrl: Schema(type=OpenAPIType.STRING, format=OpenAPIFormat.URL),
- }
- )
-
-
-_supported_types = (pydantic_v1.BaseModel, *PYDANTIC_TYPE_MAP.keys())
-if pydantic_v2 is not None: # pragma: no cover
- _supported_types = (pydantic_v2.BaseModel, *_supported_types)
-
-
-class PydanticSchemaPlugin(OpenAPISchemaPlugin):
- __slots__ = ("prefer_alias",)
-
- def __init__(self, prefer_alias: bool = False) -> None:
- self.prefer_alias = prefer_alias
-
- @staticmethod
- def is_plugin_supported_type(value: Any) -> bool:
- return isinstance(value, _supported_types) or is_class_and_subclass(value, _supported_types) # type: ignore[arg-type]
-
- @staticmethod
- def is_undefined_sentinel(value: Any) -> bool:
- return is_pydantic_undefined(value)
-
- @staticmethod
- def is_constrained_field(field_definition: FieldDefinition) -> bool:
- return is_pydantic_constrained_field(field_definition.annotation)
-
- def to_openapi_schema(self, field_definition: FieldDefinition, schema_creator: SchemaCreator) -> Schema:
- """Given a type annotation, transform it into an OpenAPI schema class.
-
- Args:
- field_definition: FieldDefinition instance.
- schema_creator: An instance of the schema creator class
-
- Returns:
- An :class:`OpenAPI <litestar.openapi.spec.schema.Schema>` instance.
- """
- if schema_creator.prefer_alias != self.prefer_alias:
- schema_creator.prefer_alias = True
- if is_pydantic_model_class(field_definition.annotation):
- return self.for_pydantic_model(field_definition=field_definition, schema_creator=schema_creator)
- return PYDANTIC_TYPE_MAP[field_definition.annotation] # pragma: no cover
-
- @classmethod
- def for_pydantic_model(cls, field_definition: FieldDefinition, schema_creator: SchemaCreator) -> Schema: # pyright: ignore
- """Create a schema object for a given pydantic model class.
-
- Args:
- field_definition: FieldDefinition instance.
- schema_creator: An instance of the schema creator class
-
- Returns:
- A schema instance.
- """
-
- annotation = field_definition.annotation
- if is_generic(annotation):
- is_generic_model = True
- model = pydantic_unwrap_and_get_origin(annotation) or annotation
- else:
- is_generic_model = False
- model = annotation
-
- if is_pydantic_2_model(model):
- model_config = model.model_config
- model_field_info = model.model_fields
- title = model_config.get("title")
- example = model_config.get("example")
- is_v2_model = True
- else:
- model_config = annotation.__config__
- model_field_info = model.__fields__
- title = getattr(model_config, "title", None)
- example = getattr(model_config, "example", None)
- is_v2_model = False
-
- model_fields: dict[str, pydantic_v1.fields.FieldInfo | pydantic_v2.fields.FieldInfo] = { # pyright: ignore
- k: getattr(f, "field_info", f) for k, f in model_field_info.items()
- }
-
- if is_v2_model:
- # extract the annotations from the FieldInfo. This allows us to skip fields
- # which have been marked as private
- model_annotations = {k: field_info.annotation for k, field_info in model_fields.items()} # type: ignore[union-attr]
-
- else:
- # pydantic v1 requires some workarounds here
- model_annotations = {
- k: f.outer_type_ if f.required else Optional[f.outer_type_] for k, f in model.__fields__.items()
- }
-
- if is_generic_model:
- # if the model is generic, resolve the type variables. We pass in the
- # already extracted annotations, to keep the logic of respecting private
- # fields consistent with the above
- model_annotations = pydantic_get_type_hints_with_generics_resolved(
- annotation, model_annotations=model_annotations, include_extras=True
- )
-
- property_fields = {
- field_info.alias if field_info.alias and schema_creator.prefer_alias else k: FieldDefinition.from_kwarg(
- annotation=Annotated[model_annotations[k], field_info, field_info.metadata] # type: ignore[union-attr]
- if is_v2_model
- else Annotated[model_annotations[k], field_info], # pyright: ignore
- name=field_info.alias if field_info.alias and schema_creator.prefer_alias else k,
- default=Empty if schema_creator.is_undefined(field_info.default) else field_info.default,
- )
- for k, field_info in model_fields.items()
- }
-
- computed_field_definitions = create_field_definitions_for_computed_fields(
- annotation, schema_creator.prefer_alias
- )
- property_fields.update(computed_field_definitions)
-
- return schema_creator.create_component_schema(
- field_definition,
- required=sorted(f.name for f in property_fields.values() if f.is_required),
- property_fields=property_fields,
- title=title,
- examples=None if example is None else [example],
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/utils.py b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/utils.py
deleted file mode 100644
index 6aee322..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/utils.py
+++ /dev/null
@@ -1,214 +0,0 @@
-# mypy: strict-equality=False
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any
-
-from typing_extensions import Annotated, get_type_hints
-
-from litestar.params import KwargDefinition
-from litestar.types import Empty
-from litestar.typing import FieldDefinition
-from litestar.utils import deprecated, is_class_and_subclass
-from litestar.utils.predicates import is_generic
-from litestar.utils.typing import (
- _substitute_typevars,
- get_origin_or_inner_type,
- get_type_hints_with_generics_resolved,
- normalize_type_annotation,
-)
-
-# isort: off
-try:
- from pydantic import v1 as pydantic_v1
- import pydantic as pydantic_v2
- from pydantic.fields import PydanticUndefined as Pydantic2Undefined # type: ignore[attr-defined]
- from pydantic.v1.fields import Undefined as Pydantic1Undefined
-
- PYDANTIC_UNDEFINED_SENTINELS = {Pydantic1Undefined, Pydantic2Undefined}
-except ImportError:
- try:
- import pydantic as pydantic_v1 # type: ignore[no-redef]
- from pydantic.fields import Undefined as Pydantic1Undefined # type: ignore[attr-defined, no-redef]
-
- pydantic_v2 = Empty # type: ignore[assignment]
- PYDANTIC_UNDEFINED_SENTINELS = {Pydantic1Undefined}
-
- except ImportError: # pyright: ignore
- pydantic_v1 = Empty # type: ignore[assignment]
- pydantic_v2 = Empty # type: ignore[assignment]
- PYDANTIC_UNDEFINED_SENTINELS = set()
-# isort: on
-
-
-if TYPE_CHECKING:
- from typing_extensions import TypeGuard
-
-
-def is_pydantic_model_class(
- annotation: Any,
-) -> TypeGuard[type[pydantic_v1.BaseModel | pydantic_v2.BaseModel]]: # pyright: ignore
- """Given a type annotation determine if the annotation is a subclass of pydantic's BaseModel.
-
- Args:
- annotation: A type.
-
- Returns:
- A typeguard determining whether the type is :data:`BaseModel pydantic.BaseModel>`.
- """
- tests: list[bool] = []
-
- if pydantic_v1 is not Empty: # pragma: no cover
- tests.append(is_class_and_subclass(annotation, pydantic_v1.BaseModel))
-
- if pydantic_v2 is not Empty: # pragma: no cover
- tests.append(is_class_and_subclass(annotation, pydantic_v2.BaseModel))
-
- return any(tests)
-
-
-def is_pydantic_model_instance(
- annotation: Any,
-) -> TypeGuard[pydantic_v1.BaseModel | pydantic_v2.BaseModel]: # pyright: ignore
- """Given a type annotation determine if the annotation is an instance of pydantic's BaseModel.
-
- Args:
- annotation: A type.
-
- Returns:
- A typeguard determining whether the type is :data:`BaseModel pydantic.BaseModel>`.
- """
- tests: list[bool] = []
-
- if pydantic_v1 is not Empty: # pragma: no cover
- tests.append(isinstance(annotation, pydantic_v1.BaseModel))
-
- if pydantic_v2 is not Empty: # pragma: no cover
- tests.append(isinstance(annotation, pydantic_v2.BaseModel))
-
- return any(tests)
-
-
-def is_pydantic_constrained_field(annotation: Any) -> bool:
- """Check if the given annotation is a constrained pydantic type.
-
- Args:
- annotation: A type annotation
-
- Returns:
- True if pydantic is installed and the type is a constrained type, otherwise False.
- """
- if pydantic_v1 is Empty: # pragma: no cover
- return False # type: ignore[unreachable]
-
- return any(
- is_class_and_subclass(annotation, constrained_type) # pyright: ignore
- for constrained_type in (
- pydantic_v1.ConstrainedBytes,
- pydantic_v1.ConstrainedDate,
- pydantic_v1.ConstrainedDecimal,
- pydantic_v1.ConstrainedFloat,
- pydantic_v1.ConstrainedFrozenSet,
- pydantic_v1.ConstrainedInt,
- pydantic_v1.ConstrainedList,
- pydantic_v1.ConstrainedSet,
- pydantic_v1.ConstrainedStr,
- )
- )
-
-
-def pydantic_unwrap_and_get_origin(annotation: Any) -> Any | None:
- if pydantic_v2 is Empty or (pydantic_v1 is not Empty and is_class_and_subclass(annotation, pydantic_v1.BaseModel)):
- return get_origin_or_inner_type(annotation)
-
- origin = annotation.__pydantic_generic_metadata__["origin"]
- return normalize_type_annotation(origin)
-
-
-def pydantic_get_type_hints_with_generics_resolved(
- annotation: Any,
- globalns: dict[str, Any] | None = None,
- localns: dict[str, Any] | None = None,
- include_extras: bool = False,
- model_annotations: dict[str, Any] | None = None,
-) -> dict[str, Any]:
- if pydantic_v2 is Empty or (pydantic_v1 is not Empty and is_class_and_subclass(annotation, pydantic_v1.BaseModel)):
- return get_type_hints_with_generics_resolved(annotation, type_hints=model_annotations)
-
- origin = pydantic_unwrap_and_get_origin(annotation)
- if origin is None:
- if model_annotations is None: # pragma: no cover
- model_annotations = get_type_hints(
- annotation, globalns=globalns, localns=localns, include_extras=include_extras
- )
- typevar_map = {p: p for p in annotation.__pydantic_generic_metadata__["parameters"]}
- else:
- if model_annotations is None:
- model_annotations = get_type_hints(
- origin, globalns=globalns, localns=localns, include_extras=include_extras
- )
- args = annotation.__pydantic_generic_metadata__["args"]
- parameters = origin.__pydantic_generic_metadata__["parameters"]
- typevar_map = dict(zip(parameters, args))
-
- return {n: _substitute_typevars(type_, typevar_map) for n, type_ in model_annotations.items()}
-
-
-@deprecated(version="2.6.2")
-def pydantic_get_unwrapped_annotation_and_type_hints(annotation: Any) -> tuple[Any, dict[str, Any]]: # pragma: pver
- """Get the unwrapped annotation and the type hints after resolving generics.
-
- Args:
- annotation: A type annotation.
-
- Returns:
- A tuple containing the unwrapped annotation and the type hints.
- """
-
- if is_generic(annotation):
- origin = pydantic_unwrap_and_get_origin(annotation)
- return origin or annotation, pydantic_get_type_hints_with_generics_resolved(annotation, include_extras=True)
- return annotation, get_type_hints(annotation, include_extras=True)
-
-
-def is_pydantic_2_model(
- obj: type[pydantic_v1.BaseModel | pydantic_v2.BaseModel], # pyright: ignore
-) -> TypeGuard[pydantic_v2.BaseModel]: # pyright: ignore
- return pydantic_v2 is not Empty and issubclass(obj, pydantic_v2.BaseModel)
-
-
-def is_pydantic_undefined(value: Any) -> bool:
- return any(v is value for v in PYDANTIC_UNDEFINED_SENTINELS)
-
-
-def create_field_definitions_for_computed_fields(
- model: type[pydantic_v1.BaseModel | pydantic_v2.BaseModel], # pyright: ignore
- prefer_alias: bool,
-) -> dict[str, FieldDefinition]:
- """Create field definitions for computed fields.
-
- Args:
- model: A pydantic model.
- prefer_alias: Whether to prefer the alias or the name of the field.
-
- Returns:
- A dictionary containing the field definitions for the computed fields.
- """
- pydantic_decorators = getattr(model, "__pydantic_decorators__", None)
- if pydantic_decorators is None:
- return {}
-
- def get_name(k: str, dec: Any) -> str:
- if not dec.info.alias:
- return k
- return dec.info.alias if prefer_alias else k # type: ignore[no-any-return]
-
- return {
- (name := get_name(k, dec)): FieldDefinition.from_annotation(
- Annotated[
- dec.info.return_type,
- KwargDefinition(title=dec.info.title, description=dec.info.description, read_only=True),
- ],
- name=name,
- )
- for k, dec in pydantic_decorators.computed_fields.items()
- }
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/repository/__init__.py b/venv/lib/python3.11/site-packages/litestar/contrib/repository/__init__.py
deleted file mode 100644
index 3a329c9..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/repository/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from litestar.utils import warn_deprecation
-
-
-def __getattr__(attr_name: str) -> object:
- from litestar import repository
-
- if attr_name in repository.__all__:
- warn_deprecation(
- deprecated_name=f"litestar.contrib.repository.{attr_name}",
- version="2.1",
- kind="import",
- removal_in="3.0",
- info=f"importing {attr_name} from 'litestar.contrib.repository' is deprecated, please"
- f"import it from 'litestar.repository.{attr_name}' instead",
- )
-
- value = globals()[attr_name] = getattr(repository, attr_name)
- return value
-
- raise AttributeError(f"module {__name__!r} has no attribute {attr_name!r}")
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 1b3c01a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/exceptions.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/exceptions.cpython-311.pyc
deleted file mode 100644
index 29868c6..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/exceptions.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/filters.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/filters.cpython-311.pyc
deleted file mode 100644
index a69925c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/filters.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/handlers.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/handlers.cpython-311.pyc
deleted file mode 100644
index 5d82074..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/handlers.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/testing.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/testing.cpython-311.pyc
deleted file mode 100644
index 474bdcf..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/testing.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/repository/abc/__init__.py b/venv/lib/python3.11/site-packages/litestar/contrib/repository/abc/__init__.py
deleted file mode 100644
index 17efc1b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/repository/abc/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from litestar.utils import warn_deprecation
-
-
-def __getattr__(attr_name: str) -> object:
- from litestar.repository import abc
-
- if attr_name in abc.__all__:
- warn_deprecation(
- deprecated_name=f"litestar.contrib.repository.abc.{attr_name}",
- version="2.1",
- kind="import",
- removal_in="3.0",
- info=f"importing {attr_name} from 'litestar.contrib.repository.abc' is deprecated, please"
- f"import it from 'litestar.repository.abc.{attr_name}' instead",
- )
-
- value = globals()[attr_name] = getattr(abc, attr_name)
- return value
-
- raise AttributeError(f"module {__name__!r} has no attribute {attr_name!r}")
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/repository/abc/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/repository/abc/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 666c136..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/repository/abc/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/repository/exceptions.py b/venv/lib/python3.11/site-packages/litestar/contrib/repository/exceptions.py
deleted file mode 100644
index 1e7e738..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/repository/exceptions.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from litestar.utils import warn_deprecation
-
-
-def __getattr__(attr_name: str) -> object:
- from litestar.repository import exceptions
-
- if attr_name in exceptions.__all__:
- warn_deprecation(
- deprecated_name=f"litestar.repository.contrib.exceptions.{attr_name}",
- version="2.1",
- kind="import",
- removal_in="3.0",
- info=f"importing {attr_name} from 'litestar.contrib.repository.exceptions' is deprecated, please"
- f"import it from 'litestar.repository.exceptions.{attr_name}' instead",
- )
-
- value = globals()[attr_name] = getattr(exceptions, attr_name)
- return value
-
- raise AttributeError(f"module {__name__!r} has no attribute {attr_name!r}")
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/repository/filters.py b/venv/lib/python3.11/site-packages/litestar/contrib/repository/filters.py
deleted file mode 100644
index 3736a76..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/repository/filters.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from litestar.utils import warn_deprecation
-
-
-def __getattr__(attr_name: str) -> object:
- from litestar.repository import filters
-
- if attr_name in filters.__all__:
- warn_deprecation(
- deprecated_name=f"litestar.repository.contrib.filters.{attr_name}",
- version="2.1",
- kind="import",
- removal_in="3.0",
- info=f"importing {attr_name} from 'litestar.contrib.repository.filters' is deprecated, please"
- f"import it from 'litestar.repository.filters.{attr_name}' instead",
- )
-
- value = globals()[attr_name] = getattr(filters, attr_name)
- return value
-
- raise AttributeError(f"module {__name__!r} has no attribute {attr_name!r}")
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/repository/handlers.py b/venv/lib/python3.11/site-packages/litestar/contrib/repository/handlers.py
deleted file mode 100644
index b1174e4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/repository/handlers.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from litestar.utils import warn_deprecation
-
-
-def __getattr__(attr_name: str) -> object:
- from litestar.repository import handlers
-
- if attr_name in handlers.__all__:
- warn_deprecation(
- deprecated_name=f"litestar.repository.contrib.handlers.{attr_name}",
- version="2.1",
- kind="import",
- removal_in="3.0",
- info=f"importing {attr_name} from 'litestar.contrib.repository.handlers' is deprecated, please"
- f"import it from 'litestar.repository.handlers.{attr_name}' instead",
- )
-
- value = globals()[attr_name] = getattr(handlers, attr_name)
- return value
-
- raise AttributeError(f"module {__name__!r} has no attribute {attr_name!r}")
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/repository/testing.py b/venv/lib/python3.11/site-packages/litestar/contrib/repository/testing.py
deleted file mode 100644
index b78fea8..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/repository/testing.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from litestar.utils import warn_deprecation
-
-
-def __getattr__(attr_name: str) -> object:
- from litestar.repository.testing import generic_mock_repository
-
- if attr_name in generic_mock_repository.__all__:
- warn_deprecation(
- deprecated_name=f"litestar.repository.contrib.testing.{attr_name}",
- version="2.1",
- kind="import",
- removal_in="3.0",
- info=f"importing {attr_name} from 'litestar.contrib.repository.testing' is deprecated, please"
- f"import it from 'litestar.repository.testing.{attr_name}' instead",
- )
-
- value = globals()[attr_name] = getattr(generic_mock_repository, attr_name)
- return value
-
- raise AttributeError(f"module {__name__!r} has no attribute {attr_name!r}")
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__init__.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__init__.py
+++ /dev/null
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 1b0f40a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/base.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/base.cpython-311.pyc
deleted file mode 100644
index 199862b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/base.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/dto.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/dto.cpython-311.pyc
deleted file mode 100644
index 5467843..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/dto.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/types.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/types.cpython-311.pyc
deleted file mode 100644
index 09819d1..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/types.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/base.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/base.py
deleted file mode 100644
index 9ce9608..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/base.py
+++ /dev/null
@@ -1,38 +0,0 @@
-"""Application ORM configuration."""
-
-from __future__ import annotations
-
-try:
- # v0.6.0+
- from advanced_alchemy._listeners import touch_updated_timestamp # pyright: ignore
-except ImportError:
- from advanced_alchemy.base import touch_updated_timestamp # type: ignore[no-redef,attr-defined]
-
-from advanced_alchemy.base import (
- AuditColumns,
- BigIntAuditBase,
- BigIntBase,
- BigIntPrimaryKey,
- CommonTableAttributes,
- ModelProtocol,
- UUIDAuditBase,
- UUIDBase,
- UUIDPrimaryKey,
- create_registry,
- orm_registry,
-)
-
-__all__ = (
- "AuditColumns",
- "BigIntAuditBase",
- "BigIntBase",
- "BigIntPrimaryKey",
- "CommonTableAttributes",
- "create_registry",
- "ModelProtocol",
- "touch_updated_timestamp",
- "UUIDAuditBase",
- "UUIDBase",
- "UUIDPrimaryKey",
- "orm_registry",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/dto.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/dto.py
deleted file mode 100644
index beea75d..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/dto.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from __future__ import annotations
-
-from advanced_alchemy.extensions.litestar.dto import SQLAlchemyDTO, SQLAlchemyDTOConfig
-
-__all__ = ("SQLAlchemyDTO", "SQLAlchemyDTOConfig")
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/__init__.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/__init__.py
deleted file mode 100644
index 5bc913c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/__init__.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from __future__ import annotations
-
-from advanced_alchemy.extensions.litestar.plugins import SQLAlchemyPlugin
-
-from .init import (
- AsyncSessionConfig,
- EngineConfig,
- GenericSessionConfig,
- GenericSQLAlchemyConfig,
- SQLAlchemyAsyncConfig,
- SQLAlchemyInitPlugin,
- SQLAlchemySyncConfig,
- SyncSessionConfig,
-)
-from .serialization import SQLAlchemySerializationPlugin
-
-__all__ = (
- "AsyncSessionConfig",
- "EngineConfig",
- "GenericSQLAlchemyConfig",
- "GenericSessionConfig",
- "SQLAlchemyAsyncConfig",
- "SQLAlchemyInitPlugin",
- "SQLAlchemyPlugin",
- "SQLAlchemySerializationPlugin",
- "SQLAlchemySyncConfig",
- "SyncSessionConfig",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 019ff72..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/__pycache__/serialization.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/__pycache__/serialization.cpython-311.pyc
deleted file mode 100644
index 7bd0360..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/__pycache__/serialization.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/__init__.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/__init__.py
deleted file mode 100644
index 2e507c1..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/__init__.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from __future__ import annotations
-
-from .config import (
- AsyncSessionConfig,
- EngineConfig,
- GenericSessionConfig,
- GenericSQLAlchemyConfig,
- SQLAlchemyAsyncConfig,
- SQLAlchemySyncConfig,
- SyncSessionConfig,
-)
-from .plugin import SQLAlchemyInitPlugin
-
-__all__ = (
- "AsyncSessionConfig",
- "EngineConfig",
- "GenericSQLAlchemyConfig",
- "GenericSessionConfig",
- "SQLAlchemyAsyncConfig",
- "SQLAlchemyInitPlugin",
- "SQLAlchemySyncConfig",
- "SyncSessionConfig",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 43da1aa..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/__pycache__/plugin.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/__pycache__/plugin.cpython-311.pyc
deleted file mode 100644
index e06ec42..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/__pycache__/plugin.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__init__.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__init__.py
deleted file mode 100644
index f2e39da..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from __future__ import annotations
-
-from .asyncio import AsyncSessionConfig, SQLAlchemyAsyncConfig
-from .common import GenericSessionConfig, GenericSQLAlchemyConfig
-from .engine import EngineConfig
-from .sync import SQLAlchemySyncConfig, SyncSessionConfig
-
-__all__ = (
- "AsyncSessionConfig",
- "EngineConfig",
- "GenericSQLAlchemyConfig",
- "GenericSessionConfig",
- "SQLAlchemyAsyncConfig",
- "SQLAlchemySyncConfig",
- "SyncSessionConfig",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 2a316ef..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/asyncio.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/asyncio.cpython-311.pyc
deleted file mode 100644
index 23fe455..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/asyncio.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/common.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/common.cpython-311.pyc
deleted file mode 100644
index 6e83a95..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/common.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/compat.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/compat.cpython-311.pyc
deleted file mode 100644
index 4ba72bb..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/compat.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/engine.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/engine.cpython-311.pyc
deleted file mode 100644
index 1d4553b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/engine.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/sync.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/sync.cpython-311.pyc
deleted file mode 100644
index d777bb9..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/sync.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/asyncio.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/asyncio.py
deleted file mode 100644
index 434c761..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/asyncio.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from __future__ import annotations
-
-from advanced_alchemy.config.asyncio import AlembicAsyncConfig, AsyncSessionConfig
-from advanced_alchemy.extensions.litestar.plugins.init.config.asyncio import (
- SQLAlchemyAsyncConfig as _SQLAlchemyAsyncConfig,
-)
-from advanced_alchemy.extensions.litestar.plugins.init.config.asyncio import (
- autocommit_before_send_handler,
- default_before_send_handler,
-)
-from sqlalchemy.ext.asyncio import AsyncEngine
-
-from litestar.contrib.sqlalchemy.plugins.init.config.compat import _CreateEngineMixin
-
-__all__ = (
- "SQLAlchemyAsyncConfig",
- "AlembicAsyncConfig",
- "AsyncSessionConfig",
- "default_before_send_handler",
- "autocommit_before_send_handler",
-)
-
-
-class SQLAlchemyAsyncConfig(_SQLAlchemyAsyncConfig, _CreateEngineMixin[AsyncEngine]): ...
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/common.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/common.py
deleted file mode 100644
index 9afc48c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/common.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import annotations
-
-from advanced_alchemy.config.common import GenericAlembicConfig, GenericSessionConfig, GenericSQLAlchemyConfig
-from advanced_alchemy.extensions.litestar.plugins.init.config.common import (
- SESSION_SCOPE_KEY,
- SESSION_TERMINUS_ASGI_EVENTS,
-)
-
-__all__ = (
- "SESSION_SCOPE_KEY",
- "SESSION_TERMINUS_ASGI_EVENTS",
- "GenericSQLAlchemyConfig",
- "GenericSessionConfig",
- "GenericAlembicConfig",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/compat.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/compat.py
deleted file mode 100644
index d76dea7..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/compat.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Generic, Protocol, TypeVar
-
-from litestar.utils.deprecation import deprecated
-
-if TYPE_CHECKING:
- from sqlalchemy import Engine
- from sqlalchemy.ext.asyncio import AsyncEngine
-
-
-EngineT_co = TypeVar("EngineT_co", bound="Engine | AsyncEngine", covariant=True)
-
-
-class HasGetEngine(Protocol[EngineT_co]):
- def get_engine(self) -> EngineT_co: ...
-
-
-class _CreateEngineMixin(Generic[EngineT_co]):
- @deprecated(version="2.1.1", removal_in="3.0.0", alternative="get_engine()")
- def create_engine(self: HasGetEngine[EngineT_co]) -> EngineT_co:
- return self.get_engine()
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/engine.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/engine.py
deleted file mode 100644
index 31c3f5e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/engine.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from __future__ import annotations
-
-from advanced_alchemy.config.engine import EngineConfig
-
-__all__ = ("EngineConfig",)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/sync.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/sync.py
deleted file mode 100644
index 48a029b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/sync.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from __future__ import annotations
-
-from advanced_alchemy.config.sync import AlembicSyncConfig, SyncSessionConfig
-from advanced_alchemy.extensions.litestar.plugins.init.config.sync import (
- SQLAlchemySyncConfig as _SQLAlchemySyncConfig,
-)
-from advanced_alchemy.extensions.litestar.plugins.init.config.sync import (
- autocommit_before_send_handler,
- default_before_send_handler,
-)
-from sqlalchemy import Engine
-
-from litestar.contrib.sqlalchemy.plugins.init.config.compat import _CreateEngineMixin
-
-__all__ = (
- "SQLAlchemySyncConfig",
- "AlembicSyncConfig",
- "SyncSessionConfig",
- "default_before_send_handler",
- "autocommit_before_send_handler",
-)
-
-
-class SQLAlchemySyncConfig(_SQLAlchemySyncConfig, _CreateEngineMixin[Engine]): ...
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/plugin.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/plugin.py
deleted file mode 100644
index dbf814b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/plugin.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from __future__ import annotations
-
-from advanced_alchemy.extensions.litestar.plugins import SQLAlchemyInitPlugin
-
-__all__ = ("SQLAlchemyInitPlugin",)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/serialization.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/serialization.py
deleted file mode 100644
index 539b194..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/serialization.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from __future__ import annotations
-
-from advanced_alchemy.extensions.litestar.plugins import SQLAlchemySerializationPlugin
-
-__all__ = ("SQLAlchemySerializationPlugin",)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__init__.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__init__.py
deleted file mode 100644
index 64a8359..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__init__.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from ._async import SQLAlchemyAsyncRepository
-from ._sync import SQLAlchemySyncRepository
-from ._util import wrap_sqlalchemy_exception
-from .types import ModelT
-
-__all__ = (
- "SQLAlchemyAsyncRepository",
- "SQLAlchemySyncRepository",
- "ModelT",
- "wrap_sqlalchemy_exception",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 3e6dacf..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/_async.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/_async.cpython-311.pyc
deleted file mode 100644
index 461fbad..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/_async.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/_sync.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/_sync.cpython-311.pyc
deleted file mode 100644
index bd6d80f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/_sync.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/_util.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/_util.cpython-311.pyc
deleted file mode 100644
index 561fd53..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/_util.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/types.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/types.cpython-311.pyc
deleted file mode 100644
index fa8191e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/types.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/_async.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/_async.py
deleted file mode 100644
index 417ec35..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/_async.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from __future__ import annotations
-
-from advanced_alchemy.repository import SQLAlchemyAsyncRepository
-
-__all__ = ("SQLAlchemyAsyncRepository",)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/_sync.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/_sync.py
deleted file mode 100644
index 58ccbb8..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/_sync.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# Do not edit this file directly. It has been autogenerated from
-# litestar/contrib/sqlalchemy/repository/_async.py
-from __future__ import annotations
-
-from advanced_alchemy.repository import SQLAlchemySyncRepository
-
-__all__ = ("SQLAlchemySyncRepository",)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/_util.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/_util.py
deleted file mode 100644
index c0ce747..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/_util.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import annotations
-
-from advanced_alchemy.repository._util import get_instrumented_attr, wrap_sqlalchemy_exception
-
-__all__ = (
- "wrap_sqlalchemy_exception",
- "get_instrumented_attr",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/types.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/types.py
deleted file mode 100644
index 2a4204c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/types.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from advanced_alchemy.repository.typing import (
- ModelT,
- RowT,
- SelectT,
- SQLAlchemyAsyncRepositoryT,
- SQLAlchemySyncRepositoryT,
-)
-
-__all__ = (
- "ModelT",
- "SelectT",
- "RowT",
- "SQLAlchemySyncRepositoryT",
- "SQLAlchemyAsyncRepositoryT",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/types.py b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/types.py
deleted file mode 100644
index 61fb75a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/types.py
+++ /dev/null
@@ -1,11 +0,0 @@
-from __future__ import annotations
-
-from advanced_alchemy.types import GUID, ORA_JSONB, BigIntIdentity, DateTimeUTC, JsonB
-
-__all__ = (
- "GUID",
- "ORA_JSONB",
- "DateTimeUTC",
- "BigIntIdentity",
- "JsonB",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/controller.py b/venv/lib/python3.11/site-packages/litestar/controller.py
deleted file mode 100644
index 967454b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/controller.py
+++ /dev/null
@@ -1,262 +0,0 @@
-from __future__ import annotations
-
-import types
-from collections import defaultdict
-from copy import deepcopy
-from operator import attrgetter
-from typing import TYPE_CHECKING, Any, Mapping, Sequence, cast
-
-from litestar._layers.utils import narrow_response_cookies, narrow_response_headers
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.handlers.base import BaseRouteHandler
-from litestar.handlers.http_handlers import HTTPRouteHandler
-from litestar.handlers.websocket_handlers import WebsocketRouteHandler
-from litestar.types.empty import Empty
-from litestar.utils import ensure_async_callable, normalize_path
-from litestar.utils.signature import add_types_to_signature_namespace
-
-__all__ = ("Controller",)
-
-
-if TYPE_CHECKING:
- from litestar.connection import Request, WebSocket
- from litestar.datastructures import CacheControlHeader, ETag
- from litestar.dto import AbstractDTO
- from litestar.openapi.spec import SecurityRequirement
- from litestar.response import Response
- from litestar.router import Router
- from litestar.types import (
- AfterRequestHookHandler,
- AfterResponseHookHandler,
- BeforeRequestHookHandler,
- Dependencies,
- ExceptionHandlersMap,
- Guard,
- Middleware,
- ParametersMap,
- ResponseCookies,
- TypeEncodersMap,
- )
- from litestar.types.composite_types import ResponseHeaders, TypeDecodersSequence
- from litestar.types.empty import EmptyType
-
-
-class Controller:
- """The Litestar Controller class.
-
- Subclass this class to create 'view' like components and utilize OOP.
- """
-
- __slots__ = (
- "after_request",
- "after_response",
- "before_request",
- "dependencies",
- "dto",
- "etag",
- "exception_handlers",
- "guards",
- "include_in_schema",
- "middleware",
- "opt",
- "owner",
- "parameters",
- "path",
- "request_class",
- "response_class",
- "response_cookies",
- "response_headers",
- "return_dto",
- "security",
- "signature_namespace",
- "tags",
- "type_encoders",
- "type_decoders",
- "websocket_class",
- )
-
- after_request: AfterRequestHookHandler | None
- """A sync or async function executed before a :class:`Request <.connection.Request>` is passed to any route handler.
-
- If this function returns a value, the request will not reach the route handler, and instead this value will be used.
- """
- after_response: AfterResponseHookHandler | None
- """A sync or async function called after the response has been awaited.
-
- It receives the :class:`Request <.connection.Request>` instance and should not return any values.
- """
- before_request: BeforeRequestHookHandler | None
- """A sync or async function called immediately before calling the route handler.
-
- It receives the :class:`Request <.connection.Request>` instance and any non-``None`` return value is used for the
- response, bypassing the route handler.
- """
- cache_control: CacheControlHeader | None
- """A :class:`CacheControlHeader <.datastructures.CacheControlHeader>` header to add to route handlers of this
- controller.
-
- Can be overridden by route handlers.
- """
- dependencies: Dependencies | None
- """A string keyed dictionary of dependency :class:`Provider <.di.Provide>` instances."""
- dto: type[AbstractDTO] | None | EmptyType
- """:class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and validation of request data."""
- etag: ETag | None
- """An ``etag`` header of type :class:`ETag <.datastructures.ETag>` to add to route handlers of this controller.
-
- Can be overridden by route handlers.
- """
- exception_handlers: ExceptionHandlersMap | None
- """A map of handler functions to status codes and/or exception types."""
- guards: Sequence[Guard] | None
- """A sequence of :class:`Guard <.types.Guard>` callables."""
- include_in_schema: bool | EmptyType
- """A boolean flag dictating whether the route handler should be documented in the OpenAPI schema"""
- middleware: Sequence[Middleware] | None
- """A sequence of :class:`Middleware <.types.Middleware>`."""
- opt: Mapping[str, Any] | None
- """A string key mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or wherever you
- have access to :class:`Request <.connection.Request>` or :class:`ASGI Scope <.types.Scope>`.
- """
- owner: Router
- """The :class:`Router <.router.Router>` or :class:`Litestar <litestar.app.Litestar>` app that owns the controller.
-
- This value is set internally by Litestar and it should not be set when subclassing the controller.
- """
- parameters: ParametersMap | None
- """A mapping of :class:`Parameter <.params.Parameter>` definitions available to all application paths."""
- path: str
- """A path fragment for the controller.
-
- All route handlers under the controller will have the fragment appended to them. If not set it defaults to ``/``.
- """
- request_class: type[Request] | None
- """A custom subclass of :class:`Request <.connection.Request>` to be used as the default request for all route
- handlers under the controller.
- """
- response_class: type[Response] | None
- """A custom subclass of :class:`Response <.response.Response>` to be used as the default response for all route
- handlers under the controller.
- """
- response_cookies: ResponseCookies | None
- """A list of :class:`Cookie <.datastructures.Cookie>` instances."""
- response_headers: ResponseHeaders | None
- """A string keyed dictionary mapping :class:`ResponseHeader <.datastructures.ResponseHeader>` instances."""
- return_dto: type[AbstractDTO] | None | EmptyType
- """:class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing outbound response
- data.
- """
- tags: Sequence[str] | None
- """A sequence of string tags that will be appended to the schema of all route handlers under the controller."""
- security: Sequence[SecurityRequirement] | None
- """A sequence of dictionaries that to the schema of all route handlers under the controller."""
- signature_namespace: dict[str, Any]
- """A mapping of names to types for use in forward reference resolution during signature modeling."""
- signature_types: Sequence[Any]
- """A sequence of types for use in forward reference resolution during signature modeling.
-
- These types will be added to the signature namespace using their ``__name__`` attribute.
- """
- type_decoders: TypeDecodersSequence | None
- """A sequence of tuples, each composed of a predicate testing for type identity and a msgspec hook for deserialization."""
- type_encoders: TypeEncodersMap | None
- """A mapping of types to callables that transform them into types supported for serialization."""
- websocket_class: type[WebSocket] | None
- """A custom subclass of :class:`WebSocket <.connection.WebSocket>` to be used as the default websocket for all route
- handlers under the controller.
- """
-
- def __init__(self, owner: Router) -> None:
- """Initialize a controller.
-
- Should only be called by routers as part of controller registration.
-
- Args:
- owner: An instance of :class:`Router <.router.Router>`
- """
- # Since functions set on classes are bound, we need replace the bound instance with the class version and wrap
- # it to ensure it does not get bound.
- for key in ("after_request", "after_response", "before_request"):
- cls_value = getattr(type(self), key, None)
- if callable(cls_value):
- setattr(self, key, ensure_async_callable(cls_value))
-
- if not hasattr(self, "dto"):
- self.dto = Empty
-
- if not hasattr(self, "return_dto"):
- self.return_dto = Empty
-
- if not hasattr(self, "include_in_schema"):
- self.include_in_schema = Empty
-
- self.signature_namespace = add_types_to_signature_namespace(
- getattr(self, "signature_types", []), getattr(self, "signature_namespace", {})
- )
-
- for key in self.__slots__:
- if not hasattr(self, key):
- setattr(self, key, None)
-
- self.response_cookies = narrow_response_cookies(self.response_cookies)
- self.response_headers = narrow_response_headers(self.response_headers)
- self.path = normalize_path(self.path or "/")
- self.owner = owner
-
- def get_route_handlers(self) -> list[BaseRouteHandler]:
- """Get a controller's route handlers and set the controller as the handlers' owner.
-
- Returns:
- A list containing a copy of the route handlers defined on the controller
- """
-
- route_handlers: list[BaseRouteHandler] = []
- controller_names = set(dir(Controller))
- self_handlers = [
- getattr(self, name)
- for name in dir(self)
- if name not in controller_names and isinstance(getattr(self, name), BaseRouteHandler)
- ]
- self_handlers.sort(key=attrgetter("handler_id"))
- for self_handler in self_handlers:
- route_handler = deepcopy(self_handler)
- # at the point we get a reference to the handler function, it's unbound, so
- # we replace it with a regular bound method here
- route_handler._fn = types.MethodType(route_handler._fn, self)
- route_handler.owner = self
- route_handlers.append(route_handler)
-
- self.validate_route_handlers(route_handlers=route_handlers)
-
- return route_handlers
-
- def validate_route_handlers(self, route_handlers: list[BaseRouteHandler]) -> None:
- """Validate that the combination of path and decorator method or type are unique on the controller.
-
- Args:
- route_handlers: The controller's route handlers.
-
- Raises:
- ImproperlyConfiguredException
-
- Returns:
- None
- """
- paths: defaultdict[str, set[str]] = defaultdict(set)
-
- for route_handler in route_handlers:
- if isinstance(route_handler, HTTPRouteHandler):
- methods: set[str] = cast("set[str]", route_handler.http_methods)
- elif isinstance(route_handler, WebsocketRouteHandler):
- methods = {"websocket"}
- else:
- methods = {"asgi"}
-
- for path in route_handler.paths:
- if (entry := paths[path]) and (intersection := entry.intersection(methods)):
- raise ImproperlyConfiguredException(
- f"the combination of path and method must be unique in a controller - "
- f"the following methods {''.join(m.lower() for m in intersection)} for {type(self).__name__} "
- f"controller path {path} are not unique"
- )
- paths[path].update(methods)
diff --git a/venv/lib/python3.11/site-packages/litestar/data_extractors.py b/venv/lib/python3.11/site-packages/litestar/data_extractors.py
deleted file mode 100644
index 61993b4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/data_extractors.py
+++ /dev/null
@@ -1,443 +0,0 @@
-from __future__ import annotations
-
-import inspect
-from typing import TYPE_CHECKING, Any, Callable, Coroutine, Iterable, Literal, TypedDict, cast
-
-from litestar._parsers import parse_cookie_string
-from litestar.connection.request import Request
-from litestar.datastructures.upload_file import UploadFile
-from litestar.enums import HttpMethod, RequestEncodingType
-
-__all__ = (
- "ConnectionDataExtractor",
- "ExtractedRequestData",
- "ExtractedResponseData",
- "ResponseDataExtractor",
- "RequestExtractorField",
- "ResponseExtractorField",
-)
-
-
-if TYPE_CHECKING:
- from litestar.connection import ASGIConnection
- from litestar.types import Method
- from litestar.types.asgi_types import HTTPResponseBodyEvent, HTTPResponseStartEvent
-
-
-def _obfuscate(values: dict[str, Any], fields_to_obfuscate: set[str]) -> dict[str, Any]:
- """Obfuscate values in a dictionary, replacing values with `******`
-
- Args:
- values: A dictionary of strings
- fields_to_obfuscate: keys to obfuscate
-
- Returns:
- A dictionary with obfuscated strings
- """
- return {key: "*****" if key.lower() in fields_to_obfuscate else value for key, value in values.items()}
-
-
-RequestExtractorField = Literal[
- "path", "method", "content_type", "headers", "cookies", "query", "path_params", "body", "scheme", "client"
-]
-
-ResponseExtractorField = Literal["status_code", "headers", "body", "cookies"]
-
-
-class ExtractedRequestData(TypedDict, total=False):
- """Dictionary representing extracted request data."""
-
- body: Coroutine[Any, Any, Any]
- client: tuple[str, int]
- content_type: tuple[str, dict[str, str]]
- cookies: dict[str, str]
- headers: dict[str, str]
- method: Method
- path: str
- path_params: dict[str, Any]
- query: bytes | dict[str, Any]
- scheme: str
-
-
-class ConnectionDataExtractor:
- """Utility class to extract data from an :class:`ASGIConnection <litestar.connection.ASGIConnection>`,
- :class:`Request <litestar.connection.Request>` or :class:`WebSocket <litestar.connection.WebSocket>` instance.
- """
-
- __slots__ = (
- "connection_extractors",
- "request_extractors",
- "parse_body",
- "parse_query",
- "obfuscate_headers",
- "obfuscate_cookies",
- "skip_parse_malformed_body",
- )
-
- def __init__(
- self,
- extract_body: bool = True,
- extract_client: bool = True,
- extract_content_type: bool = True,
- extract_cookies: bool = True,
- extract_headers: bool = True,
- extract_method: bool = True,
- extract_path: bool = True,
- extract_path_params: bool = True,
- extract_query: bool = True,
- extract_scheme: bool = True,
- obfuscate_cookies: set[str] | None = None,
- obfuscate_headers: set[str] | None = None,
- parse_body: bool = False,
- parse_query: bool = False,
- skip_parse_malformed_body: bool = False,
- ) -> None:
- """Initialize ``ConnectionDataExtractor``
-
- Args:
- extract_body: Whether to extract body, (for requests only).
- extract_client: Whether to extract the client (host, port) mapping.
- extract_content_type: Whether to extract the content type and any options.
- extract_cookies: Whether to extract cookies.
- extract_headers: Whether to extract headers.
- extract_method: Whether to extract the HTTP method, (for requests only).
- extract_path: Whether to extract the path.
- extract_path_params: Whether to extract path parameters.
- extract_query: Whether to extract query parameters.
- extract_scheme: Whether to extract the http scheme.
- obfuscate_headers: headers keys to obfuscate. Obfuscated values are replaced with '*****'.
- obfuscate_cookies: cookie keys to obfuscate. Obfuscated values are replaced with '*****'.
- parse_body: Whether to parse the body value or return the raw byte string, (for requests only).
- parse_query: Whether to parse query parameters or return the raw byte string.
- skip_parse_malformed_body: Whether to skip parsing the body if it is malformed
- """
- self.parse_body = parse_body
- self.parse_query = parse_query
- self.skip_parse_malformed_body = skip_parse_malformed_body
- self.obfuscate_headers = {h.lower() for h in (obfuscate_headers or set())}
- self.obfuscate_cookies = {c.lower() for c in (obfuscate_cookies or set())}
- self.connection_extractors: dict[str, Callable[[ASGIConnection[Any, Any, Any, Any]], Any]] = {}
- self.request_extractors: dict[RequestExtractorField, Callable[[Request[Any, Any, Any]], Any]] = {}
- if extract_scheme:
- self.connection_extractors["scheme"] = self.extract_scheme
- if extract_client:
- self.connection_extractors["client"] = self.extract_client
- if extract_path:
- self.connection_extractors["path"] = self.extract_path
- if extract_headers:
- self.connection_extractors["headers"] = self.extract_headers
- if extract_cookies:
- self.connection_extractors["cookies"] = self.extract_cookies
- if extract_query:
- self.connection_extractors["query"] = self.extract_query
- if extract_path_params:
- self.connection_extractors["path_params"] = self.extract_path_params
- if extract_method:
- self.request_extractors["method"] = self.extract_method
- if extract_content_type:
- self.request_extractors["content_type"] = self.extract_content_type
- if extract_body:
- self.request_extractors["body"] = self.extract_body
-
- def __call__(self, connection: ASGIConnection[Any, Any, Any, Any]) -> ExtractedRequestData:
- """Extract data from the connection, returning a dictionary of values.
-
- Notes:
- - The value for ``body`` - if present - is an unresolved Coroutine and as such should be awaited by the receiver.
-
- Args:
- connection: An ASGI connection or its subclasses.
-
- Returns:
- A string keyed dictionary of extracted values.
- """
- extractors = (
- {**self.connection_extractors, **self.request_extractors} # type: ignore[misc]
- if isinstance(connection, Request)
- else self.connection_extractors
- )
- return cast("ExtractedRequestData", {key: extractor(connection) for key, extractor in extractors.items()})
-
- async def extract(
- self, connection: ASGIConnection[Any, Any, Any, Any], fields: Iterable[str]
- ) -> ExtractedRequestData:
- extractors = (
- {**self.connection_extractors, **self.request_extractors} # type: ignore[misc]
- if isinstance(connection, Request)
- else self.connection_extractors
- )
- data = {}
- for key, extractor in extractors.items():
- if key not in fields:
- continue
- if inspect.iscoroutinefunction(extractor):
- value = await extractor(connection)
- else:
- value = extractor(connection)
- data[key] = value
- return cast("ExtractedRequestData", data)
-
- @staticmethod
- def extract_scheme(connection: ASGIConnection[Any, Any, Any, Any]) -> str:
- """Extract the scheme from an ``ASGIConnection``
-
- Args:
- connection: An :class:`ASGIConnection <litestar.connection.ASGIConnection>` instance.
-
- Returns:
- The connection's scope["scheme"] value
- """
- return connection.scope["scheme"]
-
- @staticmethod
- def extract_client(connection: ASGIConnection[Any, Any, Any, Any]) -> tuple[str, int]:
- """Extract the client from an ``ASGIConnection``
-
- Args:
- connection: An :class:`ASGIConnection <litestar.connection.ASGIConnection>` instance.
-
- Returns:
- The connection's scope["client"] value or a default value.
- """
- return connection.scope.get("client") or ("", 0)
-
- @staticmethod
- def extract_path(connection: ASGIConnection[Any, Any, Any, Any]) -> str:
- """Extract the path from an ``ASGIConnection``
-
- Args:
- connection: An :class:`ASGIConnection <litestar.connection.ASGIConnection>` instance.
-
- Returns:
- The connection's scope["path"] value
- """
- return connection.scope["path"]
-
- def extract_headers(self, connection: ASGIConnection[Any, Any, Any, Any]) -> dict[str, str]:
- """Extract headers from an ``ASGIConnection``
-
- Args:
- connection: An :class:`ASGIConnection <litestar.connection.ASGIConnection>` instance.
-
- Returns:
- A dictionary with the connection's headers.
- """
- headers = {k.decode("latin-1"): v.decode("latin-1") for k, v in connection.scope["headers"]}
- return _obfuscate(headers, self.obfuscate_headers) if self.obfuscate_headers else headers
-
- def extract_cookies(self, connection: ASGIConnection[Any, Any, Any, Any]) -> dict[str, str]:
- """Extract cookies from an ``ASGIConnection``
-
- Args:
- connection: An :class:`ASGIConnection <litestar.connection.ASGIConnection>` instance.
-
- Returns:
- A dictionary with the connection's cookies.
- """
- return _obfuscate(connection.cookies, self.obfuscate_cookies) if self.obfuscate_cookies else connection.cookies
-
- def extract_query(self, connection: ASGIConnection[Any, Any, Any, Any]) -> Any:
- """Extract query from an ``ASGIConnection``
-
- Args:
- connection: An :class:`ASGIConnection <litestar.connection.ASGIConnection>` instance.
-
- Returns:
- Either a dictionary with the connection's parsed query string or the raw query byte-string.
- """
- return connection.query_params.dict() if self.parse_query else connection.scope.get("query_string", b"")
-
- @staticmethod
- def extract_path_params(connection: ASGIConnection[Any, Any, Any, Any]) -> dict[str, Any]:
- """Extract the path parameters from an ``ASGIConnection``
-
- Args:
- connection: An :class:`ASGIConnection <litestar.connection.ASGIConnection>` instance.
-
- Returns:
- A dictionary with the connection's path parameters.
- """
- return connection.path_params
-
- @staticmethod
- def extract_method(request: Request[Any, Any, Any]) -> Method:
- """Extract the method from an ``ASGIConnection``
-
- Args:
- request: A :class:`Request <litestar.connection.Request>` instance.
-
- Returns:
- The request's scope["method"] value.
- """
- return request.scope["method"]
-
- @staticmethod
- def extract_content_type(request: Request[Any, Any, Any]) -> tuple[str, dict[str, str]]:
- """Extract the content-type from an ``ASGIConnection``
-
- Args:
- request: A :class:`Request <litestar.connection.Request>` instance.
-
- Returns:
- A tuple containing the request's parsed 'Content-Type' header.
- """
- return request.content_type
-
- async def extract_body(self, request: Request[Any, Any, Any]) -> Any:
- """Extract the body from an ``ASGIConnection``
-
- Args:
- request: A :class:`Request <litestar.connection.Request>` instance.
-
- Returns:
- Either the parsed request body or the raw byte-string.
- """
- if request.method == HttpMethod.GET:
- return None
- if not self.parse_body:
- return await request.body()
- try:
- request_encoding_type = request.content_type[0]
- if request_encoding_type == RequestEncodingType.JSON:
- return await request.json()
- form_data = await request.form()
- if request_encoding_type == RequestEncodingType.URL_ENCODED:
- return dict(form_data)
- return {
- key: repr(value) if isinstance(value, UploadFile) else value for key, value in form_data.multi_items()
- }
- except Exception as exc:
- if self.skip_parse_malformed_body:
- return await request.body()
- raise exc
-
-
-class ExtractedResponseData(TypedDict, total=False):
- """Dictionary representing extracted response data."""
-
- body: bytes
- status_code: int
- headers: dict[str, str]
- cookies: dict[str, str]
-
-
-class ResponseDataExtractor:
- """Utility class to extract data from a ``Message``"""
-
- __slots__ = ("extractors", "parse_headers", "obfuscate_headers", "obfuscate_cookies")
-
- def __init__(
- self,
- extract_body: bool = True,
- extract_cookies: bool = True,
- extract_headers: bool = True,
- extract_status_code: bool = True,
- obfuscate_cookies: set[str] | None = None,
- obfuscate_headers: set[str] | None = None,
- ) -> None:
- """Initialize ``ResponseDataExtractor`` with options.
-
- Args:
- extract_body: Whether to extract the body.
- extract_cookies: Whether to extract the cookies.
- extract_headers: Whether to extract the headers.
- extract_status_code: Whether to extract the status code.
- obfuscate_cookies: cookie keys to obfuscate. Obfuscated values are replaced with '*****'.
- obfuscate_headers: headers keys to obfuscate. Obfuscated values are replaced with '*****'.
- """
- self.obfuscate_headers = {h.lower() for h in (obfuscate_headers or set())}
- self.obfuscate_cookies = {c.lower() for c in (obfuscate_cookies or set())}
- self.extractors: dict[
- ResponseExtractorField, Callable[[tuple[HTTPResponseStartEvent, HTTPResponseBodyEvent]], Any]
- ] = {}
- if extract_body:
- self.extractors["body"] = self.extract_response_body
- if extract_status_code:
- self.extractors["status_code"] = self.extract_status_code
- if extract_headers:
- self.extractors["headers"] = self.extract_headers
- if extract_cookies:
- self.extractors["cookies"] = self.extract_cookies
-
- def __call__(self, messages: tuple[HTTPResponseStartEvent, HTTPResponseBodyEvent]) -> ExtractedResponseData:
- """Extract data from the response, returning a dictionary of values.
-
- Args:
- messages: A tuple containing
- :class:`HTTPResponseStartEvent <litestar.types.asgi_types.HTTPResponseStartEvent>`
- and :class:`HTTPResponseBodyEvent <litestar.types.asgi_types.HTTPResponseBodyEvent>`.
-
- Returns:
- A string keyed dictionary of extracted values.
- """
- return cast("ExtractedResponseData", {key: extractor(messages) for key, extractor in self.extractors.items()})
-
- @staticmethod
- def extract_response_body(messages: tuple[HTTPResponseStartEvent, HTTPResponseBodyEvent]) -> bytes:
- """Extract the response body from a ``Message``
-
- Args:
- messages: A tuple containing
- :class:`HTTPResponseStartEvent <litestar.types.asgi_types.HTTPResponseStartEvent>`
- and :class:`HTTPResponseBodyEvent <litestar.types.asgi_types.HTTPResponseBodyEvent>`.
-
- Returns:
- The Response's body as a byte-string.
- """
- return messages[1]["body"]
-
- @staticmethod
- def extract_status_code(messages: tuple[HTTPResponseStartEvent, HTTPResponseBodyEvent]) -> int:
- """Extract a status code from a ``Message``
-
- Args:
- messages: A tuple containing
- :class:`HTTPResponseStartEvent <litestar.types.asgi_types.HTTPResponseStartEvent>`
- and :class:`HTTPResponseBodyEvent <litestar.types.asgi_types.HTTPResponseBodyEvent>`.
-
- Returns:
- The Response's status-code.
- """
- return messages[0]["status"]
-
- def extract_headers(self, messages: tuple[HTTPResponseStartEvent, HTTPResponseBodyEvent]) -> dict[str, str]:
- """Extract headers from a ``Message``
-
- Args:
- messages: A tuple containing
- :class:`HTTPResponseStartEvent <litestar.types.asgi_types.HTTPResponseStartEvent>`
- and :class:`HTTPResponseBodyEvent <litestar.types.asgi_types.HTTPResponseBodyEvent>`.
-
- Returns:
- The Response's headers dict.
- """
- headers = {
- key.decode("latin-1"): value.decode("latin-1")
- for key, value in filter(lambda x: x[0].lower() != b"set-cookie", messages[0]["headers"])
- }
- return (
- _obfuscate(
- headers,
- self.obfuscate_headers,
- )
- if self.obfuscate_headers
- else headers
- )
-
- def extract_cookies(self, messages: tuple[HTTPResponseStartEvent, HTTPResponseBodyEvent]) -> dict[str, str]:
- """Extract cookies from a ``Message``
-
- Args:
- messages: A tuple containing
- :class:`HTTPResponseStartEvent <litestar.types.asgi_types.HTTPResponseStartEvent>`
- and :class:`HTTPResponseBodyEvent <litestar.types.asgi_types.HTTPResponseBodyEvent>`.
-
- Returns:
- The Response's cookies dict.
- """
- if cookie_string := ";".join(
- [x[1].decode("latin-1") for x in filter(lambda x: x[0].lower() == b"set-cookie", messages[0]["headers"])]
- ):
- parsed_cookies = parse_cookie_string(cookie_string)
- return _obfuscate(parsed_cookies, self.obfuscate_cookies) if self.obfuscate_cookies else parsed_cookies
- return {}
diff --git a/venv/lib/python3.11/site-packages/litestar/datastructures/__init__.py b/venv/lib/python3.11/site-packages/litestar/datastructures/__init__.py
deleted file mode 100644
index 74fc25b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/datastructures/__init__.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from litestar.datastructures.cookie import Cookie
-from litestar.datastructures.headers import (
- Accept,
- CacheControlHeader,
- ETag,
- Header,
- Headers,
- MutableScopeHeaders,
-)
-from litestar.datastructures.multi_dicts import (
- FormMultiDict,
- ImmutableMultiDict,
- MultiDict,
- MultiMixin,
-)
-from litestar.datastructures.response_header import ResponseHeader
-from litestar.datastructures.state import ImmutableState, State
-from litestar.datastructures.upload_file import UploadFile
-from litestar.datastructures.url import URL, Address
-
-__all__ = (
- "Accept",
- "Address",
- "CacheControlHeader",
- "Cookie",
- "ETag",
- "FormMultiDict",
- "Header",
- "Headers",
- "ImmutableMultiDict",
- "ImmutableState",
- "MultiDict",
- "MultiMixin",
- "MutableScopeHeaders",
- "ResponseHeader",
- "State",
- "UploadFile",
- "URL",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 085a180..0000000
--- a/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/cookie.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/cookie.cpython-311.pyc
deleted file mode 100644
index 87a2646..0000000
--- a/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/cookie.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/headers.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/headers.cpython-311.pyc
deleted file mode 100644
index 4a8e1ad..0000000
--- a/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/headers.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/multi_dicts.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/multi_dicts.cpython-311.pyc
deleted file mode 100644
index c5a3dd4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/multi_dicts.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/response_header.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/response_header.cpython-311.pyc
deleted file mode 100644
index 0c83cae..0000000
--- a/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/response_header.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/state.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/state.cpython-311.pyc
deleted file mode 100644
index 6cd1f18..0000000
--- a/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/state.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/upload_file.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/upload_file.cpython-311.pyc
deleted file mode 100644
index 4db0e27..0000000
--- a/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/upload_file.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/url.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/url.cpython-311.pyc
deleted file mode 100644
index a9c2138..0000000
--- a/venv/lib/python3.11/site-packages/litestar/datastructures/__pycache__/url.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/datastructures/cookie.py b/venv/lib/python3.11/site-packages/litestar/datastructures/cookie.py
deleted file mode 100644
index 21cedc3..0000000
--- a/venv/lib/python3.11/site-packages/litestar/datastructures/cookie.py
+++ /dev/null
@@ -1,112 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import asdict, dataclass, field
-from http.cookies import SimpleCookie
-from typing import Any, Literal
-
-__all__ = ("Cookie",)
-
-
-@dataclass
-class Cookie:
- """Container class for defining a cookie using the ``Set-Cookie`` header.
-
- See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie for more details regarding this header.
- """
-
- key: str
- """Key for the cookie."""
- path: str = "/"
- """Path fragment that must exist in the request url for the cookie to be valid.
-
- Defaults to ``/``.
- """
- value: str | None = field(default=None)
- """Value for the cookie, if none given defaults to empty string."""
- max_age: int | None = field(default=None)
- """Maximal age of the cookie before its invalidated."""
- expires: int | None = field(default=None)
- """Seconds from now until the cookie expires."""
- domain: str | None = field(default=None)
- """Domain for which the cookie is valid."""
- secure: bool | None = field(default=None)
- """Https is required for the cookie."""
- httponly: bool | None = field(default=None)
- """Forbids javascript to access the cookie via ``document.cookie``."""
- samesite: Literal["lax", "strict", "none"] = field(default="lax")
- """Controls whether or not a cookie is sent with cross-site requests.
-
- Defaults to 'lax'.
- """
- description: str | None = field(default=None)
- """Description of the response cookie header for OpenAPI documentation."""
- documentation_only: bool = field(default=False)
- """Defines the Cookie instance as for OpenAPI documentation purpose only."""
-
- @property
- def simple_cookie(self) -> SimpleCookie:
- """Get a simple cookie object from the values.
-
- Returns:
- A :class:`SimpleCookie <http.cookies.SimpleCookie>`
- """
- simple_cookie: SimpleCookie = SimpleCookie()
- simple_cookie[self.key] = self.value or ""
-
- namespace = simple_cookie[self.key]
- for key, value in self.dict.items():
- if key in {"key", "value"}:
- continue
- if value is not None:
- updated_key = key
- if updated_key == "max_age":
- updated_key = "max-age"
- namespace[updated_key] = value
-
- return simple_cookie
-
- def to_header(self, **kwargs: Any) -> str:
- """Return a string representation suitable to be sent as HTTP headers.
-
- Args:
- **kwargs: Any kwargs to pass to the simple cookie output method.
- """
- return self.simple_cookie.output(**kwargs).strip()
-
- def to_encoded_header(self) -> tuple[bytes, bytes]:
- """Create encoded header for ASGI ``send``.
-
- Returns:
- A two tuple of bytes.
- """
- return b"set-cookie", self.to_header(header="").strip().encode("latin-1")
-
- @property
- def dict(self) -> dict[str, Any]:
- """Get the cookie as a dict.
-
- Returns:
- A dict of values
- """
- return {
- k: v
- for k, v in asdict(self).items()
- if k not in {"documentation_only", "description", "__pydantic_initialised__"}
- }
-
- def __hash__(self) -> int:
- return hash((self.key, self.path, self.domain))
-
- def __eq__(self, other: Any) -> bool:
- """Determine whether two cookie instances are equal according to the cookie spec, i.e. hey have a similar path,
- domain and key.
-
- Args:
- other: An arbitrary value
-
- Returns:
- A boolean
- """
- if isinstance(other, Cookie):
- return other.key == self.key and other.path == self.path and other.domain == self.domain
- return False
diff --git a/venv/lib/python3.11/site-packages/litestar/datastructures/headers.py b/venv/lib/python3.11/site-packages/litestar/datastructures/headers.py
deleted file mode 100644
index f3e9bd7..0000000
--- a/venv/lib/python3.11/site-packages/litestar/datastructures/headers.py
+++ /dev/null
@@ -1,534 +0,0 @@
-import re
-from abc import ABC, abstractmethod
-from contextlib import suppress
-from copy import copy
-from dataclasses import dataclass
-from typing import (
- TYPE_CHECKING,
- Any,
- ClassVar,
- Dict,
- Iterable,
- Iterator,
- List,
- Mapping,
- MutableMapping,
- Optional,
- Pattern,
- Tuple,
- Union,
- cast,
-)
-
-from multidict import CIMultiDict, CIMultiDictProxy, MultiMapping
-from typing_extensions import get_type_hints
-
-from litestar._multipart import parse_content_header
-from litestar.datastructures.multi_dicts import MultiMixin
-from litestar.dto.base_dto import AbstractDTO
-from litestar.exceptions import ImproperlyConfiguredException, ValidationException
-from litestar.types.empty import Empty
-from litestar.typing import FieldDefinition
-from litestar.utils.dataclass import simple_asdict
-from litestar.utils.scope.state import ScopeState
-
-if TYPE_CHECKING:
- from litestar.types.asgi_types import (
- HeaderScope,
- Message,
- RawHeaders,
- RawHeadersList,
- Scope,
- )
-
-__all__ = ("Accept", "CacheControlHeader", "ETag", "Header", "Headers", "MutableScopeHeaders")
-
-ETAG_RE = re.compile(r'([Ww]/)?"(.+)"')
-PRINTABLE_ASCII_RE: Pattern[str] = re.compile(r"^[ -~]+$")
-
-
-def _encode_headers(headers: Iterable[Tuple[str, str]]) -> "RawHeadersList":
- return [(key.lower().encode("latin-1"), value.encode("latin-1")) for key, value in headers]
-
-
-class Headers(CIMultiDictProxy[str], MultiMixin[str]):
- """An immutable, case-insensitive multi dict for HTTP headers."""
-
- def __init__(self, headers: Optional[Union[Mapping[str, str], "RawHeaders", MultiMapping]] = None) -> None:
- """Initialize ``Headers``.
-
- Args:
- headers: Initial value.
- """
- if not isinstance(headers, MultiMapping):
- headers_: Union[Mapping[str, str], List[Tuple[str, str]]] = {}
- if headers:
- if isinstance(headers, Mapping):
- headers_ = headers # pyright: ignore
- else:
- headers_ = [(key.decode("latin-1"), value.decode("latin-1")) for key, value in headers]
-
- super().__init__(CIMultiDict(headers_))
- else:
- super().__init__(headers)
- self._header_list: Optional[RawHeadersList] = None
-
- @classmethod
- def from_scope(cls, scope: "Scope") -> "Headers":
- """Create headers from a send-message.
-
- Args:
- scope: The ASGI connection scope.
-
- Returns:
- Headers
-
- Raises:
- ValueError: If the message does not have a ``headers`` key
- """
- connection_state = ScopeState.from_scope(scope)
- if (headers := connection_state.headers) is Empty:
- headers = connection_state.headers = cls(scope["headers"])
- return headers
-
- def to_header_list(self) -> "RawHeadersList":
- """Raw header value.
-
- Returns:
- A list of tuples contain the header and header-value as bytes
- """
- # Since ``Headers`` are immutable, this can be cached
- if not self._header_list:
- self._header_list = _encode_headers((key, value) for key in set(self) for value in self.getall(key))
- return self._header_list
-
-
-class MutableScopeHeaders(MutableMapping):
- """A case-insensitive, multidict-like structure that can be used to mutate headers within a
- :class:`Scope <.types.Scope>`
- """
-
- def __init__(self, scope: Optional["HeaderScope"] = None) -> None:
- """Initialize ``MutableScopeHeaders`` from a ``HeaderScope``.
-
- Args:
- scope: The ASGI connection scope.
- """
- self.headers: RawHeadersList
- if scope is not None:
- if not isinstance(scope["headers"], list):
- scope["headers"] = list(scope["headers"])
-
- self.headers = cast("RawHeadersList", scope["headers"])
- else:
- self.headers = []
-
- @classmethod
- def from_message(cls, message: "Message") -> "MutableScopeHeaders":
- """Construct a header from a message object.
-
- Args:
- message: :class:`Message <.types.Message>`.
-
- Returns:
- MutableScopeHeaders.
-
- Raises:
- ValueError: If the message does not have a ``headers`` key.
- """
- if "headers" not in message:
- raise ValueError(f"Invalid message type: {message['type']!r}")
-
- return cls(cast("HeaderScope", message))
-
- def add(self, key: str, value: str) -> None:
- """Add a header to the scope.
-
- Notes:
- - This method keeps duplicates.
-
- Args:
- key: Header key.
- value: Header value.
-
- Returns:
- None.
- """
- self.headers.append((key.lower().encode("latin-1"), value.encode("latin-1")))
-
- def getall(self, key: str, default: Optional[List[str]] = None) -> List[str]:
- """Get all values of a header.
-
- Args:
- key: Header key.
- default: Default value to return if ``name`` is not found.
-
- Returns:
- A list of strings.
-
- Raises:
- KeyError: if no header for ``name`` was found and ``default`` is not given.
- """
- name = key.lower()
- values = [
- header_value.decode("latin-1")
- for header_name, header_value in self.headers
- if header_name.decode("latin-1").lower() == name
- ]
- if not values:
- if default:
- return default
- raise KeyError
- return values
-
- def extend_header_value(self, key: str, value: str) -> None:
- """Extend a multivalued header.
-
- Notes:
- - A multivalues header is a header that can take a comma separated list.
- - If the header previously did not exist, it will be added.
-
- Args:
- key: Header key.
- value: Header value to add,
-
- Returns:
- None
- """
- existing = self.get(key)
- if existing is not None:
- value = ",".join([*existing.split(","), value])
- self[key] = value
-
- def __getitem__(self, key: str) -> str:
- """Get the first header matching ``name``"""
- name = key.lower()
- for header in self.headers:
- if header[0].decode("latin-1").lower() == name:
- return header[1].decode("latin-1")
- raise KeyError
-
- def _find_indices(self, key: str) -> List[int]:
- name = key.lower()
- return [i for i, (name_, _) in enumerate(self.headers) if name_.decode("latin-1").lower() == name]
-
- def __setitem__(self, key: str, value: str) -> None:
- """Set a header in the scope, overwriting duplicates."""
- name_encoded = key.lower().encode("latin-1")
- value_encoded = value.encode("latin-1")
- if indices := self._find_indices(key):
- for i in indices[1:]:
- del self.headers[i]
- self.headers[indices[0]] = (name_encoded, value_encoded)
- else:
- self.headers.append((name_encoded, value_encoded))
-
- def __delitem__(self, key: str) -> None:
- """Delete all headers matching ``name``"""
- indices = self._find_indices(key)
- for i in indices[::-1]:
- del self.headers[i]
-
- def __len__(self) -> int:
- """Return the length of the internally stored headers, including duplicates."""
- return len(self.headers)
-
- def __iter__(self) -> Iterator[str]:
- """Create an iterator of header names including duplicates."""
- return iter(h[0].decode("latin-1") for h in self.headers)
-
-
-@dataclass
-class Header(ABC):
- """An abstract type for HTTP headers."""
-
- HEADER_NAME: ClassVar[str] = ""
-
- documentation_only: bool = False
- """Defines the header instance as for OpenAPI documentation purpose only."""
-
- @abstractmethod
- def _get_header_value(self) -> str:
- """Get the header value as string."""
- raise NotImplementedError
-
- @classmethod
- @abstractmethod
- def from_header(cls, header_value: str) -> "Header":
- """Construct a header from its string representation."""
-
- def to_header(self, include_header_name: bool = False) -> str:
- """Get the header as string.
-
- Args:
- include_header_name: should include the header name in the return value. If set to false
- the return value will only include the header value. if set to true the return value
- will be: ``<header name>: <header value>``. Defaults to false.
- """
-
- if not self.HEADER_NAME:
- raise ImproperlyConfiguredException("Missing header name")
-
- return (f"{self.HEADER_NAME}: " if include_header_name else "") + self._get_header_value()
-
-
-@dataclass
-class CacheControlHeader(Header):
- """A ``cache-control`` header."""
-
- HEADER_NAME: ClassVar[str] = "cache-control"
-
- max_age: Optional[int] = None
- """Accessor for the ``max-age`` directive."""
- s_maxage: Optional[int] = None
- """Accessor for the ``s-maxage`` directive."""
- no_cache: Optional[bool] = None
- """Accessor for the ``no-cache`` directive."""
- no_store: Optional[bool] = None
- """Accessor for the ``no-store`` directive."""
- private: Optional[bool] = None
- """Accessor for the ``private`` directive."""
- public: Optional[bool] = None
- """Accessor for the ``public`` directive."""
- no_transform: Optional[bool] = None
- """Accessor for the ``no-transform`` directive."""
- must_revalidate: Optional[bool] = None
- """Accessor for the ``must-revalidate`` directive."""
- proxy_revalidate: Optional[bool] = None
- """Accessor for the ``proxy-revalidate`` directive."""
- must_understand: Optional[bool] = None
- """Accessor for the ``must-understand`` directive."""
- immutable: Optional[bool] = None
- """Accessor for the ``immutable`` directive."""
- stale_while_revalidate: Optional[int] = None
- """Accessor for the ``stale-while-revalidate`` directive."""
-
- _field_definitions: ClassVar[Optional[Dict[str, FieldDefinition]]] = None
-
- def _get_header_value(self) -> str:
- """Get the header value as string."""
-
- cc_items = [
- key.replace("_", "-") if isinstance(value, bool) else f"{key.replace('_', '-')}={value}"
- for key, value in simple_asdict(self, exclude_none=True, exclude={"documentation_only"}).items()
- ]
- return ", ".join(cc_items)
-
- @classmethod
- def from_header(cls, header_value: str) -> "CacheControlHeader":
- """Create a ``CacheControlHeader`` instance from the header value.
-
- Args:
- header_value: the header value as string
-
- Returns:
- An instance of ``CacheControlHeader``
- """
-
- cc_items = [v.strip() for v in header_value.split(",")]
- kwargs: Dict[str, Any] = {}
- field_definitions = cls._get_field_definitions()
- for cc_item in cc_items:
- key_value = cc_item.split("=")
- key_value[0] = key_value[0].replace("-", "_")
- if len(key_value) == 1:
- kwargs[key_value[0]] = True
- elif len(key_value) == 2:
- key, value = key_value
- if key not in field_definitions:
- raise ImproperlyConfiguredException("Invalid cache-control header")
- kwargs[key] = cls._convert_to_type(value, field_definition=field_definitions[key])
- else:
- raise ImproperlyConfiguredException("Invalid cache-control header value")
-
- try:
- return CacheControlHeader(**kwargs)
- except TypeError as exc:
- raise ImproperlyConfiguredException from exc
-
- @classmethod
- def prevent_storing(cls) -> "CacheControlHeader":
- """Create a ``cache-control`` header with the ``no-store`` directive which indicates that any caches of any kind
- (private or shared) should not store this response.
- """
-
- return cls(no_store=True)
-
- @classmethod
- def _get_field_definitions(cls) -> Dict[str, FieldDefinition]:
- """Get the type annotations for the ``CacheControlHeader`` class properties.
-
- This is needed due to the conversion from pydantic models to dataclasses. Dataclasses do not support
- automatic conversion of types like pydantic models do.
-
- Returns:
- A dictionary of type annotations
-
- """
-
- if cls._field_definitions is None:
- cls._field_definitions = {}
- for key, value in get_type_hints(cls, include_extras=True).items():
- definition = FieldDefinition.from_kwarg(annotation=value, name=key)
- # resolve_model_type so that field_definition.raw has the real raw type e.g. <class 'bool'>
- cls._field_definitions[key] = AbstractDTO.resolve_model_type(definition)
- return cls._field_definitions
-
- @classmethod
- def _convert_to_type(cls, value: str, field_definition: FieldDefinition) -> Any:
- """Convert the value to the expected type.
-
- Args:
- value: the value of the cache-control directive
- field_definition: the field definition for the value to convert
-
- Returns:
- The value converted to the expected type
- """
- # bool values shouldn't be initiated since they should have been caught earlier in the from_header method and
- # set with a value of True
- expected_type = field_definition.raw
- if expected_type is bool:
- raise ImproperlyConfiguredException("Invalid cache-control header value")
- return expected_type(value)
-
-
-@dataclass
-class ETag(Header):
- """An ``etag`` header."""
-
- HEADER_NAME: ClassVar[str] = "etag"
-
- weak: bool = False
- value: Optional[str] = None # only ASCII characters
-
- def _get_header_value(self) -> str:
- value = f'"{self.value}"'
- return f"W/{value}" if self.weak else value
-
- @classmethod
- def from_header(cls, header_value: str) -> "ETag":
- """Construct an ``etag`` header from its string representation.
-
- Note that this will unquote etag-values
- """
- match = ETAG_RE.match(header_value)
- if not match:
- raise ImproperlyConfiguredException
- weak, value = match.group(1, 2)
- try:
- return cls(weak=bool(weak), value=value)
- except ValueError as exc:
- raise ImproperlyConfiguredException from exc
-
- def __post_init__(self) -> None:
- if self.documentation_only is False and self.value is None:
- raise ValidationException("value must be set if documentation_only is false")
- if self.value and not PRINTABLE_ASCII_RE.fullmatch(self.value):
- raise ValidationException("value must only contain ASCII printable characters")
-
-
-class MediaTypeHeader:
- """A helper class for ``Accept`` header parsing."""
-
- __slots__ = ("maintype", "subtype", "params", "_params_str")
-
- def __init__(self, type_str: str) -> None:
- # preserve the original parameters, because the order might be
- # changed in the dict
- self._params_str = "".join(type_str.partition(";")[1:])
-
- full_type, self.params = parse_content_header(type_str)
- self.maintype, _, self.subtype = full_type.partition("/")
-
- def __str__(self) -> str:
- return f"{self.maintype}/{self.subtype}{self._params_str}"
-
- @property
- def priority(self) -> Tuple[int, int]:
- # Use fixed point values with two decimals to avoid problems
- # when comparing float values
- quality = 100
- if "q" in self.params:
- with suppress(ValueError):
- quality = int(100 * float(self.params["q"]))
-
- if self.maintype == "*":
- specificity = 0
- elif self.subtype == "*":
- specificity = 1
- elif not self.params or ("q" in self.params and len(self.params) == 1):
- # no params or 'q' is the only one which we ignore
- specificity = 2
- else:
- specificity = 3
-
- return quality, specificity
-
- def match(self, other: "MediaTypeHeader") -> bool:
- return next(
- (False for key, value in self.params.items() if key != "q" and value != other.params.get(key)),
- False
- if self.subtype != "*" and other.subtype != "*" and self.subtype != other.subtype
- else self.maintype == "*" or other.maintype == "*" or self.maintype == other.maintype,
- )
-
-
-class Accept:
- """An ``Accept`` header."""
-
- __slots__ = ("_accepted_types",)
-
- def __init__(self, accept_value: str) -> None:
- self._accepted_types = [MediaTypeHeader(t) for t in accept_value.split(",")]
- self._accepted_types.sort(key=lambda t: t.priority, reverse=True)
-
- def __len__(self) -> int:
- return len(self._accepted_types)
-
- def __getitem__(self, key: int) -> str:
- return str(self._accepted_types[key])
-
- def __iter__(self) -> Iterator[str]:
- return map(str, self._accepted_types)
-
- def best_match(self, provided_types: List[str], default: Optional[str] = None) -> Optional[str]:
- """Find the best matching media type for the request.
-
- Args:
- provided_types: A list of media types that can be provided as a response. These types
- can contain a wildcard ``*`` character in the main- or subtype part.
- default: The media type that is returned if none of the provided types match.
-
- Returns:
- The best matching media type. If the matching provided type contains wildcard characters,
- they are replaced with the corresponding part of the accepted type. Otherwise the
- provided type is returned as-is.
- """
- types = [MediaTypeHeader(t) for t in provided_types]
-
- for accepted in self._accepted_types:
- for provided in types:
- if provided.match(accepted):
- # Return the accepted type with wildcards replaced
- # by concrete parts from the provided type
- result = copy(provided)
- if result.subtype == "*":
- result.subtype = accepted.subtype
- if result.maintype == "*":
- result.maintype = accepted.maintype
- return str(result)
- return default
-
- def accepts(self, media_type: str) -> bool:
- """Check if the request accepts the specified media type.
-
- If multiple media types can be provided, it is better to use :func:`best_match`.
-
- Args:
- media_type: The media type to check for.
-
- Returns:
- True if the request accepts ``media_type``.
- """
- return self.best_match([media_type]) == media_type
diff --git a/venv/lib/python3.11/site-packages/litestar/datastructures/multi_dicts.py b/venv/lib/python3.11/site-packages/litestar/datastructures/multi_dicts.py
deleted file mode 100644
index 7702e1a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/datastructures/multi_dicts.py
+++ /dev/null
@@ -1,106 +0,0 @@
-from __future__ import annotations
-
-from abc import ABC
-from typing import TYPE_CHECKING, Any, Generator, Generic, Iterable, Mapping, TypeVar
-
-from multidict import MultiDict as BaseMultiDict
-from multidict import MultiDictProxy, MultiMapping
-
-from litestar.datastructures.upload_file import UploadFile
-
-if TYPE_CHECKING:
- from typing_extensions import Self
-
-
-__all__ = ("FormMultiDict", "ImmutableMultiDict", "MultiDict", "MultiMixin")
-
-
-T = TypeVar("T")
-
-
-class MultiMixin(Generic[T], MultiMapping[T], ABC):
- """Mixin providing common methods for multi dicts, used by :class:`ImmutableMultiDict` and :class:`MultiDict`"""
-
- def dict(self) -> dict[str, list[Any]]:
- """Return the multi-dict as a dict of lists.
-
- Returns:
- A dict of lists
- """
- return {k: self.getall(k) for k in set(self.keys())}
-
- def multi_items(self) -> Generator[tuple[str, T], None, None]:
- """Get all keys and values, including duplicates.
-
- Returns:
- A list of tuples containing key-value pairs
- """
- for key in set(self):
- for value in self.getall(key):
- yield key, value
-
-
-class MultiDict(BaseMultiDict[T], MultiMixin[T], Generic[T]):
- """MultiDict, using :class:`MultiDict <multidict.MultiDictProxy>`."""
-
- def __init__(self, args: MultiMapping | Mapping[str, T] | Iterable[tuple[str, T]] | None = None) -> None:
- """Initialize ``MultiDict`` from a`MultiMapping``,
- :class:`Mapping <typing.Mapping>` or an iterable of tuples.
-
- Args:
- args: Mapping-like structure to create the ``MultiDict`` from
- """
- super().__init__(args or {})
-
- def immutable(self) -> ImmutableMultiDict[T]:
- """Create an.
-
- :class:`ImmutableMultiDict` view.
-
- Returns:
- An immutable multi dict
- """
- return ImmutableMultiDict[T](self) # pyright: ignore
-
- def copy(self) -> Self:
- """Return a shallow copy"""
- return type(self)(list(self.multi_items()))
-
-
-class ImmutableMultiDict(MultiDictProxy[T], MultiMixin[T], Generic[T]):
- """Immutable MultiDict, using class:`MultiDictProxy <multidict.MultiDictProxy>`."""
-
- def __init__(self, args: MultiMapping | Mapping[str, Any] | Iterable[tuple[str, Any]] | None = None) -> None:
- """Initialize ``ImmutableMultiDict`` from a `MultiMapping``,
- :class:`Mapping <typing.Mapping>` or an iterable of tuples.
-
- Args:
- args: Mapping-like structure to create the ``ImmutableMultiDict`` from
- """
- super().__init__(BaseMultiDict(args or {}))
-
- def mutable_copy(self) -> MultiDict[T]:
- """Create a mutable copy as a :class:`MultiDict`
-
- Returns:
- A mutable multi dict
- """
- return MultiDict(list(self.multi_items()))
-
- def copy(self) -> Self: # type: ignore[override]
- """Return a shallow copy"""
- return type(self)(self.items())
-
-
-class FormMultiDict(ImmutableMultiDict[Any]):
- """MultiDict for form data."""
-
- async def close(self) -> None:
- """Close all files in the multi-dict.
-
- Returns:
- None
- """
- for _, value in self.multi_items():
- if isinstance(value, UploadFile):
- await value.close()
diff --git a/venv/lib/python3.11/site-packages/litestar/datastructures/response_header.py b/venv/lib/python3.11/site-packages/litestar/datastructures/response_header.py
deleted file mode 100644
index f781d0c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/datastructures/response_header.py
+++ /dev/null
@@ -1,125 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING, Any
-
-from litestar.exceptions import ImproperlyConfiguredException
-
-if TYPE_CHECKING:
- from litestar.openapi.spec import Example
-
-__all__ = ("ResponseHeader",)
-
-
-@dataclass
-class ResponseHeader:
- """Container type for a response header."""
-
- name: str
- """Header name"""
-
- documentation_only: bool = False
- """Defines the ResponseHeader instance as for OpenAPI documentation purpose only."""
-
- value: str | None = None
- """Value to set for the response header."""
-
- description: str | None = None
- """A brief description of the parameter. This could contain examples of
- use.
-
- [CommonMark syntax](https://spec.commonmark.org/) MAY be used for
- rich text representation.
- """
-
- required: bool = False
- """Determines whether this parameter is mandatory.
-
- If the [parameter location](https://spec.openapis.org/oas/v3.1.0#parameterIn) is `"path"`, this property is **REQUIRED** and its value MUST be `true`.
- Otherwise, the property MAY be included and its default value is `false`.
- """
-
- deprecated: bool = False
- """Specifies that a parameter is deprecated and SHOULD be transitioned out
- of usage.
-
- Default value is `false`.
- """
-
- allow_empty_value: bool = False
- """Sets the ability to pass empty-valued parameters. This is valid only for
- `query` parameters and allows sending a parameter with an empty value.
- Default value is `false`. If.
-
- [style](https://spec.openapis.org/oas/v3.1.0#parameterStyle) is used, and if behavior is `n/a` (cannot be
- serialized), the value of `allowEmptyValue` SHALL be ignored. Use of this property is NOT RECOMMENDED, as it is
- likely to be removed in a later revision.
-
- The rules for serialization of the parameter are specified in one of two ways.
- For simpler scenarios, a [schema](https://spec.openapis.org/oas/v3.1.0#parameterSchema) and [style](https://spec.openapis.org/oas/v3.1.0#parameterStyle)
- can describe the structure and syntax of the parameter.
- """
-
- style: str | None = None
- """Describes how the parameter value will be serialized depending on the
- type of the parameter value. Default values (based on value of `in`):
-
- - for `query` - `form`;
- - for `path` - `simple`;
- - for `header` - `simple`;
- - for `cookie` - `form`.
- """
-
- explode: bool | None = None
- """When this is true, parameter values of type `array` or `object` generate
- separate parameters for each value of the array or key-value pair of the
- map.
-
- For other types of parameters this property has no effect.
- When [style](https://spec.openapis.org/oas/v3.1.0#parameterStyle) is `form`, the default value is `true`.
- For all other styles, the default value is `false`.
- """
-
- allow_reserved: bool = False
- """Determines whether the parameter value SHOULD allow reserved characters,
- as defined by.
-
- [RFC3986](https://tools.ietf.org/html/rfc3986#section-2.2) `:/?#[]@!$&'()*+,;=` to be included without percent-
- encoding.
-
- This property only applies to parameters with an `in` value of `query`. The default value is `false`.
- """
-
- example: Any | None = None
- """Example of the parameter's potential value.
-
- The example SHOULD match the specified schema and encoding
- properties if present. The `example` field is mutually exclusive of
- the `examples` field. Furthermore, if referencing a `schema` that
- contains an example, the `example` value SHALL _override_ the
- example provided by the schema. To represent examples of media types
- that cannot naturally be represented in JSON or YAML, a string value
- can contain the example with escaping where necessary.
- """
-
- examples: dict[str, Example] | None = None
- """Examples of the parameter's potential value. Each example SHOULD contain
- a value in the correct format as specified in the parameter encoding. The
- `examples` field is mutually exclusive of the `example` field. Furthermore,
- if referencing a `schema` that contains an example, the `examples` value
- SHALL _override_ the example provided by the schema.
-
- For more complex scenarios, the [content](https://spec.openapis.org/oas/v3.1.0#parameterContent) property
- can define the media type and schema of the parameter.
- A parameter MUST contain either a `schema` property, or a `content` property, but not both.
- When `example` or `examples` are provided in conjunction with the `schema` object,
- the example MUST follow the prescribed serialization strategy for the parameter.
- """
-
- def __post_init__(self) -> None:
- """Ensure that either value is set or the instance is for documentation_only."""
- if not self.documentation_only and self.value is None:
- raise ImproperlyConfiguredException("value must be set if documentation_only is false")
-
- def __hash__(self) -> int:
- return hash(self.name)
diff --git a/venv/lib/python3.11/site-packages/litestar/datastructures/state.py b/venv/lib/python3.11/site-packages/litestar/datastructures/state.py
deleted file mode 100644
index 71980e0..0000000
--- a/venv/lib/python3.11/site-packages/litestar/datastructures/state.py
+++ /dev/null
@@ -1,313 +0,0 @@
-from __future__ import annotations
-
-from copy import copy, deepcopy
-from threading import RLock
-from typing import TYPE_CHECKING, Any, Callable, Generator, Iterable, Iterator, Mapping, MutableMapping
-
-if TYPE_CHECKING:
- from typing_extensions import Self
-
-__all__ = ("ImmutableState", "State")
-
-
-class ImmutableState(Mapping[str, Any]):
- """An object meant to store arbitrary state.
-
- It can be accessed using dot notation while exposing dict like functionalities.
- """
-
- __slots__ = (
- "_state",
- "_deep_copy",
- )
-
- _state: dict[str, Any]
-
- def __init__(
- self, state: ImmutableState | Mapping[str, Any] | Iterable[tuple[str, Any]], deep_copy: bool = True
- ) -> None:
- """Initialize an ``ImmutableState`` instance.
-
- Args:
- state: An object to initialize the state from. Can be a dict, an instance of :class:`ImmutableState`, or a tuple
- of key value paris.
- deep_copy: Whether to 'deepcopy' the passed in state.
-
- Examples:
- .. code-block:: python
-
- from litestar.datastructures import ImmutableState
-
- state_dict = {"first": 1, "second": 2, "third": 3, "fourth": 4}
- state = ImmutableState(state_dict)
-
- # state implements the Mapping type:
- assert len(state) == 3
- assert "first" in state
- assert not "fourth" in state
- assert state["first"] == 1
- assert [(k, v) for k, v in state.items()] == [("first", 1), ("second", 2), ("third", 3)]
-
- # state implements __bool__
- assert state # state is true when it has values.
- assert not State() # state is empty when it has no values.
-
- # it has a 'dict' method to retrieve a shallow copy of the underlying dict
- inner_dict = state.dict()
- assert inner_dict == state_dict
-
- # you can also retrieve a mutable State by calling 'mutable_copy'
- mutable_state = state.mutable_copy()
- del state["first"]
- assert "first" not in state
-
- """
- if isinstance(state, ImmutableState):
- state = state._state
-
- if not isinstance(state, dict) and isinstance(state, Iterable):
- state = dict(state)
-
- super().__setattr__("_deep_copy", deep_copy)
- super().__setattr__("_state", deepcopy(state) if deep_copy else state)
-
- def __bool__(self) -> bool:
- """Return a boolean indicating whether the wrapped dict instance has values."""
- return bool(self._state)
-
- def __getitem__(self, key: str) -> Any:
- """Get the value for the corresponding key from the wrapped state object using subscription notation.
-
- Args:
- key: Key to access.
-
- Raises:
- KeyError
-
- Returns:
- A value from the wrapped state instance.
- """
- return self._state[key]
-
- def __iter__(self) -> Iterator[str]:
- """Return an iterator iterating the wrapped state dict.
-
- Returns:
- An iterator of strings
- """
- return iter(self._state)
-
- def __len__(self) -> int:
- """Return length of the wrapped state dict.
-
- Returns:
- An integer
- """
- return len(self._state)
-
- def __getattr__(self, key: str) -> Any:
- """Get the value for the corresponding key from the wrapped state object using attribute notation.
-
- Args:
- key: Key to retrieve
-
- Raises:
- AttributeError: if the given attribute is not set.
-
- Returns:
- The retrieved value
- """
- try:
- return self._state[key]
- except KeyError as e:
- raise AttributeError from e
-
- def __copy__(self) -> Self:
- """Return a shallow copy of the given state object.
-
- Customizes how the builtin "copy" function will work.
- """
- return self.__class__(self._state, deep_copy=self._deep_copy) # pyright: ignore
-
- def mutable_copy(self) -> State:
- """Return a mutable copy of the state object.
-
- Returns:
- A ``State``
- """
- return State(self._state, deep_copy=self._deep_copy)
-
- def dict(self) -> dict[str, Any]:
- """Return a shallow copy of the wrapped dict.
-
- Returns:
- A dict
- """
- return copy(self._state)
-
- @classmethod
- def __get_validators__(
- cls,
- ) -> Generator[Callable[[ImmutableState | dict[str, Any] | Iterable[tuple[str, Any]]], ImmutableState], None, None]: # type: ignore[valid-type]
- """Pydantic compatible method to allow custom parsing of state instances in a SignatureModel."""
- yield cls.validate
-
- @classmethod
- def validate(cls, value: ImmutableState | dict[str, Any] | Iterable[tuple[str, Any]]) -> Self: # type: ignore[valid-type]
- """Parse a value and instantiate state inside a SignatureModel. This allows us to use custom subclasses of
- state, as well as allows users to decide whether state is mutable or immutable.
-
- Args:
- value: The value from which to initialize the state instance.
-
- Returns:
- An ImmutableState instance
- """
- deep_copy = value._deep_copy if isinstance(value, ImmutableState) else False
- return cls(value, deep_copy=deep_copy)
-
-
-class State(ImmutableState, MutableMapping[str, Any]):
- """An object meant to store arbitrary state.
-
- It can be accessed using dot notation while exposing dict like functionalities.
- """
-
- __slots__ = ("_lock",)
-
- _lock: RLock
-
- def __init__(
- self,
- state: ImmutableState | Mapping[str, Any] | Iterable[tuple[str, Any]] | None = None,
- deep_copy: bool = False,
- ) -> None:
- """Initialize a ``State`` instance with an optional value.
-
- Args:
- state: An object to initialize the state from. Can be a dict, an instance of 'ImmutableState', or a tuple of key value paris.
- deep_copy: Whether to 'deepcopy' the passed in state.
-
- .. code-block:: python
- :caption: Examples
-
- from litestar.datastructures import State
-
- state_dict = {"first": 1, "second": 2, "third": 3, "fourth": 4}
- state = State(state_dict)
-
- # state can be accessed using '.' notation
- assert state.fourth == 4
- del state.fourth
-
- # state implements the Mapping type:
- assert len(state) == 3
- assert "first" in state
- assert not "fourth" in state
- assert state["first"] == 1
- assert [(k, v) for k, v in state.items()] == [("first", 1), ("second", 2), ("third", 3)]
-
- state["fourth"] = 4
- assert "fourth" in state
- del state["fourth"]
-
- # state implements __bool__
- assert state # state is true when it has values.
- assert not State() # state is empty when it has no values.
-
- # it has shallow copy
- copied_state = state.copy()
- del copied_state.first
- assert state.first
-
- # it has a 'dict' method to retrieve a shallow copy of the underlying dict
- inner_dict = state.dict()
- assert inner_dict == state_dict
-
- # you can get an immutable copy of the state by calling 'immutable_immutable_copy'
- immutable_copy = state.immutable_copy()
- del immutable_copy.first # raises AttributeError
-
- """
-
- super().__init__(state if state is not None else {}, deep_copy=deep_copy)
- super().__setattr__("_lock", RLock())
-
- def __delitem__(self, key: str) -> None:
- """Delete the value from the key from the wrapped state object using subscription notation.
-
- Args:
- key: Key to delete
-
- Raises:
- KeyError: if the given attribute is not set.
-
- Returns:
- None
- """
-
- with self._lock:
- del self._state[key]
-
- def __setitem__(self, key: str, value: Any) -> None:
- """Set an item in the state using subscription notation.
-
- Args:
- key: Key to set.
- value: Value to set.
-
- Returns:
- None
- """
-
- with self._lock:
- self._state[key] = value
-
- def __setattr__(self, key: str, value: Any) -> None:
- """Set an item in the state using attribute notation.
-
- Args:
- key: Key to set.
- value: Value to set.
-
- Returns:
- None
- """
-
- with self._lock:
- self._state[key] = value
-
- def __delattr__(self, key: str) -> None:
- """Delete the value from the key from the wrapped state object using attribute notation.
-
- Args:
- key: Key to delete
-
- Raises:
- AttributeError: if the given attribute is not set.
-
- Returns:
- None
- """
-
- try:
- with self._lock:
- del self._state[key]
- except KeyError as e:
- raise AttributeError from e
-
- def copy(self) -> Self:
- """Return a shallow copy of the state object.
-
- Returns:
- A ``State``
- """
- return self.__class__(self.dict(), deep_copy=self._deep_copy) # pyright: ignore
-
- def immutable_copy(self) -> ImmutableState:
- """Return a shallow copy of the state object, setting it to be frozen.
-
- Returns:
- A ``State``
- """
- return ImmutableState(self, deep_copy=self._deep_copy)
diff --git a/venv/lib/python3.11/site-packages/litestar/datastructures/upload_file.py b/venv/lib/python3.11/site-packages/litestar/datastructures/upload_file.py
deleted file mode 100644
index 09ad2d3..0000000
--- a/venv/lib/python3.11/site-packages/litestar/datastructures/upload_file.py
+++ /dev/null
@@ -1,101 +0,0 @@
-from __future__ import annotations
-
-from tempfile import SpooledTemporaryFile
-
-from litestar.concurrency import sync_to_thread
-from litestar.constants import ONE_MEGABYTE
-
-__all__ = ("UploadFile",)
-
-
-class UploadFile:
- """Representation of a file upload"""
-
- __slots__ = ("filename", "file", "content_type", "headers")
-
- def __init__(
- self,
- content_type: str,
- filename: str,
- file_data: bytes | None = None,
- headers: dict[str, str] | None = None,
- max_spool_size: int = ONE_MEGABYTE,
- ) -> None:
- """Upload file in-memory container.
-
- Args:
- content_type: Content type for the file.
- filename: The filename.
- file_data: File data.
- headers: Any attached headers.
- max_spool_size: The size above which the temporary file will be rolled to disk.
- """
- self.filename = filename
- self.content_type = content_type
- self.file = SpooledTemporaryFile(max_size=max_spool_size)
- self.headers = headers or {}
-
- if file_data:
- self.file.write(file_data)
- self.file.seek(0)
-
- @property
- def rolled_to_disk(self) -> bool:
- """Determine whether the spooled file exceeded the rolled-to-disk threshold and is no longer in memory.
-
- Returns:
- A boolean flag
- """
- return getattr(self.file, "_rolled", False)
-
- async def write(self, data: bytes) -> int:
- """Proxy for data writing.
-
- Args:
- data: Byte string to write.
-
- Returns:
- None
- """
- if self.rolled_to_disk:
- return await sync_to_thread(self.file.write, data)
- return self.file.write(data)
-
- async def read(self, size: int = -1) -> bytes:
- """Proxy for data reading.
-
- Args:
- size: position from which to read.
-
- Returns:
- Byte string.
- """
- if self.rolled_to_disk:
- return await sync_to_thread(self.file.read, size)
- return self.file.read(size)
-
- async def seek(self, offset: int) -> int:
- """Async proxy for file seek.
-
- Args:
- offset: start position..
-
- Returns:
- None.
- """
- if self.rolled_to_disk:
- return await sync_to_thread(self.file.seek, offset)
- return self.file.seek(offset)
-
- async def close(self) -> None:
- """Async proxy for file close.
-
- Returns:
- None.
- """
- if self.rolled_to_disk:
- return await sync_to_thread(self.file.close)
- return self.file.close()
-
- def __repr__(self) -> str:
- return f"{self.filename} - {self.content_type}"
diff --git a/venv/lib/python3.11/site-packages/litestar/datastructures/url.py b/venv/lib/python3.11/site-packages/litestar/datastructures/url.py
deleted file mode 100644
index f3441d0..0000000
--- a/venv/lib/python3.11/site-packages/litestar/datastructures/url.py
+++ /dev/null
@@ -1,262 +0,0 @@
-from __future__ import annotations
-
-from functools import lru_cache
-from typing import TYPE_CHECKING, Any, NamedTuple
-from urllib.parse import SplitResult, urlencode, urlsplit, urlunsplit
-
-from litestar._parsers import parse_query_string
-from litestar.datastructures import MultiDict
-from litestar.types import Empty
-
-if TYPE_CHECKING:
- from typing_extensions import Self
-
- from litestar.types import EmptyType, Scope
-
-__all__ = ("Address", "URL")
-
-_DEFAULT_SCHEME_PORTS = {"http": 80, "https": 443, "ftp": 21, "ws": 80, "wss": 443}
-
-
-class Address(NamedTuple):
- """Just a network address."""
-
- host: str
- """Address host."""
- port: int
- """Address port."""
-
-
-def make_absolute_url(path: str | URL, base: str | URL) -> str:
- """Create an absolute URL.
-
- Args:
- path: URL path to make absolute
- base: URL to use as a base
-
- Returns:
- A string representing the new, absolute URL
- """
- url = base if isinstance(base, URL) else URL(base)
- netloc = url.netloc
- path = url.path.rstrip("/") + str(path)
- return str(URL.from_components(scheme=url.scheme, netloc=netloc, path=path))
-
-
-class URL:
- """Representation and modification utilities of a URL."""
-
- __slots__ = (
- "_query_params",
- "_parsed_url",
- "fragment",
- "hostname",
- "netloc",
- "password",
- "path",
- "port",
- "query",
- "scheme",
- "username",
- )
-
- _query_params: EmptyType | MultiDict
- _parsed_url: str | None
-
- scheme: str
- """URL scheme."""
- netloc: str
- """Network location."""
- path: str
- """Hierarchical path."""
- fragment: str
- """Fragment component."""
- query: str
- """Query string."""
- username: str | None
- """Username if specified."""
- password: str | None
- """Password if specified."""
- port: int | None
- """Port if specified."""
- hostname: str | None
- """Hostname if specified."""
-
- def __new__(cls, url: str | SplitResult) -> URL:
- """Create a new instance.
-
- Args:
- url: url string or split result to represent.
- """
- return cls._new(url=url)
-
- @classmethod
- @lru_cache
- def _new(cls, url: str | SplitResult) -> URL:
- instance = super().__new__(cls)
- instance._parsed_url = None
-
- if isinstance(url, str):
- result = urlsplit(url)
- instance._parsed_url = url
- else:
- result = url
-
- instance.scheme = result.scheme
- instance.netloc = result.netloc
- instance.path = result.path
- instance.fragment = result.fragment
- instance.query = result.query
- instance.username = result.username
- instance.password = result.password
- instance.port = result.port
- instance.hostname = result.hostname
- instance._query_params = Empty
-
- return instance
-
- @property
- def _url(self) -> str:
- if not self._parsed_url:
- self._parsed_url = str(
- urlunsplit(
- SplitResult(
- scheme=self.scheme,
- netloc=self.netloc,
- path=self.path,
- fragment=self.fragment,
- query=self.query,
- )
- )
- )
- return self._parsed_url
-
- @classmethod
- @lru_cache
- def from_components(
- cls,
- scheme: str = "",
- netloc: str = "",
- path: str = "",
- fragment: str = "",
- query: str = "",
- ) -> Self:
- """Create a new URL from components.
-
- Args:
- scheme: URL scheme
- netloc: Network location
- path: Hierarchical path
- query: Query component
- fragment: Fragment identifier
-
- Returns:
- A new URL with the given components
- """
- return cls(
- SplitResult(
- scheme=scheme,
- netloc=netloc,
- path=path,
- fragment=fragment,
- query=query,
- )
- )
-
- @classmethod
- def from_scope(cls, scope: Scope) -> Self:
- """Construct a URL from a :class:`Scope <.types.Scope>`
-
- Args:
- scope: A scope
-
- Returns:
- A URL
- """
- scheme = scope.get("scheme", "http")
- server = scope.get("server")
- path = scope.get("root_path", "") + scope["path"]
- query_string = scope.get("query_string", b"")
-
- # we use iteration here because it's faster, and headers might not yet be cached
- host = next(
- (
- header_value.decode("latin-1")
- for header_name, header_value in scope.get("headers", [])
- if header_name == b"host"
- ),
- "",
- )
- if server and not host:
- host, port = server
- default_port = _DEFAULT_SCHEME_PORTS[scheme]
- if port != default_port:
- host = f"{host}:{port}"
-
- return cls.from_components(
- scheme=scheme if server else "",
- query=query_string.decode(),
- netloc=host,
- path=path,
- )
-
- def with_replacements(
- self,
- scheme: str = "",
- netloc: str = "",
- path: str = "",
- query: str | MultiDict | None | EmptyType = Empty,
- fragment: str = "",
- ) -> Self:
- """Create a new URL, replacing the given components.
-
- Args:
- scheme: URL scheme
- netloc: Network location
- path: Hierarchical path
- query: Raw query string
- fragment: Fragment identifier
-
- Returns:
- A new URL with the given components replaced
- """
- if isinstance(query, MultiDict):
- query = urlencode(query=query)
-
- query = (query if query is not Empty else self.query) or ""
-
- return type(self).from_components(
- scheme=scheme or self.scheme,
- netloc=netloc or self.netloc,
- path=path or self.path,
- query=query,
- fragment=fragment or self.fragment,
- )
-
- @property
- def query_params(self) -> MultiDict:
- """Query parameters of a URL as a :class:`MultiDict <.datastructures.multi_dicts.MultiDict>`
-
- Returns:
- A :class:`MultiDict <.datastructures.multi_dicts.MultiDict>` with query parameters
-
- Notes:
- - The returned ``MultiDict`` is mutable, :class:`URL` itself is *immutable*,
- therefore mutating the query parameters will not directly mutate the ``URL``.
- If you want to modify query parameters, make modifications in the
- multidict and pass them back to :meth:`with_replacements`
- """
- if self._query_params is Empty:
- self._query_params = MultiDict(parse_query_string(query_string=self.query.encode()))
- return self._query_params
-
- def __str__(self) -> str:
- return self._url
-
- def __eq__(self, other: Any) -> bool:
- if isinstance(other, (str, URL)):
- return str(self) == str(other)
- return NotImplemented # pragma: no cover
-
- def __repr__(self) -> str:
- return f"{type(self).__name__}({self._url!r})"
diff --git a/venv/lib/python3.11/site-packages/litestar/di.py b/venv/lib/python3.11/site-packages/litestar/di.py
deleted file mode 100644
index 066a128..0000000
--- a/venv/lib/python3.11/site-packages/litestar/di.py
+++ /dev/null
@@ -1,117 +0,0 @@
-from __future__ import annotations
-
-from inspect import isasyncgenfunction, isclass, isgeneratorfunction
-from typing import TYPE_CHECKING, Any
-
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.types import Empty
-from litestar.utils import ensure_async_callable
-from litestar.utils.predicates import is_async_callable
-from litestar.utils.warnings import (
- warn_implicit_sync_to_thread,
- warn_sync_to_thread_with_async_callable,
- warn_sync_to_thread_with_generator,
-)
-
-if TYPE_CHECKING:
- from litestar._signature import SignatureModel
- from litestar.types import AnyCallable
- from litestar.utils.signature import ParsedSignature
-
-__all__ = ("Provide",)
-
-
-class Provide:
- """Wrapper class for dependency injection"""
-
- __slots__ = (
- "dependency",
- "has_sync_callable",
- "has_sync_generator_dependency",
- "has_async_generator_dependency",
- "parsed_fn_signature",
- "signature_model",
- "sync_to_thread",
- "use_cache",
- "value",
- )
-
- parsed_fn_signature: ParsedSignature
- signature_model: type[SignatureModel]
- dependency: AnyCallable
-
- def __init__(
- self,
- dependency: AnyCallable | type[Any],
- use_cache: bool = False,
- sync_to_thread: bool | None = None,
- ) -> None:
- """Initialize ``Provide``
-
- Args:
- dependency: Callable to call or class to instantiate. The result is then injected as a dependency.
- use_cache: Cache the dependency return value. Defaults to False.
- sync_to_thread: Run sync code in an async thread. Defaults to False.
- """
- if not callable(dependency):
- raise ImproperlyConfiguredException("Provider dependency must a callable value")
-
- is_class_dependency = isclass(dependency)
- self.has_sync_generator_dependency = isgeneratorfunction(
- dependency if not is_class_dependency else dependency.__call__ # type: ignore[operator]
- )
- self.has_async_generator_dependency = isasyncgenfunction(
- dependency if not is_class_dependency else dependency.__call__ # type: ignore[operator]
- )
- has_generator_dependency = self.has_sync_generator_dependency or self.has_async_generator_dependency
-
- if has_generator_dependency and use_cache:
- raise ImproperlyConfiguredException(
- "Cannot cache generator dependency, consider using Lifespan Context instead."
- )
-
- has_sync_callable = is_class_dependency or not is_async_callable(dependency) # pyright: ignore
-
- if sync_to_thread is not None:
- if has_generator_dependency:
- warn_sync_to_thread_with_generator(dependency, stacklevel=3) # type: ignore[arg-type]
- elif not has_sync_callable:
- warn_sync_to_thread_with_async_callable(dependency, stacklevel=3) # pyright: ignore
- elif has_sync_callable and not has_generator_dependency:
- warn_implicit_sync_to_thread(dependency, stacklevel=3) # pyright: ignore
-
- if sync_to_thread and has_sync_callable:
- self.dependency = ensure_async_callable(dependency) # pyright: ignore
- self.has_sync_callable = False
- else:
- self.dependency = dependency # pyright: ignore
- self.has_sync_callable = has_sync_callable
-
- self.sync_to_thread = bool(sync_to_thread)
- self.use_cache = use_cache
- self.value: Any = Empty
-
- async def __call__(self, **kwargs: Any) -> Any:
- """Call the provider's dependency."""
-
- if self.use_cache and self.value is not Empty:
- return self.value
-
- if self.has_sync_callable:
- value = self.dependency(**kwargs)
- else:
- value = await self.dependency(**kwargs)
-
- if self.use_cache:
- self.value = value
-
- return value
-
- def __eq__(self, other: Any) -> bool:
- # check if memory address is identical, otherwise compare attributes
- return other is self or (
- isinstance(other, self.__class__)
- and other.dependency == self.dependency
- and other.use_cache == self.use_cache
- and other.value == self.value
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/__init__.py b/venv/lib/python3.11/site-packages/litestar/dto/__init__.py
deleted file mode 100644
index 052e6a4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from .base_dto import AbstractDTO
-from .config import DTOConfig
-from .data_structures import DTOData, DTOFieldDefinition
-from .dataclass_dto import DataclassDTO
-from .field import DTOField, Mark, dto_field
-from .msgspec_dto import MsgspecDTO
-from .types import RenameStrategy
-
-__all__ = (
- "AbstractDTO",
- "DTOConfig",
- "DTOData",
- "DTOField",
- "DTOFieldDefinition",
- "DataclassDTO",
- "Mark",
- "MsgspecDTO",
- "RenameStrategy",
- "dto_field",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 7551946..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/_backend.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/_backend.cpython-311.pyc
deleted file mode 100644
index d39aea9..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/_backend.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/_codegen_backend.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/_codegen_backend.cpython-311.pyc
deleted file mode 100644
index 610f4b4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/_codegen_backend.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/_types.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/_types.cpython-311.pyc
deleted file mode 100644
index 53877b3..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/_types.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/base_dto.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/base_dto.cpython-311.pyc
deleted file mode 100644
index eb9af7a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/base_dto.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/config.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/config.cpython-311.pyc
deleted file mode 100644
index ba3f03d..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/config.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/data_structures.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/data_structures.cpython-311.pyc
deleted file mode 100644
index 785f3b0..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/data_structures.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/dataclass_dto.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/dataclass_dto.cpython-311.pyc
deleted file mode 100644
index 2388d4a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/dataclass_dto.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/field.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/field.cpython-311.pyc
deleted file mode 100644
index a6d1cbb..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/field.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/msgspec_dto.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/msgspec_dto.cpython-311.pyc
deleted file mode 100644
index 0d15d6b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/msgspec_dto.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/types.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/types.cpython-311.pyc
deleted file mode 100644
index ec01cd4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/__pycache__/types.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/_backend.py b/venv/lib/python3.11/site-packages/litestar/dto/_backend.py
deleted file mode 100644
index 1c48dc0..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/_backend.py
+++ /dev/null
@@ -1,911 +0,0 @@
-"""DTO backends do the heavy lifting of decoding and validating raw bytes into domain models, and
-back again, to bytes.
-"""
-
-from __future__ import annotations
-
-from dataclasses import replace
-from typing import (
- TYPE_CHECKING,
- AbstractSet,
- Any,
- ClassVar,
- Collection,
- Final,
- Mapping,
- Protocol,
- Union,
- cast,
-)
-
-import msgspec
-from msgspec import UNSET, Struct, UnsetType, convert, defstruct, field
-from typing_extensions import Annotated
-
-from litestar.dto._types import (
- CollectionType,
- CompositeType,
- MappingType,
- NestedFieldInfo,
- SimpleType,
- TransferDTOFieldDefinition,
- TransferType,
- TupleType,
- UnionType,
-)
-from litestar.dto.data_structures import DTOData, DTOFieldDefinition
-from litestar.dto.field import Mark
-from litestar.enums import RequestEncodingType
-from litestar.params import KwargDefinition
-from litestar.serialization import decode_json, decode_msgpack
-from litestar.types import Empty
-from litestar.typing import FieldDefinition
-from litestar.utils import unique_name_for_scope
-
-if TYPE_CHECKING:
- from litestar.connection import ASGIConnection
- from litestar.dto import AbstractDTO, RenameStrategy
- from litestar.types.serialization import LitestarEncodableType
-
-__all__ = ("DTOBackend",)
-
-
-class CompositeTypeHandler(Protocol):
- def __call__(
- self,
- field_definition: FieldDefinition,
- exclude: AbstractSet[str],
- include: AbstractSet[str],
- rename_fields: dict[str, str],
- unique_name: str,
- nested_depth: int,
- ) -> CompositeType: ...
-
-
-class DTOBackend:
- __slots__ = (
- "annotation",
- "dto_data_type",
- "dto_factory",
- "field_definition",
- "handler_id",
- "is_data_field",
- "model_type",
- "parsed_field_definitions",
- "reverse_name_map",
- "transfer_model_type",
- "wrapper_attribute_name",
- )
-
- _seen_model_names: ClassVar[set[str]] = set()
-
- def __init__(
- self,
- dto_factory: type[AbstractDTO],
- field_definition: FieldDefinition,
- handler_id: str,
- is_data_field: bool,
- model_type: type[Any],
- wrapper_attribute_name: str | None,
- ) -> None:
- """Create dto backend instance.
-
- Args:
- dto_factory: The DTO factory class calling this backend.
- field_definition: Parsed type.
- handler_id: The name of the handler that this backend is for.
- is_data_field: Whether the field is a subclass of DTOData.
- model_type: Model type.
- wrapper_attribute_name: If the data that DTO should operate upon is wrapped in a generic datastructure, this is the name of the attribute that the data is stored in.
- """
- self.dto_factory: Final[type[AbstractDTO]] = dto_factory
- self.field_definition: Final[FieldDefinition] = field_definition
- self.is_data_field: Final[bool] = is_data_field
- self.handler_id: Final[str] = handler_id
- self.model_type: Final[type[Any]] = model_type
- self.wrapper_attribute_name: Final[str | None] = wrapper_attribute_name
-
- self.parsed_field_definitions = self.parse_model(
- model_type=model_type,
- exclude=self.dto_factory.config.exclude,
- include=self.dto_factory.config.include,
- rename_fields=self.dto_factory.config.rename_fields,
- )
- self.transfer_model_type = self.create_transfer_model_type(
- model_name=model_type.__name__, field_definitions=self.parsed_field_definitions
- )
- self.dto_data_type: type[DTOData] | None = None
-
- if field_definition.is_subclass_of(DTOData):
- self.dto_data_type = field_definition.annotation
- field_definition = self.field_definition.inner_types[0]
-
- self.annotation = build_annotation_for_backend(model_type, field_definition, self.transfer_model_type)
-
- def parse_model(
- self,
- model_type: Any,
- exclude: AbstractSet[str],
- include: AbstractSet[str],
- rename_fields: dict[str, str],
- nested_depth: int = 0,
- ) -> tuple[TransferDTOFieldDefinition, ...]:
- """Reduce :attr:`model_type` to a tuple :class:`TransferDTOFieldDefinition` instances.
-
- Returns:
- Fields for data transfer.
- """
- defined_fields = []
- generic_field_definitons = list(FieldDefinition.from_annotation(model_type).generic_types or ())
- for field_definition in self.dto_factory.generate_field_definitions(model_type):
- if field_definition.is_type_var:
- base_arg_field = generic_field_definitons.pop()
- field_definition = replace(
- field_definition, annotation=base_arg_field.annotation, raw=base_arg_field.raw
- )
-
- if _should_mark_private(field_definition, self.dto_factory.config.underscore_fields_private):
- field_definition.dto_field.mark = Mark.PRIVATE
-
- try:
- transfer_type = self._create_transfer_type(
- field_definition=field_definition,
- exclude=exclude,
- include=include,
- rename_fields=rename_fields,
- field_name=field_definition.name,
- unique_name=field_definition.model_name,
- nested_depth=nested_depth,
- )
- except RecursionError:
- continue
-
- transfer_field_definition = TransferDTOFieldDefinition.from_dto_field_definition(
- field_definition=field_definition,
- serialization_name=rename_fields.get(field_definition.name),
- transfer_type=transfer_type,
- is_partial=self.dto_factory.config.partial,
- is_excluded=_should_exclude_field(
- field_definition=field_definition,
- exclude=exclude,
- include=include,
- is_data_field=self.is_data_field,
- ),
- )
- defined_fields.append(transfer_field_definition)
- return tuple(defined_fields)
-
- def _create_transfer_model_name(self, model_name: str) -> str:
- long_name_prefix = self.handler_id.split("::")[0]
- short_name_prefix = _camelize(long_name_prefix.split(".")[-1], True)
-
- name_suffix = "RequestBody" if self.is_data_field else "ResponseBody"
-
- if (short_name := f"{short_name_prefix}{model_name}{name_suffix}") not in self._seen_model_names:
- name = short_name
- elif (long_name := f"{long_name_prefix}{model_name}{name_suffix}") not in self._seen_model_names:
- name = long_name
- else:
- name = unique_name_for_scope(long_name, self._seen_model_names)
-
- self._seen_model_names.add(name)
-
- return name
-
- def create_transfer_model_type(
- self,
- model_name: str,
- field_definitions: tuple[TransferDTOFieldDefinition, ...],
- ) -> type[Struct]:
- """Create a model for data transfer.
-
- Args:
- model_name: name for the type that should be unique across all transfer types.
- field_definitions: field definitions for the container type.
-
- Returns:
- A ``BackendT`` class.
- """
- struct_name = self._create_transfer_model_name(model_name)
-
- struct = _create_struct_for_field_definitions(
- struct_name, field_definitions, self.dto_factory.config.rename_strategy
- )
- setattr(struct, "__schema_name__", struct_name)
- return struct
-
- def parse_raw(self, raw: bytes, asgi_connection: ASGIConnection) -> Struct | Collection[Struct]:
- """Parse raw bytes into transfer model type.
-
- Args:
- raw: bytes
- asgi_connection: The current ASGI Connection
-
- Returns:
- The raw bytes parsed into transfer model type.
- """
- request_encoding = RequestEncodingType.JSON
-
- if (content_type := getattr(asgi_connection, "content_type", None)) and (media_type := content_type[0]):
- request_encoding = media_type
-
- type_decoders = asgi_connection.route_handler.resolve_type_decoders()
-
- if request_encoding == RequestEncodingType.MESSAGEPACK:
- result = decode_msgpack(value=raw, target_type=self.annotation, type_decoders=type_decoders)
- else:
- result = decode_json(value=raw, target_type=self.annotation, type_decoders=type_decoders)
-
- return cast("Struct | Collection[Struct]", result)
-
- def parse_builtins(self, builtins: Any, asgi_connection: ASGIConnection) -> Any:
- """Parse builtin types into transfer model type.
-
- Args:
- builtins: Builtin type.
- asgi_connection: The current ASGI Connection
-
- Returns:
- The builtin type parsed into transfer model type.
- """
- return convert(
- obj=builtins,
- type=self.annotation,
- dec_hook=asgi_connection.route_handler.default_deserializer,
- strict=False,
- str_keys=True,
- )
-
- def populate_data_from_builtins(self, builtins: Any, asgi_connection: ASGIConnection) -> Any:
- """Populate model instance from builtin types.
-
- Args:
- builtins: Builtin type.
- asgi_connection: The current ASGI Connection
-
- Returns:
- Instance or collection of ``model_type`` instances.
- """
- if self.dto_data_type:
- return self.dto_data_type(
- backend=self,
- data_as_builtins=_transfer_data(
- destination_type=dict,
- source_data=self.parse_builtins(builtins, asgi_connection),
- field_definitions=self.parsed_field_definitions,
- field_definition=self.field_definition,
- is_data_field=self.is_data_field,
- ),
- )
- return self.transfer_data_from_builtins(self.parse_builtins(builtins, asgi_connection))
-
- def transfer_data_from_builtins(self, builtins: Any) -> Any:
- """Populate model instance from builtin types.
-
- Args:
- builtins: Builtin type.
-
- Returns:
- Instance or collection of ``model_type`` instances.
- """
- return _transfer_data(
- destination_type=self.model_type,
- source_data=builtins,
- field_definitions=self.parsed_field_definitions,
- field_definition=self.field_definition,
- is_data_field=self.is_data_field,
- )
-
- def populate_data_from_raw(self, raw: bytes, asgi_connection: ASGIConnection) -> Any:
- """Parse raw bytes into instance of `model_type`.
-
- Args:
- raw: bytes
- asgi_connection: The current ASGI Connection
-
- Returns:
- Instance or collection of ``model_type`` instances.
- """
- if self.dto_data_type:
- return self.dto_data_type(
- backend=self,
- data_as_builtins=_transfer_data(
- destination_type=dict,
- source_data=self.parse_raw(raw, asgi_connection),
- field_definitions=self.parsed_field_definitions,
- field_definition=self.field_definition,
- is_data_field=self.is_data_field,
- ),
- )
- return _transfer_data(
- destination_type=self.model_type,
- source_data=self.parse_raw(raw, asgi_connection),
- field_definitions=self.parsed_field_definitions,
- field_definition=self.field_definition,
- is_data_field=self.is_data_field,
- )
-
- def encode_data(self, data: Any) -> LitestarEncodableType:
- """Encode data into a ``LitestarEncodableType``.
-
- Args:
- data: Data to encode.
-
- Returns:
- Encoded data.
- """
- if self.wrapper_attribute_name:
- wrapped_transfer = _transfer_data(
- destination_type=self.transfer_model_type,
- source_data=getattr(data, self.wrapper_attribute_name),
- field_definitions=self.parsed_field_definitions,
- field_definition=self.field_definition,
- is_data_field=self.is_data_field,
- )
- setattr(
- data,
- self.wrapper_attribute_name,
- wrapped_transfer,
- )
- return cast("LitestarEncodableType", data)
-
- return cast(
- "LitestarEncodableType",
- _transfer_data(
- destination_type=self.transfer_model_type,
- source_data=data,
- field_definitions=self.parsed_field_definitions,
- field_definition=self.field_definition,
- is_data_field=self.is_data_field,
- ),
- )
-
- def _get_handler_for_field_definition(self, field_definition: FieldDefinition) -> CompositeTypeHandler | None:
- if field_definition.is_union:
- return self._create_union_type
-
- if field_definition.is_tuple:
- if len(field_definition.inner_types) == 2 and field_definition.inner_types[1].annotation is Ellipsis:
- return self._create_collection_type
- return self._create_tuple_type
-
- if field_definition.is_mapping:
- return self._create_mapping_type
-
- if field_definition.is_non_string_collection:
- return self._create_collection_type
- return None
-
- def _create_transfer_type(
- self,
- field_definition: FieldDefinition,
- exclude: AbstractSet[str],
- include: AbstractSet[str],
- rename_fields: dict[str, str],
- field_name: str,
- unique_name: str,
- nested_depth: int,
- ) -> CompositeType | SimpleType:
- exclude = _filter_nested_field(exclude, field_name)
- include = _filter_nested_field(include, field_name)
- rename_fields = _filter_nested_field_mapping(rename_fields, field_name)
-
- if composite_type_handler := self._get_handler_for_field_definition(field_definition):
- return composite_type_handler(
- field_definition=field_definition,
- exclude=exclude,
- include=include,
- rename_fields=rename_fields,
- unique_name=unique_name,
- nested_depth=nested_depth,
- )
-
- transfer_model: NestedFieldInfo | None = None
-
- if self.dto_factory.detect_nested_field(field_definition):
- if nested_depth == self.dto_factory.config.max_nested_depth:
- raise RecursionError
-
- nested_field_definitions = self.parse_model(
- model_type=field_definition.annotation,
- exclude=exclude,
- include=include,
- rename_fields=rename_fields,
- nested_depth=nested_depth + 1,
- )
-
- transfer_model = NestedFieldInfo(
- model=self.create_transfer_model_type(unique_name, nested_field_definitions),
- field_definitions=nested_field_definitions,
- )
-
- return SimpleType(field_definition, nested_field_info=transfer_model)
-
- def _create_collection_type(
- self,
- field_definition: FieldDefinition,
- exclude: AbstractSet[str],
- include: AbstractSet[str],
- rename_fields: dict[str, str],
- unique_name: str,
- nested_depth: int,
- ) -> CollectionType:
- inner_types = field_definition.inner_types
- inner_type = self._create_transfer_type(
- field_definition=inner_types[0] if inner_types else FieldDefinition.from_annotation(Any),
- exclude=exclude,
- include=include,
- field_name="0",
- unique_name=f"{unique_name}_0",
- nested_depth=nested_depth,
- rename_fields=rename_fields,
- )
- return CollectionType(
- field_definition=field_definition, inner_type=inner_type, has_nested=inner_type.has_nested
- )
-
- def _create_mapping_type(
- self,
- field_definition: FieldDefinition,
- exclude: AbstractSet[str],
- include: AbstractSet[str],
- rename_fields: dict[str, str],
- unique_name: str,
- nested_depth: int,
- ) -> MappingType:
- inner_types = field_definition.inner_types
- key_type = self._create_transfer_type(
- field_definition=inner_types[0] if inner_types else FieldDefinition.from_annotation(Any),
- exclude=exclude,
- include=include,
- field_name="0",
- unique_name=f"{unique_name}_0",
- nested_depth=nested_depth,
- rename_fields=rename_fields,
- )
- value_type = self._create_transfer_type(
- field_definition=inner_types[1] if inner_types else FieldDefinition.from_annotation(Any),
- exclude=exclude,
- include=include,
- field_name="1",
- unique_name=f"{unique_name}_1",
- nested_depth=nested_depth,
- rename_fields=rename_fields,
- )
- return MappingType(
- field_definition=field_definition,
- key_type=key_type,
- value_type=value_type,
- has_nested=key_type.has_nested or value_type.has_nested,
- )
-
- def _create_tuple_type(
- self,
- field_definition: FieldDefinition,
- exclude: AbstractSet[str],
- include: AbstractSet[str],
- rename_fields: dict[str, str],
- unique_name: str,
- nested_depth: int,
- ) -> TupleType:
- inner_types = tuple(
- self._create_transfer_type(
- field_definition=inner_type,
- exclude=exclude,
- include=include,
- field_name=str(i),
- unique_name=f"{unique_name}_{i}",
- nested_depth=nested_depth,
- rename_fields=rename_fields,
- )
- for i, inner_type in enumerate(field_definition.inner_types)
- )
- return TupleType(
- field_definition=field_definition,
- inner_types=inner_types,
- has_nested=any(t.has_nested for t in inner_types),
- )
-
- def _create_union_type(
- self,
- field_definition: FieldDefinition,
- exclude: AbstractSet[str],
- include: AbstractSet[str],
- rename_fields: dict[str, str],
- unique_name: str,
- nested_depth: int,
- ) -> UnionType:
- inner_types = tuple(
- self._create_transfer_type(
- field_definition=inner_type,
- exclude=exclude,
- include=include,
- field_name=str(i),
- unique_name=f"{unique_name}_{i}",
- nested_depth=nested_depth,
- rename_fields=rename_fields,
- )
- for i, inner_type in enumerate(field_definition.inner_types)
- )
- return UnionType(
- field_definition=field_definition,
- inner_types=inner_types,
- has_nested=any(t.has_nested for t in inner_types),
- )
-
-
-def _camelize(value: str, capitalize_first_letter: bool) -> str:
- return "".join(
- word if index == 0 and not capitalize_first_letter else word.capitalize()
- for index, word in enumerate(value.split("_"))
- )
-
-
-def _filter_nested_field(field_name_set: AbstractSet[str], field_name: str) -> AbstractSet[str]:
- """Filter a nested field name."""
- return {split[1] for s in field_name_set if (split := s.split(".", 1))[0] == field_name and len(split) > 1}
-
-
-def _filter_nested_field_mapping(field_name_mapping: Mapping[str, str], field_name: str) -> dict[str, str]:
- """Filter a nested field name."""
- return {
- split[1]: v
- for s, v in field_name_mapping.items()
- if (split := s.split(".", 1))[0] == field_name and len(split) > 1
- }
-
-
-def _transfer_data(
- destination_type: type[Any],
- source_data: Any | Collection[Any],
- field_definitions: tuple[TransferDTOFieldDefinition, ...],
- field_definition: FieldDefinition,
- is_data_field: bool,
-) -> Any:
- """Create instance or iterable of instances of ``destination_type``.
-
- Args:
- destination_type: the model type received by the DTO on type narrowing.
- source_data: data that has been parsed and validated via the backend.
- field_definitions: model field definitions.
- field_definition: the parsed type that represents the handler annotation for which the DTO is being applied.
- is_data_field: whether the DTO is being applied to a ``data`` field.
-
- Returns:
- Data parsed into ``destination_type``.
- """
- if field_definition.is_non_string_collection:
- if not field_definition.is_mapping:
- return field_definition.instantiable_origin(
- _transfer_data(
- destination_type=destination_type,
- source_data=item,
- field_definitions=field_definitions,
- field_definition=field_definition.inner_types[0],
- is_data_field=is_data_field,
- )
- for item in source_data
- )
- return field_definition.instantiable_origin(
- (
- key,
- _transfer_data(
- destination_type=destination_type,
- source_data=value,
- field_definitions=field_definitions,
- field_definition=field_definition.inner_types[1],
- is_data_field=is_data_field,
- ),
- )
- for key, value in source_data.items() # type: ignore[union-attr]
- )
-
- return _transfer_instance_data(
- destination_type=destination_type,
- source_instance=source_data,
- field_definitions=field_definitions,
- is_data_field=is_data_field,
- )
-
-
-def _transfer_instance_data(
- destination_type: type[Any],
- source_instance: Any,
- field_definitions: tuple[TransferDTOFieldDefinition, ...],
- is_data_field: bool,
-) -> Any:
- """Create instance of ``destination_type`` with data from ``source_instance``.
-
- Args:
- destination_type: the model type received by the DTO on type narrowing.
- source_instance: primitive data that has been parsed and validated via the backend.
- field_definitions: model field definitions.
- is_data_field: whether the given field is a 'data' kwarg field.
-
- Returns:
- Data parsed into ``model_type``.
- """
- unstructured_data = {}
-
- for field_definition in field_definitions:
- if not is_data_field:
- if field_definition.is_excluded:
- continue
- elif not (
- field_definition.name in source_instance
- if isinstance(source_instance, Mapping)
- else hasattr(source_instance, field_definition.name)
- ):
- continue
-
- transfer_type = field_definition.transfer_type
- source_value = (
- source_instance[field_definition.name]
- if isinstance(source_instance, Mapping)
- else getattr(source_instance, field_definition.name)
- )
-
- if field_definition.is_partial and is_data_field and source_value is UNSET:
- continue
-
- unstructured_data[field_definition.name] = _transfer_type_data(
- source_value=source_value,
- transfer_type=transfer_type,
- nested_as_dict=destination_type is dict,
- is_data_field=is_data_field,
- )
-
- return destination_type(**unstructured_data)
-
-
-def _transfer_type_data(
- source_value: Any,
- transfer_type: TransferType,
- nested_as_dict: bool,
- is_data_field: bool,
-) -> Any:
- if isinstance(transfer_type, SimpleType) and transfer_type.nested_field_info:
- if nested_as_dict:
- destination_type: Any = dict
- elif is_data_field:
- destination_type = transfer_type.field_definition.annotation
- else:
- destination_type = transfer_type.nested_field_info.model
-
- return _transfer_instance_data(
- destination_type=destination_type,
- source_instance=source_value,
- field_definitions=transfer_type.nested_field_info.field_definitions,
- is_data_field=is_data_field,
- )
-
- if isinstance(transfer_type, UnionType) and transfer_type.has_nested:
- return _transfer_nested_union_type_data(
- transfer_type=transfer_type,
- source_value=source_value,
- is_data_field=is_data_field,
- )
-
- if isinstance(transfer_type, CollectionType):
- if transfer_type.has_nested:
- return transfer_type.field_definition.instantiable_origin(
- _transfer_type_data(
- source_value=item,
- transfer_type=transfer_type.inner_type,
- nested_as_dict=False,
- is_data_field=is_data_field,
- )
- for item in source_value
- )
-
- return transfer_type.field_definition.instantiable_origin(source_value)
- return source_value
-
-
-def _transfer_nested_union_type_data(
- transfer_type: UnionType,
- source_value: Any,
- is_data_field: bool,
-) -> Any:
- for inner_type in transfer_type.inner_types:
- if isinstance(inner_type, CompositeType):
- raise RuntimeError("Composite inner types not (yet) supported for nested unions.")
-
- if inner_type.nested_field_info and isinstance(
- source_value,
- inner_type.nested_field_info.model if is_data_field else inner_type.field_definition.annotation,
- ):
- return _transfer_instance_data(
- destination_type=inner_type.field_definition.annotation
- if is_data_field
- else inner_type.nested_field_info.model,
- source_instance=source_value,
- field_definitions=inner_type.nested_field_info.field_definitions,
- is_data_field=is_data_field,
- )
- return source_value
-
-
-def _create_msgspec_field(field_definition: TransferDTOFieldDefinition) -> Any:
- kwargs: dict[str, Any] = {}
- if field_definition.is_partial:
- kwargs["default"] = UNSET
-
- elif field_definition.default is not Empty:
- kwargs["default"] = field_definition.default
-
- elif field_definition.default_factory is not None:
- kwargs["default_factory"] = field_definition.default_factory
-
- if field_definition.serialization_name is not None:
- kwargs["name"] = field_definition.serialization_name
-
- return field(**kwargs)
-
-
-def _create_struct_field_meta_for_field_definition(field_definition: TransferDTOFieldDefinition) -> msgspec.Meta | None:
- if (kwarg_definition := field_definition.kwarg_definition) is None or not isinstance(
- kwarg_definition, KwargDefinition
- ):
- return None
-
- return msgspec.Meta(
- description=kwarg_definition.description,
- examples=[e.value for e in kwarg_definition.examples or []],
- ge=kwarg_definition.ge,
- gt=kwarg_definition.gt,
- le=kwarg_definition.le,
- lt=kwarg_definition.lt,
- max_length=kwarg_definition.max_length if not field_definition.is_partial else None,
- min_length=kwarg_definition.min_length if not field_definition.is_partial else None,
- multiple_of=kwarg_definition.multiple_of,
- pattern=kwarg_definition.pattern,
- title=kwarg_definition.title,
- )
-
-
-def _create_struct_for_field_definitions(
- model_name: str,
- field_definitions: tuple[TransferDTOFieldDefinition, ...],
- rename_strategy: RenameStrategy | dict[str, str] | None,
-) -> type[Struct]:
- struct_fields: list[tuple[str, type] | tuple[str, type, type]] = []
-
- for field_definition in field_definitions:
- if field_definition.is_excluded:
- continue
-
- field_type = _create_transfer_model_type_annotation(field_definition.transfer_type)
- if field_definition.is_partial:
- field_type = Union[field_type, UnsetType]
-
- if (field_meta := _create_struct_field_meta_for_field_definition(field_definition)) is not None:
- field_type = Annotated[field_type, field_meta]
-
- struct_fields.append(
- (
- field_definition.name,
- field_type,
- _create_msgspec_field(field_definition),
- )
- )
- return defstruct(model_name, struct_fields, frozen=True, kw_only=True, rename=rename_strategy)
-
-
-def build_annotation_for_backend(
- model_type: type[Any], field_definition: FieldDefinition, transfer_model: type[Struct]
-) -> Any:
- """A helper to re-build a generic outer type with new inner type.
-
- Args:
- model_type: The original model type.
- field_definition: The parsed type that represents the handler annotation for which the DTO is being applied.
- transfer_model: The transfer model generated to represent the model type.
-
- Returns:
- Annotation with new inner type if applicable.
- """
- if not field_definition.inner_types:
- if field_definition.is_subclass_of(model_type):
- return transfer_model
- return field_definition.annotation
-
- inner_types = tuple(
- build_annotation_for_backend(model_type, inner_type, transfer_model)
- for inner_type in field_definition.inner_types
- )
-
- return field_definition.safe_generic_origin[inner_types]
-
-
-def _should_mark_private(field_definition: DTOFieldDefinition, underscore_fields_private: bool) -> bool:
- """Returns ``True`` where a field should be marked as private.
-
- Fields should be marked as private when:
- - the ``underscore_fields_private`` flag is set.
- - the field is not already marked.
- - the field name is prefixed with an underscore
-
- Args:
- field_definition: defined DTO field
- underscore_fields_private: whether fields prefixed with an underscore should be marked as private.
- """
- return bool(
- underscore_fields_private and field_definition.dto_field.mark is None and field_definition.name.startswith("_")
- )
-
-
-def _should_exclude_field(
- field_definition: DTOFieldDefinition, exclude: AbstractSet[str], include: AbstractSet[str], is_data_field: bool
-) -> bool:
- """Returns ``True`` where a field should be excluded from data transfer.
-
- Args:
- field_definition: defined DTO field
- exclude: names of fields to exclude
- include: names of fields to exclude
- is_data_field: whether the field is a data field
-
- Returns:
- ``True`` if the field should not be included in any data transfer.
- """
- field_name = field_definition.name
- if field_name in exclude:
- return True
- if include and field_name not in include and not (any(f.startswith(f"{field_name}.") for f in include)):
- return True
- if field_definition.dto_field.mark is Mark.PRIVATE:
- return True
- if is_data_field and field_definition.dto_field.mark is Mark.READ_ONLY:
- return True
- return not is_data_field and field_definition.dto_field.mark is Mark.WRITE_ONLY
-
-
-def _create_transfer_model_type_annotation(transfer_type: TransferType) -> Any:
- """Create a type annotation for a transfer model.
-
- Uses the parsed type that originates from the data model and the transfer model generated to represent a nested
- type to reconstruct the type annotation for the transfer model.
- """
- if isinstance(transfer_type, SimpleType):
- if transfer_type.nested_field_info:
- return transfer_type.nested_field_info.model
- return transfer_type.field_definition.annotation
-
- if isinstance(transfer_type, CollectionType):
- return _create_transfer_model_collection_type(transfer_type)
-
- if isinstance(transfer_type, MappingType):
- return _create_transfer_model_mapping_type(transfer_type)
-
- if isinstance(transfer_type, TupleType):
- return _create_transfer_model_tuple_type(transfer_type)
-
- if isinstance(transfer_type, UnionType):
- return _create_transfer_model_union_type(transfer_type)
-
- raise RuntimeError(f"Unexpected transfer type: {type(transfer_type)}")
-
-
-def _create_transfer_model_collection_type(transfer_type: CollectionType) -> Any:
- generic_collection_type = transfer_type.field_definition.safe_generic_origin
- inner_type = _create_transfer_model_type_annotation(transfer_type.inner_type)
- if transfer_type.field_definition.origin is tuple:
- return generic_collection_type[inner_type, ...]
- return generic_collection_type[inner_type]
-
-
-def _create_transfer_model_tuple_type(transfer_type: TupleType) -> Any:
- inner_types = tuple(_create_transfer_model_type_annotation(t) for t in transfer_type.inner_types)
- return transfer_type.field_definition.safe_generic_origin[inner_types]
-
-
-def _create_transfer_model_union_type(transfer_type: UnionType) -> Any:
- inner_types = tuple(_create_transfer_model_type_annotation(t) for t in transfer_type.inner_types)
- return transfer_type.field_definition.safe_generic_origin[inner_types]
-
-
-def _create_transfer_model_mapping_type(transfer_type: MappingType) -> Any:
- key_type = _create_transfer_model_type_annotation(transfer_type.key_type)
- value_type = _create_transfer_model_type_annotation(transfer_type.value_type)
- return transfer_type.field_definition.safe_generic_origin[key_type, value_type]
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/_codegen_backend.py b/venv/lib/python3.11/site-packages/litestar/dto/_codegen_backend.py
deleted file mode 100644
index deff908..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/_codegen_backend.py
+++ /dev/null
@@ -1,541 +0,0 @@
-"""DTO backends do the heavy lifting of decoding and validating raw bytes into domain models, and
-back again, to bytes.
-"""
-
-from __future__ import annotations
-
-import re
-import textwrap
-from contextlib import contextmanager, nullcontext
-from typing import (
- TYPE_CHECKING,
- Any,
- Callable,
- ContextManager,
- Generator,
- Mapping,
- Protocol,
- cast,
-)
-
-from msgspec import UNSET
-
-from litestar.dto._backend import DTOBackend
-from litestar.dto._types import (
- CollectionType,
- CompositeType,
- SimpleType,
- TransferDTOFieldDefinition,
- TransferType,
- UnionType,
-)
-from litestar.utils.helpers import unique_name_for_scope
-
-if TYPE_CHECKING:
- from litestar.connection import ASGIConnection
- from litestar.dto import AbstractDTO
- from litestar.types.serialization import LitestarEncodableType
- from litestar.typing import FieldDefinition
-
-__all__ = ("DTOCodegenBackend",)
-
-
-class DTOCodegenBackend(DTOBackend):
- __slots__ = (
- "_transfer_to_dict",
- "_transfer_to_model_type",
- "_transfer_data_from_builtins",
- "_transfer_data_from_builtins_with_overrides",
- "_encode_data",
- )
-
- def __init__(
- self,
- dto_factory: type[AbstractDTO],
- field_definition: FieldDefinition,
- handler_id: str,
- is_data_field: bool,
- model_type: type[Any],
- wrapper_attribute_name: str | None,
- ) -> None:
- """Create dto backend instance.
-
- Args:
- dto_factory: The DTO factory class calling this backend.
- field_definition: Parsed type.
- handler_id: The name of the handler that this backend is for.
- is_data_field: Whether the field is a subclass of DTOData.
- model_type: Model type.
- wrapper_attribute_name: If the data that DTO should operate upon is wrapped in a generic datastructure,
- this is the name of the attribute that the data is stored in.
- """
- super().__init__(
- dto_factory=dto_factory,
- field_definition=field_definition,
- handler_id=handler_id,
- is_data_field=is_data_field,
- model_type=model_type,
- wrapper_attribute_name=wrapper_attribute_name,
- )
- self._transfer_to_dict = self._create_transfer_data_fn(
- destination_type=dict,
- field_definition=self.field_definition,
- )
- self._transfer_to_model_type = self._create_transfer_data_fn(
- destination_type=self.model_type,
- field_definition=self.field_definition,
- )
- self._transfer_data_from_builtins = self._create_transfer_data_fn(
- destination_type=self.model_type,
- field_definition=self.field_definition,
- )
- self._transfer_data_from_builtins_with_overrides = self._create_transfer_data_fn(
- destination_type=self.model_type,
- field_definition=self.field_definition,
- )
- self._encode_data = self._create_transfer_data_fn(
- destination_type=self.transfer_model_type,
- field_definition=self.field_definition,
- )
-
- def populate_data_from_builtins(self, builtins: Any, asgi_connection: ASGIConnection) -> Any:
- """Populate model instance from builtin types.
-
- Args:
- builtins: Builtin type.
- asgi_connection: The current ASGI Connection
-
- Returns:
- Instance or collection of ``model_type`` instances.
- """
- if self.dto_data_type:
- return self.dto_data_type(
- backend=self,
- data_as_builtins=self._transfer_to_dict(self.parse_builtins(builtins, asgi_connection)),
- )
- return self.transfer_data_from_builtins(self.parse_builtins(builtins, asgi_connection))
-
- def transfer_data_from_builtins(self, builtins: Any) -> Any:
- """Populate model instance from builtin types.
-
- Args:
- builtins: Builtin type.
-
- Returns:
- Instance or collection of ``model_type`` instances.
- """
- return self._transfer_data_from_builtins(builtins)
-
- def populate_data_from_raw(self, raw: bytes, asgi_connection: ASGIConnection) -> Any:
- """Parse raw bytes into instance of `model_type`.
-
- Args:
- raw: bytes
- asgi_connection: The current ASGI Connection
-
- Returns:
- Instance or collection of ``model_type`` instances.
- """
- if self.dto_data_type:
- return self.dto_data_type(
- backend=self,
- data_as_builtins=self._transfer_to_dict(self.parse_raw(raw, asgi_connection)),
- )
- return self._transfer_to_model_type(self.parse_raw(raw, asgi_connection))
-
- def encode_data(self, data: Any) -> LitestarEncodableType:
- """Encode data into a ``LitestarEncodableType``.
-
- Args:
- data: Data to encode.
-
- Returns:
- Encoded data.
- """
- if self.wrapper_attribute_name:
- wrapped_transfer = self._encode_data(getattr(data, self.wrapper_attribute_name))
- setattr(data, self.wrapper_attribute_name, wrapped_transfer)
- return cast("LitestarEncodableType", data)
-
- return cast("LitestarEncodableType", self._encode_data(data))
-
- def _create_transfer_data_fn(
- self,
- destination_type: type[Any],
- field_definition: FieldDefinition,
- ) -> Any:
- """Create instance or iterable of instances of ``destination_type``.
-
- Args:
- destination_type: the model type received by the DTO on type narrowing.
- field_definition: the parsed type that represents the handler annotation for which the DTO is being applied.
-
- Returns:
- Data parsed into ``destination_type``.
- """
-
- return TransferFunctionFactory.create_transfer_data(
- destination_type=destination_type,
- field_definitions=self.parsed_field_definitions,
- is_data_field=self.is_data_field,
- field_definition=field_definition,
- )
-
-
-class FieldAccessManager(Protocol):
- def __call__(self, source_name: str, field_name: str, expect_optional: bool) -> ContextManager[str]: ...
-
-
-class TransferFunctionFactory:
- def __init__(self, is_data_field: bool, nested_as_dict: bool) -> None:
- self.is_data_field = is_data_field
- self._fn_locals: dict[str, Any] = {
- "Mapping": Mapping,
- "UNSET": UNSET,
- }
- self._indentation = 1
- self._body = ""
- self.names: set[str] = set()
- self.nested_as_dict = nested_as_dict
- self._re_index_access = re.compile(r"\[['\"](\w+?)['\"]]")
-
- def _add_to_fn_globals(self, name: str, value: Any) -> str:
- unique_name = unique_name_for_scope(name, self._fn_locals)
- self._fn_locals[unique_name] = value
- return unique_name
-
- def _create_local_name(self, name: str) -> str:
- unique_name = unique_name_for_scope(name, self.names)
- self.names.add(unique_name)
- return unique_name
-
- def _make_function(
- self, source_value_name: str, return_value_name: str, fn_name: str = "func"
- ) -> Callable[[Any], Any]:
- """Wrap the current body contents in a function definition and turn it into a callable object"""
- source = f"def {fn_name}({source_value_name}):\n{self._body} return {return_value_name}"
- ctx: dict[str, Any] = {**self._fn_locals}
- exec(source, ctx) # noqa: S102
- return ctx["func"] # type: ignore[no-any-return]
-
- def _add_stmt(self, stmt: str) -> None:
- self._body += textwrap.indent(stmt + "\n", " " * self._indentation)
-
- @contextmanager
- def _start_block(self, expr: str | None = None) -> Generator[None, None, None]:
- """Start an indented block. If `expr` is given, use it as the "opening line"
- of the block.
- """
- if expr is not None:
- self._add_stmt(expr)
- self._indentation += 1
- yield
- self._indentation -= 1
-
- @contextmanager
- def _try_except_pass(self, exception: str) -> Generator[None, None, None]:
- """Enter a `try / except / pass` block. Content written while inside this context
- will go into the `try` block.
- """
- with self._start_block("try:"):
- yield
- with self._start_block(expr=f"except {exception}:"):
- self._add_stmt("pass")
-
- @contextmanager
- def _access_mapping_item(
- self, source_name: str, field_name: str, expect_optional: bool
- ) -> Generator[str, None, None]:
- """Enter a context within which an item of a mapping can be accessed safely,
- i.e. only if it is contained within that mapping.
- Yields an expression that accesses the mapping item. Content written while
- within this context can use this expression to access the desired value.
- """
- value_expr = f"{source_name}['{field_name}']"
-
- # if we expect an optional item, it's faster to check if it exists beforehand
- if expect_optional:
- with self._start_block(f"if '{field_name}' in {source_name}:"):
- yield value_expr
- # the happy path of a try/except will be faster than that, so we use that if
- # we expect a value
- else:
- with self._try_except_pass("KeyError"):
- yield value_expr
-
- @contextmanager
- def _access_attribute(self, source_name: str, field_name: str, expect_optional: bool) -> Generator[str, None, None]:
- """Enter a context within which an attribute of an object can be accessed
- safely, i.e. only if the object actually has the attribute.
- Yields an expression that retrieves the object attribute. Content written while
- within this context can use this expression to access the desired value.
- """
-
- value_expr = f"{source_name}.{field_name}"
-
- # if we expect an optional attribute it's faster to check with hasattr
- if expect_optional:
- with self._start_block(f"if hasattr({source_name}, '{field_name}'):"):
- yield value_expr
- # the happy path of a try/except will be faster than that, so we use that if
- # we expect a value
- else:
- with self._try_except_pass("AttributeError"):
- yield value_expr
-
- @classmethod
- def create_transfer_instance_data(
- cls,
- field_definitions: tuple[TransferDTOFieldDefinition, ...],
- destination_type: type[Any],
- is_data_field: bool,
- ) -> Callable[[Any], Any]:
- factory = cls(is_data_field=is_data_field, nested_as_dict=destination_type is dict)
- tmp_return_type_name = factory._create_local_name("tmp_return_type")
- source_instance_name = factory._create_local_name("source_instance")
- destination_type_name = factory._add_to_fn_globals("destination_type", destination_type)
- factory._create_transfer_instance_data(
- tmp_return_type_name=tmp_return_type_name,
- source_instance_name=source_instance_name,
- destination_type_name=destination_type_name,
- field_definitions=field_definitions,
- destination_type_is_dict=destination_type is dict,
- )
- return factory._make_function(source_value_name=source_instance_name, return_value_name=tmp_return_type_name)
-
- @classmethod
- def create_transfer_type_data(
- cls,
- transfer_type: TransferType,
- is_data_field: bool,
- ) -> Callable[[Any], Any]:
- factory = cls(is_data_field=is_data_field, nested_as_dict=False)
- tmp_return_type_name = factory._create_local_name("tmp_return_type")
- source_value_name = factory._create_local_name("source_value")
- factory._create_transfer_type_data_body(
- transfer_type=transfer_type,
- nested_as_dict=False,
- assignment_target=tmp_return_type_name,
- source_value_name=source_value_name,
- )
- return factory._make_function(source_value_name=source_value_name, return_value_name=tmp_return_type_name)
-
- @classmethod
- def create_transfer_data(
- cls,
- destination_type: type[Any],
- field_definitions: tuple[TransferDTOFieldDefinition, ...],
- is_data_field: bool,
- field_definition: FieldDefinition | None = None,
- ) -> Callable[[Any], Any]:
- if field_definition and field_definition.is_non_string_collection:
- factory = cls(
- is_data_field=is_data_field,
- nested_as_dict=False,
- )
- source_value_name = factory._create_local_name("source_value")
- return_value_name = factory._create_local_name("tmp_return_value")
- factory._create_transfer_data_body_nested(
- field_definitions=field_definitions,
- field_definition=field_definition,
- destination_type=destination_type,
- source_data_name=source_value_name,
- assignment_target=return_value_name,
- )
- return factory._make_function(source_value_name=source_value_name, return_value_name=return_value_name)
-
- return cls.create_transfer_instance_data(
- destination_type=destination_type,
- field_definitions=field_definitions,
- is_data_field=is_data_field,
- )
-
- def _create_transfer_data_body_nested(
- self,
- field_definition: FieldDefinition,
- field_definitions: tuple[TransferDTOFieldDefinition, ...],
- destination_type: type[Any],
- source_data_name: str,
- assignment_target: str,
- ) -> None:
- origin_name = self._add_to_fn_globals("origin", field_definition.instantiable_origin)
- transfer_func = TransferFunctionFactory.create_transfer_data(
- is_data_field=self.is_data_field,
- destination_type=destination_type,
- field_definition=field_definition.inner_types[0],
- field_definitions=field_definitions,
- )
- transfer_func_name = self._add_to_fn_globals("transfer_data", transfer_func)
- if field_definition.is_mapping:
- self._add_stmt(
- f"{assignment_target} = {origin_name}((key, {transfer_func_name}(item)) for key, item in {source_data_name}.items())"
- )
- else:
- self._add_stmt(
- f"{assignment_target} = {origin_name}({transfer_func_name}(item) for item in {source_data_name})"
- )
-
- def _create_transfer_instance_data(
- self,
- tmp_return_type_name: str,
- source_instance_name: str,
- destination_type_name: str,
- field_definitions: tuple[TransferDTOFieldDefinition, ...],
- destination_type_is_dict: bool,
- ) -> None:
- local_dict_name = self._create_local_name("unstructured_data")
- self._add_stmt(f"{local_dict_name} = {{}}")
-
- if field_definitions := tuple(f for f in field_definitions if self.is_data_field or not f.is_excluded):
- if len(field_definitions) > 1 and ("." in source_instance_name or "[" in source_instance_name):
- # If there's more than one field we have to access, we check if it is
- # nested. If it is nested, we assign it to a local variable to avoid
- # repeated lookups. This is only a small performance improvement for
- # regular attributes, but can be quite significant for properties or
- # other types of descriptors, where I/O may be involved, such as the
- # case for lazy loaded relationships in SQLAlchemy
- if "." in source_instance_name:
- level_1, level_2 = source_instance_name.split(".", 1)
- else:
- level_1, level_2, *_ = self._re_index_access.split(source_instance_name, maxsplit=1)
-
- new_source_instance_name = self._create_local_name(f"{level_1}_{level_2}")
- self._add_stmt(f"{new_source_instance_name} = {source_instance_name}")
- source_instance_name = new_source_instance_name
-
- for source_type in ("mapping", "object"):
- if source_type == "mapping":
- block_expr = f"if isinstance({source_instance_name}, Mapping):"
- access_item = self._access_mapping_item
- else:
- block_expr = "else:"
- access_item = self._access_attribute
-
- with self._start_block(expr=block_expr):
- self._create_transfer_instance_data_inner(
- local_dict_name=local_dict_name,
- field_definitions=field_definitions,
- access_field_safe=access_item,
- source_instance_name=source_instance_name,
- )
-
- # if the destination type is a dict we can reuse our temporary dictionary of
- # unstructured data as the "return value"
- if not destination_type_is_dict:
- self._add_stmt(f"{tmp_return_type_name} = {destination_type_name}(**{local_dict_name})")
- else:
- self._add_stmt(f"{tmp_return_type_name} = {local_dict_name}")
-
- def _create_transfer_instance_data_inner(
- self,
- *,
- local_dict_name: str,
- field_definitions: tuple[TransferDTOFieldDefinition, ...],
- access_field_safe: FieldAccessManager,
- source_instance_name: str,
- ) -> None:
- for field_definition in field_definitions:
- with access_field_safe(
- source_name=source_instance_name,
- field_name=field_definition.name,
- expect_optional=field_definition.is_partial or field_definition.is_optional,
- ) as source_value_expr:
- if self.is_data_field and field_definition.is_partial:
- # we assign the source value to a name here, so we can skip
- # getting it twice from the source instance
- source_value_name = self._create_local_name("source_value")
- self._add_stmt(f"{source_value_name} = {source_value_expr}")
- ctx = self._start_block(f"if {source_value_name} is not UNSET:")
- else:
- # in these cases, we only ever access the source value once, so
- # we can skip assigning it
- source_value_name = source_value_expr
- ctx = nullcontext() # type: ignore[assignment]
- with ctx:
- self._create_transfer_type_data_body(
- transfer_type=field_definition.transfer_type,
- nested_as_dict=self.nested_as_dict,
- source_value_name=source_value_name,
- assignment_target=f"{local_dict_name}['{field_definition.name}']",
- )
-
- def _create_transfer_type_data_body(
- self,
- transfer_type: TransferType,
- nested_as_dict: bool,
- source_value_name: str,
- assignment_target: str,
- ) -> None:
- if isinstance(transfer_type, SimpleType) and transfer_type.nested_field_info:
- if nested_as_dict:
- destination_type: Any = dict
- elif self.is_data_field:
- destination_type = transfer_type.field_definition.annotation
- else:
- destination_type = transfer_type.nested_field_info.model
-
- self._create_transfer_instance_data(
- field_definitions=transfer_type.nested_field_info.field_definitions,
- tmp_return_type_name=assignment_target,
- source_instance_name=source_value_name,
- destination_type_name=self._add_to_fn_globals("destination_type", destination_type),
- destination_type_is_dict=destination_type is dict,
- )
- return
-
- if isinstance(transfer_type, UnionType) and transfer_type.has_nested:
- self._create_transfer_nested_union_type_data(
- transfer_type=transfer_type,
- source_value_name=source_value_name,
- assignment_target=assignment_target,
- )
- return
-
- if isinstance(transfer_type, CollectionType):
- origin_name = self._add_to_fn_globals("origin", transfer_type.field_definition.instantiable_origin)
- if transfer_type.has_nested:
- transfer_type_data_fn = TransferFunctionFactory.create_transfer_type_data(
- is_data_field=self.is_data_field, transfer_type=transfer_type.inner_type
- )
- transfer_type_data_name = self._add_to_fn_globals("transfer_type_data", transfer_type_data_fn)
- self._add_stmt(
- f"{assignment_target} = {origin_name}({transfer_type_data_name}(item) for item in {source_value_name})"
- )
- return
-
- self._add_stmt(f"{assignment_target} = {origin_name}({source_value_name})")
- return
-
- self._add_stmt(f"{assignment_target} = {source_value_name}")
-
- def _create_transfer_nested_union_type_data(
- self,
- transfer_type: UnionType,
- source_value_name: str,
- assignment_target: str,
- ) -> None:
- for inner_type in transfer_type.inner_types:
- if isinstance(inner_type, CompositeType):
- continue
-
- if inner_type.nested_field_info:
- if self.is_data_field:
- constraint_type = inner_type.nested_field_info.model
- destination_type = inner_type.field_definition.annotation
- else:
- constraint_type = inner_type.field_definition.annotation
- destination_type = inner_type.nested_field_info.model
-
- constraint_type_name = self._add_to_fn_globals("constraint_type", constraint_type)
- destination_type_name = self._add_to_fn_globals("destination_type", destination_type)
-
- with self._start_block(f"if isinstance({source_value_name}, {constraint_type_name}):"):
- self._create_transfer_instance_data(
- destination_type_name=destination_type_name,
- destination_type_is_dict=destination_type is dict,
- field_definitions=inner_type.nested_field_info.field_definitions,
- source_instance_name=source_value_name,
- tmp_return_type_name=assignment_target,
- )
- return
- self._add_stmt(f"{assignment_target} = {source_value_name}")
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/_types.py b/venv/lib/python3.11/site-packages/litestar/dto/_types.py
deleted file mode 100644
index 24e99b7..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/_types.py
+++ /dev/null
@@ -1,148 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING
-
-from litestar.dto.data_structures import DTOFieldDefinition
-
-if TYPE_CHECKING:
- from typing import Any
-
- from typing_extensions import Self
-
- from litestar.typing import FieldDefinition
-
-
-@dataclass(frozen=True)
-class NestedFieldInfo:
- """Type for representing fields and model type of nested model type."""
-
- __slots__ = ("model", "field_definitions")
-
- model: type[Any]
- field_definitions: tuple[TransferDTOFieldDefinition, ...]
-
-
-@dataclass(frozen=True)
-class TransferType:
- """Type for representing model types for data transfer."""
-
- __slots__ = ("field_definition",)
-
- field_definition: FieldDefinition
-
-
-@dataclass(frozen=True)
-class SimpleType(TransferType):
- """Represents indivisible, non-composite types."""
-
- __slots__ = ("nested_field_info",)
-
- nested_field_info: NestedFieldInfo | None
- """If the type is a 'nested' type, this is the model generated for transfer to/from it."""
-
- @property
- def has_nested(self) -> bool:
- return self.nested_field_info is not None
-
-
-@dataclass(frozen=True)
-class CompositeType(TransferType):
- """A type that is made up of other types."""
-
- __slots__ = ("has_nested",)
-
- has_nested: bool
- """Whether the type represents nested model types within itself."""
-
-
-@dataclass(frozen=True)
-class UnionType(CompositeType):
- """Type for representing union types for data transfer."""
-
- __slots__ = ("inner_types",)
-
- inner_types: tuple[CompositeType | SimpleType, ...]
-
-
-@dataclass(frozen=True)
-class CollectionType(CompositeType):
- """Type for representing collection types for data transfer."""
-
- __slots__ = ("inner_type",)
-
- inner_type: CompositeType | SimpleType
-
-
-@dataclass(frozen=True)
-class TupleType(CompositeType):
- """Type for representing tuples for data transfer."""
-
- __slots__ = ("inner_types",)
-
- inner_types: tuple[CompositeType | SimpleType, ...]
-
-
-@dataclass(frozen=True)
-class MappingType(CompositeType):
- """Type for representing mappings for data transfer."""
-
- __slots__ = ("key_type", "value_type")
-
- key_type: CompositeType | SimpleType
- value_type: CompositeType | SimpleType
-
-
-@dataclass(frozen=True)
-class TransferDTOFieldDefinition(DTOFieldDefinition):
- __slots__ = (
- "default_factory",
- "dto_field",
- "model_name",
- "is_excluded",
- "is_partial",
- "serialization_name",
- "transfer_type",
- "unique_name",
- )
-
- transfer_type: TransferType
- """Type of the field for transfer."""
- serialization_name: str | None
- """Name of the field as it should appear in serialized form."""
- is_partial: bool
- """Whether the field is optional for transfer."""
- is_excluded: bool
- """Whether the field should be excluded from transfer."""
-
- @classmethod
- def from_dto_field_definition(
- cls,
- field_definition: DTOFieldDefinition,
- transfer_type: TransferType,
- serialization_name: str | None,
- is_partial: bool,
- is_excluded: bool,
- ) -> Self:
- return cls(
- annotation=field_definition.annotation,
- args=field_definition.args,
- default=field_definition.default,
- default_factory=field_definition.default_factory,
- dto_field=field_definition.dto_field,
- extra=field_definition.extra,
- inner_types=field_definition.inner_types,
- instantiable_origin=field_definition.instantiable_origin,
- is_excluded=is_excluded,
- is_partial=is_partial,
- kwarg_definition=field_definition.kwarg_definition,
- metadata=field_definition.metadata,
- name=field_definition.name,
- origin=field_definition.origin,
- raw=field_definition.raw,
- safe_generic_origin=field_definition.safe_generic_origin,
- serialization_name=serialization_name,
- transfer_type=transfer_type,
- type_wrappers=field_definition.type_wrappers,
- model_name=field_definition.model_name,
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/base_dto.py b/venv/lib/python3.11/site-packages/litestar/dto/base_dto.py
deleted file mode 100644
index 991b09f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/base_dto.py
+++ /dev/null
@@ -1,313 +0,0 @@
-from __future__ import annotations
-
-import typing
-from abc import abstractmethod
-from inspect import getmodule
-from typing import TYPE_CHECKING, Collection, Generic, TypeVar
-
-from typing_extensions import NotRequired, TypedDict, get_type_hints
-
-from litestar.dto._backend import DTOBackend
-from litestar.dto._codegen_backend import DTOCodegenBackend
-from litestar.dto.config import DTOConfig
-from litestar.dto.data_structures import DTOData
-from litestar.dto.types import RenameStrategy
-from litestar.enums import RequestEncodingType
-from litestar.exceptions.dto_exceptions import InvalidAnnotationException
-from litestar.types.builtin_types import NoneType
-from litestar.types.composite_types import TypeEncodersMap
-from litestar.typing import FieldDefinition
-
-if TYPE_CHECKING:
- from typing import Any, ClassVar, Generator
-
- from typing_extensions import Self
-
- from litestar._openapi.schema_generation import SchemaCreator
- from litestar.connection import ASGIConnection
- from litestar.dto.data_structures import DTOFieldDefinition
- from litestar.openapi.spec import Reference, Schema
- from litestar.types.serialization import LitestarEncodableType
-
-__all__ = ("AbstractDTO",)
-
-T = TypeVar("T")
-
-
-class _BackendDict(TypedDict):
- data_backend: NotRequired[DTOBackend]
- return_backend: NotRequired[DTOBackend]
-
-
-class AbstractDTO(Generic[T]):
- """Base class for DTO types."""
-
- __slots__ = ("asgi_connection",)
-
- config: ClassVar[DTOConfig]
- """Config objects to define properties of the DTO."""
- model_type: type[T]
- """If ``annotation`` is an iterable, this is the inner type, otherwise will be the same as ``annotation``."""
-
- _dto_backends: ClassVar[dict[str, _BackendDict]] = {}
-
- def __init__(self, asgi_connection: ASGIConnection) -> None:
- """Create an AbstractDTOFactory type.
-
- Args:
- asgi_connection: A :class:`ASGIConnection <litestar.connection.base.ASGIConnection>` instance.
- """
- self.asgi_connection = asgi_connection
-
- def __class_getitem__(cls, annotation: Any) -> type[Self]:
- field_definition = FieldDefinition.from_annotation(annotation)
-
- if (field_definition.is_optional and len(field_definition.args) > 2) or (
- field_definition.is_union and not field_definition.is_optional
- ):
- raise InvalidAnnotationException("Unions are currently not supported as type argument to DTOs.")
-
- if field_definition.is_forward_ref:
- raise InvalidAnnotationException("Forward references are not supported as type argument to DTO")
-
- # if a configuration is not provided, and the type narrowing is a type var, we don't want to create a subclass
- config = cls.get_dto_config_from_annotated_type(field_definition)
-
- if not config:
- if field_definition.is_type_var:
- return cls
- config = cls.config if hasattr(cls, "config") else DTOConfig()
-
- cls_dict: dict[str, Any] = {"config": config, "_type_backend_map": {}, "_handler_backend_map": {}}
- if not field_definition.is_type_var:
- cls_dict.update(model_type=field_definition.annotation)
-
- return type(f"{cls.__name__}[{annotation}]", (cls,), cls_dict) # pyright: ignore
-
- def decode_builtins(self, value: dict[str, Any]) -> Any:
- """Decode a dictionary of Python values into an the DTO's datatype."""
-
- backend = self._dto_backends[self.asgi_connection.route_handler.handler_id]["data_backend"] # pyright: ignore
- return backend.populate_data_from_builtins(value, self.asgi_connection)
-
- def decode_bytes(self, value: bytes) -> Any:
- """Decode a byte string into an the DTO's datatype."""
-
- backend = self._dto_backends[self.asgi_connection.route_handler.handler_id]["data_backend"] # pyright: ignore
- return backend.populate_data_from_raw(value, self.asgi_connection)
-
- def data_to_encodable_type(self, data: T | Collection[T]) -> LitestarEncodableType:
- backend = self._dto_backends[self.asgi_connection.route_handler.handler_id]["return_backend"] # pyright: ignore
- return backend.encode_data(data)
-
- @classmethod
- @abstractmethod
- def generate_field_definitions(cls, model_type: type[Any]) -> Generator[DTOFieldDefinition, None, None]:
- """Generate ``FieldDefinition`` instances from ``model_type``.
-
- Yields:
- ``FieldDefinition`` instances.
- """
-
- @classmethod
- @abstractmethod
- def detect_nested_field(cls, field_definition: FieldDefinition) -> bool:
- """Return ``True`` if ``field_definition`` represents a nested model field.
-
- Args:
- field_definition: inspect type to determine if field represents a nested model.
-
- Returns:
- ``True`` if ``field_definition`` represents a nested model field.
- """
-
- @classmethod
- def is_supported_model_type_field(cls, field_definition: FieldDefinition) -> bool:
- """Check support for the given type.
-
- Args:
- field_definition: A :class:`FieldDefinition <litestar.typing.FieldDefinition>` instance.
-
- Returns:
- Whether the type of the field definition is supported by the DTO.
- """
- return field_definition.is_subclass_of(cls.model_type) or (
- field_definition.origin
- and any(
- cls.resolve_model_type(inner_field).is_subclass_of(cls.model_type)
- for inner_field in field_definition.inner_types
- )
- )
-
- @classmethod
- def create_for_field_definition(
- cls,
- field_definition: FieldDefinition,
- handler_id: str,
- backend_cls: type[DTOBackend] | None = None,
- ) -> None:
- """Creates a DTO subclass for a field definition.
-
- Args:
- field_definition: A :class:`FieldDefinition <litestar.typing.FieldDefinition>` instance.
- handler_id: ID of the route handler for which to create a DTO instance.
- backend_cls: Alternative DTO backend class to use
-
- Returns:
- None
- """
-
- if handler_id not in cls._dto_backends:
- cls._dto_backends[handler_id] = {}
-
- backend_context = cls._dto_backends[handler_id]
- key = "data_backend" if field_definition.name == "data" else "return_backend"
-
- if key not in backend_context:
- model_type_field_definition = cls.resolve_model_type(field_definition=field_definition)
- wrapper_attribute_name: str | None = None
-
- if not model_type_field_definition.is_subclass_of(cls.model_type):
- if resolved_generic_result := cls.resolve_generic_wrapper_type(
- field_definition=model_type_field_definition
- ):
- model_type_field_definition, field_definition, wrapper_attribute_name = resolved_generic_result
- else:
- raise InvalidAnnotationException(
- f"DTO narrowed with '{cls.model_type}', handler type is '{field_definition.annotation}'"
- )
-
- if backend_cls is None:
- backend_cls = DTOCodegenBackend if cls.config.experimental_codegen_backend else DTOBackend
- elif backend_cls is DTOCodegenBackend and cls.config.experimental_codegen_backend is False:
- backend_cls = DTOBackend
-
- backend_context[key] = backend_cls( # type: ignore[literal-required]
- dto_factory=cls,
- field_definition=field_definition,
- model_type=model_type_field_definition.annotation,
- wrapper_attribute_name=wrapper_attribute_name,
- is_data_field=field_definition.name == "data",
- handler_id=handler_id,
- )
-
- @classmethod
- def create_openapi_schema(
- cls, field_definition: FieldDefinition, handler_id: str, schema_creator: SchemaCreator
- ) -> Reference | Schema:
- """Create an OpenAPI request body.
-
- Returns:
- OpenAPI request body.
- """
- key = "data_backend" if field_definition.name == "data" else "return_backend"
- backend = cls._dto_backends[handler_id][key] # type: ignore[literal-required]
- return schema_creator.for_field_definition(FieldDefinition.from_annotation(backend.annotation))
-
- @classmethod
- def resolve_generic_wrapper_type(
- cls, field_definition: FieldDefinition
- ) -> tuple[FieldDefinition, FieldDefinition, str] | None:
- """Handle where DTO supported data is wrapped in a generic container type.
-
- Args:
- field_definition: A parsed type annotation that represents the annotation used to narrow the DTO type.
-
- Returns:
- The data model type.
- """
- if field_definition.origin and (
- inner_fields := [
- inner_field
- for inner_field in field_definition.inner_types
- if cls.resolve_model_type(inner_field).is_subclass_of(cls.model_type)
- ]
- ):
- inner_field = inner_fields[0]
- model_field_definition = cls.resolve_model_type(inner_field)
-
- for attr, attr_type in cls.get_model_type_hints(field_definition.origin).items():
- if isinstance(attr_type.annotation, TypeVar) or any(
- isinstance(t.annotation, TypeVar) for t in attr_type.inner_types
- ):
- if attr_type.is_non_string_collection:
- # the inner type of the collection type is the type var, so we need to specialize the
- # collection type with the DTO supported type.
- specialized_annotation = attr_type.safe_generic_origin[model_field_definition.annotation]
- return model_field_definition, FieldDefinition.from_annotation(specialized_annotation), attr
- return model_field_definition, inner_field, attr
- return None
-
- @staticmethod
- def get_model_type_hints(
- model_type: type[Any], namespace: dict[str, Any] | None = None
- ) -> dict[str, FieldDefinition]:
- """Retrieve type annotations for ``model_type``.
-
- Args:
- model_type: Any type-annotated class.
- namespace: Optional namespace to use for resolving type hints.
-
- Returns:
- Parsed type hints for ``model_type`` resolved within the scope of its module.
- """
- namespace = namespace or {}
- namespace.update(vars(typing))
- namespace.update(
- {
- "TypeEncodersMap": TypeEncodersMap,
- "DTOConfig": DTOConfig,
- "RenameStrategy": RenameStrategy,
- "RequestEncodingType": RequestEncodingType,
- }
- )
-
- if model_module := getmodule(model_type):
- namespace.update(vars(model_module))
-
- return {
- k: FieldDefinition.from_kwarg(annotation=v, name=k)
- for k, v in get_type_hints(model_type, localns=namespace, include_extras=True).items() # pyright: ignore
- }
-
- @staticmethod
- def get_dto_config_from_annotated_type(field_definition: FieldDefinition) -> DTOConfig | None:
- """Extract data type and config instances from ``Annotated`` annotation.
-
- Args:
- field_definition: A parsed type annotation that represents the annotation used to narrow the DTO type.
-
- Returns:
- The type and config object extracted from the annotation.
- """
- return next((item for item in field_definition.metadata if isinstance(item, DTOConfig)), None)
-
- @classmethod
- def resolve_model_type(cls, field_definition: FieldDefinition) -> FieldDefinition:
- """Resolve the data model type from a parsed type.
-
- Args:
- field_definition: A parsed type annotation that represents the annotation used to narrow the DTO type.
-
- Returns:
- A :class:`FieldDefinition <.typing.FieldDefinition>` that represents the data model type.
- """
- if field_definition.is_optional:
- return cls.resolve_model_type(
- next(t for t in field_definition.inner_types if not t.is_subclass_of(NoneType))
- )
-
- if field_definition.is_subclass_of(DTOData):
- return cls.resolve_model_type(field_definition.inner_types[0])
-
- if field_definition.is_collection:
- if field_definition.is_mapping:
- return cls.resolve_model_type(field_definition.inner_types[1])
-
- if field_definition.is_tuple:
- if any(t is Ellipsis for t in field_definition.args):
- return cls.resolve_model_type(field_definition.inner_types[0])
- elif field_definition.is_non_string_collection:
- return cls.resolve_model_type(field_definition.inner_types[0])
-
- return field_definition
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/config.py b/venv/lib/python3.11/site-packages/litestar/dto/config.py
deleted file mode 100644
index e213d17..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/config.py
+++ /dev/null
@@ -1,66 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass, field
-from typing import TYPE_CHECKING
-
-from litestar.exceptions import ImproperlyConfiguredException
-
-if TYPE_CHECKING:
- from typing import AbstractSet
-
- from litestar.dto.types import RenameStrategy
-
-__all__ = ("DTOConfig",)
-
-
-@dataclass(frozen=True)
-class DTOConfig:
- """Control the generated DTO."""
-
- exclude: AbstractSet[str] = field(default_factory=set)
- """Explicitly exclude fields from the generated DTO.
-
- If exclude is specified, all fields not specified in exclude will be included by default.
-
- Notes:
- - The field names are dot-separated paths to nested fields, e.g. ``"address.street"`` will
- exclude the ``"street"`` field from a nested ``"address"`` model.
- - 'exclude' mutually exclusive with 'include' - specifying both values will raise an
- ``ImproperlyConfiguredException``.
- """
- include: AbstractSet[str] = field(default_factory=set)
- """Explicitly include fields in the generated DTO.
-
- If include is specified, all fields not specified in include will be excluded by default.
-
- Notes:
- - The field names are dot-separated paths to nested fields, e.g. ``"address.street"`` will
- include the ``"street"`` field from a nested ``"address"`` model.
- - 'include' mutually exclusive with 'exclude' - specifying both values will raise an
- ``ImproperlyConfiguredException``.
- """
- rename_fields: dict[str, str] = field(default_factory=dict)
- """Mapping of field names, to new name."""
- rename_strategy: RenameStrategy | None = None
- """Rename all fields using a pre-defined strategy or a custom strategy.
-
- The pre-defined strategies are: `upper`, `lower`, `camel`, `pascal`.
-
- A custom strategy is any callable that accepts a string as an argument and
- return a string.
-
- Fields defined in ``rename_fields`` are ignored."""
- max_nested_depth: int = 1
- """The maximum depth of nested items allowed for data transfer."""
- partial: bool = False
- """Allow transfer of partial data."""
- underscore_fields_private: bool = True
- """Fields starting with an underscore are considered private and excluded from data transfer."""
- experimental_codegen_backend: bool | None = None
- """Use the experimental codegen backend"""
-
- def __post_init__(self) -> None:
- if self.include and self.exclude:
- raise ImproperlyConfiguredException(
- "'include' and 'exclude' are mutually exclusive options, please use one of them"
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/data_structures.py b/venv/lib/python3.11/site-packages/litestar/dto/data_structures.py
deleted file mode 100644
index a5c3386..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/data_structures.py
+++ /dev/null
@@ -1,116 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING, Generic, TypeVar
-
-from litestar.typing import FieldDefinition
-
-if TYPE_CHECKING:
- from typing import Any, Callable
-
- from litestar.dto import DTOField
- from litestar.dto._backend import DTOBackend
-
-T = TypeVar("T")
-
-
-class DTOData(Generic[T]):
- """DTO validated data and utility methods."""
-
- __slots__ = ("_backend", "_data_as_builtins")
-
- def __init__(self, backend: DTOBackend, data_as_builtins: Any) -> None:
- self._backend = backend
- self._data_as_builtins = data_as_builtins
-
- def create_instance(self, **kwargs: Any) -> T:
- """Create an instance of the DTO validated data.
-
- Args:
- **kwargs: Additional data to create the instance with. Takes precedence over DTO validated data.
- """
- data = dict(self._data_as_builtins)
- for k, v in kwargs.items():
- _set_nested_dict_value(data, k.split("__"), v)
- return self._backend.transfer_data_from_builtins(data) # type: ignore[no-any-return]
-
- def update_instance(self, instance: T, **kwargs: Any) -> T:
- """Update an instance with the DTO validated data.
-
- Args:
- instance: The instance to update.
- **kwargs: Additional data to update the instance with. Takes precedence over DTO validated data.
- """
- data = {**self._data_as_builtins, **kwargs}
- for k, v in data.items():
- setattr(instance, k, v)
- return instance
-
- def as_builtins(self) -> Any:
- """Return the DTO validated data as builtins."""
- return self._data_as_builtins
-
-
-def _set_nested_dict_value(d: dict[str, Any], keys: list[str], value: Any) -> None:
- if len(keys) == 1:
- d[keys[0]] = value
- else:
- key = keys[0]
- d.setdefault(key, {})
- _set_nested_dict_value(d[key], keys[1:], value)
-
-
-@dataclass(frozen=True)
-class DTOFieldDefinition(FieldDefinition):
- """A model field representation for purposes of generating a DTO backend model type."""
-
- __slots__ = (
- "default_factory",
- "dto_field",
- "model_name",
- )
-
- model_name: str
- """The name of the model for which the field is generated."""
- default_factory: Callable[[], Any] | None
- """Default factory of the field."""
- dto_field: DTOField
- """DTO field configuration."""
-
- @classmethod
- def from_field_definition(
- cls,
- field_definition: FieldDefinition,
- model_name: str,
- default_factory: Callable[[], Any] | None,
- dto_field: DTOField,
- ) -> DTOFieldDefinition:
- """Create a :class:`FieldDefinition` from a :class:`FieldDefinition`.
-
- Args:
- field_definition: A :class:`FieldDefinition` to create a :class:`FieldDefinition` from.
- model_name: The name of the model.
- default_factory: Default factory function, if any.
- dto_field: DTOField instance.
-
- Returns:
- A :class:`FieldDefinition` instance.
- """
- return DTOFieldDefinition(
- annotation=field_definition.annotation,
- args=field_definition.args,
- default=field_definition.default,
- default_factory=default_factory,
- dto_field=dto_field,
- extra=field_definition.extra,
- inner_types=field_definition.inner_types,
- instantiable_origin=field_definition.instantiable_origin,
- kwarg_definition=field_definition.kwarg_definition,
- metadata=field_definition.metadata,
- model_name=model_name,
- name=field_definition.name,
- origin=field_definition.origin,
- raw=field_definition.raw,
- safe_generic_origin=field_definition.safe_generic_origin,
- type_wrappers=field_definition.type_wrappers,
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/dataclass_dto.py b/venv/lib/python3.11/site-packages/litestar/dto/dataclass_dto.py
deleted file mode 100644
index 554b0f3..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/dataclass_dto.py
+++ /dev/null
@@ -1,58 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import MISSING, fields, replace
-from typing import TYPE_CHECKING, Generic, TypeVar
-
-from litestar.dto.base_dto import AbstractDTO
-from litestar.dto.data_structures import DTOFieldDefinition
-from litestar.dto.field import DTO_FIELD_META_KEY, DTOField
-from litestar.params import DependencyKwarg, KwargDefinition
-from litestar.types.empty import Empty
-
-if TYPE_CHECKING:
- from typing import Collection, Generator
-
- from litestar.types.protocols import DataclassProtocol
- from litestar.typing import FieldDefinition
-
-
-__all__ = ("DataclassDTO", "T")
-
-T = TypeVar("T", bound="DataclassProtocol | Collection[DataclassProtocol]")
-AnyDataclass = TypeVar("AnyDataclass", bound="DataclassProtocol")
-
-
-class DataclassDTO(AbstractDTO[T], Generic[T]):
- """Support for domain modelling with dataclasses."""
-
- @classmethod
- def generate_field_definitions(
- cls, model_type: type[DataclassProtocol]
- ) -> Generator[DTOFieldDefinition, None, None]:
- dc_fields = {f.name: f for f in fields(model_type)}
- for key, field_definition in cls.get_model_type_hints(model_type).items():
- if not (dc_field := dc_fields.get(key)):
- continue
-
- default = dc_field.default if dc_field.default is not MISSING else Empty
- default_factory = dc_field.default_factory if dc_field.default_factory is not MISSING else None
- field_defintion = replace(
- DTOFieldDefinition.from_field_definition(
- field_definition=field_definition,
- default_factory=default_factory,
- dto_field=dc_field.metadata.get(DTO_FIELD_META_KEY, DTOField()),
- model_name=model_type.__name__,
- ),
- name=key,
- default=default,
- )
-
- yield (
- replace(field_defintion, default=Empty, kwarg_definition=default)
- if isinstance(default, (KwargDefinition, DependencyKwarg))
- else field_defintion
- )
-
- @classmethod
- def detect_nested_field(cls, field_definition: FieldDefinition) -> bool:
- return hasattr(field_definition.annotation, "__dataclass_fields__")
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/field.py b/venv/lib/python3.11/site-packages/litestar/dto/field.py
deleted file mode 100644
index 7ef8a39..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/field.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""DTO domain types."""
-
-from __future__ import annotations
-
-from dataclasses import dataclass
-from enum import Enum
-from typing import Literal
-
-__all__ = (
- "DTO_FIELD_META_KEY",
- "DTOField",
- "Mark",
- "dto_field",
-)
-
-DTO_FIELD_META_KEY = "__dto__"
-
-
-class Mark(str, Enum):
- """For marking field definitions on domain models."""
-
- READ_ONLY = "read-only"
- """To mark a field that can be read, but not updated by clients."""
- WRITE_ONLY = "write-only"
- """To mark a field that can be written to, but not read by clients."""
- PRIVATE = "private"
- """To mark a field that can neither be read or updated by clients."""
-
-
-@dataclass
-class DTOField:
- """For configuring DTO behavior on model fields."""
-
- mark: Mark | Literal["read-only", "write-only", "private"] | None = None
- """Mark the field as read-only, or private."""
-
-
-def dto_field(mark: Literal["read-only", "write-only", "private"] | Mark) -> dict[str, DTOField]:
- """Create a field metadata mapping.
-
- Args:
- mark: A DTO mark for the field, e.g., "read-only".
-
- Returns:
- A dict for setting as field metadata, such as the dataclass "metadata" field key, or the SQLAlchemy "info"
- field.
-
- Marking a field automates its inclusion/exclusion from DTO field definitions, depending on the DTO's purpose.
- """
- return {DTO_FIELD_META_KEY: DTOField(mark=Mark(mark))}
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/msgspec_dto.py b/venv/lib/python3.11/site-packages/litestar/dto/msgspec_dto.py
deleted file mode 100644
index 826a1d2..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/msgspec_dto.py
+++ /dev/null
@@ -1,54 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import replace
-from typing import TYPE_CHECKING, Generic, TypeVar
-
-from msgspec import NODEFAULT, Struct, structs
-
-from litestar.dto.base_dto import AbstractDTO
-from litestar.dto.data_structures import DTOFieldDefinition
-from litestar.dto.field import DTO_FIELD_META_KEY, DTOField
-from litestar.types.empty import Empty
-
-if TYPE_CHECKING:
- from typing import Any, Collection, Generator
-
- from litestar.typing import FieldDefinition
-
-
-__all__ = ("MsgspecDTO",)
-
-T = TypeVar("T", bound="Struct | Collection[Struct]")
-
-
-class MsgspecDTO(AbstractDTO[T], Generic[T]):
- """Support for domain modelling with Msgspec."""
-
- @classmethod
- def generate_field_definitions(cls, model_type: type[Struct]) -> Generator[DTOFieldDefinition, None, None]:
- msgspec_fields = {f.name: f for f in structs.fields(model_type)}
-
- def default_or_empty(value: Any) -> Any:
- return Empty if value is NODEFAULT else value
-
- def default_or_none(value: Any) -> Any:
- return None if value is NODEFAULT else value
-
- for key, field_definition in cls.get_model_type_hints(model_type).items():
- msgspec_field = msgspec_fields[key]
- dto_field = (field_definition.extra or {}).pop(DTO_FIELD_META_KEY, DTOField())
-
- yield replace(
- DTOFieldDefinition.from_field_definition(
- field_definition=field_definition,
- dto_field=dto_field,
- model_name=model_type.__name__,
- default_factory=default_or_none(msgspec_field.default_factory),
- ),
- default=default_or_empty(msgspec_field.default),
- name=key,
- )
-
- @classmethod
- def detect_nested_field(cls, field_definition: FieldDefinition) -> bool:
- return field_definition.is_subclass_of(Struct)
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/types.py b/venv/lib/python3.11/site-packages/litestar/dto/types.py
deleted file mode 100644
index f154e49..0000000
--- a/venv/lib/python3.11/site-packages/litestar/dto/types.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING
-
-if TYPE_CHECKING:
- from typing import Callable, Literal
-
- from typing_extensions import TypeAlias
-
-__all__ = ("RenameStrategy",)
-
-RenameStrategy: TypeAlias = 'Literal["lower", "upper", "camel", "pascal", "kebab"] | Callable[[str], str]'
-"""A pre-defined strategy or a custom callback for converting DTO field names."""
diff --git a/venv/lib/python3.11/site-packages/litestar/enums.py b/venv/lib/python3.11/site-packages/litestar/enums.py
deleted file mode 100644
index a660228..0000000
--- a/venv/lib/python3.11/site-packages/litestar/enums.py
+++ /dev/null
@@ -1,90 +0,0 @@
-from enum import Enum
-
-__all__ = (
- "CompressionEncoding",
- "HttpMethod",
- "MediaType",
- "OpenAPIMediaType",
- "ParamType",
- "RequestEncodingType",
- "ScopeType",
-)
-
-
-class HttpMethod(str, Enum):
- """An Enum for HTTP methods."""
-
- DELETE = "DELETE"
- GET = "GET"
- HEAD = "HEAD"
- OPTIONS = "OPTIONS"
- PATCH = "PATCH"
- POST = "POST"
- PUT = "PUT"
-
-
-class MediaType(str, Enum):
- """An Enum for ``Content-Type`` header values."""
-
- JSON = "application/json"
- MESSAGEPACK = "application/x-msgpack"
- HTML = "text/html"
- TEXT = "text/plain"
- CSS = "text/css"
- XML = "application/xml"
-
-
-class OpenAPIMediaType(str, Enum):
- """An Enum for OpenAPI specific response ``Content-Type`` header values."""
-
- OPENAPI_YAML = "application/vnd.oai.openapi"
- OPENAPI_JSON = "application/vnd.oai.openapi+json"
-
-
-class RequestEncodingType(str, Enum):
- """An Enum for request ``Content-Type`` header values designating encoding formats."""
-
- JSON = "application/json"
- MESSAGEPACK = "application/x-msgpack"
- MULTI_PART = "multipart/form-data"
- URL_ENCODED = "application/x-www-form-urlencoded"
-
-
-class ScopeType(str, Enum):
- """An Enum for the 'http' key stored under Scope.
-
- Notes:
- - ``asgi`` is used by Litestar internally and is not part of the specification.
- """
-
- HTTP = "http"
- WEBSOCKET = "websocket"
- ASGI = "asgi"
-
-
-class ParamType(str, Enum):
- """An Enum for the types of parameters a request can receive."""
-
- PATH = "path"
- QUERY = "query"
- COOKIE = "cookie"
- HEADER = "header"
-
-
-class CompressionEncoding(str, Enum):
- """An Enum for supported compression encodings."""
-
- GZIP = "gzip"
- BROTLI = "br"
-
-
-class ASGIExtension(str, Enum):
- """ASGI extension keys: https://asgi.readthedocs.io/en/latest/extensions.html"""
-
- WS_DENIAL = "websocket.http.response"
- SERVER_PUSH = "http.response.push"
- ZERO_COPY_SEND_EXTENSION = "http.response.zerocopysend"
- PATH_SEND = "http.response.pathsend"
- TLS = "tls"
- EARLY_HINTS = "http.response.early_hint"
- HTTP_TRAILERS = "http.response.trailers"
diff --git a/venv/lib/python3.11/site-packages/litestar/events/__init__.py b/venv/lib/python3.11/site-packages/litestar/events/__init__.py
deleted file mode 100644
index a291141..0000000
--- a/venv/lib/python3.11/site-packages/litestar/events/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from .emitter import BaseEventEmitterBackend, SimpleEventEmitter
-from .listener import EventListener, listener
-
-__all__ = ("EventListener", "SimpleEventEmitter", "BaseEventEmitterBackend", "listener")
diff --git a/venv/lib/python3.11/site-packages/litestar/events/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/events/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index bc8ee50..0000000
--- a/venv/lib/python3.11/site-packages/litestar/events/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/events/__pycache__/emitter.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/events/__pycache__/emitter.cpython-311.pyc
deleted file mode 100644
index f59ec24..0000000
--- a/venv/lib/python3.11/site-packages/litestar/events/__pycache__/emitter.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/events/__pycache__/listener.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/events/__pycache__/listener.cpython-311.pyc
deleted file mode 100644
index 666bcbc..0000000
--- a/venv/lib/python3.11/site-packages/litestar/events/__pycache__/listener.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/events/emitter.py b/venv/lib/python3.11/site-packages/litestar/events/emitter.py
deleted file mode 100644
index 7c33c9e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/events/emitter.py
+++ /dev/null
@@ -1,134 +0,0 @@
-from __future__ import annotations
-
-import math
-import sys
-from abc import ABC, abstractmethod
-from collections import defaultdict
-from contextlib import AsyncExitStack
-from functools import partial
-from typing import TYPE_CHECKING, Any, Sequence
-
-if sys.version_info < (3, 9):
- from typing import AsyncContextManager
-else:
- from contextlib import AbstractAsyncContextManager as AsyncContextManager
-
-import anyio
-
-from litestar.exceptions import ImproperlyConfiguredException
-
-if TYPE_CHECKING:
- from types import TracebackType
-
- from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
-
- from litestar.events.listener import EventListener
-
-__all__ = ("BaseEventEmitterBackend", "SimpleEventEmitter")
-
-
-class BaseEventEmitterBackend(AsyncContextManager["BaseEventEmitterBackend"], ABC):
- """Abstract class used to define event emitter backends."""
-
- __slots__ = ("listeners",)
-
- listeners: defaultdict[str, set[EventListener]]
-
- def __init__(self, listeners: Sequence[EventListener]) -> None:
- """Create an event emitter instance.
-
- Args:
- listeners: A list of listeners.
- """
- self.listeners = defaultdict(set)
- for listener in listeners:
- for event_id in listener.event_ids:
- self.listeners[event_id].add(listener)
-
- @abstractmethod
- def emit(self, event_id: str, *args: Any, **kwargs: Any) -> None:
- """Emit an event to all attached listeners.
-
- Args:
- event_id: The ID of the event to emit, e.g 'my_event'.
- *args: args to pass to the listener(s).
- **kwargs: kwargs to pass to the listener(s)
-
- Returns:
- None
- """
- raise NotImplementedError("not implemented")
-
-
-class SimpleEventEmitter(BaseEventEmitterBackend):
- """Event emitter the works only in the current process"""
-
- __slots__ = ("_queue", "_exit_stack", "_receive_stream", "_send_stream")
-
- def __init__(self, listeners: Sequence[EventListener]) -> None:
- """Create an event emitter instance.
-
- Args:
- listeners: A list of listeners.
- """
- super().__init__(listeners=listeners)
- self._receive_stream: MemoryObjectReceiveStream | None = None
- self._send_stream: MemoryObjectSendStream | None = None
- self._exit_stack: AsyncExitStack | None = None
-
- async def _worker(self, receive_stream: MemoryObjectReceiveStream) -> None:
- """Run items from ``receive_stream`` in a task group.
-
- Returns:
- None
- """
- async with receive_stream, anyio.create_task_group() as task_group:
- async for item in receive_stream:
- fn, args, kwargs = item
- if kwargs:
- fn = partial(fn, **kwargs)
- task_group.start_soon(fn, *args) # pyright: ignore[reportGeneralTypeIssues]
-
- async def __aenter__(self) -> SimpleEventEmitter:
- self._exit_stack = AsyncExitStack()
- send_stream, receive_stream = anyio.create_memory_object_stream(math.inf) # type: ignore[var-annotated]
- self._send_stream = send_stream
- task_group = anyio.create_task_group()
-
- await self._exit_stack.enter_async_context(task_group)
- await self._exit_stack.enter_async_context(send_stream)
- task_group.start_soon(self._worker, receive_stream)
-
- return self
-
- async def __aexit__(
- self,
- exc_type: type[BaseException] | None,
- exc_val: BaseException | None,
- exc_tb: TracebackType | None,
- ) -> None:
- if self._exit_stack:
- await self._exit_stack.__aexit__(exc_type, exc_val, exc_tb)
-
- self._exit_stack = None
- self._send_stream = None
-
- def emit(self, event_id: str, *args: Any, **kwargs: Any) -> None:
- """Emit an event to all attached listeners.
-
- Args:
- event_id: The ID of the event to emit, e.g 'my_event'.
- *args: args to pass to the listener(s).
- **kwargs: kwargs to pass to the listener(s)
-
- Returns:
- None
- """
- if not (self._send_stream and self._exit_stack):
- raise RuntimeError("Emitter not initialized")
-
- if listeners := self.listeners.get(event_id):
- for listener in listeners:
- self._send_stream.send_nowait((listener.fn, args, kwargs))
- return
- raise ImproperlyConfiguredException(f"no event listeners are registered for event ID: {event_id}")
diff --git a/venv/lib/python3.11/site-packages/litestar/events/listener.py b/venv/lib/python3.11/site-packages/litestar/events/listener.py
deleted file mode 100644
index 63c9848..0000000
--- a/venv/lib/python3.11/site-packages/litestar/events/listener.py
+++ /dev/null
@@ -1,76 +0,0 @@
-from __future__ import annotations
-
-import logging
-from typing import TYPE_CHECKING, Any
-
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.utils import ensure_async_callable
-
-if TYPE_CHECKING:
- from litestar.types import AnyCallable, AsyncAnyCallable
-
-__all__ = ("EventListener", "listener")
-
-logger = logging.getLogger(__name__)
-
-
-class EventListener:
- """Decorator for event listeners"""
-
- __slots__ = ("event_ids", "fn", "listener_id")
-
- fn: AsyncAnyCallable
-
- def __init__(self, *event_ids: str) -> None:
- """Create a decorator for event handlers.
-
- Args:
- *event_ids: The id of the event to listen to or a list of
- event ids to listen to.
- """
- self.event_ids: frozenset[str] = frozenset(event_ids)
-
- def __call__(self, fn: AnyCallable) -> EventListener:
- """Decorate a callable by wrapping it inside an instance of EventListener.
-
- Args:
- fn: Callable to decorate.
-
- Returns:
- An instance of EventListener
- """
- if not callable(fn):
- raise ImproperlyConfiguredException("EventListener instance should be called as a decorator on a callable")
-
- self.fn = self.wrap_in_error_handler(ensure_async_callable(fn))
-
- return self
-
- @staticmethod
- def wrap_in_error_handler(fn: AsyncAnyCallable) -> AsyncAnyCallable:
- """Wrap a listener function to handle errors.
-
- Listeners are executed concurrently in a TaskGroup, so we need to ensure that exceptions do not propagate
- to the task group which results in any other unfinished listeners to be cancelled, and the receive stream to
- be closed.
-
- See https://github.com/litestar-org/litestar/issues/2809
-
- Args:
- fn: The listener function to wrap.
- """
-
- async def wrapped(*args: Any, **kwargs: Any) -> None:
- """Wrap a listener function to handle errors."""
- try:
- await fn(*args, **kwargs)
- except Exception as exc:
- logger.exception("Error while executing listener %s: %s", fn.__name__, exc)
-
- return wrapped
-
- def __hash__(self) -> int:
- return hash(self.event_ids) + hash(self.fn)
-
-
-listener = EventListener
diff --git a/venv/lib/python3.11/site-packages/litestar/exceptions/__init__.py b/venv/lib/python3.11/site-packages/litestar/exceptions/__init__.py
deleted file mode 100644
index 09065c8..0000000
--- a/venv/lib/python3.11/site-packages/litestar/exceptions/__init__.py
+++ /dev/null
@@ -1,42 +0,0 @@
-from .base_exceptions import LitestarException, LitestarWarning, MissingDependencyException, SerializationException
-from .dto_exceptions import DTOFactoryException, InvalidAnnotationException
-from .http_exceptions import (
- ClientException,
- HTTPException,
- ImproperlyConfiguredException,
- InternalServerException,
- MethodNotAllowedException,
- NoRouteMatchFoundException,
- NotAuthorizedException,
- NotFoundException,
- PermissionDeniedException,
- ServiceUnavailableException,
- TemplateNotFoundException,
- TooManyRequestsException,
- ValidationException,
-)
-from .websocket_exceptions import WebSocketDisconnect, WebSocketException
-
-__all__ = (
- "ClientException",
- "DTOFactoryException",
- "HTTPException",
- "ImproperlyConfiguredException",
- "InternalServerException",
- "InvalidAnnotationException",
- "LitestarException",
- "LitestarWarning",
- "MethodNotAllowedException",
- "MissingDependencyException",
- "NoRouteMatchFoundException",
- "NotAuthorizedException",
- "NotFoundException",
- "PermissionDeniedException",
- "SerializationException",
- "ServiceUnavailableException",
- "TemplateNotFoundException",
- "TooManyRequestsException",
- "ValidationException",
- "WebSocketDisconnect",
- "WebSocketException",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 1538618..0000000
--- a/venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/base_exceptions.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/base_exceptions.cpython-311.pyc
deleted file mode 100644
index efd605d..0000000
--- a/venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/base_exceptions.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/dto_exceptions.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/dto_exceptions.cpython-311.pyc
deleted file mode 100644
index 24633ee..0000000
--- a/venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/dto_exceptions.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/http_exceptions.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/http_exceptions.cpython-311.pyc
deleted file mode 100644
index 76176d4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/http_exceptions.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/websocket_exceptions.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/websocket_exceptions.cpython-311.pyc
deleted file mode 100644
index 90c2ce2..0000000
--- a/venv/lib/python3.11/site-packages/litestar/exceptions/__pycache__/websocket_exceptions.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/exceptions/base_exceptions.py b/venv/lib/python3.11/site-packages/litestar/exceptions/base_exceptions.py
deleted file mode 100644
index bbd4040..0000000
--- a/venv/lib/python3.11/site-packages/litestar/exceptions/base_exceptions.py
+++ /dev/null
@@ -1,57 +0,0 @@
-from __future__ import annotations
-
-from typing import Any
-
-__all__ = ("MissingDependencyException", "SerializationException", "LitestarException", "LitestarWarning")
-
-
-class LitestarException(Exception):
- """Base exception class from which all Litestar exceptions inherit."""
-
- detail: str
-
- def __init__(self, *args: Any, detail: str = "") -> None:
- """Initialize ``LitestarException``.
-
- Args:
- *args: args are converted to :class:`str` before passing to :class:`Exception`
- detail: detail of the exception.
- """
- str_args = [str(arg) for arg in args if arg]
- if not detail:
- if str_args:
- detail, *str_args = str_args
- elif hasattr(self, "detail"):
- detail = self.detail
- self.detail = detail
- super().__init__(*str_args)
-
- def __repr__(self) -> str:
- if self.detail:
- return f"{self.__class__.__name__} - {self.detail}"
- return self.__class__.__name__
-
- def __str__(self) -> str:
- return " ".join((*self.args, self.detail)).strip()
-
-
-class MissingDependencyException(LitestarException, ImportError):
- """Missing optional dependency.
-
- This exception is raised only when a module depends on a dependency that has not been installed.
- """
-
- def __init__(self, package: str, install_package: str | None = None, extra: str | None = None) -> None:
- super().__init__(
- f"Package {package!r} is not installed but required. You can install it by running "
- f"'pip install litestar[{extra or install_package or package}]' to install litestar with the required extra "
- f"or 'pip install {install_package or package}' to install the package separately"
- )
-
-
-class SerializationException(LitestarException):
- """Encoding or decoding of an object failed."""
-
-
-class LitestarWarning(UserWarning):
- """Base class for Litestar warnings"""
diff --git a/venv/lib/python3.11/site-packages/litestar/exceptions/dto_exceptions.py b/venv/lib/python3.11/site-packages/litestar/exceptions/dto_exceptions.py
deleted file mode 100644
index 037e3c6..0000000
--- a/venv/lib/python3.11/site-packages/litestar/exceptions/dto_exceptions.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import annotations
-
-from litestar.exceptions import LitestarException
-
-__all__ = ("DTOFactoryException", "InvalidAnnotationException")
-
-
-class DTOFactoryException(LitestarException):
- """Base DTO exception type."""
-
-
-class InvalidAnnotationException(DTOFactoryException):
- """Unexpected DTO type argument."""
diff --git a/venv/lib/python3.11/site-packages/litestar/exceptions/http_exceptions.py b/venv/lib/python3.11/site-packages/litestar/exceptions/http_exceptions.py
deleted file mode 100644
index bd384c3..0000000
--- a/venv/lib/python3.11/site-packages/litestar/exceptions/http_exceptions.py
+++ /dev/null
@@ -1,154 +0,0 @@
-from __future__ import annotations
-
-from http import HTTPStatus
-from typing import Any
-
-from litestar.exceptions.base_exceptions import LitestarException
-from litestar.status_codes import (
- HTTP_400_BAD_REQUEST,
- HTTP_401_UNAUTHORIZED,
- HTTP_403_FORBIDDEN,
- HTTP_404_NOT_FOUND,
- HTTP_405_METHOD_NOT_ALLOWED,
- HTTP_429_TOO_MANY_REQUESTS,
- HTTP_500_INTERNAL_SERVER_ERROR,
- HTTP_503_SERVICE_UNAVAILABLE,
-)
-
-__all__ = (
- "ClientException",
- "HTTPException",
- "ImproperlyConfiguredException",
- "InternalServerException",
- "MethodNotAllowedException",
- "NoRouteMatchFoundException",
- "NotAuthorizedException",
- "NotFoundException",
- "PermissionDeniedException",
- "ServiceUnavailableException",
- "TemplateNotFoundException",
- "TooManyRequestsException",
- "ValidationException",
-)
-
-
-class HTTPException(LitestarException):
- """Base exception for HTTP error responses.
-
- These exceptions carry information to construct an HTTP response.
- """
-
- status_code: int = HTTP_500_INTERNAL_SERVER_ERROR
- """Exception status code."""
- detail: str
- """Exception details or message."""
- headers: dict[str, str] | None
- """Headers to attach to the response."""
- extra: dict[str, Any] | list[Any] | None
- """An extra mapping to attach to the exception."""
-
- def __init__(
- self,
- *args: Any,
- detail: str = "",
- status_code: int | None = None,
- headers: dict[str, str] | None = None,
- extra: dict[str, Any] | list[Any] | None = None,
- ) -> None:
- """Initialize ``HTTPException``.
-
- Set ``detail`` and ``args`` if not provided.
-
- Args:
- *args: if ``detail`` kwarg not provided, first arg should be error detail.
- detail: Exception details or message. Will default to args[0] if not provided.
- status_code: Exception HTTP status code.
- headers: Headers to set on the response.
- extra: An extra mapping to attach to the exception.
- """
- super().__init__(*args, detail=detail)
- self.status_code = status_code or self.status_code
- self.extra = extra
- self.headers = headers
- if not self.detail:
- self.detail = HTTPStatus(self.status_code).phrase
- self.args = (f"{self.status_code}: {self.detail}", *self.args)
-
- def __repr__(self) -> str:
- return f"{self.status_code} - {self.__class__.__name__} - {self.detail}"
-
- def __str__(self) -> str:
- return " ".join(self.args).strip()
-
-
-class ImproperlyConfiguredException(HTTPException, ValueError):
- """Application has improper configuration."""
-
-
-class ClientException(HTTPException):
- """Client error."""
-
- status_code: int = HTTP_400_BAD_REQUEST
-
-
-class ValidationException(ClientException, ValueError):
- """Client data validation error."""
-
-
-class NotAuthorizedException(ClientException):
- """Request lacks valid authentication credentials for the requested resource."""
-
- status_code = HTTP_401_UNAUTHORIZED
-
-
-class PermissionDeniedException(ClientException):
- """Request understood, but not authorized."""
-
- status_code = HTTP_403_FORBIDDEN
-
-
-class NotFoundException(ClientException, ValueError):
- """Cannot find the requested resource."""
-
- status_code = HTTP_404_NOT_FOUND
-
-
-class MethodNotAllowedException(ClientException):
- """Server knows the request method, but the target resource doesn't support this method."""
-
- status_code = HTTP_405_METHOD_NOT_ALLOWED
-
-
-class TooManyRequestsException(ClientException):
- """Request limits have been exceeded."""
-
- status_code = HTTP_429_TOO_MANY_REQUESTS
-
-
-class InternalServerException(HTTPException):
- """Server encountered an unexpected condition that prevented it from fulfilling the request."""
-
- status_code: int = HTTP_500_INTERNAL_SERVER_ERROR
-
-
-class ServiceUnavailableException(InternalServerException):
- """Server is not ready to handle the request."""
-
- status_code = HTTP_503_SERVICE_UNAVAILABLE
-
-
-class NoRouteMatchFoundException(InternalServerException):
- """A route with the given name could not be found."""
-
-
-class TemplateNotFoundException(InternalServerException):
- """Referenced template could not be found."""
-
- def __init__(self, *args: Any, template_name: str) -> None:
- """Initialize ``TemplateNotFoundException``.
-
- Args:
- *args (Any): Passed through to ``super().__init__()`` - should not include ``detail``.
- template_name (str): Name of template that could not be found.
- """
- super().__init__(*args, detail=f"Template {template_name} not found.")
diff --git a/venv/lib/python3.11/site-packages/litestar/exceptions/websocket_exceptions.py b/venv/lib/python3.11/site-packages/litestar/exceptions/websocket_exceptions.py
deleted file mode 100644
index 2fed9ca..0000000
--- a/venv/lib/python3.11/site-packages/litestar/exceptions/websocket_exceptions.py
+++ /dev/null
@@ -1,40 +0,0 @@
-from typing import Any
-
-from litestar.exceptions.base_exceptions import LitestarException
-from litestar.status_codes import WS_1000_NORMAL_CLOSURE
-
-__all__ = ("WebSocketDisconnect", "WebSocketException")
-
-
-class WebSocketException(LitestarException):
- """Exception class for websocket related events."""
-
- code: int
- """Exception code. For custom exceptions, this should be a number in the 4000+ range. Other codes can be found in
- ``litestar.status_code`` with the ``WS_`` prefix.
- """
-
- def __init__(self, *args: Any, detail: str, code: int = 4500) -> None:
- """Initialize ``WebSocketException``.
-
- Args:
- *args: Any exception args.
- detail: Exception details.
- code: Exception code. Should be a number in the >= 1000.
- """
- super().__init__(*args, detail=detail)
- self.code = code
-
-
-class WebSocketDisconnect(WebSocketException):
- """Exception class for websocket disconnect events."""
-
- def __init__(self, *args: Any, detail: str, code: int = WS_1000_NORMAL_CLOSURE) -> None:
- """Initialize ``WebSocketDisconnect``.
-
- Args:
- *args: Any exception args.
- detail: Exception details.
- code: Exception code. Should be a number in the >= 1000.
- """
- super().__init__(*args, detail=detail, code=code)
diff --git a/venv/lib/python3.11/site-packages/litestar/file_system.py b/venv/lib/python3.11/site-packages/litestar/file_system.py
deleted file mode 100644
index fcb77c7..0000000
--- a/venv/lib/python3.11/site-packages/litestar/file_system.py
+++ /dev/null
@@ -1,154 +0,0 @@
-from __future__ import annotations
-
-from stat import S_ISDIR
-from typing import TYPE_CHECKING, Any, AnyStr, cast
-
-from anyio import AsyncFile, Path, open_file
-
-from litestar.concurrency import sync_to_thread
-from litestar.exceptions import InternalServerException, NotAuthorizedException
-from litestar.types.file_types import FileSystemProtocol
-from litestar.utils.predicates import is_async_callable
-
-__all__ = ("BaseLocalFileSystem", "FileSystemAdapter")
-
-
-if TYPE_CHECKING:
- from os import stat_result
-
- from _typeshed import OpenBinaryMode
-
- from litestar.types import PathType
- from litestar.types.file_types import FileInfo
-
-
-class BaseLocalFileSystem(FileSystemProtocol):
- """Base class for a local file system."""
-
- async def info(self, path: PathType, **kwargs: Any) -> FileInfo:
- """Retrieve information about a given file path.
-
- Args:
- path: A file path.
- **kwargs: Any additional kwargs.
-
- Returns:
- A dictionary of file info.
- """
- result = await Path(path).stat()
- return await FileSystemAdapter.parse_stat_result(path=path, result=result)
-
- async def open(self, file: PathType, mode: str, buffering: int = -1) -> AsyncFile[AnyStr]: # pyright: ignore
- """Return a file-like object from the filesystem.
-
- Notes:
- - The return value must be a context-manager
-
- Args:
- file: Path to the target file.
- mode: Mode, similar to the built ``open``.
- buffering: Buffer size.
- """
- return await open_file(file=file, mode=mode, buffering=buffering) # type: ignore[call-overload, no-any-return]
-
-
-class FileSystemAdapter:
- """Wrapper around a ``FileSystemProtocol``, normalising its interface."""
-
- def __init__(self, file_system: FileSystemProtocol) -> None:
- """Initialize an adapter from a given ``file_system``
-
- Args:
- file_system: A filesystem class adhering to the :class:`FileSystemProtocol <litestar.types.FileSystemProtocol>`
- """
- self.file_system = file_system
-
- async def info(self, path: PathType) -> FileInfo:
- """Proxies the call to the underlying FS Spec's ``info`` method, ensuring it's done in an async fashion and with
- strong typing.
-
- Args:
- path: A file path to load the info for.
-
- Returns:
- A dictionary of file info.
- """
- try:
- awaitable = (
- self.file_system.info(str(path))
- if is_async_callable(self.file_system.info)
- else sync_to_thread(self.file_system.info, str(path))
- )
- return cast("FileInfo", await awaitable)
- except FileNotFoundError as e:
- raise e
- except PermissionError as e:
- raise NotAuthorizedException(f"failed to read {path} due to missing permissions") from e
- except OSError as e: # pragma: no cover
- raise InternalServerException from e
-
- async def open(
- self,
- file: PathType,
- mode: OpenBinaryMode = "rb",
- buffering: int = -1,
- ) -> AsyncFile[bytes]:
- """Return a file-like object from the filesystem.
-
- Notes:
- - The return value must function correctly in a context ``with`` block.
-
- Args:
- file: Path to the target file.
- mode: Mode, similar to the built ``open``.
- buffering: Buffer size.
- """
- try:
- if is_async_callable(self.file_system.open): # pyright: ignore
- return cast(
- "AsyncFile[bytes]",
- await self.file_system.open(
- file=file,
- mode=mode,
- buffering=buffering,
- ),
- )
- return AsyncFile(await sync_to_thread(self.file_system.open, file, mode, buffering)) # type: ignore[arg-type]
- except PermissionError as e:
- raise NotAuthorizedException(f"failed to open {file} due to missing permissions") from e
- except OSError as e:
- raise InternalServerException from e
-
- @staticmethod
- async def parse_stat_result(path: PathType, result: stat_result) -> FileInfo:
- """Convert a ``stat_result`` instance into a ``FileInfo``.
-
- Args:
- path: The file path for which the :func:`stat_result <os.stat_result>` is provided.
- result: The :func:`stat_result <os.stat_result>` instance.
-
- Returns:
- A dictionary of file info.
- """
- file_info: FileInfo = {
- "created": result.st_ctime,
- "gid": result.st_gid,
- "ino": result.st_ino,
- "islink": await Path(path).is_symlink(),
- "mode": result.st_mode,
- "mtime": result.st_mtime,
- "name": str(path),
- "nlink": result.st_nlink,
- "size": result.st_size,
- "type": "directory" if S_ISDIR(result.st_mode) else "file",
- "uid": result.st_uid,
- }
-
- if file_info["islink"]:
- file_info["destination"] = str(await Path(path).readlink()).encode("utf-8")
- try:
- file_info["size"] = (await Path(path).stat()).st_size
- except OSError: # pragma: no cover
- file_info["size"] = result.st_size
-
- return file_info
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/__init__.py b/venv/lib/python3.11/site-packages/litestar/handlers/__init__.py
deleted file mode 100644
index 822fe7e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/__init__.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from .asgi_handlers import ASGIRouteHandler, asgi
-from .base import BaseRouteHandler
-from .http_handlers import HTTPRouteHandler, delete, get, head, patch, post, put, route
-from .websocket_handlers import (
- WebsocketListener,
- WebsocketListenerRouteHandler,
- WebsocketRouteHandler,
- websocket,
- websocket_listener,
-)
-
-__all__ = (
- "ASGIRouteHandler",
- "BaseRouteHandler",
- "HTTPRouteHandler",
- "WebsocketListener",
- "WebsocketRouteHandler",
- "WebsocketListenerRouteHandler",
- "asgi",
- "delete",
- "get",
- "head",
- "patch",
- "post",
- "put",
- "route",
- "websocket",
- "websocket_listener",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 6976d76..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/asgi_handlers.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/asgi_handlers.cpython-311.pyc
deleted file mode 100644
index 85de8f8..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/asgi_handlers.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/base.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/base.cpython-311.pyc
deleted file mode 100644
index 2331fc7..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/__pycache__/base.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/asgi_handlers.py b/venv/lib/python3.11/site-packages/litestar/handlers/asgi_handlers.py
deleted file mode 100644
index 91f3517..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/asgi_handlers.py
+++ /dev/null
@@ -1,90 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any, Mapping, Sequence
-
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.handlers.base import BaseRouteHandler
-from litestar.types.builtin_types import NoneType
-from litestar.utils.predicates import is_async_callable
-
-__all__ = ("ASGIRouteHandler", "asgi")
-
-
-if TYPE_CHECKING:
- from litestar.types import (
- ExceptionHandlersMap,
- Guard,
- MaybePartial, # noqa: F401
- )
-
-
-class ASGIRouteHandler(BaseRouteHandler):
- """ASGI Route Handler decorator.
-
- Use this decorator to decorate ASGI applications.
- """
-
- __slots__ = ("is_mount", "is_static")
-
- def __init__(
- self,
- path: str | Sequence[str] | None = None,
- *,
- exception_handlers: ExceptionHandlersMap | None = None,
- guards: Sequence[Guard] | None = None,
- name: str | None = None,
- opt: Mapping[str, Any] | None = None,
- is_mount: bool = False,
- is_static: bool = False,
- signature_namespace: Mapping[str, Any] | None = None,
- **kwargs: Any,
- ) -> None:
- """Initialize ``ASGIRouteHandler``.
-
- Args:
- exception_handlers: A mapping of status codes and/or exception types to handler functions.
- guards: A sequence of :class:`Guard <.types.Guard>` callables.
- name: A string identifying the route handler.
- opt: A string key mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or
- wherever you have access to :class:`Request <.connection.Request>` or
- :class:`ASGI Scope <.types.Scope>`.
- path: A path fragment for the route handler function or a list of path fragments. If not given defaults to
- ``/``
- is_mount: A boolean dictating whether the handler's paths should be regarded as mount paths. Mount path
- accept any arbitrary paths that begin with the defined prefixed path. For example, a mount with the path
- ``/some-path/`` will accept requests for ``/some-path/`` and any sub path under this, e.g.
- ``/some-path/sub-path/`` etc.
- is_static: A boolean dictating whether the handler's paths should be regarded as static paths. Static paths
- are used to deliver static files.
- signature_namespace: A mapping of names to types for use in forward reference resolution during signature modelling.
- type_encoders: A mapping of types to callables that transform them into types supported for serialization.
- **kwargs: Any additional kwarg - will be set in the opt dictionary.
- """
- self.is_mount = is_mount or is_static
- self.is_static = is_static
- super().__init__(
- path,
- exception_handlers=exception_handlers,
- guards=guards,
- name=name,
- opt=opt,
- signature_namespace=signature_namespace,
- **kwargs,
- )
-
- def _validate_handler_function(self) -> None:
- """Validate the route handler function once it's set by inspecting its return annotations."""
- super()._validate_handler_function()
-
- if not self.parsed_fn_signature.return_type.is_subclass_of(NoneType):
- raise ImproperlyConfiguredException("ASGI handler functions should return 'None'")
-
- if any(key not in self.parsed_fn_signature.parameters for key in ("scope", "send", "receive")):
- raise ImproperlyConfiguredException(
- "ASGI handler functions should define 'scope', 'send' and 'receive' arguments"
- )
- if not is_async_callable(self.fn):
- raise ImproperlyConfiguredException("Functions decorated with 'asgi' must be async functions")
-
-
-asgi = ASGIRouteHandler
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/base.py b/venv/lib/python3.11/site-packages/litestar/handlers/base.py
deleted file mode 100644
index 9dbb70e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/base.py
+++ /dev/null
@@ -1,577 +0,0 @@
-from __future__ import annotations
-
-from copy import copy
-from functools import partial
-from typing import TYPE_CHECKING, Any, Callable, Mapping, Sequence, cast
-
-from litestar._signature import SignatureModel
-from litestar.config.app import ExperimentalFeatures
-from litestar.di import Provide
-from litestar.dto import DTOData
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.plugins import DIPlugin, PluginRegistry
-from litestar.serialization import default_deserializer, default_serializer
-from litestar.types import (
- Dependencies,
- Empty,
- ExceptionHandlersMap,
- Guard,
- Middleware,
- TypeDecodersSequence,
- TypeEncodersMap,
-)
-from litestar.typing import FieldDefinition
-from litestar.utils import ensure_async_callable, get_name, normalize_path
-from litestar.utils.helpers import unwrap_partial
-from litestar.utils.signature import ParsedSignature, add_types_to_signature_namespace
-
-if TYPE_CHECKING:
- from typing_extensions import Self
-
- from litestar.app import Litestar
- from litestar.connection import ASGIConnection
- from litestar.controller import Controller
- from litestar.dto import AbstractDTO
- from litestar.dto._backend import DTOBackend
- from litestar.params import ParameterKwarg
- from litestar.router import Router
- from litestar.types import AnyCallable, AsyncAnyCallable, ExceptionHandler
- from litestar.types.empty import EmptyType
-
-__all__ = ("BaseRouteHandler",)
-
-
-class BaseRouteHandler:
- """Base route handler.
-
- Serves as a subclass for all route handlers
- """
-
- __slots__ = (
- "_fn",
- "_parsed_data_field",
- "_parsed_fn_signature",
- "_parsed_return_field",
- "_resolved_data_dto",
- "_resolved_dependencies",
- "_resolved_guards",
- "_resolved_layered_parameters",
- "_resolved_return_dto",
- "_resolved_signature_namespace",
- "_resolved_type_decoders",
- "_resolved_type_encoders",
- "_signature_model",
- "dependencies",
- "dto",
- "exception_handlers",
- "guards",
- "middleware",
- "name",
- "opt",
- "owner",
- "paths",
- "return_dto",
- "signature_namespace",
- "type_decoders",
- "type_encoders",
- )
-
- def __init__(
- self,
- path: str | Sequence[str] | None = None,
- *,
- dependencies: Dependencies | None = None,
- dto: type[AbstractDTO] | None | EmptyType = Empty,
- exception_handlers: ExceptionHandlersMap | None = None,
- guards: Sequence[Guard] | None = None,
- middleware: Sequence[Middleware] | None = None,
- name: str | None = None,
- opt: Mapping[str, Any] | None = None,
- return_dto: type[AbstractDTO] | None | EmptyType = Empty,
- signature_namespace: Mapping[str, Any] | None = None,
- signature_types: Sequence[Any] | None = None,
- type_decoders: TypeDecodersSequence | None = None,
- type_encoders: TypeEncodersMap | None = None,
- **kwargs: Any,
- ) -> None:
- """Initialize ``HTTPRouteHandler``.
-
- Args:
- path: A path fragment for the route handler function or a sequence of path fragments. If not given defaults
- to ``/``
- dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances.
- dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and
- validation of request data.
- exception_handlers: A mapping of status codes and/or exception types to handler functions.
- guards: A sequence of :class:`Guard <.types.Guard>` callables.
- middleware: A sequence of :class:`Middleware <.types.Middleware>`.
- name: A string identifying the route handler.
- opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or
- wherever you have access to :class:`Request <.connection.Request>` or
- :class:`ASGI Scope <.types.Scope>`.
- return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing
- outbound response data.
- signature_namespace: A mapping of names to types for use in forward reference resolution during signature
- modelling.
- signature_types: A sequence of types for use in forward reference resolution during signature modeling.
- These types will be added to the signature namespace using their ``__name__`` attribute.
- type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec hook for deserialization.
- type_encoders: A mapping of types to callables that transform them into types supported for serialization.
- **kwargs: Any additional kwarg - will be set in the opt dictionary.
- """
- self._parsed_fn_signature: ParsedSignature | EmptyType = Empty
- self._parsed_return_field: FieldDefinition | EmptyType = Empty
- self._parsed_data_field: FieldDefinition | None | EmptyType = Empty
- self._resolved_data_dto: type[AbstractDTO] | None | EmptyType = Empty
- self._resolved_dependencies: dict[str, Provide] | EmptyType = Empty
- self._resolved_guards: list[Guard] | EmptyType = Empty
- self._resolved_layered_parameters: dict[str, FieldDefinition] | EmptyType = Empty
- self._resolved_return_dto: type[AbstractDTO] | None | EmptyType = Empty
- self._resolved_signature_namespace: dict[str, Any] | EmptyType = Empty
- self._resolved_type_decoders: TypeDecodersSequence | EmptyType = Empty
- self._resolved_type_encoders: TypeEncodersMap | EmptyType = Empty
- self._signature_model: type[SignatureModel] | EmptyType = Empty
-
- self.dependencies = dependencies
- self.dto = dto
- self.exception_handlers = exception_handlers
- self.guards = guards
- self.middleware = middleware
- self.name = name
- self.opt = dict(opt or {})
- self.opt.update(**kwargs)
- self.owner: Controller | Router | None = None
- self.return_dto = return_dto
- self.signature_namespace = add_types_to_signature_namespace(
- signature_types or [], dict(signature_namespace or {})
- )
- self.type_decoders = type_decoders
- self.type_encoders = type_encoders
-
- self.paths = (
- {normalize_path(p) for p in path} if path and isinstance(path, list) else {normalize_path(path or "/")} # type: ignore[arg-type]
- )
-
- def __call__(self, fn: AsyncAnyCallable) -> Self:
- """Replace a function with itself."""
- self._fn = fn
- return self
-
- @property
- def handler_id(self) -> str:
- """A unique identifier used for generation of DTOs."""
- return f"{self!s}::{sum(id(layer) for layer in self.ownership_layers)}"
-
- @property
- def default_deserializer(self) -> Callable[[Any, Any], Any]:
- """Get a default deserializer for the route handler.
-
- Returns:
- A default deserializer for the route handler.
-
- """
- return partial(default_deserializer, type_decoders=self.resolve_type_decoders())
-
- @property
- def default_serializer(self) -> Callable[[Any], Any]:
- """Get a default serializer for the route handler.
-
- Returns:
- A default serializer for the route handler.
-
- """
- return partial(default_serializer, type_encoders=self.resolve_type_encoders())
-
- @property
- def signature_model(self) -> type[SignatureModel]:
- """Get the signature model for the route handler.
-
- Returns:
- A signature model for the route handler.
-
- """
- if self._signature_model is Empty:
- self._signature_model = SignatureModel.create(
- dependency_name_set=self.dependency_name_set,
- fn=cast("AnyCallable", self.fn),
- parsed_signature=self.parsed_fn_signature,
- data_dto=self.resolve_data_dto(),
- type_decoders=self.resolve_type_decoders(),
- )
- return self._signature_model
-
- @property
- def fn(self) -> AsyncAnyCallable:
- """Get the handler function.
-
- Raises:
- ImproperlyConfiguredException: if handler fn is not set.
-
- Returns:
- Handler function
- """
- if not hasattr(self, "_fn"):
- raise ImproperlyConfiguredException("No callable has been registered for this handler")
- return self._fn
-
- @property
- def parsed_fn_signature(self) -> ParsedSignature:
- """Return the parsed signature of the handler function.
-
- This method is memoized so the computation occurs only once.
-
- Returns:
- A ParsedSignature instance
- """
- if self._parsed_fn_signature is Empty:
- self._parsed_fn_signature = ParsedSignature.from_fn(
- unwrap_partial(self.fn), self.resolve_signature_namespace()
- )
-
- return self._parsed_fn_signature
-
- @property
- def parsed_return_field(self) -> FieldDefinition:
- if self._parsed_return_field is Empty:
- self._parsed_return_field = self.parsed_fn_signature.return_type
- return self._parsed_return_field
-
- @property
- def parsed_data_field(self) -> FieldDefinition | None:
- if self._parsed_data_field is Empty:
- self._parsed_data_field = self.parsed_fn_signature.parameters.get("data")
- return self._parsed_data_field
-
- @property
- def handler_name(self) -> str:
- """Get the name of the handler function.
-
- Raises:
- ImproperlyConfiguredException: if handler fn is not set.
-
- Returns:
- Name of the handler function
- """
- return get_name(unwrap_partial(self.fn))
-
- @property
- def dependency_name_set(self) -> set[str]:
- """Set of all dependency names provided in the handler's ownership layers."""
- layered_dependencies = (layer.dependencies or {} for layer in self.ownership_layers)
- return {name for layer in layered_dependencies for name in layer} # pyright: ignore
-
- @property
- def ownership_layers(self) -> list[Self | Controller | Router]:
- """Return the handler layers from the app down to the route handler.
-
- ``app -> ... -> route handler``
- """
- layers = []
-
- cur: Any = self
- while cur:
- layers.append(cur)
- cur = cur.owner
-
- return list(reversed(layers))
-
- @property
- def app(self) -> Litestar:
- return cast("Litestar", self.ownership_layers[0])
-
- def resolve_type_encoders(self) -> TypeEncodersMap:
- """Return a merged type_encoders mapping.
-
- This method is memoized so the computation occurs only once.
-
- Returns:
- A dict of type encoders
- """
- if self._resolved_type_encoders is Empty:
- self._resolved_type_encoders = {}
-
- for layer in self.ownership_layers:
- if type_encoders := getattr(layer, "type_encoders", None):
- self._resolved_type_encoders.update(type_encoders)
- return cast("TypeEncodersMap", self._resolved_type_encoders)
-
- def resolve_type_decoders(self) -> TypeDecodersSequence:
- """Return a merged type_encoders mapping.
-
- This method is memoized so the computation occurs only once.
-
- Returns:
- A dict of type encoders
- """
- if self._resolved_type_decoders is Empty:
- self._resolved_type_decoders = []
-
- for layer in self.ownership_layers:
- if type_decoders := getattr(layer, "type_decoders", None):
- self._resolved_type_decoders.extend(list(type_decoders))
- return cast("TypeDecodersSequence", self._resolved_type_decoders)
-
- def resolve_layered_parameters(self) -> dict[str, FieldDefinition]:
- """Return all parameters declared above the handler."""
- if self._resolved_layered_parameters is Empty:
- parameter_kwargs: dict[str, ParameterKwarg] = {}
-
- for layer in self.ownership_layers:
- parameter_kwargs.update(getattr(layer, "parameters", {}) or {})
-
- self._resolved_layered_parameters = {
- key: FieldDefinition.from_kwarg(name=key, annotation=parameter.annotation, kwarg_definition=parameter)
- for key, parameter in parameter_kwargs.items()
- }
-
- return self._resolved_layered_parameters
-
- def resolve_guards(self) -> list[Guard]:
- """Return all guards in the handlers scope, starting from highest to current layer."""
- if self._resolved_guards is Empty:
- self._resolved_guards = []
-
- for layer in self.ownership_layers:
- self._resolved_guards.extend(layer.guards or []) # pyright: ignore
-
- self._resolved_guards = cast(
- "list[Guard]", [ensure_async_callable(guard) for guard in self._resolved_guards]
- )
-
- return self._resolved_guards
-
- def _get_plugin_registry(self) -> PluginRegistry | None:
- from litestar.app import Litestar
-
- root_owner = self.ownership_layers[0]
- if isinstance(root_owner, Litestar):
- return root_owner.plugins
- return None
-
- def resolve_dependencies(self) -> dict[str, Provide]:
- """Return all dependencies correlating to handler function's kwargs that exist in the handler's scope."""
- plugin_registry = self._get_plugin_registry()
- if self._resolved_dependencies is Empty:
- self._resolved_dependencies = {}
- for layer in self.ownership_layers:
- for key, provider in (layer.dependencies or {}).items():
- self._resolved_dependencies[key] = self._resolve_dependency(
- key=key, provider=provider, plugin_registry=plugin_registry
- )
-
- return self._resolved_dependencies
-
- def _resolve_dependency(
- self, key: str, provider: Provide | AnyCallable, plugin_registry: PluginRegistry | None
- ) -> Provide:
- if not isinstance(provider, Provide):
- provider = Provide(provider)
-
- if self._resolved_dependencies is not Empty: # pragma: no cover
- self._validate_dependency_is_unique(dependencies=self._resolved_dependencies, key=key, provider=provider)
-
- if not getattr(provider, "parsed_fn_signature", None):
- dependency = unwrap_partial(provider.dependency)
- plugin: DIPlugin | None = None
- if plugin_registry:
- plugin = next(
- (p for p in plugin_registry.di if isinstance(p, DIPlugin) and p.has_typed_init(dependency)),
- None,
- )
- if plugin:
- signature, init_type_hints = plugin.get_typed_init(dependency)
- provider.parsed_fn_signature = ParsedSignature.from_signature(signature, init_type_hints)
- else:
- provider.parsed_fn_signature = ParsedSignature.from_fn(dependency, self.resolve_signature_namespace())
-
- if not getattr(provider, "signature_model", None):
- provider.signature_model = SignatureModel.create(
- dependency_name_set=self.dependency_name_set,
- fn=provider.dependency,
- parsed_signature=provider.parsed_fn_signature,
- data_dto=self.resolve_data_dto(),
- type_decoders=self.resolve_type_decoders(),
- )
- return provider
-
- def resolve_middleware(self) -> list[Middleware]:
- """Build the middleware stack for the RouteHandler and return it.
-
- The middlewares are added from top to bottom (``app -> router -> controller -> route handler``) and then
- reversed.
- """
- resolved_middleware: list[Middleware] = []
- for layer in self.ownership_layers:
- resolved_middleware.extend(layer.middleware or []) # pyright: ignore
- return list(reversed(resolved_middleware))
-
- def resolve_exception_handlers(self) -> ExceptionHandlersMap:
- """Resolve the exception_handlers by starting from the route handler and moving up.
-
- This method is memoized so the computation occurs only once.
- """
- resolved_exception_handlers: dict[int | type[Exception], ExceptionHandler] = {}
- for layer in self.ownership_layers:
- resolved_exception_handlers.update(layer.exception_handlers or {}) # pyright: ignore
- return resolved_exception_handlers
-
- def resolve_opts(self) -> None:
- """Build the route handler opt dictionary by going from top to bottom.
-
- When merging keys from multiple layers, if the same key is defined by multiple layers, the value from the
- layer closest to the response handler will take precedence.
- """
-
- opt: dict[str, Any] = {}
- for layer in self.ownership_layers:
- opt.update(layer.opt or {}) # pyright: ignore
-
- self.opt = opt
-
- def resolve_signature_namespace(self) -> dict[str, Any]:
- """Build the route handler signature namespace dictionary by going from top to bottom.
-
- When merging keys from multiple layers, if the same key is defined by multiple layers, the value from the
- layer closest to the response handler will take precedence.
- """
- if self._resolved_layered_parameters is Empty:
- ns: dict[str, Any] = {}
- for layer in self.ownership_layers:
- ns.update(layer.signature_namespace)
-
- self._resolved_signature_namespace = ns
- return cast("dict[str, Any]", self._resolved_signature_namespace)
-
- def _get_dto_backend_cls(self) -> type[DTOBackend] | None:
- if ExperimentalFeatures.DTO_CODEGEN in self.app.experimental_features:
- from litestar.dto._codegen_backend import DTOCodegenBackend
-
- return DTOCodegenBackend
- return None
-
- def resolve_data_dto(self) -> type[AbstractDTO] | None:
- """Resolve the data_dto by starting from the route handler and moving up.
- If a handler is found it is returned, otherwise None is set.
- This method is memoized so the computation occurs only once.
-
- Returns:
- An optional :class:`DTO type <.dto.base_dto.AbstractDTO>`
- """
- if self._resolved_data_dto is Empty:
- if data_dtos := cast(
- "list[type[AbstractDTO] | None]",
- [layer.dto for layer in self.ownership_layers if layer.dto is not Empty],
- ):
- data_dto: type[AbstractDTO] | None = data_dtos[-1]
- elif self.parsed_data_field and (
- plugins_for_data_type := [
- plugin
- for plugin in self.app.plugins.serialization
- if self.parsed_data_field.match_predicate_recursively(plugin.supports_type)
- ]
- ):
- data_dto = plugins_for_data_type[0].create_dto_for_type(self.parsed_data_field)
- else:
- data_dto = None
-
- if self.parsed_data_field and data_dto:
- data_dto.create_for_field_definition(
- field_definition=self.parsed_data_field,
- handler_id=self.handler_id,
- backend_cls=self._get_dto_backend_cls(),
- )
-
- self._resolved_data_dto = data_dto
-
- return self._resolved_data_dto
-
- def resolve_return_dto(self) -> type[AbstractDTO] | None:
- """Resolve the return_dto by starting from the route handler and moving up.
- If a handler is found it is returned, otherwise None is set.
- This method is memoized so the computation occurs only once.
-
- Returns:
- An optional :class:`DTO type <.dto.base_dto.AbstractDTO>`
- """
- if self._resolved_return_dto is Empty:
- if return_dtos := cast(
- "list[type[AbstractDTO] | None]",
- [layer.return_dto for layer in self.ownership_layers if layer.return_dto is not Empty],
- ):
- return_dto: type[AbstractDTO] | None = return_dtos[-1]
- elif plugins_for_return_type := [
- plugin
- for plugin in self.app.plugins.serialization
- if self.parsed_return_field.match_predicate_recursively(plugin.supports_type)
- ]:
- return_dto = plugins_for_return_type[0].create_dto_for_type(self.parsed_return_field)
- else:
- return_dto = self.resolve_data_dto()
-
- if return_dto and return_dto.is_supported_model_type_field(self.parsed_return_field):
- return_dto.create_for_field_definition(
- field_definition=self.parsed_return_field,
- handler_id=self.handler_id,
- backend_cls=self._get_dto_backend_cls(),
- )
- self._resolved_return_dto = return_dto
- else:
- self._resolved_return_dto = None
-
- return self._resolved_return_dto
-
- async def authorize_connection(self, connection: ASGIConnection) -> None:
- """Ensure the connection is authorized by running all the route guards in scope."""
- for guard in self.resolve_guards():
- await guard(connection, copy(self)) # type: ignore[misc]
-
- @staticmethod
- def _validate_dependency_is_unique(dependencies: dict[str, Provide], key: str, provider: Provide) -> None:
- """Validate that a given provider has not been already defined under a different key."""
- for dependency_key, value in dependencies.items():
- if provider == value:
- raise ImproperlyConfiguredException(
- f"Provider for key {key} is already defined under the different key {dependency_key}. "
- f"If you wish to override a provider, it must have the same key."
- )
-
- def on_registration(self, app: Litestar) -> None:
- """Called once per handler when the app object is instantiated.
-
- Args:
- app: The :class:`Litestar<.app.Litestar>` app object.
-
- Returns:
- None
- """
- self._validate_handler_function()
- self.resolve_dependencies()
- self.resolve_guards()
- self.resolve_middleware()
- self.resolve_opts()
- self.resolve_data_dto()
- self.resolve_return_dto()
-
- def _validate_handler_function(self) -> None:
- """Validate the route handler function once set by inspecting its return annotations."""
- if (
- self.parsed_data_field is not None
- and self.parsed_data_field.is_subclass_of(DTOData)
- and not self.resolve_data_dto()
- ):
- raise ImproperlyConfiguredException(
- f"Handler function {self.handler_name} has a data parameter that is a subclass of DTOData but no "
- "DTO has been registered for it."
- )
-
- def __str__(self) -> str:
- """Return a unique identifier for the route handler.
-
- Returns:
- A string
- """
- target: type[AsyncAnyCallable] | AsyncAnyCallable # pyright: ignore
- target = unwrap_partial(self.fn)
- if not hasattr(target, "__qualname__"):
- target = type(target)
- return f"{target.__module__}.{target.__qualname__}"
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__init__.py b/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__init__.py
deleted file mode 100644
index 844f046..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__init__.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import annotations
-
-from .base import HTTPRouteHandler, route
-from .decorators import delete, get, head, patch, post, put
-
-__all__ = (
- "HTTPRouteHandler",
- "delete",
- "get",
- "head",
- "patch",
- "post",
- "put",
- "route",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 848ac8f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/_utils.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/_utils.cpython-311.pyc
deleted file mode 100644
index 22a7f67..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/_utils.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/base.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/base.cpython-311.pyc
deleted file mode 100644
index eb39166..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/base.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/decorators.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/decorators.cpython-311.pyc
deleted file mode 100644
index 0acd7c8..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/__pycache__/decorators.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/_utils.py b/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/_utils.py
deleted file mode 100644
index ec95145..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/_utils.py
+++ /dev/null
@@ -1,221 +0,0 @@
-from __future__ import annotations
-
-from functools import lru_cache
-from inspect import isawaitable
-from typing import TYPE_CHECKING, Any, Sequence, cast
-
-from litestar.enums import HttpMethod
-from litestar.exceptions import ValidationException
-from litestar.response import Response
-from litestar.status_codes import HTTP_200_OK, HTTP_201_CREATED, HTTP_204_NO_CONTENT
-from litestar.types.builtin_types import NoneType
-
-if TYPE_CHECKING:
- from litestar.app import Litestar
- from litestar.background_tasks import BackgroundTask, BackgroundTasks
- from litestar.connection import Request
- from litestar.datastructures import Cookie, ResponseHeader
- from litestar.types import AfterRequestHookHandler, ASGIApp, AsyncAnyCallable, Method, TypeEncodersMap
- from litestar.typing import FieldDefinition
-
-__all__ = (
- "create_data_handler",
- "create_generic_asgi_response_handler",
- "create_response_handler",
- "get_default_status_code",
- "is_empty_response_annotation",
- "normalize_headers",
- "normalize_http_method",
-)
-
-
-def create_data_handler(
- after_request: AfterRequestHookHandler | None,
- background: BackgroundTask | BackgroundTasks | None,
- cookies: frozenset[Cookie],
- headers: frozenset[ResponseHeader],
- media_type: str,
- response_class: type[Response],
- status_code: int,
- type_encoders: TypeEncodersMap | None,
-) -> AsyncAnyCallable:
- """Create a handler function for arbitrary data.
-
- Args:
- after_request: An after request handler.
- background: A background task or background tasks.
- cookies: A set of pre-defined cookies.
- headers: A set of response headers.
- media_type: The response media type.
- response_class: The response class to use.
- status_code: The response status code.
- type_encoders: A mapping of types to encoder functions.
-
- Returns:
- A handler function.
-
- """
-
- async def handler(
- data: Any,
- request: Request[Any, Any, Any],
- app: Litestar,
- **kwargs: Any,
- ) -> ASGIApp:
- if isawaitable(data):
- data = await data
-
- response = response_class(
- background=background,
- content=data,
- media_type=media_type,
- status_code=status_code,
- type_encoders=type_encoders,
- )
-
- if after_request:
- response = await after_request(response) # type: ignore[arg-type,misc]
-
- return response.to_asgi_response(app=None, request=request, headers=normalize_headers(headers), cookies=cookies) # pyright: ignore
-
- return handler
-
-
-def create_generic_asgi_response_handler(after_request: AfterRequestHookHandler | None) -> AsyncAnyCallable:
- """Create a handler function for Responses.
-
- Args:
- after_request: An after request handler.
-
- Returns:
- A handler function.
- """
-
- async def handler(data: ASGIApp, **kwargs: Any) -> ASGIApp:
- return await after_request(data) if after_request else data # type: ignore[arg-type, misc, no-any-return]
-
- return handler
-
-
-@lru_cache(1024)
-def normalize_headers(headers: frozenset[ResponseHeader]) -> dict[str, str]:
- """Given a dictionary of ResponseHeader, filter them and return a dictionary of values.
-
- Args:
- headers: A dictionary of :class:`ResponseHeader <litestar.datastructures.ResponseHeader>` values
-
- Returns:
- A string keyed dictionary of normalized values
- """
- return {
- header.name: cast("str", header.value) # we know value to be a string at this point because we validate it
- # that it's not None when initializing a header with documentation_only=True
- for header in headers
- if not header.documentation_only
- }
-
-
-def create_response_handler(
- after_request: AfterRequestHookHandler | None,
- background: BackgroundTask | BackgroundTasks | None,
- cookies: frozenset[Cookie],
- headers: frozenset[ResponseHeader],
- media_type: str,
- status_code: int,
- type_encoders: TypeEncodersMap | None,
-) -> AsyncAnyCallable:
- """Create a handler function for Litestar Responses.
-
- Args:
- after_request: An after request handler.
- background: A background task or background tasks.
- cookies: A set of pre-defined cookies.
- headers: A set of response headers.
- media_type: The response media type.
- status_code: The response status code.
- type_encoders: A mapping of types to encoder functions.
-
- Returns:
- A handler function.
- """
-
- normalized_headers = normalize_headers(headers)
- cookie_list = list(cookies)
-
- async def handler(
- data: Response,
- app: Litestar,
- request: Request,
- **kwargs: Any, # kwargs is for return dto
- ) -> ASGIApp:
- response = await after_request(data) if after_request else data # type:ignore[arg-type,misc]
- return response.to_asgi_response( # type: ignore[no-any-return]
- app=None,
- background=background,
- cookies=cookie_list,
- headers=normalized_headers,
- media_type=media_type,
- request=request,
- status_code=status_code,
- type_encoders=type_encoders,
- )
-
- return handler
-
-
-def normalize_http_method(http_methods: HttpMethod | Method | Sequence[HttpMethod | Method]) -> set[Method]:
- """Normalize HTTP method(s) into a set of upper-case method names.
-
- Args:
- http_methods: A value for http method.
-
- Returns:
- A normalized set of http methods.
- """
- output: set[str] = set()
-
- if isinstance(http_methods, str):
- http_methods = [http_methods] # pyright: ignore
-
- for method in http_methods:
- method_name = method.value.upper() if isinstance(method, HttpMethod) else method.upper()
- if method_name not in HTTP_METHOD_NAMES:
- raise ValidationException(f"Invalid HTTP method: {method_name}")
- output.add(method_name)
-
- return cast("set[Method]", output)
-
-
-def get_default_status_code(http_methods: set[Method]) -> int:
- """Return the default status code for a given set of HTTP methods.
-
- Args:
- http_methods: A set of method strings
-
- Returns:
- A status code
- """
- if HttpMethod.POST in http_methods:
- return HTTP_201_CREATED
- if HttpMethod.DELETE in http_methods:
- return HTTP_204_NO_CONTENT
- return HTTP_200_OK
-
-
-def is_empty_response_annotation(return_annotation: FieldDefinition) -> bool:
- """Return whether the return annotation is an empty response.
-
- Args:
- return_annotation: A return annotation.
-
- Returns:
- Whether the return annotation is an empty response.
- """
- return (
- return_annotation.is_subclass_of(NoneType)
- or return_annotation.is_subclass_of(Response)
- and return_annotation.has_inner_subclass_of(NoneType)
- )
-
-
-HTTP_METHOD_NAMES = {m.value for m in HttpMethod}
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/base.py b/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/base.py
deleted file mode 100644
index 757253e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/base.py
+++ /dev/null
@@ -1,591 +0,0 @@
-from __future__ import annotations
-
-from enum import Enum
-from typing import TYPE_CHECKING, AnyStr, Mapping, Sequence, TypedDict, cast
-
-from litestar._layers.utils import narrow_response_cookies, narrow_response_headers
-from litestar.connection import Request
-from litestar.datastructures.cookie import Cookie
-from litestar.datastructures.response_header import ResponseHeader
-from litestar.enums import HttpMethod, MediaType
-from litestar.exceptions import (
- HTTPException,
- ImproperlyConfiguredException,
-)
-from litestar.handlers.base import BaseRouteHandler
-from litestar.handlers.http_handlers._utils import (
- create_data_handler,
- create_generic_asgi_response_handler,
- create_response_handler,
- get_default_status_code,
- is_empty_response_annotation,
- normalize_http_method,
-)
-from litestar.openapi.spec import Operation
-from litestar.response import Response
-from litestar.status_codes import HTTP_204_NO_CONTENT, HTTP_304_NOT_MODIFIED
-from litestar.types import (
- AfterRequestHookHandler,
- AfterResponseHookHandler,
- AnyCallable,
- ASGIApp,
- BeforeRequestHookHandler,
- CacheKeyBuilder,
- Dependencies,
- Empty,
- EmptyType,
- ExceptionHandlersMap,
- Guard,
- Method,
- Middleware,
- ResponseCookies,
- ResponseHeaders,
- TypeEncodersMap,
-)
-from litestar.utils import ensure_async_callable
-from litestar.utils.predicates import is_async_callable
-from litestar.utils.warnings import warn_implicit_sync_to_thread, warn_sync_to_thread_with_async_callable
-
-if TYPE_CHECKING:
- from typing import Any, Awaitable, Callable
-
- from litestar.app import Litestar
- from litestar.background_tasks import BackgroundTask, BackgroundTasks
- from litestar.config.response_cache import CACHE_FOREVER
- from litestar.datastructures import CacheControlHeader, ETag
- from litestar.dto import AbstractDTO
- from litestar.openapi.datastructures import ResponseSpec
- from litestar.openapi.spec import SecurityRequirement
- from litestar.types.callable_types import AsyncAnyCallable, OperationIDCreator
- from litestar.types.composite_types import TypeDecodersSequence
-
-__all__ = ("HTTPRouteHandler", "route")
-
-
-class ResponseHandlerMap(TypedDict):
- default_handler: Callable[[Any], Awaitable[ASGIApp]] | EmptyType
- response_type_handler: Callable[[Any], Awaitable[ASGIApp]] | EmptyType
-
-
-class HTTPRouteHandler(BaseRouteHandler):
- """HTTP Route Decorator.
-
- Use this decorator to decorate an HTTP handler with multiple methods.
- """
-
- __slots__ = (
- "_resolved_after_response",
- "_resolved_before_request",
- "_response_handler_mapping",
- "_resolved_include_in_schema",
- "_resolved_tags",
- "_resolved_security",
- "after_request",
- "after_response",
- "background",
- "before_request",
- "cache",
- "cache_control",
- "cache_key_builder",
- "content_encoding",
- "content_media_type",
- "deprecated",
- "description",
- "etag",
- "has_sync_callable",
- "http_methods",
- "include_in_schema",
- "media_type",
- "operation_class",
- "operation_id",
- "raises",
- "request_class",
- "response_class",
- "response_cookies",
- "response_description",
- "response_headers",
- "responses",
- "security",
- "status_code",
- "summary",
- "sync_to_thread",
- "tags",
- "template_name",
- )
-
- has_sync_callable: bool
-
- def __init__(
- self,
- path: str | Sequence[str] | None = None,
- *,
- after_request: AfterRequestHookHandler | None = None,
- after_response: AfterResponseHookHandler | None = None,
- background: BackgroundTask | BackgroundTasks | None = None,
- before_request: BeforeRequestHookHandler | None = None,
- cache: bool | int | type[CACHE_FOREVER] = False,
- cache_control: CacheControlHeader | None = None,
- cache_key_builder: CacheKeyBuilder | None = None,
- dependencies: Dependencies | None = None,
- dto: type[AbstractDTO] | None | EmptyType = Empty,
- etag: ETag | None = None,
- exception_handlers: ExceptionHandlersMap | None = None,
- guards: Sequence[Guard] | None = None,
- http_method: HttpMethod | Method | Sequence[HttpMethod | Method],
- media_type: MediaType | str | None = None,
- middleware: Sequence[Middleware] | None = None,
- name: str | None = None,
- opt: Mapping[str, Any] | None = None,
- request_class: type[Request] | None = None,
- response_class: type[Response] | None = None,
- response_cookies: ResponseCookies | None = None,
- response_headers: ResponseHeaders | None = None,
- return_dto: type[AbstractDTO] | None | EmptyType = Empty,
- status_code: int | None = None,
- sync_to_thread: bool | None = None,
- # OpenAPI related attributes
- content_encoding: str | None = None,
- content_media_type: str | None = None,
- deprecated: bool = False,
- description: str | None = None,
- include_in_schema: bool | EmptyType = Empty,
- operation_class: type[Operation] = Operation,
- operation_id: str | OperationIDCreator | None = None,
- raises: Sequence[type[HTTPException]] | None = None,
- response_description: str | None = None,
- responses: Mapping[int, ResponseSpec] | None = None,
- signature_namespace: Mapping[str, Any] | None = None,
- security: Sequence[SecurityRequirement] | None = None,
- summary: str | None = None,
- tags: Sequence[str] | None = None,
- type_decoders: TypeDecodersSequence | None = None,
- type_encoders: TypeEncodersMap | None = None,
- **kwargs: Any,
- ) -> None:
- """Initialize ``HTTPRouteHandler``.
-
- Args:
- path: A path fragment for the route handler function or a sequence of path fragments.
- If not given defaults to ``/``
- after_request: A sync or async function executed before a :class:`Request <.connection.Request>` is passed
- to any route handler. If this function returns a value, the request will not reach the route handler,
- and instead this value will be used.
- after_response: A sync or async function called after the response has been awaited. It receives the
- :class:`Request <.connection.Request>` object and should not return any values.
- background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or
- :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished.
- Defaults to ``None``.
- before_request: A sync or async function called immediately before calling the route handler. Receives
- the :class:`Request <.connection.Request>` instance and any non-``None`` return value is used for the
- response, bypassing the route handler.
- cache: Enables response caching if configured on the application level. Valid values are ``True`` or a
- number of seconds (e.g. ``120``) to cache the response.
- cache_control: A ``cache-control`` header of type
- :class:`CacheControlHeader <.datastructures.CacheControlHeader>` that will be added to the response.
- cache_key_builder: A :class:`cache-key builder function <.types.CacheKeyBuilder>`. Allows for customization
- of the cache key if caching is configured on the application level.
- dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances.
- dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and
- validation of request data.
- etag: An ``etag`` header of type :class:`ETag <.datastructures.ETag>` that will be added to the response.
- exception_handlers: A mapping of status codes and/or exception types to handler functions.
- guards: A sequence of :class:`Guard <.types.Guard>` callables.
- http_method: An :class:`http method string <.types.Method>`, a member of the enum
- :class:`HttpMethod <.enums.HttpMethod>` or a list of these that correlates to the methods the route
- handler function should handle.
- media_type: A member of the :class:`MediaType <.enums.MediaType>` enum or a string with a valid IANA
- Media-Type.
- middleware: A sequence of :class:`Middleware <.types.Middleware>`.
- name: A string identifying the route handler.
- opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or
- wherever you have access to :class:`Request <.connection.Request>` or
- :class:`ASGI Scope <.types.Scope>`.
- request_class: A custom subclass of :class:`Request <.connection.Request>` to be used as route handler's
- default request.
- response_class: A custom subclass of :class:`Response <.response.Response>` to be used as route handler's
- default response.
- response_cookies: A sequence of :class:`Cookie <.datastructures.Cookie>` instances.
- response_headers: A string keyed mapping of :class:`ResponseHeader <.datastructures.ResponseHeader>`
- instances.
- responses: A mapping of additional status codes and a description of their expected content.
- This information will be included in the OpenAPI schema
- return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing
- outbound response data.
- signature_namespace: A mapping of names to types for use in forward reference resolution during signature modelling.
- status_code: An http status code for the response. Defaults to ``200`` for mixed method or ``GET``, ``PUT`` and
- ``PATCH``, ``201`` for ``POST`` and ``204`` for ``DELETE``.
- sync_to_thread: A boolean dictating whether the handler function will be executed in a worker thread or the
- main event loop. This has an effect only for sync handler functions. See using sync handler functions.
- content_encoding: A string describing the encoding of the content, e.g. ``"base64"``.
- content_media_type: A string designating the media-type of the content, e.g. ``"image/png"``.
- deprecated: A boolean dictating whether this route should be marked as deprecated in the OpenAPI schema.
- description: Text used for the route's schema description section.
- include_in_schema: A boolean flag dictating whether the route handler should be documented in the OpenAPI schema.
- operation_class: :class:`Operation <.openapi.spec.operation.Operation>` to be used with the route's OpenAPI schema.
- operation_id: Either a string or a callable returning a string. An identifier used for the route's schema operationId.
- raises: A list of exception classes extending from litestar.HttpException that is used for the OpenAPI documentation.
- This list should describe all exceptions raised within the route handler's function/method. The Litestar
- ValidationException will be added automatically for the schema if any validation is involved.
- response_description: Text used for the route's response schema description section.
- security: A sequence of dictionaries that contain information about which security scheme can be used on the endpoint.
- summary: Text used for the route's schema summary section.
- tags: A sequence of string tags that will be appended to the OpenAPI schema.
- type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec hook for deserialization.
- type_encoders: A mapping of types to callables that transform them into types supported for serialization.
- **kwargs: Any additional kwarg - will be set in the opt dictionary.
- """
- if not http_method:
- raise ImproperlyConfiguredException("An http_method kwarg is required")
-
- self.http_methods = normalize_http_method(http_methods=http_method)
- self.status_code = status_code or get_default_status_code(http_methods=self.http_methods)
-
- super().__init__(
- path=path,
- dependencies=dependencies,
- dto=dto,
- exception_handlers=exception_handlers,
- guards=guards,
- middleware=middleware,
- name=name,
- opt=opt,
- return_dto=return_dto,
- signature_namespace=signature_namespace,
- type_decoders=type_decoders,
- type_encoders=type_encoders,
- **kwargs,
- )
-
- self.after_request = ensure_async_callable(after_request) if after_request else None # pyright: ignore
- self.after_response = ensure_async_callable(after_response) if after_response else None
- self.background = background
- self.before_request = ensure_async_callable(before_request) if before_request else None
- self.cache = cache
- self.cache_control = cache_control
- self.cache_key_builder = cache_key_builder
- self.etag = etag
- self.media_type: MediaType | str = media_type or ""
- self.request_class = request_class
- self.response_class = response_class
- self.response_cookies: Sequence[Cookie] | None = narrow_response_cookies(response_cookies)
- self.response_headers: Sequence[ResponseHeader] | None = narrow_response_headers(response_headers)
-
- self.sync_to_thread = sync_to_thread
- # OpenAPI related attributes
- self.content_encoding = content_encoding
- self.content_media_type = content_media_type
- self.deprecated = deprecated
- self.description = description
- self.include_in_schema = include_in_schema
- self.operation_class = operation_class
- self.operation_id = operation_id
- self.raises = raises
- self.response_description = response_description
- self.summary = summary
- self.tags = tags
- self.security = security
- self.responses = responses
- # memoized attributes, defaulted to Empty
- self._resolved_after_response: AsyncAnyCallable | None | EmptyType = Empty
- self._resolved_before_request: AsyncAnyCallable | None | EmptyType = Empty
- self._response_handler_mapping: ResponseHandlerMap = {"default_handler": Empty, "response_type_handler": Empty}
- self._resolved_include_in_schema: bool | EmptyType = Empty
- self._resolved_security: list[SecurityRequirement] | EmptyType = Empty
- self._resolved_tags: list[str] | EmptyType = Empty
-
- def __call__(self, fn: AnyCallable) -> HTTPRouteHandler:
- """Replace a function with itself."""
- if not is_async_callable(fn):
- if self.sync_to_thread is None:
- warn_implicit_sync_to_thread(fn, stacklevel=3)
- elif self.sync_to_thread is not None:
- warn_sync_to_thread_with_async_callable(fn, stacklevel=3)
-
- super().__call__(fn)
- return self
-
- def resolve_request_class(self) -> type[Request]:
- """Return the closest custom Request class in the owner graph or the default Request class.
-
- This method is memoized so the computation occurs only once.
-
- Returns:
- The default :class:`Request <.connection.Request>` class for the route handler.
- """
- return next(
- (layer.request_class for layer in reversed(self.ownership_layers) if layer.request_class is not None),
- Request,
- )
-
- def resolve_response_class(self) -> type[Response]:
- """Return the closest custom Response class in the owner graph or the default Response class.
-
- This method is memoized so the computation occurs only once.
-
- Returns:
- The default :class:`Response <.response.Response>` class for the route handler.
- """
- return next(
- (layer.response_class for layer in reversed(self.ownership_layers) if layer.response_class is not None),
- Response,
- )
-
- def resolve_response_headers(self) -> frozenset[ResponseHeader]:
- """Return all header parameters in the scope of the handler function.
-
- Returns:
- A dictionary mapping keys to :class:`ResponseHeader <.datastructures.ResponseHeader>` instances.
- """
- resolved_response_headers: dict[str, ResponseHeader] = {}
-
- for layer in self.ownership_layers:
- if layer_response_headers := layer.response_headers:
- if isinstance(layer_response_headers, Mapping):
- # this can't happen unless you manually set response_headers on an instance, which would result in a
- # type-checking error on everything but the controller. We cover this case nevertheless
- resolved_response_headers.update(
- {name: ResponseHeader(name=name, value=value) for name, value in layer_response_headers.items()}
- )
- else:
- resolved_response_headers.update({h.name: h for h in layer_response_headers})
- for extra_header in ("cache_control", "etag"):
- if header_model := getattr(layer, extra_header, None):
- resolved_response_headers[header_model.HEADER_NAME] = ResponseHeader(
- name=header_model.HEADER_NAME,
- value=header_model.to_header(),
- documentation_only=header_model.documentation_only,
- )
-
- return frozenset(resolved_response_headers.values())
-
- def resolve_response_cookies(self) -> frozenset[Cookie]:
- """Return a list of Cookie instances. Filters the list to ensure each cookie key is unique.
-
- Returns:
- A list of :class:`Cookie <.datastructures.Cookie>` instances.
- """
- response_cookies: set[Cookie] = set()
- for layer in reversed(self.ownership_layers):
- if layer_response_cookies := layer.response_cookies:
- if isinstance(layer_response_cookies, Mapping):
- # this can't happen unless you manually set response_cookies on an instance, which would result in a
- # type-checking error on everything but the controller. We cover this case nevertheless
- response_cookies.update(
- {Cookie(key=key, value=value) for key, value in layer_response_cookies.items()}
- )
- else:
- response_cookies.update(cast("set[Cookie]", layer_response_cookies))
- return frozenset(response_cookies)
-
- def resolve_before_request(self) -> AsyncAnyCallable | None:
- """Resolve the before_handler handler by starting from the route handler and moving up.
-
- If a handler is found it is returned, otherwise None is set.
- This method is memoized so the computation occurs only once.
-
- Returns:
- An optional :class:`before request lifecycle hook handler <.types.BeforeRequestHookHandler>`
- """
- if self._resolved_before_request is Empty:
- before_request_handlers = [layer.before_request for layer in self.ownership_layers if layer.before_request]
- self._resolved_before_request = before_request_handlers[-1] if before_request_handlers else None
- return cast("AsyncAnyCallable | None", self._resolved_before_request)
-
- def resolve_after_response(self) -> AsyncAnyCallable | None:
- """Resolve the after_response handler by starting from the route handler and moving up.
-
- If a handler is found it is returned, otherwise None is set.
- This method is memoized so the computation occurs only once.
-
- Returns:
- An optional :class:`after response lifecycle hook handler <.types.AfterResponseHookHandler>`
- """
- if self._resolved_after_response is Empty:
- after_response_handlers: list[AsyncAnyCallable] = [
- layer.after_response # type: ignore[misc]
- for layer in self.ownership_layers
- if layer.after_response
- ]
- self._resolved_after_response = after_response_handlers[-1] if after_response_handlers else None
-
- return cast("AsyncAnyCallable | None", self._resolved_after_response)
-
- def resolve_include_in_schema(self) -> bool:
- """Resolve the 'include_in_schema' property by starting from the route handler and moving up.
-
- If 'include_in_schema' is found in any of the ownership layers, the last value found is returned.
- If not found in any layer, the default value ``True`` is returned.
-
- Returns:
- bool: The resolved 'include_in_schema' property.
- """
- if self._resolved_include_in_schema is Empty:
- include_in_schemas = [
- i.include_in_schema for i in self.ownership_layers if isinstance(i.include_in_schema, bool)
- ]
- self._resolved_include_in_schema = include_in_schemas[-1] if include_in_schemas else True
-
- return self._resolved_include_in_schema
-
- def resolve_security(self) -> list[SecurityRequirement]:
- """Resolve the security property by starting from the route handler and moving up.
-
- Security requirements are additive, so the security requirements of the route handler are the sum of all
- security requirements of the ownership layers.
-
- Returns:
- list[SecurityRequirement]: The resolved security property.
- """
- if self._resolved_security is Empty:
- self._resolved_security = []
- for layer in self.ownership_layers:
- if isinstance(layer.security, Sequence):
- self._resolved_security.extend(layer.security)
-
- return self._resolved_security
-
- def resolve_tags(self) -> list[str]:
- """Resolve the tags property by starting from the route handler and moving up.
-
- Tags are additive, so the tags of the route handler are the sum of all tags of the ownership layers.
-
- Returns:
- list[str]: A sorted list of unique tags.
- """
- if self._resolved_tags is Empty:
- tag_set = set()
- for layer in self.ownership_layers:
- for tag in layer.tags or []:
- tag_set.add(tag)
- self._resolved_tags = sorted(tag_set)
-
- return self._resolved_tags
-
- def get_response_handler(self, is_response_type_data: bool = False) -> Callable[[Any], Awaitable[ASGIApp]]:
- """Resolve the response_handler function for the route handler.
-
- This method is memoized so the computation occurs only once.
-
- Args:
- is_response_type_data: Whether to return a handler for 'Response' instances.
-
- Returns:
- Async Callable to handle an HTTP Request
- """
- if self._response_handler_mapping["default_handler"] is Empty:
- after_request_handlers: list[AsyncAnyCallable] = [
- layer.after_request # type: ignore[misc]
- for layer in self.ownership_layers
- if layer.after_request
- ]
- after_request = cast(
- "AfterRequestHookHandler | None",
- after_request_handlers[-1] if after_request_handlers else None,
- )
-
- media_type = self.media_type.value if isinstance(self.media_type, Enum) else self.media_type
- response_class = self.resolve_response_class()
- headers = self.resolve_response_headers()
- cookies = self.resolve_response_cookies()
- type_encoders = self.resolve_type_encoders()
-
- return_type = self.parsed_fn_signature.return_type
- return_annotation = return_type.annotation
-
- self._response_handler_mapping["response_type_handler"] = response_type_handler = create_response_handler(
- after_request=after_request,
- background=self.background,
- cookies=cookies,
- headers=headers,
- media_type=media_type,
- status_code=self.status_code,
- type_encoders=type_encoders,
- )
-
- if return_type.is_subclass_of(Response):
- self._response_handler_mapping["default_handler"] = response_type_handler
- elif is_async_callable(return_annotation) or return_annotation is ASGIApp:
- self._response_handler_mapping["default_handler"] = create_generic_asgi_response_handler(
- after_request=after_request
- )
- else:
- self._response_handler_mapping["default_handler"] = create_data_handler(
- after_request=after_request,
- background=self.background,
- cookies=cookies,
- headers=headers,
- media_type=media_type,
- response_class=response_class,
- status_code=self.status_code,
- type_encoders=type_encoders,
- )
-
- return cast(
- "Callable[[Any], Awaitable[ASGIApp]]",
- self._response_handler_mapping["response_type_handler"]
- if is_response_type_data
- else self._response_handler_mapping["default_handler"],
- )
-
- async def to_response(self, app: Litestar, data: Any, request: Request) -> ASGIApp:
- """Return a :class:`Response <.response.Response>` from the handler by resolving and calling it.
-
- Args:
- app: The :class:`Litestar <litestar.app.Litestar>` app instance
- data: Either an instance of a :class:`Response <.response.Response>`,
- a Response instance or an arbitrary value.
- request: A :class:`Request <.connection.Request>` instance
-
- Returns:
- A Response instance
- """
- if return_dto_type := self.resolve_return_dto():
- data = return_dto_type(request).data_to_encodable_type(data)
-
- response_handler = self.get_response_handler(is_response_type_data=isinstance(data, Response))
- return await response_handler(app=app, data=data, request=request) # type: ignore[call-arg]
-
- def on_registration(self, app: Litestar) -> None:
- super().on_registration(app)
- self.resolve_after_response()
- self.resolve_include_in_schema()
- self.has_sync_callable = not is_async_callable(self.fn)
-
- if self.has_sync_callable and self.sync_to_thread:
- self._fn = ensure_async_callable(self.fn)
- self.has_sync_callable = False
-
- def _validate_handler_function(self) -> None:
- """Validate the route handler function once it is set by inspecting its return annotations."""
- super()._validate_handler_function()
-
- return_type = self.parsed_fn_signature.return_type
-
- if return_type.annotation is Empty:
- raise ImproperlyConfiguredException(
- "A return value of a route handler function should be type annotated. "
- "If your function doesn't return a value, annotate it as returning 'None'."
- )
-
- if (
- self.status_code < 200 or self.status_code in {HTTP_204_NO_CONTENT, HTTP_304_NOT_MODIFIED}
- ) and not is_empty_response_annotation(return_type):
- raise ImproperlyConfiguredException(
- "A status code 204, 304 or in the range below 200 does not support a response body. "
- "If the function should return a value, change the route handler status code to an appropriate value.",
- )
-
- if not self.media_type:
- if return_type.is_subclass_of((str, bytes)) or return_type.annotation is AnyStr:
- self.media_type = MediaType.TEXT
- elif not return_type.is_subclass_of(Response):
- self.media_type = MediaType.JSON
-
- if "socket" in self.parsed_fn_signature.parameters:
- raise ImproperlyConfiguredException("The 'socket' kwarg is not supported with http handlers")
-
- if "data" in self.parsed_fn_signature.parameters and "GET" in self.http_methods:
- raise ImproperlyConfiguredException("'data' kwarg is unsupported for 'GET' request handlers")
-
-
-route = HTTPRouteHandler
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/decorators.py b/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/decorators.py
deleted file mode 100644
index 1ae72e5..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/http_handlers/decorators.py
+++ /dev/null
@@ -1,1096 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING
-
-from litestar.enums import HttpMethod, MediaType
-from litestar.exceptions import HTTPException, ImproperlyConfiguredException
-from litestar.openapi.spec import Operation
-from litestar.response.file import ASGIFileResponse, File
-from litestar.types import Empty, TypeDecodersSequence
-from litestar.types.builtin_types import NoneType
-from litestar.utils import is_class_and_subclass
-
-from .base import HTTPRouteHandler
-
-if TYPE_CHECKING:
- from typing import Any, Mapping, Sequence
-
- from litestar.background_tasks import BackgroundTask, BackgroundTasks
- from litestar.config.response_cache import CACHE_FOREVER
- from litestar.connection import Request
- from litestar.datastructures import CacheControlHeader, ETag
- from litestar.dto import AbstractDTO
- from litestar.openapi.datastructures import ResponseSpec
- from litestar.openapi.spec import SecurityRequirement
- from litestar.response import Response
- from litestar.types import (
- AfterRequestHookHandler,
- AfterResponseHookHandler,
- BeforeRequestHookHandler,
- CacheKeyBuilder,
- Dependencies,
- EmptyType,
- ExceptionHandlersMap,
- Guard,
- Middleware,
- ResponseCookies,
- ResponseHeaders,
- TypeEncodersMap,
- )
- from litestar.types.callable_types import OperationIDCreator
-
-
-__all__ = ("get", "head", "post", "put", "patch", "delete")
-
-MSG_SEMANTIC_ROUTE_HANDLER_WITH_HTTP = "semantic route handlers cannot define http_method"
-
-
-class delete(HTTPRouteHandler):
- """DELETE Route Decorator.
-
- Use this decorator to decorate an HTTP handler for DELETE requests.
- """
-
- def __init__(
- self,
- path: str | None | Sequence[str] = None,
- *,
- after_request: AfterRequestHookHandler | None = None,
- after_response: AfterResponseHookHandler | None = None,
- background: BackgroundTask | BackgroundTasks | None = None,
- before_request: BeforeRequestHookHandler | None = None,
- cache: bool | int | type[CACHE_FOREVER] = False,
- cache_control: CacheControlHeader | None = None,
- cache_key_builder: CacheKeyBuilder | None = None,
- dependencies: Dependencies | None = None,
- dto: type[AbstractDTO] | None | EmptyType = Empty,
- etag: ETag | None = None,
- exception_handlers: ExceptionHandlersMap | None = None,
- guards: Sequence[Guard] | None = None,
- media_type: MediaType | str | None = None,
- middleware: Sequence[Middleware] | None = None,
- name: str | None = None,
- opt: Mapping[str, Any] | None = None,
- request_class: type[Request] | None = None,
- response_class: type[Response] | None = None,
- response_cookies: ResponseCookies | None = None,
- response_headers: ResponseHeaders | None = None,
- return_dto: type[AbstractDTO] | None | EmptyType = Empty,
- signature_namespace: Mapping[str, Any] | None = None,
- status_code: int | None = None,
- sync_to_thread: bool | None = None,
- # OpenAPI related attributes
- content_encoding: str | None = None,
- content_media_type: str | None = None,
- deprecated: bool = False,
- description: str | None = None,
- include_in_schema: bool | EmptyType = Empty,
- operation_class: type[Operation] = Operation,
- operation_id: str | OperationIDCreator | None = None,
- raises: Sequence[type[HTTPException]] | None = None,
- response_description: str | None = None,
- responses: Mapping[int, ResponseSpec] | None = None,
- security: Sequence[SecurityRequirement] | None = None,
- summary: str | None = None,
- tags: Sequence[str] | None = None,
- type_decoders: TypeDecodersSequence | None = None,
- type_encoders: TypeEncodersMap | None = None,
- **kwargs: Any,
- ) -> None:
- """Initialize ``delete``
-
- Args:
- path: A path fragment for the route handler function or a sequence of path fragments.
- If not given defaults to ``/``
- after_request: A sync or async function executed before a :class:`Request <.connection.Request>` is passed
- to any route handler. If this function returns a value, the request will not reach the route handler,
- and instead this value will be used.
- after_response: A sync or async function called after the response has been awaited. It receives the
- :class:`Request <.connection.Request>` object and should not return any values.
- background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or
- :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished.
- Defaults to ``None``.
- before_request: A sync or async function called immediately before calling the route handler. Receives
- the :class:`.connection.Request` instance and any non-``None`` return value is used for the response,
- bypassing the route handler.
- cache: Enables response caching if configured on the application level. Valid values are ``True`` or a number
- of seconds (e.g. ``120``) to cache the response.
- cache_control: A ``cache-control`` header of type
- :class:`CacheControlHeader <.datastructures.CacheControlHeader>` that will be added to the response.
- cache_key_builder: A :class:`cache-key builder function <.types.CacheKeyBuilder>`. Allows for customization
- of the cache key if caching is configured on the application level.
- dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and
- validation of request data.
- dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances.
- etag: An ``etag`` header of type :class:`ETag <.datastructures.ETag>` that will be added to the response.
- exception_handlers: A mapping of status codes and/or exception types to handler functions.
- guards: A sequence of :class:`Guard <.types.Guard>` callables.
- http_method: An :class:`http method string <.types.Method>`, a member of the enum
- :class:`HttpMethod <litestar.enums.HttpMethod>` or a list of these that correlates to the methods the
- route handler function should handle.
- media_type: A member of the :class:`MediaType <.enums.MediaType>` enum or a string with a
- valid IANA Media-Type.
- middleware: A sequence of :class:`Middleware <.types.Middleware>`.
- name: A string identifying the route handler.
- opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or
- wherever you have access to :class:`Request <.connection.Request>` or :class:`ASGI Scope <.types.Scope>`.
- request_class: A custom subclass of :class:`Request <.connection.Request>` to be used as route handler's
- default request.
- response_class: A custom subclass of :class:`Response <.response.Response>` to be used as route handler's
- default response.
- response_cookies: A sequence of :class:`Cookie <.datastructures.Cookie>` instances.
- response_headers: A string keyed mapping of :class:`ResponseHeader <.datastructures.ResponseHeader>`
- instances.
- responses: A mapping of additional status codes and a description of their expected content.
- This information will be included in the OpenAPI schema
- return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing
- outbound response data.
- signature_namespace: A mapping of names to types for use in forward reference resolution during signature modelling.
- status_code: An http status code for the response. Defaults to ``200`` for mixed method or ``GET``, ``PUT``
- and ``PATCH``, ``201`` for ``POST`` and ``204`` for ``DELETE``.
- sync_to_thread: A boolean dictating whether the handler function will be executed in a worker thread or the
- main event loop. This has an effect only for sync handler functions. See using sync handler functions.
- content_encoding: A string describing the encoding of the content, e.g. ``base64``.
- content_media_type: A string designating the media-type of the content, e.g. ``image/png``.
- deprecated: A boolean dictating whether this route should be marked as deprecated in the OpenAPI schema.
- description: Text used for the route's schema description section.
- include_in_schema: A boolean flag dictating whether the route handler should be documented in the OpenAPI schema.
- operation_class: :class:`Operation <.openapi.spec.operation.Operation>` to be used with the route's OpenAPI schema.
- operation_id: Either a string or a callable returning a string. An identifier used for the route's schema operationId.
- raises: A list of exception classes extending from litestar.HttpException that is used for the OpenAPI documentation.
- This list should describe all exceptions raised within the route handler's function/method. The Litestar
- ValidationException will be added automatically for the schema if any validation is involved.
- response_description: Text used for the route's response schema description section.
- security: A sequence of dictionaries that contain information about which security scheme can be used on the endpoint.
- summary: Text used for the route's schema summary section.
- tags: A sequence of string tags that will be appended to the OpenAPI schema.
- type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec
- hook for deserialization.
- type_encoders: A mapping of types to callables that transform them into types supported for serialization.
- **kwargs: Any additional kwarg - will be set in the opt dictionary.
- """
- if "http_method" in kwargs:
- raise ImproperlyConfiguredException(MSG_SEMANTIC_ROUTE_HANDLER_WITH_HTTP)
- super().__init__(
- after_request=after_request,
- after_response=after_response,
- background=background,
- before_request=before_request,
- cache=cache,
- cache_control=cache_control,
- cache_key_builder=cache_key_builder,
- content_encoding=content_encoding,
- content_media_type=content_media_type,
- dependencies=dependencies,
- deprecated=deprecated,
- description=description,
- dto=dto,
- etag=etag,
- exception_handlers=exception_handlers,
- guards=guards,
- http_method=HttpMethod.DELETE,
- include_in_schema=include_in_schema,
- media_type=media_type,
- middleware=middleware,
- name=name,
- operation_class=operation_class,
- operation_id=operation_id,
- opt=opt,
- path=path,
- raises=raises,
- request_class=request_class,
- response_class=response_class,
- response_cookies=response_cookies,
- response_description=response_description,
- response_headers=response_headers,
- responses=responses,
- return_dto=return_dto,
- security=security,
- signature_namespace=signature_namespace,
- status_code=status_code,
- summary=summary,
- sync_to_thread=sync_to_thread,
- tags=tags,
- type_decoders=type_decoders,
- type_encoders=type_encoders,
- **kwargs,
- )
-
-
-class get(HTTPRouteHandler):
- """GET Route Decorator.
-
- Use this decorator to decorate an HTTP handler for GET requests.
- """
-
- def __init__(
- self,
- path: str | None | Sequence[str] = None,
- *,
- after_request: AfterRequestHookHandler | None = None,
- after_response: AfterResponseHookHandler | None = None,
- background: BackgroundTask | BackgroundTasks | None = None,
- before_request: BeforeRequestHookHandler | None = None,
- cache: bool | int | type[CACHE_FOREVER] = False,
- cache_control: CacheControlHeader | None = None,
- cache_key_builder: CacheKeyBuilder | None = None,
- dependencies: Dependencies | None = None,
- dto: type[AbstractDTO] | None | EmptyType = Empty,
- etag: ETag | None = None,
- exception_handlers: ExceptionHandlersMap | None = None,
- guards: Sequence[Guard] | None = None,
- media_type: MediaType | str | None = None,
- middleware: Sequence[Middleware] | None = None,
- name: str | None = None,
- opt: Mapping[str, Any] | None = None,
- request_class: type[Request] | None = None,
- response_class: type[Response] | None = None,
- response_cookies: ResponseCookies | None = None,
- response_headers: ResponseHeaders | None = None,
- return_dto: type[AbstractDTO] | None | EmptyType = Empty,
- signature_namespace: Mapping[str, Any] | None = None,
- status_code: int | None = None,
- sync_to_thread: bool | None = None,
- # OpenAPI related attributes
- content_encoding: str | None = None,
- content_media_type: str | None = None,
- deprecated: bool = False,
- description: str | None = None,
- include_in_schema: bool | EmptyType = Empty,
- operation_class: type[Operation] = Operation,
- operation_id: str | OperationIDCreator | None = None,
- raises: Sequence[type[HTTPException]] | None = None,
- response_description: str | None = None,
- responses: Mapping[int, ResponseSpec] | None = None,
- security: Sequence[SecurityRequirement] | None = None,
- summary: str | None = None,
- tags: Sequence[str] | None = None,
- type_decoders: TypeDecodersSequence | None = None,
- type_encoders: TypeEncodersMap | None = None,
- **kwargs: Any,
- ) -> None:
- """Initialize ``get``.
-
- Args:
- path: A path fragment for the route handler function or a sequence of path fragments.
- If not given defaults to ``/``
- after_request: A sync or async function executed before a :class:`Request <.connection.Request>` is passed
- to any route handler. If this function returns a value, the request will not reach the route handler,
- and instead this value will be used.
- after_response: A sync or async function called after the response has been awaited. It receives the
- :class:`Request <.connection.Request>` object and should not return any values.
- background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or
- :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished.
- Defaults to ``None``.
- before_request: A sync or async function called immediately before calling the route handler. Receives
- the :class:`.connection.Request` instance and any non-``None`` return value is used for the response,
- bypassing the route handler.
- cache: Enables response caching if configured on the application level. Valid values are ``True`` or a number
- of seconds (e.g. ``120``) to cache the response.
- cache_control: A ``cache-control`` header of type
- :class:`CacheControlHeader <.datastructures.CacheControlHeader>` that will be added to the response.
- cache_key_builder: A :class:`cache-key builder function <.types.CacheKeyBuilder>`. Allows for customization
- of the cache key if caching is configured on the application level.
- dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances.
- dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and
- validation of request data.
- etag: An ``etag`` header of type :class:`ETag <.datastructures.ETag>` that will be added to the response.
- exception_handlers: A mapping of status codes and/or exception types to handler functions.
- guards: A sequence of :class:`Guard <.types.Guard>` callables.
- http_method: An :class:`http method string <.types.Method>`, a member of the enum
- :class:`HttpMethod <litestar.enums.HttpMethod>` or a list of these that correlates to the methods the
- route handler function should handle.
- media_type: A member of the :class:`MediaType <.enums.MediaType>` enum or a string with a
- valid IANA Media-Type.
- middleware: A sequence of :class:`Middleware <.types.Middleware>`.
- name: A string identifying the route handler.
- opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or
- wherever you have access to :class:`Request <.connection.Request>` or :class:`ASGI Scope <.types.Scope>`.
- request_class: A custom subclass of :class:`Request <.connection.Request>` to be used as route handler's
- default request.
- response_class: A custom subclass of :class:`Response <.response.Response>` to be used as route handler's
- default response.
- response_cookies: A sequence of :class:`Cookie <.datastructures.Cookie>` instances.
- response_headers: A string keyed mapping of :class:`ResponseHeader <.datastructures.ResponseHeader>`
- instances.
- responses: A mapping of additional status codes and a description of their expected content.
- This information will be included in the OpenAPI schema
- return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing
- outbound response data.
- signature_namespace: A mapping of names to types for use in forward reference resolution during signature modelling.
- status_code: An http status code for the response. Defaults to ``200`` for mixed method or ``GET``, ``PUT`` and
- ``PATCH``, ``201`` for ``POST`` and ``204`` for ``DELETE``.
- sync_to_thread: A boolean dictating whether the handler function will be executed in a worker thread or the
- main event loop. This has an effect only for sync handler functions. See using sync handler functions.
- content_encoding: A string describing the encoding of the content, e.g. ``base64``.
- content_media_type: A string designating the media-type of the content, e.g. ``image/png``.
- deprecated: A boolean dictating whether this route should be marked as deprecated in the OpenAPI schema.
- description: Text used for the route's schema description section.
- include_in_schema: A boolean flag dictating whether the route handler should be documented in the OpenAPI schema.
- operation_class: :class:`Operation <.openapi.spec.operation.Operation>` to be used with the route's OpenAPI schema.
- operation_id: Either a string or a callable returning a string. An identifier used for the route's schema operationId.
- raises: A list of exception classes extending from litestar.HttpException that is used for the OpenAPI documentation.
- This list should describe all exceptions raised within the route handler's function/method. The Litestar
- ValidationException will be added automatically for the schema if any validation is involved.
- response_description: Text used for the route's response schema description section.
- security: A sequence of dictionaries that contain information about which security scheme can be used on the endpoint.
- summary: Text used for the route's schema summary section.
- tags: A sequence of string tags that will be appended to the OpenAPI schema.
- type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec
- hook for deserialization.
- type_encoders: A mapping of types to callables that transform them into types supported for serialization.
- **kwargs: Any additional kwarg - will be set in the opt dictionary.
- """
- if "http_method" in kwargs:
- raise ImproperlyConfiguredException(MSG_SEMANTIC_ROUTE_HANDLER_WITH_HTTP)
-
- super().__init__(
- after_request=after_request,
- after_response=after_response,
- background=background,
- before_request=before_request,
- cache=cache,
- cache_control=cache_control,
- cache_key_builder=cache_key_builder,
- content_encoding=content_encoding,
- content_media_type=content_media_type,
- dependencies=dependencies,
- deprecated=deprecated,
- description=description,
- dto=dto,
- etag=etag,
- exception_handlers=exception_handlers,
- guards=guards,
- http_method=HttpMethod.GET,
- include_in_schema=include_in_schema,
- media_type=media_type,
- middleware=middleware,
- name=name,
- operation_class=operation_class,
- operation_id=operation_id,
- opt=opt,
- path=path,
- raises=raises,
- request_class=request_class,
- response_class=response_class,
- response_cookies=response_cookies,
- response_description=response_description,
- response_headers=response_headers,
- responses=responses,
- return_dto=return_dto,
- security=security,
- signature_namespace=signature_namespace,
- status_code=status_code,
- summary=summary,
- sync_to_thread=sync_to_thread,
- tags=tags,
- type_decoders=type_decoders,
- type_encoders=type_encoders,
- **kwargs,
- )
-
-
-class head(HTTPRouteHandler):
- """HEAD Route Decorator.
-
- Use this decorator to decorate an HTTP handler for HEAD requests.
- """
-
- def __init__(
- self,
- path: str | None | Sequence[str] = None,
- *,
- after_request: AfterRequestHookHandler | None = None,
- after_response: AfterResponseHookHandler | None = None,
- background: BackgroundTask | BackgroundTasks | None = None,
- before_request: BeforeRequestHookHandler | None = None,
- cache: bool | int | type[CACHE_FOREVER] = False,
- cache_control: CacheControlHeader | None = None,
- cache_key_builder: CacheKeyBuilder | None = None,
- dependencies: Dependencies | None = None,
- dto: type[AbstractDTO] | None | EmptyType = Empty,
- etag: ETag | None = None,
- exception_handlers: ExceptionHandlersMap | None = None,
- guards: Sequence[Guard] | None = None,
- media_type: MediaType | str | None = None,
- middleware: Sequence[Middleware] | None = None,
- name: str | None = None,
- opt: Mapping[str, Any] | None = None,
- request_class: type[Request] | None = None,
- response_class: type[Response] | None = None,
- response_cookies: ResponseCookies | None = None,
- response_headers: ResponseHeaders | None = None,
- signature_namespace: Mapping[str, Any] | None = None,
- status_code: int | None = None,
- sync_to_thread: bool | None = None,
- # OpenAPI related attributes
- content_encoding: str | None = None,
- content_media_type: str | None = None,
- deprecated: bool = False,
- description: str | None = None,
- include_in_schema: bool | EmptyType = Empty,
- operation_class: type[Operation] = Operation,
- operation_id: str | OperationIDCreator | None = None,
- raises: Sequence[type[HTTPException]] | None = None,
- response_description: str | None = None,
- responses: Mapping[int, ResponseSpec] | None = None,
- return_dto: type[AbstractDTO] | None | EmptyType = Empty,
- security: Sequence[SecurityRequirement] | None = None,
- summary: str | None = None,
- tags: Sequence[str] | None = None,
- type_decoders: TypeDecodersSequence | None = None,
- type_encoders: TypeEncodersMap | None = None,
- **kwargs: Any,
- ) -> None:
- """Initialize ``head``.
-
- Notes:
- - A response to a head request cannot include a body.
- See: [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD).
-
- Args:
- path: A path fragment for the route handler function or a sequence of path fragments.
- If not given defaults to ``/``
- after_request: A sync or async function executed before a :class:`Request <.connection.Request>` is passed
- to any route handler. If this function returns a value, the request will not reach the route handler,
- and instead this value will be used.
- after_response: A sync or async function called after the response has been awaited. It receives the
- :class:`Request <.connection.Request>` object and should not return any values.
- background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or
- :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished.
- Defaults to ``None``.
- before_request: A sync or async function called immediately before calling the route handler. Receives
- the :class:`.connection.Request` instance and any non-``None`` return value is used for the response,
- bypassing the route handler.
- cache: Enables response caching if configured on the application level. Valid values are ``True`` or a number
- of seconds (e.g. ``120``) to cache the response.
- cache_control: A ``cache-control`` header of type
- :class:`CacheControlHeader <.datastructures.CacheControlHeader>` that will be added to the response.
- cache_key_builder: A :class:`cache-key builder function <.types.CacheKeyBuilder>`. Allows for customization
- of the cache key if caching is configured on the application level.
- dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances.
- dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and
- validation of request data.
- etag: An ``etag`` header of type :class:`ETag <.datastructures.ETag>` that will be added to the response.
- exception_handlers: A mapping of status codes and/or exception types to handler functions.
- guards: A sequence of :class:`Guard <.types.Guard>` callables.
- http_method: An :class:`http method string <.types.Method>`, a member of the enum
- :class:`HttpMethod <litestar.enums.HttpMethod>` or a list of these that correlates to the methods the
- route handler function should handle.
- media_type: A member of the :class:`MediaType <.enums.MediaType>` enum or a string with a
- valid IANA Media-Type.
- middleware: A sequence of :class:`Middleware <.types.Middleware>`.
- name: A string identifying the route handler.
- opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or
- wherever you have access to :class:`Request <.connection.Request>` or :class:`ASGI Scope <.types.Scope>`.
- request_class: A custom subclass of :class:`Request <.connection.Request>` to be used as route handler's
- default request.
- response_class: A custom subclass of :class:`Response <.response.Response>` to be used as route handler's
- default response.
- response_cookies: A sequence of :class:`Cookie <.datastructures.Cookie>` instances.
- response_headers: A string keyed mapping of :class:`ResponseHeader <.datastructures.ResponseHeader>`
- instances.
- responses: A mapping of additional status codes and a description of their expected content.
- This information will be included in the OpenAPI schema
- return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing
- outbound response data.
- signature_namespace: A mapping of names to types for use in forward reference resolution during signature modelling.
- status_code: An http status code for the response. Defaults to ``200`` for mixed method or ``GET``, ``PUT`` and
- ``PATCH``, ``201`` for ``POST`` and ``204`` for ``DELETE``.
- sync_to_thread: A boolean dictating whether the handler function will be executed in a worker thread or the
- main event loop. This has an effect only for sync handler functions. See using sync handler functions.
- content_encoding: A string describing the encoding of the content, e.g. ``base64``.
- content_media_type: A string designating the media-type of the content, e.g. ``image/png``.
- deprecated: A boolean dictating whether this route should be marked as deprecated in the OpenAPI schema.
- description: Text used for the route's schema description section.
- include_in_schema: A boolean flag dictating whether the route handler should be documented in the OpenAPI schema.
- operation_class: :class:`Operation <.openapi.spec.operation.Operation>` to be used with the route's OpenAPI schema.
- operation_id: Either a string or a callable returning a string. An identifier used for the route's schema operationId.
- raises: A list of exception classes extending from litestar.HttpException that is used for the OpenAPI documentation.
- This list should describe all exceptions raised within the route handler's function/method. The Litestar
- ValidationException will be added automatically for the schema if any validation is involved.
- response_description: Text used for the route's response schema description section.
- security: A sequence of dictionaries that contain information about which security scheme can be used on the endpoint.
- summary: Text used for the route's schema summary section.
- tags: A sequence of string tags that will be appended to the OpenAPI schema.
- type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec
- hook for deserialization.
- type_encoders: A mapping of types to callables that transform them into types supported for serialization.
- **kwargs: Any additional kwarg - will be set in the opt dictionary.
- """
- if "http_method" in kwargs:
- raise ImproperlyConfiguredException(MSG_SEMANTIC_ROUTE_HANDLER_WITH_HTTP)
-
- super().__init__(
- after_request=after_request,
- after_response=after_response,
- background=background,
- before_request=before_request,
- cache=cache,
- cache_control=cache_control,
- cache_key_builder=cache_key_builder,
- content_encoding=content_encoding,
- content_media_type=content_media_type,
- dependencies=dependencies,
- deprecated=deprecated,
- description=description,
- dto=dto,
- etag=etag,
- exception_handlers=exception_handlers,
- guards=guards,
- http_method=HttpMethod.HEAD,
- include_in_schema=include_in_schema,
- media_type=media_type,
- middleware=middleware,
- name=name,
- operation_class=operation_class,
- operation_id=operation_id,
- opt=opt,
- path=path,
- raises=raises,
- request_class=request_class,
- response_class=response_class,
- response_cookies=response_cookies,
- response_description=response_description,
- response_headers=response_headers,
- responses=responses,
- return_dto=return_dto,
- security=security,
- signature_namespace=signature_namespace,
- status_code=status_code,
- summary=summary,
- sync_to_thread=sync_to_thread,
- tags=tags,
- type_decoders=type_decoders,
- type_encoders=type_encoders,
- **kwargs,
- )
-
- def _validate_handler_function(self) -> None:
- """Validate the route handler function once it is set by inspecting its return annotations."""
- super()._validate_handler_function()
-
- # we allow here File and File because these have special setting for head responses
- return_annotation = self.parsed_fn_signature.return_type.annotation
- if not (
- return_annotation in {NoneType, None}
- or is_class_and_subclass(return_annotation, File)
- or is_class_and_subclass(return_annotation, ASGIFileResponse)
- ):
- raise ImproperlyConfiguredException("A response to a head request should not have a body")
-
-
-class patch(HTTPRouteHandler):
- """PATCH Route Decorator.
-
- Use this decorator to decorate an HTTP handler for PATCH requests.
- """
-
- def __init__(
- self,
- path: str | None | Sequence[str] = None,
- *,
- after_request: AfterRequestHookHandler | None = None,
- after_response: AfterResponseHookHandler | None = None,
- background: BackgroundTask | BackgroundTasks | None = None,
- before_request: BeforeRequestHookHandler | None = None,
- cache: bool | int | type[CACHE_FOREVER] = False,
- cache_control: CacheControlHeader | None = None,
- cache_key_builder: CacheKeyBuilder | None = None,
- dependencies: Dependencies | None = None,
- dto: type[AbstractDTO] | None | EmptyType = Empty,
- etag: ETag | None = None,
- exception_handlers: ExceptionHandlersMap | None = None,
- guards: Sequence[Guard] | None = None,
- media_type: MediaType | str | None = None,
- middleware: Sequence[Middleware] | None = None,
- name: str | None = None,
- opt: Mapping[str, Any] | None = None,
- request_class: type[Request] | None = None,
- response_class: type[Response] | None = None,
- response_cookies: ResponseCookies | None = None,
- response_headers: ResponseHeaders | None = None,
- return_dto: type[AbstractDTO] | None | EmptyType = Empty,
- signature_namespace: Mapping[str, Any] | None = None,
- status_code: int | None = None,
- sync_to_thread: bool | None = None,
- # OpenAPI related attributes
- content_encoding: str | None = None,
- content_media_type: str | None = None,
- deprecated: bool = False,
- description: str | None = None,
- include_in_schema: bool | EmptyType = Empty,
- operation_class: type[Operation] = Operation,
- operation_id: str | OperationIDCreator | None = None,
- raises: Sequence[type[HTTPException]] | None = None,
- response_description: str | None = None,
- responses: Mapping[int, ResponseSpec] | None = None,
- security: Sequence[SecurityRequirement] | None = None,
- summary: str | None = None,
- tags: Sequence[str] | None = None,
- type_decoders: TypeDecodersSequence | None = None,
- type_encoders: TypeEncodersMap | None = None,
- **kwargs: Any,
- ) -> None:
- """Initialize ``patch``.
-
- Args:
- path: A path fragment for the route handler function or a sequence of path fragments.
- If not given defaults to ``/``
- after_request: A sync or async function executed before a :class:`Request <.connection.Request>` is passed
- to any route handler. If this function returns a value, the request will not reach the route handler,
- and instead this value will be used.
- after_response: A sync or async function called after the response has been awaited. It receives the
- :class:`Request <.connection.Request>` object and should not return any values.
- background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or
- :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished.
- Defaults to ``None``.
- before_request: A sync or async function called immediately before calling the route handler. Receives
- the :class:`.connection.Request` instance and any non-``None`` return value is used for the response,
- bypassing the route handler.
- cache: Enables response caching if configured on the application level. Valid values are ``True`` or a number
- of seconds (e.g. ``120``) to cache the response.
- cache_control: A ``cache-control`` header of type
- :class:`CacheControlHeader <.datastructures.CacheControlHeader>` that will be added to the response.
- cache_key_builder: A :class:`cache-key builder function <.types.CacheKeyBuilder>`. Allows for customization
- of the cache key if caching is configured on the application level.
- dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances.
- dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and
- validation of request data.
- etag: An ``etag`` header of type :class:`ETag <.datastructures.ETag>` that will be added to the response.
- exception_handlers: A mapping of status codes and/or exception types to handler functions.
- guards: A sequence of :class:`Guard <.types.Guard>` callables.
- http_method: An :class:`http method string <.types.Method>`, a member of the enum
- :class:`HttpMethod <litestar.enums.HttpMethod>` or a list of these that correlates to the methods the
- route handler function should handle.
- media_type: A member of the :class:`MediaType <.enums.MediaType>` enum or a string with a
- valid IANA Media-Type.
- middleware: A sequence of :class:`Middleware <.types.Middleware>`.
- name: A string identifying the route handler.
- opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or
- wherever you have access to :class:`Request <.connection.Request>` or :class:`ASGI Scope <.types.Scope>`.
- request_class: A custom subclass of :class:`Request <.connection.Request>` to be used as route handler's
- default request.
- response_class: A custom subclass of :class:`Response <.response.Response>` to be used as route handler's
- default response.
- response_cookies: A sequence of :class:`Cookie <.datastructures.Cookie>` instances.
- response_headers: A string keyed mapping of :class:`ResponseHeader <.datastructures.ResponseHeader>`
- instances.
- responses: A mapping of additional status codes and a description of their expected content.
- This information will be included in the OpenAPI schema
- return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing
- outbound response data.
- signature_namespace: A mapping of names to types for use in forward reference resolution during signature modelling.
- status_code: An http status code for the response. Defaults to ``200`` for mixed method or ``GET``, ``PUT`` and
- ``PATCH``, ``201`` for ``POST`` and ``204`` for ``DELETE``.
- sync_to_thread: A boolean dictating whether the handler function will be executed in a worker thread or the
- main event loop. This has an effect only for sync handler functions. See using sync handler functions.
- content_encoding: A string describing the encoding of the content, e.g. ``base64``.
- content_media_type: A string designating the media-type of the content, e.g. ``image/png``.
- deprecated: A boolean dictating whether this route should be marked as deprecated in the OpenAPI schema.
- description: Text used for the route's schema description section.
- include_in_schema: A boolean flag dictating whether the route handler should be documented in the OpenAPI schema.
- operation_class: :class:`Operation <.openapi.spec.operation.Operation>` to be used with the route's OpenAPI schema.
- operation_id: Either a string or a callable returning a string. An identifier used for the route's schema operationId.
- raises: A list of exception classes extending from litestar.HttpException that is used for the OpenAPI documentation.
- This list should describe all exceptions raised within the route handler's function/method. The Litestar
- ValidationException will be added automatically for the schema if any validation is involved.
- response_description: Text used for the route's response schema description section.
- security: A sequence of dictionaries that contain information about which security scheme can be used on the endpoint.
- summary: Text used for the route's schema summary section.
- tags: A sequence of string tags that will be appended to the OpenAPI schema.
- type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec
- hook for deserialization.
- type_encoders: A mapping of types to callables that transform them into types supported for serialization.
- **kwargs: Any additional kwarg - will be set in the opt dictionary.
- """
- if "http_method" in kwargs:
- raise ImproperlyConfiguredException(MSG_SEMANTIC_ROUTE_HANDLER_WITH_HTTP)
- super().__init__(
- after_request=after_request,
- after_response=after_response,
- background=background,
- before_request=before_request,
- cache=cache,
- cache_control=cache_control,
- cache_key_builder=cache_key_builder,
- content_encoding=content_encoding,
- content_media_type=content_media_type,
- dependencies=dependencies,
- deprecated=deprecated,
- description=description,
- dto=dto,
- etag=etag,
- exception_handlers=exception_handlers,
- guards=guards,
- http_method=HttpMethod.PATCH,
- include_in_schema=include_in_schema,
- media_type=media_type,
- middleware=middleware,
- name=name,
- operation_class=operation_class,
- operation_id=operation_id,
- opt=opt,
- path=path,
- raises=raises,
- request_class=request_class,
- response_class=response_class,
- response_cookies=response_cookies,
- response_description=response_description,
- response_headers=response_headers,
- responses=responses,
- return_dto=return_dto,
- security=security,
- signature_namespace=signature_namespace,
- status_code=status_code,
- summary=summary,
- sync_to_thread=sync_to_thread,
- tags=tags,
- type_decoders=type_decoders,
- type_encoders=type_encoders,
- **kwargs,
- )
-
-
-class post(HTTPRouteHandler):
- """POST Route Decorator.
-
- Use this decorator to decorate an HTTP handler for POST requests.
- """
-
- def __init__(
- self,
- path: str | None | Sequence[str] = None,
- *,
- after_request: AfterRequestHookHandler | None = None,
- after_response: AfterResponseHookHandler | None = None,
- background: BackgroundTask | BackgroundTasks | None = None,
- before_request: BeforeRequestHookHandler | None = None,
- cache: bool | int | type[CACHE_FOREVER] = False,
- cache_control: CacheControlHeader | None = None,
- cache_key_builder: CacheKeyBuilder | None = None,
- dependencies: Dependencies | None = None,
- dto: type[AbstractDTO] | None | EmptyType = Empty,
- etag: ETag | None = None,
- exception_handlers: ExceptionHandlersMap | None = None,
- guards: Sequence[Guard] | None = None,
- media_type: MediaType | str | None = None,
- middleware: Sequence[Middleware] | None = None,
- name: str | None = None,
- opt: Mapping[str, Any] | None = None,
- request_class: type[Request] | None = None,
- response_class: type[Response] | None = None,
- response_cookies: ResponseCookies | None = None,
- response_headers: ResponseHeaders | None = None,
- return_dto: type[AbstractDTO] | None | EmptyType = Empty,
- signature_namespace: Mapping[str, Any] | None = None,
- status_code: int | None = None,
- sync_to_thread: bool | None = None,
- # OpenAPI related attributes
- content_encoding: str | None = None,
- content_media_type: str | None = None,
- deprecated: bool = False,
- description: str | None = None,
- include_in_schema: bool | EmptyType = Empty,
- operation_class: type[Operation] = Operation,
- operation_id: str | OperationIDCreator | None = None,
- raises: Sequence[type[HTTPException]] | None = None,
- response_description: str | None = None,
- responses: Mapping[int, ResponseSpec] | None = None,
- security: Sequence[SecurityRequirement] | None = None,
- summary: str | None = None,
- tags: Sequence[str] | None = None,
- type_decoders: TypeDecodersSequence | None = None,
- type_encoders: TypeEncodersMap | None = None,
- **kwargs: Any,
- ) -> None:
- """Initialize ``post``
-
- Args:
- path: A path fragment for the route handler function or a sequence of path fragments.
- If not given defaults to ``/``
- after_request: A sync or async function executed before a :class:`Request <.connection.Request>` is passed
- to any route handler. If this function returns a value, the request will not reach the route handler,
- and instead this value will be used.
- after_response: A sync or async function called after the response has been awaited. It receives the
- :class:`Request <.connection.Request>` object and should not return any values.
- background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or
- :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished.
- Defaults to ``None``.
- before_request: A sync or async function called immediately before calling the route handler. Receives
- the :class:`.connection.Request` instance and any non-``None`` return value is used for the response,
- bypassing the route handler.
- cache: Enables response caching if configured on the application level. Valid values are ``True`` or a number
- of seconds (e.g. ``120``) to cache the response.
- cache_control: A ``cache-control`` header of type
- :class:`CacheControlHeader <.datastructures.CacheControlHeader>` that will be added to the response.
- cache_key_builder: A :class:`cache-key builder function <.types.CacheKeyBuilder>`. Allows for customization
- of the cache key if caching is configured on the application level.
- dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances.
- dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and
- validation of request data.
- etag: An ``etag`` header of type :class:`ETag <.datastructures.ETag>` that will be added to the response.
- exception_handlers: A mapping of status codes and/or exception types to handler functions.
- guards: A sequence of :class:`Guard <.types.Guard>` callables.
- http_method: An :class:`http method string <.types.Method>`, a member of the enum
- :class:`HttpMethod <litestar.enums.HttpMethod>` or a list of these that correlates to the methods the
- route handler function should handle.
- media_type: A member of the :class:`MediaType <.enums.MediaType>` enum or a string with a
- valid IANA Media-Type.
- middleware: A sequence of :class:`Middleware <.types.Middleware>`.
- name: A string identifying the route handler.
- opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or
- wherever you have access to :class:`Request <.connection.Request>` or :class:`ASGI Scope <.types.Scope>`.
- request_class: A custom subclass of :class:`Request <.connection.Request>` to be used as route handler's
- default request.
- response_class: A custom subclass of :class:`Response <.response.Response>` to be used as route handler's
- default response.
- response_cookies: A sequence of :class:`Cookie <.datastructures.Cookie>` instances.
- response_headers: A string keyed mapping of :class:`ResponseHeader <.datastructures.ResponseHeader>`
- instances.
- responses: A mapping of additional status codes and a description of their expected content.
- This information will be included in the OpenAPI schema
- return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing
- outbound response data.
- signature_namespace: A mapping of names to types for use in forward reference resolution during signature modelling.
- status_code: An http status code for the response. Defaults to ``200`` for mixed method or ``GET``, ``PUT`` and
- ``PATCH``, ``201`` for ``POST`` and ``204`` for ``DELETE``.
- sync_to_thread: A boolean dictating whether the handler function will be executed in a worker thread or the
- main event loop. This has an effect only for sync handler functions. See using sync handler functions.
- content_encoding: A string describing the encoding of the content, e.g. ``base64``.
- content_media_type: A string designating the media-type of the content, e.g. ``image/png``.
- deprecated: A boolean dictating whether this route should be marked as deprecated in the OpenAPI schema.
- description: Text used for the route's schema description section.
- include_in_schema: A boolean flag dictating whether the route handler should be documented in the OpenAPI schema.
- operation_class: :class:`Operation <.openapi.spec.operation.Operation>` to be used with the route's OpenAPI schema.
- operation_id: Either a string or a callable returning a string. An identifier used for the route's schema operationId.
- raises: A list of exception classes extending from litestar.HttpException that is used for the OpenAPI documentation.
- This list should describe all exceptions raised within the route handler's function/method. The Litestar
- ValidationException will be added automatically for the schema if any validation is involved.
- response_description: Text used for the route's response schema description section.
- security: A sequence of dictionaries that contain information about which security scheme can be used on the endpoint.
- summary: Text used for the route's schema summary section.
- tags: A sequence of string tags that will be appended to the OpenAPI schema.
- type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec
- hook for deserialization.
- type_encoders: A mapping of types to callables that transform them into types supported for serialization.
- **kwargs: Any additional kwarg - will be set in the opt dictionary.
- """
- if "http_method" in kwargs:
- raise ImproperlyConfiguredException(MSG_SEMANTIC_ROUTE_HANDLER_WITH_HTTP)
- super().__init__(
- after_request=after_request,
- after_response=after_response,
- background=background,
- before_request=before_request,
- cache=cache,
- cache_control=cache_control,
- cache_key_builder=cache_key_builder,
- content_encoding=content_encoding,
- content_media_type=content_media_type,
- dependencies=dependencies,
- deprecated=deprecated,
- description=description,
- dto=dto,
- exception_handlers=exception_handlers,
- etag=etag,
- guards=guards,
- http_method=HttpMethod.POST,
- include_in_schema=include_in_schema,
- media_type=media_type,
- middleware=middleware,
- name=name,
- operation_class=operation_class,
- operation_id=operation_id,
- opt=opt,
- path=path,
- raises=raises,
- request_class=request_class,
- response_class=response_class,
- response_cookies=response_cookies,
- response_description=response_description,
- response_headers=response_headers,
- responses=responses,
- return_dto=return_dto,
- signature_namespace=signature_namespace,
- security=security,
- status_code=status_code,
- summary=summary,
- sync_to_thread=sync_to_thread,
- tags=tags,
- type_decoders=type_decoders,
- type_encoders=type_encoders,
- **kwargs,
- )
-
-
-class put(HTTPRouteHandler):
- """PUT Route Decorator.
-
- Use this decorator to decorate an HTTP handler for PUT requests.
- """
-
- def __init__(
- self,
- path: str | None | Sequence[str] = None,
- *,
- after_request: AfterRequestHookHandler | None = None,
- after_response: AfterResponseHookHandler | None = None,
- background: BackgroundTask | BackgroundTasks | None = None,
- before_request: BeforeRequestHookHandler | None = None,
- cache: bool | int | type[CACHE_FOREVER] = False,
- cache_control: CacheControlHeader | None = None,
- cache_key_builder: CacheKeyBuilder | None = None,
- dependencies: Dependencies | None = None,
- dto: type[AbstractDTO] | None | EmptyType = Empty,
- etag: ETag | None = None,
- exception_handlers: ExceptionHandlersMap | None = None,
- guards: Sequence[Guard] | None = None,
- media_type: MediaType | str | None = None,
- middleware: Sequence[Middleware] | None = None,
- name: str | None = None,
- opt: Mapping[str, Any] | None = None,
- request_class: type[Request] | None = None,
- response_class: type[Response] | None = None,
- response_cookies: ResponseCookies | None = None,
- response_headers: ResponseHeaders | None = None,
- return_dto: type[AbstractDTO] | None | EmptyType = Empty,
- signature_namespace: Mapping[str, Any] | None = None,
- status_code: int | None = None,
- sync_to_thread: bool | None = None,
- # OpenAPI related attributes
- content_encoding: str | None = None,
- content_media_type: str | None = None,
- deprecated: bool = False,
- description: str | None = None,
- include_in_schema: bool | EmptyType = Empty,
- operation_class: type[Operation] = Operation,
- operation_id: str | OperationIDCreator | None = None,
- raises: Sequence[type[HTTPException]] | None = None,
- response_description: str | None = None,
- responses: Mapping[int, ResponseSpec] | None = None,
- security: Sequence[SecurityRequirement] | None = None,
- summary: str | None = None,
- tags: Sequence[str] | None = None,
- type_decoders: TypeDecodersSequence | None = None,
- type_encoders: TypeEncodersMap | None = None,
- **kwargs: Any,
- ) -> None:
- """Initialize ``put``
-
- Args:
- path: A path fragment for the route handler function or a sequence of path fragments.
- If not given defaults to ``/``
- after_request: A sync or async function executed before a :class:`Request <.connection.Request>` is passed
- to any route handler. If this function returns a value, the request will not reach the route handler,
- and instead this value will be used.
- after_response: A sync or async function called after the response has been awaited. It receives the
- :class:`Request <.connection.Request>` object and should not return any values.
- background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or
- :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished.
- Defaults to ``None``.
- before_request: A sync or async function called immediately before calling the route handler. Receives
- the :class:`.connection.Request` instance and any non-``None`` return value is used for the response,
- bypassing the route handler.
- cache: Enables response caching if configured on the application level. Valid values are ``True`` or a number
- of seconds (e.g. ``120``) to cache the response.
- cache_control: A ``cache-control`` header of type
- :class:`CacheControlHeader <.datastructures.CacheControlHeader>` that will be added to the response.
- cache_key_builder: A :class:`cache-key builder function <.types.CacheKeyBuilder>`. Allows for customization
- of the cache key if caching is configured on the application level.
- dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances.
- dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and
- validation of request data.
- etag: An ``etag`` header of type :class:`ETag <.datastructures.ETag>` that will be added to the response.
- exception_handlers: A mapping of status codes and/or exception types to handler functions.
- guards: A sequence of :class:`Guard <.types.Guard>` callables.
- http_method: An :class:`http method string <.types.Method>`, a member of the enum
- :class:`HttpMethod <litestar.enums.HttpMethod>` or a list of these that correlates to the methods the
- route handler function should handle.
- media_type: A member of the :class:`MediaType <.enums.MediaType>` enum or a string with a
- valid IANA Media-Type.
- middleware: A sequence of :class:`Middleware <.types.Middleware>`.
- name: A string identifying the route handler.
- opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or
- wherever you have access to :class:`Request <.connection.Request>` or :class:`ASGI Scope <.types.Scope>`.
- request_class: A custom subclass of :class:`Request <.connection.Request>` to be used as route handler's
- default request.
- response_class: A custom subclass of :class:`Response <.response.Response>` to be used as route handler's
- default response.
- response_cookies: A sequence of :class:`Cookie <.datastructures.Cookie>` instances.
- response_headers: A string keyed mapping of :class:`ResponseHeader <.datastructures.ResponseHeader>`
- instances.
- responses: A mapping of additional status codes and a description of their expected content.
- This information will be included in the OpenAPI schema
- return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing
- outbound response data.
- signature_namespace: A mapping of names to types for use in forward reference resolution during signature modelling.
- status_code: An http status code for the response. Defaults to ``200`` for mixed method or ``GET``, ``PUT`` and
- ``PATCH``, ``201`` for ``POST`` and ``204`` for ``DELETE``.
- sync_to_thread: A boolean dictating whether the handler function will be executed in a worker thread or the
- main event loop. This has an effect only for sync handler functions. See using sync handler functions.
- content_encoding: A string describing the encoding of the content, e.g. ``base64``.
- content_media_type: A string designating the media-type of the content, e.g. ``image/png``.
- deprecated: A boolean dictating whether this route should be marked as deprecated in the OpenAPI schema.
- description: Text used for the route's schema description section.
- include_in_schema: A boolean flag dictating whether the route handler should be documented in the OpenAPI schema.
- operation_class: :class:`Operation <.openapi.spec.operation.Operation>` to be used with the route's OpenAPI schema.
- operation_id: Either a string or a callable returning a string. An identifier used for the route's schema operationId.
- raises: A list of exception classes extending from litestar.HttpException that is used for the OpenAPI documentation.
- This list should describe all exceptions raised within the route handler's function/method. The Litestar
- ValidationException will be added automatically for the schema if any validation is involved.
- response_description: Text used for the route's response schema description section.
- security: A sequence of dictionaries that contain information about which security scheme can be used on the endpoint.
- summary: Text used for the route's schema summary section.
- tags: A sequence of string tags that will be appended to the OpenAPI schema.
- type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec
- hook for deserialization.
- type_encoders: A mapping of types to callables that transform them into types supported for serialization.
- **kwargs: Any additional kwarg - will be set in the opt dictionary.
- """
- if "http_method" in kwargs:
- raise ImproperlyConfiguredException(MSG_SEMANTIC_ROUTE_HANDLER_WITH_HTTP)
- super().__init__(
- after_request=after_request,
- after_response=after_response,
- background=background,
- before_request=before_request,
- cache=cache,
- cache_control=cache_control,
- cache_key_builder=cache_key_builder,
- content_encoding=content_encoding,
- content_media_type=content_media_type,
- dependencies=dependencies,
- deprecated=deprecated,
- description=description,
- dto=dto,
- exception_handlers=exception_handlers,
- etag=etag,
- guards=guards,
- http_method=HttpMethod.PUT,
- include_in_schema=include_in_schema,
- media_type=media_type,
- middleware=middleware,
- name=name,
- operation_class=operation_class,
- operation_id=operation_id,
- opt=opt,
- path=path,
- raises=raises,
- request_class=request_class,
- response_class=response_class,
- response_cookies=response_cookies,
- response_description=response_description,
- response_headers=response_headers,
- responses=responses,
- return_dto=return_dto,
- security=security,
- signature_namespace=signature_namespace,
- status_code=status_code,
- summary=summary,
- sync_to_thread=sync_to_thread,
- tags=tags,
- type_decoders=type_decoders,
- type_encoders=type_encoders,
- **kwargs,
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__init__.py b/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__init__.py
deleted file mode 100644
index 5b24734..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from __future__ import annotations
-
-from litestar.handlers.websocket_handlers.listener import (
- WebsocketListener,
- WebsocketListenerRouteHandler,
- websocket_listener,
-)
-from litestar.handlers.websocket_handlers.route_handler import WebsocketRouteHandler, websocket
-
-__all__ = (
- "WebsocketListener",
- "WebsocketListenerRouteHandler",
- "WebsocketRouteHandler",
- "websocket",
- "websocket_listener",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index f6d1115..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/_utils.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/_utils.cpython-311.pyc
deleted file mode 100644
index c5ae4c8..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/_utils.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/listener.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/listener.cpython-311.pyc
deleted file mode 100644
index 38b8219..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/listener.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/route_handler.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/route_handler.cpython-311.pyc
deleted file mode 100644
index 0e92ccd..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/__pycache__/route_handler.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/_utils.py b/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/_utils.py
deleted file mode 100644
index bcd90ac..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/_utils.py
+++ /dev/null
@@ -1,154 +0,0 @@
-from __future__ import annotations
-
-from functools import wraps
-from inspect import Parameter, Signature
-from typing import TYPE_CHECKING, Any, Callable, Coroutine, Dict
-
-from msgspec.json import Encoder as JsonEncoder
-
-from litestar.di import Provide
-from litestar.serialization import decode_json
-from litestar.types.builtin_types import NoneType
-from litestar.utils import ensure_async_callable
-from litestar.utils.helpers import unwrap_partial
-
-if TYPE_CHECKING:
- from litestar import WebSocket
- from litestar.handlers.websocket_handlers.listener import WebsocketListenerRouteHandler
- from litestar.types import AnyCallable
- from litestar.utils.signature import ParsedSignature
-
-
-def create_handle_receive(listener: WebsocketListenerRouteHandler) -> Callable[[WebSocket], Coroutine[Any, None, None]]:
- if data_dto := listener.resolve_data_dto():
-
- async def handle_receive(socket: WebSocket) -> Any:
- received_data = await socket.receive_data(mode=listener._receive_mode)
- return data_dto(socket).decode_bytes(
- received_data.encode("utf-8") if isinstance(received_data, str) else received_data
- )
-
- elif listener.parsed_data_field and listener.parsed_data_field.annotation is str:
-
- async def handle_receive(socket: WebSocket) -> Any:
- received_data = await socket.receive_data(mode=listener._receive_mode)
- return received_data.decode("utf-8") if isinstance(received_data, bytes) else received_data
-
- elif listener.parsed_data_field and listener.parsed_data_field.annotation is bytes:
-
- async def handle_receive(socket: WebSocket) -> Any:
- received_data = await socket.receive_data(mode=listener._receive_mode)
- return received_data.encode("utf-8") if isinstance(received_data, str) else received_data
-
- else:
-
- async def handle_receive(socket: WebSocket) -> Any:
- received_data = await socket.receive_data(mode=listener._receive_mode)
- return decode_json(value=received_data, type_decoders=socket.route_handler.resolve_type_decoders())
-
- return handle_receive
-
-
-def create_handle_send(
- listener: WebsocketListenerRouteHandler,
-) -> Callable[[WebSocket, Any], Coroutine[None, None, None]]:
- json_encoder = JsonEncoder(enc_hook=listener.default_serializer)
-
- if return_dto := listener.resolve_return_dto():
-
- async def handle_send(socket: WebSocket, data: Any) -> None:
- encoded_data = return_dto(socket).data_to_encodable_type(data)
- data = json_encoder.encode(encoded_data)
- await socket.send_data(data=data, mode=listener._send_mode)
-
- elif listener.parsed_return_field.is_subclass_of((str, bytes)) or (
- listener.parsed_return_field.is_optional and listener.parsed_return_field.has_inner_subclass_of((str, bytes))
- ):
-
- async def handle_send(socket: WebSocket, data: Any) -> None:
- await socket.send_data(data=data, mode=listener._send_mode)
-
- else:
-
- async def handle_send(socket: WebSocket, data: Any) -> None:
- data = json_encoder.encode(data)
- await socket.send_data(data=data, mode=listener._send_mode)
-
- return handle_send
-
-
-class ListenerHandler:
- __slots__ = ("_can_send_data", "_fn", "_listener", "_pass_socket")
-
- def __init__(
- self,
- listener: WebsocketListenerRouteHandler,
- fn: AnyCallable,
- parsed_signature: ParsedSignature,
- namespace: dict[str, Any],
- ) -> None:
- self._can_send_data = not parsed_signature.return_type.is_subclass_of(NoneType)
- self._fn = ensure_async_callable(fn)
- self._listener = listener
- self._pass_socket = "socket" in parsed_signature.parameters
-
- async def __call__(
- self,
- *args: Any,
- socket: WebSocket,
- connection_lifespan_dependencies: Dict[str, Any], # noqa: UP006
- **kwargs: Any,
- ) -> None:
- lifespan_mananger = self._listener._connection_lifespan or self._listener.default_connection_lifespan
- handle_send = self._listener.resolve_send_handler() if self._can_send_data else None
- handle_receive = self._listener.resolve_receive_handler()
-
- if self._pass_socket:
- kwargs["socket"] = socket
-
- async with lifespan_mananger(**connection_lifespan_dependencies):
- while True:
- received_data = await handle_receive(socket)
- data = await self._fn(*args, data=received_data, **kwargs)
- if handle_send:
- await handle_send(socket, data)
-
-
-def create_handler_signature(callback_signature: Signature) -> Signature:
- """Creates a :class:`Signature` for the handler function for signature modelling.
-
- This is required for two reasons:
-
- 1. the :class:`.handlers.WebsocketHandler` signature model cannot contain the ``data`` parameter, which is
- required for :class:`.handlers.websocket_listener` handlers.
- 2. the :class;`.handlers.WebsocketHandler` signature model must include the ``socket`` parameter, which is
- optional for :class:`.handlers.websocket_listener` handlers.
-
- Args:
- callback_signature: The :class:`Signature` of the listener callback.
-
- Returns:
- The :class:`Signature` for the listener callback as required for signature modelling.
- """
- new_params = [p for p in callback_signature.parameters.values() if p.name != "data"]
- if "socket" not in callback_signature.parameters:
- new_params.append(Parameter(name="socket", kind=Parameter.KEYWORD_ONLY, annotation="WebSocket"))
-
- new_params.append(
- Parameter(name="connection_lifespan_dependencies", kind=Parameter.KEYWORD_ONLY, annotation="Dict[str, Any]")
- )
-
- return callback_signature.replace(parameters=new_params)
-
-
-def create_stub_dependency(src: AnyCallable) -> Provide:
- """Create a stub dependency, accepting any kwargs defined in ``src``, and
- wrap it in ``Provide``
- """
- src = unwrap_partial(src)
-
- @wraps(src)
- async def stub(**kwargs: Any) -> Dict[str, Any]: # noqa: UP006
- return kwargs
-
- return Provide(stub)
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/listener.py b/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/listener.py
deleted file mode 100644
index 86fefc9..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/listener.py
+++ /dev/null
@@ -1,417 +0,0 @@
-from __future__ import annotations
-
-from abc import ABC, abstractmethod
-from contextlib import AbstractAsyncContextManager, asynccontextmanager
-from typing import (
- TYPE_CHECKING,
- Any,
- AsyncGenerator,
- Callable,
- Dict,
- Mapping,
- Optional,
- cast,
- overload,
-)
-
-from litestar._signature import SignatureModel
-from litestar.connection import WebSocket
-from litestar.exceptions import ImproperlyConfiguredException, WebSocketDisconnect
-from litestar.types import (
- AnyCallable,
- Dependencies,
- Empty,
- EmptyType,
- ExceptionHandler,
- Guard,
- Middleware,
- TypeEncodersMap,
-)
-from litestar.utils import ensure_async_callable
-from litestar.utils.signature import ParsedSignature, get_fn_type_hints
-
-from ._utils import (
- ListenerHandler,
- create_handle_receive,
- create_handle_send,
- create_handler_signature,
- create_stub_dependency,
-)
-from .route_handler import WebsocketRouteHandler
-
-if TYPE_CHECKING:
- from typing import Coroutine
-
- from typing_extensions import Self
-
- from litestar import Router
- from litestar.dto import AbstractDTO
- from litestar.types.asgi_types import WebSocketMode
- from litestar.types.composite_types import TypeDecodersSequence
-
-__all__ = ("WebsocketListener", "WebsocketListenerRouteHandler", "websocket_listener")
-
-
-class WebsocketListenerRouteHandler(WebsocketRouteHandler):
- """A websocket listener that automatically accepts a connection, handles disconnects,
- invokes a callback function every time new data is received and sends any data
- returned
- """
-
- __slots__ = {
- "connection_accept_handler": "Callback to accept a WebSocket connection. By default, calls WebSocket.accept",
- "on_accept": "Callback invoked after a WebSocket connection has been accepted",
- "on_disconnect": "Callback invoked after a WebSocket connection has been closed",
- "weboscket_class": "WebSocket class",
- "_connection_lifespan": None,
- "_handle_receive": None,
- "_handle_send": None,
- "_receive_mode": None,
- "_send_mode": None,
- }
-
- @overload
- def __init__(
- self,
- path: str | list[str] | None = None,
- *,
- connection_lifespan: Callable[..., AbstractAsyncContextManager[Any]] | None = None,
- dependencies: Dependencies | None = None,
- dto: type[AbstractDTO] | None | EmptyType = Empty,
- exception_handlers: dict[int | type[Exception], ExceptionHandler] | None = None,
- guards: list[Guard] | None = None,
- middleware: list[Middleware] | None = None,
- receive_mode: WebSocketMode = "text",
- send_mode: WebSocketMode = "text",
- name: str | None = None,
- opt: dict[str, Any] | None = None,
- return_dto: type[AbstractDTO] | None | EmptyType = Empty,
- signature_namespace: Mapping[str, Any] | None = None,
- type_decoders: TypeDecodersSequence | None = None,
- type_encoders: TypeEncodersMap | None = None,
- websocket_class: type[WebSocket] | None = None,
- **kwargs: Any,
- ) -> None: ...
-
- @overload
- def __init__(
- self,
- path: str | list[str] | None = None,
- *,
- connection_accept_handler: Callable[[WebSocket], Coroutine[Any, Any, None]] = WebSocket.accept,
- dependencies: Dependencies | None = None,
- dto: type[AbstractDTO] | None | EmptyType = Empty,
- exception_handlers: dict[int | type[Exception], ExceptionHandler] | None = None,
- guards: list[Guard] | None = None,
- middleware: list[Middleware] | None = None,
- receive_mode: WebSocketMode = "text",
- send_mode: WebSocketMode = "text",
- name: str | None = None,
- on_accept: AnyCallable | None = None,
- on_disconnect: AnyCallable | None = None,
- opt: dict[str, Any] | None = None,
- return_dto: type[AbstractDTO] | None | EmptyType = Empty,
- signature_namespace: Mapping[str, Any] | None = None,
- type_decoders: TypeDecodersSequence | None = None,
- type_encoders: TypeEncodersMap | None = None,
- websocket_class: type[WebSocket] | None = None,
- **kwargs: Any,
- ) -> None: ...
-
- def __init__(
- self,
- path: str | list[str] | None = None,
- *,
- connection_accept_handler: Callable[[WebSocket], Coroutine[Any, Any, None]] = WebSocket.accept,
- connection_lifespan: Callable[..., AbstractAsyncContextManager[Any]] | None = None,
- dependencies: Dependencies | None = None,
- dto: type[AbstractDTO] | None | EmptyType = Empty,
- exception_handlers: dict[int | type[Exception], ExceptionHandler] | None = None,
- guards: list[Guard] | None = None,
- middleware: list[Middleware] | None = None,
- receive_mode: WebSocketMode = "text",
- send_mode: WebSocketMode = "text",
- name: str | None = None,
- on_accept: AnyCallable | None = None,
- on_disconnect: AnyCallable | None = None,
- opt: dict[str, Any] | None = None,
- return_dto: type[AbstractDTO] | None | EmptyType = Empty,
- signature_namespace: Mapping[str, Any] | None = None,
- type_decoders: TypeDecodersSequence | None = None,
- type_encoders: TypeEncodersMap | None = None,
- websocket_class: type[WebSocket] | None = None,
- **kwargs: Any,
- ) -> None:
- """Initialize ``WebsocketRouteHandler``
-
- Args:
- path: A path fragment for the route handler function or a sequence of path fragments. If not given defaults
- to ``/``
- connection_accept_handler: A callable that accepts a :class:`WebSocket <.connection.WebSocket>` instance
- and returns a coroutine that when awaited, will accept the connection. Defaults to ``WebSocket.accept``.
- connection_lifespan: An asynchronous context manager, handling the lifespan of the connection. By default,
- it calls the ``connection_accept_handler``, ``on_connect`` and ``on_disconnect``. Can request any
- dependencies, for example the :class:`WebSocket <.connection.WebSocket>` connection
- dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances.
- dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and
- validation of request data.
- exception_handlers: A mapping of status codes and/or exception types to handler functions.
- guards: A sequence of :class:`Guard <.types.Guard>` callables.
- middleware: A sequence of :class:`Middleware <.types.Middleware>`.
- receive_mode: Websocket mode to receive data in, either `text` or `binary`.
- send_mode: Websocket mode to receive data in, either `text` or `binary`.
- name: A string identifying the route handler.
- on_accept: Callback invoked after a connection has been accepted. Can request any dependencies, for example
- the :class:`WebSocket <.connection.WebSocket>` connection
- on_disconnect: Callback invoked after a connection has been closed. Can request any dependencies, for
- example the :class:`WebSocket <.connection.WebSocket>` connection
- opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or
- wherever you have access to :class:`Request <.connection.Request>` or
- :class:`ASGI Scope <.types.Scope>`.
- return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing
- outbound response data.
- signature_namespace: A mapping of names to types for use in forward reference resolution during signature
- modelling.
- type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec
- hook for deserialization.
- type_encoders: A mapping of types to callables that transform them into types supported for serialization.
- **kwargs: Any additional kwarg - will be set in the opt dictionary.
- websocket_class: A custom subclass of :class:`WebSocket <.connection.WebSocket>` to be used as route handler's
- default websocket class.
- """
- if connection_lifespan and any([on_accept, on_disconnect, connection_accept_handler is not WebSocket.accept]):
- raise ImproperlyConfiguredException(
- "connection_lifespan can not be used with connection hooks "
- "(on_accept, on_disconnect, connection_accept_handler)",
- )
-
- self._receive_mode: WebSocketMode = receive_mode
- self._send_mode: WebSocketMode = send_mode
- self._connection_lifespan = connection_lifespan
- self._send_handler: Callable[[WebSocket, Any], Coroutine[None, None, None]] | EmptyType = Empty
- self._receive_handler: Callable[[WebSocket], Any] | EmptyType = Empty
-
- self.connection_accept_handler = connection_accept_handler
- self.on_accept = ensure_async_callable(on_accept) if on_accept else None
- self.on_disconnect = ensure_async_callable(on_disconnect) if on_disconnect else None
- self.type_decoders = type_decoders
- self.type_encoders = type_encoders
- self.websocket_class = websocket_class
-
- listener_dependencies = dict(dependencies or {})
-
- listener_dependencies["connection_lifespan_dependencies"] = create_stub_dependency(
- connection_lifespan or self.default_connection_lifespan
- )
-
- if self.on_accept:
- listener_dependencies["on_accept_dependencies"] = create_stub_dependency(self.on_accept)
-
- if self.on_disconnect:
- listener_dependencies["on_disconnect_dependencies"] = create_stub_dependency(self.on_disconnect)
-
- super().__init__(
- path=path,
- dependencies=listener_dependencies,
- exception_handlers=exception_handlers,
- guards=guards,
- middleware=middleware,
- name=name,
- opt=opt,
- signature_namespace=signature_namespace,
- dto=dto,
- return_dto=return_dto,
- type_decoders=type_decoders,
- type_encoders=type_encoders,
- websocket_class=websocket_class,
- **kwargs,
- )
-
- def __call__(self, fn: AnyCallable) -> Self:
- parsed_signature = ParsedSignature.from_fn(fn, self.resolve_signature_namespace())
-
- if "data" not in parsed_signature.parameters:
- raise ImproperlyConfiguredException("Websocket listeners must accept a 'data' parameter")
-
- for param in ("request", "body"):
- if param in parsed_signature.parameters:
- raise ImproperlyConfiguredException(f"The {param} kwarg is not supported with websocket listeners")
-
- # we are manipulating the signature of the decorated function below, so we must store the original values for
- # use elsewhere.
- self._parsed_return_field = parsed_signature.return_type
- self._parsed_data_field = parsed_signature.parameters.get("data")
- self._parsed_fn_signature = ParsedSignature.from_signature(
- create_handler_signature(parsed_signature.original_signature),
- fn_type_hints={
- **get_fn_type_hints(fn, namespace=self.resolve_signature_namespace()),
- **get_fn_type_hints(ListenerHandler.__call__, namespace=self.resolve_signature_namespace()),
- },
- )
-
- return super().__call__(
- ListenerHandler(
- listener=self, fn=fn, parsed_signature=parsed_signature, namespace=self.resolve_signature_namespace()
- )
- )
-
- def _validate_handler_function(self) -> None:
- """Validate the route handler function once it's set by inspecting its return annotations."""
- # validation occurs in the call method
-
- @property
- def signature_model(self) -> type[SignatureModel]:
- """Get the signature model for the route handler.
-
- Returns:
- A signature model for the route handler.
-
- """
- if self._signature_model is Empty:
- self._signature_model = SignatureModel.create(
- dependency_name_set=self.dependency_name_set,
- fn=cast("AnyCallable", self.fn),
- parsed_signature=self.parsed_fn_signature,
- type_decoders=self.resolve_type_decoders(),
- )
- return self._signature_model
-
- @asynccontextmanager
- async def default_connection_lifespan(
- self,
- socket: WebSocket,
- on_accept_dependencies: Optional[Dict[str, Any]] = None, # noqa: UP006, UP007
- on_disconnect_dependencies: Optional[Dict[str, Any]] = None, # noqa: UP006, UP007
- ) -> AsyncGenerator[None, None]:
- """Handle the connection lifespan of a :class:`WebSocket <.connection.WebSocket>`.
-
- Args:
- socket: The :class:`WebSocket <.connection.WebSocket>` connection
- on_accept_dependencies: Dependencies requested by the :attr:`on_accept` hook
- on_disconnect_dependencies: Dependencies requested by the :attr:`on_disconnect` hook
-
- By, default this will
-
- - Call :attr:`connection_accept_handler` to accept a connection
- - Call :attr:`on_accept` if defined after a connection has been accepted
- - Call :attr:`on_disconnect` upon leaving the context
- """
- await self.connection_accept_handler(socket)
-
- if self.on_accept:
- await self.on_accept(**(on_accept_dependencies or {}))
-
- try:
- yield
- except WebSocketDisconnect:
- pass
- finally:
- if self.on_disconnect:
- await self.on_disconnect(**(on_disconnect_dependencies or {}))
-
- def resolve_receive_handler(self) -> Callable[[WebSocket], Any]:
- if self._receive_handler is Empty:
- self._receive_handler = create_handle_receive(self)
- return self._receive_handler
-
- def resolve_send_handler(self) -> Callable[[WebSocket, Any], Coroutine[None, None, None]]:
- if self._send_handler is Empty:
- self._send_handler = create_handle_send(self)
- return self._send_handler
-
-
-websocket_listener = WebsocketListenerRouteHandler
-
-
-class WebsocketListener(ABC):
- path: str | list[str] | None = None
- """A path fragment for the route handler function or a sequence of path fragments. If not given defaults to ``/``"""
- dependencies: Dependencies | None = None
- """A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances."""
- dto: type[AbstractDTO] | None | EmptyType = Empty
- """:class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and validation of request data"""
- exception_handlers: dict[int | type[Exception], ExceptionHandler] | None = None
- """A mapping of status codes and/or exception types to handler functions."""
- guards: list[Guard] | None = None
- """A sequence of :class:`Guard <.types.Guard>` callables."""
- middleware: list[Middleware] | None = None
- """A sequence of :class:`Middleware <.types.Middleware>`."""
- on_accept: AnyCallable | None = None
- """Called after a :class:`WebSocket <.connection.WebSocket>` connection has been accepted. Can receive any dependencies"""
- on_disconnect: AnyCallable | None = None
- """Called after a :class:`WebSocket <.connection.WebSocket>` connection has been disconnected. Can receive any dependencies"""
- receive_mode: WebSocketMode = "text"
- """:class:`WebSocket <.connection.WebSocket>` mode to receive data in, either ``text`` or ``binary``."""
- send_mode: WebSocketMode = "text"
- """Websocket mode to send data in, either `text` or `binary`."""
- name: str | None = None
- """A string identifying the route handler."""
- opt: dict[str, Any] | None = None
- """
- A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or wherever you
- have access to :class:`Request <.connection.Request>` or :class:`ASGI Scope <.types.Scope>`.
- """
- return_dto: type[AbstractDTO] | None | EmptyType = Empty
- """:class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing outbound response data."""
- signature_namespace: Mapping[str, Any] | None = None
- """
- A mapping of names to types for use in forward reference resolution during signature modelling.
- """
- type_decoders: TypeDecodersSequence | None = None
- """
- type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec
- hook for deserialization.
- """
- type_encoders: TypeEncodersMap | None = None
- """
- type_encoders: A mapping of types to callables that transform them into types supported for serialization.
- """
- websocket_class: type[WebSocket] | None = None
- """
- websocket_class: A custom subclass of :class:`WebSocket <.connection.WebSocket>` to be used as route handler's
- default websocket class.
- """
-
- def __init__(self, owner: Router) -> None:
- """Initialize a WebsocketListener instance.
-
- Args:
- owner: The :class:`Router <.router.Router>` instance that owns this listener.
- """
- self._owner = owner
-
- def to_handler(self) -> WebsocketListenerRouteHandler:
- handler = WebsocketListenerRouteHandler(
- dependencies=self.dependencies,
- dto=self.dto,
- exception_handlers=self.exception_handlers,
- guards=self.guards,
- middleware=self.middleware,
- send_mode=self.send_mode,
- receive_mode=self.receive_mode,
- name=self.name,
- on_accept=self.on_accept,
- on_disconnect=self.on_disconnect,
- opt=self.opt,
- path=self.path,
- return_dto=self.return_dto,
- signature_namespace=self.signature_namespace,
- type_decoders=self.type_decoders,
- type_encoders=self.type_encoders,
- websocket_class=self.websocket_class,
- )(self.on_receive)
- handler.owner = self._owner
- return handler
-
- @abstractmethod
- def on_receive(self, *args: Any, **kwargs: Any) -> Any:
- """Called after data has been received from the WebSocket.
-
- This should take a ``data`` argument, receiving the processed WebSocket data,
- and can additionally include handler dependencies such as ``state``, or other
- regular dependencies.
-
- Data returned from this function will be serialized and sent via the socket
- according to handler configuration.
- """
- raise NotImplementedError
diff --git a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/route_handler.py b/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/route_handler.py
deleted file mode 100644
index edb49c3..0000000
--- a/venv/lib/python3.11/site-packages/litestar/handlers/websocket_handlers/route_handler.py
+++ /dev/null
@@ -1,99 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any, Mapping
-
-from litestar.connection import WebSocket
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.handlers import BaseRouteHandler
-from litestar.types.builtin_types import NoneType
-from litestar.utils.predicates import is_async_callable
-
-if TYPE_CHECKING:
- from litestar.types import Dependencies, ExceptionHandler, Guard, Middleware
-
-
-class WebsocketRouteHandler(BaseRouteHandler):
- """Websocket route handler decorator.
-
- Use this decorator to decorate websocket handler functions.
- """
-
- def __init__(
- self,
- path: str | list[str] | None = None,
- *,
- dependencies: Dependencies | None = None,
- exception_handlers: dict[int | type[Exception], ExceptionHandler] | None = None,
- guards: list[Guard] | None = None,
- middleware: list[Middleware] | None = None,
- name: str | None = None,
- opt: dict[str, Any] | None = None,
- signature_namespace: Mapping[str, Any] | None = None,
- websocket_class: type[WebSocket] | None = None,
- **kwargs: Any,
- ) -> None:
- """Initialize ``WebsocketRouteHandler``
-
- Args:
- path: A path fragment for the route handler function or a sequence of path fragments. If not given defaults
- to ``/``
- dependencies: A string keyed mapping of dependency :class:`Provider <.di.Provide>` instances.
- exception_handlers: A mapping of status codes and/or exception types to handler functions.
- guards: A sequence of :class:`Guard <.types.Guard>` callables.
- middleware: A sequence of :class:`Middleware <.types.Middleware>`.
- name: A string identifying the route handler.
- opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or
- wherever you have access to :class:`Request <.connection.Request>` or
- :class:`ASGI Scope <.types.Scope>`.
- signature_namespace: A mapping of names to types for use in forward reference resolution during signature modelling.
- type_encoders: A mapping of types to callables that transform them into types supported for serialization.
- **kwargs: Any additional kwarg - will be set in the opt dictionary.
- websocket_class: A custom subclass of :class:`WebSocket <.connection.WebSocket>` to be used as route handler's
- default websocket class.
- """
- self.websocket_class = websocket_class
-
- super().__init__(
- path=path,
- dependencies=dependencies,
- exception_handlers=exception_handlers,
- guards=guards,
- middleware=middleware,
- name=name,
- opt=opt,
- signature_namespace=signature_namespace,
- **kwargs,
- )
-
- def resolve_websocket_class(self) -> type[WebSocket]:
- """Return the closest custom WebSocket class in the owner graph or the default Websocket class.
-
- This method is memoized so the computation occurs only once.
-
- Returns:
- The default :class:`WebSocket <.connection.WebSocket>` class for the route handler.
- """
- return next(
- (layer.websocket_class for layer in reversed(self.ownership_layers) if layer.websocket_class is not None),
- WebSocket,
- )
-
- def _validate_handler_function(self) -> None:
- """Validate the route handler function once it's set by inspecting its return annotations."""
- super()._validate_handler_function()
-
- if not self.parsed_fn_signature.return_type.is_subclass_of(NoneType):
- raise ImproperlyConfiguredException("Websocket handler functions should return 'None'")
-
- if "socket" not in self.parsed_fn_signature.parameters:
- raise ImproperlyConfiguredException("Websocket handlers must set a 'socket' kwarg")
-
- for param in ("request", "body", "data"):
- if param in self.parsed_fn_signature.parameters:
- raise ImproperlyConfiguredException(f"The {param} kwarg is not supported with websocket handlers")
-
- if not is_async_callable(self.fn):
- raise ImproperlyConfiguredException("Functions decorated with 'websocket' must be async functions")
-
-
-websocket = WebsocketRouteHandler
diff --git a/venv/lib/python3.11/site-packages/litestar/logging/__init__.py b/venv/lib/python3.11/site-packages/litestar/logging/__init__.py
deleted file mode 100644
index b05ceba..0000000
--- a/venv/lib/python3.11/site-packages/litestar/logging/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from .config import BaseLoggingConfig, LoggingConfig, StructLoggingConfig
-
-__all__ = ("BaseLoggingConfig", "StructLoggingConfig", "LoggingConfig")
diff --git a/venv/lib/python3.11/site-packages/litestar/logging/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/logging/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 6a830eb..0000000
--- a/venv/lib/python3.11/site-packages/litestar/logging/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/logging/__pycache__/_utils.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/logging/__pycache__/_utils.cpython-311.pyc
deleted file mode 100644
index ba06e72..0000000
--- a/venv/lib/python3.11/site-packages/litestar/logging/__pycache__/_utils.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/logging/__pycache__/config.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/logging/__pycache__/config.cpython-311.pyc
deleted file mode 100644
index f1c97d4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/logging/__pycache__/config.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/logging/__pycache__/picologging.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/logging/__pycache__/picologging.cpython-311.pyc
deleted file mode 100644
index 1488885..0000000
--- a/venv/lib/python3.11/site-packages/litestar/logging/__pycache__/picologging.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/logging/__pycache__/standard.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/logging/__pycache__/standard.cpython-311.pyc
deleted file mode 100644
index ceda61d..0000000
--- a/venv/lib/python3.11/site-packages/litestar/logging/__pycache__/standard.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/logging/_utils.py b/venv/lib/python3.11/site-packages/litestar/logging/_utils.py
deleted file mode 100644
index ee67b9f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/logging/_utils.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from __future__ import annotations
-
-from typing import Any
-
-__all__ = ("resolve_handlers",)
-
-
-def resolve_handlers(handlers: list[Any]) -> list[Any]:
- """Convert list of string of handlers to the object of respective handler.
-
- Indexing the list performs the evaluation of the object.
-
- Args:
- handlers: An instance of 'ConvertingList'
-
- Returns:
- A list of resolved handlers.
-
- Notes:
- Due to missing typing in 'typeshed' we cannot type this as ConvertingList for now.
- """
- return [handlers[i] for i in range(len(handlers))]
diff --git a/venv/lib/python3.11/site-packages/litestar/logging/config.py b/venv/lib/python3.11/site-packages/litestar/logging/config.py
deleted file mode 100644
index a4a3713..0000000
--- a/venv/lib/python3.11/site-packages/litestar/logging/config.py
+++ /dev/null
@@ -1,509 +0,0 @@
-from __future__ import annotations
-
-import sys
-from abc import ABC, abstractmethod
-from dataclasses import asdict, dataclass, field, fields
-from importlib.util import find_spec
-from logging import INFO
-from typing import TYPE_CHECKING, Any, Callable, Literal, cast
-
-from litestar.exceptions import ImproperlyConfiguredException, MissingDependencyException
-from litestar.serialization.msgspec_hooks import _msgspec_json_encoder
-from litestar.utils.deprecation import deprecated
-
-__all__ = ("BaseLoggingConfig", "LoggingConfig", "StructLoggingConfig")
-
-
-if TYPE_CHECKING:
- from collections.abc import Iterable
- from typing import NoReturn
-
- # these imports are duplicated on purpose so sphinx autodoc can find and link them
- from structlog.types import BindableLogger, Processor, WrappedLogger
- from structlog.typing import EventDict
-
- from litestar.types import Logger, Scope
- from litestar.types.callable_types import ExceptionLoggingHandler, GetLogger
-
-
-try:
- from structlog.types import BindableLogger, Processor, WrappedLogger
-except ImportError:
- BindableLogger = Any # type: ignore[assignment, misc]
- Processor = Any # type: ignore[misc]
- WrappedLogger = Any # type: ignore[misc]
-
-
-default_handlers: dict[str, dict[str, Any]] = {
- "console": {
- "class": "logging.StreamHandler",
- "level": "DEBUG",
- "formatter": "standard",
- },
- "queue_listener": {
- "class": "litestar.logging.standard.QueueListenerHandler",
- "level": "DEBUG",
- "formatter": "standard",
- },
-}
-
-if sys.version_info >= (3, 12, 0):
- default_handlers["queue_listener"].update(
- {
- "class": "logging.handlers.QueueHandler",
- "queue": {
- "()": "queue.Queue",
- "maxsize": -1,
- },
- "listener": "litestar.logging.standard.LoggingQueueListener",
- "handlers": ["console"],
- }
- )
-
- # do not format twice, the console handler will do the job
- del default_handlers["queue_listener"]["formatter"]
-
-
-default_picologging_handlers: dict[str, dict[str, Any]] = {
- "console": {
- "class": "picologging.StreamHandler",
- "level": "DEBUG",
- "formatter": "standard",
- },
- "queue_listener": {
- "class": "litestar.logging.picologging.QueueListenerHandler",
- "level": "DEBUG",
- "formatter": "standard",
- },
-}
-
-
-def get_logger_placeholder(_: str | None = None) -> NoReturn:
- """Raise: An :class:`ImproperlyConfiguredException <.exceptions.ImproperlyConfiguredException>`"""
- raise ImproperlyConfiguredException(
- "cannot call '.get_logger' without passing 'logging_config' to the Litestar constructor first"
- )
-
-
-def _get_default_handlers() -> dict[str, dict[str, Any]]:
- """Return the default logging handlers for the config.
-
- Returns:
- A dictionary of logging handlers
- """
- if find_spec("picologging"):
- return default_picologging_handlers
- return default_handlers
-
-
-def _default_exception_logging_handler_factory(
- is_struct_logger: bool, traceback_line_limit: int
-) -> ExceptionLoggingHandler:
- """Create an exception logging handler function.
-
- Args:
- is_struct_logger: Whether the logger is a structlog instance.
- traceback_line_limit: Maximal number of lines to log from the
- traceback.
-
- Returns:
- An exception logging handler.
- """
-
- def _default_exception_logging_handler(logger: Logger, scope: Scope, tb: list[str]) -> None:
- # we limit the length of the stack trace to 20 lines.
- first_line = tb.pop(0)
-
- if is_struct_logger:
- logger.exception(
- "Uncaught Exception",
- connection_type=scope["type"],
- path=scope["path"],
- traceback="".join(tb[-traceback_line_limit:]),
- )
- else:
- stack_trace = first_line + "".join(tb[-traceback_line_limit:])
- logger.exception(
- "exception raised on %s connection to route %s\n\n%s", scope["type"], scope["path"], stack_trace
- )
-
- return _default_exception_logging_handler
-
-
-class BaseLoggingConfig(ABC):
- """Abstract class that should be extended by logging configs."""
-
- __slots__ = ("log_exceptions", "traceback_line_limit", "exception_logging_handler")
-
- log_exceptions: Literal["always", "debug", "never"]
- """Should exceptions be logged, defaults to log exceptions when ``app.debug == True``'"""
- traceback_line_limit: int
- """Max number of lines to print for exception traceback"""
- exception_logging_handler: ExceptionLoggingHandler | None
- """Handler function for logging exceptions."""
-
- @abstractmethod
- def configure(self) -> GetLogger:
- """Return logger with the given configuration.
-
- Returns:
- A 'logging.getLogger' like function.
- """
- raise NotImplementedError("abstract method")
-
- @staticmethod
- def set_level(logger: Any, level: int) -> None:
- """Provides a consistent interface to call `setLevel` for all loggers."""
- raise NotImplementedError("abstract method")
-
-
-@dataclass
-class LoggingConfig(BaseLoggingConfig):
- """Configuration class for standard logging.
-
- Notes:
- - If 'picologging' is installed it will be used by default.
- """
-
- version: Literal[1] = field(default=1)
- """The only valid value at present is 1."""
- incremental: bool = field(default=False)
- """Whether the configuration is to be interpreted as incremental to the existing configuration.
-
- Notes:
- - This option is ignored for 'picologging'
- """
- disable_existing_loggers: bool = field(default=False)
- """Whether any existing non-root loggers are to be disabled."""
- filters: dict[str, dict[str, Any]] | None = field(default=None)
- """A dict in which each key is a filter id and each value is a dict describing how to configure the corresponding
- Filter instance.
- """
- propagate: bool = field(default=True)
- """If messages must propagate to handlers higher up the logger hierarchy from this logger."""
- formatters: dict[str, dict[str, Any]] = field(
- default_factory=lambda: {
- "standard": {"format": "%(levelname)s - %(asctime)s - %(name)s - %(module)s - %(message)s"}
- }
- )
- handlers: dict[str, dict[str, Any]] = field(default_factory=_get_default_handlers)
- """A dict in which each key is a handler id and each value is a dict describing how to configure the corresponding
- Handler instance.
- """
- loggers: dict[str, dict[str, Any]] = field(
- default_factory=lambda: {
- "litestar": {"level": "INFO", "handlers": ["queue_listener"], "propagate": False},
- }
- )
- """A dict in which each key is a logger name and each value is a dict describing how to configure the corresponding
- Logger instance.
- """
- root: dict[str, dict[str, Any] | list[Any] | str] = field(
- default_factory=lambda: {
- "handlers": ["queue_listener"],
- "level": "INFO",
- }
- )
- """This will be the configuration for the root logger.
-
- Processing of the configuration will be as for any logger, except that the propagate setting will not be applicable.
- """
- configure_root_logger: bool = field(default=True)
- """Should the root logger be configured, defaults to True for ease of configuration."""
- log_exceptions: Literal["always", "debug", "never"] = field(default="debug")
- """Should exceptions be logged, defaults to log exceptions when 'app.debug == True'"""
- traceback_line_limit: int = field(default=20)
- """Max number of lines to print for exception traceback"""
- exception_logging_handler: ExceptionLoggingHandler | None = field(default=None)
- """Handler function for logging exceptions."""
-
- def __post_init__(self) -> None:
- if "queue_listener" not in self.handlers:
- self.handlers["queue_listener"] = _get_default_handlers()["queue_listener"]
-
- if "litestar" not in self.loggers:
- self.loggers["litestar"] = {
- "level": "INFO",
- "handlers": ["queue_listener"],
- "propagate": False,
- }
-
- if self.log_exceptions != "never" and self.exception_logging_handler is None:
- self.exception_logging_handler = _default_exception_logging_handler_factory(
- is_struct_logger=False, traceback_line_limit=self.traceback_line_limit
- )
-
- def configure(self) -> GetLogger:
- """Return logger with the given configuration.
-
- Returns:
- A 'logging.getLogger' like function.
- """
-
- excluded_fields: tuple[str, ...]
- if "picologging" in " ".join([handler["class"] for handler in self.handlers.values()]):
- try:
- from picologging import config, getLogger
- except ImportError as e:
- raise MissingDependencyException("picologging") from e
-
- excluded_fields = ("incremental", "configure_root_logger")
- else:
- from logging import config, getLogger # type: ignore[no-redef, assignment]
-
- excluded_fields = ("configure_root_logger",)
-
- values = {
- _field.name: getattr(self, _field.name)
- for _field in fields(self)
- if getattr(self, _field.name) is not None and _field.name not in excluded_fields
- }
-
- if not self.configure_root_logger:
- values.pop("root")
- config.dictConfig(values)
- return cast("Callable[[str], Logger]", getLogger)
-
- @staticmethod
- def set_level(logger: Logger, level: int) -> None:
- """Provides a consistent interface to call `setLevel` for all loggers."""
- logger.setLevel(level)
-
-
-class StructlogEventFilter:
- """Remove keys from the log event.
-
- Add an instance to the processor chain.
-
- .. code-block:: python
- :caption: Examples
-
- structlog.configure(
- ...,
- processors=[
- ...,
- EventFilter(["color_message"]),
- ...,
- ],
- )
-
- """
-
- def __init__(self, filter_keys: Iterable[str]) -> None:
- """Initialize the EventFilter.
-
- Args:
- filter_keys: Iterable of string keys to be excluded from the log event.
- """
- self.filter_keys = filter_keys
-
- def __call__(self, _: WrappedLogger, __: str, event_dict: EventDict) -> EventDict:
- """Receive the log event, and filter keys.
-
- Args:
- _ ():
- __ ():
- event_dict (): The data to be logged.
-
- Returns:
- The log event with any key in `self.filter_keys` removed.
- """
- for key in self.filter_keys:
- event_dict.pop(key, None)
- return event_dict
-
-
-def default_json_serializer(value: EventDict, **_: Any) -> bytes:
- return _msgspec_json_encoder.encode(value)
-
-
-def stdlib_json_serializer(value: EventDict, **_: Any) -> str: # pragma: no cover
- return _msgspec_json_encoder.encode(value).decode("utf-8")
-
-
-def default_structlog_processors(as_json: bool = True) -> list[Processor]: # pyright: ignore
- """Set the default processors for structlog.
-
- Returns:
- An optional list of processors.
- """
- try:
- import structlog
- from structlog.dev import RichTracebackFormatter
-
- if as_json:
- return [
- structlog.contextvars.merge_contextvars,
- structlog.processors.add_log_level,
- structlog.processors.format_exc_info,
- structlog.processors.TimeStamper(fmt="iso"),
- structlog.processors.JSONRenderer(serializer=default_json_serializer),
- ]
- return [
- structlog.contextvars.merge_contextvars,
- structlog.processors.add_log_level,
- structlog.processors.TimeStamper(fmt="iso"),
- structlog.dev.ConsoleRenderer(
- colors=True, exception_formatter=RichTracebackFormatter(max_frames=1, show_locals=False, width=80)
- ),
- ]
-
- except ImportError:
- return []
-
-
-def default_structlog_standard_lib_processors(as_json: bool = True) -> list[Processor]: # pyright: ignore
- """Set the default processors for structlog stdlib.
-
- Returns:
- An optional list of processors.
- """
- try:
- import structlog
- from structlog.dev import RichTracebackFormatter
-
- if as_json:
- return [
- structlog.processors.TimeStamper(fmt="iso"),
- structlog.stdlib.add_log_level,
- structlog.stdlib.ExtraAdder(),
- StructlogEventFilter(["color_message"]),
- structlog.stdlib.ProcessorFormatter.remove_processors_meta,
- structlog.processors.JSONRenderer(serializer=stdlib_json_serializer),
- ]
- return [
- structlog.processors.TimeStamper(fmt="iso"),
- structlog.stdlib.add_log_level,
- structlog.stdlib.ExtraAdder(),
- StructlogEventFilter(["color_message"]),
- structlog.stdlib.ProcessorFormatter.remove_processors_meta,
- structlog.dev.ConsoleRenderer(
- colors=True, exception_formatter=RichTracebackFormatter(max_frames=1, show_locals=False, width=80)
- ),
- ]
- except ImportError:
- return []
-
-
-def default_logger_factory(as_json: bool = True) -> Callable[..., WrappedLogger] | None:
- """Set the default logger factory for structlog.
-
- Returns:
- An optional logger factory.
- """
- try:
- import structlog
-
- if as_json:
- return structlog.BytesLoggerFactory()
- return structlog.WriteLoggerFactory()
- except ImportError:
- return None
-
-
-@dataclass
-class StructLoggingConfig(BaseLoggingConfig):
- """Configuration class for structlog.
-
- Notes:
- - requires ``structlog`` to be installed.
- """
-
- processors: list[Processor] | None = field(default=None) # pyright: ignore
- """Iterable of structlog logging processors."""
- standard_lib_logging_config: LoggingConfig | None = field(default=None) # pyright: ignore
- """Optional customized standard logging configuration.
-
- Use this when you need to modify the standard library outside of the Structlog pre-configured implementation.
- """
- wrapper_class: type[BindableLogger] | None = field(default=None) # pyright: ignore
- """Structlog bindable logger."""
- context_class: dict[str, Any] | None = None
- """Context class (a 'contextvar' context) for the logger."""
- logger_factory: Callable[..., WrappedLogger] | None = field(default=None) # pyright: ignore
- """Logger factory to use."""
- cache_logger_on_first_use: bool = field(default=True)
- """Whether to cache the logger configuration and reuse."""
- log_exceptions: Literal["always", "debug", "never"] = field(default="debug")
- """Should exceptions be logged, defaults to log exceptions when 'app.debug == True'"""
- traceback_line_limit: int = field(default=20)
- """Max number of lines to print for exception traceback"""
- exception_logging_handler: ExceptionLoggingHandler | None = field(default=None)
- """Handler function for logging exceptions."""
- pretty_print_tty: bool = field(default=True)
- """Pretty print log output when run from an interactive terminal."""
-
- def __post_init__(self) -> None:
- if self.processors is None:
- self.processors = default_structlog_processors(not sys.stderr.isatty() and self.pretty_print_tty)
- if self.logger_factory is None:
- self.logger_factory = default_logger_factory(not sys.stderr.isatty() and self.pretty_print_tty)
- if self.log_exceptions != "never" and self.exception_logging_handler is None:
- self.exception_logging_handler = _default_exception_logging_handler_factory(
- is_struct_logger=True, traceback_line_limit=self.traceback_line_limit
- )
- try:
- import structlog
-
- if self.standard_lib_logging_config is None:
- self.standard_lib_logging_config = LoggingConfig(
- formatters={
- "standard": {
- "()": structlog.stdlib.ProcessorFormatter,
- "processors": default_structlog_standard_lib_processors(
- as_json=not sys.stderr.isatty() and self.pretty_print_tty
- ),
- }
- }
- )
- except ImportError:
- self.standard_lib_logging_config = LoggingConfig()
-
- def configure(self) -> GetLogger:
- """Return logger with the given configuration.
-
- Returns:
- A 'logging.getLogger' like function.
- """
- try:
- import structlog
- except ImportError as e:
- raise MissingDependencyException("structlog") from e
-
- structlog.configure(
- **{
- k: v
- for k, v in asdict(self).items()
- if k
- not in (
- "standard_lib_logging_config",
- "log_exceptions",
- "traceback_line_limit",
- "exception_logging_handler",
- "pretty_print_tty",
- )
- }
- )
- return structlog.get_logger
-
- @staticmethod
- def set_level(logger: Logger, level: int) -> None:
- """Provides a consistent interface to call `setLevel` for all loggers."""
-
- try:
- import structlog
-
- structlog.configure(wrapper_class=structlog.make_filtering_bound_logger(level))
- except ImportError:
- """"""
- return
-
-
-@deprecated(version="2.6.0", removal_in="3.0.0", alternative="`StructLoggingConfig.set_level`")
-def default_wrapper_class(log_level: int = INFO) -> type[BindableLogger] | None: # pragma: no cover # pyright: ignore
- try: # pragma: no cover
- import structlog
-
- return structlog.make_filtering_bound_logger(log_level)
- except ImportError:
- return None
diff --git a/venv/lib/python3.11/site-packages/litestar/logging/picologging.py b/venv/lib/python3.11/site-packages/litestar/logging/picologging.py
deleted file mode 100644
index 2cd599f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/logging/picologging.py
+++ /dev/null
@@ -1,39 +0,0 @@
-from __future__ import annotations
-
-import atexit
-from queue import Queue
-from typing import Any
-
-from litestar.exceptions import MissingDependencyException
-from litestar.logging._utils import resolve_handlers
-
-__all__ = ("QueueListenerHandler",)
-
-
-try:
- import picologging # noqa: F401
-except ImportError as e:
- raise MissingDependencyException("picologging") from e
-
-from picologging import StreamHandler
-from picologging.handlers import QueueHandler, QueueListener
-
-
-class QueueListenerHandler(QueueHandler):
- """Configure queue listener and handler to support non-blocking logging configuration."""
-
- def __init__(self, handlers: list[Any] | None = None) -> None:
- """Initialize ``QueueListenerHandler``.
-
- Args:
- handlers: Optional 'ConvertingList'
-
- Notes:
- - Requires ``picologging`` to be installed.
- """
- super().__init__(Queue(-1))
- handlers = resolve_handlers(handlers) if handlers else [StreamHandler()]
- self.listener = QueueListener(self.queue, *handlers)
- self.listener.start()
-
- atexit.register(self.listener.stop)
diff --git a/venv/lib/python3.11/site-packages/litestar/logging/standard.py b/venv/lib/python3.11/site-packages/litestar/logging/standard.py
deleted file mode 100644
index 131c0ed..0000000
--- a/venv/lib/python3.11/site-packages/litestar/logging/standard.py
+++ /dev/null
@@ -1,47 +0,0 @@
-from __future__ import annotations
-
-import atexit
-from logging import Handler, LogRecord, StreamHandler
-from logging.handlers import QueueHandler, QueueListener
-from queue import Queue
-from typing import Any
-
-from litestar.logging._utils import resolve_handlers
-
-__all__ = ("LoggingQueueListener", "QueueListenerHandler")
-
-
-class LoggingQueueListener(QueueListener):
- """Custom ``QueueListener`` which starts and stops the listening process."""
-
- def __init__(self, queue: Queue[LogRecord], *handlers: Handler, respect_handler_level: bool = False) -> None:
- """Initialize ``LoggingQueueListener``.
-
- Args:
- queue: The queue to send messages to
- *handlers: A list of handlers which will handle entries placed on the queue
- respect_handler_level: If ``respect_handler_level`` is ``True``, a handler's level is respected (compared with the level for the message) when deciding whether to pass messages to that handler
- """
- super().__init__(queue, *handlers, respect_handler_level=respect_handler_level)
- self.start()
- atexit.register(self.stop)
-
-
-class QueueListenerHandler(QueueHandler):
- """Configure queue listener and handler to support non-blocking logging configuration.
-
- .. caution::
-
- This handler doesn't work with Python >= 3.12 and ``logging.config.dictConfig``. It might
- be deprecated in the future. Please use ``logging.QueueHandler`` instead.
- """
-
- def __init__(self, handlers: list[Any] | None = None) -> None:
- """Initialize ``QueueListenerHandler``.
-
- Args:
- handlers: Optional 'ConvertingList'
- """
- super().__init__(Queue(-1))
- handlers = resolve_handlers(handlers) if handlers else [StreamHandler()]
- self.listener = LoggingQueueListener(self.queue, *handlers) # type: ignore[arg-type]
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/__init__.py b/venv/lib/python3.11/site-packages/litestar/middleware/__init__.py
deleted file mode 100644
index 7024e54..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from litestar.middleware.authentication import (
- AbstractAuthenticationMiddleware,
- AuthenticationResult,
-)
-from litestar.middleware.base import (
- AbstractMiddleware,
- DefineMiddleware,
- MiddlewareProtocol,
-)
-
-__all__ = (
- "AbstractAuthenticationMiddleware",
- "AbstractMiddleware",
- "AuthenticationResult",
- "DefineMiddleware",
- "MiddlewareProtocol",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index c807c7a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/_utils.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/_utils.cpython-311.pyc
deleted file mode 100644
index 95f4515..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/_utils.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/allowed_hosts.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/allowed_hosts.cpython-311.pyc
deleted file mode 100644
index 48bfb2a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/allowed_hosts.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/authentication.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/authentication.cpython-311.pyc
deleted file mode 100644
index 193563c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/authentication.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/base.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/base.cpython-311.pyc
deleted file mode 100644
index 6a0ef6f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/base.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/cors.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/cors.cpython-311.pyc
deleted file mode 100644
index f4277f4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/cors.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/csrf.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/csrf.cpython-311.pyc
deleted file mode 100644
index 4679eea..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/csrf.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/logging.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/logging.cpython-311.pyc
deleted file mode 100644
index 20db6ff..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/logging.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/rate_limit.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/rate_limit.cpython-311.pyc
deleted file mode 100644
index 83090e5..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/rate_limit.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/response_cache.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/response_cache.cpython-311.pyc
deleted file mode 100644
index 1672eb4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/__pycache__/response_cache.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/_utils.py b/venv/lib/python3.11/site-packages/litestar/middleware/_utils.py
deleted file mode 100644
index 778a508..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/_utils.py
+++ /dev/null
@@ -1,69 +0,0 @@
-from __future__ import annotations
-
-import re
-from typing import TYPE_CHECKING, Pattern, Sequence
-
-from litestar.exceptions import ImproperlyConfiguredException
-
-__all__ = ("build_exclude_path_pattern", "should_bypass_middleware")
-
-
-if TYPE_CHECKING:
- from litestar.types import Method, Scope, Scopes
-
-
-def build_exclude_path_pattern(*, exclude: str | list[str] | None = None) -> Pattern | None:
- """Build single path pattern from list of patterns to opt-out from middleware processing.
-
- Args:
- exclude: A pattern or a list of patterns.
-
- Returns:
- An optional pattern to match against scope["path"] to opt-out from middleware processing.
- """
- if exclude is None:
- return None
-
- try:
- return re.compile("|".join(exclude)) if isinstance(exclude, list) else re.compile(exclude)
- except re.error as e: # pragma: no cover
- raise ImproperlyConfiguredException(
- "Unable to compile exclude patterns for middleware. Please make sure you passed a valid regular expression."
- ) from e
-
-
-def should_bypass_middleware(
- *,
- exclude_http_methods: Sequence[Method] | None = None,
- exclude_opt_key: str | None = None,
- exclude_path_pattern: Pattern | None = None,
- scope: Scope,
- scopes: Scopes,
-) -> bool:
- """Determine weather a middleware should be bypassed.
-
- Args:
- exclude_http_methods: A sequence of http methods that do not require authentication.
- exclude_opt_key: Key in ``opt`` with which a route handler can "opt-out" of a middleware.
- exclude_path_pattern: If this pattern matches scope["path"], the middleware should be bypassed.
- scope: The ASGI scope.
- scopes: A set with the ASGI scope types that are supported by the middleware.
-
- Returns:
- A boolean indicating if a middleware should be bypassed
- """
- if scope["type"] not in scopes:
- return True
-
- if exclude_opt_key and scope["route_handler"].opt.get(exclude_opt_key):
- return True
-
- if exclude_http_methods and scope.get("method") in exclude_http_methods:
- return True
-
- return bool(
- exclude_path_pattern
- and exclude_path_pattern.findall(
- scope["raw_path"].decode() if getattr(scope.get("route_handler", {}), "is_mount", False) else scope["path"]
- )
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/allowed_hosts.py b/venv/lib/python3.11/site-packages/litestar/middleware/allowed_hosts.py
deleted file mode 100644
index 0172176..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/allowed_hosts.py
+++ /dev/null
@@ -1,79 +0,0 @@
-from __future__ import annotations
-
-import re
-from typing import TYPE_CHECKING, Pattern
-
-from litestar.datastructures import URL, MutableScopeHeaders
-from litestar.middleware.base import AbstractMiddleware
-from litestar.response.base import ASGIResponse
-from litestar.response.redirect import ASGIRedirectResponse
-from litestar.status_codes import HTTP_400_BAD_REQUEST
-
-__all__ = ("AllowedHostsMiddleware",)
-
-
-if TYPE_CHECKING:
- from litestar.config.allowed_hosts import AllowedHostsConfig
- from litestar.types import ASGIApp, Receive, Scope, Send
-
-
-class AllowedHostsMiddleware(AbstractMiddleware):
- """Middleware ensuring the host of a request originated in a trusted host."""
-
- def __init__(self, app: ASGIApp, config: AllowedHostsConfig) -> None:
- """Initialize ``AllowedHostsMiddleware``.
-
- Args:
- app: The ``next`` ASGI app to call.
- config: An instance of AllowedHostsConfig.
- """
-
- super().__init__(app=app, exclude=config.exclude, exclude_opt_key=config.exclude_opt_key, scopes=config.scopes)
-
- self.allowed_hosts_regex: Pattern | None = None
- self.redirect_domains: Pattern | None = None
-
- if any(host == "*" for host in config.allowed_hosts):
- return
-
- allowed_hosts: set[str] = {
- rf".*\.{host.replace('*.', '')}$" if host.startswith("*.") else host for host in config.allowed_hosts
- }
-
- self.allowed_hosts_regex = re.compile("|".join(sorted(allowed_hosts))) # pyright: ignore
-
- if config.www_redirect and (
- redirect_domains := {host.replace("www.", "") for host in config.allowed_hosts if host.startswith("www.")}
- ):
- self.redirect_domains = re.compile("|".join(sorted(redirect_domains))) # pyright: ignore
-
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
- """ASGI callable.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
- if self.allowed_hosts_regex is None:
- await self.app(scope, receive, send)
- return
-
- headers = MutableScopeHeaders(scope=scope)
- if host := headers.get("host", headers.get("x-forwarded-host", "")).split(":")[0]:
- if self.allowed_hosts_regex.fullmatch(host):
- await self.app(scope, receive, send)
- return
-
- if self.redirect_domains is not None and self.redirect_domains.fullmatch(host):
- url = URL.from_scope(scope)
- redirect_url = url.with_replacements(netloc=f"www.{url.netloc}")
- redirect_response = ASGIRedirectResponse(path=str(redirect_url))
- await redirect_response(scope, receive, send)
- return
-
- response = ASGIResponse(body=b'{"message":"invalid host header"}', status_code=HTTP_400_BAD_REQUEST)
- await response(scope, receive, send)
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/authentication.py b/venv/lib/python3.11/site-packages/litestar/middleware/authentication.py
deleted file mode 100644
index 9502df0..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/authentication.py
+++ /dev/null
@@ -1,108 +0,0 @@
-from __future__ import annotations
-
-from abc import ABC, abstractmethod
-from dataclasses import dataclass
-from typing import TYPE_CHECKING, Any, Sequence
-
-from litestar.connection import ASGIConnection
-from litestar.enums import HttpMethod, ScopeType
-from litestar.middleware._utils import (
- build_exclude_path_pattern,
- should_bypass_middleware,
-)
-
-__all__ = ("AbstractAuthenticationMiddleware", "AuthenticationResult")
-
-
-if TYPE_CHECKING:
- from litestar.types import ASGIApp, Method, Receive, Scope, Scopes, Send
-
-
-@dataclass
-class AuthenticationResult:
- """Pydantic model for authentication data."""
-
- __slots__ = ("user", "auth")
-
- user: Any
- """The user model, this can be any value corresponding to a user of the API."""
- auth: Any
- """The auth value, this can for example be a JWT token."""
-
-
-class AbstractAuthenticationMiddleware(ABC):
- """Abstract AuthenticationMiddleware that allows users to create their own AuthenticationMiddleware by extending it
- and overriding :meth:`AbstractAuthenticationMiddleware.authenticate_request`.
- """
-
- __slots__ = (
- "app",
- "exclude",
- "exclude_http_methods",
- "exclude_opt_key",
- "scopes",
- )
-
- def __init__(
- self,
- app: ASGIApp,
- exclude: str | list[str] | None = None,
- exclude_from_auth_key: str = "exclude_from_auth",
- exclude_http_methods: Sequence[Method] | None = None,
- scopes: Scopes | None = None,
- ) -> None:
- """Initialize ``AbstractAuthenticationMiddleware``.
-
- Args:
- app: An ASGIApp, this value is the next ASGI handler to call in the middleware stack.
- exclude: A pattern or list of patterns to skip in the authentication middleware.
- exclude_from_auth_key: An identifier to use on routes to disable authentication for a particular route.
- exclude_http_methods: A sequence of http methods that do not require authentication.
- scopes: ASGI scopes processed by the authentication middleware.
- """
- self.app = app
- self.exclude = build_exclude_path_pattern(exclude=exclude)
- self.exclude_http_methods = (HttpMethod.OPTIONS,) if exclude_http_methods is None else exclude_http_methods
- self.exclude_opt_key = exclude_from_auth_key
- self.scopes = scopes or {ScopeType.HTTP, ScopeType.WEBSOCKET}
-
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
- """ASGI callable.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
- if not should_bypass_middleware(
- exclude_http_methods=self.exclude_http_methods,
- exclude_opt_key=self.exclude_opt_key,
- exclude_path_pattern=self.exclude,
- scope=scope,
- scopes=self.scopes,
- ):
- auth_result = await self.authenticate_request(ASGIConnection(scope))
- scope["user"] = auth_result.user
- scope["auth"] = auth_result.auth
- await self.app(scope, receive, send)
-
- @abstractmethod
- async def authenticate_request(self, connection: ASGIConnection) -> AuthenticationResult:
- """Receive the http connection and return an :class:`AuthenticationResult`.
-
- Notes:
- - This method must be overridden by subclasses.
-
- Args:
- connection: An :class:`ASGIConnection <litestar.connection.ASGIConnection>` instance.
-
- Raises:
- NotAuthorizedException | PermissionDeniedException: if authentication fails.
-
- Returns:
- An instance of :class:`AuthenticationResult <litestar.middleware.authentication.AuthenticationResult>`.
- """
- raise NotImplementedError("authenticate_request must be overridden by subclasses")
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/base.py b/venv/lib/python3.11/site-packages/litestar/middleware/base.py
deleted file mode 100644
index 43106c9..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/base.py
+++ /dev/null
@@ -1,151 +0,0 @@
-from __future__ import annotations
-
-from abc import abstractmethod
-from typing import TYPE_CHECKING, Any, Callable, Protocol, runtime_checkable
-
-from litestar.enums import ScopeType
-from litestar.middleware._utils import (
- build_exclude_path_pattern,
- should_bypass_middleware,
-)
-
-__all__ = ("AbstractMiddleware", "DefineMiddleware", "MiddlewareProtocol")
-
-
-if TYPE_CHECKING:
- from litestar.types import Scopes
- from litestar.types.asgi_types import ASGIApp, Receive, Scope, Send
-
-
-@runtime_checkable
-class MiddlewareProtocol(Protocol):
- """Abstract middleware protocol."""
-
- __slots__ = ("app",)
-
- app: ASGIApp
-
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
- """Execute the ASGI middleware.
-
- Called by the previous middleware in the stack if a response is not awaited prior.
-
- Upon completion, middleware should call the next ASGI handler and await it - or await a response created in its
- closure.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
-
-
-class DefineMiddleware:
- """Container enabling passing ``*args`` and ``**kwargs`` to Middleware class constructors and factory functions."""
-
- __slots__ = ("middleware", "args", "kwargs")
-
- def __init__(self, middleware: Callable[..., ASGIApp], *args: Any, **kwargs: Any) -> None:
- """Initialize ``DefineMiddleware``.
-
- Args:
- middleware: A callable that returns an ASGIApp.
- *args: Positional arguments to pass to the callable.
- **kwargs: Key word arguments to pass to the callable.
-
- Notes:
- The callable will be passed a kwarg ``app``, which is the next ASGI app to call in the middleware stack.
- It therefore must define such a kwarg.
- """
- self.middleware = middleware
- self.args = args
- self.kwargs = kwargs
-
- def __call__(self, app: ASGIApp) -> ASGIApp:
- """Call the middleware constructor or factory.
-
- Args:
- app: An ASGIApp, this value is the next ASGI handler to call in the middleware stack.
-
- Returns:
- Calls :class:`DefineMiddleware.middleware <.DefineMiddleware>` and returns the ASGIApp created.
- """
-
- return self.middleware(*self.args, app=app, **self.kwargs)
-
-
-class AbstractMiddleware:
- """Abstract middleware providing base functionality common to all middlewares, for dynamically engaging/bypassing
- the middleware based on paths, ``opt``-keys and scope types.
-
- When implementing new middleware, this class should be used as a base.
- """
-
- scopes: Scopes = {ScopeType.HTTP, ScopeType.WEBSOCKET}
- exclude: str | list[str] | None = None
- exclude_opt_key: str | None = None
-
- def __init__(
- self,
- app: ASGIApp,
- exclude: str | list[str] | None = None,
- exclude_opt_key: str | None = None,
- scopes: Scopes | None = None,
- ) -> None:
- """Initialize the middleware.
-
- Args:
- app: The ``next`` ASGI app to call.
- exclude: A pattern or list of patterns to match against a request's path.
- If a match is found, the middleware will be skipped.
- exclude_opt_key: An identifier that is set in the route handler
- ``opt`` key which allows skipping the middleware.
- scopes: ASGI scope types, should be a set including
- either or both 'ScopeType.HTTP' and 'ScopeType.WEBSOCKET'.
- """
- self.app = app
- self.scopes = scopes or self.scopes
- self.exclude_opt_key = exclude_opt_key or self.exclude_opt_key
- self.exclude_pattern = build_exclude_path_pattern(exclude=(exclude or self.exclude))
-
- @classmethod
- def __init_subclass__(cls, **kwargs: Any) -> None:
- super().__init_subclass__(**kwargs)
-
- original__call__ = cls.__call__
-
- async def wrapped_call(self: AbstractMiddleware, scope: Scope, receive: Receive, send: Send) -> None:
- if should_bypass_middleware(
- scope=scope,
- scopes=self.scopes,
- exclude_path_pattern=self.exclude_pattern,
- exclude_opt_key=self.exclude_opt_key,
- ):
- await self.app(scope, receive, send)
- else:
- await original__call__(self, scope, receive, send) # pyright: ignore
-
- # https://github.com/python/mypy/issues/2427#issuecomment-384229898
- setattr(cls, "__call__", wrapped_call)
-
- @abstractmethod
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
- """Execute the ASGI middleware.
-
- Called by the previous middleware in the stack if a response is not awaited prior.
-
- Upon completion, middleware should call the next ASGI handler and await it - or await a response created in its
- closure.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
- raise NotImplementedError("abstract method must be implemented")
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/compression/__init__.py b/venv/lib/python3.11/site-packages/litestar/middleware/compression/__init__.py
deleted file mode 100644
index 0885932..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/compression/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from litestar.middleware.compression.facade import CompressionFacade
-from litestar.middleware.compression.middleware import CompressionMiddleware
-
-__all__ = ("CompressionMiddleware", "CompressionFacade")
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 80ea058..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/brotli_facade.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/brotli_facade.cpython-311.pyc
deleted file mode 100644
index 7378c0f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/brotli_facade.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/facade.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/facade.cpython-311.pyc
deleted file mode 100644
index d336c8f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/facade.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/gzip_facade.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/gzip_facade.cpython-311.pyc
deleted file mode 100644
index 66e1df4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/gzip_facade.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/middleware.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/middleware.cpython-311.pyc
deleted file mode 100644
index a683673..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/compression/__pycache__/middleware.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/compression/brotli_facade.py b/venv/lib/python3.11/site-packages/litestar/middleware/compression/brotli_facade.py
deleted file mode 100644
index 3d01950..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/compression/brotli_facade.py
+++ /dev/null
@@ -1,51 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Literal
-
-from litestar.enums import CompressionEncoding
-from litestar.exceptions import MissingDependencyException
-from litestar.middleware.compression.facade import CompressionFacade
-
-try:
- from brotli import MODE_FONT, MODE_GENERIC, MODE_TEXT, Compressor
-except ImportError as e:
- raise MissingDependencyException("brotli") from e
-
-
-if TYPE_CHECKING:
- from io import BytesIO
-
- from litestar.config.compression import CompressionConfig
-
-
-class BrotliCompression(CompressionFacade):
- __slots__ = ("compressor", "buffer", "compression_encoding")
-
- encoding = CompressionEncoding.BROTLI
-
- def __init__(
- self,
- buffer: BytesIO,
- compression_encoding: Literal[CompressionEncoding.BROTLI] | str,
- config: CompressionConfig,
- ) -> None:
- self.buffer = buffer
- self.compression_encoding = compression_encoding
- modes: dict[Literal["generic", "text", "font"], int] = {
- "text": int(MODE_TEXT),
- "font": int(MODE_FONT),
- "generic": int(MODE_GENERIC),
- }
- self.compressor = Compressor(
- quality=config.brotli_quality,
- mode=modes[config.brotli_mode],
- lgwin=config.brotli_lgwin,
- lgblock=config.brotli_lgblock,
- )
-
- def write(self, body: bytes) -> None:
- self.buffer.write(self.compressor.process(body))
- self.buffer.write(self.compressor.flush())
-
- def close(self) -> None:
- self.buffer.write(self.compressor.finish())
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/compression/facade.py b/venv/lib/python3.11/site-packages/litestar/middleware/compression/facade.py
deleted file mode 100644
index 0074b57..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/compression/facade.py
+++ /dev/null
@@ -1,47 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, ClassVar, Protocol
-
-if TYPE_CHECKING:
- from io import BytesIO
-
- from litestar.config.compression import CompressionConfig
- from litestar.enums import CompressionEncoding
-
-
-class CompressionFacade(Protocol):
- """A unified facade offering a uniform interface for different compression libraries."""
-
- encoding: ClassVar[str]
- """The encoding of the compression."""
-
- def __init__(
- self, buffer: BytesIO, compression_encoding: CompressionEncoding | str, config: CompressionConfig
- ) -> None:
- """Initialize ``CompressionFacade``.
-
- Args:
- buffer: A bytes IO buffer to write the compressed data into.
- compression_encoding: The compression encoding used.
- config: The app compression config.
- """
- ...
-
- def write(self, body: bytes) -> None:
- """Write compressed bytes.
-
- Args:
- body: Message body to process
-
- Returns:
- None
- """
- ...
-
- def close(self) -> None:
- """Close the compression stream.
-
- Returns:
- None
- """
- ...
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/compression/gzip_facade.py b/venv/lib/python3.11/site-packages/litestar/middleware/compression/gzip_facade.py
deleted file mode 100644
index b10ef73..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/compression/gzip_facade.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from __future__ import annotations
-
-from gzip import GzipFile
-from typing import TYPE_CHECKING, Literal
-
-from litestar.enums import CompressionEncoding
-from litestar.middleware.compression.facade import CompressionFacade
-
-if TYPE_CHECKING:
- from io import BytesIO
-
- from litestar.config.compression import CompressionConfig
-
-
-class GzipCompression(CompressionFacade):
- __slots__ = ("compressor", "buffer", "compression_encoding")
-
- encoding = CompressionEncoding.GZIP
-
- def __init__(
- self, buffer: BytesIO, compression_encoding: Literal[CompressionEncoding.GZIP] | str, config: CompressionConfig
- ) -> None:
- self.buffer = buffer
- self.compression_encoding = compression_encoding
- self.compressor = GzipFile(mode="wb", fileobj=buffer, compresslevel=config.gzip_compress_level)
-
- def write(self, body: bytes) -> None:
- self.compressor.write(body)
- self.compressor.flush()
-
- def close(self) -> None:
- self.compressor.close()
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/compression/middleware.py b/venv/lib/python3.11/site-packages/litestar/middleware/compression/middleware.py
deleted file mode 100644
index 7ea7853..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/compression/middleware.py
+++ /dev/null
@@ -1,191 +0,0 @@
-from __future__ import annotations
-
-from io import BytesIO
-from typing import TYPE_CHECKING, Any, Literal
-
-from litestar.datastructures import Headers, MutableScopeHeaders
-from litestar.enums import CompressionEncoding, ScopeType
-from litestar.middleware.base import AbstractMiddleware
-from litestar.middleware.compression.gzip_facade import GzipCompression
-from litestar.utils.empty import value_or_default
-from litestar.utils.scope.state import ScopeState
-
-if TYPE_CHECKING:
- from litestar.config.compression import CompressionConfig
- from litestar.middleware.compression.facade import CompressionFacade
- from litestar.types import (
- ASGIApp,
- HTTPResponseStartEvent,
- Message,
- Receive,
- Scope,
- Send,
- )
-
- try:
- from brotli import Compressor
- except ImportError:
- Compressor = Any
-
-
-class CompressionMiddleware(AbstractMiddleware):
- """Compression Middleware Wrapper.
-
- This is a wrapper allowing for generic compression configuration / handler middleware
- """
-
- def __init__(self, app: ASGIApp, config: CompressionConfig) -> None:
- """Initialize ``CompressionMiddleware``
-
- Args:
- app: The ``next`` ASGI app to call.
- config: An instance of CompressionConfig.
- """
- super().__init__(
- app=app, exclude=config.exclude, exclude_opt_key=config.exclude_opt_key, scopes={ScopeType.HTTP}
- )
- self.config = config
-
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
- """ASGI callable.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
- accept_encoding = Headers.from_scope(scope).get("accept-encoding", "")
- config = self.config
-
- if config.compression_facade.encoding in accept_encoding:
- await self.app(
- scope,
- receive,
- self.create_compression_send_wrapper(
- send=send, compression_encoding=config.compression_facade.encoding, scope=scope
- ),
- )
- return
-
- if config.gzip_fallback and CompressionEncoding.GZIP in accept_encoding:
- await self.app(
- scope,
- receive,
- self.create_compression_send_wrapper(
- send=send, compression_encoding=CompressionEncoding.GZIP, scope=scope
- ),
- )
- return
-
- await self.app(scope, receive, send)
-
- def create_compression_send_wrapper(
- self,
- send: Send,
- compression_encoding: Literal[CompressionEncoding.BROTLI, CompressionEncoding.GZIP] | str,
- scope: Scope,
- ) -> Send:
- """Wrap ``send`` to handle brotli compression.
-
- Args:
- send: The ASGI send function.
- compression_encoding: The compression encoding used.
- scope: The ASGI connection scope
-
- Returns:
- An ASGI send function.
- """
- bytes_buffer = BytesIO()
-
- facade: CompressionFacade
- # We can't use `self.config.compression_facade` directly if the compression is `gzip` since
- # it may be being used as a fallback.
- if compression_encoding == CompressionEncoding.GZIP:
- facade = GzipCompression(buffer=bytes_buffer, compression_encoding=compression_encoding, config=self.config)
- else:
- facade = self.config.compression_facade(
- buffer=bytes_buffer, compression_encoding=compression_encoding, config=self.config
- )
-
- initial_message: HTTPResponseStartEvent | None = None
- started = False
-
- connection_state = ScopeState.from_scope(scope)
-
- async def send_wrapper(message: Message) -> None:
- """Handle and compresses the HTTP Message with brotli.
-
- Args:
- message (Message): An ASGI Message.
- """
- nonlocal started
- nonlocal initial_message
-
- if message["type"] == "http.response.start":
- initial_message = message
- return
-
- if initial_message is not None and value_or_default(connection_state.is_cached, False):
- await send(initial_message)
- await send(message)
- return
-
- if initial_message and message["type"] == "http.response.body":
- body = message["body"]
- more_body = message.get("more_body")
-
- if not started:
- started = True
- if more_body:
- headers = MutableScopeHeaders(initial_message)
- headers["Content-Encoding"] = compression_encoding
- headers.extend_header_value("vary", "Accept-Encoding")
- del headers["Content-Length"]
- connection_state.response_compressed = True
-
- facade.write(body)
-
- message["body"] = bytes_buffer.getvalue()
- bytes_buffer.seek(0)
- bytes_buffer.truncate()
- await send(initial_message)
- await send(message)
-
- elif len(body) >= self.config.minimum_size:
- facade.write(body)
- facade.close()
- body = bytes_buffer.getvalue()
-
- headers = MutableScopeHeaders(initial_message)
- headers["Content-Encoding"] = compression_encoding
- headers["Content-Length"] = str(len(body))
- headers.extend_header_value("vary", "Accept-Encoding")
- message["body"] = body
- connection_state.response_compressed = True
-
- await send(initial_message)
- await send(message)
-
- else:
- await send(initial_message)
- await send(message)
-
- else:
- facade.write(body)
- if not more_body:
- facade.close()
-
- message["body"] = bytes_buffer.getvalue()
-
- bytes_buffer.seek(0)
- bytes_buffer.truncate()
-
- if not more_body:
- bytes_buffer.close()
-
- await send(message)
-
- return send_wrapper
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/cors.py b/venv/lib/python3.11/site-packages/litestar/middleware/cors.py
deleted file mode 100644
index 6c4de31..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/cors.py
+++ /dev/null
@@ -1,84 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING
-
-from litestar.datastructures import Headers, MutableScopeHeaders
-from litestar.enums import ScopeType
-from litestar.middleware.base import AbstractMiddleware
-
-__all__ = ("CORSMiddleware",)
-
-
-if TYPE_CHECKING:
- from litestar.config.cors import CORSConfig
- from litestar.types import ASGIApp, Message, Receive, Scope, Send
-
-
-class CORSMiddleware(AbstractMiddleware):
- """CORS Middleware."""
-
- __slots__ = ("config",)
-
- def __init__(self, app: ASGIApp, config: CORSConfig) -> None:
- """Middleware that adds CORS validation to the application.
-
- Args:
- app: The ``next`` ASGI app to call.
- config: An instance of :class:`CORSConfig <litestar.config.cors.CORSConfig>`
- """
- super().__init__(app=app, scopes={ScopeType.HTTP})
- self.config = config
-
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
- """ASGI callable.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
- headers = Headers.from_scope(scope=scope)
- if origin := headers.get("origin"):
- await self.app(scope, receive, self.send_wrapper(send=send, origin=origin, has_cookie="cookie" in headers))
- else:
- await self.app(scope, receive, send)
-
- def send_wrapper(self, send: Send, origin: str, has_cookie: bool) -> Send:
- """Wrap ``send`` to ensure that state is not disconnected.
-
- Args:
- has_cookie: Boolean flag dictating if the connection has a cookie set.
- origin: The value of the ``Origin`` header.
- send: The ASGI send function.
-
- Returns:
- An ASGI send function.
- """
-
- async def wrapped_send(message: Message) -> None:
- if message["type"] == "http.response.start":
- message.setdefault("headers", [])
- headers = MutableScopeHeaders.from_message(message=message)
- headers.update(self.config.simple_headers)
-
- if (self.config.is_allow_all_origins and has_cookie) or (
- not self.config.is_allow_all_origins and self.config.is_origin_allowed(origin=origin)
- ):
- headers["Access-Control-Allow-Origin"] = origin
- headers["Vary"] = "Origin"
-
- # We don't want to overwrite this for preflight requests.
- allow_headers = headers.get("Access-Control-Allow-Headers")
- if not allow_headers and self.config.allow_headers:
- headers["Access-Control-Allow-Headers"] = ", ".join(sorted(set(self.config.allow_headers)))
-
- allow_methods = headers.get("Access-Control-Allow-Methods")
- if not allow_methods and self.config.allow_methods:
- headers["Access-Control-Allow-Methods"] = ", ".join(sorted(set(self.config.allow_methods)))
-
- await send(message)
-
- return wrapped_send
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/csrf.py b/venv/lib/python3.11/site-packages/litestar/middleware/csrf.py
deleted file mode 100644
index 94dd422..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/csrf.py
+++ /dev/null
@@ -1,190 +0,0 @@
-from __future__ import annotations
-
-import hashlib
-import hmac
-import secrets
-from secrets import compare_digest
-from typing import TYPE_CHECKING, Any
-
-from litestar.datastructures import MutableScopeHeaders
-from litestar.datastructures.cookie import Cookie
-from litestar.enums import RequestEncodingType, ScopeType
-from litestar.exceptions import PermissionDeniedException
-from litestar.middleware._utils import (
- build_exclude_path_pattern,
- should_bypass_middleware,
-)
-from litestar.middleware.base import MiddlewareProtocol
-from litestar.utils.scope.state import ScopeState
-
-if TYPE_CHECKING:
- from litestar.config.csrf import CSRFConfig
- from litestar.connection import Request
- from litestar.types import (
- ASGIApp,
- HTTPSendMessage,
- Message,
- Receive,
- Scope,
- Scopes,
- Send,
- )
-
-__all__ = ("CSRFMiddleware",)
-
-
-CSRF_SECRET_BYTES = 32
-CSRF_SECRET_LENGTH = CSRF_SECRET_BYTES * 2
-
-
-def generate_csrf_hash(token: str, secret: str) -> str:
- """Generate an HMAC that signs the CSRF token.
-
- Args:
- token: A hashed token.
- secret: A secret value.
-
- Returns:
- A CSRF hash.
- """
- return hmac.new(secret.encode(), token.encode(), hashlib.sha256).hexdigest()
-
-
-def generate_csrf_token(secret: str) -> str:
- """Generate a CSRF token that includes a randomly generated string signed by an HMAC.
-
- Args:
- secret: A secret string.
-
- Returns:
- A unique CSRF token.
- """
- token = secrets.token_hex(CSRF_SECRET_BYTES)
- token_hash = generate_csrf_hash(token=token, secret=secret)
- return token + token_hash
-
-
-class CSRFMiddleware(MiddlewareProtocol):
- """CSRF Middleware class.
-
- This Middleware protects against attacks by setting a CSRF cookie with a token and verifying it in request headers.
- """
-
- scopes: Scopes = {ScopeType.HTTP}
-
- def __init__(self, app: ASGIApp, config: CSRFConfig) -> None:
- """Initialize ``CSRFMiddleware``.
-
- Args:
- app: The ``next`` ASGI app to call.
- config: The CSRFConfig instance.
- """
- self.app = app
- self.config = config
- self.exclude = build_exclude_path_pattern(exclude=config.exclude)
-
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
- """ASGI callable.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
- if scope["type"] != ScopeType.HTTP:
- await self.app(scope, receive, send)
- return
-
- request: Request[Any, Any, Any] = scope["app"].request_class(scope=scope, receive=receive)
- content_type, _ = request.content_type
- csrf_cookie = request.cookies.get(self.config.cookie_name)
- existing_csrf_token = request.headers.get(self.config.header_name)
-
- if not existing_csrf_token and content_type in {
- RequestEncodingType.URL_ENCODED,
- RequestEncodingType.MULTI_PART,
- }:
- form = await request.form()
- existing_csrf_token = form.get("_csrf_token", None)
-
- connection_state = ScopeState.from_scope(scope)
- if request.method in self.config.safe_methods or should_bypass_middleware(
- scope=scope,
- scopes=self.scopes,
- exclude_opt_key=self.config.exclude_from_csrf_key,
- exclude_path_pattern=self.exclude,
- ):
- token = connection_state.csrf_token = csrf_cookie or generate_csrf_token(secret=self.config.secret)
- await self.app(scope, receive, self.create_send_wrapper(send=send, csrf_cookie=csrf_cookie, token=token))
- elif (
- existing_csrf_token is not None
- and csrf_cookie is not None
- and self._csrf_tokens_match(existing_csrf_token, csrf_cookie)
- ):
- connection_state.csrf_token = existing_csrf_token
- await self.app(scope, receive, send)
- else:
- raise PermissionDeniedException("CSRF token verification failed")
-
- def create_send_wrapper(self, send: Send, token: str, csrf_cookie: str | None) -> Send:
- """Wrap ``send`` to handle CSRF validation.
-
- Args:
- token: The CSRF token.
- send: The ASGI send function.
- csrf_cookie: CSRF cookie.
-
- Returns:
- An ASGI send function.
- """
-
- async def send_wrapper(message: Message) -> None:
- """Send function that wraps the original send to inject a cookie.
-
- Args:
- message: An ASGI ``Message``
-
- Returns:
- None
- """
- if csrf_cookie is None and message["type"] == "http.response.start":
- message.setdefault("headers", [])
- self._set_cookie_if_needed(message=message, token=token)
- await send(message)
-
- return send_wrapper
-
- def _set_cookie_if_needed(self, message: HTTPSendMessage, token: str) -> None:
- headers = MutableScopeHeaders.from_message(message)
- cookie = Cookie(
- key=self.config.cookie_name,
- value=token,
- path=self.config.cookie_path,
- secure=self.config.cookie_secure,
- httponly=self.config.cookie_httponly,
- samesite=self.config.cookie_samesite,
- domain=self.config.cookie_domain,
- )
- headers.add("set-cookie", cookie.to_header(header=""))
-
- def _decode_csrf_token(self, token: str) -> str | None:
- """Decode a CSRF token and validate its HMAC."""
- if len(token) < CSRF_SECRET_LENGTH + 1:
- return None
-
- token_secret = token[:CSRF_SECRET_LENGTH]
- existing_hash = token[CSRF_SECRET_LENGTH:]
- expected_hash = generate_csrf_hash(token=token_secret, secret=self.config.secret)
- return token_secret if compare_digest(existing_hash, expected_hash) else None
-
- def _csrf_tokens_match(self, request_csrf_token: str, cookie_csrf_token: str) -> bool:
- """Take the CSRF tokens from the request and the cookie and verify both are valid and identical."""
- decoded_request_token = self._decode_csrf_token(request_csrf_token)
- decoded_cookie_token = self._decode_csrf_token(cookie_csrf_token)
- if decoded_request_token is None or decoded_cookie_token is None:
- return False
-
- return compare_digest(decoded_request_token, decoded_cookie_token)
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/__init__.py b/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/__init__.py
deleted file mode 100644
index 5328adf..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from litestar.middleware.exceptions.middleware import ExceptionHandlerMiddleware
-
-__all__ = ("ExceptionHandlerMiddleware",)
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index c443e00..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/__pycache__/_debug_response.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/__pycache__/_debug_response.cpython-311.pyc
deleted file mode 100644
index b41fc85..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/__pycache__/_debug_response.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/__pycache__/middleware.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/__pycache__/middleware.cpython-311.pyc
deleted file mode 100644
index 2259206..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/__pycache__/middleware.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/_debug_response.py b/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/_debug_response.py
deleted file mode 100644
index 99e8c87..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/_debug_response.py
+++ /dev/null
@@ -1,210 +0,0 @@
-from __future__ import annotations
-
-from html import escape
-from inspect import getinnerframes
-from pathlib import Path
-from traceback import format_exception
-from typing import TYPE_CHECKING, Any
-
-from litestar.enums import MediaType
-from litestar.response import Response
-from litestar.status_codes import HTTP_500_INTERNAL_SERVER_ERROR
-from litestar.utils import get_name
-
-__all__ = (
- "create_debug_response",
- "create_exception_html",
- "create_frame_html",
- "create_html_response_content",
- "create_line_html",
- "create_plain_text_response_content",
- "get_symbol_name",
-)
-
-
-if TYPE_CHECKING:
- from inspect import FrameInfo
-
- from litestar.connection import Request
- from litestar.types import TypeEncodersMap
-
-tpl_dir = Path(__file__).parent / "templates"
-
-
-def get_symbol_name(frame: FrameInfo) -> str:
- """Return full name of the function that is being executed by the given frame.
-
- Args:
- frame: An instance of [FrameInfo](https://docs.python.org/3/library/inspect.html#inspect.FrameInfo).
-
- Notes:
- - class detection assumes standard names (self and cls) of params.
- - if current class name can not be determined only function (method) name will be returned.
- - we can not distinguish static methods from ordinary functions at the moment.
-
- Returns:
- A string containing full function name.
- """
-
- locals_dict = frame.frame.f_locals
- # this piece assumes that the code uses standard names "self" and "cls"
- # in instance and class methods
- instance_or_cls = inst if (inst := locals_dict.get("self")) is not None else locals_dict.get("cls")
-
- classname = f"{get_name(instance_or_cls)}." if instance_or_cls is not None else ""
-
- return f"{classname}{frame.function}"
-
-
-def create_line_html(
- line: str,
- line_no: int,
- frame_index: int,
- idx: int,
-) -> str:
- """Produce HTML representation of a line including real line number in the source code.
-
- Args:
- line: A string representing the current line.
- line_no: The line number associated with the executed line.
- frame_index: Index of the executed line in the code context.
- idx: Index of the current line in the code context.
-
- Returns:
- A string containing HTML representation of the given line.
- """
- template = '<tr class="{line_class}"><td class="line_no">{line_no}</td><td class="code_line">{line}</td></tr>'
- data = {
- # line_no - frame_index produces actual line number of the very first line in the frame code context.
- # so adding index (aka relative number) of a line in the code context we can calculate its actual number in the source file,
- "line_no": line_no - frame_index + idx,
- "line": escape(line).replace(" ", "&nbsp"),
- "line_class": "executed-line" if idx == frame_index else "",
- }
- return template.format(**data)
-
-
-def create_frame_html(frame: FrameInfo, collapsed: bool) -> str:
- """Produce HTML representation of the given frame object including filename containing source code and name of the
- function being executed.
-
- Args:
- frame: An instance of [FrameInfo](https://docs.python.org/3/library/inspect.html#inspect.FrameInfo).
- collapsed: Flag controlling whether frame should be collapsed on the page load.
-
- Returns:
- A string containing HTML representation of the execution frame.
- """
- frame_tpl = (tpl_dir / "frame.html").read_text()
-
- code_lines: list[str] = [
- create_line_html(line, frame.lineno, frame.index or 0, idx) for idx, line in enumerate(frame.code_context or [])
- ]
- data = {
- "file": escape(frame.filename),
- "line": frame.lineno,
- "symbol_name": escape(get_symbol_name(frame)),
- "code": "".join(code_lines),
- "frame_class": "collapsed" if collapsed else "",
- }
- return frame_tpl.format(**data)
-
-
-def create_exception_html(exc: BaseException, line_limit: int) -> str:
- """Produce HTML representation of the exception frames.
-
- Args:
- exc: An Exception instance to generate.
- line_limit: Number of lines of code context to return, which are centered around the executed line.
-
- Returns:
- A string containing HTML representation of the execution frames related to the exception.
- """
- frames = getinnerframes(exc.__traceback__, line_limit) if exc.__traceback__ else []
- result = [create_frame_html(frame=frame, collapsed=idx > 0) for idx, frame in enumerate(reversed(frames))]
- return "".join(result)
-
-
-def create_html_response_content(exc: Exception, request: Request, line_limit: int = 15) -> str:
- """Given an exception, produces its traceback in HTML.
-
- Args:
- exc: An Exception instance to render debug response from.
- request: A :class:`Request <litestar.connection.Request>` instance.
- line_limit: Number of lines of code context to return, which are centered around the executed line.
-
- Returns:
- A string containing HTML page with exception traceback.
- """
- exception_data: list[str] = [create_exception_html(exc, line_limit)]
- cause = exc.__cause__
- while cause:
- cause_data = create_exception_html(cause, line_limit)
- cause_header = '<h4 class="cause-header">The above exception was caused by</h4>'
- cause_error_description = f"<h3><span>{escape(str(cause))}</span></h3>"
- cause_error = f"<h4><span>{escape(cause.__class__.__name__)}</span></h4>"
- exception_data.append(
- f'<div class="cause-wrapper">{cause_header}{cause_error}{cause_error_description}{cause_data}</div>'
- )
- cause = cause.__cause__
-
- scripts = (tpl_dir / "scripts.js").read_text()
- styles = (tpl_dir / "styles.css").read_text()
- body_tpl = (tpl_dir / "body.html").read_text()
- return body_tpl.format(
- scripts=scripts,
- styles=styles,
- error=f"<span>{escape(exc.__class__.__name__)}</span> on {request.method} {escape(request.url.path)}",
- error_description=escape(str(exc)),
- exception_data="".join(exception_data),
- )
-
-
-def create_plain_text_response_content(exc: Exception) -> str:
- """Given an exception, produces its traceback in plain text.
-
- Args:
- exc: An Exception instance to render debug response from.
-
- Returns:
- A string containing exception traceback.
- """
- return "".join(format_exception(type(exc), value=exc, tb=exc.__traceback__))
-
-
-def create_debug_response(request: Request, exc: Exception) -> Response:
- """Create debug response either in plain text or HTML depending on client capabilities.
-
- Args:
- request: A :class:`Request <litestar.connection.Request>` instance.
- exc: An Exception instance to render debug response from.
-
- Returns:
- A response with a rendered exception traceback.
- """
- if MediaType.HTML in request.headers.get("accept", ""):
- content: Any = create_html_response_content(exc=exc, request=request)
- media_type = MediaType.HTML
- elif MediaType.JSON in request.headers.get("accept", ""):
- content = {"details": create_plain_text_response_content(exc), "status_code": HTTP_500_INTERNAL_SERVER_ERROR}
- media_type = MediaType.JSON
- else:
- content = create_plain_text_response_content(exc)
- media_type = MediaType.TEXT
-
- return Response(
- content=content,
- media_type=media_type,
- status_code=HTTP_500_INTERNAL_SERVER_ERROR,
- type_encoders=_get_type_encoders_for_request(request),
- )
-
-
-def _get_type_encoders_for_request(request: Request) -> TypeEncodersMap | None:
- try:
- return request.route_handler.resolve_type_encoders()
- # we might be in a 404, or before we could resolve the handler, so this
- # could potentially error out. In this case we fall back on the application
- # type encoders
- except (KeyError, AttributeError):
- return request.app.type_encoders
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/middleware.py b/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/middleware.py
deleted file mode 100644
index f3ff157..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/middleware.py
+++ /dev/null
@@ -1,316 +0,0 @@
-from __future__ import annotations
-
-import pdb # noqa: T100
-from dataclasses import asdict, dataclass, field
-from inspect import getmro
-from sys import exc_info
-from traceback import format_exception
-from typing import TYPE_CHECKING, Any, Type, cast
-
-from litestar.datastructures import Headers
-from litestar.enums import MediaType, ScopeType
-from litestar.exceptions import HTTPException, LitestarException, WebSocketException
-from litestar.middleware.cors import CORSMiddleware
-from litestar.middleware.exceptions._debug_response import _get_type_encoders_for_request, create_debug_response
-from litestar.serialization import encode_json
-from litestar.status_codes import HTTP_500_INTERNAL_SERVER_ERROR
-from litestar.utils.deprecation import warn_deprecation
-
-__all__ = ("ExceptionHandlerMiddleware", "ExceptionResponseContent", "create_exception_response")
-
-
-if TYPE_CHECKING:
- from starlette.exceptions import HTTPException as StarletteHTTPException
-
- from litestar import Response
- from litestar.app import Litestar
- from litestar.connection import Request
- from litestar.logging import BaseLoggingConfig
- from litestar.types import (
- ASGIApp,
- ExceptionHandler,
- ExceptionHandlersMap,
- Logger,
- Receive,
- Scope,
- Send,
- )
- from litestar.types.asgi_types import WebSocketCloseEvent
-
-
-def get_exception_handler(exception_handlers: ExceptionHandlersMap, exc: Exception) -> ExceptionHandler | None:
- """Given a dictionary that maps exceptions and status codes to handler functions, and an exception, returns the
- appropriate handler if existing.
-
- Status codes are given preference over exception type.
-
- If no status code match exists, each class in the MRO of the exception type is checked and
- the first matching handler is returned.
-
- Finally, if a ``500`` handler is registered, it will be returned for any exception that isn't a
- subclass of :class:`HTTPException <litestar.exceptions.HTTPException>`.
-
- Args:
- exception_handlers: Mapping of status codes and exception types to handlers.
- exc: Exception Instance to be resolved to a handler.
-
- Returns:
- Optional exception handler callable.
- """
- if not exception_handlers:
- return None
-
- default_handler: ExceptionHandler | None = None
- if isinstance(exc, HTTPException):
- if exception_handler := exception_handlers.get(exc.status_code):
- return exception_handler
- else:
- default_handler = exception_handlers.get(HTTP_500_INTERNAL_SERVER_ERROR)
-
- return next(
- (exception_handlers[cast("Type[Exception]", cls)] for cls in getmro(type(exc)) if cls in exception_handlers),
- default_handler,
- )
-
-
-@dataclass
-class ExceptionResponseContent:
- """Represent the contents of an exception-response."""
-
- status_code: int
- """Exception status code."""
- detail: str
- """Exception details or message."""
- media_type: MediaType | str
- """Media type of the response."""
- headers: dict[str, str] | None = field(default=None)
- """Headers to attach to the response."""
- extra: dict[str, Any] | list[Any] | None = field(default=None)
- """An extra mapping to attach to the exception."""
-
- def to_response(self, request: Request | None = None) -> Response:
- """Create a response from the model attributes.
-
- Returns:
- A response instance.
- """
- from litestar.response import Response
-
- content: Any = {k: v for k, v in asdict(self).items() if k not in ("headers", "media_type") and v is not None}
-
- if self.media_type != MediaType.JSON:
- content = encode_json(content)
-
- return Response(
- content=content,
- headers=self.headers,
- status_code=self.status_code,
- media_type=self.media_type,
- type_encoders=_get_type_encoders_for_request(request) if request is not None else None,
- )
-
-
-def _starlette_exception_handler(request: Request[Any, Any, Any], exc: StarletteHTTPException) -> Response:
- return create_exception_response(
- request=request,
- exc=HTTPException(
- detail=exc.detail,
- status_code=exc.status_code,
- headers=exc.headers,
- ),
- )
-
-
-def create_exception_response(request: Request[Any, Any, Any], exc: Exception) -> Response:
- """Construct a response from an exception.
-
- Notes:
- - For instances of :class:`HTTPException <litestar.exceptions.HTTPException>` or other exception classes that have a
- ``status_code`` attribute (e.g. Starlette exceptions), the status code is drawn from the exception, otherwise
- response status is ``HTTP_500_INTERNAL_SERVER_ERROR``.
-
- Args:
- request: The request that triggered the exception.
- exc: An exception.
-
- Returns:
- Response: HTTP response constructed from exception details.
- """
- headers: dict[str, Any] | None
- extra: dict[str, Any] | list | None
-
- if isinstance(exc, HTTPException):
- status_code = exc.status_code
- headers = exc.headers
- extra = exc.extra
- else:
- status_code = HTTP_500_INTERNAL_SERVER_ERROR
- headers = None
- extra = None
-
- detail = (
- exc.detail
- if isinstance(exc, LitestarException) and status_code != HTTP_500_INTERNAL_SERVER_ERROR
- else "Internal Server Error"
- )
-
- try:
- media_type = request.route_handler.media_type
- except (KeyError, AttributeError):
- media_type = MediaType.JSON
-
- content = ExceptionResponseContent(
- status_code=status_code,
- detail=detail,
- headers=headers,
- extra=extra,
- media_type=media_type,
- )
- return content.to_response(request=request)
-
-
-class ExceptionHandlerMiddleware:
- """Middleware used to wrap an ASGIApp inside a try catch block and handle any exceptions raised.
-
- This used in multiple layers of Litestar.
- """
-
- def __init__(self, app: ASGIApp, debug: bool | None, exception_handlers: ExceptionHandlersMap) -> None:
- """Initialize ``ExceptionHandlerMiddleware``.
-
- Args:
- app: The ``next`` ASGI app to call.
- debug: Whether ``debug`` mode is enabled. Deprecated. Debug mode will be inferred from the request scope
- exception_handlers: A dictionary mapping status codes and/or exception types to handler functions.
-
- .. deprecated:: 2.0.0
- The ``debug`` parameter is deprecated. It will be inferred from the request scope
- """
- self.app = app
- self.exception_handlers = exception_handlers
- self.debug = debug
- if debug is not None:
- warn_deprecation(
- "2.0.0",
- deprecated_name="debug",
- kind="parameter",
- info="Debug mode will be inferred from the request scope",
- )
-
- self._get_debug = self._get_debug_scope if debug is None else lambda *a: debug
-
- @staticmethod
- def _get_debug_scope(scope: Scope) -> bool:
- return scope["app"].debug
-
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
- """ASGI-callable.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
- try:
- await self.app(scope, receive, send)
- except Exception as e: # noqa: BLE001
- litestar_app = scope["app"]
-
- if litestar_app.logging_config and (logger := litestar_app.logger):
- self.handle_exception_logging(logger=logger, logging_config=litestar_app.logging_config, scope=scope)
-
- for hook in litestar_app.after_exception:
- await hook(e, scope)
-
- if litestar_app.pdb_on_exception:
- pdb.post_mortem()
-
- if scope["type"] == ScopeType.HTTP:
- await self.handle_request_exception(
- litestar_app=litestar_app, scope=scope, receive=receive, send=send, exc=e
- )
- else:
- await self.handle_websocket_exception(send=send, exc=e)
-
- async def handle_request_exception(
- self, litestar_app: Litestar, scope: Scope, receive: Receive, send: Send, exc: Exception
- ) -> None:
- """Handle exception raised inside 'http' scope routes.
-
- Args:
- litestar_app: The litestar app instance.
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
- exc: The caught exception.
-
- Returns:
- None.
- """
-
- headers = Headers.from_scope(scope=scope)
- if litestar_app.cors_config and (origin := headers.get("origin")):
- cors_middleware = CORSMiddleware(app=self.app, config=litestar_app.cors_config)
- send = cors_middleware.send_wrapper(send=send, origin=origin, has_cookie="cookie" in headers)
-
- exception_handler = get_exception_handler(self.exception_handlers, exc) or self.default_http_exception_handler
- request: Request[Any, Any, Any] = litestar_app.request_class(scope=scope, receive=receive, send=send)
- response = exception_handler(request, exc)
- await response.to_asgi_response(app=None, request=request)(scope=scope, receive=receive, send=send)
-
- @staticmethod
- async def handle_websocket_exception(send: Send, exc: Exception) -> None:
- """Handle exception raised inside 'websocket' scope routes.
-
- Args:
- send: The ASGI send function.
- exc: The caught exception.
-
- Returns:
- None.
- """
- code = 4000 + HTTP_500_INTERNAL_SERVER_ERROR
- reason = "Internal Server Error"
- if isinstance(exc, WebSocketException):
- code = exc.code
- reason = exc.detail
- elif isinstance(exc, LitestarException):
- reason = exc.detail
-
- event: WebSocketCloseEvent = {"type": "websocket.close", "code": code, "reason": reason}
- await send(event)
-
- def default_http_exception_handler(self, request: Request, exc: Exception) -> Response[Any]:
- """Handle an HTTP exception by returning the appropriate response.
-
- Args:
- request: An HTTP Request instance.
- exc: The caught exception.
-
- Returns:
- An HTTP response.
- """
- status_code = exc.status_code if isinstance(exc, HTTPException) else HTTP_500_INTERNAL_SERVER_ERROR
- if status_code == HTTP_500_INTERNAL_SERVER_ERROR and self._get_debug_scope(request.scope):
- return create_debug_response(request=request, exc=exc)
- return create_exception_response(request=request, exc=exc)
-
- def handle_exception_logging(self, logger: Logger, logging_config: BaseLoggingConfig, scope: Scope) -> None:
- """Handle logging - if the litestar app has a logging config in place.
-
- Args:
- logger: A logger instance.
- logging_config: Logging Config instance.
- scope: The ASGI connection scope.
-
- Returns:
- None
- """
- if (
- logging_config.log_exceptions == "always"
- or (logging_config.log_exceptions == "debug" and self._get_debug_scope(scope))
- ) and logging_config.exception_logging_handler:
- logging_config.exception_logging_handler(logger, scope, format_exception(*exc_info()))
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/templates/body.html b/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/templates/body.html
deleted file mode 100644
index 1c6705c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/templates/body.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!doctype html>
-
-<html lang="en">
- <head>
- <meta charset="utf-8" />
- <style type="text/css">
- {styles}
- </style>
- <title>Litestar exception page</title>
- </head>
- <body>
- <h4>{error}</h4>
- <h3><span>{error_description}</span></h3>
- {exception_data}
- <script type="text/javascript">
- // prettier-ignore
- {scripts} // NOSONAR
- </script>
- </body>
-</html>
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/templates/frame.html b/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/templates/frame.html
deleted file mode 100644
index 2ead8dd..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/templates/frame.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<div class="frame {frame_class}">
- <div class="frame-name">
- <span class="expander">â–¼</span>
- <span class="breakable">{file}</span> in <span>{symbol_name}</span> at line
- <span>{line}</span>
- </div>
- <div class="code-snippet-wrapper">
- <table role="presentation" class="code-snippet">
- {code}
- </table>
- </div>
-</div>
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/templates/scripts.js b/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/templates/scripts.js
deleted file mode 100644
index 014a256..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/templates/scripts.js
+++ /dev/null
@@ -1,27 +0,0 @@
-const expanders = document.querySelectorAll(".frame .expander");
-
-for (const expander of expanders) {
- expander.addEventListener("click", (evt) => {
- const currentSnippet = evt.currentTarget.closest(".frame");
- const snippetWrapper = currentSnippet.querySelector(
- ".code-snippet-wrapper",
- );
- if (currentSnippet.classList.contains("collapsed")) {
- snippetWrapper.style.height = `${snippetWrapper.scrollHeight}px`;
- currentSnippet.classList.remove("collapsed");
- } else {
- currentSnippet.classList.add("collapsed");
- snippetWrapper.style.height = "0px";
- }
- });
-}
-
-// init height for non-collapsed code snippets so animation will be show
-// their first collapse
-const nonCollapsedSnippets = document.querySelectorAll(
- ".frame:not(.collapsed) .code-snippet-wrapper",
-);
-
-for (const snippet of nonCollapsedSnippets) {
- snippet.style.height = `${snippet.scrollHeight}px`;
-}
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/templates/styles.css b/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/templates/styles.css
deleted file mode 100644
index 6b98b89..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/exceptions/templates/styles.css
+++ /dev/null
@@ -1,121 +0,0 @@
-:root {
- --code-background-color: #f5f5f5;
- --code-background-color-dark: #b8b8b8;
- --code-color: #1d2534;
- --code-color-light: #546996;
- --code-font-family: Consolas, monospace;
- --header-color: #303b55;
- --warn-color: hsl(356, 92%, 60%);
- --text-font-family: -apple-system, BlinkMacSystemFont, Helvetica, Arial,
- sans-serif;
-}
-
-html {
- font-size: 20px;
-}
-
-body {
- font-family: var(--text-font-family);
- font-size: 0.8rem;
-}
-
-h1,
-h2,
-h3,
-h4 {
- color: var(--header-color);
-}
-
-h4 {
- font-size: 1rem;
-}
-
-h3 {
- font-size: 1.35rem;
-}
-
-h2 {
- font-size: 1.83rem;
-}
-
-h3 span,
-h4 span {
- color: var(--warn-color);
-}
-
-.frame {
- background-color: var(--code-background-color);
- border-radius: 0.2rem;
- margin-bottom: 20px;
-}
-
-.frame-name {
- border-bottom: 1px solid var(--code-color-light);
- padding: 10px 16px;
-}
-
-.frame.collapsed .frame-name {
- border-bottom: none;
-}
-
-.frame-name span {
- font-weight: 700;
-}
-
-span.expander {
- display: inline-block;
- margin-right: 10px;
- cursor: pointer;
- transition: transform 0.33s ease-in-out;
-}
-
-.frame.collapsed span.expander {
- transform: rotate(-90deg);
-}
-
-.frame-name span.breakable {
- word-break: break-all;
-}
-
-.code-snippet-wrapper {
- height: auto;
- overflow-y: hidden;
- transition: height 0.33s ease-in-out;
-}
-
-.frame.collapsed .code-snippet-wrapper {
- height: 0;
-}
-
-.code-snippet {
- margin: 10px 16px;
- border-spacing: 0 0;
- color: var(--code-color);
- font-family: var(--code-font-family);
- font-size: 0.68rem;
-}
-
-.code-snippet td {
- padding: 0;
- text-align: left;
-}
-
-td.line_no {
- color: var(--code-color-light);
- min-width: 4ch;
- padding-right: 20px;
- text-align: right;
- user-select: none;
-}
-
-td.code_line {
- width: 99%;
-}
-
-tr.executed-line {
- background-color: var(--code-background-color-dark);
-}
-
-.cause-wrapper {
- margin-top: 50px;
-}
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/logging.py b/venv/lib/python3.11/site-packages/litestar/middleware/logging.py
deleted file mode 100644
index 0094f10..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/logging.py
+++ /dev/null
@@ -1,360 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass, field
-from typing import TYPE_CHECKING, Any, Iterable
-
-from litestar.constants import (
- HTTP_RESPONSE_BODY,
- HTTP_RESPONSE_START,
-)
-from litestar.data_extractors import (
- ConnectionDataExtractor,
- RequestExtractorField,
- ResponseDataExtractor,
- ResponseExtractorField,
-)
-from litestar.enums import ScopeType
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.middleware.base import AbstractMiddleware, DefineMiddleware
-from litestar.serialization import encode_json
-from litestar.utils.empty import value_or_default
-from litestar.utils.scope import get_serializer_from_scope
-from litestar.utils.scope.state import ScopeState
-
-__all__ = ("LoggingMiddleware", "LoggingMiddlewareConfig")
-
-
-if TYPE_CHECKING:
- from litestar.connection import Request
- from litestar.types import (
- ASGIApp,
- Logger,
- Message,
- Receive,
- Scope,
- Send,
- Serializer,
- )
-
-try:
- from structlog.types import BindableLogger
-
- structlog_installed = True
-except ImportError:
- BindableLogger = object # type: ignore[assignment, misc]
- structlog_installed = False
-
-
-class LoggingMiddleware(AbstractMiddleware):
- """Logging middleware."""
-
- __slots__ = ("config", "logger", "request_extractor", "response_extractor", "is_struct_logger")
-
- logger: Logger
-
- def __init__(self, app: ASGIApp, config: LoggingMiddlewareConfig) -> None:
- """Initialize ``LoggingMiddleware``.
-
- Args:
- app: The ``next`` ASGI app to call.
- config: An instance of LoggingMiddlewareConfig.
- """
- super().__init__(
- app=app, scopes={ScopeType.HTTP}, exclude=config.exclude, exclude_opt_key=config.exclude_opt_key
- )
- self.is_struct_logger = structlog_installed
- self.config = config
-
- self.request_extractor = ConnectionDataExtractor(
- extract_body="body" in self.config.request_log_fields,
- extract_client="client" in self.config.request_log_fields,
- extract_content_type="content_type" in self.config.request_log_fields,
- extract_cookies="cookies" in self.config.request_log_fields,
- extract_headers="headers" in self.config.request_log_fields,
- extract_method="method" in self.config.request_log_fields,
- extract_path="path" in self.config.request_log_fields,
- extract_path_params="path_params" in self.config.request_log_fields,
- extract_query="query" in self.config.request_log_fields,
- extract_scheme="scheme" in self.config.request_log_fields,
- obfuscate_cookies=self.config.request_cookies_to_obfuscate,
- obfuscate_headers=self.config.request_headers_to_obfuscate,
- parse_body=self.is_struct_logger,
- parse_query=self.is_struct_logger,
- skip_parse_malformed_body=True,
- )
- self.response_extractor = ResponseDataExtractor(
- extract_body="body" in self.config.response_log_fields,
- extract_headers="headers" in self.config.response_log_fields,
- extract_status_code="status_code" in self.config.response_log_fields,
- obfuscate_cookies=self.config.response_cookies_to_obfuscate,
- obfuscate_headers=self.config.response_headers_to_obfuscate,
- )
-
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
- """ASGI callable.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
- if not hasattr(self, "logger"):
- self.logger = scope["app"].get_logger(self.config.logger_name)
- self.is_struct_logger = structlog_installed and repr(self.logger).startswith("<BoundLoggerLazyProxy")
-
- if self.config.response_log_fields:
- send = self.create_send_wrapper(scope=scope, send=send)
-
- if self.config.request_log_fields:
- await self.log_request(scope=scope, receive=receive)
-
- await self.app(scope, receive, send)
-
- async def log_request(self, scope: Scope, receive: Receive) -> None:
- """Extract request data and log the message.
-
- Args:
- scope: The ASGI connection scope.
- receive: ASGI receive callable
-
- Returns:
- None
- """
- extracted_data = await self.extract_request_data(request=scope["app"].request_class(scope, receive))
- self.log_message(values=extracted_data)
-
- def log_response(self, scope: Scope) -> None:
- """Extract the response data and log the message.
-
- Args:
- scope: The ASGI connection scope.
-
- Returns:
- None
- """
- extracted_data = self.extract_response_data(scope=scope)
- self.log_message(values=extracted_data)
-
- def log_message(self, values: dict[str, Any]) -> None:
- """Log a message.
-
- Args:
- values: Extract values to log.
-
- Returns:
- None
- """
- message = values.pop("message")
- if self.is_struct_logger:
- self.logger.info(message, **values)
- else:
- value_strings = [f"{key}={value}" for key, value in values.items()]
- log_message = f"{message}: {', '.join(value_strings)}"
- self.logger.info(log_message)
-
- def _serialize_value(self, serializer: Serializer | None, value: Any) -> Any:
- if not self.is_struct_logger and isinstance(value, (dict, list, tuple, set)):
- value = encode_json(value, serializer)
- return value.decode("utf-8", errors="backslashreplace") if isinstance(value, bytes) else value
-
- async def extract_request_data(self, request: Request) -> dict[str, Any]:
- """Create a dictionary of values for the message.
-
- Args:
- request: A :class:`Request <litestar.connection.Request>` instance.
-
- Returns:
- An dict.
- """
-
- data: dict[str, Any] = {"message": self.config.request_log_message}
- serializer = get_serializer_from_scope(request.scope)
-
- extracted_data = await self.request_extractor.extract(connection=request, fields=self.config.request_log_fields)
-
- for key in self.config.request_log_fields:
- data[key] = self._serialize_value(serializer, extracted_data.get(key))
- return data
-
- def extract_response_data(self, scope: Scope) -> dict[str, Any]:
- """Extract data from the response.
-
- Args:
- scope: The ASGI connection scope.
-
- Returns:
- An dict.
- """
- data: dict[str, Any] = {"message": self.config.response_log_message}
- serializer = get_serializer_from_scope(scope)
- connection_state = ScopeState.from_scope(scope)
- extracted_data = self.response_extractor(
- messages=(
- connection_state.log_context.pop(HTTP_RESPONSE_START),
- connection_state.log_context.pop(HTTP_RESPONSE_BODY),
- ),
- )
- response_body_compressed = value_or_default(connection_state.response_compressed, False)
- for key in self.config.response_log_fields:
- value: Any
- value = extracted_data.get(key)
- if key == "body" and response_body_compressed:
- if self.config.include_compressed_body:
- data[key] = value
- continue
- data[key] = self._serialize_value(serializer, value)
- return data
-
- def create_send_wrapper(self, scope: Scope, send: Send) -> Send:
- """Create a ``send`` wrapper, which handles logging response data.
-
- Args:
- scope: The ASGI connection scope.
- send: The ASGI send function.
-
- Returns:
- An ASGI send function.
- """
- connection_state = ScopeState.from_scope(scope)
-
- async def send_wrapper(message: Message) -> None:
- if message["type"] == HTTP_RESPONSE_START:
- connection_state.log_context[HTTP_RESPONSE_START] = message
- elif message["type"] == HTTP_RESPONSE_BODY:
- connection_state.log_context[HTTP_RESPONSE_BODY] = message
- self.log_response(scope=scope)
- await send(message)
-
- return send_wrapper
-
-
-@dataclass
-class LoggingMiddlewareConfig:
- """Configuration for ``LoggingMiddleware``"""
-
- exclude: str | list[str] | None = field(default=None)
- """List of paths to exclude from logging."""
- exclude_opt_key: str | None = field(default=None)
- """An identifier to use on routes to disable logging for a particular route."""
- include_compressed_body: bool = field(default=False)
- """Include body of compressed response in middleware. If `"body"` not set in.
- :attr:`response_log_fields <LoggingMiddlewareConfig.response_log_fields>` this config value is ignored.
- """
- logger_name: str = field(default="litestar")
- """Name of the logger to retrieve using `app.get_logger("<name>")`."""
- request_cookies_to_obfuscate: set[str] = field(default_factory=lambda: {"session"})
- """Request cookie keys to obfuscate.
-
- Obfuscated values are replaced with '*****'.
- """
- request_headers_to_obfuscate: set[str] = field(default_factory=lambda: {"Authorization", "X-API-KEY"})
- """Request header keys to obfuscate.
-
- Obfuscated values are replaced with '*****'.
- """
- response_cookies_to_obfuscate: set[str] = field(default_factory=lambda: {"session"})
- """Response cookie keys to obfuscate.
-
- Obfuscated values are replaced with '*****'.
- """
- response_headers_to_obfuscate: set[str] = field(default_factory=lambda: {"Authorization", "X-API-KEY"})
- """Response header keys to obfuscate.
-
- Obfuscated values are replaced with '*****'.
- """
- request_log_message: str = field(default="HTTP Request")
- """Log message to prepend when logging a request."""
- response_log_message: str = field(default="HTTP Response")
- """Log message to prepend when logging a response."""
- request_log_fields: Iterable[RequestExtractorField] = field(
- default=(
- "path",
- "method",
- "content_type",
- "headers",
- "cookies",
- "query",
- "path_params",
- "body",
- )
- )
- """Fields to extract and log from the request.
-
- Notes:
- - The order of fields in the iterable determines the order of the log message logged out.
- Thus, re-arranging the log-message is as simple as changing the iterable.
- - To turn off logging of requests, use and empty iterable.
- """
- response_log_fields: Iterable[ResponseExtractorField] = field(
- default=(
- "status_code",
- "cookies",
- "headers",
- "body",
- )
- )
- """Fields to extract and log from the response. The order of fields in the iterable determines the order of the log
- message logged out.
-
- Notes:
- - The order of fields in the iterable determines the order of the log message logged out.
- Thus, re-arranging the log-message is as simple as changing the iterable.
- - To turn off logging of responses, use and empty iterable.
- """
- middleware_class: type[LoggingMiddleware] = field(default=LoggingMiddleware)
- """Middleware class to use.
-
- Should be a subclass of [litestar.middleware.LoggingMiddleware].
- """
-
- def __post_init__(self) -> None:
- """Override default Pydantic type conversion for iterables.
-
- Args:
- value: An iterable
-
- Returns:
- The `value` argument cast as a tuple.
- """
- if not isinstance(self.response_log_fields, Iterable):
- raise ImproperlyConfiguredException("response_log_fields must be a valid Iterable")
-
- if not isinstance(self.request_log_fields, Iterable):
- raise ImproperlyConfiguredException("request_log_fields must be a valid Iterable")
-
- self.response_log_fields = tuple(self.response_log_fields)
- self.request_log_fields = tuple(self.request_log_fields)
-
- @property
- def middleware(self) -> DefineMiddleware:
- """Use this property to insert the config into a middleware list on one of the application layers.
-
- Examples:
- .. code-block:: python
-
- from litestar import Litestar, Request, get
- from litestar.logging import LoggingConfig
- from litestar.middleware.logging import LoggingMiddlewareConfig
-
- logging_config = LoggingConfig()
-
- logging_middleware_config = LoggingMiddlewareConfig()
-
-
- @get("/")
- def my_handler(request: Request) -> None: ...
-
-
- app = Litestar(
- route_handlers=[my_handler],
- logging_config=logging_config,
- middleware=[logging_middleware_config.middleware],
- )
-
- Returns:
- An instance of DefineMiddleware including ``self`` as the config kwarg value.
- """
- return DefineMiddleware(self.middleware_class, config=self)
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/rate_limit.py b/venv/lib/python3.11/site-packages/litestar/middleware/rate_limit.py
deleted file mode 100644
index cd767ba..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/rate_limit.py
+++ /dev/null
@@ -1,275 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass, field
-from time import time
-from typing import TYPE_CHECKING, Any, Callable, Literal, cast
-
-from litestar.datastructures import MutableScopeHeaders
-from litestar.enums import ScopeType
-from litestar.exceptions import TooManyRequestsException
-from litestar.middleware.base import AbstractMiddleware, DefineMiddleware
-from litestar.serialization import decode_json, encode_json
-from litestar.utils import ensure_async_callable
-
-__all__ = ("CacheObject", "RateLimitConfig", "RateLimitMiddleware")
-
-
-if TYPE_CHECKING:
- from typing import Awaitable
-
- from litestar import Litestar
- from litestar.connection import Request
- from litestar.stores.base import Store
- from litestar.types import ASGIApp, Message, Receive, Scope, Send, SyncOrAsyncUnion
-
-
-DurationUnit = Literal["second", "minute", "hour", "day"]
-
-DURATION_VALUES: dict[DurationUnit, int] = {"second": 1, "minute": 60, "hour": 3600, "day": 86400}
-
-
-@dataclass
-class CacheObject:
- """Representation of a cached object's metadata."""
-
- __slots__ = ("history", "reset")
-
- history: list[int]
- reset: int
-
-
-class RateLimitMiddleware(AbstractMiddleware):
- """Rate-limiting middleware."""
-
- __slots__ = ("app", "check_throttle_handler", "max_requests", "unit", "request_quota", "config")
-
- def __init__(self, app: ASGIApp, config: RateLimitConfig) -> None:
- """Initialize ``RateLimitMiddleware``.
-
- Args:
- app: The ``next`` ASGI app to call.
- config: An instance of RateLimitConfig.
- """
- super().__init__(
- app=app, exclude=config.exclude, exclude_opt_key=config.exclude_opt_key, scopes={ScopeType.HTTP}
- )
- self.check_throttle_handler = cast("Callable[[Request], Awaitable[bool]] | None", config.check_throttle_handler)
- self.config = config
- self.max_requests: int = config.rate_limit[1]
- self.unit: DurationUnit = config.rate_limit[0]
-
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
- """ASGI callable.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
- app = scope["app"]
- request: Request[Any, Any, Any] = app.request_class(scope)
- store = self.config.get_store_from_app(app)
- if await self.should_check_request(request=request):
- key = self.cache_key_from_request(request=request)
- cache_object = await self.retrieve_cached_history(key, store)
- if len(cache_object.history) >= self.max_requests:
- raise TooManyRequestsException(
- headers=self.create_response_headers(cache_object=cache_object)
- if self.config.set_rate_limit_headers
- else None
- )
- await self.set_cached_history(key=key, cache_object=cache_object, store=store)
- if self.config.set_rate_limit_headers:
- send = self.create_send_wrapper(send=send, cache_object=cache_object)
-
- await self.app(scope, receive, send) # pyright: ignore
-
- def create_send_wrapper(self, send: Send, cache_object: CacheObject) -> Send:
- """Create a ``send`` function that wraps the original send to inject response headers.
-
- Args:
- send: The ASGI send function.
- cache_object: A StorageObject instance.
-
- Returns:
- Send wrapper callable.
- """
-
- async def send_wrapper(message: Message) -> None:
- """Wrap the ASGI ``Send`` callable.
-
- Args:
- message: An ASGI ``Message``
-
- Returns:
- None
- """
- if message["type"] == "http.response.start":
- message.setdefault("headers", [])
- headers = MutableScopeHeaders(message)
- for key, value in self.create_response_headers(cache_object=cache_object).items():
- headers.add(key, value)
- await send(message)
-
- return send_wrapper
-
- def cache_key_from_request(self, request: Request[Any, Any, Any]) -> str:
- """Get a cache-key from a ``Request``
-
- Args:
- request: A :class:`Request <.connection.Request>` instance.
-
- Returns:
- A cache key.
- """
- host = request.client.host if request.client else "anonymous"
- identifier = request.headers.get("X-Forwarded-For") or request.headers.get("X-Real-IP") or host
- route_handler = request.scope["route_handler"]
- if getattr(route_handler, "is_mount", False):
- identifier += "::mount"
-
- if getattr(route_handler, "is_static", False):
- identifier += "::static"
-
- return f"{type(self).__name__}::{identifier}"
-
- async def retrieve_cached_history(self, key: str, store: Store) -> CacheObject:
- """Retrieve a list of time stamps for the given duration unit.
-
- Args:
- key: Cache key.
- store: A :class:`Store <.stores.base.Store>`
-
- Returns:
- An :class:`CacheObject`.
- """
- duration = DURATION_VALUES[self.unit]
- now = int(time())
- cached_string = await store.get(key)
- if cached_string:
- cache_object = CacheObject(**decode_json(value=cached_string))
- if cache_object.reset <= now:
- return CacheObject(history=[], reset=now + duration)
-
- while cache_object.history and cache_object.history[-1] <= now - duration:
- cache_object.history.pop()
- return cache_object
-
- return CacheObject(history=[], reset=now + duration)
-
- async def set_cached_history(self, key: str, cache_object: CacheObject, store: Store) -> None:
- """Store history extended with the current timestamp in cache.
-
- Args:
- key: Cache key.
- cache_object: A :class:`CacheObject`.
- store: A :class:`Store <.stores.base.Store>`
-
- Returns:
- None
- """
- cache_object.history = [int(time()), *cache_object.history]
- await store.set(key, encode_json(cache_object), expires_in=DURATION_VALUES[self.unit])
-
- async def should_check_request(self, request: Request[Any, Any, Any]) -> bool:
- """Return a boolean indicating if a request should be checked for rate limiting.
-
- Args:
- request: A :class:`Request <.connection.Request>` instance.
-
- Returns:
- Boolean dictating whether the request should be checked for rate-limiting.
- """
- if self.check_throttle_handler:
- return await self.check_throttle_handler(request)
- return True
-
- def create_response_headers(self, cache_object: CacheObject) -> dict[str, str]:
- """Create ratelimit response headers.
-
- Notes:
- * see the `IETF RateLimit draft <https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/>_`
-
- Args:
- cache_object:A :class:`CacheObject`.
-
- Returns:
- A dict of http headers.
- """
- remaining_requests = str(
- len(cache_object.history) - self.max_requests if len(cache_object.history) <= self.max_requests else 0
- )
-
- return {
- self.config.rate_limit_policy_header_key: f"{self.max_requests}; w={DURATION_VALUES[self.unit]}",
- self.config.rate_limit_limit_header_key: str(self.max_requests),
- self.config.rate_limit_remaining_header_key: remaining_requests,
- self.config.rate_limit_reset_header_key: str(int(time()) - cache_object.reset),
- }
-
-
-@dataclass
-class RateLimitConfig:
- """Configuration for ``RateLimitMiddleware``"""
-
- rate_limit: tuple[DurationUnit, int]
- """A tuple containing a time unit (second, minute, hour, day) and quantity, e.g. ("day", 1) or ("minute", 5)."""
- exclude: str | list[str] | None = field(default=None)
- """A pattern or list of patterns to skip in the rate limiting middleware."""
- exclude_opt_key: str | None = field(default=None)
- """An identifier to use on routes to disable rate limiting for a particular route."""
- check_throttle_handler: Callable[[Request[Any, Any, Any]], SyncOrAsyncUnion[bool]] | None = field(default=None)
- """Handler callable that receives the request instance, returning a boolean dictating whether or not the request
- should be checked for rate limiting.
- """
- middleware_class: type[RateLimitMiddleware] = field(default=RateLimitMiddleware)
- """The middleware class to use."""
- set_rate_limit_headers: bool = field(default=True)
- """Boolean dictating whether to set the rate limit headers on the response."""
- rate_limit_policy_header_key: str = field(default="RateLimit-Policy")
- """Key to use for the rate limit policy header."""
- rate_limit_remaining_header_key: str = field(default="RateLimit-Remaining")
- """Key to use for the rate limit remaining header."""
- rate_limit_reset_header_key: str = field(default="RateLimit-Reset")
- """Key to use for the rate limit reset header."""
- rate_limit_limit_header_key: str = field(default="RateLimit-Limit")
- """Key to use for the rate limit limit header."""
- store: str = "rate_limit"
- """Name of the :class:`Store <.stores.base.Store>` to use"""
-
- def __post_init__(self) -> None:
- if self.check_throttle_handler:
- self.check_throttle_handler = ensure_async_callable(self.check_throttle_handler) # type: ignore[arg-type]
-
- @property
- def middleware(self) -> DefineMiddleware:
- """Use this property to insert the config into a middleware list on one of the application layers.
-
- Examples:
- .. code-block:: python
-
- from litestar import Litestar, Request, get
- from litestar.middleware.rate_limit import RateLimitConfig
-
- # limit to 10 requests per minute, excluding the schema path
- throttle_config = RateLimitConfig(rate_limit=("minute", 10), exclude=["/schema"])
-
-
- @get("/")
- def my_handler(request: Request) -> None: ...
-
-
- app = Litestar(route_handlers=[my_handler], middleware=[throttle_config.middleware])
-
- Returns:
- An instance of :class:`DefineMiddleware <.middleware.base.DefineMiddleware>` including ``self`` as the
- config kwarg value.
- """
- return DefineMiddleware(self.middleware_class, config=self)
-
- def get_store_from_app(self, app: Litestar) -> Store:
- """Get the store defined in :attr:`store` from an :class:`Litestar <.app.Litestar>` instance."""
- return app.stores.get(self.store)
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/response_cache.py b/venv/lib/python3.11/site-packages/litestar/middleware/response_cache.py
deleted file mode 100644
index 62dcde6..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/response_cache.py
+++ /dev/null
@@ -1,58 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, cast
-
-from msgspec.msgpack import encode as encode_msgpack
-
-from litestar import Request
-from litestar.constants import HTTP_RESPONSE_BODY, HTTP_RESPONSE_START
-from litestar.enums import ScopeType
-from litestar.utils.empty import value_or_default
-from litestar.utils.scope.state import ScopeState
-
-from .base import AbstractMiddleware
-
-if TYPE_CHECKING:
- from litestar.config.response_cache import ResponseCacheConfig
- from litestar.handlers import HTTPRouteHandler
- from litestar.types import ASGIApp, HTTPScope, Message, Receive, Scope, Send
-
-__all__ = ["ResponseCacheMiddleware"]
-
-
-class ResponseCacheMiddleware(AbstractMiddleware):
- def __init__(self, app: ASGIApp, config: ResponseCacheConfig) -> None:
- self.config = config
- super().__init__(app=app, scopes={ScopeType.HTTP})
-
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
- route_handler = cast("HTTPRouteHandler", scope["route_handler"])
-
- expires_in: int | None = None
- if route_handler.cache is True:
- expires_in = self.config.default_expiration
- elif route_handler.cache is not False and isinstance(route_handler.cache, int):
- expires_in = route_handler.cache
-
- connection_state = ScopeState.from_scope(scope)
-
- messages: list[Message] = []
-
- async def wrapped_send(message: Message) -> None:
- if not value_or_default(connection_state.is_cached, False):
- if message["type"] == HTTP_RESPONSE_START:
- do_cache = connection_state.do_cache = self.config.cache_response_filter(
- cast("HTTPScope", scope), message["status"]
- )
- if do_cache:
- messages.append(message)
- elif value_or_default(connection_state.do_cache, False):
- messages.append(message)
-
- if messages and message["type"] == HTTP_RESPONSE_BODY and not message["more_body"]:
- key = (route_handler.cache_key_builder or self.config.key_builder)(Request(scope))
- store = self.config.get_store_from_app(scope["app"])
- await store.set(key, encode_msgpack(messages), expires_in=expires_in)
- await send(message)
-
- await self.app(scope, receive, wrapped_send)
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/session/__init__.py b/venv/lib/python3.11/site-packages/litestar/middleware/session/__init__.py
deleted file mode 100644
index 1ca9c17..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/session/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from .base import SessionMiddleware
-
-__all__ = ("SessionMiddleware",)
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/session/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/session/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 8748ce3..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/session/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/session/__pycache__/base.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/session/__pycache__/base.cpython-311.pyc
deleted file mode 100644
index 68a8b9c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/session/__pycache__/base.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/session/__pycache__/client_side.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/session/__pycache__/client_side.cpython-311.pyc
deleted file mode 100644
index 692f54c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/session/__pycache__/client_side.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/session/__pycache__/server_side.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/middleware/session/__pycache__/server_side.cpython-311.pyc
deleted file mode 100644
index bd2373c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/session/__pycache__/server_side.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/session/base.py b/venv/lib/python3.11/site-packages/litestar/middleware/session/base.py
deleted file mode 100644
index a823848..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/session/base.py
+++ /dev/null
@@ -1,256 +0,0 @@
-from __future__ import annotations
-
-from abc import ABC, abstractmethod
-from typing import (
- TYPE_CHECKING,
- Any,
- Awaitable,
- Callable,
- Generic,
- Literal,
- TypeVar,
- cast,
-)
-
-from litestar.connection import ASGIConnection
-from litestar.enums import ScopeType
-from litestar.middleware.base import AbstractMiddleware, DefineMiddleware
-from litestar.serialization import decode_json, encode_json
-from litestar.utils import get_serializer_from_scope
-
-__all__ = ("BaseBackendConfig", "BaseSessionBackend", "SessionMiddleware")
-
-
-if TYPE_CHECKING:
- from litestar.types import ASGIApp, Message, Receive, Scope, Scopes, ScopeSession, Send
-
-ONE_DAY_IN_SECONDS = 60 * 60 * 24
-
-ConfigT = TypeVar("ConfigT", bound="BaseBackendConfig")
-BaseSessionBackendT = TypeVar("BaseSessionBackendT", bound="BaseSessionBackend")
-
-
-class BaseBackendConfig(ABC, Generic[BaseSessionBackendT]): # pyright: ignore
- """Configuration for Session middleware backends."""
-
- _backend_class: type[BaseSessionBackendT] # pyright: ignore
-
- key: str
- """Key to use for the cookie inside the header, e.g. ``session=<data>`` where ``session`` is the cookie key and
- ``<data>`` is the session data.
-
- Notes:
- - If a session cookie exceeds 4KB in size it is split. In this case the key will be of the format
- ``session-{segment number}``.
-
- """
- max_age: int
- """Maximal age of the cookie before its invalidated."""
- scopes: Scopes = {ScopeType.HTTP, ScopeType.WEBSOCKET}
- """Scopes for the middleware - options are ``http`` and ``websocket`` with the default being both"""
- path: str
- """Path fragment that must exist in the request url for the cookie to be valid.
-
- Defaults to ``'/'``.
- """
- domain: str | None
- """Domain for which the cookie is valid."""
- secure: bool
- """Https is required for the cookie."""
- httponly: bool
- """Forbids javascript to access the cookie via 'Document.cookie'."""
- samesite: Literal["lax", "strict", "none"]
- """Controls whether or not a cookie is sent with cross-site requests.
-
- Defaults to ``lax``.
- """
- exclude: str | list[str] | None
- """A pattern or list of patterns to skip in the session middleware."""
- exclude_opt_key: str
- """An identifier to use on routes to disable the session middleware for a particular route."""
-
- @property
- def middleware(self) -> DefineMiddleware:
- """Use this property to insert the config into a middleware list on one of the application layers.
-
- Examples:
- .. code-block:: python
-
- from os import urandom
-
- from litestar import Litestar, Request, get
- from litestar.middleware.sessions.cookie_backend import CookieBackendConfig
-
- session_config = CookieBackendConfig(secret=urandom(16))
-
-
- @get("/")
- def my_handler(request: Request) -> None: ...
-
-
- app = Litestar(route_handlers=[my_handler], middleware=[session_config.middleware])
-
-
- Returns:
- An instance of DefineMiddleware including ``self`` as the config kwarg value.
- """
- return DefineMiddleware(SessionMiddleware, backend=self._backend_class(config=self))
-
-
-class BaseSessionBackend(ABC, Generic[ConfigT]):
- """Abstract session backend defining the interface between a storage mechanism and the application
- :class:`SessionMiddleware`.
-
- This serves as the base class for all client- and server-side backends
- """
-
- __slots__ = ("config",)
-
- def __init__(self, config: ConfigT) -> None:
- """Initialize ``BaseSessionBackend``
-
- Args:
- config: A instance of a subclass of ``BaseBackendConfig``
- """
- self.config = config
-
- @staticmethod
- def serialize_data(data: ScopeSession, scope: Scope | None = None) -> bytes:
- """Serialize data into bytes for storage in the backend.
-
- Args:
- data: Session data of the current scope.
- scope: A scope, if applicable, from which to extract a serializer.
-
- Notes:
- - The serializer will be extracted from ``scope`` or fall back to
- :func:`default_serializer <.serialization.default_serializer>`
-
- Returns:
- ``data`` serialized as bytes.
- """
- serializer = get_serializer_from_scope(scope) if scope else None
- return encode_json(data, serializer)
-
- @staticmethod
- def deserialize_data(data: Any) -> dict[str, Any]:
- """Deserialize data into a dictionary for use in the application scope.
-
- Args:
- data: Data to be deserialized
-
- Returns:
- Deserialized data as a dictionary
- """
- return cast("dict[str, Any]", decode_json(value=data))
-
- @abstractmethod
- def get_session_id(self, connection: ASGIConnection) -> str | None:
- """Try to fetch session id from connection ScopeState. If one does not exist, generate one.
-
- Args:
- connection: Originating ASGIConnection containing the scope
-
- Returns:
- Session id str or None if the concept of a session id does not apply.
- """
-
- @abstractmethod
- async def store_in_message(self, scope_session: ScopeSession, message: Message, connection: ASGIConnection) -> None:
- """Store the necessary information in the outgoing ``Message``
-
- Args:
- scope_session: Current session to store
- message: Outgoing send-message
- connection: Originating ASGIConnection containing the scope
-
- Returns:
- None
- """
-
- @abstractmethod
- async def load_from_connection(self, connection: ASGIConnection) -> dict[str, Any]:
- """Load session data from a connection and return it as a dictionary to be used in the current application
- scope.
-
- Args:
- connection: An ASGIConnection instance
-
- Returns:
- The session data
-
- Notes:
- - This should not modify the connection's scope. The data returned by this
- method will be stored in the application scope by the middleware
-
- """
-
-
-class SessionMiddleware(AbstractMiddleware, Generic[BaseSessionBackendT]):
- """Litestar session middleware for storing session data."""
-
- def __init__(self, app: ASGIApp, backend: BaseSessionBackendT) -> None:
- """Initialize ``SessionMiddleware``
-
- Args:
- app: An ASGI application
- backend: A :class:`BaseSessionBackend` instance used to store and retrieve session data
- """
-
- super().__init__(
- app=app,
- exclude=backend.config.exclude,
- exclude_opt_key=backend.config.exclude_opt_key,
- scopes=backend.config.scopes,
- )
- self.backend = backend
-
- def create_send_wrapper(self, connection: ASGIConnection) -> Callable[[Message], Awaitable[None]]:
- """Create a wrapper for the ASGI send function, which handles setting the cookies on the outgoing response.
-
- Args:
- connection: ASGIConnection
-
- Returns:
- None
- """
-
- async def wrapped_send(message: Message) -> None:
- """Wrap the ``send`` function.
-
- Declared in local scope to make use of closure values.
-
- Args:
- message: An ASGI message.
-
- Returns:
- None
- """
- if message["type"] != "http.response.start":
- await connection.send(message)
- return
-
- scope_session = connection.scope.get("session")
-
- await self.backend.store_in_message(scope_session, message, connection)
- await connection.send(message)
-
- return wrapped_send
-
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
- """ASGI-callable.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
-
- connection = ASGIConnection[Any, Any, Any, Any](scope, receive=receive, send=send)
- scope["session"] = await self.backend.load_from_connection(connection)
- connection._connection_state.session_id = self.backend.get_session_id(connection) # pyright: ignore [reportGeneralTypeIssues]
-
- await self.app(scope, receive, self.create_send_wrapper(connection))
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/session/client_side.py b/venv/lib/python3.11/site-packages/litestar/middleware/session/client_side.py
deleted file mode 100644
index f709410..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/session/client_side.py
+++ /dev/null
@@ -1,264 +0,0 @@
-from __future__ import annotations
-
-import binascii
-import contextlib
-import re
-import time
-from base64 import b64decode, b64encode
-from dataclasses import dataclass, field
-from os import urandom
-from typing import TYPE_CHECKING, Any, Literal
-
-from litestar.datastructures import MutableScopeHeaders
-from litestar.datastructures.cookie import Cookie
-from litestar.enums import ScopeType
-from litestar.exceptions import (
- ImproperlyConfiguredException,
- MissingDependencyException,
-)
-from litestar.serialization import decode_json, encode_json
-from litestar.types import Empty, Scopes
-from litestar.utils.dataclass import extract_dataclass_items
-
-from .base import ONE_DAY_IN_SECONDS, BaseBackendConfig, BaseSessionBackend
-
-__all__ = ("ClientSideSessionBackend", "CookieBackendConfig")
-
-
-try:
- from cryptography.exceptions import InvalidTag
- from cryptography.hazmat.primitives.ciphers.aead import AESGCM
-except ImportError as e:
- raise MissingDependencyException("cryptography") from e
-
-if TYPE_CHECKING:
- from litestar.connection import ASGIConnection
- from litestar.types import Message, Scope, ScopeSession
-
-NONCE_SIZE = 12
-CHUNK_SIZE = 4096 - 64
-AAD = b"additional_authenticated_data="
-
-
-class ClientSideSessionBackend(BaseSessionBackend["CookieBackendConfig"]):
- """Cookie backend for SessionMiddleware."""
-
- __slots__ = ("aesgcm", "cookie_re")
-
- def __init__(self, config: CookieBackendConfig) -> None:
- """Initialize ``ClientSideSessionBackend``.
-
- Args:
- config: SessionCookieConfig instance.
- """
- super().__init__(config)
- self.aesgcm = AESGCM(config.secret)
- self.cookie_re = re.compile(rf"{self.config.key}(?:-\d+)?")
-
- def dump_data(self, data: Any, scope: Scope | None = None) -> list[bytes]:
- """Given serializable data, including pydantic models and numpy types, dump it into a bytes string, encrypt,
- encode and split it into chunks of the desirable size.
-
- Args:
- data: Data to serialize, encrypt, encode and chunk.
- scope: The ASGI connection scope.
-
- Notes:
- - The returned list is composed of a chunks of a single base64 encoded
- string that is encrypted using AES-CGM.
-
- Returns:
- List of encoded bytes string of a maximum length equal to the ``CHUNK_SIZE`` constant.
- """
- serialized = self.serialize_data(data, scope)
- associated_data = encode_json({"expires_at": round(time.time()) + self.config.max_age})
- nonce = urandom(NONCE_SIZE)
- encrypted = self.aesgcm.encrypt(nonce, serialized, associated_data=associated_data)
- encoded = b64encode(nonce + encrypted + AAD + associated_data)
- return [encoded[i : i + CHUNK_SIZE] for i in range(0, len(encoded), CHUNK_SIZE)]
-
- def load_data(self, data: list[bytes]) -> dict[str, Any]:
- """Given a list of strings, decodes them into the session object.
-
- Args:
- data: A list of strings derived from the request's session cookie(s).
-
- Returns:
- A deserialized session value.
- """
- decoded = b64decode(b"".join(data))
- nonce = decoded[:NONCE_SIZE]
- aad_starts_from = decoded.find(AAD)
- associated_data = decoded[aad_starts_from:].replace(AAD, b"") if aad_starts_from != -1 else None
- if associated_data and decode_json(value=associated_data)["expires_at"] > round(time.time()):
- encrypted_session = decoded[NONCE_SIZE:aad_starts_from]
- decrypted = self.aesgcm.decrypt(nonce, encrypted_session, associated_data=associated_data)
- return self.deserialize_data(decrypted)
- return {}
-
- def get_cookie_keys(self, connection: ASGIConnection) -> list[str]:
- """Return a list of cookie-keys from the connection if they match the session-cookie pattern.
-
- Args:
- connection: An ASGIConnection instance
-
- Returns:
- A list of session-cookie keys
- """
- return sorted(key for key in connection.cookies if self.cookie_re.fullmatch(key))
-
- def _create_session_cookies(self, data: list[bytes], cookie_params: dict[str, Any] | None = None) -> list[Cookie]:
- """Create a list of cookies containing the session data.
- If the data is split into multiple cookies, the key will be of the format ``session-{segment number}``,
- however if only one cookie is needed, the key will be ``session``.
- """
- if cookie_params is None:
- cookie_params = dict(
- extract_dataclass_items(
- self.config,
- exclude_none=True,
- include={f for f in Cookie.__dict__ if f not in ("key", "secret")},
- )
- )
-
- if len(data) == 1:
- return [
- Cookie(
- value=data[0].decode("utf-8"),
- key=self.config.key,
- **cookie_params,
- )
- ]
-
- return [
- Cookie(
- value=datum.decode("utf-8"),
- key=f"{self.config.key}-{i}",
- **cookie_params,
- )
- for i, datum in enumerate(data)
- ]
-
- async def store_in_message(self, scope_session: ScopeSession, message: Message, connection: ASGIConnection) -> None:
- """Store data from ``scope_session`` in ``Message`` in the form of cookies. If the contents of ``scope_session``
- are too large to fit a single cookie, it will be split across several cookies, following the naming scheme of
- ``<cookie key>-<n>``. If the session is empty or shrinks, cookies will be cleared by setting their value to
- ``"null"``
-
- Args:
- scope_session: Current session to store
- message: Outgoing send-message
- connection: Originating ASGIConnection containing the scope
-
- Returns:
- None
- """
-
- scope = connection.scope
- headers = MutableScopeHeaders.from_message(message)
- cookie_keys = self.get_cookie_keys(connection)
-
- if scope_session and scope_session is not Empty:
- data = self.dump_data(scope_session, scope=scope)
- cookie_params = dict(
- extract_dataclass_items(
- self.config,
- exclude_none=True,
- include={f for f in Cookie.__dict__ if f not in ("key", "secret")},
- )
- )
- for cookie in self._create_session_cookies(data, cookie_params):
- headers.add("Set-Cookie", cookie.to_header(header=""))
- # Cookies with the same key overwrite the earlier cookie with that key. To expire earlier session
- # cookies, first check how many session cookies will not be overwritten in this upcoming response.
- # If leftover cookies are greater than or equal to 1, that means older session cookies have to be
- # expired and their names are in cookie_keys.
- cookies_to_clear = cookie_keys[len(data) :] if len(cookie_keys) - len(data) > 0 else []
- else:
- cookies_to_clear = cookie_keys
-
- for cookie_key in cookies_to_clear:
- cookie_params = dict(
- extract_dataclass_items(
- self.config,
- exclude_none=True,
- include={f for f in Cookie.__dict__ if f not in ("key", "secret", "max_age")},
- )
- )
- headers.add(
- "Set-Cookie",
- Cookie(value="null", key=cookie_key, expires=0, **cookie_params).to_header(header=""),
- )
-
- async def load_from_connection(self, connection: ASGIConnection) -> dict[str, Any]:
- """Load session data from a connection's session-cookies and return it as a dictionary.
-
- Args:
- connection: Originating ASGIConnection
-
- Returns:
- The session data
- """
- if cookie_keys := self.get_cookie_keys(connection):
- data = [connection.cookies[key].encode("utf-8") for key in cookie_keys]
- # If these exceptions occur, the session must remain empty so do nothing.
- with contextlib.suppress(InvalidTag, binascii.Error):
- return self.load_data(data)
- return {}
-
- def get_session_id(self, connection: ASGIConnection) -> str | None:
- return None
-
-
-@dataclass
-class CookieBackendConfig(BaseBackendConfig[ClientSideSessionBackend]): # pyright: ignore
- """Configuration for [SessionMiddleware] middleware."""
-
- _backend_class = ClientSideSessionBackend
-
- secret: bytes
- """A secret key to use for generating an encryption key.
-
- Must have a length of 16 (128 bits), 24 (192 bits) or 32 (256 bits) characters.
- """
- key: str = field(default="session")
- """Key to use for the cookie inside the header, e.g. ``session=<data>`` where ``session`` is the cookie key and
- ``<data>`` is the session data.
-
- Notes:
- - If a session cookie exceeds 4KB in size it is split. In this case the key will be of the format
- ``session-{segment number}``.
-
- """
- max_age: int = field(default=ONE_DAY_IN_SECONDS * 14)
- """Maximal age of the cookie before its invalidated."""
- scopes: Scopes = field(default_factory=lambda: {ScopeType.HTTP, ScopeType.WEBSOCKET})
- """Scopes for the middleware - options are ``http`` and ``websocket`` with the default being both"""
- path: str = field(default="/")
- """Path fragment that must exist in the request url for the cookie to be valid.
-
- Defaults to ``'/'``.
- """
- domain: str | None = field(default=None)
- """Domain for which the cookie is valid."""
- secure: bool = field(default=False)
- """Https is required for the cookie."""
- httponly: bool = field(default=True)
- """Forbids javascript to access the cookie via 'Document.cookie'."""
- samesite: Literal["lax", "strict", "none"] = field(default="lax")
- """Controls whether or not a cookie is sent with cross-site requests.
-
- Defaults to ``lax``.
- """
- exclude: str | list[str] | None = field(default=None)
- """A pattern or list of patterns to skip in the session middleware."""
- exclude_opt_key: str = field(default="skip_session")
- """An identifier to use on routes to disable the session middleware for a particular route."""
-
- def __post_init__(self) -> None:
- if len(self.key) < 1 or len(self.key) > 256:
- raise ImproperlyConfiguredException("key must be a string with a length between 1-256")
- if self.max_age < 1:
- raise ImproperlyConfiguredException("max_age must be greater than 0")
- if len(self.secret) not in {16, 24, 32}:
- raise ImproperlyConfiguredException("secret length must be 16 (128 bit), 24 (192 bit) or 32 (256 bit)")
diff --git a/venv/lib/python3.11/site-packages/litestar/middleware/session/server_side.py b/venv/lib/python3.11/site-packages/litestar/middleware/session/server_side.py
deleted file mode 100644
index 91708ac..0000000
--- a/venv/lib/python3.11/site-packages/litestar/middleware/session/server_side.py
+++ /dev/null
@@ -1,219 +0,0 @@
-from __future__ import annotations
-
-import secrets
-from dataclasses import dataclass, field
-from typing import TYPE_CHECKING, Any, Literal
-
-from litestar.datastructures import Cookie, MutableScopeHeaders
-from litestar.enums import ScopeType
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.middleware.session.base import ONE_DAY_IN_SECONDS, BaseBackendConfig, BaseSessionBackend
-from litestar.types import Empty, Message, Scopes, ScopeSession
-from litestar.utils.dataclass import extract_dataclass_items
-
-__all__ = ("ServerSideSessionBackend", "ServerSideSessionConfig")
-
-
-if TYPE_CHECKING:
- from litestar import Litestar
- from litestar.connection import ASGIConnection
- from litestar.stores.base import Store
-
-
-class ServerSideSessionBackend(BaseSessionBackend["ServerSideSessionConfig"]):
- """Base class for server-side backends.
-
- Implements :class:`BaseSessionBackend` and defines and interface which subclasses can
- implement to facilitate the storage of session data.
- """
-
- def __init__(self, config: ServerSideSessionConfig) -> None:
- """Initialize ``ServerSideSessionBackend``
-
- Args:
- config: A subclass of ``ServerSideSessionConfig``
- """
- super().__init__(config=config)
-
- async def get(self, session_id: str, store: Store) -> bytes | None:
- """Retrieve data associated with ``session_id``.
-
- Args:
- session_id: The session-ID
- store: Store to retrieve the session data from
-
- Returns:
- The session data, if existing, otherwise ``None``.
- """
- max_age = int(self.config.max_age) if self.config.max_age is not None else None
- return await store.get(session_id, renew_for=max_age if self.config.renew_on_access else None)
-
- async def set(self, session_id: str, data: bytes, store: Store) -> None:
- """Store ``data`` under the ``session_id`` for later retrieval.
-
- If there is already data associated with ``session_id``, replace
- it with ``data`` and reset its expiry time
-
- Args:
- session_id: The session-ID
- data: Serialized session data
- store: Store to save the session data in
-
- Returns:
- None
- """
- expires_in = int(self.config.max_age) if self.config.max_age is not None else None
- await store.set(session_id, data, expires_in=expires_in)
-
- async def delete(self, session_id: str, store: Store) -> None:
- """Delete the data associated with ``session_id``. Fails silently if no such session-ID exists.
-
- Args:
- session_id: The session-ID
- store: Store to delete the session data from
-
- Returns:
- None
- """
- await store.delete(session_id)
-
- def get_session_id(self, connection: ASGIConnection) -> str:
- """Try to fetch session id from the connection. If one does not exist, generate one.
-
- If a session ID already exists in the cookies, it is returned.
- If there is no ID in the cookies but one in the connection state, then the session exists but has not yet
- been returned to the user.
- Otherwise, a new session must be created.
-
- Args:
- connection: Originating ASGIConnection containing the scope
- Returns:
- Session id str or None if the concept of a session id does not apply.
- """
- session_id = connection.cookies.get(self.config.key)
- if not session_id or session_id == "null":
- session_id = connection.get_session_id()
- if not session_id:
- session_id = self.generate_session_id()
- return session_id
-
- def generate_session_id(self) -> str:
- """Generate a new session-ID, with
- n=:attr:`session_id_bytes <ServerSideSessionConfig.session_id_bytes>` random bytes.
-
- Returns:
- A session-ID
- """
- return secrets.token_hex(self.config.session_id_bytes)
-
- async def store_in_message(self, scope_session: ScopeSession, message: Message, connection: ASGIConnection) -> None:
- """Store the necessary information in the outgoing ``Message`` by setting a cookie containing the session-ID.
-
- If the session is empty, a null-cookie will be set. Otherwise, the serialised
- data will be stored using :meth:`set <ServerSideSessionBackend.set>`, under the current session-id. If no session-ID
- exists, a new ID will be generated using :meth:`generate_session_id <ServerSideSessionBackend.generate_session_id>`.
-
- Args:
- scope_session: Current session to store
- message: Outgoing send-message
- connection: Originating ASGIConnection containing the scope
-
- Returns:
- None
- """
- scope = connection.scope
- store = self.config.get_store_from_app(scope["app"])
- headers = MutableScopeHeaders.from_message(message)
- session_id = self.get_session_id(connection)
-
- cookie_params = dict(extract_dataclass_items(self.config, exclude_none=True, include=Cookie.__dict__.keys()))
-
- if scope_session is Empty:
- await self.delete(session_id, store=store)
- headers.add(
- "Set-Cookie",
- Cookie(value="null", key=self.config.key, expires=0, **cookie_params).to_header(header=""),
- )
- else:
- serialised_data = self.serialize_data(scope_session, scope)
- await self.set(session_id=session_id, data=serialised_data, store=store)
- headers.add(
- "Set-Cookie", Cookie(value=session_id, key=self.config.key, **cookie_params).to_header(header="")
- )
-
- async def load_from_connection(self, connection: ASGIConnection) -> dict[str, Any]:
- """Load session data from a connection and return it as a dictionary to be used in the current application
- scope.
-
- The session-ID will be gathered from a cookie with the key set in
- :attr:`BaseBackendConfig.key`. If a cookie is found, its value will be used as the session-ID and data associated
- with this ID will be loaded using :meth:`get <ServerSideSessionBackend.get>`.
- If no cookie was found or no data was loaded from the store, this will return an
- empty dictionary.
-
- Args:
- connection: An ASGIConnection instance
-
- Returns:
- The current session data
- """
- if session_id := connection.cookies.get(self.config.key):
- store = self.config.get_store_from_app(connection.scope["app"])
- data = await self.get(session_id, store=store)
- if data is not None:
- return self.deserialize_data(data)
- return {}
-
-
-@dataclass
-class ServerSideSessionConfig(BaseBackendConfig[ServerSideSessionBackend]): # pyright: ignore
- """Base configuration for server side backends."""
-
- _backend_class = ServerSideSessionBackend
-
- session_id_bytes: int = field(default=32)
- """Number of bytes used to generate a random session-ID."""
- renew_on_access: bool = field(default=False)
- """Renew expiry times of sessions when they're being accessed"""
- key: str = field(default="session")
- """Key to use for the cookie inside the header, e.g. ``session=<data>`` where ``session`` is the cookie key and
- ``<data>`` is the session data.
-
- Notes:
- - If a session cookie exceeds 4KB in size it is split. In this case the key will be of the format
- ``session-{segment number}``.
-
- """
- max_age: int = field(default=ONE_DAY_IN_SECONDS * 14)
- """Maximal age of the cookie before its invalidated."""
- scopes: Scopes = field(default_factory=lambda: {ScopeType.HTTP, ScopeType.WEBSOCKET})
- """Scopes for the middleware - options are ``http`` and ``websocket`` with the default being both"""
- path: str = field(default="/")
- """Path fragment that must exist in the request url for the cookie to be valid.
-
- Defaults to ``'/'``.
- """
- domain: str | None = field(default=None)
- """Domain for which the cookie is valid."""
- secure: bool = field(default=False)
- """Https is required for the cookie."""
- httponly: bool = field(default=True)
- """Forbids javascript to access the cookie via 'Document.cookie'."""
- samesite: Literal["lax", "strict", "none"] = field(default="lax")
- """Controls whether or not a cookie is sent with cross-site requests. Defaults to ``lax``."""
- exclude: str | list[str] | None = field(default=None)
- """A pattern or list of patterns to skip in the session middleware."""
- exclude_opt_key: str = field(default="skip_session")
- """An identifier to use on routes to disable the session middleware for a particular route."""
- store: str = "sessions"
- """Name of the :class:`Store <.stores.base.Store>` to use"""
-
- def __post_init__(self) -> None:
- if len(self.key) < 1 or len(self.key) > 256:
- raise ImproperlyConfiguredException("key must be a string with a length between 1-256")
- if self.max_age < 1:
- raise ImproperlyConfiguredException("max_age must be greater than 0")
-
- def get_store_from_app(self, app: Litestar) -> Store:
- """Get the store defined in :attr:`store` from an :class:`Litestar <.app.Litestar>` instance"""
- return app.stores.get(self.store)
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/__init__.py b/venv/lib/python3.11/site-packages/litestar/openapi/__init__.py
deleted file mode 100644
index 8cc83d3..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from .config import OpenAPIConfig
-from .controller import OpenAPIController
-from .datastructures import ResponseSpec
-
-__all__ = ("OpenAPIController", "OpenAPIConfig", "ResponseSpec")
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 510eb6f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/__pycache__/config.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/__pycache__/config.cpython-311.pyc
deleted file mode 100644
index 16411a1..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/__pycache__/config.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/__pycache__/controller.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/__pycache__/controller.cpython-311.pyc
deleted file mode 100644
index f153bae..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/__pycache__/controller.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/__pycache__/datastructures.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/__pycache__/datastructures.cpython-311.pyc
deleted file mode 100644
index 042a57f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/__pycache__/datastructures.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/config.py b/venv/lib/python3.11/site-packages/litestar/openapi/config.py
deleted file mode 100644
index c935693..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/config.py
+++ /dev/null
@@ -1,153 +0,0 @@
-from __future__ import annotations
-
-from copy import deepcopy
-from dataclasses import dataclass, field, fields
-from typing import TYPE_CHECKING, Literal
-
-from litestar._openapi.utils import default_operation_id_creator
-from litestar.openapi.controller import OpenAPIController
-from litestar.openapi.spec import (
- Components,
- Contact,
- ExternalDocumentation,
- Info,
- License,
- OpenAPI,
- PathItem,
- Reference,
- SecurityRequirement,
- Server,
- Tag,
-)
-from litestar.utils.path import normalize_path
-
-__all__ = ("OpenAPIConfig",)
-
-
-if TYPE_CHECKING:
- from litestar.types.callable_types import OperationIDCreator
-
-
-@dataclass
-class OpenAPIConfig:
- """Configuration for OpenAPI.
-
- To enable OpenAPI schema generation and serving, pass an instance of this class to the
- :class:`Litestar <.app.Litestar>` constructor using the ``openapi_config`` kwargs.
- """
-
- title: str
- """Title of API documentation."""
- version: str
- """API version, e.g. '1.0.0'."""
-
- create_examples: bool = field(default=False)
- """Generate examples using the polyfactory library."""
- random_seed: int = 10
- """The random seed used when creating the examples to ensure deterministic generation of examples."""
- openapi_controller: type[OpenAPIController] = field(default_factory=lambda: OpenAPIController)
- """Controller for generating OpenAPI routes.
-
- Must be subclass of :class:`OpenAPIController <litestar.openapi.controller.OpenAPIController>`.
- """
- contact: Contact | None = field(default=None)
- """API contact information, should be an :class:`Contact <litestar.openapi.spec.contact.Contact>` instance."""
- description: str | None = field(default=None)
- """API description."""
- external_docs: ExternalDocumentation | None = field(default=None)
- """Links to external documentation.
-
- Should be an instance of :class:`ExternalDocumentation <litestar.openapi.spec.external_documentation.ExternalDocumentation>`.
- """
- license: License | None = field(default=None)
- """API Licensing information.
-
- Should be an instance of :class:`License <litestar.openapi.spec.license.License>`.
- """
- security: list[SecurityRequirement] | None = field(default=None)
- """API Security requirements information.
-
- Should be an instance of
- :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>`.
- """
- components: Components | list[Components] = field(default_factory=Components)
- """API Components information.
-
- Should be an instance of :class:`Components <litestar.openapi.spec.components.Components>` or a list thereof.
- """
- servers: list[Server] = field(default_factory=lambda: [Server(url="/")])
- """A list of :class:`Server <litestar.openapi.spec.server.Server>` instances."""
- summary: str | None = field(default=None)
- """A summary text."""
- tags: list[Tag] | None = field(default=None)
- """A list of :class:`Tag <litestar.openapi.spec.tag.Tag>` instances."""
- terms_of_service: str | None = field(default=None)
- """URL to page that contains terms of service."""
- use_handler_docstrings: bool = field(default=False)
- """Draw operation description from route handler docstring if not otherwise provided."""
- webhooks: dict[str, PathItem | Reference] | None = field(default=None)
- """A mapping of key to either :class:`PathItem <litestar.openapi.spec.path_item.PathItem>` or.
-
- :class:`Reference <litestar.openapi.spec.reference.Reference>` objects.
- """
- root_schema_site: Literal["redoc", "swagger", "elements", "rapidoc"] = "redoc"
- """The static schema generator to use for the "root" path of `/schema/`."""
- enabled_endpoints: set[str] = field(
- default_factory=lambda: {
- "redoc",
- "swagger",
- "elements",
- "rapidoc",
- "openapi.json",
- "openapi.yaml",
- "openapi.yml",
- "oauth2-redirect.html",
- }
- )
- """A set of the enabled documentation sites and schema download endpoints."""
- operation_id_creator: OperationIDCreator = default_operation_id_creator
- """A callable that generates unique operation ids"""
- path: str | None = field(default=None)
- """Base path for the OpenAPI documentation endpoints."""
-
- def __post_init__(self) -> None:
- if self.path:
- self.path = normalize_path(self.path)
- self.openapi_controller = type("OpenAPIController", (self.openapi_controller,), {"path": self.path})
-
- def to_openapi_schema(self) -> OpenAPI:
- """Return an ``OpenAPI`` instance from the values stored in ``self``.
-
- Returns:
- An instance of :class:`OpenAPI <litestar.openapi.spec.open_api.OpenAPI>`.
- """
-
- if isinstance(self.components, list):
- merged_components = Components()
- for components in self.components:
- for key in (f.name for f in fields(components)):
- if value := getattr(components, key, None):
- merged_value_dict = getattr(merged_components, key, {}) or {}
- merged_value_dict.update(value)
- setattr(merged_components, key, merged_value_dict)
-
- self.components = merged_components
-
- return OpenAPI(
- external_docs=self.external_docs,
- security=self.security,
- components=deepcopy(self.components), # deepcopy prevents mutation of the config's components
- servers=self.servers,
- tags=self.tags,
- webhooks=self.webhooks,
- info=Info(
- title=self.title,
- version=self.version,
- description=self.description,
- contact=self.contact,
- license=self.license,
- summary=self.summary,
- terms_of_service=self.terms_of_service,
- ),
- paths={},
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/controller.py b/venv/lib/python3.11/site-packages/litestar/openapi/controller.py
deleted file mode 100644
index ac03d4c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/controller.py
+++ /dev/null
@@ -1,604 +0,0 @@
-from __future__ import annotations
-
-from functools import cached_property
-from typing import TYPE_CHECKING, Any, Callable, Final, Literal
-
-from yaml import dump as dump_yaml
-
-from litestar.constants import OPENAPI_NOT_INITIALIZED
-from litestar.controller import Controller
-from litestar.enums import MediaType, OpenAPIMediaType
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.handlers import get
-from litestar.response.base import ASGIResponse
-from litestar.serialization import encode_json
-from litestar.serialization.msgspec_hooks import decode_json
-from litestar.status_codes import HTTP_404_NOT_FOUND
-
-__all__ = ("OpenAPIController",)
-
-
-if TYPE_CHECKING:
- from litestar.connection.request import Request
- from litestar.openapi.spec.open_api import OpenAPI
-
-_OPENAPI_JSON_ROUTER_NAME: Final = "__litestar_openapi_json"
-
-
-class OpenAPIController(Controller):
- """Controller for OpenAPI endpoints."""
-
- path: str = "/schema"
- """Base path for the OpenAPI documentation endpoints."""
- style: str = "body { margin: 0; padding: 0 }"
- """Base styling of the html body."""
- redoc_version: str = "next"
- """Redoc version to download from the CDN."""
- swagger_ui_version: str = "5.1.3"
- """SwaggerUI version to download from the CDN."""
- stoplight_elements_version: str = "7.7.18"
- """StopLight Elements version to download from the CDN."""
- rapidoc_version: str = "9.3.4"
- """RapiDoc version to download from the CDN."""
- favicon_url: str = ""
- """URL to download a favicon from."""
- redoc_google_fonts: bool = True
- """Download google fonts via CDN.
-
- Should be set to ``False`` when not using a CDN.
- """
- redoc_js_url: str = f"https://cdn.jsdelivr.net/npm/redoc@{redoc_version}/bundles/redoc.standalone.js"
- """Download url for the Redoc JS bundle."""
- swagger_css_url: str = f"https://cdn.jsdelivr.net/npm/swagger-ui-dist@{swagger_ui_version}/swagger-ui.css"
- """Download url for the Swagger UI CSS bundle."""
- swagger_ui_bundle_js_url: str = (
- f"https://cdn.jsdelivr.net/npm/swagger-ui-dist@{swagger_ui_version}/swagger-ui-bundle.js"
- )
- """Download url for the Swagger UI JS bundle."""
- swagger_ui_standalone_preset_js_url: str = (
- f"https://cdn.jsdelivr.net/npm/swagger-ui-dist@{swagger_ui_version}/swagger-ui-standalone-preset.js"
- )
- """Download url for the Swagger Standalone Preset JS bundle."""
- swagger_ui_init_oauth: dict[Any, Any] | bytes = {}
- """
- JSON to initialize Swagger UI OAuth2 by calling the `initOAuth` method.
-
- Refer to the following URL for details:
- `Swagger-UI <https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/>`_.
- """
- stoplight_elements_css_url: str = (
- f"https://unpkg.com/@stoplight/elements@{stoplight_elements_version}/styles.min.css"
- )
- """Download url for the Stoplight Elements CSS bundle."""
- stoplight_elements_js_url: str = (
- f"https://unpkg.com/@stoplight/elements@{stoplight_elements_version}/web-components.min.js"
- )
- """Download url for the Stoplight Elements JS bundle."""
- rapidoc_js_url: str = f"https://unpkg.com/rapidoc@{rapidoc_version}/dist/rapidoc-min.js"
- """Download url for the RapiDoc JS bundle."""
-
- # internal
- _dumped_json_schema: str = ""
- _dumped_yaml_schema: bytes = b""
- # until swagger-ui supports v3.1.* of OpenAPI officially, we need to modify the schema for it and keep it
- # separate from the redoc version of the schema, which is unmodified.
- dto = None
- return_dto = None
-
- @staticmethod
- def get_schema_from_request(request: Request[Any, Any, Any]) -> OpenAPI:
- """Return the OpenAPI pydantic model from the request instance.
-
- Args:
- request: A :class:`Litestar <.connection.Request>` instance.
-
- Returns:
- An :class:`OpenAPI <litestar.openapi.spec.open_api.OpenAPI>` instance.
- """
- return request.app.openapi_schema
-
- def should_serve_endpoint(self, request: Request[Any, Any, Any]) -> bool:
- """Verify that the requested path is within the enabled endpoints in the openapi_config.
-
- Args:
- request: To be tested if endpoint enabled.
-
- Returns:
- A boolean.
-
- Raises:
- ImproperlyConfiguredException: If the application ``openapi_config`` attribute is ``None``.
- """
- if not request.app.openapi_config: # pragma: no cover
- raise ImproperlyConfiguredException("Litestar has not been instantiated with an OpenAPIConfig")
-
- asgi_root_path = set(filter(None, request.scope.get("root_path", "").split("/")))
- full_request_path = set(filter(None, request.url.path.split("/")))
- request_path = full_request_path.difference(asgi_root_path)
- root_path = set(filter(None, self.path.split("/")))
-
- config = request.app.openapi_config
-
- if request_path == root_path and config.root_schema_site in config.enabled_endpoints:
- return True
-
- return bool(request_path & config.enabled_endpoints)
-
- @property
- def favicon(self) -> str:
- """Return favicon ``<link>`` tag, if applicable.
-
- Returns:
- A ``<link>`` tag if ``self.favicon_url`` is not empty, otherwise returns a placeholder meta tag.
- """
- return f"<link rel='icon' type='image/x-icon' href='{self.favicon_url}'>" if self.favicon_url else "<meta/>"
-
- @cached_property
- def render_methods_map(
- self,
- ) -> dict[Literal["redoc", "swagger", "elements", "rapidoc"], Callable[[Request], bytes]]:
- """Map render method names to render methods.
-
- Returns:
- A mapping of string keys to render methods.
- """
- return {
- "redoc": self.render_redoc,
- "swagger": self.render_swagger_ui,
- "elements": self.render_stoplight_elements,
- "rapidoc": self.render_rapidoc,
- }
-
- @get(
- path=["/openapi.yaml", "openapi.yml"],
- media_type=OpenAPIMediaType.OPENAPI_YAML,
- include_in_schema=False,
- sync_to_thread=False,
- )
- def retrieve_schema_yaml(self, request: Request[Any, Any, Any]) -> ASGIResponse:
- """Return the OpenAPI schema as YAML with an ``application/vnd.oai.openapi`` Content-Type header.
-
- Args:
- request:
- A :class:`Request <.connection.Request>` instance.
-
- Returns:
- A Response instance with the YAML object rendered into a string.
- """
- if self.should_serve_endpoint(request):
- if not self._dumped_json_schema:
- schema_json = decode_json(self._get_schema_as_json(request))
- schema_yaml = dump_yaml(schema_json, default_flow_style=False)
- self._dumped_yaml_schema = schema_yaml.encode("utf-8")
- return ASGIResponse(body=self._dumped_yaml_schema, media_type=OpenAPIMediaType.OPENAPI_YAML)
- return ASGIResponse(body=b"", status_code=HTTP_404_NOT_FOUND, media_type=MediaType.HTML)
-
- @get(
- path="/openapi.json",
- media_type=OpenAPIMediaType.OPENAPI_JSON,
- include_in_schema=False,
- sync_to_thread=False,
- name=_OPENAPI_JSON_ROUTER_NAME,
- )
- def retrieve_schema_json(self, request: Request[Any, Any, Any]) -> ASGIResponse:
- """Return the OpenAPI schema as JSON with an ``application/vnd.oai.openapi+json`` Content-Type header.
-
- Args:
- request:
- A :class:`Request <.connection.Request>` instance.
-
- Returns:
- A Response instance with the JSON object rendered into a string.
- """
- if self.should_serve_endpoint(request):
- return ASGIResponse(
- body=self._get_schema_as_json(request),
- media_type=OpenAPIMediaType.OPENAPI_JSON,
- )
- return ASGIResponse(body=b"", status_code=HTTP_404_NOT_FOUND, media_type=MediaType.HTML)
-
- @get(path="/", include_in_schema=False, sync_to_thread=False)
- def root(self, request: Request[Any, Any, Any]) -> ASGIResponse:
- """Render a static documentation site.
-
- The site to be rendered is based on the ``root_schema_site`` value set in the application's
- :class:`OpenAPIConfig <.openapi.OpenAPIConfig>`. Defaults to ``redoc``.
-
- Args:
- request:
- A :class:`Request <.connection.Request>` instance.
-
- Returns:
- A response with the rendered site defined in root_schema_site.
-
- Raises:
- ImproperlyConfiguredException: If the application ``openapi_config`` attribute is ``None``.
- """
- config = request.app.openapi_config
- if not config: # pragma: no cover
- raise ImproperlyConfiguredException(OPENAPI_NOT_INITIALIZED)
-
- render_method = self.render_methods_map[config.root_schema_site]
-
- if self.should_serve_endpoint(request):
- return ASGIResponse(body=render_method(request), media_type=MediaType.HTML)
- return ASGIResponse(body=self.render_404_page(), status_code=HTTP_404_NOT_FOUND, media_type=MediaType.HTML)
-
- @get(path="/swagger", include_in_schema=False, sync_to_thread=False)
- def swagger_ui(self, request: Request[Any, Any, Any]) -> ASGIResponse:
- """Route handler responsible for rendering Swagger-UI.
-
- Args:
- request:
- A :class:`Request <.connection.Request>` instance.
-
- Returns:
- A response with a rendered swagger documentation site
- """
- if self.should_serve_endpoint(request):
- return ASGIResponse(body=self.render_swagger_ui(request), media_type=MediaType.HTML)
- return ASGIResponse(body=self.render_404_page(), status_code=HTTP_404_NOT_FOUND, media_type=MediaType.HTML)
-
- @get(path="/elements", media_type=MediaType.HTML, include_in_schema=False, sync_to_thread=False)
- def stoplight_elements(self, request: Request[Any, Any, Any]) -> ASGIResponse:
- """Route handler responsible for rendering StopLight Elements.
-
- Args:
- request:
- A :class:`Request <.connection.Request>` instance.
-
- Returns:
- A response with a rendered stoplight elements documentation site
- """
- if self.should_serve_endpoint(request):
- return ASGIResponse(body=self.render_stoplight_elements(request), media_type=MediaType.HTML)
- return ASGIResponse(body=self.render_404_page(), status_code=HTTP_404_NOT_FOUND, media_type=MediaType.HTML)
-
- @get(path="/redoc", media_type=MediaType.HTML, include_in_schema=False, sync_to_thread=False)
- def redoc(self, request: Request[Any, Any, Any]) -> ASGIResponse: # pragma: no cover
- """Route handler responsible for rendering Redoc.
-
- Args:
- request:
- A :class:`Request <.connection.Request>` instance.
-
- Returns:
- A response with a rendered redoc documentation site
- """
- if self.should_serve_endpoint(request):
- return ASGIResponse(body=self.render_redoc(request), media_type=MediaType.HTML)
- return ASGIResponse(body=self.render_404_page(), status_code=HTTP_404_NOT_FOUND, media_type=MediaType.HTML)
-
- @get(path="/rapidoc", media_type=MediaType.HTML, include_in_schema=False, sync_to_thread=False)
- def rapidoc(self, request: Request[Any, Any, Any]) -> ASGIResponse:
- if self.should_serve_endpoint(request):
- return ASGIResponse(body=self.render_rapidoc(request), media_type=MediaType.HTML)
- return ASGIResponse(body=self.render_404_page(), status_code=HTTP_404_NOT_FOUND, media_type=MediaType.HTML)
-
- @get(path="/oauth2-redirect.html", media_type=MediaType.HTML, include_in_schema=False, sync_to_thread=False)
- def swagger_ui_oauth2_redirect(self, request: Request[Any, Any, Any]) -> ASGIResponse: # pragma: no cover
- """Route handler responsible for rendering oauth2-redirect.html page for Swagger-UI.
-
- Args:
- request:
- A :class:`Request <.connection.Request>` instance.
-
- Returns:
- A response with a rendered oauth2-redirect.html page for Swagger-UI.
- """
- if self.should_serve_endpoint(request):
- return ASGIResponse(body=self.render_swagger_ui_oauth2_redirect(request), media_type=MediaType.HTML)
- return ASGIResponse(body=self.render_404_page(), status_code=HTTP_404_NOT_FOUND, media_type=MediaType.HTML)
-
- def render_swagger_ui_oauth2_redirect(self, request: Request[Any, Any, Any]) -> bytes:
- """Render an HTML oauth2-redirect.html page for Swagger-UI.
-
- Notes:
- - override this method to customize the template.
-
- Args:
- request:
- A :class:`Request <.connection.Request>` instance.
-
- Returns:
- A rendered html string.
- """
- return rb"""<!doctype html>
- <html lang="en-US">
- <head>
- <title>Swagger UI: OAuth2 Redirect</title>
- </head>
- <body>
- <script>
- 'use strict';
- function run () {
- var oauth2 = window.opener.swaggerUIRedirectOauth2;
- var sentState = oauth2.state;
- var redirectUrl = oauth2.redirectUrl;
- var isValid, qp, arr;
-
- if (/code|token|error/.test(window.location.hash)) {
- qp = window.location.hash.substring(1).replace('?', '&');
- } else {
- qp = location.search.substring(1);
- }
-
- arr = qp.split("&");
- arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
- qp = qp ? JSON.parse('{' + arr.join() + '}',
- function (key, value) {
- return key === "" ? value : decodeURIComponent(value);
- }
- ) : {};
-
- isValid = qp.state === sentState;
-
- if ((
- oauth2.auth.schema.get("flow") === "accessCode" ||
- oauth2.auth.schema.get("flow") === "authorizationCode" ||
- oauth2.auth.schema.get("flow") === "authorization_code"
- ) && !oauth2.auth.code) {
- if (!isValid) {
- oauth2.errCb({
- authId: oauth2.auth.name,
- source: "auth",
- level: "warning",
- message: "Authorization may be unsafe, passed state was changed in server. The passed state wasn't returned from auth server."
- });
- }
-
- if (qp.code) {
- delete oauth2.state;
- oauth2.auth.code = qp.code;
- oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
- } else {
- let oauthErrorMsg;
- if (qp.error) {
- oauthErrorMsg = "["+qp.error+"]: " +
- (qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
- (qp.error_uri ? "More info: "+qp.error_uri : "");
- }
-
- oauth2.errCb({
- authId: oauth2.auth.name,
- source: "auth",
- level: "error",
- message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server."
- });
- }
- } else {
- oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
- }
- window.close();
- }
-
- if (document.readyState !== 'loading') {
- run();
- } else {
- document.addEventListener('DOMContentLoaded', function () {
- run();
- });
- }
- </script>
- </body>
- </html>"""
-
- def render_swagger_ui(self, request: Request[Any, Any, Any]) -> bytes:
- """Render an HTML page for Swagger-UI.
-
- Notes:
- - override this method to customize the template.
-
- Args:
- request:
- A :class:`Request <.connection.Request>` instance.
-
- Returns:
- A rendered html string.
- """
- schema = self.get_schema_from_request(request)
-
- head = f"""
- <head>
- <title>{schema.info.title}</title>
- {self.favicon}
- <meta charset="utf-8"/>
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <link href="{self.swagger_css_url}" rel="stylesheet">
- <script src="{self.swagger_ui_bundle_js_url}" crossorigin></script>
- <script src="{self.swagger_ui_standalone_preset_js_url}" crossorigin></script>
- <style>{self.style}</style>
- </head>
- """
-
- body = f"""
- <body>
- <div id='swagger-container'/>
- <script type="text/javascript">
- const ui = SwaggerUIBundle({{
- spec: {self._get_schema_as_json(request)},
- dom_id: '#swagger-container',
- deepLinking: true,
- showExtensions: true,
- showCommonExtensions: true,
- presets: [
- SwaggerUIBundle.presets.apis,
- SwaggerUIBundle.SwaggerUIStandalonePreset
- ],
- }})
- ui.initOAuth({encode_json(self.swagger_ui_init_oauth).decode('utf-8')})
- </script>
- </body>
- """
-
- return f"""
- <!DOCTYPE html>
- <html>
- {head}
- {body}
- </html>
- """.encode()
-
- def render_stoplight_elements(self, request: Request[Any, Any, Any]) -> bytes:
- """Render an HTML page for StopLight Elements.
-
- Notes:
- - override this method to customize the template.
-
- Args:
- request:
- A :class:`Request <.connection.Request>` instance.
-
- Returns:
- A rendered html string.
- """
- schema = self.get_schema_from_request(request)
- head = f"""
- <head>
- <title>{schema.info.title}</title>
- {self.favicon}
- <meta charset="utf-8"/>
- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
- <link rel="stylesheet" href="{self.stoplight_elements_css_url}">
- <script src="{self.stoplight_elements_js_url}" crossorigin></script>
- <style>{self.style}</style>
- </head>
- """
-
- body = f"""
- <body>
- <elements-api
- apiDescriptionUrl="{request.app.route_reverse(_OPENAPI_JSON_ROUTER_NAME)}"
- router="hash"
- layout="sidebar"
- />
- </body>
- """
-
- return f"""
- <!DOCTYPE html>
- <html>
- {head}
- {body}
- </html>
- """.encode()
-
- def render_rapidoc(self, request: Request[Any, Any, Any]) -> bytes: # pragma: no cover
- schema = self.get_schema_from_request(request)
-
- head = f"""
- <head>
- <title>{schema.info.title}</title>
- {self.favicon}
- <meta charset="utf-8"/>
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <script src="{self.rapidoc_js_url}" crossorigin></script>
- <style>{self.style}</style>
- </head>
- """
-
- body = f"""
- <body>
- <rapi-doc spec-url="{request.app.route_reverse(_OPENAPI_JSON_ROUTER_NAME)}" />
- </body>
- """
-
- return f"""
- <!DOCTYPE html>
- <html>
- {head}
- {body}
- </html>
- """.encode()
-
- def render_redoc(self, request: Request[Any, Any, Any]) -> bytes: # pragma: no cover
- """Render an HTML page for Redoc.
-
- Notes:
- - override this method to customize the template.
-
- Args:
- request:
- A :class:`Request <.connection.Request>` instance.
-
- Returns:
- A rendered html string.
- """
- schema = self.get_schema_from_request(request)
-
- head = f"""
- <head>
- <title>{schema.info.title}</title>
- {self.favicon}
- <meta charset="utf-8"/>
- <meta name="viewport" content="width=device-width, initial-scale=1">
- """
-
- if self.redoc_google_fonts:
- head += """
- <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
- """
-
- head += f"""
- <script src="{self.redoc_js_url}" crossorigin></script>
- <style>
- {self.style}
- </style>
- </head>
- """
-
- body = f"""
- <body>
- <div id='redoc-container'/>
- <script type="text/javascript">
- Redoc.init(
- {self._get_schema_as_json(request)},
- undefined,
- document.getElementById('redoc-container')
- )
- </script>
- </body>
- """
-
- return f"""
- <!DOCTYPE html>
- <html>
- {head}
- {body}
- </html>
- """.encode()
-
- def render_404_page(self) -> bytes:
- """Render an HTML 404 page.
-
- Returns:
- A rendered html string.
- """
-
- return f"""
- <!DOCTYPE html>
- <html>
- <head>
- <title>404 Not found</title>
- {self.favicon}
- <meta charset="utf-8"/>
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <style>
- {self.style}
- </style>
- </head>
- <body>
- <h1>Error 404</h1>
- </body>
- </html>
- """.encode()
-
- def _get_schema_as_json(self, request: Request) -> str:
- """Get the schema encoded as a JSON string."""
-
- if not self._dumped_json_schema:
- schema = self.get_schema_from_request(request).to_schema()
- json_encoded_schema = encode_json(schema, request.route_handler.default_serializer)
- self._dumped_json_schema = json_encoded_schema.decode("utf-8")
-
- return self._dumped_json_schema
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/datastructures.py b/venv/lib/python3.11/site-packages/litestar/openapi/datastructures.py
deleted file mode 100644
index 5796a48..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/datastructures.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass, field
-from typing import TYPE_CHECKING
-
-from litestar.enums import MediaType
-
-if TYPE_CHECKING:
- from litestar.openapi.spec import Example
- from litestar.types import DataContainerType
-
-
-__all__ = ("ResponseSpec",)
-
-
-@dataclass
-class ResponseSpec:
- """Container type of additional responses."""
-
- data_container: DataContainerType | None
- """A model that describes the content of the response."""
- generate_examples: bool = field(default=True)
- """Generate examples for the response content."""
- description: str = field(default="Additional response")
- """A description of the response."""
- media_type: MediaType = field(default=MediaType.JSON)
- """Response media type."""
- examples: list[Example] | None = field(default=None)
- """A list of Example models."""
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__init__.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__init__.py
deleted file mode 100644
index 438c351..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__init__.py
+++ /dev/null
@@ -1,68 +0,0 @@
-from .base import BaseSchemaObject
-from .callback import Callback
-from .components import Components
-from .contact import Contact
-from .discriminator import Discriminator
-from .encoding import Encoding
-from .enums import OpenAPIFormat, OpenAPIType
-from .example import Example
-from .external_documentation import ExternalDocumentation
-from .header import OpenAPIHeader
-from .info import Info
-from .license import License
-from .link import Link
-from .media_type import OpenAPIMediaType
-from .oauth_flow import OAuthFlow
-from .oauth_flows import OAuthFlows
-from .open_api import OpenAPI
-from .operation import Operation
-from .parameter import Parameter
-from .path_item import PathItem
-from .paths import Paths
-from .reference import Reference
-from .request_body import RequestBody
-from .response import OpenAPIResponse
-from .responses import Responses
-from .schema import Schema
-from .security_requirement import SecurityRequirement
-from .security_scheme import SecurityScheme
-from .server import Server
-from .server_variable import ServerVariable
-from .tag import Tag
-from .xml import XML
-
-__all__ = (
- "BaseSchemaObject",
- "Callback",
- "Components",
- "Contact",
- "Discriminator",
- "Encoding",
- "Example",
- "ExternalDocumentation",
- "Info",
- "License",
- "Link",
- "OAuthFlow",
- "OAuthFlows",
- "OpenAPI",
- "OpenAPIFormat",
- "OpenAPIHeader",
- "OpenAPIMediaType",
- "OpenAPIResponse",
- "OpenAPIType",
- "Operation",
- "Parameter",
- "PathItem",
- "Paths",
- "Reference",
- "RequestBody",
- "Responses",
- "Schema",
- "SecurityRequirement",
- "SecurityScheme",
- "Server",
- "ServerVariable",
- "Tag",
- "XML",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 682acac..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/base.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/base.cpython-311.pyc
deleted file mode 100644
index 7f9658f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/base.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/callback.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/callback.cpython-311.pyc
deleted file mode 100644
index 8fb170e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/callback.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/components.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/components.cpython-311.pyc
deleted file mode 100644
index 98c83be..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/components.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/contact.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/contact.cpython-311.pyc
deleted file mode 100644
index 53b94c2..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/contact.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/discriminator.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/discriminator.cpython-311.pyc
deleted file mode 100644
index 5a4b1bc..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/discriminator.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/encoding.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/encoding.cpython-311.pyc
deleted file mode 100644
index 58ab620..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/encoding.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/enums.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/enums.cpython-311.pyc
deleted file mode 100644
index 9e328e3..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/enums.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/example.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/example.cpython-311.pyc
deleted file mode 100644
index 4f031b1..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/example.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/external_documentation.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/external_documentation.cpython-311.pyc
deleted file mode 100644
index a0f445b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/external_documentation.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/header.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/header.cpython-311.pyc
deleted file mode 100644
index 1596fd8..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/header.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/info.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/info.cpython-311.pyc
deleted file mode 100644
index 45c4fdd..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/info.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/license.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/license.cpython-311.pyc
deleted file mode 100644
index 98c60d4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/license.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/link.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/link.cpython-311.pyc
deleted file mode 100644
index b30775a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/link.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/media_type.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/media_type.cpython-311.pyc
deleted file mode 100644
index 47c85af..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/media_type.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/oauth_flow.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/oauth_flow.cpython-311.pyc
deleted file mode 100644
index a6a8564..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/oauth_flow.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/oauth_flows.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/oauth_flows.cpython-311.pyc
deleted file mode 100644
index 04555f8..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/oauth_flows.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/open_api.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/open_api.cpython-311.pyc
deleted file mode 100644
index 1926726..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/open_api.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/operation.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/operation.cpython-311.pyc
deleted file mode 100644
index 1c3ddc2..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/operation.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/parameter.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/parameter.cpython-311.pyc
deleted file mode 100644
index e860dc9..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/parameter.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/path_item.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/path_item.cpython-311.pyc
deleted file mode 100644
index cf33d1c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/path_item.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/paths.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/paths.cpython-311.pyc
deleted file mode 100644
index 4dc2e6e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/paths.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/reference.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/reference.cpython-311.pyc
deleted file mode 100644
index 66b4e2c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/reference.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/request_body.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/request_body.cpython-311.pyc
deleted file mode 100644
index 5788ebc..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/request_body.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/response.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/response.cpython-311.pyc
deleted file mode 100644
index 364f342..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/response.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/responses.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/responses.cpython-311.pyc
deleted file mode 100644
index db08130..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/responses.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/schema.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/schema.cpython-311.pyc
deleted file mode 100644
index 6af9ca3..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/schema.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/security_requirement.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/security_requirement.cpython-311.pyc
deleted file mode 100644
index 5aa7c2f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/security_requirement.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/security_scheme.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/security_scheme.cpython-311.pyc
deleted file mode 100644
index a2b1045..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/security_scheme.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/server.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/server.cpython-311.pyc
deleted file mode 100644
index 26b70b3..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/server.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/server_variable.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/server_variable.cpython-311.pyc
deleted file mode 100644
index 46ab0cd..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/server_variable.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/tag.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/tag.cpython-311.pyc
deleted file mode 100644
index 7597e16..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/tag.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/xml.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/xml.cpython-311.pyc
deleted file mode 100644
index 97cacd9..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/__pycache__/xml.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/base.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/base.py
deleted file mode 100644
index 69cd3f3..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/base.py
+++ /dev/null
@@ -1,56 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import asdict, dataclass, fields, is_dataclass
-from enum import Enum
-from typing import Any
-
-__all__ = ("BaseSchemaObject",)
-
-
-def _normalize_key(key: str) -> str:
- if key.endswith("_in"):
- return "in"
- if key.startswith("schema_"):
- return key.split("_")[1]
- if "_" in key:
- components = key.split("_")
- return components[0] + "".join(component.title() for component in components[1:])
- return "$ref" if key == "ref" else key
-
-
-def _normalize_value(value: Any) -> Any:
- if isinstance(value, BaseSchemaObject):
- return value.to_schema()
- if is_dataclass(value):
- return {_normalize_value(k): _normalize_value(v) for k, v in asdict(value).items() if v is not None}
- if isinstance(value, dict):
- return {_normalize_value(k): _normalize_value(v) for k, v in value.items() if v is not None}
- if isinstance(value, list):
- return [_normalize_value(v) for v in value]
- return value.value if isinstance(value, Enum) else value
-
-
-@dataclass
-class BaseSchemaObject:
- """Base class for schema spec objects"""
-
- def to_schema(self) -> dict[str, Any]:
- """Transform the spec dataclass object into a string keyed dictionary. This method traverses all nested values
- recursively.
- """
- result: dict[str, Any] = {}
-
- for field in fields(self):
- value = _normalize_value(getattr(self, field.name, None))
-
- if value is not None:
- if "alias" in field.metadata:
- if not isinstance(field.metadata["alias"], str):
- raise TypeError('metadata["alias"] must be a str')
- key = field.metadata["alias"]
- else:
- key = _normalize_key(field.name)
-
- result[key] = value
-
- return result
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/callback.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/callback.py
deleted file mode 100644
index c4bb129..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/callback.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Dict, Union
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.path_item import PathItem
- from litestar.openapi.spec.reference import Reference
-
-
-Callback = Dict[str, Union["PathItem", "Reference"]]
-"""A map of possible out-of band callbacks related to the parent operation. Each value in the map is a
-`Path Item Object <https://spec.openapis.org/oas/v3.1.0#pathItemObject>`_ that describes a set of requests that may be
-initiated by the API provider and the expected responses. The key value used to identify the path item object is an
-expression, evaluated at runtime, that identifies a URL to use for the callback operation.
-
-Patterned Fields
-
-{expression}: 'PathItem' = ...
-
-A Path Item Object used to define a callback request and expected responses.
-
-A `complete example <https://github.com/OAI/OpenAPI-Specification/blob/main/examples/v3.1/webhook-example.yaml>`_ is
-available.
-"""
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/components.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/components.py
deleted file mode 100644
index b11da78..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/components.py
+++ /dev/null
@@ -1,72 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass, field
-from typing import TYPE_CHECKING
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-__all__ = ("Components",)
-
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.callback import Callback
- from litestar.openapi.spec.example import Example
- from litestar.openapi.spec.header import OpenAPIHeader
- from litestar.openapi.spec.link import Link
- from litestar.openapi.spec.parameter import Parameter
- from litestar.openapi.spec.path_item import PathItem
- from litestar.openapi.spec.reference import Reference
- from litestar.openapi.spec.request_body import RequestBody
- from litestar.openapi.spec.response import OpenAPIResponse
- from litestar.openapi.spec.schema import Schema
- from litestar.openapi.spec.security_scheme import SecurityScheme
-
-
-@dataclass
-class Components(BaseSchemaObject):
- """Holds a set of reusable objects for different aspects of the OAS.
-
- All objects defined within the components object will have no effect
- on the API unless they are explicitly referenced from properties
- outside the components object.
- """
-
- schemas: dict[str, Schema] = field(default_factory=dict)
- """An object to hold reusable
- `Schema Objects <https://spec.openapis.org/oas/v3.1.0#schemaObject>`_"""
-
- responses: dict[str, OpenAPIResponse | Reference] | None = None
- """An object to hold reusable
- `Response Objects <https://spec.openapis.org/oas/v3.1.0#responseObject>`_"""
-
- parameters: dict[str, Parameter | Reference] | None = None
- """An object to hold reusable
- `Parameter Objects <https://spec.openapis.org/oas/v3.1.0#parameterObject>`_"""
-
- examples: dict[str, Example | Reference] | None = None
- """An object to hold reusable
- `Example Objects <https://spec.openapis.org/oas/v3.1.0#exampleObject>`_"""
-
- request_bodies: dict[str, RequestBody | Reference] | None = None
- """An object to hold reusable
- `Request Body Objects <https://spec.openapis.org/oas/v3.1.0#requestBodyObject>`_"""
-
- headers: dict[str, OpenAPIHeader | Reference] | None = None
- """An object to hold reusable
- `Header Objects <https://spec.openapis.org/oas/v3.1.0#headerObject>`_"""
-
- security_schemes: dict[str, SecurityScheme | Reference] | None = None
- """An object to hold reusable
- `Security Scheme Objects <https://spec.openapis.org/oas/v3.1.0#securitySchemeObject>`_"""
-
- links: dict[str, Link | Reference] | None = None
- """An object to hold reusable
- `Link Objects <https://spec.openapis.org/oas/v3.1.0#linkObject>`_"""
-
- callbacks: dict[str, Callback | Reference] | None = None
- """An object to hold reusable
- `Callback Objects <https://spec.openapis.org/oas/v3.1.0#callbackObject>`_"""
-
- path_items: dict[str, PathItem | Reference] | None = None
- """An object to hold reusable
- `Path Item Object <https://spec.openapis.org/oas/v3.1.0#pathItemObject>`_"""
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/contact.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/contact.py
deleted file mode 100644
index b816288..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/contact.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-__all__ = ("Contact",)
-
-
-@dataclass
-class Contact(BaseSchemaObject):
- """Contact information for the exposed API."""
-
- name: str | None = None
- """The identifying name of the contact person/organization."""
-
- url: str | None = None
- """The URL pointing to the contact information. MUST be in the form of a URL."""
-
- email: str | None = None
- """The email address of the contact person/organization. MUST be in the form of an email address."""
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/discriminator.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/discriminator.py
deleted file mode 100644
index 3c292ce..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/discriminator.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-__all__ = ("Discriminator",)
-
-
-@dataclass(unsafe_hash=True)
-class Discriminator(BaseSchemaObject):
- """When request bodies or response payloads may be one of a number of different schemas, a ``discriminator``
- object can be used to aid in serialization, deserialization, and validation.
-
- The discriminator is a specific object in a schema which is used to inform the consumer of the specification of an
- alternative schema based on the value associated with it.
-
- When using the discriminator, _inline_ schemas will not be considered.
- """
-
- property_name: str
- """**REQUIRED**. The name of the property in the payload that will hold the discriminator value."""
-
- mapping: dict[str, str] | None = None
- """An object to hold mappings between payload values and schema names or references."""
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/encoding.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/encoding.py
deleted file mode 100644
index 2a469c8..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/encoding.py
+++ /dev/null
@@ -1,67 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.header import OpenAPIHeader
- from litestar.openapi.spec.reference import Reference
-
-__all__ = ("Encoding",)
-
-
-@dataclass
-class Encoding(BaseSchemaObject):
- """A single encoding definition applied to a single schema property."""
-
- content_type: str | None = None
- """The Content-Type for encoding a specific property. Default value depends n the property type:
-
- - for ``object``: ``application/json``
- - for ``array``: the default is defined based on the inner type
- - for all other cases the default is ``application/octet-stream``.
-
- The value can be a specific media type (e.g. ``application/json``), a wildcard media type (e.g. ``image/*``), or a
- comma-separated list of the two types.
- """
-
- headers: dict[str, OpenAPIHeader | Reference] | None = None
- """A map allowing additional information to be provided as headers, for example ``Content-Disposition``.
-
- ``Content-Type`` is described separately and SHALL be ignored in this section. This property SHALL be ignored if the
- request body media type is not a ``multipart``.
- """
-
- style: str | None = None
- """Describes how a specific property value will be serialized depending on its type.
-
- See `Parameter Object <https://spec.openapis.org/oas/v3.1.0#parameterObject>`_ for details on the
- `style <https://spec.openapis.org/oas/v3.1.0#parameterStyle>`__ property. The behavior follows the same values as
- ``query`` parameters, including default values. This property SHALL be ignored if the request body media type is not
- ``application/x-www-form-urlencoded`` or ``multipart/form-data``. If a value is explicitly defined, then the value
- of `contentType <https://spec.openapis.org/oas/v3.1.0#encodingContentType>`_ (implicit or explicit) SHALL be
- ignored.
- """
-
- explode: bool = False
- """When this is true, property values of type ``array`` or ``object`` generate separate parameters for each value of
- the array, or key-value-pair of the map.
-
- For other types of properties this property has no effect. When
- `style <https://spec.openapis.org/oas/v3.1.0#encodingStyle>`_ is ``form``, the default value is ``True``. For all
- other styles, the default value is ``False``. This property SHALL be ignored if the request body media type is not
- ``application/x-www-form-urlencoded`` or ``multipart/form-data``. If a value is explicitly defined, then the value
- of `contentType <https://spec.openapis.org/oas/v3.1.0#encodingContentType>`_ (implicit or explicit) SHALL be
- ignored.
- """
-
- allow_reserved: bool = False
- """Determines whether the parameter value SHOULD allow reserved characters, as defined by :rfc:`3986`
- (``:/?#[]@!$&'()*+,;=``) to be included without percent-encoding.
-
- This property SHALL be ignored if the request body media type s not ``application/x-www-form-urlencoded`` or
- ``multipart/form-data``. If a value is explicitly defined, then the value of
- `contentType <https://spec.openapis.org/oas/v3.1.0#encodingContentType>`_ (implicit or explicit) SHALL be ignored.
- """
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/enums.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/enums.py
deleted file mode 100644
index da9adea..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/enums.py
+++ /dev/null
@@ -1,41 +0,0 @@
-from enum import Enum
-
-__all__ = ("OpenAPIFormat", "OpenAPIType")
-
-
-class OpenAPIFormat(str, Enum):
- """Formats extracted from: https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-validation-00#page-13"""
-
- DATE = "date"
- DATE_TIME = "date-time"
- TIME = "time"
- DURATION = "duration"
- URL = "url"
- EMAIL = "email"
- IDN_EMAIL = "idn-email"
- HOST_NAME = "hostname"
- IDN_HOST_NAME = "idn-hostname"
- IPV4 = "ipv4"
- IPV6 = "ipv6"
- URI = "uri"
- URI_REFERENCE = "uri-reference"
- URI_TEMPLATE = "uri-template"
- JSON_POINTER = "json-pointer"
- RELATIVE_JSON_POINTER = "relative-json-pointer"
- IRI = "iri-reference"
- IRI_REFERENCE = "iri-reference" # noqa: PIE796
- UUID = "uuid"
- REGEX = "regex"
- BINARY = "binary"
-
-
-class OpenAPIType(str, Enum):
- """An OopenAPI type."""
-
- ARRAY = "array"
- BOOLEAN = "boolean"
- INTEGER = "integer"
- NULL = "null"
- NUMBER = "number"
- OBJECT = "object"
- STRING = "string"
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/example.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/example.py
deleted file mode 100644
index 414452e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/example.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import Any
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-
-@dataclass
-class Example(BaseSchemaObject):
- summary: str | None = None
- """Short description for the example."""
-
- description: str | None = None
- """Long description for the example.
-
- `CommonMark syntax <https://spec.commonmark.org/>`_ MAY be used for rich text representation.
- """
-
- value: Any | None = None
- """Embedded literal example.
-
- The ``value`` field and ``externalValue`` field are mutually exclusive. To represent examples of media types that
- cannot naturally represented in JSON or YAML, use a string value to contain the example, escaping where necessary.
- """
-
- external_value: str | None = None
- """A URL that points to the literal example. This provides the capability to reference examples that cannot easily
- be included in JSON or YAML documents.
-
- The ``value`` field and ``externalValue`` field are mutually exclusive. See the rules for resolving
- `Relative References <https://spec.openapis.org/oas/v3.1.0#relativeReferencesURI>`_.
- """
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/external_documentation.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/external_documentation.py
deleted file mode 100644
index f11b90d..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/external_documentation.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-__all__ = ("ExternalDocumentation",)
-
-
-@dataclass
-class ExternalDocumentation(BaseSchemaObject):
- """Allows referencing an external resource for extended documentation."""
-
- url: str
- """**REQUIRED**. The URL for the target documentation. Value MUST be in the form of a URL."""
-
- description: str | None = None
- """A short description of the target documentation.
-
- `CommonMark syntax <https://spec.commonmark.org/>`_ MAY be used for rich text representation.
- """
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/header.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/header.py
deleted file mode 100644
index 006ff22..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/header.py
+++ /dev/null
@@ -1,121 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING, Any, Literal
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.example import Example
- from litestar.openapi.spec.media_type import OpenAPIMediaType
- from litestar.openapi.spec.reference import Reference
- from litestar.openapi.spec.schema import Schema
-
-__all__ = ("OpenAPIHeader",)
-
-
-@dataclass
-class OpenAPIHeader(BaseSchemaObject):
- """The Header Object follows the structure of the [Parameter
- Object](https://spec.openapis.org/oas/v3.1.0#parameterObject) with the
- following changes:
-
- 1. ``name`` MUST NOT be specified, it is given in the corresponding ``headers`` map.
- 2. ``in`` MUST NOT be specified, it is implicitly in ``header``.
- 3. All traits that are affected by the location MUST be applicable to a location of ``header``
- (for example, `style <https://spec.openapis.org/oas/v3.1.0#parameterStyle>`__).
- """
-
- schema: Schema | Reference | None = None
- """The schema defining the type used for the parameter."""
-
- name: Literal[""] = ""
- """MUST NOT be specified, it is given in the corresponding ``headers`` map."""
-
- param_in: Literal["header"] = "header"
- """MUST NOT be specified, it is implicitly in ``header``."""
-
- description: str | None = None
- """A brief description of the parameter. This could contain examples of
- use.
-
- `CommonMark syntax <https://spec.commonmark.org/>`_ MAY be used for rich text representation.
- """
-
- required: bool = False
- """Determines whether this parameter is mandatory.
-
- If the `parameter location <https://spec.openapis.org/oas/v3.1.0#parameterIn>`_ is ``"path"``, this property is
- **REQUIRED** and its value MUST be ``True``. Otherwise, the property MAY be included and its default value is
- ``False``.
- """
-
- deprecated: bool = False
- """Specifies that a parameter is deprecated and SHOULD be transitioned out of usage. Default value is ``False``."""
-
- allow_empty_value: bool = False
- """Sets the ability to pass empty-valued parameters. This is valid only for ``query`` parameters and allows sending
- a parameter with an empty value. Default value is ``False``. If
- `style <https://spec.openapis.org/oas/v3.1.0#parameterStyle>`__ is used, and if behavior is ``n/a`` (cannot be
- serialized), the value of ``allowEmptyValue`` SHALL be ignored. Use of this property is NOT RECOMMENDED, as it is
- likely to be removed in a later revision.
-
- The rules for serialization of the parameter are specified in one of two ways.For simpler scenarios, a
- `schema <https://spec.openapis.org/oas/v3.1.0#parameterSchema>`_ and
- `style <https://spec.openapis.org/oas/v3.1.0#parameterStyle>`__ can describe the structure and syntax of the
- parameter.
- """
-
- style: str | None = None
- """Describes how the parameter value will be serialized depending on the
- type of the parameter value. Default values (based on value of ``in``):
-
- - for ``query`` - ``form``;
- - for ``path`` - ``simple``;
- - for ``header`` - ``simple``;
- - for ``cookie`` - ``form``.
- """
-
- explode: bool | None = None
- """When this is true, parameter values of type ``array`` or ``object`` generate separate parameters for each value
- of the array or key-value pair of the map.
-
- For other types of parameters this property has no effect.When
- `style <https://spec.openapis.org/oas/v3.1.0#parameterStyle>`__ is ``form``, the default value is ``True``. For all
- other styles, the default value is ``False``.
- """
-
- allow_reserved: bool = False
- """Determines whether the parameter value SHOULD allow reserved characters, as defined by. :rfc:`3986`
- (``:/?#[]@!$&'()*+,;=``) to be included without percent-encoding.
-
- This property only applies to parameters with an ``in`` value of ``query``. The default value is ``False``.
- """
-
- example: Any | None = None
- """Example of the parameter's potential value.
-
- The example SHOULD match the specified schema and encoding properties if present. The ``example`` field is mutually
- exclusive of the ``examples`` field. Furthermore, if referencing a ``schema`` that contains an example, the
- ``example`` value SHALL _override_ the example provided by the schema. To represent examples of media types that
- cannot naturally be represented in JSON or YAML, a string value can contain the example with escaping where
- necessary.
- """
-
- examples: dict[str, Example | Reference] | None = None
- """Examples of the parameter's potential value. Each example SHOULD contain a value in the correct format as
- specified in the parameter encoding. The ``examples`` field is mutually exclusive of the ``example`` field.
- Furthermore, if referencing a ``schema`` that contains an example, the ``examples`` value SHALL _override_ the
- example provided by the schema.
-
- For more complex scenarios, the `content <https://spec.openapis.org/oas/v3.1.0#parameterContent>`_ property can
- define the media type and schema of the parameter. A parameter MUST contain either a ``schema`` property, or a
- ``content`` property, but not both. When ``example`` or ``examples`` are provided in conjunction with the ``schema``
- object, the example MUST follow the prescribed serialization strategy for the parameter.
- """
-
- content: dict[str, OpenAPIMediaType] | None = None
- """A map containing the representations for the parameter.
-
- The key is the media type and the value describes it. The map MUST only contain one entry.
- """
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/info.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/info.py
deleted file mode 100644
index 1d858db..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/info.py
+++ /dev/null
@@ -1,50 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.contact import Contact
- from litestar.openapi.spec.license import License
-
-__all__ = ("Info",)
-
-
-@dataclass
-class Info(BaseSchemaObject):
- """The object provides metadata about the API.
-
- The metadata MAY be used by the clients if needed, and MAY be presented in editing or documentation generation tools
- for convenience.
- """
-
- title: str
- """
- **REQUIRED**. The title of the API.
- """
-
- version: str
- """
- **REQUIRED**. The version of the OpenAPI document which is distinct from the
- `OpenAPI Specification version <https://spec.openapis.org/oas/v3.1.0#oasVersion>`_ or the API implementation version
- """
-
- summary: str | None = None
- """A short summary of the API."""
-
- description: str | None = None
- """A description of the API.
-
- `CommonMark syntax <https://spec.commonmark.org/>`_ MAY be used for rich text representation.
- """
-
- terms_of_service: str | None = None
- """A URL to the Terms of Service for the API. MUST be in the form of a URL."""
-
- contact: Contact | None = None
- """The contact information for the exposed API."""
-
- license: License | None = None
- """The license information for the exposed API."""
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/license.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/license.py
deleted file mode 100644
index b779bb4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/license.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-__all__ = ("License",)
-
-
-@dataclass
-class License(BaseSchemaObject):
- """License information for the exposed API."""
-
- name: str
- """**REQUIRED**. The license name used for the API."""
-
- identifier: str | None = None
- """An
- `SPDX <https://spdx.github.io/spdx-spec/v2.3/SPDX-license-list/#a1-licenses-with-short-identifiers>`_ license expression for the API.
-
- The ``identifier`` field is mutually exclusive of the ``url`` field.
- """
-
- url: str | None = None
- """A URL to the license used for the API.
-
- This MUST be in the form of a URL. The ``url`` field is mutually exclusive of the ``identifier`` field.
- """
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/link.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/link.py
deleted file mode 100644
index 78c4f85..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/link.py
+++ /dev/null
@@ -1,66 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING, Any
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.server import Server
-
-__all__ = ("Link",)
-
-
-@dataclass
-class Link(BaseSchemaObject):
- """The ``Link object`` represents a possible design-time link for a response. The presence of a link does not
- guarantee the caller's ability to successfully invoke it, rather it provides a known relationship and traversal
- mechanism between responses and other operations.
-
- Unlike _dynamic_ links (i.e. links provided **in** the response payload), the OAS linking mechanism does not require
- link information in the runtime response.
-
- For computing links, and providing instructions to execute them, a
- `runtime expression <https://spec.openapis.org/oas/v3.1.0#runtimeExpression>`_ is used for accessing values in an
- operation and using them as parameters while invoking the linked operation.
- """
-
- operation_ref: str | None = None
- """A relative or absolute URI reference to an OAS operation.
-
- This field is mutually exclusive of the ``operationId`` field, and MUST point to an
- `Operation Object <https://spec.openapis.org/oas/v3.1.0#operationObject>`_. Relative ``operationRef`` values MAY be
- used to locate an existing `Operation Object <https://spec.openapis.org/oas/v3.1.0#operationObject>`_ in the OpenAPI
- definition. See the rules for resolving
- `Relative References <https://spec.openapis.org/oas/v3.1.0#relativeReferencesURI>`_
- """
-
- operation_id: str | None = None
- """The name of an _existing_, resolvable OAS operation, as defined with a unique ``operationId``.
-
- This field is mutually exclusive of the ``operationRef`` field.
- """
-
- parameters: dict[str, Any] | None = None
- """A map representing parameters to pass to an operation as specified with ``operationId`` or identified via
- ``operationRef``. The key is the parameter name to be used, whereas the value can be a constant or an expression to
- be evaluated and passed to the linked operation.
-
- The parameter name can be qualified using the
- `parameter location <https://spec.openapis.org/oas/v3.1.0#parameterIn>`_ ``[{in}.]{name}`` for operations that use
- the same parameter name in different locations (e.g. path.id).
- """
-
- request_body: Any | None = None
- """A literal value or
- `{expression} <https://spec.openapis.org/oas/v3.1.0#runtimeExpression>`_ to use as a request body when calling the
- target operation."""
-
- description: str | None = None
- """A description of the link.
-
- `CommonMark syntax <https://spec.commonmark.org/>`_ MAY be used for rich text representation.
- """
-
- server: Server | None = None
- """A server object to be used by the target operation."""
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/media_type.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/media_type.py
deleted file mode 100644
index 3e83fb5..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/media_type.py
+++ /dev/null
@@ -1,51 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING, Any
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.encoding import Encoding
- from litestar.openapi.spec.example import Example
- from litestar.openapi.spec.reference import Reference
- from litestar.openapi.spec.schema import Schema
-
-__all__ = ("OpenAPIMediaType",)
-
-
-@dataclass
-class OpenAPIMediaType(BaseSchemaObject):
- """Each Media Type Object provides schema and examples for the media type identified by its key."""
-
- schema: Reference | Schema | None = None
- """The schema defining the content of the request, response, or parameter."""
-
- example: Any | None = None
- """Example of the media type.
-
- The example object SHOULD be in the correct format as specified by the media type.
-
- The ``example`` field is mutually exclusive of the ``examples`` field.
-
- Furthermore, if referencing a ``schema`` which contains an example, the ``example`` value SHALL _override_ the
- example provided by the schema.
- """
-
- examples: dict[str, Example | Reference] | None = None
- """Examples of the media type.
-
- Each example object SHOULD match the media type and specified schema if present.
-
- The ``examples`` field is mutually exclusive of the ``example`` field.
-
- Furthermore, if referencing a ``schema`` which contains an example, the ``examples`` value SHALL _override_ the
- example provided by the schema.
- """
-
- encoding: dict[str, Encoding] | None = None
- """A map between a property name and its encoding information.
-
- The key, being the property name, MUST exist in the schema as a property. The encoding object SHALL only apply to
- ``requestBody`` objects when the media type is ``multipart`` or ``application/x-www-form-urlencoded``.
- """
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/oauth_flow.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/oauth_flow.py
deleted file mode 100644
index c322efc..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/oauth_flow.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-__all__ = ("OAuthFlow",)
-
-
-@dataclass
-class OAuthFlow(BaseSchemaObject):
- """Configuration details for a supported OAuth Flow."""
-
- authorization_url: str | None = None
- """
- **REQUIRED** for ``oauth2`` ("implicit", "authorizationCode"). The authorization URL to be used for this flow. This
- MUST be in the form of a URL. The OAuth2 standard requires the use of TLS.
- """
-
- token_url: str | None = None
- """
- **REQUIRED** for ``oauth2`` ("password", "clientCredentials", "authorizationCode"). The token URL to be used for
- this flow. This MUST be in the form of a URL. The OAuth2 standard requires the use of TLS.
- """
-
- refresh_url: str | None = None
- """The URL to be used for obtaining refresh tokens.
-
- This MUST be in the form of a URL. The OAuth2 standard requires the use of TLS.
- """
-
- scopes: dict[str, str] | None = None
- """
- **REQUIRED** for ``oauth2``. The available scopes for the OAuth2 security scheme. A map between the scope name and a
- short description for it the map MAY be empty.
- """
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/oauth_flows.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/oauth_flows.py
deleted file mode 100644
index 920d095..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/oauth_flows.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.oauth_flow import OAuthFlow
-
-__all__ = ("OAuthFlows",)
-
-
-@dataclass
-class OAuthFlows(BaseSchemaObject):
- """Allows configuration of the supported OAuth Flows."""
-
- implicit: OAuthFlow | None = None
- """Configuration for the OAuth Implicit flow."""
-
- password: OAuthFlow | None = None
- """Configuration for the OAuth Resource Owner Password flow."""
-
- client_credentials: OAuthFlow | None = None
- """Configuration for the OAuth Client Credentials flow. Previously called ``application`` in OpenAPI 2.0."""
-
- authorization_code: OAuthFlow | None = None
- """Configuration for the OAuth Authorization Code flow. Previously called ``accessCode`` in OpenAPI 2.0."""
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/open_api.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/open_api.py
deleted file mode 100644
index 55465fa..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/open_api.py
+++ /dev/null
@@ -1,87 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass, field
-from typing import TYPE_CHECKING
-
-from litestar.openapi.spec.base import BaseSchemaObject
-from litestar.openapi.spec.components import Components
-from litestar.openapi.spec.server import Server
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.external_documentation import ExternalDocumentation
- from litestar.openapi.spec.info import Info
- from litestar.openapi.spec.path_item import PathItem
- from litestar.openapi.spec.paths import Paths
- from litestar.openapi.spec.reference import Reference
- from litestar.openapi.spec.security_requirement import SecurityRequirement
- from litestar.openapi.spec.tag import Tag
-
-__all__ = ("OpenAPI",)
-
-
-@dataclass
-class OpenAPI(BaseSchemaObject):
- """Root OpenAPI document."""
-
- info: Info
- """
- **REQUIRED**. Provides metadata about the API. The metadata MAY be used by tooling as required.
- """
-
- openapi: str = "3.1.0"
- """
- **REQUIRED**. This string MUST be the
- `version number <https://spec.openapis.org/oas/v3.1.0#versions>`_ of the OpenAPI Specification that the OpenAPI
- document uses. The ``openapi`` field SHOULD be used by tooling to interpret the OpenAPI document. This is *not*
- related to the API `info.version <https://spec.openapis.org/oas/v3.1.0#infoVersion>`_ string.
- """
-
- json_schema_dialect: str | None = None
- """The default value for the ``$schema`` keyword within
- `Schema Objects <https://spec.openapis.org/oas/v3.1.0#schemaObject>`_ contained within this OAS document.
-
- This MUST be in the form of a URI.
- """
-
- servers: list[Server] = field(default_factory=lambda x: [Server(url="/")]) # type: ignore[misc, arg-type]
- """An array of Server Objects, which provide connectivity information to a target server.
-
- If the ``servers`` property is not provided, or is an empty array, the default value would be a
- `Server Object <https://spec.openapis.org/oas/v3.1.0#serverObject>`_ with a
- `url <https://spec.openapis.org/oas/v3.1.0#serverUrl>`_ value of ``/``.
- """
-
- paths: Paths | None = None
- """The available paths and operations for the API."""
-
- webhooks: dict[str, PathItem | Reference] | None = None
- """The incoming webhooks that MAY be received as part of this API and that the API consumer MAY choose to implement.
-
- Closely related to the ``callbacks`` feature, this section describes requests initiated other than by an API call,
- for example by an out of band registration. The key name is a unique string to refer to each webhook, while the
- (optionally referenced) Path Item Object describes a request that may be initiated by the API provider and the
- expected responses. An
- `example <https://github.com/OAI/OpenAPI-Specification/blob/main/examples/v3.1/webhook-example.yaml>`_ is available.
- """
-
- components: Components = field(default_factory=Components)
- """An element to hold various schemas for the document."""
-
- security: list[SecurityRequirement] | None = None
- """A declaration of which security mechanisms can be used across the API.
-
- The list of values includes alternative security requirement objects that can be used. Only one of the security
- requirement objects need to be satisfied to authorize a request. Individual operations can override this definition.
- To make security optional, an empty security requirement ( ``{}`` ) can be included in the array.
- """
-
- tags: list[Tag] | None = None
- """A list of tags used by the document with additional metadata.
-
- The order of the tags can be used to reflect on their order by the parsing tools. Not all tags that are used by the
- `Operation Object <https://spec.openapis.org/oas/v3.1.0#operationObject>`_ must be declared. The tags that are not
- declared MAY be organized randomly or based on the tools' logic. Each tag name in the list MUST be unique.
- """
-
- external_docs: ExternalDocumentation | None = None
- """Additional external documentation."""
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/operation.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/operation.py
deleted file mode 100644
index ab80181..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/operation.py
+++ /dev/null
@@ -1,105 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.callback import Callback
- from litestar.openapi.spec.external_documentation import ExternalDocumentation
- from litestar.openapi.spec.parameter import Parameter
- from litestar.openapi.spec.reference import Reference
- from litestar.openapi.spec.request_body import RequestBody
- from litestar.openapi.spec.responses import Responses
- from litestar.openapi.spec.security_requirement import SecurityRequirement
- from litestar.openapi.spec.server import Server
-
-__all__ = ("Operation",)
-
-
-@dataclass
-class Operation(BaseSchemaObject):
- """Describes a single API operation on a path."""
-
- tags: list[str] | None = None
- """A list of tags for API documentation control.
-
- Tags can be used for logical grouping of operations by resources or any other qualifier.
- """
-
- summary: str | None = None
- """A short summary of what the operation does."""
-
- description: str | None = None
- """A verbose explanation of the operation behavior.
-
- `CommonMark syntax <https://spec.commonmark.org/>`_ MAY be used for rich text representation.
- """
-
- external_docs: ExternalDocumentation | None = None
- """Additional external documentation for this operation."""
-
- operation_id: str | None = None
- """Unique string used to identify the operation.
-
- The id MUST be unique among all operations described in the API. The operationId value is **case-sensitive**. Tools
- and libraries MAY use the operationId to uniquely identify an operation, therefore, it is RECOMMENDED to follow
- common programming naming conventions.
- """
-
- parameters: list[Parameter | Reference] | None = None
- """A list of parameters that are applicable for this operation.
-
- If a parameter is already defined at the `Path Item <https://spec.openapis.org/oas/v3.1.0#pathItemParameters>`_,
- the new definition will override it but can never remove it. The list MUST NOT include duplicated parameters. A
- unique parameter is defined by a combination of a `name <https://spec.openapis.org/oas/v3.1.0#parameterName>`_ and
- `location <https://spec.openapis.org/oas/v3.1.0#parameterIn>`_. The list can use the
- `Reference Object <https://spec.openapis.org/oas/v3.1.0#referenceObject>`_ to link to parameters that are defined at
- the `OpenAPI Object's components/parameters <https://spec.openapis.org/oas/v3.1.0#componentsParameters>`_.
- """
-
- request_body: RequestBody | Reference | None = None
- """The request body applicable for this operation.
-
- The ``requestBody`` is fully supported in HTTP methods where the HTTP 1.1 specification
- :rfc:`7231` has explicitly defined semantics for request bodies. In other cases where the HTTP spec is vague (such
- as `GET <https://tools.ietf.org/html/rfc7231#section-4.3.1>`_,
- `HEAD <https://tools.ietf.org/html/rfc7231#section-4.3.2>`_ and
- `DELETE <https://tools.ietf.org/html/rfc7231#section-4.3.5>`_, ``requestBody`` is permitted but does not have
- well-defined semantics and SHOULD be avoided if possible.
- """
-
- responses: Responses | None = None
- """The list of possible responses as they are returned from executing this operation."""
-
- callbacks: dict[str, Callback | Reference] | None = None
- """A map of possible out-of band callbacks related to the parent operation.
-
- The key is a unique identifier for the Callback Object. Each value in the map is a
- `Callback Object <https://spec.openapis.org/oas/v3.1.0#callbackObject>`_ that describes a request that may be
- initiated by the API provider and the expected responses.
- """
-
- deprecated: bool = False
- """Declares this operation to be deprecated.
-
- Consumers SHOULD refrain from usage of the declared operation. Default value is ``False``.
- """
-
- security: list[SecurityRequirement] | None = None
- """A declaration of which security mechanisms can be used for this operation.
-
- The list of values includes alternative security requirement objects that can be used. Only one of the security
- requirement objects need to be satisfied to authorize a request. To make security optional, an empty security
- requirement (``{}``) can be included in the array. This definition overrides any declared top-level
- `security <https://spec.openapis.org/oas/v3.1.0#oasSecurity>`_. To remove a top-level security declaration, an empty
- array can be used.
- """
-
- servers: list[Server] | None = None
- """An alternative ``server`` array to service this operation.
-
- If an alternative ``server`` object is specified at the Path Item Object or Root level, it will be overridden by
- this value.
- """
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/parameter.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/parameter.py
deleted file mode 100644
index 74a100f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/parameter.py
+++ /dev/null
@@ -1,136 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING, Any, Mapping
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.example import Example
- from litestar.openapi.spec.media_type import OpenAPIMediaType
- from litestar.openapi.spec.reference import Reference
- from litestar.openapi.spec.schema import Schema
-
-__all__ = ("Parameter",)
-
-
-@dataclass
-class Parameter(BaseSchemaObject):
- """Describes a single operation parameter.
-
- A unique parameter is defined by a combination of a `name <https://spec.openapis.org/oas/v3.1.0#parameterName>`_ and
- `location <https://spec.openapis.org/oas/v3.1.0#parameterIn>`_.
- """
-
- name: str
- """
- **REQUIRED**. The name of the parameter.
- Parameter names are *case sensitive*.
-
- - If `in <https://spec.openapis.org/oas/v3.1.0#parameterIn>`_ is ``"path"``, the ``name`` field MUST correspond to a
- template expression occurring within the `path <https://spec.openapis.org/oas/v3.1.0#pathsPath>`_ field in the
- `Paths Object <https://spec.openapis.org/oas/v3.1.0#pathsObject>`_. See
- `Path Templating <https://spec.openapis.org/oas/v3.1.0#pathTemplating>`_ for further information.
- - If `in <https://spec.openapis.org/oas/v3.1.0#parameterIn>`_ is ``"header"`` and the ``name`` field is
- ``"Accept"``, ``"Content-Type"`` or ``"Authorization"``, the parameter definition SHALL be ignored.
- - For all other cases, the ``name`` corresponds to the parameter name used by the
- `in <https://spec.openapis.org/oas/v3.1.0#parameterIn>`_ property.
- """
-
- param_in: str
- """
- **REQUIRED**. The location of the parameter. Possible values are
- ``"query"``, ``"header"``, ``"path"`` or ``"cookie"``.
- """
-
- schema: Schema | Reference | None = None
- """The schema defining the type used for the parameter."""
-
- description: str | None = None
- """A brief description of the parameter. This could contain examples of
- use.
-
- `CommonMark syntax <https://spec.commonmark.org/>`_ MAY be used for rich text representation.
- """
-
- required: bool = False
- """Determines whether this parameter is mandatory.
-
- If the `parameter location <https://spec.openapis.org/oas/v3.1.0#parameterIn>`_ is ``"path"``, this property is
- **REQUIRED** and its value MUST be ``True``. Otherwise, the property MAY be included and its default value is
- ``False``.
- """
-
- deprecated: bool = False
- """Specifies that a parameter is deprecated and SHOULD be transitioned out of usage.
-
- Default value is ``False``.
- """
-
- allow_empty_value: bool = False
- """Sets the ability to pass empty-valued parameters. This is valid only for ``query`` parameters and allows sending
- a parameter with an empty value. Default value is ``False``. If
- `style <https://spec.openapis.org/oas/v3.1.0#parameterStyle>`__ is used, and if behavior is ``n/a`` (cannot be
- serialized), the value of ``allowEmptyValue`` SHALL be ignored. Use of this property is NOT RECOMMENDED, as it is
- likely to be removed in a later revision.
-
- The rules for serialization of the parameter are specified in one of two ways. For simpler scenarios, a
- `schema <https://spec.openapis.org/oas/v3.1.0#parameterSchema>`_ and
- `style <https://spec.openapis.org/oas/v3.1.0#parameterStyle>`__ can describe the structure and syntax of the
- parameter.
- """
-
- style: str | None = None
- """Describes how the parameter value will be serialized depending on the ype of the parameter value. Default values
- (based on value of ``in``):
-
- - for ``query`` - ``form``
- - for ``path`` - ``simple``
- - for ``header`` - ``simple``
- - for ``cookie`` - ``form``
- """
-
- explode: bool | None = None
- """When this is true, parameter values of type ``array`` or ``object`` generate separate parameters for each value
- of the array or key-value pair of the map.
-
- For other types of parameters this property has no effect. When
- `style <https://spec.openapis.org/oas/v3.1.0#parameterStyle>`__ is ``form``, the default value is ``True``. For all
- other styles, the default value is ``False``.
- """
-
- allow_reserved: bool = False
- """Determines whether the parameter value SHOULD allow reserved characters, as defined by.
-
- :rfc:`3986` ``:/?#[]@!$&'()*+,;=`` to be included without percent-encoding.
-
- This property only applies to parameters with an ``in`` value of ``query``. The default value is ``False``.
- """
-
- example: Any | None = None
- """Example of the parameter's potential value.
-
- The example SHOULD match the specified schema and encoding properties if present. The ``example`` field is mutually
- exclusive of the ``examples`` field. Furthermore, if referencing a ``schema`` that contains an example, the
- ``example`` value SHALL _override_ the example provided by the schema. To represent examples of media types that
- cannot naturally be represented in JSON or YAML, a string value can contain the example with escaping where
- necessary.
- """
-
- examples: Mapping[str, Example | Reference] | None = None
- """Examples of the parameter's potential value. Each example SHOULD contain a value in the correct format as
- specified in the parameter encoding. The ``examples`` field is mutually exclusive of the ``example`` field.
- Furthermore, if referencing a ``schema`` that contains an example, the ``examples`` value SHALL _override_ the
- example provided by the schema.
-
- For more complex scenarios, the `content <https://spec.openapis.org/oas/v3.1.0#parameterContent>`_ property can
- define the media type and schema of the parameter. A parameter MUST contain either a ``schema`` property, or a
- ``content`` property, but not both. When ``example`` or ``examples`` are provided in conjunction with the
- ``schema`` object, the example MUST follow the prescribed serialization strategy for the parameter.
- """
-
- content: dict[str, OpenAPIMediaType] | None = None
- """A map containing the representations for the parameter.
-
- The key is the media type and the value describes it. The map MUST only contain one entry.
- """
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/path_item.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/path_item.py
deleted file mode 100644
index 17005c5..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/path_item.py
+++ /dev/null
@@ -1,78 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.operation import Operation
- from litestar.openapi.spec.parameter import Parameter
- from litestar.openapi.spec.reference import Reference
- from litestar.openapi.spec.server import Server
-
-__all__ = ("PathItem",)
-
-
-@dataclass
-class PathItem(BaseSchemaObject):
- """Describes the operations available on a single path.
-
- A Path Item MAY be empty, due to `ACL constraints <https://spec.openapis.org/oas/v3.1.0#securityFiltering>`_. The
- path itself is still exposed to the documentation viewer, but they will not know which operations and parameters are
- available.
- """
-
- ref: str | None = None
- """Allows for an external definition of this path item. The referenced structure MUST be in the format of a
- `Path Item Object <https://spec.openapis.org/oas/v3.1.0#pathItemObject>`.
-
- In case a Path Item Object field appears both in the defined object and the referenced object, the behavior is
- undefined. See the rules for resolving
- `Relative References <https://spec.openapis.org/oas/v3.1.0#relativeReferencesURI>`_.
- """
-
- summary: str | None = None
- """An optional, string summary, intended to apply to all operations in this path."""
-
- description: str | None = None
- """An optional, string description, intended to apply to all operations in this path.
-
- `CommonMark syntax <https://spec.commonmark.org/>`_ MAY be used for rich text representation.
- """
-
- get: Operation | None = None
- """A definition of a GET operation on this path."""
-
- put: Operation | None = None
- """A definition of a PUT operation on this path."""
-
- post: Operation | None = None
- """A definition of a POST operation on this path."""
-
- delete: Operation | None = None
- """A definition of a DELETE operation on this path."""
-
- options: Operation | None = None
- """A definition of a OPTIONS operation on this path."""
-
- head: Operation | None = None
- """A definition of a HEAD operation on this path."""
-
- patch: Operation | None = None
- """A definition of a PATCH operation on this path."""
-
- trace: Operation | None = None
- """A definition of a TRACE operation on this path."""
-
- servers: list[Server] | None = None
- """An alternative ``server`` array to service all operations in this path."""
-
- parameters: list[Parameter | Reference] | None = None
- """A list of parameters that are applicable for all the operations described under this path. These parameters can
- be overridden at the operation level, but cannot be removed there. The list MUST NOT include duplicated parameters.
- A unique parameter is defined by a combination of a `name <https://spec.openapis.org/oas/v3.1.0#parameterName>`_ and
- `location <https://spec.openapis.org/oas/v3.1.0#parameterIn>`_. The list can use the
- `Reference Object <https://spec.openapis.org/oas/v3.1.0#referenceObject>`_ to link to parameters that are defined at
- the `OpenAPI Object's components/parameters <https://spec.openapis.org/oas/v3.1.0#componentsParameters>`_.
- """
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/paths.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/paths.py
deleted file mode 100644
index 682664e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/paths.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Dict
-
-if TYPE_CHECKING:
- from litestar.openapi.spec import PathItem
-
-Paths = Dict[str, "PathItem"]
-"""Holds the relative paths to the individual endpoints and their operations. The path is appended to the URL from the.
-
-`Server Object <https://spec.openapis.org/oas/v3.1.0#serverObject>`_ in order to construct the full URL.
-
-The Paths MAY be empty, due to
-`Access Control List (ACL) constraints <https://spec.openapis.org/oas/v3.1.0#securityFiltering>`_.
-
-Patterned Fields
-
-/{path}: PathItem
-
-A relative path to an individual endpoint. The field name MUST begin with a forward slash (``/``). The path is
-**appended** (no relative URL resolution) to the expanded URL from the
-`Server Object <https://spec.openapis.org/oas/v3.1.0#serverObject>`_ 's ``url`` field in order to construct the full
-URL. `Path templating <https://spec.openapis.org/oas/v3.1.0#pathTemplating>`_ is allowed. When matching URLs, concrete
-(non-templated) paths would be matched before their templated counterparts. Templated paths with the same hierarchy but
-different templated names MUST NOT exist as they are identical. In case of ambiguous matching, it's up to the tooling to
-decide which one to use.
-"""
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/reference.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/reference.py
deleted file mode 100644
index 5ee2a95..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/reference.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-__all__ = ("Reference",)
-
-
-@dataclass
-class Reference(BaseSchemaObject):
- """A simple object to allow referencing other components in the OpenAPI document, internally and externally.
-
- The ``$ref`` string value contains a URI `RFC3986 <https://tools.ietf.org/html/rfc3986>`_ , which identifies the
- location of the value being referenced.
-
- See the rules for resolving `Relative References <https://spec.openapis.org/oas/v3.1.0#relativeReferencesURI>`_.
- """
-
- ref: str
- """**REQUIRED**. The reference identifier. This MUST be in the form of a URI."""
-
- summary: str | None = None
- """A short summary which by default SHOULD override that of the referenced component.
-
- If the referenced object-type does not allow a ``summary`` field, then this field has no effect.
- """
-
- description: str | None = None
- """A description which by default SHOULD override that of the referenced component.
-
- `CommonMark syntax <https://spec.commonmark.org/>`_ MAY be used for rich text representation. If the referenced
- object-type does not allow a ``description`` field, then this field has no effect.
- """
-
- @property
- def value(self) -> str:
- return self.ref.split("/")[-1]
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/request_body.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/request_body.py
deleted file mode 100644
index 5e4e195..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/request_body.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.media_type import OpenAPIMediaType
-
-__all__ = ("RequestBody",)
-
-
-@dataclass
-class RequestBody(BaseSchemaObject):
- """Describes a single request body."""
-
- content: dict[str, OpenAPIMediaType]
- """
- **REQUIRED**. The content of the request body.
- The key is a media type or `media type range <https://tools.ietf.org/html/rfc7231#appendix-D>`_ and the value
- describes it.
-
- For requests that match multiple keys, only the most specific key is applicable. e.g. ``text/plain`` overrides
- ``text/*``
- """
-
- description: str | None = None
- """A brief description of the request body. This could contain examples of use.
-
- `CommonMark syntax <https://spec.commonmark.org/>`_ MAY be used for rich text representation.
- """
-
- required: bool = False
- """Determines if the request body is required in the request.
-
- Defaults to ``False``.
- """
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/response.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/response.py
deleted file mode 100644
index 236bc40..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/response.py
+++ /dev/null
@@ -1,48 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.header import OpenAPIHeader
- from litestar.openapi.spec.link import Link
- from litestar.openapi.spec.media_type import OpenAPIMediaType
- from litestar.openapi.spec.reference import Reference
-
-
-__all__ = ("OpenAPIResponse",)
-
-
-@dataclass
-class OpenAPIResponse(BaseSchemaObject):
- """Describes a single response from an API Operation, including design-time, static ``links`` to operations based on
- the response.
- """
-
- description: str
- """**REQUIRED**. A short description of the response.
- `CommonMark syntax <https://spec.commonmark.org/>`_ MAY be used for rich text representation.
- """
-
- headers: dict[str, OpenAPIHeader | Reference] | None = None
- """Maps a header name to its definition.
- `RFC7230 <https://tools.ietf.org/html/rfc7230#page-22>`_ states header names are case insensitive.
- If a response header is defined with the name ``Content-Type``, it SHALL be ignored.
- """
-
- content: dict[str, OpenAPIMediaType] | None = None
- """A map containing descriptions of potential response payloads. The key is a media type or
- `media type range <https://tools.ietf.org/html/rfc7231#appendix-D>`_ and the value describes it.
-
- For responses that match multiple keys, only the most specific key is applicable. e.g. ``text/plain`` overrides
- ``text/*``
- """
-
- links: dict[str, Link | Reference] | None = None
- """A map of operations links that can be followed from the response.
-
- The key of the map is a short name for the link, following the naming constraints of the names for
- `Component Objects <https://spec.openapis.org/oas/v3.1.0#componentsObject>`_.
- """
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/responses.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/responses.py
deleted file mode 100644
index 0cff680..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/responses.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Dict, Union
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.reference import Reference
- from litestar.openapi.spec.response import OpenAPIResponse
-
-Responses = Dict[str, Union["OpenAPIResponse", "Reference"]]
-"""A container for the expected responses of an operation. The container maps a
-HTTP response code to the expected response.
-
-The documentation is not necessarily expected to cover all possible HTTP response codes because they may not be known in
-advance. However, documentation is expected to cover a successful operation response and any known errors.
-
-The ``default`` MAY be used as a default response object for all HTTP codes hat are not covered individually by the
-specification.
-
-The ``Responses Object`` MUST contain at least one response code, and it SHOULD be the response for a successful
-operation call.
-
-Fixed Fields
-
-default: ``Optional[Union[Response, Reference]]``
-
-The documentation of responses other than the ones declared for specific HTTP response codes. Use this field to cover
-undeclared responses. A `Reference Object <https://spec.openapis.org/oas/v3.1.0#referenceObject>`_ can link to a
-response that the `OpenAPI Object's components/responses <https://spec.openapis.org/oas/v3.1.0#componentsResponses>`_
-section defines.
-
-Patterned Fields
-{httpStatusCode}: ``Optional[Union[Response, Reference]]``
-
-Any `HTTP status code <https://spec.openapis.org/oas/v3.1.0#httpCodes>`_ can be used as the property name, but only one
-property per code, to describe the expected response for that HTTP status code.
-
-A `Reference Object <https://spec.openapis.org/oas/v3.1.0#referenceObject>`_ can link to a response that is defined in
-the `OpenAPI Object's components/responses <https://spec.openapis.org/oas/v3.1.0#componentsResponses>`_ section. This
-field MUST be enclosed in quotation marks (for example, ``200``) for compatibility between JSON and YAML. To define a
-range of response codes, this field MAY contain the uppercase wildcard character ``X``. For example, ``2XX`` represents
-all response codes between ``[200-299]``. Only the following range definitions are allowed: ``1XX``, ``2XX``, ``3XX``,
-``4XX``, and ``5XX``. If a response is defined using an explicit code, the explicit code definition takes precedence
-over the range definition for that code.
-"""
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/schema.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/schema.py
deleted file mode 100644
index 4be2b7c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/schema.py
+++ /dev/null
@@ -1,652 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass, fields, is_dataclass
-from typing import TYPE_CHECKING, Any, Hashable, Mapping, Sequence
-
-from litestar.openapi.spec.base import BaseSchemaObject
-from litestar.utils.predicates import is_non_string_sequence
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.discriminator import Discriminator
- from litestar.openapi.spec.enums import OpenAPIFormat, OpenAPIType
- from litestar.openapi.spec.external_documentation import ExternalDocumentation
- from litestar.openapi.spec.reference import Reference
- from litestar.openapi.spec.xml import XML
- from litestar.types import DataclassProtocol
-
-__all__ = ("Schema", "SchemaDataContainer")
-
-
-def _recursive_hash(value: Hashable | Sequence | Mapping | DataclassProtocol | type[DataclassProtocol]) -> int:
- if isinstance(value, Mapping):
- hash_value = 0
- for k, v in value.items():
- if k != "examples":
- hash_value += hash(k)
- hash_value += _recursive_hash(v)
- return hash_value
- if is_dataclass(value):
- hash_value = hash(type(value).__name__)
- for field in fields(value):
- if field.name != "examples":
- hash_value += hash(field.name)
- hash_value += _recursive_hash(getattr(value, field.name, None))
- return hash_value
- if is_non_string_sequence(value):
- return sum(_recursive_hash(v) for v in value)
- return hash(value) if isinstance(value, Hashable) else 0
-
-
-@dataclass
-class Schema(BaseSchemaObject):
- """The Schema Object allows the definition of input and output data types. These types can be objects, but also
- primitives and arrays. This object is a superset of the
- `JSON Schema Specification Draft 2020-12 <https://tools.ietf.org/html/draft-bhutton-json-schema-00>`_.
-
- For more information about the properties, see
- `JSON Schema Core <https://tools.ietf.org/html/draft-wright-json-schema-00>`_ and
- `JSON Schema Validation <https://tools.ietf.org/html/draft-wright-json-schema-validation-00>`_.
-
- Unless stated otherwise, the property definitions follow those of JSON Schema and do not add any additional
- semantics. Where JSON Schema indicates that behavior is defined by the application (e.g. for annotations), OAS also
- defers the definition of semantics to the application consuming the OpenAPI document.
-
- The following properties are taken directly from the
- `JSON Schema Core <https://tools.ietf.org/html/draft-wright-json-schema-00>`_ and follow the same specifications.
- """
-
- all_of: Sequence[Reference | Schema] | None = None
- """This keyword's value MUST be a non-empty array. Each item of the array MUST be a valid JSON Schema.
-
- An instance validates successfully against this keyword if it validates successfully against all schemas defined by
- this keyword's value.
- """
-
- any_of: Sequence[Reference | Schema] | None = None
- """This keyword's value MUST be a non-empty array. Each item of the array MUST be a valid JSON Schema.
-
- An instance validates successfully against this keyword if it validates successfully against at least one schema
- defined by this keyword's value. Note that when annotations are being collected, all subschemas MUST be examined so
- that annotations are collected from each subschema that validates successfully.
- """
-
- one_of: Sequence[Reference | Schema] | None = None
- """This keyword's value MUST be a non-empty array. Each item of the array MUST be a valid JSON Schema.
-
- An instance validates successfully against this keyword if it validates successfully against exactly one schema
- defined by this keyword's value.
- """
-
- schema_not: Reference | Schema | None = None
- """This keyword's value MUST be a valid JSON Schema.
-
- An instance is valid against this keyword if it fails to validate successfully against the schema defined by this
- keyword.
- """
-
- schema_if: Reference | Schema | None = None
- """This keyword's value MUST be a valid JSON Schema.
-
- This validation outcome of this keyword's subschema has no direct effect on the overall validation result. Rather,
- it controls which of the "then" or "else" keywords are evaluated.
-
- Instances that successfully validate against this keyword's subschema MUST also be valid against the subschema
- value of the "then" keyword, if present.
-
- Instances that fail to validate against this keyword's subschema MUST also be valid against the subschema value of
- the "else" keyword, if present.
-
- If annotations (Section 7.7) are being collected, they are collected rom this keyword's subschema in the usual way,
- including when the keyword is present without either "then" or "else".
- """
-
- then: Reference | Schema | None = None
- """This keyword's value MUST be a valid JSON Schema.
-
- When "if" is present, and the instance successfully validates against its subschema, then validation succeeds
- against this keyword if the instance also successfully validates against this keyword's subschema.
-
- This keyword has no effect when "if" is absent, or when the instance fails to validate against its subschema.
- Implementations MUST NOT evaluate the instance against this keyword, for either validation or annotation collection
- purposes, in such cases.
- """
-
- schema_else: Reference | Schema | None = None
- """This keyword's value MUST be a valid JSON Schema.
-
- When "if" is present, and the instance fails to validate against its subschema, then validation succeeds against
- this keyword if the instance successfully validates against this keyword's subschema.
-
- This keyword has no effect when "if" is absent, or when the instance successfully validates against its subschema.
- Implementations MUST NOT evaluate the instance against this keyword, for either validation or annotation collection
- purposes, in such cases.
- """
-
- dependent_schemas: dict[str, Reference | Schema] | None = None
- """This keyword specifies subschemas that are evaluated if the instance is
- an object and contains a certain property.
-
- This keyword's value MUST be an object. Each value in the object MUST be a valid JSON Schema.
-
- If the object key is a property in the instance, the entire instance must validate against the subschema. Its use is
- dependent on the presence of the property.
-
- Omitting this keyword has the same behavior as an empty object.
- """
-
- prefix_items: Sequence[Reference | Schema] | None = None
- """The value of "prefixItems" MUST be a non-empty array of valid JSON Schemas.
-
- Validation succeeds if each element of the instance validates against the schema at the same position, if any.
- This keyword does not constrain the length of the array. If the array is longer than this keyword's value, this
- keyword validates only the prefix of matching length.
-
- This keyword produces an annotation value which is the largest index to which this keyword applied a subschema.
- he value MAY be a boolean true if a subschema was applied to every index of the instance, such as is produced by the
- "items" keyword. This annotation affects the behavior of "items" and "unevaluatedItems".
-
- Omitting this keyword has the same assertion behavior as an empty array.
- """
-
- items: Reference | Schema | None = None
- """The value of "items" MUST be a valid JSON Schema.
-
- This keyword applies its subschema to all instance elements at indexes greater than the length of the "prefixItems"
- array in the same schema object, as reported by the annotation result of that "prefixItems" keyword. If no such
- annotation result exists, "items" applies its subschema to all instance array elements. [[CREF11: Note that the
- behavior of "items" without "prefixItems" is identical to that of the schema form of "items" in prior drafts. When
- "prefixItems" is present, the behavior of "items" is identical to the former "additionalItems" keyword. ]]
-
- If the "items" subschema is applied to any positions within the instance array, it produces an annotation result of
- boolean true, indicating that all remaining array elements have been evaluated against this keyword's subschema.
-
- Omitting this keyword has the same assertion behavior as an empty schema.
-
- Implementations MAY choose to implement or optimize this keyword in another way that produces the same effect, such
- as by directly checking for the presence and size of a "prefixItems" array. Implementations that do not support
- annotation collection MUST do so.
- """
-
- contains: Reference | Schema | None = None
- """The value of this keyword MUST be a valid JSON Schema.
-
- An array instance is valid against "contains" if at least one of its elements is valid against the given schema.
- The subschema MUST be applied to every array element even after the first match has been found, in order to collect
- annotations for use by other keywords. This is to ensure that all possible annotations are collected.
-
- Logically, the validation result of applying the value subschema to each item in the array MUST be ORed with
- "false", resulting in an overall validation result.
-
- This keyword produces an annotation value which is an array of the indexes to which this keyword validates
- successfully when applying its subschema, in ascending order. The value MAY be a boolean "true" if the subschema
- validates successfully when applied to every index of the instance. The annotation MUST be present if the instance
- array to which this keyword's schema applies is empty.
- """
-
- properties: dict[str, Reference | Schema] | None = None
- """The value of "properties" MUST be an object. Each value of this object MUST be a valid JSON Schema.
-
- Validation succeeds if, for each name that appears in both the instance and as a name within this keyword's value,
- the child instance for that name successfully validates against the corresponding schema.
-
- The annotation result of this keyword is the set of instance property names matched by this keyword.
-
- Omitting this keyword has the same assertion behavior as an empty object.
- """
-
- pattern_properties: dict[str, Reference | Schema] | None = None
- """The value of "patternProperties" MUST be an object. Each property name of this object SHOULD be a valid
- regular expression, according to the ECMA-262 regular expression dialect. Each property value of this object
- MUST be a valid JSON Schema.
-
- Validation succeeds if, for each instance name that matches any regular expressions that appear as a property name
- in this keyword's value, the child instance for that name successfully validates against each schema that
- corresponds to a matching regular expression.
-
- The annotation result of this keyword is the set of instance property names matched by this keyword.
-
- Omitting this keyword has the same assertion behavior as an empty object.
- """
-
- additional_properties: Reference | Schema | bool | None = None
- """The value of "additionalProperties" MUST be a valid JSON Schema.
-
- The behavior of this keyword depends on the presence and annotation results of "properties" and "patternProperties"
- within the same schema object. Validation with "additionalProperties" applies only to the child values of instance
- names that do not appear in the annotation results of either "properties" or "patternProperties".
-
- For all such properties, validation succeeds if the child instance validates against the "additionalProperties"
- schema.
-
- The annotation result of this keyword is the set of instance property names validated by this keyword's subschema.
-
- Omitting this keyword has the same assertion behavior as an empty schema.
-
- Implementations MAY choose to implement or optimize this keyword in another way that produces the same effect, such
- as by directly checking the names in "properties" and the patterns in "patternProperties" against the instance
- property set. Implementations that do not support annotation collection MUST do so.
- """
-
- property_names: Reference | Schema | None = None
- """The value of "propertyNames" MUST be a valid JSON Schema.
-
- If the instance is an object, this keyword validates if every property name in the instance validates against the
- provided schema. Note the property name that the schema is testing will always be a string.
-
- Omitting this keyword has the same behavior as an empty schema.
- """
-
- unevaluated_items: Reference | Schema | None = None
- """The value of "unevaluatedItems" MUST be a valid JSON Schema.
-
- The behavior of this keyword depends on the annotation results of adjacent keywords that apply to the instance
- location being validated. Specifically, the annotations from "prefixItems" items", and "contains", which can come
- from those keywords when they are adjacent to the "unevaluatedItems" keyword. Those three annotations, as well as
- "unevaluatedItems", can also result from any and all adjacent in-place applicator (Section 10.2) keywords. This
- includes but is not limited to the in-place applicators defined in this document.
-
- If no relevant annotations are present, the "unevaluatedItems" subschema MUST be applied to all locations in the
- array. If a boolean true value is present from any of the relevant annotations, unevaluatedItems" MUST be ignored.
- Otherwise, the subschema MUST be applied to any index greater than the largest annotation value for "prefixItems",
- which does not appear in any annotation value for
- "contains".
-
- This means that "prefixItems", "items", "contains", and all in-place applicators MUST be evaluated before this
- keyword can be evaluated. Authors of extension keywords MUST NOT define an in-place applicator that would need to be
- evaluated after this keyword.
-
- If the "unevaluatedItems" subschema is applied to any positions within the instance array, it produces an annotation
- result of boolean true, analogous to the behavior of "items".
-
- Omitting this keyword has the same assertion behavior as an empty schema.
- """
-
- unevaluated_properties: Reference | Schema | None = None
- """The value of "unevaluatedProperties" MUST be a valid JSON Schema.
-
- The behavior of this keyword depends on the annotation results of adjacent keywords that apply to the instance
- location being validated. Specifically, the annotations from "properties", "patternProperties", and
- "additionalProperties", which can come from those keywords when they are adjacent to the "unevaluatedProperties"
- keyword. Those three annotations, as well as "unevaluatedProperties", can also result from any and all adjacent
- in-place applicator (Section 10.2) keywords. This includes but is not limited to the in-place applicators defined
- in this document.
-
- Validation with "unevaluatedProperties" applies only to the child values of instance names that do not appear in
- the "properties", "patternProperties", "additionalProperties", or "unevaluatedProperties" annotation results that
- apply to the instance location being validated.
-
- For all such properties, validation succeeds if the child instance validates against the "unevaluatedProperties"
- schema.
-
- This means that "properties", "patternProperties", "additionalProperties", and all in-place applicators MUST be
- evaluated before this keyword can be evaluated. Authors of extension keywords MUST NOT define an in-place
- applicator that would need to be evaluated after this keyword.
-
- The annotation result of this keyword is the set of instance property names validated by this keyword's subschema.
-
- Omitting this keyword has the same assertion behavior as an empty schema.
-
- The following properties are taken directly from the
- `JSON Schema Validation <https://tools.ietf.org/html/draft-wright-json-schema-validation-00>`_ and follow the same
- specifications:
- """
-
- type: OpenAPIType | Sequence[OpenAPIType] | None = None
- """The value of this keyword MUST be either a string or an array. If it is an array, elements of the array MUST be
- strings and MUST be unique.
-
- String values MUST be one of the six primitive types (``"null"``, ``"boolean"``, ``"object"``, ``"array"``,
- ``"number"``, and ``"string"``), or ``"integer"`` which matches any number with a zero fractional part.
-
- An instance validates if and only if the instance is in any of the sets listed for this keyword.
- """
-
- enum: Sequence[Any] | None = None
- """The value of this keyword MUST be an array. This array SHOULD have at least one element. Elements in the array
- SHOULD be unique.
-
- An instance validates successfully against this keyword if its value is equal to one of the elements in this
- keyword's array value.
-
- Elements in the array might be of any type, including null.
- """
-
- const: Any | None = None
- """The value of this keyword MAY be of any type, including null.
-
- Use of this keyword is functionally equivalent to an "enum" (Section 6.1.2) with a single value.
-
- An instance validates successfully against this keyword if its value is equal to the value of the keyword.
- """
-
- multiple_of: float | None = None
- """The value of "multipleOf" MUST be a number, strictly greater than 0.
-
- A numeric instance is only valid if division by this keyword's value results in an integer.
- """
-
- maximum: float | None = None
- """The value of "maximum" MUST be a number, representing an inclusive upper limit for a numeric instance.
-
- If the instance is a number, then this keyword validates only if the instance is less than or exactly equal to
- "maximum".
- """
-
- exclusive_maximum: float | None = None
- """The value of "exclusiveMaximum" MUST be a number, representing an exclusive upper limit for a numeric instance.
-
- If the instance is a number, then the instance is valid only if it has a value strictly less than (not equal to)
- "exclusiveMaximum".
- """
-
- minimum: float | None = None
- """The value of "minimum" MUST be a number, representing an inclusive lower limit for a numeric instance.
-
- If the instance is a number, then this keyword validates only if the instance is greater than or exactly equal to
- "minimum".
- """
-
- exclusive_minimum: float | None = None
- """The value of "exclusiveMinimum" MUST be a number, representing an exclusive lower limit for a numeric instance.
-
- If the instance is a number, then the instance is valid only if it has a value strictly greater than (not equal to)
- "exclusiveMinimum".
- """
-
- max_length: int | None = None
- """The value of this keyword MUST be a non-negative integer.
-
- A string instance is valid against this keyword if its length is less than, or equal to, the value of this keyword.
-
- The length of a string instance is defined as the number of its characters as defined by :rfc:`8259`.
- """
-
- min_length: int | None = None
- """The value of this keyword MUST be a non-negative integer.
-
- A string instance is valid against this keyword if its length is greater than, or equal to, the value of this
- keyword.
-
- The length of a string instance is defined as the number of its characters as defined by :rfc:`8259`.
-
- Omitting this keyword has the same behavior as a value of 0.
- """
-
- pattern: str | None = None
- """The value of this keyword MUST be a string. This string SHOULD be a valid regular expression, according to the
- ECMA-262 regular expression dialect.
-
- A string instance is considered valid if the regular expression matches the instance successfully. Recall: regular
- expressions are not implicitly anchored.
- """
-
- max_items: int | None = None
- """The value of this keyword MUST be a non-negative integer.
-
- An array instance is valid against "maxItems" if its size is less than, or equal to, the value of this keyword.
- """
-
- min_items: int | None = None
- """The value of this keyword MUST be a non-negative integer.
-
- An array instance is valid against "minItems" if its size is greater than, or equal to, the value of this keyword.
-
- Omitting this keyword has the same behavior as a value of 0.
- """
-
- unique_items: bool | None = None
- """The value of this keyword MUST be a boolean.
-
- If this keyword has boolean value false, the instance validates successfully. If it has boolean value true, the
- instance validates successfully if all of its elements are unique.
-
- Omitting this keyword has the same behavior as a value of false.
- """
-
- max_contains: int | None = None
- """The value of this keyword MUST be a non-negative integer.
-
- If "contains" is not present within the same schema object, then this keyword has no effect.
-
- An instance array is valid against "maxContains" in two ways, depending on the form of the annotation result of an
- adjacent "contains" [json-schema] keyword. The first way is if the annotation result is an array and the length of
- that array is less than or equal to the "maxContains" value. The second way is if the annotation result is a
- boolean "true" and the instance array length is less than r equal to the "maxContains" value.
- """
-
- min_contains: int | None = None
- """The value of this keyword MUST be a non-negative integer.
-
- If "contains" is not present within the same schema object, then this keyword has no effect.
-
- An instance array is valid against "minContains" in two ways, depending on the form of the annotation result of an
- adjacent "contains" [json-schema] keyword. The first way is if the annotation result is an array and the length of
- that array is greater than or equal to the "minContains" value. The second way is if the annotation result is a
- boolean "true" and the instance array length is greater than or equal to the "minContains" value.
-
- A value of 0 is allowed, but is only useful for setting a range of occurrences from 0 to the value of "maxContains".
- A value of 0 with no "maxContains" causes "contains" to always pass validation.
-
- Omitting this keyword has the same behavior as a value of 1.
- """
-
- max_properties: int | None = None
- """The value of this keyword MUST be a non-negative integer.
-
- An object instance is valid against "maxProperties" if its number of properties is less than, or equal to, the value
- of this keyword.
- """
-
- min_properties: int | None = None
- """The value of this keyword MUST be a non-negative integer.
-
- An object instance is valid against "minProperties" if its number of properties is greater than, or equal to, the
- value of this keyword.
-
- Omitting this keyword has the same behavior as a value of 0.
- """
-
- required: Sequence[str] | None = None
- """The value of this keyword MUST be an array. Elements of this array, if any, MUST be strings, and MUST be unique.
-
- An object instance is valid against this keyword if every item in the rray is the name of a property in the instance.
-
- Omitting this keyword has the same behavior as an empty array.
- """
-
- dependent_required: dict[str, Sequence[str]] | None = None
- """The value of this keyword MUST be an object. Properties in this object, f any, MUST be arrays. Elements in each
- array, if any, MUST be strings, and MUST be unique.
-
- This keyword specifies properties that are required if a specific other property is present. Their requirement is
- dependent on the presence of the other property.
-
- Validation succeeds if, for each name that appears in both the instance and as a name within this keyword's value,
- every item in the corresponding array is also the name of a property in the instance.
-
- Omitting this keyword has the same behavior as an empty object.
- """
-
- format: OpenAPIFormat | None = None
- """From OpenAPI:
-
- See `Data Type Formats <https://spec.openapis.org/oas/v3.1.0#dataTypeFormat>`_ for further details. While relying on
- JSON Schema's defined formats, the OAS offers a few additional predefined formats.
-
- From JSON Schema:
-
- Structural validation alone may be insufficient to allow an application to correctly utilize certain values.
- The "format" annotation keyword is defined to allow schema authors to convey semantic information for a fixed subset
- of values which are accurately described by authoritative resources, be they RFCs or other external specifications.
-
- The value of this keyword is called a format attribute. It MUST be a string. A format attribute can generally only
- validate a given set of instance types. If the type of the instance to validate is not in this set, validation for
- this format attribute and instance SHOULD succeed. All format attributes defined in this section apply to strings,
- but a format attribute can be specified to apply to any instance types defined in the data model defined in the core
- JSON Schema. [json-schema] [[CREF1: Note that the "type" keyword in this specification defines an "integer" type
- which is not part of the data model. Therefore a format attribute can be limited to numbers, but not specifically to
- integers. However, a numeric format can be used alongside the "type" keyword with a value of "integer", or could be
- explicitly defined to always pass if the number is not an integer, which produces essentially the same behavior as
- only applying to integers. ]]
- """
-
- content_encoding: str | None = None
- """If the instance value is a string, this property defines that the string SHOULD be interpreted as binary data and
- decoded using the encoding named by this property.
-
- Possible values indicating base 16, 32, and 64 encodings with several variations are listed in :rfc:`4648`.
- Additionally, sections 6.7 and 6.8 of :rfc:`2045` provide encodings used in MIME. As "base64" is defined in both
- RFCs, the definition from :rfc:`4648` SHOULD be assumed unless the string is specifically intended for use in a
- MIME context. Note that all of these encodings result in strings consisting only of 7-bit ASCII characters.
- therefore, this keyword has no meaning for strings containing characters outside of that range.
-
- If this keyword is absent, but "contentMediaType" is present, this indicates that the encoding is the identity
- encoding, meaning that no transformation was needed in order to represent the content in a UTF-8 string.
- """
-
- content_media_type: str | None = None
- """If the instance is a string, this property indicates the media type of the contents of the string. If
- "contentEncoding" is present, this property describes the decoded string.
-
- The value of this property MUST be a string, which MUST be a media type, as defined by :rfc:`2046`
- """
-
- content_schema: Reference | Schema | None = None
- """If the instance is a string, and if "contentMediaType" is present, this property contains a schema which
- describes the structure of the string.
-
- This keyword MAY be used with any media type that can be mapped into JSON Schema's data model.
-
- The value of this property MUST be a valid JSON schema. It SHOULD be ignored if "contentMediaType" is not present.
- """
-
- title: str | None = None
- """The value of "title" MUST be a string.
-
- The title can be used to decorate a user interface with information about the data produced by this user interface.
- A title will preferably be short.
- """
-
- description: str | None = None
- """From OpenAPI:
-
- `CommonMark syntax <https://spec.commonmark.org/>`_ MAY be used for rich text representation.
-
- From JSON Schema:
- The value "description" MUST be a string.
-
- The description can be used to decorate a user interface with information about the data produced by this user
- interface. A description will provide explanation about the purpose of the instance described by this schema.
- """
-
- default: Any | None = None
- """There are no restrictions placed on the value of this keyword. When multiple occurrences of this keyword are
- applicable to a single sub-instance, implementations SHOULD remove duplicates.
-
- This keyword can be used to supply a default JSON value associated with a particular schema. It is RECOMMENDED that
- a default value be valid against the associated schema.
- """
-
- deprecated: bool | None = None
- """The value of this keyword MUST be a boolean. When multiple occurrences of this keyword are applicable to a
- single sub-instance, applications SHOULD consider the instance location to be deprecated if any occurrence specifies
- a true value.
-
- If "deprecated" has a value of boolean true, it indicates that applications SHOULD refrain from usage of the
- declared property. It MAY mean the property is going to be removed in the future.
-
- A root schema containing "deprecated" with a value of true indicates that the entire resource being described MAY be
- removed in the future.
-
- The "deprecated" keyword applies to each instance location to which the schema object containing the keyword
- successfully applies. This can result in scenarios where every array item or object property is deprecated even
- though the containing array or object is not.
-
- Omitting this keyword has the same behavior as a value of false.
- """
-
- read_only: bool | None = None
- """The value of "readOnly" MUST be a boolean. When multiple occurrences of this keyword are applicable to a single
- sub-instance, the resulting behavior SHOULD be as for a true value if any occurrence specifies a true value, and
- SHOULD be as for a false value otherwise.
-
- If "readOnly" has a value of boolean true, it indicates that the value of the instance is managed exclusively by
- the owning authority, and attempts by an application to modify the value of this property are expected to be ignored
- or rejected by that owning authority.
-
- An instance document that is marked as "readOnly" for the entire document MAY be ignored if sent to the owning
- authority, or MAY result in an error, at the authority's discretion.
-
- For example, "readOnly" would be used to mark a database-generated serial number as read-only, while "writeOnly"
- would be used to mark a password input field.
-
- This keyword can be used to assist in user interface instance generation. In particular, an application MAY choose
- to use a widget that hides input values as they are typed for write-only fields.
-
- Omitting these keywords has the same behavior as values of false.
- """
-
- write_only: bool | None = None
- """The value of "writeOnly" MUST be a boolean. When multiple occurrences of this keyword are applicable to a
- single sub-instance, the resulting behavior SHOULD be as for a true value if any occurrence specifies a true value,
- and SHOULD be as for a false value otherwise.
-
- If "writeOnly" has a value of boolean true, it indicates that the value is never present when the instance is
- retrieved from the owning authority. It can be present when sent to the owning authority to update or create the
- document (or the resource it represents), but it will not be included in any updated or newly created version of the
- instance.
-
- An instance document that is marked as "writeOnly" for the entire document MAY be returned as a blank document of
- some sort, or MAY produce an error upon retrieval, or have the retrieval request ignored, at the authority's
- discretion.
-
- For example, "readOnly" would be used to mark a database-generated serial number as read-only, while "writeOnly"
- would be used to mark a password input field.
-
- This keyword can be used to assist in user interface instance generation. In particular, an application MAY choose
- to use a widget that hides input values as they are typed for write-only fields.
-
- Omitting these keywords has the same behavior as values of false.
- """
-
- examples: list[Any] | None = None
- """The value of this must be an array containing the example values."""
-
- discriminator: Discriminator | None = None
- """Adds support for polymorphism.
-
- The discriminator is an object name that is used to differentiate between other schemas which may satisfy the
- payload description. See `Composition and Inheritance <https://spec.openapis.org/oas/v3.1.0#schemaComposition>`_
- for more details.
- """
-
- xml: XML | None = None
- """This MAY be used only on properties schemas.
-
- It has no effect on root schemas. Adds additional metadata to describe the XML representation of this property.
- """
-
- external_docs: ExternalDocumentation | None = None
- """Additional external documentation for this schema."""
-
- example: Any | None = None
- """A free-form property to include an example of an instance for this schema. To represent examples that cannot be
- naturally represented in JSON or YAML, a string value can be used to contain the example with escaping where
- necessary.
-
- Deprecated: The example property has been deprecated in favor of the JSON Schema examples keyword. Use of example is
- discouraged, and later versions of this specification may remove it.
- """
-
- def __hash__(self) -> int:
- return _recursive_hash(self)
-
-
-@dataclass
-class SchemaDataContainer(Schema):
- """Special class that allows using python data containers, e.g. dataclasses or pydantic models, to represent a
- schema
- """
-
- data_container: Any = None
- """A data container instance that will be used to generate the schema."""
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/security_requirement.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/security_requirement.py
deleted file mode 100644
index e3d1394..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/security_requirement.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from __future__ import annotations
-
-from typing import Dict, List
-
-SecurityRequirement = Dict[str, List[str]]
-"""Lists the required security schemes to execute this operation. The name used for each property MUST correspond to a
-security scheme declared in the.
-
-`Security Schemes <https://spec.openapis.org/oas/v3.1.0#componentsSecuritySchemes>`_ under the
-`Components Object <https://spec.openapis.org/oas/v3.1.0#componentsObject>`_.
-
-Security Requirement Objects that contain multiple schemes require that all schemes MUST be satisfied for a request to
-be authorized. This enables support for scenarios where multiple query parameters or HTTP headers are required to convey
-security information.
-
-When a list of Security Requirement Objects is defined on the
-`OpenAPI Object <https://spec.openapis.org/oas/v3.1.0#oasObject>`_ or
-`Operation Object <https://spec.openapis.org/oas/v3.1.0#operationObject>`_, only one of the Security Requirement
-Objects in the list needs to be satisfied to authorize the request.
-
-Patterned Fields
-
-{name}: ``List[str]``
-Each name MUST correspond to a security scheme which is declared
-in the `Security Schemes <https://spec.openapis.org/oas/v3.1.0#componentsSecuritySchemes>`_ under the
-`Components Object <https://spec.openapis.org/oas/v3.1.0#componentsObject>`_. if the security scheme is of type
-``"oauth2"`` or ``"openIdConnect"``, then the value is a list of scope names required for the execution, and the list
-MAY be empty if authorization does not require a specified scope. For other security scheme types, the array MAY contain
-a list of role names which are required for the execution,but are not otherwise defined or exchanged in-band.
-"""
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/security_scheme.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/security_scheme.py
deleted file mode 100644
index badc77e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/security_scheme.py
+++ /dev/null
@@ -1,69 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING, Literal
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.oauth_flows import OAuthFlows
-
-__all__ = ("SecurityScheme",)
-
-
-@dataclass
-class SecurityScheme(BaseSchemaObject):
- """Defines a security scheme that can be used by the operations.
-
- Supported schemes are HTTP authentication, an API key (either as a header, a cookie parameter or as a query
- parameter), mutual TLS (use of a client certificate), OAuth2's common flows (implicit, password, client credentials
- and authorization code) as defined in :rfc`6749`, and
- `OpenID Connect Discovery <https://tools.ietf.org/html/draft-ietf-oauth-discovery-06>`_.
-
- Please note that as of 2020, the implicit flow is about to be deprecated by
- `OAuth 2.0 Security Best Current Practice <https://tools.ietf.org/html/draft-ietf-oauth-security-topics>`_.
- Recommended for most use case is Authorization Code Grant flow with PKCE.
- """
-
- type: Literal["apiKey", "http", "mutualTLS", "oauth2", "openIdConnect"]
- """**REQUIRED**. The type of the security scheme."""
-
- description: str | None = None
- """A description for security scheme.
-
- `CommonMark syntax <https://spec.commonmark.org/>`_ MAY be used for rich text representation.
- """
-
- name: str | None = None
- """
- **REQUIRED** for ``apiKey``. The name of the header, query or cookie parameter to be used.
- """
-
- security_scheme_in: Literal["query", "header", "cookie"] | None = None
- """
- **REQUIRED** for ``apiKey``. The location of the API key.
- """
-
- scheme: str | None = None
- """
- **REQUIRED** for ``http``. The name of the HTTP Authorization scheme to be used in the
- authorization header as defined in :rfc:`7235`.
-
- The values used SHOULD be registered in the
- `IANA Authentication Scheme registry <https://www.iana.org/assignments/http-authschemes/http-authschemes.xhtml>`_
- """
-
- bearer_format: str | None = None
- """A hint to the client to identify how the bearer token is formatted.
-
- Bearer tokens are usually generated by an authorization server, so this information is primarily for documentation
- purposes.
- """
-
- flows: OAuthFlows | None = None
- """**REQUIRED** for ``oauth2``. An object containing configuration information for the flow types supported."""
-
- open_id_connect_url: str | None = None
- """**REQUIRED** for ``openIdConnect``. OpenId Connect URL to discover OAuth2 configuration values. This MUST be in
- the form of a URL. The OpenID Connect standard requires the use of TLS.
- """
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/server.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/server.py
deleted file mode 100644
index 2c12fcf..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/server.py
+++ /dev/null
@@ -1,34 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.server_variable import ServerVariable
-
-__all__ = ("Server",)
-
-
-@dataclass
-class Server(BaseSchemaObject):
- """An object representing a Server."""
-
- url: str
- """
- **REQUIRED**. A URL to the target host.
-
- This URL supports Server Variables and MAY be relative, to indicate that the host location is relative to the
- location where the OpenAPI document is being served. Variable substitutions will be made when a variable is named in
- ``{brackets}``.
- """
-
- description: str | None = None
- """An optional string describing the host designated by the URL.
-
- `CommonMark syntax <https://spec.commonmark.org/>`_ MAY be used for rich text representation.
- """
-
- variables: dict[str, ServerVariable] | None = None
- """A map between a variable name and its value. The value is used for substitution in the server's URL template."""
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/server_variable.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/server_variable.py
deleted file mode 100644
index c59c542..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/server_variable.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-__all__ = ("ServerVariable",)
-
-
-@dataclass
-class ServerVariable(BaseSchemaObject):
- """An object representing a Server Variable for server URL template substitution."""
-
- default: str
- """**REQUIRED**. The default value to use for substitution, which SHALL be sent if an alternate value is _not_
- supplied. Note this behavior is different than the
- `Schema Object's <https://spec.openapis.org/oas/v3.1.0#schemaObject>`_ treatment of default values, because in those
- cases parameter values are optional. If the `enum <https://spec.openapis.org/oas/v3.1.0#serverVariableEnum>`_ is
- defined, the value MUST exist in the enum's values.
- """
-
- enum: list[str] | None = None
- """An enumeration of string values to be used if the substitution options are from a limited set.
-
- The array SHOULD NOT be empty.
- """
-
- description: str | None = None
- """An optional description for the server variable.
-
- `CommonMark syntax <https://spec.commonmark.org/>`_ MAY be used for rich text representation.
- """
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/tag.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/tag.py
deleted file mode 100644
index c3e6374..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/tag.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.external_documentation import ExternalDocumentation
-
-__all__ = ("Tag",)
-
-
-@dataclass
-class Tag(BaseSchemaObject):
- """Adds metadata to a single tag that is used by the
- `Operation Object <https://spec.openapis.org/oas/v3.1.0#operationObject>`_.
-
- It is not mandatory to have a Tag Object per tag defined in the Operation Object instances.
- """
-
- name: str
- """**REQUIRED**. The name of the tag."""
-
- description: str | None = None
- """A short description for the tag.
-
- `CommonMark syntax <https://spec.commonmark.org/>`_ MAY be used for rich text representation.
- """
-
- external_docs: ExternalDocumentation | None = None
- """Additional external documentation for this tag."""
diff --git a/venv/lib/python3.11/site-packages/litestar/openapi/spec/xml.py b/venv/lib/python3.11/site-packages/litestar/openapi/spec/xml.py
deleted file mode 100644
index 6030998..0000000
--- a/venv/lib/python3.11/site-packages/litestar/openapi/spec/xml.py
+++ /dev/null
@@ -1,44 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-
-from litestar.openapi.spec.base import BaseSchemaObject
-
-__all__ = ("XML",)
-
-
-@dataclass()
-class XML(BaseSchemaObject):
- """A metadata object that allows for more fine-tuned XML model definitions.
-
- When using arrays, XML element names are *not* inferred (for singular/plural forms) and the ``name`` property SHOULD
- be used to add that information. See examples for expected behavior.
- """
-
- name: str | None = None
- """
- Replaces the name of the element/attribute used for the described schema property. When defined within ``items``, it
- will affect the name of the individual XML elements within the list. When defined alongside ``type`` being ``array``
- (outside the ``items``), it will affect the wrapping element and only if ``wrapped`` is ``True``. If ``wrapped`` is
- ``False``, it will be ignored.
- """
-
- namespace: str | None = None
- """The URI of the namespace definition. Value MUST be in the form of an absolute URI."""
-
- prefix: str | None = None
- """The prefix to be used for the
- `xmlName <https://spec.openapis.org/oas/v3.1.0#xmlName>`_
- """
-
- attribute: bool = False
- """Declares whether the property definition translates to an attribute instead of an element. Default value is
- ``False``.
- """
-
- wrapped: bool = False
- """
- MAY be used only for an array definition. Signifies whether the array is wrapped (for example,
- ``<books><book/><book/></books>``) or unwrapped (``<book/><book/>``). Default value is ``False``. The definition
- takes effect only when defined alongside ``type`` being ``array`` (outside the ``items``).
- """
diff --git a/venv/lib/python3.11/site-packages/litestar/pagination.py b/venv/lib/python3.11/site-packages/litestar/pagination.py
deleted file mode 100644
index 294a13a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/pagination.py
+++ /dev/null
@@ -1,342 +0,0 @@
-# ruff: noqa: UP006,UP007
-from __future__ import annotations
-
-from abc import ABC, abstractmethod
-from dataclasses import dataclass
-from typing import Generic, List, Optional, TypeVar
-from uuid import UUID
-
-__all__ = (
- "AbstractAsyncClassicPaginator",
- "AbstractAsyncCursorPaginator",
- "AbstractAsyncOffsetPaginator",
- "AbstractSyncClassicPaginator",
- "AbstractSyncCursorPaginator",
- "AbstractSyncOffsetPaginator",
- "ClassicPagination",
- "CursorPagination",
- "OffsetPagination",
-)
-
-
-T = TypeVar("T")
-C = TypeVar("C", int, str, UUID)
-
-
-@dataclass
-class ClassicPagination(Generic[T]):
- """Container for data returned using limit/offset pagination."""
-
- __slots__ = ("items", "page_size", "current_page", "total_pages")
-
- items: List[T]
- """List of data being sent as part of the response."""
- page_size: int
- """Number of items per page."""
- current_page: int
- """Current page number."""
- total_pages: int
- """Total number of pages."""
-
-
-@dataclass
-class OffsetPagination(Generic[T]):
- """Container for data returned using limit/offset pagination."""
-
- __slots__ = ("items", "limit", "offset", "total")
-
- items: List[T]
- """List of data being sent as part of the response."""
- limit: int
- """Maximal number of items to send."""
- offset: int
- """Offset from the beginning of the query.
-
- Identical to an index.
- """
- total: int
- """Total number of items."""
-
-
-@dataclass
-class CursorPagination(Generic[C, T]):
- """Container for data returned using cursor pagination."""
-
- __slots__ = ("items", "results_per_page", "cursor", "next_cursor")
-
- items: List[T]
- """List of data being sent as part of the response."""
- results_per_page: int
- """Maximal number of items to send."""
- cursor: Optional[C]
- """Unique ID, designating the last identifier in the given data set.
-
- This value can be used to request the "next" batch of records.
- """
-
-
-class AbstractSyncClassicPaginator(ABC, Generic[T]):
- """Base paginator class for sync classic pagination.
-
- Implement this class to return paginated result sets using the classic pagination scheme.
- """
-
- @abstractmethod
- def get_total(self, page_size: int) -> int:
- """Return the total number of records.
-
- Args:
- page_size: Maximal number of records to return.
-
- Returns:
- An integer.
- """
- raise NotImplementedError
-
- @abstractmethod
- def get_items(self, page_size: int, current_page: int) -> list[T]:
- """Return a list of items of the given size 'page_size' correlating with 'current_page'.
-
- Args:
- page_size: Maximal number of records to return.
- current_page: The current page of results to return.
-
- Returns:
- A list of items.
- """
- raise NotImplementedError
-
- def __call__(self, page_size: int, current_page: int) -> ClassicPagination[T]:
- """Return a paginated result set.
-
- Args:
- page_size: Maximal number of records to return.
- current_page: The current page of results to return.
-
- Returns:
- A paginated result set.
- """
- total_pages = self.get_total(page_size=page_size)
-
- items = self.get_items(page_size=page_size, current_page=current_page)
-
- return ClassicPagination[T](
- items=items, total_pages=total_pages, page_size=page_size, current_page=current_page
- )
-
-
-class AbstractAsyncClassicPaginator(ABC, Generic[T]):
- """Base paginator class for async classic pagination.
-
- Implement this class to return paginated result sets using the classic pagination scheme.
- """
-
- @abstractmethod
- async def get_total(self, page_size: int) -> int:
- """Return the total number of records.
-
- Args:
- page_size: Maximal number of records to return.
-
- Returns:
- An integer.
- """
- raise NotImplementedError
-
- @abstractmethod
- async def get_items(self, page_size: int, current_page: int) -> list[T]:
- """Return a list of items of the given size 'page_size' correlating with 'current_page'.
-
- Args:
- page_size: Maximal number of records to return.
- current_page: The current page of results to return.
-
- Returns:
- A list of items.
- """
- raise NotImplementedError
-
- async def __call__(self, page_size: int, current_page: int) -> ClassicPagination[T]:
- """Return a paginated result set.
-
- Args:
- page_size: Maximal number of records to return.
- current_page: The current page of results to return.
-
- Returns:
- A paginated result set.
- """
- total_pages = await self.get_total(page_size=page_size)
-
- items = await self.get_items(page_size=page_size, current_page=current_page)
-
- return ClassicPagination[T](
- items=items, total_pages=total_pages, page_size=page_size, current_page=current_page
- )
-
-
-class AbstractSyncOffsetPaginator(ABC, Generic[T]):
- """Base paginator class for limit / offset pagination.
-
- Implement this class to return paginated result sets using the limit / offset pagination scheme.
- """
-
- @abstractmethod
- def get_total(self) -> int:
- """Return the total number of records.
-
- Returns:
- An integer.
- """
- raise NotImplementedError
-
- @abstractmethod
- def get_items(self, limit: int, offset: int) -> list[T]:
- """Return a list of items of the given size 'limit' starting from position 'offset'.
-
- Args:
- limit: Maximal number of records to return.
- offset: Starting position within the result set (assume index 0 as starting position).
-
- Returns:
- A list of items.
- """
- raise NotImplementedError
-
- def __call__(self, limit: int, offset: int) -> OffsetPagination[T]:
- """Return a paginated result set.
-
- Args:
- limit: Maximal number of records to return.
- offset: Starting position within the result set (assume index 0 as starting position).
-
- Returns:
- A paginated result set.
- """
- total = self.get_total()
-
- items = self.get_items(limit=limit, offset=offset)
-
- return OffsetPagination[T](items=items, total=total, offset=offset, limit=limit)
-
-
-class AbstractAsyncOffsetPaginator(ABC, Generic[T]):
- """Base paginator class for limit / offset pagination.
-
- Implement this class to return paginated result sets using the limit / offset pagination scheme.
- """
-
- @abstractmethod
- async def get_total(self) -> int:
- """Return the total number of records.
-
- Returns:
- An integer.
- """
- raise NotImplementedError
-
- @abstractmethod
- async def get_items(self, limit: int, offset: int) -> list[T]:
- """Return a list of items of the given size 'limit' starting from position 'offset'.
-
- Args:
- limit: Maximal number of records to return.
- offset: Starting position within the result set (assume index 0 as starting position).
-
- Returns:
- A list of items.
- """
- raise NotImplementedError
-
- async def __call__(self, limit: int, offset: int) -> OffsetPagination[T]:
- """Return a paginated result set.
-
- Args:
- limit: Maximal number of records to return.
- offset: Starting position within the result set (assume index 0 as starting position).
-
- Returns:
- A paginated result set.
- """
- total = await self.get_total()
- items = await self.get_items(limit=limit, offset=offset)
-
- return OffsetPagination[T](items=items, total=total, offset=offset, limit=limit)
-
-
-class AbstractSyncCursorPaginator(ABC, Generic[C, T]):
- """Base paginator class for sync cursor pagination.
-
- Implement this class to return paginated result sets using the cursor pagination scheme.
- """
-
- @abstractmethod
- def get_items(self, cursor: C | None, results_per_page: int) -> tuple[list[T], C | None]:
- """Return a list of items of the size 'results_per_page' following the given cursor, if any,
-
- Args:
- cursor: A unique identifier that acts as the 'cursor' after which results should be given.
- results_per_page: A maximal number of results to return.
-
- Returns:
- A tuple containing the result set and a new cursor that marks the last record retrieved.
- The new cursor can be used to ask for the 'next_cursor' batch of results.
- """
- raise NotImplementedError
-
- def __call__(self, cursor: C | None, results_per_page: int) -> CursorPagination[C, T]:
- """Return a paginated result set given an optional cursor (unique ID) and a maximal number of results to return.
-
- Args:
- cursor: A unique identifier that acts as the 'cursor' after which results should be given.
- results_per_page: A maximal number of results to return.
-
- Returns:
- A paginated result set.
- """
- items, new_cursor = self.get_items(cursor=cursor, results_per_page=results_per_page)
-
- return CursorPagination[C, T](
- items=items,
- results_per_page=results_per_page,
- cursor=new_cursor,
- )
-
-
-class AbstractAsyncCursorPaginator(ABC, Generic[C, T]):
- """Base paginator class for async cursor pagination.
-
- Implement this class to return paginated result sets using the cursor pagination scheme.
- """
-
- @abstractmethod
- async def get_items(self, cursor: C | None, results_per_page: int) -> tuple[list[T], C | None]:
- """Return a list of items of the size 'results_per_page' following the given cursor, if any,
-
- Args:
- cursor: A unique identifier that acts as the 'cursor' after which results should be given.
- results_per_page: A maximal number of results to return.
-
- Returns:
- A tuple containing the result set and a new cursor that marks the last record retrieved.
- The new cursor can be used to ask for the 'next_cursor' batch of results.
- """
- raise NotImplementedError
-
- async def __call__(self, cursor: C | None, results_per_page: int) -> CursorPagination[C, T]:
- """Return a paginated result set given an optional cursor (unique ID) and a maximal number of results to return.
-
- Args:
- cursor: A unique identifier that acts as the 'cursor' after which results should be given.
- results_per_page: A maximal number of results to return.
-
- Returns:
- A paginated result set.
- """
- items, new_cursor = await self.get_items(cursor=cursor, results_per_page=results_per_page)
-
- return CursorPagination[C, T](
- items=items,
- results_per_page=results_per_page,
- cursor=new_cursor,
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/params.py b/venv/lib/python3.11/site-packages/litestar/params.py
deleted file mode 100644
index bff010b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/params.py
+++ /dev/null
@@ -1,383 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import asdict, dataclass, field
-from typing import TYPE_CHECKING, Any, Hashable, Sequence
-
-from litestar.enums import RequestEncodingType
-from litestar.types import Empty
-
-__all__ = (
- "Body",
- "BodyKwarg",
- "Dependency",
- "DependencyKwarg",
- "KwargDefinition",
- "Parameter",
- "ParameterKwarg",
-)
-
-
-if TYPE_CHECKING:
- from litestar.openapi.spec.example import Example
- from litestar.openapi.spec.external_documentation import (
- ExternalDocumentation,
- )
-
-
-@dataclass(frozen=True)
-class KwargDefinition:
- """Data container representing a constrained kwarg."""
-
- examples: list[Example] | None = field(default=None)
- """A list of Example models."""
- external_docs: ExternalDocumentation | None = field(default=None)
- """A url pointing at external documentation for the given parameter."""
- content_encoding: str | None = field(default=None)
- """The content encoding of the value.
-
- Applicable on to string values. See OpenAPI 3.1 for details.
- """
- default: Any = field(default=Empty)
- """A default value.
-
- If const is true, this value is required.
- """
- title: str | None = field(default=None)
- """String value used in the title section of the OpenAPI schema for the given parameter."""
- description: str | None = field(default=None)
- """String value used in the description section of the OpenAPI schema for the given parameter."""
- const: bool | None = field(default=None)
- """A boolean flag dictating whether this parameter is a constant.
-
- If True, the value passed to the parameter must equal its default value. This also causes the OpenAPI const field to
- be populated with the default value.
- """
- gt: float | None = field(default=None)
- """Constrict value to be greater than a given float or int.
-
- Equivalent to exclusiveMinimum in the OpenAPI specification.
- """
- ge: float | None = field(default=None)
- """Constrict value to be greater or equal to a given float or int.
-
- Equivalent to minimum in the OpenAPI specification.
- """
- lt: float | None = field(default=None)
- """Constrict value to be less than a given float or int.
-
- Equivalent to exclusiveMaximum in the OpenAPI specification.
- """
- le: float | None = field(default=None)
- """Constrict value to be less or equal to a given float or int.
-
- Equivalent to maximum in the OpenAPI specification.
- """
- multiple_of: float | None = field(default=None)
- """Constrict value to a multiple of a given float or int.
-
- Equivalent to multipleOf in the OpenAPI specification.
- """
- min_items: int | None = field(default=None)
- """Constrict a set or a list to have a minimum number of items.
-
- Equivalent to minItems in the OpenAPI specification.
- """
- max_items: int | None = field(default=None)
- """Constrict a set or a list to have a maximum number of items.
-
- Equivalent to maxItems in the OpenAPI specification.
- """
- min_length: int | None = field(default=None)
- """Constrict a string or bytes value to have a minimum length.
-
- Equivalent to minLength in the OpenAPI specification.
- """
- max_length: int | None = field(default=None)
- """Constrict a string or bytes value to have a maximum length.
-
- Equivalent to maxLength in the OpenAPI specification.
- """
- pattern: str | None = field(default=None)
- """A string representing a regex against which the given string will be matched.
-
- Equivalent to pattern in the OpenAPI specification.
- """
- lower_case: bool | None = field(default=None)
- """Constrict a string value to be lower case."""
- upper_case: bool | None = field(default=None)
- """Constrict a string value to be upper case."""
- format: str | None = field(default=None)
- """Specify the format to which a string value should be converted."""
- enum: Sequence[Any] | None = field(default=None)
- """A sequence of valid values."""
- read_only: bool | None = field(default=None)
- """A boolean flag dictating whether this parameter is read only."""
-
- @property
- def is_constrained(self) -> bool:
- """Return True if any of the constraints are set."""
- return any(
- attr if attr and attr is not Empty else False # type: ignore[comparison-overlap]
- for attr in (
- self.gt,
- self.ge,
- self.lt,
- self.le,
- self.multiple_of,
- self.min_items,
- self.max_items,
- self.min_length,
- self.max_length,
- self.pattern,
- self.const,
- self.lower_case,
- self.upper_case,
- )
- )
-
-
-@dataclass(frozen=True)
-class ParameterKwarg(KwargDefinition):
- """Data container representing a parameter."""
-
- annotation: Any = field(default=Empty)
- """The field value - `Empty` by default."""
- header: str | None = field(default=None)
- """The header parameter key - required for header parameters."""
- cookie: str | None = field(default=None)
- """The cookie parameter key - required for cookie parameters."""
- query: str | None = field(default=None)
- """The query parameter key for this parameter."""
- required: bool | None = field(default=None)
- """A boolean flag dictating whether this parameter is required.
-
- If set to False, None values will be allowed. Defaults to True.
- """
-
- def __hash__(self) -> int: # pragma: no cover
- """Hash the dataclass in a safe way.
-
- Returns:
- A hash
- """
- return sum(hash(v) for v in asdict(self) if isinstance(v, Hashable))
-
-
-def Parameter(
- annotation: Any = Empty,
- *,
- const: bool | None = None,
- content_encoding: str | None = None,
- cookie: str | None = None,
- default: Any = Empty,
- description: str | None = None,
- examples: list[Example] | None = None,
- external_docs: ExternalDocumentation | None = None,
- ge: float | None = None,
- gt: float | None = None,
- header: str | None = None,
- le: float | None = None,
- lt: float | None = None,
- max_items: int | None = None,
- max_length: int | None = None,
- min_items: int | None = None,
- min_length: int | None = None,
- multiple_of: float | None = None,
- pattern: str | None = None,
- query: str | None = None,
- required: bool | None = None,
- title: str | None = None,
-) -> Any:
- """Create an extended parameter kwarg definition.
-
- Args:
- annotation: `Empty` by default.
- const: A boolean flag dictating whether this parameter is a constant. If True, the value passed to the parameter
- must equal its default value. This also causes the OpenAPI const field
- to be populated with the default value.
- content_encoding: The content encoding of the value.
- Applicable on to string values. See OpenAPI 3.1 for details.
- cookie: The cookie parameter key - required for cookie parameters.
- default: A default value. If const is true, this value is required.
- description: String value used in the description section of the OpenAPI schema for the given parameter.
- examples: A list of Example models.
- external_docs: A url pointing at external documentation for the given parameter.
- ge: Constrict value to be greater or equal to a given float or int.
- Equivalent to minimum in the OpenAPI specification.
- gt: Constrict value to be greater than a given float or int.
- Equivalent to exclusiveMinimum in the OpenAPI specification.
- header: The header parameter key - required for header parameters.
- le: Constrict value to be less or equal to a given float or int.
- Equivalent to maximum in the OpenAPI specification.
- lt: Constrict value to be less than a given float or int.
- Equivalent to exclusiveMaximum in the OpenAPI specification.
- max_items: Constrict a set or a list to have a maximum number of items.
- Equivalent to maxItems in the OpenAPI specification.
- max_length: Constrict a string or bytes value to have a maximum length.
- Equivalent to maxLength in the OpenAPI specification.
- min_items: Constrict a set or a list to have a minimum number of items. Ö¿
- Equivalent to minItems in the OpenAPI specification.
- min_length: Constrict a string or bytes value to have a minimum length.
- Equivalent to minLength in the OpenAPI specification.
- multiple_of: Constrict value to a multiple of a given float or int.
- Equivalent to multipleOf in the OpenAPI specification.
- pattern: A string representing a regex against which the given string will be matched.
- Equivalent to pattern in the OpenAPI specification.
- query: The query parameter key for this parameter.
- required: A boolean flag dictating whether this parameter is required.
- If set to False, None values will be allowed. Defaults to True.
- title: String value used in the title section of the OpenAPI schema for the given parameter.
- """
- return ParameterKwarg(
- annotation=annotation,
- header=header,
- cookie=cookie,
- query=query,
- examples=examples,
- external_docs=external_docs,
- content_encoding=content_encoding,
- required=required,
- default=default,
- title=title,
- description=description,
- const=const,
- gt=gt,
- ge=ge,
- lt=lt,
- le=le,
- multiple_of=multiple_of,
- min_items=min_items,
- max_items=max_items,
- min_length=min_length,
- max_length=max_length,
- pattern=pattern,
- )
-
-
-@dataclass(frozen=True)
-class BodyKwarg(KwargDefinition):
- """Data container representing a request body."""
-
- media_type: str | RequestEncodingType = field(default=RequestEncodingType.JSON)
- """Media-Type of the body."""
-
- multipart_form_part_limit: int | None = field(default=None)
- """The maximal number of allowed parts in a multipart/formdata request. This limit is intended to protect from DoS attacks."""
-
- def __hash__(self) -> int: # pragma: no cover
- """Hash the dataclass in a safe way.
-
- Returns:
- A hash
- """
- return sum(hash(v) for v in asdict(self) if isinstance(v, Hashable))
-
-
-def Body(
- *,
- const: bool | None = None,
- content_encoding: str | None = None,
- default: Any = Empty,
- description: str | None = None,
- examples: list[Example] | None = None,
- external_docs: ExternalDocumentation | None = None,
- ge: float | None = None,
- gt: float | None = None,
- le: float | None = None,
- lt: float | None = None,
- max_items: int | None = None,
- max_length: int | None = None,
- media_type: str | RequestEncodingType = RequestEncodingType.JSON,
- min_items: int | None = None,
- min_length: int | None = None,
- multipart_form_part_limit: int | None = None,
- multiple_of: float | None = None,
- pattern: str | None = None,
- title: str | None = None,
-) -> Any:
- """Create an extended request body kwarg definition.
-
- Args:
- const: A boolean flag dictating whether this parameter is a constant. If True, the value passed to the parameter
- must equal its default value. This also causes the OpenAPI const field to be
- populated with the default value.
- content_encoding: The content encoding of the value. Applicable on to string values.
- See OpenAPI 3.1 for details.
- default: A default value. If const is true, this value is required.
- description: String value used in the description section of the OpenAPI schema for the given parameter.
- examples: A list of Example models.
- external_docs: A url pointing at external documentation for the given parameter.
- ge: Constrict value to be greater or equal to a given float or int.
- Equivalent to minimum in the OpenAPI specification.
- gt: Constrict value to be greater than a given float or int.
- Equivalent to exclusiveMinimum in the OpenAPI specification.
- le: Constrict value to be less or equal to a given float or int.
- Equivalent to maximum in the OpenAPI specification.
- lt: Constrict value to be less than a given float or int.
- Equivalent to exclusiveMaximum in the OpenAPI specification.
- max_items: Constrict a set or a list to have a maximum number of items.
- Equivalent to maxItems in the OpenAPI specification.
- max_length: Constrict a string or bytes value to have a maximum length.
- Equivalent to maxLength in the OpenAPI specification.
- media_type: Defaults to RequestEncodingType.JSON.
- min_items: Constrict a set or a list to have a minimum number of items.
- Equivalent to minItems in the OpenAPI specification.
- min_length: Constrict a string or bytes value to have a minimum length.
- Equivalent to minLength in the OpenAPI specification.
- multipart_form_part_limit: The maximal number of allowed parts in a multipart/formdata request.
- This limit is intended to protect from DoS attacks.
- multiple_of: Constrict value to a multiple of a given float or int.
- Equivalent to multipleOf in the OpenAPI specification.
- pattern: A string representing a regex against which the given string will be matched.
- Equivalent to pattern in the OpenAPI specification.
- title: String value used in the title section of the OpenAPI schema for the given parameter.
- """
- return BodyKwarg(
- media_type=media_type,
- examples=examples,
- external_docs=external_docs,
- content_encoding=content_encoding,
- default=default,
- title=title,
- description=description,
- const=const,
- gt=gt,
- ge=ge,
- lt=lt,
- le=le,
- multiple_of=multiple_of,
- min_items=min_items,
- max_items=max_items,
- min_length=min_length,
- max_length=max_length,
- pattern=pattern,
- multipart_form_part_limit=multipart_form_part_limit,
- )
-
-
-@dataclass(frozen=True)
-class DependencyKwarg:
- """Data container representing a dependency."""
-
- default: Any = field(default=Empty)
- """A default value."""
- skip_validation: bool = field(default=False)
- """Flag dictating whether to skip validation."""
-
- def __hash__(self) -> int:
- """Hash the dataclass in a safe way.
-
- Returns:
- A hash
- """
- return sum(hash(v) for v in asdict(self) if isinstance(v, Hashable))
-
-
-def Dependency(*, default: Any = Empty, skip_validation: bool = False) -> Any:
- """Create a dependency kwarg definition.
-
- Args:
- default: A default value to use in case a dependency is not provided.
- skip_validation: If `True` provided dependency values are not validated by signature model.
- """
- return DependencyKwarg(default=default, skip_validation=skip_validation)
diff --git a/venv/lib/python3.11/site-packages/litestar/plugins/__init__.py b/venv/lib/python3.11/site-packages/litestar/plugins/__init__.py
deleted file mode 100644
index f093104..0000000
--- a/venv/lib/python3.11/site-packages/litestar/plugins/__init__.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from litestar.plugins.base import (
- CLIPlugin,
- CLIPluginProtocol,
- DIPlugin,
- InitPluginProtocol,
- OpenAPISchemaPlugin,
- OpenAPISchemaPluginProtocol,
- PluginProtocol,
- PluginRegistry,
- SerializationPluginProtocol,
-)
-
-__all__ = (
- "SerializationPluginProtocol",
- "DIPlugin",
- "CLIPlugin",
- "InitPluginProtocol",
- "OpenAPISchemaPluginProtocol",
- "OpenAPISchemaPlugin",
- "PluginProtocol",
- "CLIPluginProtocol",
- "PluginRegistry",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index e547c6a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/base.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/base.cpython-311.pyc
deleted file mode 100644
index 582d144..0000000
--- a/venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/base.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/core.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/core.cpython-311.pyc
deleted file mode 100644
index d197b7e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/core.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/sqlalchemy.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/sqlalchemy.cpython-311.pyc
deleted file mode 100644
index 2b9ab93..0000000
--- a/venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/sqlalchemy.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/structlog.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/structlog.cpython-311.pyc
deleted file mode 100644
index e575d1b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/plugins/__pycache__/structlog.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/plugins/base.py b/venv/lib/python3.11/site-packages/litestar/plugins/base.py
deleted file mode 100644
index afc571e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/plugins/base.py
+++ /dev/null
@@ -1,323 +0,0 @@
-from __future__ import annotations
-
-import abc
-from contextlib import contextmanager
-from typing import TYPE_CHECKING, Any, Iterator, Protocol, TypeVar, Union, cast, runtime_checkable
-
-if TYPE_CHECKING:
- from inspect import Signature
-
- from click import Group
-
- from litestar._openapi.schema_generation import SchemaCreator
- from litestar.app import Litestar
- from litestar.config.app import AppConfig
- from litestar.dto import AbstractDTO
- from litestar.openapi.spec import Schema
- from litestar.routes import BaseRoute
- from litestar.typing import FieldDefinition
-
-__all__ = (
- "SerializationPluginProtocol",
- "InitPluginProtocol",
- "OpenAPISchemaPluginProtocol",
- "OpenAPISchemaPlugin",
- "PluginProtocol",
- "CLIPlugin",
- "CLIPluginProtocol",
- "PluginRegistry",
- "DIPlugin",
-)
-
-
-@runtime_checkable
-class InitPluginProtocol(Protocol):
- """Protocol used to define plugins that affect the application's init process."""
-
- __slots__ = ()
-
- def on_app_init(self, app_config: AppConfig) -> AppConfig:
- """Receive the :class:`AppConfig<.config.app.AppConfig>` instance after `on_app_init` hooks have been called.
-
- Examples:
- .. code-block:: python
-
- from litestar import Litestar, get
- from litestar.di import Provide
- from litestar.plugins import InitPluginProtocol
-
-
- def get_name() -> str:
- return "world"
-
-
- @get("/my-path")
- def my_route_handler(name: str) -> dict[str, str]:
- return {"hello": name}
-
-
- class MyPlugin(InitPluginProtocol):
- def on_app_init(self, app_config: AppConfig) -> AppConfig:
- app_config.dependencies["name"] = Provide(get_name)
- app_config.route_handlers.append(my_route_handler)
- return app_config
-
-
- app = Litestar(plugins=[MyPlugin()])
-
- Args:
- app_config: The :class:`AppConfig <litestar.config.app.AppConfig>` instance.
-
- Returns:
- The app config object.
- """
- return app_config # pragma: no cover
-
-
-class ReceiveRoutePlugin:
- """Receive routes as they are added to the application."""
-
- __slots__ = ()
-
- def receive_route(self, route: BaseRoute) -> None:
- """Receive routes as they are registered on an application."""
-
-
-@runtime_checkable
-class CLIPluginProtocol(Protocol):
- """Plugin protocol to extend the CLI."""
-
- __slots__ = ()
-
- def on_cli_init(self, cli: Group) -> None:
- """Called when the CLI is initialized.
-
- This can be used to extend or override existing commands.
-
- Args:
- cli: The root :class:`click.Group` of the Litestar CLI
-
- Examples:
- .. code-block:: python
-
- from litestar import Litestar
- from litestar.plugins import CLIPluginProtocol
- from click import Group
-
-
- class CLIPlugin(CLIPluginProtocol):
- def on_cli_init(self, cli: Group) -> None:
- @cli.command()
- def is_debug_mode(app: Litestar):
- print(app.debug)
-
-
- app = Litestar(plugins=[CLIPlugin()])
- """
-
-
-class CLIPlugin(CLIPluginProtocol):
- """Plugin protocol to extend the CLI Server Lifespan."""
-
- __slots__ = ()
-
- def on_cli_init(self, cli: Group) -> None:
- return super().on_cli_init(cli)
-
- @contextmanager
- def server_lifespan(self, app: Litestar) -> Iterator[None]:
- yield
-
-
-@runtime_checkable
-class SerializationPluginProtocol(Protocol):
- """Protocol used to define a serialization plugin for DTOs."""
-
- __slots__ = ()
-
- def supports_type(self, field_definition: FieldDefinition) -> bool:
- """Given a value of indeterminate type, determine if this value is supported by the plugin.
-
- Args:
- field_definition: A parsed type.
-
- Returns:
- Whether the type is supported by the plugin.
- """
- raise NotImplementedError()
-
- def create_dto_for_type(self, field_definition: FieldDefinition) -> type[AbstractDTO]:
- """Given a parsed type, create a DTO class.
-
- Args:
- field_definition: A parsed type.
-
- Returns:
- A DTO class.
- """
- raise NotImplementedError()
-
-
-class DIPlugin(abc.ABC):
- """Extend dependency injection"""
-
- @abc.abstractmethod
- def has_typed_init(self, type_: Any) -> bool:
- """Return ``True`` if ``type_`` has type information available for its
- :func:`__init__` method that cannot be extracted from this method's type
- annotations (e.g. a Pydantic BaseModel subclass), and
- :meth:`DIPlugin.get_typed_init` supports extraction of these annotations.
- """
- ...
-
- @abc.abstractmethod
- def get_typed_init(self, type_: Any) -> tuple[Signature, dict[str, Any]]:
- r"""Return signature and type information about the ``type_``\ s :func:`__init__`
- method.
- """
- ...
-
-
-@runtime_checkable
-class OpenAPISchemaPluginProtocol(Protocol):
- """Plugin protocol to extend the support of OpenAPI schema generation for non-library types."""
-
- __slots__ = ()
-
- @staticmethod
- def is_plugin_supported_type(value: Any) -> bool:
- """Given a value of indeterminate type, determine if this value is supported by the plugin.
-
- Args:
- value: An arbitrary value.
-
- Returns:
- A typeguard dictating whether the value is supported by the plugin.
- """
- raise NotImplementedError()
-
- def to_openapi_schema(self, field_definition: FieldDefinition, schema_creator: SchemaCreator) -> Schema:
- """Given a type annotation, transform it into an OpenAPI schema class.
-
- Args:
- field_definition: An :class:`OpenAPI <litestar.openapi.spec.schema.Schema>` instance.
- schema_creator: An instance of the openapi SchemaCreator.
-
- Returns:
- An :class:`OpenAPI <litestar.openapi.spec.schema.Schema>` instance.
- """
- raise NotImplementedError()
-
-
-class OpenAPISchemaPlugin(OpenAPISchemaPluginProtocol):
- """Plugin to extend the support of OpenAPI schema generation for non-library types."""
-
- @staticmethod
- def is_plugin_supported_type(value: Any) -> bool:
- """Given a value of indeterminate type, determine if this value is supported by the plugin.
-
- This is called by the default implementation of :meth:`is_plugin_supported_field` for
- backwards compatibility. User's should prefer to override that method instead.
-
- Args:
- value: An arbitrary value.
-
- Returns:
- A bool indicating whether the value is supported by the plugin.
- """
- raise NotImplementedError(
- "One of either is_plugin_supported_type or is_plugin_supported_field should be defined. "
- "The default implementation of is_plugin_supported_field calls is_plugin_supported_type "
- "for backwards compatibility. Users should prefer to override is_plugin_supported_field "
- "as it receives a 'FieldDefinition' instance which is more useful than a raw type."
- )
-
- def is_plugin_supported_field(self, field_definition: FieldDefinition) -> bool:
- """Given a :class:`FieldDefinition <litestar.typing.FieldDefinition>` that represents an indeterminate type,
- determine if this value is supported by the plugin
-
- Args:
- field_definition: A parsed type.
-
- Returns:
- Whether the type is supported by the plugin.
- """
- return self.is_plugin_supported_type(field_definition.annotation)
-
- @staticmethod
- def is_undefined_sentinel(value: Any) -> bool:
- """Return ``True`` if ``value`` should be treated as an undefined field"""
- return False
-
- @staticmethod
- def is_constrained_field(field_definition: FieldDefinition) -> bool:
- """Return ``True`` if the field should be treated as constrained. If returning
- ``True``, constraints should be defined in the field's extras
- """
- return False
-
-
-PluginProtocol = Union[
- CLIPlugin,
- CLIPluginProtocol,
- InitPluginProtocol,
- OpenAPISchemaPlugin,
- OpenAPISchemaPluginProtocol,
- ReceiveRoutePlugin,
- SerializationPluginProtocol,
- DIPlugin,
-]
-
-PluginT = TypeVar("PluginT", bound=PluginProtocol)
-
-
-class PluginRegistry:
- __slots__ = {
- "init": "Plugins that implement the InitPluginProtocol",
- "openapi": "Plugins that implement the OpenAPISchemaPluginProtocol",
- "receive_route": "ReceiveRoutePlugin instances",
- "serialization": "Plugins that implement the SerializationPluginProtocol",
- "cli": "Plugins that implement the CLIPluginProtocol",
- "di": "DIPlugin instances",
- "_plugins_by_type": None,
- "_plugins": None,
- "_get_plugins_of_type": None,
- }
-
- def __init__(self, plugins: list[PluginProtocol]) -> None:
- self._plugins_by_type = {type(p): p for p in plugins}
- self._plugins = frozenset(plugins)
- self.init = tuple(p for p in plugins if isinstance(p, InitPluginProtocol))
- self.openapi = tuple(p for p in plugins if isinstance(p, OpenAPISchemaPluginProtocol))
- self.receive_route = tuple(p for p in plugins if isinstance(p, ReceiveRoutePlugin))
- self.serialization = tuple(p for p in plugins if isinstance(p, SerializationPluginProtocol))
- self.cli = tuple(p for p in plugins if isinstance(p, CLIPluginProtocol))
- self.di = tuple(p for p in plugins if isinstance(p, DIPlugin))
-
- def get(self, type_: type[PluginT] | str) -> PluginT:
- """Return the registered plugin of ``type_``.
-
- This should be used with subclasses of the plugin protocols.
- """
- if isinstance(type_, str):
- for plugin in self._plugins:
- _name = plugin.__class__.__name__
- _module = plugin.__class__.__module__
- _qualname = (
- f"{_module}.{plugin.__class__.__qualname__}"
- if _module is not None and _module != "__builtin__"
- else plugin.__class__.__qualname__
- )
- if type_ in {_name, _qualname}:
- return cast(PluginT, plugin)
- raise KeyError(f"No plugin of type {type_!r} registered")
- try:
- return cast(PluginT, self._plugins_by_type[type_]) # type: ignore[index]
- except KeyError as e:
- raise KeyError(f"No plugin of type {type_.__name__!r} registered") from e
-
- def __iter__(self) -> Iterator[PluginProtocol]:
- return iter(self._plugins)
-
- def __contains__(self, item: PluginProtocol) -> bool:
- return item in self._plugins
diff --git a/venv/lib/python3.11/site-packages/litestar/plugins/core.py b/venv/lib/python3.11/site-packages/litestar/plugins/core.py
deleted file mode 100644
index d25d6d6..0000000
--- a/venv/lib/python3.11/site-packages/litestar/plugins/core.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from __future__ import annotations
-
-import inspect
-from inspect import Signature
-from typing import Any
-
-import msgspec
-
-from litestar.plugins import DIPlugin
-
-__all__ = ("MsgspecDIPlugin",)
-
-
-class MsgspecDIPlugin(DIPlugin):
- def has_typed_init(self, type_: Any) -> bool:
- return type(type_) is type(msgspec.Struct) # noqa: E721
-
- def get_typed_init(self, type_: Any) -> tuple[Signature, dict[str, Any]]:
- parameters = []
- type_hints = {}
- for field_info in msgspec.structs.fields(type_):
- type_hints[field_info.name] = field_info.type
- parameters.append(
- inspect.Parameter(
- name=field_info.name,
- kind=inspect.Parameter.KEYWORD_ONLY,
- annotation=field_info.type,
- default=field_info.default,
- )
- )
- return inspect.Signature(parameters), type_hints
diff --git a/venv/lib/python3.11/site-packages/litestar/plugins/sqlalchemy.py b/venv/lib/python3.11/site-packages/litestar/plugins/sqlalchemy.py
deleted file mode 100644
index d65d712..0000000
--- a/venv/lib/python3.11/site-packages/litestar/plugins/sqlalchemy.py
+++ /dev/null
@@ -1,54 +0,0 @@
-from advanced_alchemy import filters, types
-from advanced_alchemy.base import (
- AuditColumns,
- BigIntAuditBase,
- BigIntBase,
- BigIntPrimaryKey,
- CommonTableAttributes,
- UUIDAuditBase,
- UUIDBase,
- UUIDPrimaryKey,
- orm_registry,
-)
-from advanced_alchemy.extensions.litestar import (
- AlembicAsyncConfig,
- AlembicCommands,
- AlembicSyncConfig,
- AsyncSessionConfig,
- EngineConfig,
- SQLAlchemyAsyncConfig,
- SQLAlchemyDTO,
- SQLAlchemyDTOConfig,
- SQLAlchemyInitPlugin,
- SQLAlchemyPlugin,
- SQLAlchemySerializationPlugin,
- SQLAlchemySyncConfig,
- SyncSessionConfig,
-)
-
-__all__ = (
- "orm_registry",
- "filters",
- "types",
- "AuditColumns",
- "BigIntAuditBase",
- "BigIntBase",
- "UUIDAuditBase",
- "UUIDPrimaryKey",
- "CommonTableAttributes",
- "UUIDBase",
- "BigIntPrimaryKey",
- "AlembicCommands",
- "AlembicAsyncConfig",
- "AlembicSyncConfig",
- "AsyncSessionConfig",
- "SyncSessionConfig",
- "SQLAlchemyDTO",
- "SQLAlchemyDTOConfig",
- "SQLAlchemyAsyncConfig",
- "SQLAlchemyInitPlugin",
- "SQLAlchemyPlugin",
- "SQLAlchemySerializationPlugin",
- "SQLAlchemySyncConfig",
- "EngineConfig",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/plugins/structlog.py b/venv/lib/python3.11/site-packages/litestar/plugins/structlog.py
deleted file mode 100644
index fafa3dd..0000000
--- a/venv/lib/python3.11/site-packages/litestar/plugins/structlog.py
+++ /dev/null
@@ -1,56 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass, field
-from typing import TYPE_CHECKING
-
-from litestar.cli._utils import console
-from litestar.logging.config import StructLoggingConfig
-from litestar.middleware.logging import LoggingMiddlewareConfig
-from litestar.plugins import InitPluginProtocol
-
-if TYPE_CHECKING:
- from litestar.config.app import AppConfig
-
-
-@dataclass
-class StructlogConfig:
- structlog_logging_config: StructLoggingConfig = field(default_factory=StructLoggingConfig)
- """Structlog Logging configuration for Litestar. See ``litestar.logging.config.StructLoggingConfig``` for details."""
- middleware_logging_config: LoggingMiddlewareConfig = field(default_factory=LoggingMiddlewareConfig)
- """Middleware logging config."""
- enable_middleware_logging: bool = True
- """Enable request logging."""
-
-
-class StructlogPlugin(InitPluginProtocol):
- """Structlog Plugin."""
-
- __slots__ = ("_config",)
-
- def __init__(self, config: StructlogConfig | None = None) -> None:
- if config is None:
- config = StructlogConfig()
- self._config = config
- super().__init__()
-
- def on_app_init(self, app_config: AppConfig) -> AppConfig:
- """Structlog Plugin
-
- Args:
- app_config: The :class:`AppConfig <litestar.config.app.AppConfig>` instance.
-
- Returns:
- The app config object.
- """
- if app_config.logging_config is not None and isinstance(app_config.logging_config, StructLoggingConfig):
- console.print(
- "[red dim]* Found pre-configured `StructLoggingConfig` on the `app` instance. Skipping configuration.[/]",
- )
- else:
- app_config.logging_config = self._config.structlog_logging_config
- app_config.logging_config.configure()
- if self._config.structlog_logging_config.standard_lib_logging_config is not None: # pragma: no cover
- self._config.structlog_logging_config.standard_lib_logging_config.configure() # pragma: no cover
- if self._config.enable_middleware_logging:
- app_config.middleware.append(self._config.middleware_logging_config.middleware)
- return app_config # pragma: no cover
diff --git a/venv/lib/python3.11/site-packages/litestar/py.typed b/venv/lib/python3.11/site-packages/litestar/py.typed
deleted file mode 100644
index e69de29..0000000
--- a/venv/lib/python3.11/site-packages/litestar/py.typed
+++ /dev/null
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/__init__.py b/venv/lib/python3.11/site-packages/litestar/repository/__init__.py
deleted file mode 100644
index 62e3f83..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/__init__.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from __future__ import annotations
-
-from .abc import AbstractAsyncRepository, AbstractSyncRepository
-from .exceptions import ConflictError, NotFoundError, RepositoryError
-from .filters import FilterTypes
-
-__all__ = (
- "AbstractAsyncRepository",
- "AbstractSyncRepository",
- "ConflictError",
- "FilterTypes",
- "NotFoundError",
- "RepositoryError",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/repository/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 42bf9be..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/__pycache__/_exceptions.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/repository/__pycache__/_exceptions.cpython-311.pyc
deleted file mode 100644
index 0f48627..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/__pycache__/_exceptions.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/__pycache__/_filters.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/repository/__pycache__/_filters.cpython-311.pyc
deleted file mode 100644
index 2f16cb4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/__pycache__/_filters.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/__pycache__/exceptions.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/repository/__pycache__/exceptions.cpython-311.pyc
deleted file mode 100644
index 3c9f01e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/__pycache__/exceptions.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/__pycache__/filters.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/repository/__pycache__/filters.cpython-311.pyc
deleted file mode 100644
index 87d90db..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/__pycache__/filters.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/__pycache__/handlers.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/repository/__pycache__/handlers.cpython-311.pyc
deleted file mode 100644
index abe227b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/__pycache__/handlers.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/_exceptions.py b/venv/lib/python3.11/site-packages/litestar/repository/_exceptions.py
deleted file mode 100644
index 1c2b7be..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/_exceptions.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from __future__ import annotations # pragma: no cover
-
-__all__ = ("ConflictError", "NotFoundError", "RepositoryError") # pragma: no cover
-
-
-class RepositoryError(Exception): # pragma: no cover
- """Base repository exception type."""
-
-
-class ConflictError(RepositoryError): # pragma: no cover
- """Data integrity error."""
-
-
-class NotFoundError(RepositoryError): # pragma: no cover
- """An identity does not exist."""
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/_filters.py b/venv/lib/python3.11/site-packages/litestar/repository/_filters.py
deleted file mode 100644
index f6b787e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/_filters.py
+++ /dev/null
@@ -1,117 +0,0 @@
-"""Collection filter datastructures."""
-
-from __future__ import annotations
-
-from collections import abc # noqa: TCH003
-from dataclasses import dataclass
-from datetime import datetime # noqa: TCH003
-from typing import TYPE_CHECKING, Any, Generic, Literal, TypeVar
-
-if TYPE_CHECKING:
- from typing_extensions import TypeAlias
-
-T = TypeVar("T")
-
-__all__ = (
- "BeforeAfter",
- "CollectionFilter",
- "FilterTypes",
- "LimitOffset",
- "OrderBy",
- "SearchFilter",
- "NotInCollectionFilter",
- "OnBeforeAfter",
- "NotInSearchFilter",
-)
-
-
-FilterTypes: TypeAlias = "BeforeAfter | OnBeforeAfter | CollectionFilter[Any] | LimitOffset | OrderBy | SearchFilter | NotInCollectionFilter[Any] | NotInSearchFilter"
-"""Aggregate type alias of the types supported for collection filtering."""
-
-
-@dataclass
-class BeforeAfter:
- """Data required to filter a query on a ``datetime`` column."""
-
- field_name: str
- """Name of the model attribute to filter on."""
- before: datetime | None
- """Filter results where field earlier than this."""
- after: datetime | None
- """Filter results where field later than this."""
-
-
-@dataclass
-class OnBeforeAfter:
- """Data required to filter a query on a ``datetime`` column."""
-
- field_name: str
- """Name of the model attribute to filter on."""
- on_or_before: datetime | None
- """Filter results where field is on or earlier than this."""
- on_or_after: datetime | None
- """Filter results where field on or later than this."""
-
-
-@dataclass
-class CollectionFilter(Generic[T]):
- """Data required to construct a ``WHERE ... IN (...)`` clause."""
-
- field_name: str
- """Name of the model attribute to filter on."""
- values: abc.Collection[T]
- """Values for ``IN`` clause."""
-
-
-@dataclass
-class NotInCollectionFilter(Generic[T]):
- """Data required to construct a ``WHERE ... NOT IN (...)`` clause."""
-
- field_name: str
- """Name of the model attribute to filter on."""
- values: abc.Collection[T]
- """Values for ``NOT IN`` clause."""
-
-
-@dataclass
-class LimitOffset:
- """Data required to add limit/offset filtering to a query."""
-
- limit: int
- """Value for ``LIMIT`` clause of query."""
- offset: int
- """Value for ``OFFSET`` clause of query."""
-
-
-@dataclass
-class OrderBy:
- """Data required to construct a ``ORDER BY ...`` clause."""
-
- field_name: str
- """Name of the model attribute to sort on."""
- sort_order: Literal["asc", "desc"] = "asc"
- """Sort ascending or descending"""
-
-
-@dataclass
-class SearchFilter:
- """Data required to construct a ``WHERE field_name LIKE '%' || :value || '%'`` clause."""
-
- field_name: str
- """Name of the model attribute to sort on."""
- value: str
- """Values for ``LIKE`` clause."""
- ignore_case: bool | None = False
- """Should the search be case insensitive."""
-
-
-@dataclass
-class NotInSearchFilter:
- """Data required to construct a ``WHERE field_name NOT LIKE '%' || :value || '%'`` clause."""
-
- field_name: str
- """Name of the model attribute to search on."""
- value: str
- """Values for ``NOT LIKE`` clause."""
- ignore_case: bool | None = False
- """Should the search be case insensitive."""
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/abc/__init__.py b/venv/lib/python3.11/site-packages/litestar/repository/abc/__init__.py
deleted file mode 100644
index def6bb4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/abc/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from ._async import AbstractAsyncRepository
-from ._sync import AbstractSyncRepository
-
-__all__ = (
- "AbstractAsyncRepository",
- "AbstractSyncRepository",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/abc/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/repository/abc/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 710a74b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/abc/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/abc/__pycache__/_async.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/repository/abc/__pycache__/_async.cpython-311.pyc
deleted file mode 100644
index 24217cc..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/abc/__pycache__/_async.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/abc/__pycache__/_sync.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/repository/abc/__pycache__/_sync.cpython-311.pyc
deleted file mode 100644
index 7a69407..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/abc/__pycache__/_sync.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/abc/_async.py b/venv/lib/python3.11/site-packages/litestar/repository/abc/_async.py
deleted file mode 100644
index 85ca139..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/abc/_async.py
+++ /dev/null
@@ -1,303 +0,0 @@
-from __future__ import annotations
-
-from abc import ABCMeta, abstractmethod
-from typing import TYPE_CHECKING, Any, Generic, TypeVar
-
-from litestar.repository.exceptions import NotFoundError
-
-if TYPE_CHECKING:
- from litestar.repository.filters import FilterTypes
-
-T = TypeVar("T")
-CollectionT = TypeVar("CollectionT")
-
-
-class AbstractAsyncRepository(Generic[T], metaclass=ABCMeta):
- """Interface for persistent data interaction."""
-
- model_type: type[T]
- """Type of object represented by the repository."""
- id_attribute: Any = "id"
- """Name of the primary identifying attribute on :attr:`model_type`."""
-
- def __init__(self, **kwargs: Any) -> None:
- """Repository constructors accept arbitrary kwargs."""
- super().__init__(**kwargs)
-
- @abstractmethod
- async def add(self, data: T) -> T:
- """Add ``data`` to the collection.
-
- Args:
- data: Instance to be added to the collection.
-
- Returns:
- The added instance.
- """
-
- @abstractmethod
- async def add_many(self, data: list[T]) -> list[T]:
- """Add multiple ``data`` to the collection.
-
- Args:
- data: Instances to be added to the collection.
-
- Returns:
- The added instances.
- """
-
- @abstractmethod
- async def count(self, *filters: FilterTypes, **kwargs: Any) -> int:
- """Get the count of records returned by a query.
-
- Args:
- *filters: Types for specific filtering operations.
- **kwargs: Instance attribute value filters.
-
- Returns:
- The count of instances
- """
-
- @abstractmethod
- async def delete(self, item_id: Any) -> T:
- """Delete instance identified by ``item_id``.
-
- Args:
- item_id: Identifier of instance to be deleted.
-
- Returns:
- The deleted instance.
-
- Raises:
- NotFoundError: If no instance found identified by ``item_id``.
- """
-
- @abstractmethod
- async def delete_many(self, item_ids: list[Any]) -> list[T]:
- """Delete multiple instances identified by list of IDs ``item_ids``.
-
- Args:
- item_ids: list of Identifiers to be deleted.
-
- Returns:
- The deleted instances.
- """
-
- @abstractmethod
- async def exists(self, *filters: FilterTypes, **kwargs: Any) -> bool:
- """Return true if the object specified by ``kwargs`` exists.
-
- Args:
- *filters: Types for specific filtering operations.
- **kwargs: Identifier of the instance to be retrieved.
-
- Returns:
- True if the instance was found. False if not found.
-
- """
-
- @abstractmethod
- async def get(self, item_id: Any, **kwargs: Any) -> T:
- """Get instance identified by ``item_id``.
-
- Args:
- item_id: Identifier of the instance to be retrieved.
- **kwargs: Additional arguments
-
- Returns:
- The retrieved instance.
-
- Raises:
- NotFoundError: If no instance found identified by ``item_id``.
- """
-
- @abstractmethod
- async def get_one(self, **kwargs: Any) -> T:
- """Get an instance specified by the ``kwargs`` filters if it exists.
-
- Args:
- **kwargs: Instance attribute value filters.
-
- Returns:
- The retrieved instance.
-
- Raises:
- NotFoundError: If no instance found identified by ``kwargs``.
- """
-
- @abstractmethod
- async def get_or_create(self, **kwargs: Any) -> tuple[T, bool]:
- """Get an instance specified by the ``kwargs`` filters if it exists or create it.
-
- Args:
- **kwargs: Instance attribute value filters.
-
- Returns:
- A tuple that includes the retrieved or created instance, and a boolean on whether the record was created or not
- """
-
- @abstractmethod
- async def get_one_or_none(self, **kwargs: Any) -> T | None:
- """Get an instance if it exists or None.
-
- Args:
- **kwargs: Instance attribute value filters.
-
- Returns:
- The retrieved instance or None.
- """
-
- @abstractmethod
- async def update(self, data: T) -> T:
- """Update instance with the attribute values present on ``data``.
-
- Args:
- data: An instance that should have a value for :attr:`id_attribute <AbstractAsyncRepository.id_attribute>` that exists in the
- collection.
-
- Returns:
- The updated instance.
-
- Raises:
- NotFoundError: If no instance found with same identifier as ``data``.
- """
-
- @abstractmethod
- async def update_many(self, data: list[T]) -> list[T]:
- """Update multiple instances with the attribute values present on instances in ``data``.
-
- Args:
- data: A list of instance that should have a value for :attr:`id_attribute <AbstractAsyncRepository.id_attribute>` that exists in the
- collection.
-
- Returns:
- a list of the updated instances.
-
- Raises:
- NotFoundError: If no instance found with same identifier as ``data``.
- """
-
- @abstractmethod
- async def upsert(self, data: T) -> T:
- """Update or create instance.
-
- Updates instance with the attribute values present on ``data``, or creates a new instance if
- one doesn't exist.
-
- Args:
- data: Instance to update existing, or be created. Identifier used to determine if an
- existing instance exists is the value of an attribute on ``data`` named as value of
- :attr:`id_attribute <AbstractAsyncRepository.id_attribute>`.
-
- Returns:
- The updated or created instance.
-
- Raises:
- NotFoundError: If no instance found with same identifier as ``data``.
- """
-
- @abstractmethod
- async def upsert_many(self, data: list[T]) -> list[T]:
- """Update or create multiple instances.
-
- Update instances with the attribute values present on ``data``, or create a new instance if
- one doesn't exist.
-
- Args:
- data: Instances to update or created. Identifier used to determine if an
- existing instance exists is the value of an attribute on ``data`` named as value of
- :attr:`id_attribute <AbstractAsyncRepository.id_attribute>`.
-
- Returns:
- The updated or created instances.
-
- Raises:
- NotFoundError: If no instance found with same identifier as ``data``.
- """
-
- @abstractmethod
- async def list_and_count(self, *filters: FilterTypes, **kwargs: Any) -> tuple[list[T], int]:
- """List records with total count.
-
- Args:
- *filters: Types for specific filtering operations.
- **kwargs: Instance attribute value filters.
-
- Returns:
- a tuple containing The list of instances, after filtering applied, and a count of records returned by query, ignoring pagination.
- """
-
- @abstractmethod
- async def list(self, *filters: FilterTypes, **kwargs: Any) -> list[T]:
- """Get a list of instances, optionally filtered.
-
- Args:
- *filters: filters for specific filtering operations
- **kwargs: Instance attribute value filters.
-
- Returns:
- The list of instances, after filtering applied
- """
-
- @abstractmethod
- def filter_collection_by_kwargs(self, collection: CollectionT, /, **kwargs: Any) -> CollectionT:
- """Filter the collection by kwargs.
-
- Has ``AND`` semantics where multiple kwargs name/value pairs are provided.
-
- Args:
- collection: the objects to be filtered
- **kwargs: key/value pairs such that objects remaining in the collection after filtering
- have the property that their attribute named ``key`` has value equal to ``value``.
-
-
- Returns:
- The filtered objects
-
- Raises:
- RepositoryError: if a named attribute doesn't exist on :attr:`model_type <AbstractAsyncRepository.model_type>`.
- """
-
- @staticmethod
- def check_not_found(item_or_none: T | None) -> T:
- """Raise :class:`NotFoundError` if ``item_or_none`` is ``None``.
-
- Args:
- item_or_none: Item (:class:`T <T>`) to be tested for existence.
-
- Returns:
- The item, if it exists.
- """
- if item_or_none is None:
- raise NotFoundError("No item found when one was expected")
- return item_or_none
-
- @classmethod
- def get_id_attribute_value(cls, item: T | type[T], id_attribute: str | None = None) -> Any:
- """Get value of attribute named as :attr:`id_attribute <AbstractAsyncRepository.id_attribute>` on ``item``.
-
- Args:
- item: Anything that should have an attribute named as :attr:`id_attribute <AbstractAsyncRepository.id_attribute>` value.
- id_attribute: Allows customization of the unique identifier to use for model fetching.
- Defaults to `None`, but can reference any surrogate or candidate key for the table.
-
- Returns:
- The value of attribute on ``item`` named as :attr:`id_attribute <AbstractAsyncRepository.id_attribute>`.
- """
- return getattr(item, id_attribute if id_attribute is not None else cls.id_attribute)
-
- @classmethod
- def set_id_attribute_value(cls, item_id: Any, item: T, id_attribute: str | None = None) -> T:
- """Return the ``item`` after the ID is set to the appropriate attribute.
-
- Args:
- item_id: Value of ID to be set on instance
- item: Anything that should have an attribute named as :attr:`id_attribute <AbstractAsyncRepository.id_attribute>` value.
- id_attribute: Allows customization of the unique identifier to use for model fetching.
- Defaults to `None`, but can reference any surrogate or candidate key for the table.
-
- Returns:
- Item with ``item_id`` set to :attr:`id_attribute <AbstractAsyncRepository.id_attribute>`
- """
- setattr(item, id_attribute if id_attribute is not None else cls.id_attribute, item_id)
- return item
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/abc/_sync.py b/venv/lib/python3.11/site-packages/litestar/repository/abc/_sync.py
deleted file mode 100644
index d667fc2..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/abc/_sync.py
+++ /dev/null
@@ -1,305 +0,0 @@
-# Do not edit this file directly. It has been autogenerated from
-# litestar/repository/abc/_async.py
-from __future__ import annotations
-
-from abc import ABCMeta, abstractmethod
-from typing import TYPE_CHECKING, Any, Generic, TypeVar
-
-from litestar.repository.exceptions import NotFoundError
-
-if TYPE_CHECKING:
- from litestar.repository.filters import FilterTypes
-
-T = TypeVar("T")
-CollectionT = TypeVar("CollectionT")
-
-
-class AbstractSyncRepository(Generic[T], metaclass=ABCMeta):
- """Interface for persistent data interaction."""
-
- model_type: type[T]
- """Type of object represented by the repository."""
- id_attribute: Any = "id"
- """Name of the primary identifying attribute on :attr:`model_type`."""
-
- def __init__(self, **kwargs: Any) -> None:
- """Repository constructors accept arbitrary kwargs."""
- super().__init__(**kwargs)
-
- @abstractmethod
- def add(self, data: T) -> T:
- """Add ``data`` to the collection.
-
- Args:
- data: Instance to be added to the collection.
-
- Returns:
- The added instance.
- """
-
- @abstractmethod
- def add_many(self, data: list[T]) -> list[T]:
- """Add multiple ``data`` to the collection.
-
- Args:
- data: Instances to be added to the collection.
-
- Returns:
- The added instances.
- """
-
- @abstractmethod
- def count(self, *filters: FilterTypes, **kwargs: Any) -> int:
- """Get the count of records returned by a query.
-
- Args:
- *filters: Types for specific filtering operations.
- **kwargs: Instance attribute value filters.
-
- Returns:
- The count of instances
- """
-
- @abstractmethod
- def delete(self, item_id: Any) -> T:
- """Delete instance identified by ``item_id``.
-
- Args:
- item_id: Identifier of instance to be deleted.
-
- Returns:
- The deleted instance.
-
- Raises:
- NotFoundError: If no instance found identified by ``item_id``.
- """
-
- @abstractmethod
- def delete_many(self, item_ids: list[Any]) -> list[T]:
- """Delete multiple instances identified by list of IDs ``item_ids``.
-
- Args:
- item_ids: list of Identifiers to be deleted.
-
- Returns:
- The deleted instances.
- """
-
- @abstractmethod
- def exists(self, *filters: FilterTypes, **kwargs: Any) -> bool:
- """Return true if the object specified by ``kwargs`` exists.
-
- Args:
- *filters: Types for specific filtering operations.
- **kwargs: Identifier of the instance to be retrieved.
-
- Returns:
- True if the instance was found. False if not found.
-
- """
-
- @abstractmethod
- def get(self, item_id: Any, **kwargs: Any) -> T:
- """Get instance identified by ``item_id``.
-
- Args:
- item_id: Identifier of the instance to be retrieved.
- **kwargs: Additional arguments
-
- Returns:
- The retrieved instance.
-
- Raises:
- NotFoundError: If no instance found identified by ``item_id``.
- """
-
- @abstractmethod
- def get_one(self, **kwargs: Any) -> T:
- """Get an instance specified by the ``kwargs`` filters if it exists.
-
- Args:
- **kwargs: Instance attribute value filters.
-
- Returns:
- The retrieved instance.
-
- Raises:
- NotFoundError: If no instance found identified by ``kwargs``.
- """
-
- @abstractmethod
- def get_or_create(self, **kwargs: Any) -> tuple[T, bool]:
- """Get an instance specified by the ``kwargs`` filters if it exists or create it.
-
- Args:
- **kwargs: Instance attribute value filters.
-
- Returns:
- A tuple that includes the retrieved or created instance, and a boolean on whether the record was created or not
- """
-
- @abstractmethod
- def get_one_or_none(self, **kwargs: Any) -> T | None:
- """Get an instance if it exists or None.
-
- Args:
- **kwargs: Instance attribute value filters.
-
- Returns:
- The retrieved instance or None.
- """
-
- @abstractmethod
- def update(self, data: T) -> T:
- """Update instance with the attribute values present on ``data``.
-
- Args:
- data: An instance that should have a value for :attr:`id_attribute <AbstractAsyncRepository.id_attribute>` that exists in the
- collection.
-
- Returns:
- The updated instance.
-
- Raises:
- NotFoundError: If no instance found with same identifier as ``data``.
- """
-
- @abstractmethod
- def update_many(self, data: list[T]) -> list[T]:
- """Update multiple instances with the attribute values present on instances in ``data``.
-
- Args:
- data: A list of instance that should have a value for :attr:`id_attribute <AbstractAsyncRepository.id_attribute>` that exists in the
- collection.
-
- Returns:
- a list of the updated instances.
-
- Raises:
- NotFoundError: If no instance found with same identifier as ``data``.
- """
-
- @abstractmethod
- def upsert(self, data: T) -> T:
- """Update or create instance.
-
- Updates instance with the attribute values present on ``data``, or creates a new instance if
- one doesn't exist.
-
- Args:
- data: Instance to update existing, or be created. Identifier used to determine if an
- existing instance exists is the value of an attribute on ``data`` named as value of
- :attr:`id_attribute <AbstractAsyncRepository.id_attribute>`.
-
- Returns:
- The updated or created instance.
-
- Raises:
- NotFoundError: If no instance found with same identifier as ``data``.
- """
-
- @abstractmethod
- def upsert_many(self, data: list[T]) -> list[T]:
- """Update or create multiple instances.
-
- Update instances with the attribute values present on ``data``, or create a new instance if
- one doesn't exist.
-
- Args:
- data: Instances to update or created. Identifier used to determine if an
- existing instance exists is the value of an attribute on ``data`` named as value of
- :attr:`id_attribute <AbstractAsyncRepository.id_attribute>`.
-
- Returns:
- The updated or created instances.
-
- Raises:
- NotFoundError: If no instance found with same identifier as ``data``.
- """
-
- @abstractmethod
- def list_and_count(self, *filters: FilterTypes, **kwargs: Any) -> tuple[list[T], int]:
- """List records with total count.
-
- Args:
- *filters: Types for specific filtering operations.
- **kwargs: Instance attribute value filters.
-
- Returns:
- a tuple containing The list of instances, after filtering applied, and a count of records returned by query, ignoring pagination.
- """
-
- @abstractmethod
- def list(self, *filters: FilterTypes, **kwargs: Any) -> list[T]:
- """Get a list of instances, optionally filtered.
-
- Args:
- *filters: filters for specific filtering operations
- **kwargs: Instance attribute value filters.
-
- Returns:
- The list of instances, after filtering applied
- """
-
- @abstractmethod
- def filter_collection_by_kwargs(self, collection: CollectionT, /, **kwargs: Any) -> CollectionT:
- """Filter the collection by kwargs.
-
- Has ``AND`` semantics where multiple kwargs name/value pairs are provided.
-
- Args:
- collection: the objects to be filtered
- **kwargs: key/value pairs such that objects remaining in the collection after filtering
- have the property that their attribute named ``key`` has value equal to ``value``.
-
-
- Returns:
- The filtered objects
-
- Raises:
- RepositoryError: if a named attribute doesn't exist on :attr:`model_type <AbstractAsyncRepository.model_type>`.
- """
-
- @staticmethod
- def check_not_found(item_or_none: T | None) -> T:
- """Raise :class:`NotFoundError` if ``item_or_none`` is ``None``.
-
- Args:
- item_or_none: Item (:class:`T <T>`) to be tested for existence.
-
- Returns:
- The item, if it exists.
- """
- if item_or_none is None:
- raise NotFoundError("No item found when one was expected")
- return item_or_none
-
- @classmethod
- def get_id_attribute_value(cls, item: T | type[T], id_attribute: str | None = None) -> Any:
- """Get value of attribute named as :attr:`id_attribute <AbstractAsyncRepository.id_attribute>` on ``item``.
-
- Args:
- item: Anything that should have an attribute named as :attr:`id_attribute <AbstractAsyncRepository.id_attribute>` value.
- id_attribute: Allows customization of the unique identifier to use for model fetching.
- Defaults to `None`, but can reference any surrogate or candidate key for the table.
-
- Returns:
- The value of attribute on ``item`` named as :attr:`id_attribute <AbstractAsyncRepository.id_attribute>`.
- """
- return getattr(item, id_attribute if id_attribute is not None else cls.id_attribute)
-
- @classmethod
- def set_id_attribute_value(cls, item_id: Any, item: T, id_attribute: str | None = None) -> T:
- """Return the ``item`` after the ID is set to the appropriate attribute.
-
- Args:
- item_id: Value of ID to be set on instance
- item: Anything that should have an attribute named as :attr:`id_attribute <AbstractAsyncRepository.id_attribute>` value.
- id_attribute: Allows customization of the unique identifier to use for model fetching.
- Defaults to `None`, but can reference any surrogate or candidate key for the table.
-
- Returns:
- Item with ``item_id`` set to :attr:`id_attribute <AbstractAsyncRepository.id_attribute>`
- """
- setattr(item, id_attribute if id_attribute is not None else cls.id_attribute, item_id)
- return item
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/exceptions.py b/venv/lib/python3.11/site-packages/litestar/repository/exceptions.py
deleted file mode 100644
index 8dad182..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/exceptions.py
+++ /dev/null
@@ -1,7 +0,0 @@
-try:
- from advanced_alchemy.exceptions import IntegrityError as ConflictError
- from advanced_alchemy.exceptions import NotFoundError, RepositoryError
-except ImportError: # pragma: no cover
- from ._exceptions import ConflictError, NotFoundError, RepositoryError # type: ignore[assignment]
-
-__all__ = ("ConflictError", "NotFoundError", "RepositoryError")
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/filters.py b/venv/lib/python3.11/site-packages/litestar/repository/filters.py
deleted file mode 100644
index e0cce48..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/filters.py
+++ /dev/null
@@ -1,37 +0,0 @@
-try:
- from advanced_alchemy.filters import (
- BeforeAfter,
- CollectionFilter,
- FilterTypes,
- LimitOffset,
- NotInCollectionFilter,
- NotInSearchFilter,
- OnBeforeAfter,
- OrderBy,
- SearchFilter,
- )
-except ImportError:
- from ._filters import ( # type: ignore[assignment]
- BeforeAfter,
- CollectionFilter,
- FilterTypes,
- LimitOffset,
- NotInCollectionFilter,
- NotInSearchFilter,
- OnBeforeAfter,
- OrderBy,
- SearchFilter,
- )
-
-
-__all__ = (
- "BeforeAfter",
- "CollectionFilter",
- "FilterTypes",
- "LimitOffset",
- "OrderBy",
- "SearchFilter",
- "NotInCollectionFilter",
- "OnBeforeAfter",
- "NotInSearchFilter",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/handlers.py b/venv/lib/python3.11/site-packages/litestar/repository/handlers.py
deleted file mode 100644
index 0bc1434..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/handlers.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from typing import TYPE_CHECKING
-
-from litestar.repository.filters import (
- BeforeAfter,
- CollectionFilter,
- FilterTypes,
- LimitOffset,
- NotInCollectionFilter,
- NotInSearchFilter,
- OnBeforeAfter,
- OrderBy,
- SearchFilter,
-)
-
-if TYPE_CHECKING:
- from litestar.config.app import AppConfig
-
-__all__ = ("signature_namespace_values", "on_app_init")
-
-signature_namespace_values = {
- "BeforeAfter": BeforeAfter,
- "OnBeforeAfter": OnBeforeAfter,
- "CollectionFilter": CollectionFilter,
- "LimitOffset": LimitOffset,
- "OrderBy": OrderBy,
- "SearchFilter": SearchFilter,
- "NotInCollectionFilter": NotInCollectionFilter,
- "NotInSearchFilter": NotInSearchFilter,
- "FilterTypes": FilterTypes,
-}
-
-
-def on_app_init(app_config: "AppConfig") -> "AppConfig":
- """Add custom filters for the application during signature modelling."""
-
- app_config.signature_namespace.update(signature_namespace_values)
- return app_config
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/testing/__init__.py b/venv/lib/python3.11/site-packages/litestar/repository/testing/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/testing/__init__.py
+++ /dev/null
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/testing/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/repository/testing/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index a008ff2..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/testing/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/testing/__pycache__/generic_mock_repository.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/repository/testing/__pycache__/generic_mock_repository.cpython-311.pyc
deleted file mode 100644
index c871877..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/testing/__pycache__/generic_mock_repository.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/repository/testing/generic_mock_repository.py b/venv/lib/python3.11/site-packages/litestar/repository/testing/generic_mock_repository.py
deleted file mode 100644
index 5aa094c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/repository/testing/generic_mock_repository.py
+++ /dev/null
@@ -1,784 +0,0 @@
-"""A repository implementation for tests.
-
-Uses a `dict` for storage.
-"""
-
-from __future__ import annotations
-
-from datetime import datetime, timezone, tzinfo
-from typing import TYPE_CHECKING, Generic, Protocol, TypeVar
-from uuid import uuid4
-
-from litestar.repository import AbstractAsyncRepository, AbstractSyncRepository, FilterTypes
-from litestar.repository.exceptions import ConflictError, RepositoryError
-
-if TYPE_CHECKING:
- from collections.abc import Callable, Hashable, Iterable, MutableMapping
- from typing import Any
-
-__all__ = ("GenericAsyncMockRepository", "GenericSyncMockRepository")
-
-
-class HasID(Protocol):
- id: Any
-
-
-ModelT = TypeVar("ModelT", bound="HasID")
-AsyncMockRepoT = TypeVar("AsyncMockRepoT", bound="GenericAsyncMockRepository")
-SyncMockRepoT = TypeVar("SyncMockRepoT", bound="GenericSyncMockRepository")
-
-
-class GenericAsyncMockRepository(AbstractAsyncRepository[ModelT], Generic[ModelT]):
- """A repository implementation for tests.
-
- Uses a :class:`dict` for storage.
- """
-
- collection: MutableMapping[Hashable, ModelT]
- model_type: type[ModelT]
- match_fields: list[str] | str | None = None
-
- _model_has_created_at: bool
- _model_has_updated_at: bool
-
- def __init__(
- self, id_factory: Callable[[], Any] = uuid4, tz: tzinfo = timezone.utc, allow_ids_on_add: bool = False, **_: Any
- ) -> None:
- super().__init__()
- self._id_factory = id_factory
- self.tz = tz
- self.allow_ids_on_add = allow_ids_on_add
-
- @classmethod
- def __class_getitem__(cls: type[AsyncMockRepoT], item: type[ModelT]) -> type[AsyncMockRepoT]:
- """Add collection to ``_collections`` for the type.
-
- Args:
- item: The type that the class has been parametrized with.
- """
- return type( # pyright:ignore
- f"{cls.__name__}[{item.__name__}]",
- (cls,),
- {
- "collection": {},
- "model_type": item,
- "_model_has_created_at": hasattr(item, "created_at"),
- "_model_has_updated_at": hasattr(item, "updated_at"),
- },
- )
-
- def _find_or_raise_not_found(self, item_id: Any) -> ModelT:
- return self.check_not_found(self.collection.get(item_id))
-
- def _find_or_none(self, item_id: Any) -> ModelT | None:
- return self.collection.get(item_id)
-
- def _now(self) -> datetime:
- return datetime.now(tz=self.tz).replace(tzinfo=None)
-
- def _update_audit_attributes(self, data: ModelT, now: datetime | None = None, do_created: bool = False) -> ModelT:
- now = now or self._now()
- if self._model_has_updated_at:
- data.updated_at = now # type:ignore[attr-defined]
- if do_created:
- data.created_at = now # type:ignore[attr-defined]
- return data
-
- async def add(self, data: ModelT) -> ModelT:
- """Add ``data`` to the collection.
-
- Args:
- data: Instance to be added to the collection.
-
- Returns:
- The added instance.
- """
- if self.allow_ids_on_add is False and self.get_id_attribute_value(data) is not None:
- raise ConflictError("`add()` received identified item.")
- self._update_audit_attributes(data, do_created=True)
- if self.allow_ids_on_add is False:
- id_ = self._id_factory()
- self.set_id_attribute_value(id_, data)
- self.collection[data.id] = data
- return data
-
- async def add_many(self, data: Iterable[ModelT]) -> list[ModelT]:
- """Add multiple ``data`` to the collection.
-
- Args:
- data: Instance to be added to the collection.
-
- Returns:
- The added instance.
- """
- now = self._now()
- for data_row in data:
- if self.allow_ids_on_add is False and self.get_id_attribute_value(data_row) is not None:
- raise ConflictError("`add()` received identified item.")
-
- self._update_audit_attributes(data_row, do_created=True, now=now)
- if self.allow_ids_on_add is False:
- id_ = self._id_factory()
- self.set_id_attribute_value(id_, data_row)
- self.collection[data_row.id] = data_row
- return list(data)
-
- async def delete(self, item_id: Any) -> ModelT:
- """Delete instance identified by ``item_id``.
-
- Args:
- item_id: Identifier of instance to be deleted.
-
- Returns:
- The deleted instance.
-
- Raises:
- NotFoundError: If no instance found identified by ``item_id``.
- """
- try:
- return self._find_or_raise_not_found(item_id)
- finally:
- del self.collection[item_id]
-
- async def delete_many(self, item_ids: list[Any]) -> list[ModelT]:
- """Delete instances identified by list of identifiers ``item_ids``.
-
- Args:
- item_ids: list of identifiers of instances to be deleted.
-
- Returns:
- The deleted instances.
-
- """
- instances: list[ModelT] = []
- for item_id in item_ids:
- obj = await self.get_one_or_none(**{self.id_attribute: item_id})
- if obj:
- obj = await self.delete(obj.id)
- instances.append(obj)
- return instances
-
- async def exists(self, *filters: FilterTypes, **kwargs: Any) -> bool:
- """Return true if the object specified by ``kwargs`` exists.
-
- Args:
- *filters: Types for specific filtering operations.
- **kwargs: Identifier of the instance to be retrieved.
-
- Returns:
- True if the instance was found. False if not found..
-
- """
- existing = await self.count(*filters, **kwargs)
- return bool(existing)
-
- async def get(self, item_id: Any, **kwargs: Any) -> ModelT:
- """Get instance identified by ``item_id``.
-
- Args:
- item_id: Identifier of the instance to be retrieved.
- **kwargs: additional arguments
-
- Returns:
- The retrieved instance.
-
- Raises:
- NotFoundError: If no instance found identified by ``item_id``.
- """
- return self._find_or_raise_not_found(item_id)
-
- async def get_or_create(self, match_fields: list[str] | str | None = None, **kwargs: Any) -> tuple[ModelT, bool]:
- """Get instance identified by ``kwargs`` or create if it doesn't exist.
-
- Args:
- match_fields: a list of keys to use to match the existing model. When empty, all fields are matched.
- **kwargs: Identifier of the instance to be retrieved.
-
- Returns:
- a tuple that includes the instance and whether it needed to be created.
-
- """
- match_fields = match_fields or self.match_fields
- if isinstance(match_fields, str):
- match_fields = [match_fields]
- if match_fields:
- match_filter = {
- field_name: field_value
- for field_name in match_fields
- if (field_value := kwargs.get(field_name)) is not None
- }
- else:
- match_filter = kwargs
- existing = await self.get_one_or_none(**match_filter)
- if existing:
- for field_name, new_field_value in kwargs.items():
- field = getattr(existing, field_name, None)
- if field and field != new_field_value:
- setattr(existing, field_name, new_field_value)
-
- return existing, False
- return await self.add(self.model_type(**kwargs)), True # pyright: ignore[reportGeneralTypeIssues]
-
- async def get_one(self, **kwargs: Any) -> ModelT:
- """Get instance identified by query filters.
-
- Args:
- **kwargs: Instance attribute value filters.
-
- Returns:
- The retrieved instance or None
-
- Raises:
- NotFoundError: If no instance found identified by ``kwargs``.
- """
- data = await self.list(**kwargs)
- return self.check_not_found(data[0] if data else None)
-
- async def get_one_or_none(self, **kwargs: Any) -> ModelT | None:
- """Get instance identified by query filters or None if not found.
-
- Args:
- **kwargs: Instance attribute value filters.
-
- Returns:
- The retrieved instance or None
- """
- data = await self.list(**kwargs)
- return data[0] if data else None
-
- async def count(self, *filters: FilterTypes, **kwargs: Any) -> int:
- """Count of rows returned by query.
-
- Args:
- *filters: Types for specific filtering operations.
- **kwargs: Instance attribute value filters.
-
- Returns:
- Count of instances in collection, ignoring pagination.
- """
- return len(await self.list(*filters, **kwargs))
-
- async def update(self, data: ModelT) -> ModelT:
- """Update instance with the attribute values present on ``data``.
-
- Args:
- data: An instance that should have a value for :attr:`id_attribute <AsyncGenericMockRepository.id_attribute>` that exists in the
- collection.
-
- Returns:
- The updated instance.
-
- Raises:
- NotFoundError: If no instance found with same identifier as ``data``.
- """
- item = self._find_or_raise_not_found(self.get_id_attribute_value(data))
- self._update_audit_attributes(data, do_created=False)
- for key, val in model_items(data):
- setattr(item, key, val)
- return item
-
- async def update_many(self, data: list[ModelT]) -> list[ModelT]:
- """Update instances with the attribute values present on ``data``.
-
- Args:
- data: A list of instances that should have a value for :attr:`id_attribute <AsyncGenericMockRepository.id_attribute>`
- that exists in the collection.
-
- Returns:
- The updated instances.
-
- Raises:
- NotFoundError: If no instance found with same identifier as ``data``.
- """
- items = [self._find_or_raise_not_found(self.get_id_attribute_value(row)) for row in data]
- now = self._now()
- for item in items:
- self._update_audit_attributes(item, do_created=False, now=now)
- for key, val in model_items(item):
- setattr(item, key, val)
- return items
-
- async def upsert(self, data: ModelT) -> ModelT:
- """Update or create instance.
-
- Updates instance with the attribute values present on ``data``, or creates a new instance if
- one doesn't exist.
-
- Args:
- data: Instance to update existing, or be created. Identifier used to determine if an
- existing instance exists is the value of an attribute on `data` named as value of
- :attr:`id_attribute <AsyncGenericMockRepository.id_attribute>`.
-
- Returns:
- The updated or created instance.
-
- Raises:
- NotFoundError: If no instance found with same identifier as ``data``.
- """
- item_id = self.get_id_attribute_value(data)
- if item_id in self.collection:
- return await self.update(data)
- return await self.add(data)
-
- async def upsert_many(self, data: list[ModelT]) -> list[ModelT]:
- """Update or create multiple instance.
-
- Update instance with the attribute values present on ``data``, or create a new instance if
- one doesn't exist.
-
- Args:
- data: List of instances to update existing, or be created. Identifier used to determine if an
- existing instance exists is the value of an attribute on `data` named as value of
- :attr:`id_attribute <AsyncGenericMockRepository.id_attribute>`.
-
- Returns:
- The updated or created instances.
- """
- data_to_update = [row for row in data if self._find_or_none(self.get_id_attribute_value(row)) is not None]
- data_to_add = [row for row in data if self._find_or_none(self.get_id_attribute_value(row)) is None]
-
- updated_items = await self.update_many(data_to_update)
- added_items = await self.add_many(data_to_add)
- return updated_items + added_items
-
- async def list_and_count(
- self,
- *filters: FilterTypes,
- **kwargs: Any,
- ) -> tuple[list[ModelT], int]:
- """Get a list of instances, optionally filtered with a total row count.
-
- Args:
- *filters: Types for specific filtering operations.
- **kwargs: Instance attribute value filters.
-
- Returns:
- List of instances, and count of records returned by query, ignoring pagination.
- """
- return await self.list(*filters, **kwargs), await self.count(*filters, **kwargs)
-
- async def list(self, *filters: FilterTypes, **kwargs: Any) -> list[ModelT]:
- """Get a list of instances, optionally filtered.
-
- Args:
- *filters: Types for specific filtering operations.
- **kwargs: Instance attribute value filters.
-
- Returns:
- The list of instances, after filtering applied.
- """
- return list(self.filter_collection_by_kwargs(self.collection, **kwargs).values())
-
- def filter_collection_by_kwargs( # type:ignore[override]
- self, collection: MutableMapping[Hashable, ModelT], /, **kwargs: Any
- ) -> MutableMapping[Hashable, ModelT]:
- """Filter the collection by kwargs.
-
- Args:
- collection: set of objects to filter
- **kwargs: key/value pairs such that objects remaining in the collection after filtering
- have the property that their attribute named ``key`` has value equal to ``value``.
- """
- new_collection: dict[Hashable, ModelT] = {}
- for item in self.collection.values():
- try:
- if all(getattr(item, name) == value for name, value in kwargs.items()):
- new_collection[item.id] = item
- except AttributeError as orig:
- raise RepositoryError from orig
- return new_collection
-
- @classmethod
- def seed_collection(cls, instances: Iterable[ModelT]) -> None:
- """Seed the collection for repository type.
-
- Args:
- instances: the instances to be added to the collection.
- """
- for instance in instances:
- cls.collection[cls.get_id_attribute_value(instance)] = instance
-
- @classmethod
- def clear_collection(cls) -> None:
- """Empty the collection for repository type."""
- cls.collection = {}
-
-
-class GenericSyncMockRepository(AbstractSyncRepository[ModelT], Generic[ModelT]):
- """A repository implementation for tests.
-
- Uses a :class:`dict` for storage.
- """
-
- collection: MutableMapping[Hashable, ModelT]
- model_type: type[ModelT]
- match_fields: list[str] | str | None = None
-
- _model_has_created_at: bool
- _model_has_updated_at: bool
-
- def __init__(
- self,
- id_factory: Callable[[], Any] = uuid4,
- tz: tzinfo = timezone.utc,
- allow_ids_on_add: bool = False,
- **_: Any,
- ) -> None:
- super().__init__()
- self._id_factory = id_factory
- self.tz = tz
- self.allow_ids_on_add = allow_ids_on_add
-
- @classmethod
- def __class_getitem__(cls: type[SyncMockRepoT], item: type[ModelT]) -> type[SyncMockRepoT]:
- """Add collection to ``_collections`` for the type.
-
- Args:
- item: The type that the class has been parametrized with.
- """
- return type( # pyright:ignore
- f"{cls.__name__}[{item.__name__}]",
- (cls,),
- {
- "collection": {},
- "model_type": item,
- "_model_has_created_at": hasattr(item, "created_at"),
- "_model_has_updated_at": hasattr(item, "updated_at"),
- },
- )
-
- def _find_or_raise_not_found(self, item_id: Any) -> ModelT:
- return self.check_not_found(self.collection.get(item_id))
-
- def _find_or_none(self, item_id: Any) -> ModelT | None:
- return self.collection.get(item_id)
-
- def _now(self) -> datetime:
- return datetime.now(tz=self.tz).replace(tzinfo=None)
-
- def _update_audit_attributes(self, data: ModelT, now: datetime | None = None, do_created: bool = False) -> ModelT:
- now = now or self._now()
- if self._model_has_updated_at:
- data.updated_at = now # type:ignore[attr-defined]
- if do_created:
- data.created_at = now # type:ignore[attr-defined]
- return data
-
- def add(self, data: ModelT) -> ModelT:
- """Add ``data`` to the collection.
-
- Args:
- data: Instance to be added to the collection.
-
- Returns:
- The added instance.
- """
- if self.allow_ids_on_add is False and self.get_id_attribute_value(data) is not None:
- raise ConflictError("`add()` received identified item.")
- self._update_audit_attributes(data, do_created=True)
- if self.allow_ids_on_add is False:
- id_ = self._id_factory()
- self.set_id_attribute_value(id_, data)
- self.collection[data.id] = data
- return data
-
- def add_many(self, data: Iterable[ModelT]) -> list[ModelT]:
- """Add multiple ``data`` to the collection.
-
- Args:
- data: Instance to be added to the collection.
-
- Returns:
- The added instance.
- """
- now = self._now()
- for data_row in data:
- if self.allow_ids_on_add is False and self.get_id_attribute_value(data_row) is not None:
- raise ConflictError("`add()` received identified item.")
-
- self._update_audit_attributes(data_row, do_created=True, now=now)
- if self.allow_ids_on_add is False:
- id_ = self._id_factory()
- self.set_id_attribute_value(id_, data_row)
- self.collection[data_row.id] = data_row
- return list(data)
-
- def delete(self, item_id: Any) -> ModelT:
- """Delete instance identified by ``item_id``.
-
- Args:
- item_id: Identifier of instance to be deleted.
-
- Returns:
- The deleted instance.
-
- Raises:
- NotFoundError: If no instance found identified by ``item_id``.
- """
- try:
- return self._find_or_raise_not_found(item_id)
- finally:
- del self.collection[item_id]
-
- def delete_many(self, item_ids: list[Any]) -> list[ModelT]:
- """Delete instances identified by list of identifiers ``item_ids``.
-
- Args:
- item_ids: list of identifiers of instances to be deleted.
-
- Returns:
- The deleted instances.
-
- """
- instances: list[ModelT] = []
- for item_id in item_ids:
- if obj := self.get_one_or_none(**{self.id_attribute: item_id}):
- obj = self.delete(obj.id)
- instances.append(obj)
- return instances
-
- def exists(self, *filters: FilterTypes, **kwargs: Any) -> bool:
- """Return true if the object specified by ``kwargs`` exists.
-
- Args:
- *filters: Types for specific filtering operations.
- **kwargs: Identifier of the instance to be retrieved.
-
- Returns:
- True if the instance was found. False if not found..
-
- """
- existing = self.count(*filters, **kwargs)
- return bool(existing)
-
- def get(self, item_id: Any, **kwargs: Any) -> ModelT:
- """Get instance identified by ``item_id``.
-
- Args:
- item_id: Identifier of the instance to be retrieved.
- **kwargs: additional arguments
-
- Returns:
- The retrieved instance.
-
- Raises:
- NotFoundError: If no instance found identified by ``item_id``.
- """
- return self._find_or_raise_not_found(item_id)
-
- def get_or_create(self, match_fields: list[str] | str | None = None, **kwargs: Any) -> tuple[ModelT, bool]:
- """Get instance identified by ``kwargs`` or create if it doesn't exist.
-
- Args:
- match_fields: a list of keys to use to match the existing model. When empty, all fields are matched.
- **kwargs: Identifier of the instance to be retrieved.
-
- Returns:
- a tuple that includes the instance and whether it needed to be created.
-
- """
- match_fields = match_fields or self.match_fields
- if isinstance(match_fields, str):
- match_fields = [match_fields]
- if match_fields:
- match_filter = {
- field_name: field_value
- for field_name in match_fields
- if (field_value := kwargs.get(field_name)) is not None
- }
- else:
- match_filter = kwargs
- if existing := self.get_one_or_none(**match_filter):
- for field_name, new_field_value in kwargs.items():
- field = getattr(existing, field_name, None)
- if field and field != new_field_value:
- setattr(existing, field_name, new_field_value)
-
- return existing, False
- return self.add(self.model_type(**kwargs)), True # pyright: ignore[reportGeneralTypeIssues]
-
- def get_one(self, **kwargs: Any) -> ModelT:
- """Get instance identified by query filters.
-
- Args:
- **kwargs: Instance attribute value filters.
-
- Returns:
- The retrieved instance or None
-
- Raises:
- NotFoundError: If no instance found identified by ``kwargs``.
- """
- data = self.list(**kwargs)
- return self.check_not_found(data[0] if data else None)
-
- def get_one_or_none(self, **kwargs: Any) -> ModelT | None:
- """Get instance identified by query filters or None if not found.
-
- Args:
- **kwargs: Instance attribute value filters.
-
- Returns:
- The retrieved instance or None
- """
- data = self.list(**kwargs)
- return data[0] if data else None
-
- def count(self, *filters: FilterTypes, **kwargs: Any) -> int:
- """Count of rows returned by query.
-
- Args:
- *filters: Types for specific filtering operations.
- **kwargs: Instance attribute value filters.
-
- Returns:
- Count of instances in collection, ignoring pagination.
- """
- return len(self.list(*filters, **kwargs))
-
- def update(self, data: ModelT) -> ModelT:
- """Update instance with the attribute values present on ``data``.
-
- Args:
- data: An instance that should have a value for :attr:`id_attribute <AsyncGenericMockRepository.id_attribute>` that exists in the
- collection.
-
- Returns:
- The updated instance.
-
- Raises:
- NotFoundError: If no instance found with same identifier as ``data``.
- """
- item = self._find_or_raise_not_found(self.get_id_attribute_value(data))
- self._update_audit_attributes(data, do_created=False)
- for key, val in model_items(data):
- setattr(item, key, val)
- return item
-
- def update_many(self, data: list[ModelT]) -> list[ModelT]:
- """Update instances with the attribute values present on ``data``.
-
- Args:
- data: A list of instances that should have a value for :attr:`id_attribute <AsyncGenericMockRepository.id_attribute>`
- that exists in the collection.
-
- Returns:
- The updated instances.
-
- Raises:
- NotFoundError: If no instance found with same identifier as ``data``.
- """
- items = [self._find_or_raise_not_found(self.get_id_attribute_value(row)) for row in data]
- now = self._now()
- for item in items:
- self._update_audit_attributes(item, do_created=False, now=now)
- for key, val in model_items(item):
- setattr(item, key, val)
- return items
-
- def upsert(self, data: ModelT) -> ModelT:
- """Update or create instance.
-
- Updates instance with the attribute values present on ``data``, or creates a new instance if
- one doesn't exist.
-
- Args:
- data: Instance to update existing, or be created. Identifier used to determine if an
- existing instance exists is the value of an attribute on `data` named as value of
- :attr:`id_attribute <AsyncGenericMockRepository.id_attribute>`.
-
- Returns:
- The updated or created instance.
-
- Raises:
- NotFoundError: If no instance found with same identifier as ``data``.
- """
- item_id = self.get_id_attribute_value(data)
- return self.update(data) if item_id in self.collection else self.add(data)
-
- def upsert_many(self, data: list[ModelT]) -> list[ModelT]:
- """Update or create multiple instance.
-
- Update instance with the attribute values present on ``data``, or create a new instance if
- one doesn't exist.
-
- Args:
- data: List of instances to update existing, or be created. Identifier used to determine if an
- existing instance exists is the value of an attribute on `data` named as value of
- :attr:`id_attribute <AsyncGenericMockRepository.id_attribute>`.
-
- Returns:
- The updated or created instances.
- """
- data_to_update = [row for row in data if self._find_or_none(self.get_id_attribute_value(row)) is not None]
- data_to_add = [row for row in data if self._find_or_none(self.get_id_attribute_value(row)) is None]
-
- updated_items = self.update_many(data_to_update)
- added_items = self.add_many(data_to_add)
- return updated_items + added_items
-
- def list_and_count(
- self,
- *filters: FilterTypes,
- **kwargs: Any,
- ) -> tuple[list[ModelT], int]:
- """Get a list of instances, optionally filtered with a total row count.
-
- Args:
- *filters: Types for specific filtering operations.
- **kwargs: Instance attribute value filters.
-
- Returns:
- List of instances, and count of records returned by query, ignoring pagination.
- """
- return self.list(*filters, **kwargs), self.count(*filters, **kwargs)
-
- def list(self, *filters: FilterTypes, **kwargs: Any) -> list[ModelT]:
- """Get a list of instances, optionally filtered.
-
- Args:
- *filters: Types for specific filtering operations.
- **kwargs: Instance attribute value filters.
-
- Returns:
- The list of instances, after filtering applied.
- """
- return list(self.filter_collection_by_kwargs(self.collection, **kwargs).values())
-
- def filter_collection_by_kwargs( # type:ignore[override]
- self, collection: MutableMapping[Hashable, ModelT], /, **kwargs: Any
- ) -> MutableMapping[Hashable, ModelT]:
- """Filter the collection by kwargs.
-
- Args:
- collection: set of objects to filter
- **kwargs: key/value pairs such that objects remaining in the collection after filtering
- have the property that their attribute named ``key`` has value equal to ``value``.
- """
- new_collection: dict[Hashable, ModelT] = {}
- for item in self.collection.values():
- try:
- if all(getattr(item, name) == value for name, value in kwargs.items()):
- new_collection[item.id] = item
- except AttributeError as orig:
- raise RepositoryError from orig
- return new_collection
-
- @classmethod
- def seed_collection(cls, instances: Iterable[ModelT]) -> None:
- """Seed the collection for repository type.
-
- Args:
- instances: the instances to be added to the collection.
- """
- for instance in instances:
- cls.collection[cls.get_id_attribute_value(instance)] = instance
-
- @classmethod
- def clear_collection(cls) -> None:
- """Empty the collection for repository type."""
- cls.collection = {}
-
-
-def model_items(model: Any) -> list[tuple[str, Any]]:
- return [(k, v) for k, v in model.__dict__.items() if not k.startswith("_")]
diff --git a/venv/lib/python3.11/site-packages/litestar/response/__init__.py b/venv/lib/python3.11/site-packages/litestar/response/__init__.py
deleted file mode 100644
index c655758..0000000
--- a/venv/lib/python3.11/site-packages/litestar/response/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from .base import Response
-from .file import File
-from .redirect import Redirect
-from .sse import ServerSentEvent, ServerSentEventMessage
-from .streaming import Stream
-from .template import Template
-
-__all__ = (
- "File",
- "Redirect",
- "Response",
- "ServerSentEvent",
- "ServerSentEventMessage",
- "Stream",
- "Template",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/response/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/response/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index a806282..0000000
--- a/venv/lib/python3.11/site-packages/litestar/response/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/response/__pycache__/base.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/response/__pycache__/base.cpython-311.pyc
deleted file mode 100644
index 885cbe8..0000000
--- a/venv/lib/python3.11/site-packages/litestar/response/__pycache__/base.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/response/__pycache__/file.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/response/__pycache__/file.cpython-311.pyc
deleted file mode 100644
index 23c09f2..0000000
--- a/venv/lib/python3.11/site-packages/litestar/response/__pycache__/file.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/response/__pycache__/redirect.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/response/__pycache__/redirect.cpython-311.pyc
deleted file mode 100644
index d776095..0000000
--- a/venv/lib/python3.11/site-packages/litestar/response/__pycache__/redirect.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/response/__pycache__/sse.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/response/__pycache__/sse.cpython-311.pyc
deleted file mode 100644
index 2a03883..0000000
--- a/venv/lib/python3.11/site-packages/litestar/response/__pycache__/sse.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/response/__pycache__/streaming.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/response/__pycache__/streaming.cpython-311.pyc
deleted file mode 100644
index 350cf9e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/response/__pycache__/streaming.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/response/__pycache__/template.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/response/__pycache__/template.cpython-311.pyc
deleted file mode 100644
index 91dde51..0000000
--- a/venv/lib/python3.11/site-packages/litestar/response/__pycache__/template.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/response/base.py b/venv/lib/python3.11/site-packages/litestar/response/base.py
deleted file mode 100644
index 67eec09..0000000
--- a/venv/lib/python3.11/site-packages/litestar/response/base.py
+++ /dev/null
@@ -1,459 +0,0 @@
-from __future__ import annotations
-
-import itertools
-import re
-from typing import TYPE_CHECKING, Any, ClassVar, Generic, Iterable, Literal, Mapping, TypeVar, overload
-
-from litestar.datastructures.cookie import Cookie
-from litestar.datastructures.headers import ETag, MutableScopeHeaders
-from litestar.enums import MediaType, OpenAPIMediaType
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.serialization import default_serializer, encode_json, encode_msgpack, get_serializer
-from litestar.status_codes import HTTP_200_OK, HTTP_204_NO_CONTENT, HTTP_304_NOT_MODIFIED
-from litestar.types.empty import Empty
-from litestar.utils.deprecation import deprecated, warn_deprecation
-from litestar.utils.helpers import get_enum_string_value
-
-if TYPE_CHECKING:
- from typing import Optional
-
- from litestar.app import Litestar
- from litestar.background_tasks import BackgroundTask, BackgroundTasks
- from litestar.connection import Request
- from litestar.types import (
- HTTPResponseBodyEvent,
- HTTPResponseStartEvent,
- Receive,
- ResponseCookies,
- ResponseHeaders,
- Scope,
- Send,
- Serializer,
- TypeEncodersMap,
- )
-
-__all__ = ("ASGIResponse", "Response")
-
-T = TypeVar("T")
-
-MEDIA_TYPE_APPLICATION_JSON_PATTERN = re.compile(r"^application/(?:.+\+)?json")
-
-
-class ASGIResponse:
- """A low-level ASGI response class."""
-
- __slots__ = (
- "background",
- "body",
- "content_length",
- "encoding",
- "is_head_response",
- "status_code",
- "_encoded_cookies",
- "headers",
- )
-
- _should_set_content_length: ClassVar[bool] = True
- """A flag to indicate whether the content-length header should be set by default or not."""
-
- def __init__(
- self,
- *,
- background: BackgroundTask | BackgroundTasks | None = None,
- body: bytes | str = b"",
- content_length: int | None = None,
- cookies: Iterable[Cookie] | None = None,
- encoded_headers: Iterable[tuple[bytes, bytes]] | None = None,
- encoding: str = "utf-8",
- headers: dict[str, Any] | Iterable[tuple[str, str]] | None = None,
- is_head_response: bool = False,
- media_type: MediaType | str | None = None,
- status_code: int | None = None,
- ) -> None:
- """A low-level ASGI response class.
-
- Args:
- background: A background task or a list of background tasks to be executed after the response is sent.
- body: encoded content to send in the response body.
- content_length: The response content length.
- cookies: The response cookies.
- encoded_headers: The response headers.
- encoding: The response encoding.
- headers: The response headers.
- is_head_response: A boolean indicating if the response is a HEAD response.
- media_type: The response media type.
- status_code: The response status code.
- """
- body = body.encode() if isinstance(body, str) else body
- status_code = status_code or HTTP_200_OK
- self.headers = MutableScopeHeaders()
-
- if encoded_headers is not None:
- warn_deprecation("3.0", kind="parameter", deprecated_name="encoded_headers", alternative="headers")
- for header_name, header_value in encoded_headers:
- self.headers.add(header_name.decode("latin-1"), header_value.decode("latin-1"))
-
- if headers is not None:
- for k, v in headers.items() if isinstance(headers, dict) else headers:
- self.headers.add(k, v) # pyright: ignore
-
- media_type = get_enum_string_value(media_type or MediaType.JSON)
-
- status_allows_body = (
- status_code not in {HTTP_204_NO_CONTENT, HTTP_304_NOT_MODIFIED} and status_code >= HTTP_200_OK
- )
-
- if content_length is None:
- content_length = len(body)
-
- if not status_allows_body or is_head_response:
- if body and body != b"null":
- raise ImproperlyConfiguredException(
- "response content is not supported for HEAD responses and responses with a status code "
- "that does not allow content (304, 204, < 200)"
- )
- body = b""
- else:
- self.headers.setdefault(
- "content-type", (f"{media_type}; charset={encoding}" if media_type.startswith("text/") else media_type)
- )
-
- if self._should_set_content_length:
- self.headers.setdefault("content-length", str(content_length))
-
- self.background = background
- self.body = body
- self.content_length = content_length
- self._encoded_cookies = tuple(
- cookie.to_encoded_header() for cookie in (cookies or ()) if not cookie.documentation_only
- )
- self.encoding = encoding
- self.is_head_response = is_head_response
- self.status_code = status_code
-
- @property
- @deprecated("3.0", kind="property", alternative="encode_headers()")
- def encoded_headers(self) -> list[tuple[bytes, bytes]]:
- return self.encode_headers()
-
- def encode_headers(self) -> list[tuple[bytes, bytes]]:
- return [*self.headers.headers, *self._encoded_cookies]
-
- async def after_response(self) -> None:
- """Execute after the response is sent.
-
- Returns:
- None
- """
- if self.background is not None:
- await self.background()
-
- async def start_response(self, send: Send) -> None:
- """Emit the start event of the response. This event includes the headers and status codes.
-
- Args:
- send: The ASGI send function.
-
- Returns:
- None
- """
- event: HTTPResponseStartEvent = {
- "type": "http.response.start",
- "status": self.status_code,
- "headers": self.encode_headers(),
- }
- await send(event)
-
- async def send_body(self, send: Send, receive: Receive) -> None:
- """Emit the response body.
-
- Args:
- send: The ASGI send function.
- receive: The ASGI receive function.
-
- Notes:
- - Response subclasses should customize this method if there is a need to customize sending data.
-
- Returns:
- None
- """
- event: HTTPResponseBodyEvent = {"type": "http.response.body", "body": self.body, "more_body": False}
- await send(event)
-
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
- """ASGI callable of the ``Response``.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
- await self.start_response(send=send)
-
- if self.is_head_response:
- event: HTTPResponseBodyEvent = {"type": "http.response.body", "body": b"", "more_body": False}
- await send(event)
- else:
- await self.send_body(send=send, receive=receive)
-
- await self.after_response()
-
-
-class Response(Generic[T]):
- """Base Litestar HTTP response class, used as the basis for all other response classes."""
-
- __slots__ = (
- "background",
- "content",
- "cookies",
- "encoding",
- "headers",
- "media_type",
- "status_code",
- "response_type_encoders",
- )
-
- content: T
- type_encoders: Optional[TypeEncodersMap] = None # noqa: UP007
-
- def __init__(
- self,
- content: T,
- *,
- background: BackgroundTask | BackgroundTasks | None = None,
- cookies: ResponseCookies | None = None,
- encoding: str = "utf-8",
- headers: ResponseHeaders | None = None,
- media_type: MediaType | OpenAPIMediaType | str | None = None,
- status_code: int | None = None,
- type_encoders: TypeEncodersMap | None = None,
- ) -> None:
- """Initialize the response.
-
- Args:
- content: A value for the response body that will be rendered into bytes string.
- status_code: An HTTP status code.
- media_type: A value for the response ``Content-Type`` header.
- background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or
- :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished.
- Defaults to ``None``.
- headers: A string keyed dictionary of response headers. Header keys are insensitive.
- cookies: A list of :class:`Cookie <.datastructures.Cookie>` instances to be set under the response
- ``Set-Cookie`` header.
- encoding: The encoding to be used for the response headers.
- type_encoders: A mapping of types to callables that transform them into types supported for serialization.
- """
- self.content = content
- self.background = background
- self.cookies: list[Cookie] = (
- [Cookie(key=key, value=value) for key, value in cookies.items()]
- if isinstance(cookies, Mapping)
- else list(cookies or [])
- )
- self.encoding = encoding
- self.headers: dict[str, Any] = (
- dict(headers) if isinstance(headers, Mapping) else {h.name: h.value for h in headers or {}}
- )
- self.media_type = media_type
- self.status_code = status_code
- self.response_type_encoders = {**(self.type_encoders or {}), **(type_encoders or {})}
-
- @overload
- def set_cookie(self, /, cookie: Cookie) -> None: ...
-
- @overload
- def set_cookie(
- self,
- key: str,
- value: str | None = None,
- max_age: int | None = None,
- expires: int | None = None,
- path: str = "/",
- domain: str | None = None,
- secure: bool = False,
- httponly: bool = False,
- samesite: Literal["lax", "strict", "none"] = "lax",
- ) -> None: ...
-
- def set_cookie( # type: ignore[misc]
- self,
- key: str | Cookie,
- value: str | None = None,
- max_age: int | None = None,
- expires: int | None = None,
- path: str = "/",
- domain: str | None = None,
- secure: bool = False,
- httponly: bool = False,
- samesite: Literal["lax", "strict", "none"] = "lax",
- ) -> None:
- """Set a cookie on the response. If passed a :class:`Cookie <.datastructures.Cookie>` instance, keyword
- arguments will be ignored.
-
- Args:
- key: Key for the cookie or a :class:`Cookie <.datastructures.Cookie>` instance.
- value: Value for the cookie, if none given defaults to empty string.
- max_age: Maximal age of the cookie before its invalidated.
- expires: Seconds from now until the cookie expires.
- path: Path fragment that must exist in the request url for the cookie to be valid. Defaults to ``/``.
- domain: Domain for which the cookie is valid.
- secure: Https is required for the cookie.
- httponly: Forbids javascript to access the cookie via ``document.cookie``.
- samesite: Controls whether a cookie is sent with cross-site requests. Defaults to ``lax``.
-
- Returns:
- None.
- """
- if not isinstance(key, Cookie):
- key = Cookie(
- domain=domain,
- expires=expires,
- httponly=httponly,
- key=key,
- max_age=max_age,
- path=path,
- samesite=samesite,
- secure=secure,
- value=value,
- )
- self.cookies.append(key)
-
- def set_header(self, key: str, value: Any) -> None:
- """Set a header on the response.
-
- Args:
- key: Header key.
- value: Header value.
-
- Returns:
- None.
- """
- self.headers[key] = value
-
- def set_etag(self, etag: str | ETag) -> None:
- """Set an etag header.
-
- Args:
- etag: An etag value.
-
- Returns:
- None
- """
- self.headers["etag"] = etag.to_header() if isinstance(etag, ETag) else etag
-
- def delete_cookie(
- self,
- key: str,
- path: str = "/",
- domain: str | None = None,
- ) -> None:
- """Delete a cookie.
-
- Args:
- key: Key of the cookie.
- path: Path of the cookie.
- domain: Domain of the cookie.
-
- Returns:
- None.
- """
- cookie = Cookie(key=key, path=path, domain=domain, expires=0, max_age=0)
- self.cookies = [c for c in self.cookies if c != cookie]
- self.cookies.append(cookie)
-
- def render(self, content: Any, media_type: str, enc_hook: Serializer = default_serializer) -> bytes:
- """Handle the rendering of content into a bytes string.
-
- Returns:
- An encoded bytes string
- """
- if isinstance(content, bytes):
- return content
-
- if content is Empty:
- raise RuntimeError("The `Empty` sentinel cannot be used as response content")
-
- try:
- if media_type.startswith("text/") and not content:
- return b""
-
- if isinstance(content, str):
- return content.encode(self.encoding)
-
- if media_type == MediaType.MESSAGEPACK:
- return encode_msgpack(content, enc_hook)
-
- if MEDIA_TYPE_APPLICATION_JSON_PATTERN.match(
- media_type,
- ):
- return encode_json(content, enc_hook)
-
- raise ImproperlyConfiguredException(f"unsupported media_type {media_type} for content {content!r}")
- except (AttributeError, ValueError, TypeError) as e:
- raise ImproperlyConfiguredException("Unable to serialize response content") from e
-
- def to_asgi_response(
- self,
- app: Litestar | None,
- request: Request,
- *,
- background: BackgroundTask | BackgroundTasks | None = None,
- cookies: Iterable[Cookie] | None = None,
- encoded_headers: Iterable[tuple[bytes, bytes]] | None = None,
- headers: dict[str, str] | None = None,
- is_head_response: bool = False,
- media_type: MediaType | str | None = None,
- status_code: int | None = None,
- type_encoders: TypeEncodersMap | None = None,
- ) -> ASGIResponse:
- """Create an ASGIResponse from a Response instance.
-
- Args:
- app: The :class:`Litestar <.app.Litestar>` application instance.
- background: Background task(s) to be executed after the response is sent.
- cookies: A list of cookies to be set on the response.
- encoded_headers: A list of already encoded headers.
- headers: Additional headers to be merged with the response headers. Response headers take precedence.
- is_head_response: Whether the response is a HEAD response.
- media_type: Media type for the response. If ``media_type`` is already set on the response, this is ignored.
- request: The :class:`Request <.connection.Request>` instance.
- status_code: Status code for the response. If ``status_code`` is already set on the response, this is
- type_encoders: A dictionary of type encoders to use for encoding the response content.
-
- Returns:
- An ASGIResponse instance.
- """
-
- if app is not None:
- warn_deprecation(
- version="2.1",
- deprecated_name="app",
- kind="parameter",
- removal_in="3.0.0",
- alternative="request.app",
- )
-
- headers = {**headers, **self.headers} if headers is not None else self.headers
- cookies = self.cookies if cookies is None else itertools.chain(self.cookies, cookies)
-
- if type_encoders:
- type_encoders = {**type_encoders, **(self.response_type_encoders or {})}
- else:
- type_encoders = self.response_type_encoders
-
- media_type = get_enum_string_value(self.media_type or media_type or MediaType.JSON)
-
- return ASGIResponse(
- background=self.background or background,
- body=self.render(self.content, media_type, get_serializer(type_encoders)),
- cookies=cookies,
- encoded_headers=encoded_headers,
- encoding=self.encoding,
- headers=headers,
- is_head_response=is_head_response,
- media_type=media_type,
- status_code=self.status_code or status_code,
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/response/file.py b/venv/lib/python3.11/site-packages/litestar/response/file.py
deleted file mode 100644
index 1fc6f86..0000000
--- a/venv/lib/python3.11/site-packages/litestar/response/file.py
+++ /dev/null
@@ -1,386 +0,0 @@
-from __future__ import annotations
-
-import itertools
-from email.utils import formatdate
-from inspect import iscoroutine
-from mimetypes import encodings_map, guess_type
-from typing import TYPE_CHECKING, Any, AsyncGenerator, Coroutine, Iterable, Literal, cast
-from urllib.parse import quote
-from zlib import adler32
-
-from litestar.constants import ONE_MEGABYTE
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.file_system import BaseLocalFileSystem, FileSystemAdapter
-from litestar.response.base import Response
-from litestar.response.streaming import ASGIStreamingResponse
-from litestar.utils.deprecation import warn_deprecation
-from litestar.utils.helpers import get_enum_string_value
-
-if TYPE_CHECKING:
- from os import PathLike
- from os import stat_result as stat_result_type
-
- from anyio import Path
-
- from litestar.app import Litestar
- from litestar.background_tasks import BackgroundTask, BackgroundTasks
- from litestar.connection import Request
- from litestar.datastructures.cookie import Cookie
- from litestar.datastructures.headers import ETag
- from litestar.enums import MediaType
- from litestar.types import (
- HTTPResponseBodyEvent,
- PathType,
- Receive,
- ResponseCookies,
- ResponseHeaders,
- Send,
- TypeEncodersMap,
- )
- from litestar.types.file_types import FileInfo, FileSystemProtocol
-
-__all__ = (
- "ASGIFileResponse",
- "File",
- "async_file_iterator",
- "create_etag_for_file",
-)
-
-# brotli not supported in 'mimetypes.encodings_map' until py 3.9.
-encodings_map[".br"] = "br"
-
-
-async def async_file_iterator(
- file_path: PathType, chunk_size: int, adapter: FileSystemAdapter
-) -> AsyncGenerator[bytes, None]:
- """Return an async that asynchronously reads a file and yields its chunks.
-
- Args:
- file_path: A path to a file.
- chunk_size: The chunk file to use.
- adapter: File system adapter class.
- adapter: File system adapter class.
-
- Returns:
- An async generator.
- """
- async with await adapter.open(file_path) as file:
- while chunk := await file.read(chunk_size):
- yield chunk
-
-
-def create_etag_for_file(path: PathType, modified_time: float, file_size: int) -> str:
- """Create an etag.
-
- Notes:
- - Function is derived from flask.
-
- Returns:
- An etag.
- """
- check = adler32(str(path).encode("utf-8")) & 0xFFFFFFFF
- return f'"{modified_time}-{file_size}-{check}"'
-
-
-class ASGIFileResponse(ASGIStreamingResponse):
- """A low-level ASGI response, streaming a file as response body."""
-
- def __init__(
- self,
- *,
- background: BackgroundTask | BackgroundTasks | None = None,
- body: bytes | str = b"",
- chunk_size: int = ONE_MEGABYTE,
- content_disposition_type: Literal["attachment", "inline"] = "attachment",
- content_length: int | None = None,
- cookies: Iterable[Cookie] | None = None,
- encoded_headers: Iterable[tuple[bytes, bytes]] | None = None,
- encoding: str = "utf-8",
- etag: ETag | None = None,
- file_info: FileInfo | Coroutine[None, None, FileInfo] | None = None,
- file_path: str | PathLike | Path,
- file_system: FileSystemProtocol | None = None,
- filename: str = "",
- headers: dict[str, str] | None = None,
- is_head_response: bool = False,
- media_type: MediaType | str | None = None,
- stat_result: stat_result_type | None = None,
- status_code: int | None = None,
- ) -> None:
- """A low-level ASGI response, streaming a file as response body.
-
- Args:
- background: A background task or a list of background tasks to be executed after the response is sent.
- body: encoded content to send in the response body.
- chunk_size: The chunk size to use.
- content_disposition_type: The type of the ``Content-Disposition``. Either ``inline`` or ``attachment``.
- content_length: The response content length.
- cookies: The response cookies.
- encoded_headers: A list of encoded headers.
- encoding: The response encoding.
- etag: An etag.
- file_info: A file info.
- file_path: A path to a file.
- file_system: A file system adapter.
- filename: The name of the file.
- headers: A dictionary of headers.
- headers: The response headers.
- is_head_response: A boolean indicating if the response is a HEAD response.
- media_type: The media type of the file.
- stat_result: A stat result.
- status_code: The response status code.
- """
- headers = headers or {}
- if not media_type:
- mimetype, content_encoding = guess_type(filename) if filename else (None, None)
- media_type = mimetype or "application/octet-stream"
- if content_encoding is not None:
- headers.update({"content-encoding": content_encoding})
-
- self.adapter = FileSystemAdapter(file_system or BaseLocalFileSystem())
-
- super().__init__(
- iterator=async_file_iterator(file_path=file_path, chunk_size=chunk_size, adapter=self.adapter),
- headers=headers,
- media_type=media_type,
- cookies=cookies,
- background=background,
- status_code=status_code,
- body=body,
- content_length=content_length,
- encoding=encoding,
- is_head_response=is_head_response,
- encoded_headers=encoded_headers,
- )
-
- quoted_filename = quote(filename)
- is_utf8 = quoted_filename == filename
- if is_utf8:
- content_disposition = f'{content_disposition_type}; filename="{filename}"'
- else:
- content_disposition = f"{content_disposition_type}; filename*=utf-8''{quoted_filename}"
-
- self.headers.setdefault("content-disposition", content_disposition)
-
- self.chunk_size = chunk_size
- self.etag = etag
- self.file_path = file_path
-
- if file_info:
- self.file_info: FileInfo | Coroutine[Any, Any, FileInfo] = file_info
- elif stat_result:
- self.file_info = self.adapter.parse_stat_result(result=stat_result, path=file_path)
- else:
- self.file_info = self.adapter.info(self.file_path)
-
- async def send_body(self, send: Send, receive: Receive) -> None:
- """Emit a stream of events correlating with the response body.
-
- Args:
- send: The ASGI send function.
- receive: The ASGI receive function.
-
- Returns:
- None
- """
- if self.chunk_size < self.content_length:
- await super().send_body(send=send, receive=receive)
- return
-
- async with await self.adapter.open(self.file_path) as file:
- body_event: HTTPResponseBodyEvent = {
- "type": "http.response.body",
- "body": await file.read(),
- "more_body": False,
- }
- await send(body_event)
-
- async def start_response(self, send: Send) -> None:
- """Emit the start event of the response. This event includes the headers and status codes.
-
- Args:
- send: The ASGI send function.
-
- Returns:
- None
- """
- try:
- fs_info = self.file_info = cast(
- "FileInfo", (await self.file_info if iscoroutine(self.file_info) else self.file_info)
- )
- except FileNotFoundError as e:
- raise ImproperlyConfiguredException(f"{self.file_path} does not exist") from e
-
- if fs_info["type"] != "file":
- raise ImproperlyConfiguredException(f"{self.file_path} is not a file")
-
- self.content_length = fs_info["size"]
-
- self.headers.setdefault("content-length", str(self.content_length))
- self.headers.setdefault("last-modified", formatdate(fs_info["mtime"], usegmt=True))
-
- if self.etag:
- self.headers.setdefault("etag", self.etag.to_header())
- else:
- self.headers.setdefault(
- "etag",
- create_etag_for_file(path=self.file_path, modified_time=fs_info["mtime"], file_size=fs_info["size"]),
- )
-
- await super().start_response(send=send)
-
-
-class File(Response):
- """A response, streaming a file as response body."""
-
- __slots__ = (
- "chunk_size",
- "content_disposition_type",
- "etag",
- "file_path",
- "file_system",
- "filename",
- "file_info",
- "stat_result",
- )
-
- def __init__(
- self,
- path: str | PathLike | Path,
- *,
- background: BackgroundTask | BackgroundTasks | None = None,
- chunk_size: int = ONE_MEGABYTE,
- content_disposition_type: Literal["attachment", "inline"] = "attachment",
- cookies: ResponseCookies | None = None,
- encoding: str = "utf-8",
- etag: ETag | None = None,
- file_info: FileInfo | Coroutine[Any, Any, FileInfo] | None = None,
- file_system: FileSystemProtocol | None = None,
- filename: str | None = None,
- headers: ResponseHeaders | None = None,
- media_type: Literal[MediaType.TEXT] | str | None = None,
- stat_result: stat_result_type | None = None,
- status_code: int | None = None,
- ) -> None:
- """Initialize ``File``
-
- Notes:
- - This class extends the :class:`Stream <.response.Stream>` class.
-
- Args:
- path: A file path in one of the supported formats.
- background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or
- :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished.
- Defaults to None.
- chunk_size: The chunk sizes to use when streaming the file. Defaults to 1MB.
- content_disposition_type: The type of the ``Content-Disposition``. Either ``inline`` or ``attachment``.
- cookies: A list of :class:`Cookie <.datastructures.Cookie>` instances to be set under the response
- ``Set-Cookie`` header.
- encoding: The encoding to be used for the response headers.
- etag: An optional :class:`ETag <.datastructures.ETag>` instance. If not provided, an etag will be
- generated.
- file_info: The output of calling :meth:`file_system.info <types.FileSystemProtocol.info>`, equivalent to
- providing an :class:`os.stat_result`.
- file_system: An implementation of the :class:`FileSystemProtocol <.types.FileSystemProtocol>`. If provided
- it will be used to load the file.
- filename: An optional filename to set in the header.
- headers: A string keyed dictionary of response headers. Header keys are insensitive.
- media_type: A value for the response ``Content-Type`` header. If not provided, the value will be either
- derived from the filename if provided and supported by the stdlib, or will default to
- ``application/octet-stream``.
- stat_result: An optional result of calling :func:os.stat:. If not provided, this will be done by the
- response constructor.
- status_code: An HTTP status code.
- """
-
- if file_system is not None and not (
- callable(getattr(file_system, "info", None)) and callable(getattr(file_system, "open", None))
- ):
- raise ImproperlyConfiguredException("file_system must adhere to the FileSystemProtocol type")
-
- self.chunk_size = chunk_size
- self.content_disposition_type = content_disposition_type
- self.etag = etag
- self.file_info = file_info
- self.file_path = path
- self.file_system = file_system
- self.filename = filename or ""
- self.stat_result = stat_result
-
- super().__init__(
- content=None,
- status_code=status_code,
- media_type=media_type,
- background=background,
- headers=headers,
- cookies=cookies,
- encoding=encoding,
- )
-
- def to_asgi_response(
- self,
- app: Litestar | None,
- request: Request,
- *,
- background: BackgroundTask | BackgroundTasks | None = None,
- encoded_headers: Iterable[tuple[bytes, bytes]] | None = None,
- cookies: Iterable[Cookie] | None = None,
- headers: dict[str, str] | None = None,
- is_head_response: bool = False,
- media_type: MediaType | str | None = None,
- status_code: int | None = None,
- type_encoders: TypeEncodersMap | None = None,
- ) -> ASGIFileResponse:
- """Create an :class:`ASGIFileResponse <litestar.response.file.ASGIFileResponse>` instance.
-
- Args:
- app: The :class:`Litestar <.app.Litestar>` application instance.
- background: Background task(s) to be executed after the response is sent.
- cookies: A list of cookies to be set on the response.
- encoded_headers: A list of already encoded headers.
- headers: Additional headers to be merged with the response headers. Response headers take precedence.
- is_head_response: Whether the response is a HEAD response.
- media_type: Media type for the response. If ``media_type`` is already set on the response, this is ignored.
- request: The :class:`Request <.connection.Request>` instance.
- status_code: Status code for the response. If ``status_code`` is already set on the response, this is
- type_encoders: A dictionary of type encoders to use for encoding the response content.
-
- Returns:
- A low-level ASGI file response.
- """
- if app is not None:
- warn_deprecation(
- version="2.1",
- deprecated_name="app",
- kind="parameter",
- removal_in="3.0.0",
- alternative="request.app",
- )
-
- headers = {**headers, **self.headers} if headers is not None else self.headers
- cookies = self.cookies if cookies is None else itertools.chain(self.cookies, cookies)
-
- media_type = self.media_type or media_type
- if media_type is not None:
- media_type = get_enum_string_value(media_type)
-
- return ASGIFileResponse(
- background=self.background or background,
- body=b"",
- chunk_size=self.chunk_size,
- content_disposition_type=self.content_disposition_type, # pyright: ignore
- content_length=0,
- cookies=cookies,
- encoded_headers=encoded_headers,
- encoding=self.encoding,
- etag=self.etag,
- file_info=self.file_info,
- file_path=self.file_path,
- file_system=self.file_system,
- filename=self.filename,
- headers=headers,
- is_head_response=is_head_response,
- media_type=media_type,
- stat_result=self.stat_result,
- status_code=self.status_code or status_code,
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/response/redirect.py b/venv/lib/python3.11/site-packages/litestar/response/redirect.py
deleted file mode 100644
index 6a07076..0000000
--- a/venv/lib/python3.11/site-packages/litestar/response/redirect.py
+++ /dev/null
@@ -1,169 +0,0 @@
-from __future__ import annotations
-
-import itertools
-from typing import TYPE_CHECKING, Any, Iterable, Literal
-
-from litestar.constants import REDIRECT_ALLOWED_MEDIA_TYPES, REDIRECT_STATUS_CODES
-from litestar.enums import MediaType
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.response.base import ASGIResponse, Response
-from litestar.status_codes import HTTP_302_FOUND
-from litestar.utils import url_quote
-from litestar.utils.deprecation import warn_deprecation
-from litestar.utils.helpers import get_enum_string_value
-
-if TYPE_CHECKING:
- from litestar.app import Litestar
- from litestar.background_tasks import BackgroundTask, BackgroundTasks
- from litestar.connection import Request
- from litestar.datastructures import Cookie
- from litestar.types import ResponseCookies, ResponseHeaders, TypeEncodersMap
-
-__all__ = (
- "ASGIRedirectResponse",
- "Redirect",
-)
-
-
-RedirectStatusType = Literal[301, 302, 303, 307, 308]
-"""Acceptable status codes for redirect responses."""
-
-
-class ASGIRedirectResponse(ASGIResponse):
- """A low-level ASGI redirect response class."""
-
- def __init__(
- self,
- path: str | bytes,
- media_type: str | None = None,
- status_code: RedirectStatusType | None = None,
- headers: dict[str, Any] | None = None,
- encoded_headers: Iterable[tuple[bytes, bytes]] | None = None,
- background: BackgroundTask | BackgroundTasks | None = None,
- body: bytes | str = b"",
- content_length: int | None = None,
- cookies: Iterable[Cookie] | None = None,
- encoding: str = "utf-8",
- is_head_response: bool = False,
- ) -> None:
- headers = {**(headers or {}), "location": url_quote(path)}
- media_type = media_type or MediaType.TEXT
- status_code = status_code or HTTP_302_FOUND
-
- if status_code not in REDIRECT_STATUS_CODES:
- raise ImproperlyConfiguredException(
- f"{status_code} is not a valid for this response. "
- f"Redirect responses should have one of "
- f"the following status codes: {', '.join([str(s) for s in REDIRECT_STATUS_CODES])}"
- )
-
- if media_type not in REDIRECT_ALLOWED_MEDIA_TYPES:
- raise ImproperlyConfiguredException(
- f"{media_type} media type is not supported yet. "
- f"Media type should be one of "
- f"the following values: {', '.join([str(s) for s in REDIRECT_ALLOWED_MEDIA_TYPES])}"
- )
-
- super().__init__(
- status_code=status_code,
- headers=headers,
- media_type=media_type,
- background=background,
- is_head_response=is_head_response,
- encoding=encoding,
- cookies=cookies,
- content_length=content_length,
- body=body,
- encoded_headers=encoded_headers,
- )
-
-
-class Redirect(Response[Any]):
- """A redirect response."""
-
- __slots__ = ("url",)
-
- def __init__(
- self,
- path: str,
- *,
- background: BackgroundTask | BackgroundTasks | None = None,
- cookies: ResponseCookies | None = None,
- encoding: str = "utf-8",
- headers: ResponseHeaders | None = None,
- media_type: str | MediaType | None = None,
- status_code: RedirectStatusType | None = None,
- type_encoders: TypeEncodersMap | None = None,
- ) -> None:
- """Initialize the response.
-
- Args:
- path: A path to redirect to.
- background: A background task or tasks to be run after the response is sent.
- cookies: A list of :class:`Cookie <.datastructures.Cookie>` instances to be set under the response
- ``Set-Cookie`` header.
- encoding: The encoding to be used for the response headers.
- headers: A string keyed dictionary of response headers. Header keys are insensitive.
- media_type: A value for the response ``Content-Type`` header.
- status_code: An HTTP status code. The status code should be one of 301, 302, 303, 307 or 308,
- otherwise an exception will be raised.
- type_encoders: A mapping of types to callables that transform them into types supported for serialization.
-
- Raises:
- ImproperlyConfiguredException: Either if status code is not a redirect status code or media type is not
- supported.
- """
- self.url = path
- if status_code is None:
- status_code = HTTP_302_FOUND
- super().__init__(
- background=background,
- content=b"",
- cookies=cookies,
- encoding=encoding,
- headers=headers,
- media_type=media_type,
- status_code=status_code,
- type_encoders=type_encoders,
- )
-
- def to_asgi_response(
- self,
- app: Litestar | None,
- request: Request,
- *,
- background: BackgroundTask | BackgroundTasks | None = None,
- cookies: Iterable[Cookie] | None = None,
- encoded_headers: Iterable[tuple[bytes, bytes]] | None = None,
- headers: dict[str, str] | None = None,
- is_head_response: bool = False,
- media_type: MediaType | str | None = None,
- status_code: int | None = None,
- type_encoders: TypeEncodersMap | None = None,
- ) -> ASGIResponse:
- headers = {**headers, **self.headers} if headers is not None else self.headers
- cookies = self.cookies if cookies is None else itertools.chain(self.cookies, cookies)
- media_type = get_enum_string_value(self.media_type or media_type or MediaType.TEXT)
-
- if app is not None:
- warn_deprecation(
- version="2.1",
- deprecated_name="app",
- kind="parameter",
- removal_in="3.0.0",
- alternative="request.app",
- )
-
- return ASGIRedirectResponse(
- path=self.url,
- background=self.background or background,
- body=b"",
- content_length=None,
- cookies=cookies,
- encoded_headers=encoded_headers,
- encoding=self.encoding,
- headers=headers,
- is_head_response=is_head_response,
- media_type=media_type,
- status_code=self.status_code or status_code, # type:ignore[arg-type]
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/response/sse.py b/venv/lib/python3.11/site-packages/litestar/response/sse.py
deleted file mode 100644
index 48a9192..0000000
--- a/venv/lib/python3.11/site-packages/litestar/response/sse.py
+++ /dev/null
@@ -1,180 +0,0 @@
-from __future__ import annotations
-
-import io
-import re
-from dataclasses import dataclass
-from typing import TYPE_CHECKING, Any, AsyncGenerator, AsyncIterable, AsyncIterator, Iterable, Iterator
-
-from litestar.concurrency import sync_to_thread
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.response.streaming import Stream
-from litestar.utils import AsyncIteratorWrapper
-
-if TYPE_CHECKING:
- from litestar.background_tasks import BackgroundTask, BackgroundTasks
- from litestar.types import ResponseCookies, ResponseHeaders, SSEData, StreamType
-
-_LINE_BREAK_RE = re.compile(r"\r\n|\r|\n")
-DEFAULT_SEPARATOR = "\r\n"
-
-
-class _ServerSentEventIterator(AsyncIteratorWrapper[bytes]):
- __slots__ = ("content_async_iterator", "event_id", "event_type", "retry_duration", "comment_message")
-
- content_async_iterator: AsyncIterable[SSEData]
-
- def __init__(
- self,
- content: str | bytes | StreamType[SSEData],
- event_type: str | None = None,
- event_id: int | str | None = None,
- retry_duration: int | None = None,
- comment_message: str | None = None,
- ) -> None:
- self.comment_message = comment_message
- self.event_id = event_id
- self.event_type = event_type
- self.retry_duration = retry_duration
- chunks: list[bytes] = []
- if comment_message is not None:
- chunks.extend([f": {chunk}\r\n".encode() for chunk in _LINE_BREAK_RE.split(comment_message)])
-
- if event_id is not None:
- chunks.append(f"id: {event_id}\r\n".encode())
-
- if event_type is not None:
- chunks.append(f"event: {event_type}\r\n".encode())
-
- if retry_duration is not None:
- chunks.append(f"retry: {retry_duration}\r\n".encode())
-
- super().__init__(iterator=chunks)
-
- if not isinstance(content, (Iterator, AsyncIterator, AsyncIteratorWrapper)) and callable(content):
- content = content() # type: ignore[unreachable]
-
- if isinstance(content, (str, bytes)):
- self.content_async_iterator = AsyncIteratorWrapper([content])
- elif isinstance(content, (Iterable, Iterator)):
- self.content_async_iterator = AsyncIteratorWrapper(content)
- elif isinstance(content, (AsyncIterable, AsyncIterator, AsyncIteratorWrapper)):
- self.content_async_iterator = content
- else:
- raise ImproperlyConfiguredException(f"Invalid type {type(content)} for ServerSentEvent")
-
- def ensure_bytes(self, data: str | int | bytes | dict | ServerSentEventMessage | Any, sep: str) -> bytes:
- if isinstance(data, ServerSentEventMessage):
- return data.encode()
- if isinstance(data, dict):
- data["sep"] = sep
- return ServerSentEventMessage(**data).encode()
-
- return ServerSentEventMessage(
- data=data, id=self.event_id, event=self.event_type, retry=self.retry_duration, sep=sep
- ).encode()
-
- def _call_next(self) -> bytes:
- try:
- return next(self.iterator)
- except StopIteration as e:
- raise ValueError from e
-
- async def _async_generator(self) -> AsyncGenerator[bytes, None]:
- while True:
- try:
- yield await sync_to_thread(self._call_next)
- except ValueError:
- async for value in self.content_async_iterator:
- yield self.ensure_bytes(value, DEFAULT_SEPARATOR)
- break
-
-
-@dataclass
-class ServerSentEventMessage:
- data: str | int | bytes | None = ""
- event: str | None = None
- id: int | str | None = None
- retry: int | None = None
- comment: str | None = None
- sep: str = DEFAULT_SEPARATOR
-
- def encode(self) -> bytes:
- buffer = io.StringIO()
- if self.comment is not None:
- for chunk in _LINE_BREAK_RE.split(str(self.comment)):
- buffer.write(f": {chunk}")
- buffer.write(self.sep)
-
- if self.id is not None:
- buffer.write(_LINE_BREAK_RE.sub("", f"id: {self.id}"))
- buffer.write(self.sep)
-
- if self.event is not None:
- buffer.write(_LINE_BREAK_RE.sub("", f"event: {self.event}"))
- buffer.write(self.sep)
-
- if self.data is not None:
- data = self.data
- for chunk in _LINE_BREAK_RE.split(data.decode() if isinstance(data, bytes) else str(data)):
- buffer.write(f"data: {chunk}")
- buffer.write(self.sep)
-
- if self.retry is not None:
- buffer.write(f"retry: {self.retry}")
- buffer.write(self.sep)
-
- buffer.write(self.sep)
- return buffer.getvalue().encode("utf-8")
-
-
-class ServerSentEvent(Stream):
- def __init__(
- self,
- content: str | bytes | StreamType[SSEData],
- *,
- background: BackgroundTask | BackgroundTasks | None = None,
- cookies: ResponseCookies | None = None,
- encoding: str = "utf-8",
- headers: ResponseHeaders | None = None,
- event_type: str | None = None,
- event_id: int | str | None = None,
- retry_duration: int | None = None,
- comment_message: str | None = None,
- status_code: int | None = None,
- ) -> None:
- """Initialize the response.
-
- Args:
- content: Bytes, string or a sync or async iterator or iterable.
- background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or
- :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished.
- Defaults to None.
- cookies: A list of :class:`Cookie <.datastructures.Cookie>` instances to be set under the response
- ``Set-Cookie`` header.
- encoding: The encoding to be used for the response headers.
- headers: A string keyed dictionary of response headers. Header keys are insensitive.
- status_code: The response status code. Defaults to 200.
- event_type: The type of the SSE event. If given, the browser will sent the event to any 'event-listener'
- declared for it (e.g. via 'addEventListener' in JS).
- event_id: The event ID. This sets the event source's 'last event id'.
- retry_duration: Retry duration in milliseconds.
- comment_message: A comment message. This value is ignored by clients and is used mostly for pinging.
- """
- super().__init__(
- content=_ServerSentEventIterator(
- content=content,
- event_type=event_type,
- event_id=event_id,
- retry_duration=retry_duration,
- comment_message=comment_message,
- ),
- media_type="text/event-stream",
- background=background,
- cookies=cookies,
- encoding=encoding,
- headers=headers,
- status_code=status_code,
- )
- self.headers.setdefault("Cache-Control", "no-cache")
- self.headers["Connection"] = "keep-alive"
- self.headers["X-Accel-Buffering"] = "no"
diff --git a/venv/lib/python3.11/site-packages/litestar/response/streaming.py b/venv/lib/python3.11/site-packages/litestar/response/streaming.py
deleted file mode 100644
index fc76522..0000000
--- a/venv/lib/python3.11/site-packages/litestar/response/streaming.py
+++ /dev/null
@@ -1,239 +0,0 @@
-from __future__ import annotations
-
-import itertools
-from functools import partial
-from typing import TYPE_CHECKING, Any, AsyncGenerator, AsyncIterable, AsyncIterator, Callable, Iterable, Iterator, Union
-
-from anyio import CancelScope, create_task_group
-
-from litestar.enums import MediaType
-from litestar.response.base import ASGIResponse, Response
-from litestar.types.helper_types import StreamType
-from litestar.utils.deprecation import warn_deprecation
-from litestar.utils.helpers import get_enum_string_value
-from litestar.utils.sync import AsyncIteratorWrapper
-
-if TYPE_CHECKING:
- from litestar.app import Litestar
- from litestar.background_tasks import BackgroundTask, BackgroundTasks
- from litestar.connection import Request
- from litestar.datastructures.cookie import Cookie
- from litestar.enums import OpenAPIMediaType
- from litestar.types import HTTPResponseBodyEvent, Receive, ResponseCookies, ResponseHeaders, Send, TypeEncodersMap
-
-__all__ = (
- "ASGIStreamingResponse",
- "Stream",
-)
-
-
-class ASGIStreamingResponse(ASGIResponse):
- """A streaming response."""
-
- __slots__ = ("iterator",)
-
- _should_set_content_length = False
-
- def __init__(
- self,
- *,
- iterator: StreamType,
- background: BackgroundTask | BackgroundTasks | None = None,
- body: bytes | str = b"",
- content_length: int | None = None,
- cookies: Iterable[Cookie] | None = None,
- encoded_headers: Iterable[tuple[bytes, bytes]] | None = None,
- encoding: str = "utf-8",
- headers: dict[str, Any] | None = None,
- is_head_response: bool = False,
- media_type: MediaType | str | None = None,
- status_code: int | None = None,
- ) -> None:
- """A low-level ASGI streaming response.
-
- Args:
- background: A background task or a list of background tasks to be executed after the response is sent.
- body: encoded content to send in the response body.
- content_length: The response content length.
- cookies: The response cookies.
- encoded_headers: The response headers.
- encoding: The response encoding.
- headers: The response headers.
- is_head_response: A boolean indicating if the response is a HEAD response.
- iterator: An async iterator or iterable.
- media_type: The response media type.
- status_code: The response status code.
- """
- super().__init__(
- background=background,
- body=body,
- content_length=content_length,
- cookies=cookies,
- encoding=encoding,
- headers=headers,
- is_head_response=is_head_response,
- media_type=media_type,
- status_code=status_code,
- encoded_headers=encoded_headers,
- )
- self.iterator: AsyncIterable[str | bytes] | AsyncGenerator[str | bytes, None] = (
- iterator if isinstance(iterator, (AsyncIterable, AsyncIterator)) else AsyncIteratorWrapper(iterator)
- )
-
- async def _listen_for_disconnect(self, cancel_scope: CancelScope, receive: Receive) -> None:
- """Listen for a cancellation message, and if received - call cancel on the cancel scope.
-
- Args:
- cancel_scope: A task group cancel scope instance.
- receive: The ASGI receive function.
-
- Returns:
- None
- """
- if not cancel_scope.cancel_called:
- message = await receive()
- if message["type"] == "http.disconnect":
- # despite the IDE warning, this is not a coroutine because anyio 3+ changed this.
- # therefore make sure not to await this.
- cancel_scope.cancel()
- else:
- await self._listen_for_disconnect(cancel_scope=cancel_scope, receive=receive)
-
- async def _stream(self, send: Send) -> None:
- """Send the chunks from the iterator as a stream of ASGI 'http.response.body' events.
-
- Args:
- send: The ASGI Send function.
-
- Returns:
- None
- """
- async for chunk in self.iterator:
- stream_event: HTTPResponseBodyEvent = {
- "type": "http.response.body",
- "body": chunk if isinstance(chunk, bytes) else chunk.encode(self.encoding),
- "more_body": True,
- }
- await send(stream_event)
- terminus_event: HTTPResponseBodyEvent = {"type": "http.response.body", "body": b"", "more_body": False}
- await send(terminus_event)
-
- async def send_body(self, send: Send, receive: Receive) -> None:
- """Emit a stream of events correlating with the response body.
-
- Args:
- send: The ASGI send function.
- receive: The ASGI receive function.
-
- Returns:
- None
- """
-
- async with create_task_group() as task_group:
- task_group.start_soon(partial(self._stream, send))
- await self._listen_for_disconnect(cancel_scope=task_group.cancel_scope, receive=receive)
-
-
-class Stream(Response[StreamType[Union[str, bytes]]]):
- """An HTTP response that streams the response data as a series of ASGI ``http.response.body`` events."""
-
- __slots__ = ("iterator",)
-
- def __init__(
- self,
- content: StreamType[str | bytes] | Callable[[], StreamType[str | bytes]],
- *,
- background: BackgroundTask | BackgroundTasks | None = None,
- cookies: ResponseCookies | None = None,
- encoding: str = "utf-8",
- headers: ResponseHeaders | None = None,
- media_type: MediaType | OpenAPIMediaType | str | None = None,
- status_code: int | None = None,
- ) -> None:
- """Initialize the response.
-
- Args:
- content: A sync or async iterator or iterable.
- background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or
- :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished.
- Defaults to None.
- cookies: A list of :class:`Cookie <.datastructures.Cookie>` instances to be set under the response
- ``Set-Cookie`` header.
- encoding: The encoding to be used for the response headers.
- headers: A string keyed dictionary of response headers. Header keys are insensitive.
- media_type: A value for the response ``Content-Type`` header.
- status_code: An HTTP status code.
- """
- super().__init__(
- background=background,
- content=b"", # type: ignore[arg-type]
- cookies=cookies,
- encoding=encoding,
- headers=headers,
- media_type=media_type,
- status_code=status_code,
- )
- self.iterator = content
-
- def to_asgi_response(
- self,
- app: Litestar | None,
- request: Request,
- *,
- background: BackgroundTask | BackgroundTasks | None = None,
- cookies: Iterable[Cookie] | None = None,
- encoded_headers: Iterable[tuple[bytes, bytes]] | None = None,
- headers: dict[str, str] | None = None,
- is_head_response: bool = False,
- media_type: MediaType | str | None = None,
- status_code: int | None = None,
- type_encoders: TypeEncodersMap | None = None,
- ) -> ASGIResponse:
- """Create an ASGIStreamingResponse from a StremaingResponse instance.
-
- Args:
- app: The :class:`Litestar <.app.Litestar>` application instance.
- background: Background task(s) to be executed after the response is sent.
- cookies: A list of cookies to be set on the response.
- encoded_headers: A list of already encoded headers.
- headers: Additional headers to be merged with the response headers. Response headers take precedence.
- is_head_response: Whether the response is a HEAD response.
- media_type: Media type for the response. If ``media_type`` is already set on the response, this is ignored.
- request: The :class:`Request <.connection.Request>` instance.
- status_code: Status code for the response. If ``status_code`` is already set on the response, this is
- type_encoders: A dictionary of type encoders to use for encoding the response content.
-
- Returns:
- An ASGIStreamingResponse instance.
- """
- if app is not None:
- warn_deprecation(
- version="2.1",
- deprecated_name="app",
- kind="parameter",
- removal_in="3.0.0",
- alternative="request.app",
- )
-
- headers = {**headers, **self.headers} if headers is not None else self.headers
- cookies = self.cookies if cookies is None else itertools.chain(self.cookies, cookies)
-
- media_type = get_enum_string_value(media_type or self.media_type or MediaType.JSON)
-
- iterator = self.iterator
- if not isinstance(iterator, (Iterable, Iterator, AsyncIterable, AsyncIterator)) and callable(iterator):
- iterator = iterator()
-
- return ASGIStreamingResponse(
- background=self.background or background,
- body=b"",
- content_length=0,
- cookies=cookies,
- encoded_headers=encoded_headers,
- encoding=self.encoding,
- headers=headers,
- is_head_response=is_head_response,
- iterator=iterator,
- media_type=media_type,
- status_code=self.status_code or status_code,
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/response/template.py b/venv/lib/python3.11/site-packages/litestar/response/template.py
deleted file mode 100644
index 6499aae..0000000
--- a/venv/lib/python3.11/site-packages/litestar/response/template.py
+++ /dev/null
@@ -1,162 +0,0 @@
-from __future__ import annotations
-
-import itertools
-from mimetypes import guess_type
-from pathlib import PurePath
-from typing import TYPE_CHECKING, Any, Iterable, cast
-
-from litestar.enums import MediaType
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.response.base import ASGIResponse, Response
-from litestar.status_codes import HTTP_200_OK
-from litestar.utils.deprecation import warn_deprecation
-from litestar.utils.empty import value_or_default
-from litestar.utils.scope.state import ScopeState
-
-if TYPE_CHECKING:
- from litestar.app import Litestar
- from litestar.background_tasks import BackgroundTask, BackgroundTasks
- from litestar.connection import Request
- from litestar.datastructures import Cookie
- from litestar.types import ResponseCookies, TypeEncodersMap
-
-__all__ = ("Template",)
-
-
-class Template(Response[bytes]):
- """Template-based response, rendering a given template into a bytes string."""
-
- __slots__ = (
- "template_name",
- "template_str",
- "context",
- )
-
- def __init__(
- self,
- template_name: str | None = None,
- *,
- template_str: str | None = None,
- background: BackgroundTask | BackgroundTasks | None = None,
- context: dict[str, Any] | None = None,
- cookies: ResponseCookies | None = None,
- encoding: str = "utf-8",
- headers: dict[str, Any] | None = None,
- media_type: MediaType | str | None = None,
- status_code: int = HTTP_200_OK,
- ) -> None:
- """Handle the rendering of a given template into a bytes string.
-
- Args:
- template_name: Path-like name for the template to be rendered, e.g. ``index.html``.
- template_str: A string representing the template, e.g. ``tmpl = "Hello <strong>World</strong>"``.
- background: A :class:`BackgroundTask <.background_tasks.BackgroundTask>` instance or
- :class:`BackgroundTasks <.background_tasks.BackgroundTasks>` to execute after the response is finished.
- Defaults to ``None``.
- context: A dictionary of key/value pairs to be passed to the temple engine's render method.
- cookies: A list of :class:`Cookie <.datastructures.Cookie>` instances to be set under the response
- ``Set-Cookie`` header.
- encoding: Content encoding
- headers: A string keyed dictionary of response headers. Header keys are insensitive.
- media_type: A string or member of the :class:`MediaType <.enums.MediaType>` enum. If not set, try to infer
- the media type based on the template name. If this fails, fall back to ``text/plain``.
- status_code: A value for the response HTTP status code.
- """
- if not (template_name or template_str):
- raise ValueError("Either template_name or template_str must be provided.")
-
- if template_name and template_str:
- raise ValueError("Either template_name or template_str must be provided, not both.")
-
- super().__init__(
- background=background,
- content=b"",
- cookies=cookies,
- encoding=encoding,
- headers=headers,
- media_type=media_type,
- status_code=status_code,
- )
- self.context = context or {}
- self.template_name = template_name
- self.template_str = template_str
-
- def create_template_context(self, request: Request) -> dict[str, Any]:
- """Create a context object for the template.
-
- Args:
- request: A :class:`Request <.connection.Request>` instance.
-
- Returns:
- A dictionary holding the template context
- """
- csrf_token = value_or_default(ScopeState.from_scope(request.scope).csrf_token, "")
- return {
- **self.context,
- "request": request,
- "csrf_input": f'<input type="hidden" name="_csrf_token" value="{csrf_token}" />',
- }
-
- def to_asgi_response(
- self,
- app: Litestar | None,
- request: Request,
- *,
- background: BackgroundTask | BackgroundTasks | None = None,
- cookies: Iterable[Cookie] | None = None,
- encoded_headers: Iterable[tuple[bytes, bytes]] | None = None,
- headers: dict[str, str] | None = None,
- is_head_response: bool = False,
- media_type: MediaType | str | None = None,
- status_code: int | None = None,
- type_encoders: TypeEncodersMap | None = None,
- ) -> ASGIResponse:
- if app is not None:
- warn_deprecation(
- version="2.1",
- deprecated_name="app",
- kind="parameter",
- removal_in="3.0.0",
- alternative="request.app",
- )
-
- if not (template_engine := request.app.template_engine):
- raise ImproperlyConfiguredException("Template engine is not configured")
-
- headers = {**headers, **self.headers} if headers is not None else self.headers
- cookies = self.cookies if cookies is None else itertools.chain(self.cookies, cookies)
-
- media_type = self.media_type or media_type
- if not media_type:
- if self.template_name:
- suffixes = PurePath(self.template_name).suffixes
- for suffix in suffixes:
- if _type := guess_type(f"name{suffix}")[0]:
- media_type = _type
- break
- else:
- media_type = MediaType.TEXT
- else:
- media_type = MediaType.HTML
-
- context = self.create_template_context(request)
-
- if self.template_str is not None:
- body = template_engine.render_string(self.template_str, context)
- else:
- # cast to str b/c we know that either template_name cannot be None if template_str is None
- template = template_engine.get_template(cast("str", self.template_name))
- body = template.render(**context).encode(self.encoding)
-
- return ASGIResponse(
- background=self.background or background,
- body=body,
- content_length=None,
- cookies=cookies,
- encoded_headers=encoded_headers,
- encoding=self.encoding,
- headers=headers,
- is_head_response=is_head_response,
- media_type=media_type,
- status_code=self.status_code or status_code,
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/router.py b/venv/lib/python3.11/site-packages/litestar/router.py
deleted file mode 100644
index 85346d8..0000000
--- a/venv/lib/python3.11/site-packages/litestar/router.py
+++ /dev/null
@@ -1,338 +0,0 @@
-from __future__ import annotations
-
-from collections import defaultdict
-from copy import copy, deepcopy
-from typing import TYPE_CHECKING, Any, Mapping, Sequence, cast
-
-from litestar._layers.utils import narrow_response_cookies, narrow_response_headers
-from litestar.controller import Controller
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.handlers.asgi_handlers import ASGIRouteHandler
-from litestar.handlers.http_handlers import HTTPRouteHandler
-from litestar.handlers.websocket_handlers import WebsocketListener, WebsocketRouteHandler
-from litestar.routes import ASGIRoute, HTTPRoute, WebSocketRoute
-from litestar.types.empty import Empty
-from litestar.utils import find_index, is_class_and_subclass, join_paths, normalize_path, unique
-from litestar.utils.signature import add_types_to_signature_namespace
-from litestar.utils.sync import ensure_async_callable
-
-__all__ = ("Router",)
-
-
-if TYPE_CHECKING:
- from litestar.connection import Request, WebSocket
- from litestar.datastructures import CacheControlHeader, ETag
- from litestar.dto import AbstractDTO
- from litestar.openapi.spec import SecurityRequirement
- from litestar.response import Response
- from litestar.routes import BaseRoute
- from litestar.types import (
- AfterRequestHookHandler,
- AfterResponseHookHandler,
- BeforeRequestHookHandler,
- ControllerRouterHandler,
- ExceptionHandlersMap,
- Guard,
- Middleware,
- ParametersMap,
- ResponseCookies,
- RouteHandlerMapItem,
- RouteHandlerType,
- TypeEncodersMap,
- )
- from litestar.types.composite_types import Dependencies, ResponseHeaders, TypeDecodersSequence
- from litestar.types.empty import EmptyType
-
-
-class Router:
- """The Litestar Router class.
-
- A Router instance is used to group controller, routers and route handler functions under a shared path fragment
- """
-
- __slots__ = (
- "after_request",
- "after_response",
- "before_request",
- "cache_control",
- "dependencies",
- "dto",
- "etag",
- "exception_handlers",
- "guards",
- "include_in_schema",
- "middleware",
- "opt",
- "owner",
- "parameters",
- "path",
- "registered_route_handler_ids",
- "request_class",
- "response_class",
- "response_cookies",
- "response_headers",
- "return_dto",
- "routes",
- "security",
- "signature_namespace",
- "tags",
- "type_decoders",
- "type_encoders",
- "websocket_class",
- )
-
- def __init__(
- self,
- path: str,
- *,
- after_request: AfterRequestHookHandler | None = None,
- after_response: AfterResponseHookHandler | None = None,
- before_request: BeforeRequestHookHandler | None = None,
- cache_control: CacheControlHeader | None = None,
- dependencies: Dependencies | None = None,
- dto: type[AbstractDTO] | None | EmptyType = Empty,
- etag: ETag | None = None,
- exception_handlers: ExceptionHandlersMap | None = None,
- guards: Sequence[Guard] | None = None,
- include_in_schema: bool | EmptyType = Empty,
- middleware: Sequence[Middleware] | None = None,
- opt: Mapping[str, Any] | None = None,
- parameters: ParametersMap | None = None,
- request_class: type[Request] | None = None,
- response_class: type[Response] | None = None,
- response_cookies: ResponseCookies | None = None,
- response_headers: ResponseHeaders | None = None,
- return_dto: type[AbstractDTO] | None | EmptyType = Empty,
- route_handlers: Sequence[ControllerRouterHandler],
- security: Sequence[SecurityRequirement] | None = None,
- signature_namespace: Mapping[str, Any] | None = None,
- signature_types: Sequence[Any] | None = None,
- tags: Sequence[str] | None = None,
- type_decoders: TypeDecodersSequence | None = None,
- type_encoders: TypeEncodersMap | None = None,
- websocket_class: type[WebSocket] | None = None,
- ) -> None:
- """Initialize a ``Router``.
-
- Args:
- after_request: A sync or async function executed before a :class:`Request <.connection.Request>` is passed
- to any route handler. If this function returns a value, the request will not reach the route handler,
- and instead this value will be used.
- after_response: A sync or async function called after the response has been awaited. It receives the
- :class:`Request <.connection.Request>` object and should not return any values.
- before_request: A sync or async function called immediately before calling the route handler. Receives
- the :class:`litestar.connection.Request` instance and any non-``None`` return value is used for the
- response, bypassing the route handler.
- cache_control: A ``cache-control`` header of type
- :class:`CacheControlHeader <.datastructures.CacheControlHeader>` to add to route handlers of
- this router. Can be overridden by route handlers.
- dependencies: A string keyed mapping of dependency :class:`Provide <.di.Provide>` instances.
- dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and
- validation of request data.
- etag: An ``etag`` header of type :class:`ETag <.datastructures.ETag>` to add to route handlers of this app.
- exception_handlers: A mapping of status codes and/or exception types to handler functions.
- guards: A sequence of :data:`Guard <.types.Guard>` callables.
- include_in_schema: A boolean flag dictating whether the route handler should be documented in the OpenAPI schema.
- middleware: A sequence of :data:`Middleware <.types.Middleware>`.
- opt: A string keyed mapping of arbitrary values that can be accessed in :data:`Guards <.types.Guard>` or
- wherever you have access to :class:`Request <.connection.Request>` or
- :data:`ASGI Scope <.types.Scope>`.
- parameters: A mapping of :func:`Parameter <.params.Parameter>` definitions available to all application
- paths.
- path: A path fragment that is prefixed to all route handlers, controllers and other routers associated
- with the router instance.
- request_class: A custom subclass of :class:`Request <.connection.Request>` to be used as the default for
- all route handlers, controllers and other routers associated with the router instance.
- response_class: A custom subclass of :class:`Response <.response.Response>` to be used as the default for
- all route handlers, controllers and other routers associated with the router instance.
- response_cookies: A sequence of :class:`Cookie <.datastructures.Cookie>` instances.
- response_headers: A string keyed mapping of :class:`ResponseHeader <.datastructures.ResponseHeader>`
- instances.
- return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing
- outbound response data.
- route_handlers: A required sequence of route handlers, which can include instances of
- :class:`Router <.router.Router>`, subclasses of :class:`Controller <.controller.Controller>` or any
- function decorated by the route handler decorators.
- security: A sequence of dicts that will be added to the schema of all route handlers in the application.
- See :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>`
- for details.
- signature_namespace: A mapping of names to types for use in forward reference resolution during signature modeling.
- signature_types: A sequence of types for use in forward reference resolution during signature modeling.
- These types will be added to the signature namespace using their ``__name__`` attribute.
- tags: A sequence of string tags that will be appended to the schema of all route handlers under the
- application.
- type_decoders: A sequence of tuples, each composed of a predicate testing for type identity and a msgspec hook for deserialization.
- type_encoders: A mapping of types to callables that transform them into types supported for serialization.
- websocket_class: A custom subclass of :class:`WebSocket <.connection.WebSocket>` to be used as the default for
- all route handlers, controllers and other routers associated with the router instance.
- """
-
- self.after_request = ensure_async_callable(after_request) if after_request else None # pyright: ignore
- self.after_response = ensure_async_callable(after_response) if after_response else None
- self.before_request = ensure_async_callable(before_request) if before_request else None
- self.cache_control = cache_control
- self.dto = dto
- self.etag = etag
- self.dependencies = dict(dependencies or {})
- self.exception_handlers = dict(exception_handlers or {})
- self.guards = list(guards or [])
- self.include_in_schema = include_in_schema
- self.middleware = list(middleware or [])
- self.opt = dict(opt or {})
- self.owner: Router | None = None
- self.parameters = dict(parameters or {})
- self.path = normalize_path(path)
- self.request_class = request_class
- self.response_class = response_class
- self.response_cookies = narrow_response_cookies(response_cookies)
- self.response_headers = narrow_response_headers(response_headers)
- self.return_dto = return_dto
- self.routes: list[HTTPRoute | ASGIRoute | WebSocketRoute] = []
- self.security = list(security or [])
- self.signature_namespace = add_types_to_signature_namespace(
- signature_types or [], dict(signature_namespace or {})
- )
- self.tags = list(tags or [])
- self.registered_route_handler_ids: set[int] = set()
- self.type_encoders = dict(type_encoders) if type_encoders is not None else None
- self.type_decoders = list(type_decoders) if type_decoders is not None else None
- self.websocket_class = websocket_class
-
- for route_handler in route_handlers or []:
- self.register(value=route_handler)
-
- def register(self, value: ControllerRouterHandler) -> list[BaseRoute]:
- """Register a Controller, Route instance or RouteHandler on the router.
-
- Args:
- value: a subclass or instance of Controller, an instance of :class:`Router` or a function/method that has
- been decorated by any of the routing decorators, e.g. :class:`get <.handlers.get>`,
- :class:`post <.handlers.post>`.
-
- Returns:
- Collection of handlers added to the router.
- """
- validated_value = self._validate_registration_value(value)
-
- routes: list[BaseRoute] = []
-
- for route_path, handlers_map in self.get_route_handler_map(value=validated_value).items():
- path = join_paths([self.path, route_path])
- if http_handlers := unique(
- [handler for handler in handlers_map.values() if isinstance(handler, HTTPRouteHandler)]
- ):
- if existing_handlers := unique(
- [
- handler
- for handler in self.route_handler_method_map.get(path, {}).values()
- if isinstance(handler, HTTPRouteHandler)
- ]
- ):
- http_handlers.extend(existing_handlers)
- existing_route_index = find_index(self.routes, lambda x: x.path == path) # noqa: B023
-
- if existing_route_index == -1: # pragma: no cover
- raise ImproperlyConfiguredException("unable to find_index existing route index")
-
- route: WebSocketRoute | ASGIRoute | HTTPRoute = HTTPRoute(
- path=path,
- route_handlers=http_handlers,
- )
- self.routes[existing_route_index] = route
- else:
- route = HTTPRoute(path=path, route_handlers=http_handlers)
- self.routes.append(route)
-
- routes.append(route)
-
- if websocket_handler := handlers_map.get("websocket"):
- route = WebSocketRoute(path=path, route_handler=cast("WebsocketRouteHandler", websocket_handler))
- self.routes.append(route)
- routes.append(route)
-
- if asgi_handler := handlers_map.get("asgi"):
- route = ASGIRoute(path=path, route_handler=cast("ASGIRouteHandler", asgi_handler))
- self.routes.append(route)
- routes.append(route)
-
- return routes
-
- @property
- def route_handler_method_map(self) -> dict[str, RouteHandlerMapItem]:
- """Map route paths to :class:`RouteHandlerMapItem <litestar.types.internal_typ es.RouteHandlerMapItem>`
-
- Returns:
- A dictionary mapping paths to route handlers
- """
- route_map: dict[str, RouteHandlerMapItem] = defaultdict(dict)
- for route in self.routes:
- if isinstance(route, HTTPRoute):
- for route_handler in route.route_handlers:
- for method in route_handler.http_methods:
- route_map[route.path][method] = route_handler
- else:
- route_map[route.path]["websocket" if isinstance(route, WebSocketRoute) else "asgi"] = (
- route.route_handler
- )
-
- return route_map
-
- @classmethod
- def get_route_handler_map(
- cls,
- value: Controller | RouteHandlerType | Router,
- ) -> dict[str, RouteHandlerMapItem]:
- """Map route handlers to HTTP methods."""
- if isinstance(value, Router):
- return value.route_handler_method_map
-
- if isinstance(value, (HTTPRouteHandler, ASGIRouteHandler, WebsocketRouteHandler)):
- copied_value = copy(value)
- if isinstance(value, HTTPRouteHandler):
- return {path: {http_method: copied_value for http_method in value.http_methods} for path in value.paths}
-
- return {
- path: {"websocket" if isinstance(value, WebsocketRouteHandler) else "asgi": copied_value}
- for path in value.paths
- }
-
- handlers_map: defaultdict[str, RouteHandlerMapItem] = defaultdict(dict)
- for route_handler in value.get_route_handlers():
- for handler_path in route_handler.paths:
- path = join_paths([value.path, handler_path]) if handler_path else value.path
- if isinstance(route_handler, HTTPRouteHandler):
- for http_method in route_handler.http_methods:
- handlers_map[path][http_method] = route_handler
- else:
- handlers_map[path]["websocket" if isinstance(route_handler, WebsocketRouteHandler) else "asgi"] = (
- cast("WebsocketRouteHandler | ASGIRouteHandler", route_handler)
- )
-
- return handlers_map
-
- def _validate_registration_value(self, value: ControllerRouterHandler) -> Controller | RouteHandlerType | Router:
- """Ensure values passed to the register method are supported."""
- if is_class_and_subclass(value, Controller):
- return value(owner=self)
-
- # this narrows down to an ABC, but we assume a non-abstract subclass of the ABC superclass
- if is_class_and_subclass(value, WebsocketListener):
- return value(owner=self).to_handler() # pyright: ignore
-
- if isinstance(value, Router):
- if value is self:
- raise ImproperlyConfiguredException("Cannot register a router on itself")
-
- router_copy = deepcopy(value)
- router_copy.owner = self
- return router_copy
-
- if isinstance(value, (ASGIRouteHandler, HTTPRouteHandler, WebsocketRouteHandler)):
- value.owner = self
- return value
-
- raise ImproperlyConfiguredException(
- "Unsupported value passed to `Router.register`. "
- "If you passed in a function or method, "
- "make sure to decorate it first with one of the routing decorators"
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/routes/__init__.py b/venv/lib/python3.11/site-packages/litestar/routes/__init__.py
deleted file mode 100644
index c8b5d3d..0000000
--- a/venv/lib/python3.11/site-packages/litestar/routes/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from .asgi import ASGIRoute
-from .base import BaseRoute
-from .http import HTTPRoute
-from .websocket import WebSocketRoute
-
-__all__ = ("BaseRoute", "ASGIRoute", "WebSocketRoute", "HTTPRoute")
diff --git a/venv/lib/python3.11/site-packages/litestar/routes/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/routes/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index ae8dee1..0000000
--- a/venv/lib/python3.11/site-packages/litestar/routes/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/routes/__pycache__/asgi.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/routes/__pycache__/asgi.cpython-311.pyc
deleted file mode 100644
index b3330b1..0000000
--- a/venv/lib/python3.11/site-packages/litestar/routes/__pycache__/asgi.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/routes/__pycache__/base.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/routes/__pycache__/base.cpython-311.pyc
deleted file mode 100644
index 98b66b4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/routes/__pycache__/base.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/routes/__pycache__/http.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/routes/__pycache__/http.cpython-311.pyc
deleted file mode 100644
index a430b70..0000000
--- a/venv/lib/python3.11/site-packages/litestar/routes/__pycache__/http.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/routes/__pycache__/websocket.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/routes/__pycache__/websocket.cpython-311.pyc
deleted file mode 100644
index 79da4a4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/routes/__pycache__/websocket.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/routes/asgi.py b/venv/lib/python3.11/site-packages/litestar/routes/asgi.py
deleted file mode 100644
index a8564d0..0000000
--- a/venv/lib/python3.11/site-packages/litestar/routes/asgi.py
+++ /dev/null
@@ -1,54 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any
-
-from litestar.connection import ASGIConnection
-from litestar.enums import ScopeType
-from litestar.routes.base import BaseRoute
-
-if TYPE_CHECKING:
- from litestar.handlers.asgi_handlers import ASGIRouteHandler
- from litestar.types import Receive, Scope, Send
-
-
-class ASGIRoute(BaseRoute):
- """An ASGI route, handling a single ``ASGIRouteHandler``"""
-
- __slots__ = ("route_handler",)
-
- def __init__(
- self,
- *,
- path: str,
- route_handler: ASGIRouteHandler,
- ) -> None:
- """Initialize the route.
-
- Args:
- path: The path for the route.
- route_handler: An instance of :class:`~.handlers.ASGIRouteHandler`.
- """
- self.route_handler = route_handler
- super().__init__(
- path=path,
- scope_type=ScopeType.ASGI,
- handler_names=[route_handler.handler_name],
- )
-
- async def handle(self, scope: Scope, receive: Receive, send: Send) -> None:
- """ASGI app that authorizes the connection and then awaits the handler function.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
-
- if self.route_handler.resolve_guards():
- connection = ASGIConnection["ASGIRouteHandler", Any, Any, Any](scope=scope, receive=receive)
- await self.route_handler.authorize_connection(connection=connection)
-
- await self.route_handler.fn(scope=scope, receive=receive, send=send)
diff --git a/venv/lib/python3.11/site-packages/litestar/routes/base.py b/venv/lib/python3.11/site-packages/litestar/routes/base.py
deleted file mode 100644
index b9baab4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/routes/base.py
+++ /dev/null
@@ -1,195 +0,0 @@
-from __future__ import annotations
-
-import re
-from abc import ABC, abstractmethod
-from datetime import date, datetime, time, timedelta
-from decimal import Decimal
-from pathlib import Path
-from typing import TYPE_CHECKING, Any, Callable
-from uuid import UUID
-
-import msgspec
-
-from litestar._kwargs import KwargsModel
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.types.internal_types import PathParameterDefinition
-from litestar.utils import join_paths, normalize_path
-
-if TYPE_CHECKING:
- from litestar.enums import ScopeType
- from litestar.handlers.base import BaseRouteHandler
- from litestar.types import Method, Receive, Scope, Send
-
-
-def _parse_datetime(value: str) -> datetime:
- return msgspec.convert(value, datetime)
-
-
-def _parse_date(value: str) -> date:
- return msgspec.convert(value, date)
-
-
-def _parse_time(value: str) -> time:
- return msgspec.convert(value, time)
-
-
-def _parse_timedelta(value: str) -> timedelta:
- try:
- return msgspec.convert(value, timedelta)
- except msgspec.ValidationError:
- return timedelta(seconds=int(float(value)))
-
-
-param_match_regex = re.compile(r"{(.*?)}")
-
-param_type_map = {
- "str": str,
- "int": int,
- "float": float,
- "uuid": UUID,
- "decimal": Decimal,
- "date": date,
- "datetime": datetime,
- "time": time,
- "timedelta": timedelta,
- "path": Path,
-}
-
-
-parsers_map: dict[Any, Callable[[Any], Any]] = {
- float: float,
- int: int,
- Decimal: Decimal,
- UUID: UUID,
- date: _parse_date,
- datetime: _parse_datetime,
- time: _parse_time,
- timedelta: _parse_timedelta,
-}
-
-
-class BaseRoute(ABC):
- """Base Route class used by Litestar.
-
- It's an abstract class meant to be extended.
- """
-
- __slots__ = (
- "app",
- "handler_names",
- "methods",
- "path",
- "path_format",
- "path_parameters",
- "path_components",
- "scope_type",
- )
-
- def __init__(
- self,
- *,
- handler_names: list[str],
- path: str,
- scope_type: ScopeType,
- methods: list[Method] | None = None,
- ) -> None:
- """Initialize the route.
-
- Args:
- handler_names: Names of the associated handler functions
- path: Base path of the route
- scope_type: Type of the ASGI scope
- methods: Supported methods
- """
- self.path, self.path_format, self.path_components = self._parse_path(path)
- self.path_parameters: tuple[PathParameterDefinition, ...] = tuple(
- component for component in self.path_components if isinstance(component, PathParameterDefinition)
- )
- self.handler_names = handler_names
- self.scope_type = scope_type
- self.methods = set(methods or [])
-
- @abstractmethod
- async def handle(self, scope: Scope, receive: Receive, send: Send) -> None:
- """ASGI App of the route.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
- raise NotImplementedError("Route subclasses must implement handle which serves as the ASGI app entry point")
-
- def create_handler_kwargs_model(self, route_handler: BaseRouteHandler) -> KwargsModel:
- """Create a `KwargsModel` for a given route handler."""
-
- path_parameters = set()
- for param in self.path_parameters:
- if param.name in path_parameters:
- raise ImproperlyConfiguredException(f"Duplicate parameter '{param.name}' detected in '{self.path}'.")
- path_parameters.add(param.name)
-
- return KwargsModel.create_for_signature_model(
- signature_model=route_handler.signature_model,
- parsed_signature=route_handler.parsed_fn_signature,
- dependencies=route_handler.resolve_dependencies(),
- path_parameters=path_parameters,
- layered_parameters=route_handler.resolve_layered_parameters(),
- )
-
- @staticmethod
- def _validate_path_parameter(param: str, path: str) -> None:
- """Validate that a path parameter adheres to the required format and datatypes.
-
- Raises:
- ImproperlyConfiguredException: If the parameter has an invalid format.
- """
- if len(param.split(":")) != 2:
- raise ImproperlyConfiguredException(
- f"Path parameters should be declared with a type using the following pattern: '{{parameter_name:type}}', e.g. '/my-path/{{my_param:int}}' in path: '{path}'"
- )
- param_name, param_type = (p.strip() for p in param.split(":"))
- if not param_name:
- raise ImproperlyConfiguredException("Path parameter names should be of length greater than zero")
- if param_type not in param_type_map:
- raise ImproperlyConfiguredException(
- f"Path parameters should be declared with an allowed type, i.e. one of {', '.join(param_type_map.keys())} in path: '{path}'"
- )
-
- @classmethod
- def _parse_path(cls, path: str) -> tuple[str, str, list[str | PathParameterDefinition]]:
- """Normalize and parse a path.
-
- Splits the path into a list of components, parsing any that are path parameters. Also builds the OpenAPI
- compatible path, which does not include the type of the path parameters.
-
- Returns:
- A 3-tuple of the normalized path, the OpenAPI formatted path, and the list of parsed components.
- """
- path = normalize_path(path)
-
- parsed_components: list[str | PathParameterDefinition] = []
- path_format_components = []
-
- components = [component for component in path.split("/") if component]
- for component in components:
- if param_match := param_match_regex.fullmatch(component):
- param = param_match.group(1)
- cls._validate_path_parameter(param, path)
- param_name, param_type = (p.strip() for p in param.split(":"))
- type_class = param_type_map[param_type]
- parser = parsers_map[type_class] if type_class not in {str, Path} else None
- parsed_components.append(
- PathParameterDefinition(name=param_name, type=type_class, full=param, parser=parser)
- )
- path_format_components.append("{" + param_name + "}")
- else:
- parsed_components.append(component)
- path_format_components.append(component)
-
- path_format = join_paths(path_format_components)
-
- return path, path_format, parsed_components
diff --git a/venv/lib/python3.11/site-packages/litestar/routes/http.py b/venv/lib/python3.11/site-packages/litestar/routes/http.py
deleted file mode 100644
index b1f70cb..0000000
--- a/venv/lib/python3.11/site-packages/litestar/routes/http.py
+++ /dev/null
@@ -1,327 +0,0 @@
-from __future__ import annotations
-
-from itertools import chain
-from typing import TYPE_CHECKING, Any, cast
-
-from msgspec.msgpack import decode as _decode_msgpack_plain
-
-from litestar.constants import DEFAULT_ALLOWED_CORS_HEADERS
-from litestar.datastructures.headers import Headers
-from litestar.datastructures.upload_file import UploadFile
-from litestar.enums import HttpMethod, MediaType, ScopeType
-from litestar.exceptions import ClientException, ImproperlyConfiguredException, SerializationException
-from litestar.handlers.http_handlers import HTTPRouteHandler
-from litestar.response import Response
-from litestar.routes.base import BaseRoute
-from litestar.status_codes import HTTP_204_NO_CONTENT, HTTP_400_BAD_REQUEST
-from litestar.types.empty import Empty
-from litestar.utils.scope.state import ScopeState
-
-if TYPE_CHECKING:
- from litestar._kwargs import KwargsModel
- from litestar._kwargs.cleanup import DependencyCleanupGroup
- from litestar.connection import Request
- from litestar.types import ASGIApp, HTTPScope, Method, Receive, Scope, Send
-
-
-class HTTPRoute(BaseRoute):
- """An HTTP route, capable of handling multiple ``HTTPRouteHandler``\\ s.""" # noqa: D301
-
- __slots__ = (
- "route_handler_map",
- "route_handlers",
- )
-
- def __init__(
- self,
- *,
- path: str,
- route_handlers: list[HTTPRouteHandler],
- ) -> None:
- """Initialize ``HTTPRoute``.
-
- Args:
- path: The path for the route.
- route_handlers: A list of :class:`~.handlers.HTTPRouteHandler`.
- """
- methods = list(chain.from_iterable([route_handler.http_methods for route_handler in route_handlers]))
- if "OPTIONS" not in methods:
- methods.append("OPTIONS")
- options_handler = self.create_options_handler(path)
- options_handler.owner = route_handlers[0].owner
- route_handlers.append(options_handler)
-
- self.route_handlers = route_handlers
- self.route_handler_map: dict[Method, tuple[HTTPRouteHandler, KwargsModel]] = {}
-
- super().__init__(
- methods=methods,
- path=path,
- scope_type=ScopeType.HTTP,
- handler_names=[route_handler.handler_name for route_handler in self.route_handlers],
- )
-
- async def handle(self, scope: HTTPScope, receive: Receive, send: Send) -> None: # type: ignore[override]
- """ASGI app that creates a Request from the passed in args, determines which handler function to call and then
- handles the call.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
- route_handler, parameter_model = self.route_handler_map[scope["method"]]
- request: Request[Any, Any, Any] = route_handler.resolve_request_class()(scope=scope, receive=receive, send=send)
-
- if route_handler.resolve_guards():
- await route_handler.authorize_connection(connection=request)
-
- response = await self._get_response_for_request(
- scope=scope, request=request, route_handler=route_handler, parameter_model=parameter_model
- )
-
- await response(scope, receive, send)
-
- if after_response_handler := route_handler.resolve_after_response():
- await after_response_handler(request)
-
- if form_data := scope.get("_form", {}):
- await self._cleanup_temporary_files(form_data=cast("dict[str, Any]", form_data))
-
- def create_handler_map(self) -> None:
- """Parse the ``router_handlers`` of this route and return a mapping of
- http- methods and route handlers.
- """
- for route_handler in self.route_handlers:
- kwargs_model = self.create_handler_kwargs_model(route_handler=route_handler)
- for http_method in route_handler.http_methods:
- if self.route_handler_map.get(http_method):
- raise ImproperlyConfiguredException(
- f"Handler already registered for path {self.path!r} and http method {http_method}"
- )
- self.route_handler_map[http_method] = (route_handler, kwargs_model)
-
- async def _get_response_for_request(
- self,
- scope: Scope,
- request: Request[Any, Any, Any],
- route_handler: HTTPRouteHandler,
- parameter_model: KwargsModel,
- ) -> ASGIApp:
- """Return a response for the request.
-
- If caching is enabled and a response exist in the cache, the cached response will be returned.
- If caching is enabled and a response does not exist in the cache, the newly created
- response will be cached.
-
- Args:
- scope: The Request's scope
- request: The Request instance
- route_handler: The HTTPRouteHandler instance
- parameter_model: The Handler's KwargsModel
-
- Returns:
- An instance of Response or a compatible ASGIApp or a subclass of it
- """
- if route_handler.cache and (
- response := await self._get_cached_response(request=request, route_handler=route_handler)
- ):
- return response
-
- return await self._call_handler_function(
- scope=scope, request=request, parameter_model=parameter_model, route_handler=route_handler
- )
-
- async def _call_handler_function(
- self, scope: Scope, request: Request, parameter_model: KwargsModel, route_handler: HTTPRouteHandler
- ) -> ASGIApp:
- """Call the before request handlers, retrieve any data required for the route handler, and call the route
- handler's ``to_response`` method.
-
- This is wrapped in a try except block - and if an exception is raised,
- it tries to pass it to an appropriate exception handler - if defined.
- """
- response_data: Any = None
- cleanup_group: DependencyCleanupGroup | None = None
-
- if before_request_handler := route_handler.resolve_before_request():
- response_data = await before_request_handler(request)
-
- if not response_data:
- response_data, cleanup_group = await self._get_response_data(
- route_handler=route_handler, parameter_model=parameter_model, request=request
- )
-
- response: ASGIApp = await route_handler.to_response(app=scope["app"], data=response_data, request=request)
-
- if cleanup_group:
- await cleanup_group.cleanup()
-
- return response
-
- @staticmethod
- async def _get_response_data(
- route_handler: HTTPRouteHandler, parameter_model: KwargsModel, request: Request
- ) -> tuple[Any, DependencyCleanupGroup | None]:
- """Determine what kwargs are required for the given route handler's ``fn`` and calls it."""
- parsed_kwargs: dict[str, Any] = {}
- cleanup_group: DependencyCleanupGroup | None = None
-
- if parameter_model.has_kwargs and route_handler.signature_model:
- kwargs = parameter_model.to_kwargs(connection=request)
-
- if "data" in kwargs:
- try:
- data = await kwargs["data"]
- except SerializationException as e:
- raise ClientException(str(e)) from e
-
- if data is Empty:
- del kwargs["data"]
- else:
- kwargs["data"] = data
-
- if "body" in kwargs:
- kwargs["body"] = await kwargs["body"]
-
- if parameter_model.dependency_batches:
- cleanup_group = await parameter_model.resolve_dependencies(request, kwargs)
-
- parsed_kwargs = route_handler.signature_model.parse_values_from_connection_kwargs(
- connection=request, **kwargs
- )
-
- if cleanup_group:
- async with cleanup_group:
- data = (
- route_handler.fn(**parsed_kwargs)
- if route_handler.has_sync_callable
- else await route_handler.fn(**parsed_kwargs)
- )
- elif route_handler.has_sync_callable:
- data = route_handler.fn(**parsed_kwargs)
- else:
- data = await route_handler.fn(**parsed_kwargs)
-
- return data, cleanup_group
-
- @staticmethod
- async def _get_cached_response(request: Request, route_handler: HTTPRouteHandler) -> ASGIApp | None:
- """Retrieve and un-pickle the cached response, if existing.
-
- Args:
- request: The :class:`Request <litestar.connection.Request>` instance
- route_handler: The :class:`~.handlers.HTTPRouteHandler` instance
-
- Returns:
- A cached response instance, if existing.
- """
-
- cache_config = request.app.response_cache_config
- cache_key = (route_handler.cache_key_builder or cache_config.key_builder)(request)
- store = cache_config.get_store_from_app(request.app)
-
- if not (cached_response_data := await store.get(key=cache_key)):
- return None
-
- # we use the regular msgspec.msgpack.decode here since we don't need any of
- # the added decoders
- messages = _decode_msgpack_plain(cached_response_data)
-
- async def cached_response(scope: Scope, receive: Receive, send: Send) -> None:
- ScopeState.from_scope(scope).is_cached = True
- for message in messages:
- await send(message)
-
- return cached_response
-
- def create_options_handler(self, path: str) -> HTTPRouteHandler:
- """Args:
- path: The route path
-
- Returns:
- An HTTP route handler for OPTIONS requests.
- """
-
- def options_handler(scope: Scope) -> Response:
- """Handler function for OPTIONS requests.
-
- Args:
- scope: The ASGI Scope.
-
- Returns:
- Response
- """
- cors_config = scope["app"].cors_config
- request_headers = Headers.from_scope(scope=scope)
- origin = request_headers.get("origin")
-
- if cors_config and origin:
- pre_flight_method = request_headers.get("Access-Control-Request-Method")
- failures = []
-
- if not cors_config.is_allow_all_methods and (
- pre_flight_method and pre_flight_method not in cors_config.allow_methods
- ):
- failures.append("method")
-
- response_headers = cors_config.preflight_headers.copy()
-
- if not cors_config.is_origin_allowed(origin):
- failures.append("Origin")
- elif response_headers.get("Access-Control-Allow-Origin") != "*":
- response_headers["Access-Control-Allow-Origin"] = origin
-
- pre_flight_requested_headers = [
- header.strip()
- for header in request_headers.get("Access-Control-Request-Headers", "").split(",")
- if header.strip()
- ]
-
- if pre_flight_requested_headers:
- if cors_config.is_allow_all_headers:
- response_headers["Access-Control-Allow-Headers"] = ", ".join(
- sorted(set(pre_flight_requested_headers) | DEFAULT_ALLOWED_CORS_HEADERS) # pyright: ignore
- )
- elif any(
- header.lower() not in cors_config.allow_headers for header in pre_flight_requested_headers
- ):
- failures.append("headers")
-
- return (
- Response(
- content=f"Disallowed CORS {', '.join(failures)}",
- status_code=HTTP_400_BAD_REQUEST,
- media_type=MediaType.TEXT,
- )
- if failures
- else Response(
- content=None,
- status_code=HTTP_204_NO_CONTENT,
- media_type=MediaType.TEXT,
- headers=response_headers,
- )
- )
-
- return Response(
- content=None,
- status_code=HTTP_204_NO_CONTENT,
- headers={"Allow": ", ".join(sorted(self.methods))}, # pyright: ignore
- media_type=MediaType.TEXT,
- )
-
- return HTTPRouteHandler(
- path=path,
- http_method=[HttpMethod.OPTIONS],
- include_in_schema=False,
- sync_to_thread=False,
- )(options_handler)
-
- @staticmethod
- async def _cleanup_temporary_files(form_data: dict[str, Any]) -> None:
- for v in form_data.values():
- if isinstance(v, UploadFile) and not v.file.closed:
- await v.close()
diff --git a/venv/lib/python3.11/site-packages/litestar/routes/websocket.py b/venv/lib/python3.11/site-packages/litestar/routes/websocket.py
deleted file mode 100644
index ebf4959..0000000
--- a/venv/lib/python3.11/site-packages/litestar/routes/websocket.py
+++ /dev/null
@@ -1,86 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any
-
-from litestar.enums import ScopeType
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.routes.base import BaseRoute
-
-if TYPE_CHECKING:
- from litestar._kwargs import KwargsModel
- from litestar._kwargs.cleanup import DependencyCleanupGroup
- from litestar.connection import WebSocket
- from litestar.handlers.websocket_handlers import WebsocketRouteHandler
- from litestar.types import Receive, Send, WebSocketScope
-
-
-class WebSocketRoute(BaseRoute):
- """A websocket route, handling a single ``WebsocketRouteHandler``"""
-
- __slots__ = (
- "route_handler",
- "handler_parameter_model",
- )
-
- def __init__(
- self,
- *,
- path: str,
- route_handler: WebsocketRouteHandler,
- ) -> None:
- """Initialize the route.
-
- Args:
- path: The path for the route.
- route_handler: An instance of :class:`~.handlers.WebsocketRouteHandler`.
- """
- self.route_handler = route_handler
- self.handler_parameter_model: KwargsModel | None = None
-
- super().__init__(
- path=path,
- scope_type=ScopeType.WEBSOCKET,
- handler_names=[route_handler.handler_name],
- )
-
- async def handle(self, scope: WebSocketScope, receive: Receive, send: Send) -> None: # type: ignore[override]
- """ASGI app that creates a WebSocket from the passed in args, and then awaits the handler function.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
-
- if not self.handler_parameter_model: # pragma: no cover
- raise ImproperlyConfiguredException("handler parameter model not defined")
-
- websocket: WebSocket[Any, Any, Any] = self.route_handler.resolve_websocket_class()(
- scope=scope, receive=receive, send=send
- )
-
- if self.route_handler.resolve_guards():
- await self.route_handler.authorize_connection(connection=websocket)
-
- parsed_kwargs: dict[str, Any] = {}
- cleanup_group: DependencyCleanupGroup | None = None
-
- if self.handler_parameter_model.has_kwargs and self.route_handler.signature_model:
- parsed_kwargs = self.handler_parameter_model.to_kwargs(connection=websocket)
-
- if self.handler_parameter_model.dependency_batches:
- cleanup_group = await self.handler_parameter_model.resolve_dependencies(websocket, parsed_kwargs)
-
- parsed_kwargs = self.route_handler.signature_model.parse_values_from_connection_kwargs(
- connection=websocket, **parsed_kwargs
- )
-
- if cleanup_group:
- async with cleanup_group:
- await self.route_handler.fn(**parsed_kwargs)
- await cleanup_group.cleanup()
- else:
- await self.route_handler.fn(**parsed_kwargs)
diff --git a/venv/lib/python3.11/site-packages/litestar/security/__init__.py b/venv/lib/python3.11/site-packages/litestar/security/__init__.py
deleted file mode 100644
index d864d43..0000000
--- a/venv/lib/python3.11/site-packages/litestar/security/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from litestar.security.base import AbstractSecurityConfig
-
-__all__ = ("AbstractSecurityConfig",)
diff --git a/venv/lib/python3.11/site-packages/litestar/security/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/security/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 419b39e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/security/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/security/__pycache__/base.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/security/__pycache__/base.cpython-311.pyc
deleted file mode 100644
index 6133974..0000000
--- a/venv/lib/python3.11/site-packages/litestar/security/__pycache__/base.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/security/base.py b/venv/lib/python3.11/site-packages/litestar/security/base.py
deleted file mode 100644
index fbe7913..0000000
--- a/venv/lib/python3.11/site-packages/litestar/security/base.py
+++ /dev/null
@@ -1,183 +0,0 @@
-from __future__ import annotations
-
-from abc import ABC, abstractmethod
-from copy import copy
-from dataclasses import field
-from typing import TYPE_CHECKING, Any, Callable, Generic, Iterable, Sequence, TypeVar, cast
-
-from litestar import Response
-from litestar.utils.sync import ensure_async_callable
-
-if TYPE_CHECKING:
- from litestar.config.app import AppConfig
- from litestar.connection import ASGIConnection
- from litestar.di import Provide
- from litestar.enums import MediaType, OpenAPIMediaType
- from litestar.middleware.authentication import AbstractAuthenticationMiddleware
- from litestar.middleware.base import DefineMiddleware
- from litestar.openapi.spec import Components, SecurityRequirement
- from litestar.types import (
- ControllerRouterHandler,
- Guard,
- Method,
- ResponseCookies,
- Scopes,
- SyncOrAsyncUnion,
- TypeEncodersMap,
- )
-
-__all__ = ("AbstractSecurityConfig",)
-
-UserType = TypeVar("UserType")
-AuthType = TypeVar("AuthType")
-
-
-class AbstractSecurityConfig(ABC, Generic[UserType, AuthType]):
- """A base class for Security Configs - this class can be used on the application level
- or be manually configured on the router / controller level to provide auth.
- """
-
- authentication_middleware_class: type[AbstractAuthenticationMiddleware]
- """The authentication middleware class to use.
-
- Must inherit from
- :class:`AbstractAuthenticationMiddleware <litestar.middleware.authentication.AbstractAuthenticationMiddleware>`
- """
- guards: Iterable[Guard] | None = None
- """An iterable of guards to call for requests, providing authorization functionalities."""
- exclude: str | list[str] | None = None
- """A pattern or list of patterns to skip in the authentication middleware."""
- exclude_opt_key: str = "exclude_from_auth"
- """An identifier to use on routes to disable authentication and authorization checks for a particular route."""
- exclude_http_methods: Sequence[Method] | None = field(
- default_factory=lambda: cast("Sequence[Method]", ["OPTIONS", "HEAD"])
- )
- """A sequence of http methods that do not require authentication. Defaults to ['OPTIONS', 'HEAD']"""
- scopes: Scopes | None = None
- """ASGI scopes processed by the authentication middleware, if ``None``, both ``http`` and ``websocket`` will be
- processed."""
- route_handlers: Iterable[ControllerRouterHandler] | None = None
- """An optional iterable of route handlers to register."""
- dependencies: dict[str, Provide] | None = None
- """An optional dictionary of dependency providers."""
- retrieve_user_handler: Callable[[Any, ASGIConnection], SyncOrAsyncUnion[Any | None]]
- """Callable that receives the ``auth`` value from the authentication middleware and returns a ``user`` value.
-
- Notes:
- - User and Auth can be any arbitrary values specified by the security backend.
- - The User and Auth values will be set by the middleware as ``scope["user"]`` and ``scope["auth"]`` respectively.
- Once provided, they can access via the ``connection.user`` and ``connection.auth`` properties.
- - The callable can be sync or async. If it is sync, it will be wrapped to support async.
-
- """
- type_encoders: TypeEncodersMap | None = None
- """A mapping of types to callables that transform them into types supported for serialization."""
-
- def on_app_init(self, app_config: AppConfig) -> AppConfig:
- """Handle app init by injecting middleware, guards etc. into the app. This method can be used only on the app
- level.
-
- Args:
- app_config: An instance of :class:`AppConfig <.config.app.AppConfig>`
-
- Returns:
- The :class:`AppConfig <.config.app.AppConfig>`.
- """
- app_config.middleware.insert(0, self.middleware)
-
- if app_config.openapi_config:
- app_config.openapi_config = copy(app_config.openapi_config)
- if isinstance(app_config.openapi_config.components, list):
- app_config.openapi_config.components.append(self.openapi_components)
- elif app_config.openapi_config.components:
- app_config.openapi_config.components = [self.openapi_components, app_config.openapi_config.components]
- else:
- app_config.openapi_config.components = [self.openapi_components]
-
- if isinstance(app_config.openapi_config.security, list):
- app_config.openapi_config.security.append(self.security_requirement)
- else:
- app_config.openapi_config.security = [self.security_requirement]
-
- if self.guards:
- app_config.guards.extend(self.guards)
-
- if self.dependencies:
- app_config.dependencies.update(self.dependencies)
-
- if self.route_handlers:
- app_config.route_handlers.extend(self.route_handlers)
-
- if self.type_encoders is None:
- self.type_encoders = app_config.type_encoders
-
- return app_config
-
- def create_response(
- self,
- content: Any | None,
- status_code: int,
- media_type: MediaType | OpenAPIMediaType | str,
- headers: dict[str, Any] | None = None,
- cookies: ResponseCookies | None = None,
- ) -> Response[Any]:
- """Create a response object.
-
- Handles setting the type encoders mapping on the response.
-
- Args:
- content: A value for the response body that will be rendered into bytes string.
- status_code: An HTTP status code.
- media_type: A value for the response 'Content-Type' header.
- headers: A string keyed dictionary of response headers. Header keys are insensitive.
- cookies: A list of :class:`Cookie <litestar.datastructures.Cookie>` instances to be set under
- the response 'Set-Cookie' header.
-
- Returns:
- A response object.
- """
- return Response(
- content=content,
- status_code=status_code,
- media_type=media_type,
- headers=headers,
- cookies=cookies,
- type_encoders=self.type_encoders,
- )
-
- def __post_init__(self) -> None:
- self.retrieve_user_handler = ensure_async_callable(self.retrieve_user_handler)
-
- @property
- @abstractmethod
- def openapi_components(self) -> Components:
- """Create OpenAPI documentation for the JWT auth schema used.
-
- Returns:
- An :class:`Components <litestar.openapi.spec.components.Components>` instance.
- """
- raise NotImplementedError
-
- @property
- @abstractmethod
- def security_requirement(self) -> SecurityRequirement:
- """Return OpenAPI 3.1.
-
- :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>` for the auth
- backend.
-
- Returns:
- An OpenAPI 3.1 :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>` dictionary.
- """
- raise NotImplementedError
-
- @property
- @abstractmethod
- def middleware(self) -> DefineMiddleware:
- """Create an instance of the config's ``authentication_middleware_class`` attribute and any required kwargs,
- wrapping it in Litestar's ``DefineMiddleware``.
-
- Returns:
- An instance of :class:`DefineMiddleware <litestar.middleware.base.DefineMiddleware>`.
- """
- raise NotImplementedError
diff --git a/venv/lib/python3.11/site-packages/litestar/security/jwt/__init__.py b/venv/lib/python3.11/site-packages/litestar/security/jwt/__init__.py
deleted file mode 100644
index 4fd88de..0000000
--- a/venv/lib/python3.11/site-packages/litestar/security/jwt/__init__.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from litestar.security.jwt.auth import (
- BaseJWTAuth,
- JWTAuth,
- JWTCookieAuth,
- OAuth2Login,
- OAuth2PasswordBearerAuth,
-)
-from litestar.security.jwt.middleware import (
- JWTAuthenticationMiddleware,
- JWTCookieAuthenticationMiddleware,
-)
-from litestar.security.jwt.token import Token
-
-__all__ = (
- "BaseJWTAuth",
- "JWTAuth",
- "JWTAuthenticationMiddleware",
- "JWTCookieAuth",
- "JWTCookieAuthenticationMiddleware",
- "OAuth2Login",
- "OAuth2PasswordBearerAuth",
- "Token",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/security/jwt/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/security/jwt/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index f04d57f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/security/jwt/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/security/jwt/__pycache__/auth.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/security/jwt/__pycache__/auth.cpython-311.pyc
deleted file mode 100644
index cec42c0..0000000
--- a/venv/lib/python3.11/site-packages/litestar/security/jwt/__pycache__/auth.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/security/jwt/__pycache__/middleware.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/security/jwt/__pycache__/middleware.cpython-311.pyc
deleted file mode 100644
index 8d5603e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/security/jwt/__pycache__/middleware.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/security/jwt/__pycache__/token.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/security/jwt/__pycache__/token.cpython-311.pyc
deleted file mode 100644
index b4f8c45..0000000
--- a/venv/lib/python3.11/site-packages/litestar/security/jwt/__pycache__/token.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/security/jwt/auth.py b/venv/lib/python3.11/site-packages/litestar/security/jwt/auth.py
deleted file mode 100644
index 2a0f094..0000000
--- a/venv/lib/python3.11/site-packages/litestar/security/jwt/auth.py
+++ /dev/null
@@ -1,691 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import asdict, dataclass, field
-from datetime import datetime, timedelta, timezone
-from typing import TYPE_CHECKING, Any, Callable, Generic, Iterable, Literal, Sequence, TypeVar, cast
-
-from litestar.datastructures import Cookie
-from litestar.enums import MediaType
-from litestar.middleware import DefineMiddleware
-from litestar.openapi.spec import Components, OAuthFlow, OAuthFlows, SecurityRequirement, SecurityScheme
-from litestar.security.base import AbstractSecurityConfig
-from litestar.security.jwt.middleware import JWTAuthenticationMiddleware, JWTCookieAuthenticationMiddleware
-from litestar.security.jwt.token import Token
-from litestar.status_codes import HTTP_201_CREATED
-from litestar.types import ControllerRouterHandler, Empty, Guard, Method, Scopes, SyncOrAsyncUnion, TypeEncodersMap
-
-__all__ = ("BaseJWTAuth", "JWTAuth", "JWTCookieAuth", "OAuth2Login", "OAuth2PasswordBearerAuth")
-
-
-if TYPE_CHECKING:
- from litestar import Response
- from litestar.connection import ASGIConnection
- from litestar.di import Provide
-
-
-UserType = TypeVar("UserType")
-
-
-class BaseJWTAuth(Generic[UserType], AbstractSecurityConfig[UserType, Token]):
- """Base class for JWT Auth backends"""
-
- token_secret: str
- """Key with which to generate the token hash.
-
- Notes:
- - This value should be kept as a secret and the standard practice is to inject it into the environment.
- """
- retrieve_user_handler: Callable[[Any, ASGIConnection], SyncOrAsyncUnion[Any | None]]
- """Callable that receives the ``auth`` value from the authentication middleware and returns a ``user`` value.
-
- Notes:
- - User and Auth can be any arbitrary values specified by the security backend.
- - The User and Auth values will be set by the middleware as ``scope["user"]`` and ``scope["auth"]`` respectively.
- Once provided, they can access via the ``connection.user`` and ``connection.auth`` properties.
- - The callable can be sync or async. If it is sync, it will be wrapped to support async.
-
- """
- algorithm: str
- """Algorithm to use for JWT hashing."""
- auth_header: str
- """Request header key from which to retrieve the token.
-
- E.g. ``Authorization`` or ``X-Api-Key``.
- """
- default_token_expiration: timedelta
- """The default value for token expiration."""
- openapi_security_scheme_name: str
- """The value to use for the OpenAPI security scheme and security requirements."""
- description: str
- """Description for the OpenAPI security scheme."""
- authentication_middleware_class: type[JWTAuthenticationMiddleware] # pyright: ignore
- """The authentication middleware class to use.
-
- Must inherit from :class:`JWTAuthenticationMiddleware`
- """
-
- @property
- def openapi_components(self) -> Components:
- """Create OpenAPI documentation for the JWT auth schema used.
-
- Returns:
- An :class:`Components <litestar.openapi.spec.components.Components>` instance.
- """
- return Components(
- security_schemes={
- self.openapi_security_scheme_name: SecurityScheme(
- type="http",
- scheme="Bearer",
- name=self.auth_header,
- bearer_format="JWT",
- description=self.description,
- )
- }
- )
-
- @property
- def security_requirement(self) -> SecurityRequirement:
- """Return OpenAPI 3.1.
-
- :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>`
-
- Returns:
- An OpenAPI 3.1
- :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>`
- dictionary.
- """
- return {self.openapi_security_scheme_name: []}
-
- @property
- def middleware(self) -> DefineMiddleware:
- """Create :class:`JWTAuthenticationMiddleware` wrapped in
- :class:`DefineMiddleware <.middleware.base.DefineMiddleware>`.
-
- Returns:
- An instance of :class:`DefineMiddleware <.middleware.base.DefineMiddleware>`.
- """
- return DefineMiddleware(
- self.authentication_middleware_class,
- algorithm=self.algorithm,
- auth_header=self.auth_header,
- exclude=self.exclude,
- exclude_opt_key=self.exclude_opt_key,
- exclude_http_methods=self.exclude_http_methods,
- retrieve_user_handler=self.retrieve_user_handler,
- scopes=self.scopes,
- token_secret=self.token_secret,
- )
-
- def login(
- self,
- identifier: str,
- *,
- response_body: Any = Empty,
- response_media_type: str | MediaType = MediaType.JSON,
- response_status_code: int = HTTP_201_CREATED,
- token_expiration: timedelta | None = None,
- token_issuer: str | None = None,
- token_audience: str | None = None,
- token_unique_jwt_id: str | None = None,
- token_extras: dict[str, Any] | None = None,
- send_token_as_response_body: bool = False,
- ) -> Response[Any]:
- """Create a response with a JWT header.
-
- Args:
- identifier: Unique identifier of the token subject. Usually this is a user ID or equivalent kind of value.
- response_body: An optional response body to send.
- response_media_type: An optional ``Content-Type``. Defaults to ``application/json``.
- response_status_code: An optional status code for the response. Defaults to ``201``.
- token_expiration: An optional timedelta for the token expiration.
- token_issuer: An optional value of the token ``iss`` field.
- token_audience: An optional value for the token ``aud`` field.
- token_unique_jwt_id: An optional value for the token ``jti`` field.
- token_extras: An optional dictionary to include in the token ``extras`` field.
- send_token_as_response_body: If ``True`` the response will be a dict including the token: ``{ "token": <token> }``
- will be returned as the response body. Note: if a response body is passed this setting will be ignored.
-
- Returns:
- A :class:`Response <.response.Response>` instance.
- """
- encoded_token = self.create_token(
- identifier=identifier,
- token_expiration=token_expiration,
- token_issuer=token_issuer,
- token_audience=token_audience,
- token_unique_jwt_id=token_unique_jwt_id,
- token_extras=token_extras,
- )
-
- if response_body is not Empty:
- body = response_body
- elif send_token_as_response_body:
- body = {"token": encoded_token}
- else:
- body = None
-
- return self.create_response(
- content=body,
- headers={self.auth_header: self.format_auth_header(encoded_token)},
- media_type=response_media_type,
- status_code=response_status_code,
- )
-
- def create_token(
- self,
- identifier: str,
- token_expiration: timedelta | None = None,
- token_issuer: str | None = None,
- token_audience: str | None = None,
- token_unique_jwt_id: str | None = None,
- token_extras: dict | None = None,
- ) -> str:
- """Create a Token instance from the passed in parameters, persists and returns it.
-
- Args:
- identifier: Unique identifier of the token subject. Usually this is a user ID or equivalent kind of value.
- token_expiration: An optional timedelta for the token expiration.
- token_issuer: An optional value of the token ``iss`` field.
- token_audience: An optional value for the token ``aud`` field.
- token_unique_jwt_id: An optional value for the token ``jti`` field.
- token_extras: An optional dictionary to include in the token ``extras`` field.
-
- Returns:
- The created token.
- """
- token = Token(
- sub=identifier,
- exp=(datetime.now(timezone.utc) + (token_expiration or self.default_token_expiration)),
- iss=token_issuer,
- aud=token_audience,
- jti=token_unique_jwt_id,
- extras=token_extras or {},
- )
- return token.encode(secret=self.token_secret, algorithm=self.algorithm)
-
- def format_auth_header(self, encoded_token: str) -> str:
- """Format a token according to the specified OpenAPI scheme.
-
- Args:
- encoded_token: An encoded JWT token
-
- Returns:
- The encoded token formatted for the HTTP headers
- """
- security = self.openapi_components.security_schemes.get(self.openapi_security_scheme_name, None) # type: ignore[union-attr]
- return f"{security.scheme} {encoded_token}" if isinstance(security, SecurityScheme) else encoded_token
-
-
-@dataclass
-class JWTAuth(Generic[UserType], BaseJWTAuth[UserType]):
- """JWT Authentication Configuration.
-
- This class is the main entry point to the library, and it includes methods to create the middleware, provide login
- functionality, and create OpenAPI documentation.
- """
-
- token_secret: str
- """Key with which to generate the token hash.
-
- Notes:
- - This value should be kept as a secret and the standard practice is to inject it into the environment.
- """
- retrieve_user_handler: Callable[[Any, ASGIConnection], SyncOrAsyncUnion[Any | None]]
- """Callable that receives the ``auth`` value from the authentication middleware and returns a ``user`` value.
-
- Notes:
- - User and Auth can be any arbitrary values specified by the security backend.
- - The User and Auth values will be set by the middleware as ``scope["user"]`` and ``scope["auth"]`` respectively.
- Once provided, they can access via the ``connection.user`` and ``connection.auth`` properties.
- - The callable can be sync or async. If it is sync, it will be wrapped to support async.
-
- """
- guards: Iterable[Guard] | None = field(default=None)
- """An iterable of guards to call for requests, providing authorization functionalities."""
- exclude: str | list[str] | None = field(default=None)
- """A pattern or list of patterns to skip in the authentication middleware."""
- exclude_opt_key: str = field(default="exclude_from_auth")
- """An identifier to use on routes to disable authentication and authorization checks for a particular route."""
- exclude_http_methods: Sequence[Method] | None = field(
- default_factory=lambda: cast("Sequence[Method]", ["OPTIONS", "HEAD"])
- )
- """A sequence of http methods that do not require authentication. Defaults to ['OPTIONS', 'HEAD']"""
- scopes: Scopes | None = field(default=None)
- """ASGI scopes processed by the authentication middleware, if ``None``, both ``http`` and ``websocket`` will be
- processed."""
- route_handlers: Iterable[ControllerRouterHandler] | None = field(default=None)
- """An optional iterable of route handlers to register."""
- dependencies: dict[str, Provide] | None = field(default=None)
- """An optional dictionary of dependency providers."""
-
- type_encoders: TypeEncodersMap | None = field(default=None)
- """A mapping of types to callables that transform them into types supported for serialization."""
-
- algorithm: str = field(default="HS256")
- """Algorithm to use for JWT hashing."""
- auth_header: str = field(default="Authorization")
- """Request header key from which to retrieve the token.
-
- E.g. ``Authorization`` or ``X-Api-Key``.
- """
- default_token_expiration: timedelta = field(default_factory=lambda: timedelta(days=1))
- """The default value for token expiration."""
- openapi_security_scheme_name: str = field(default="BearerToken")
- """The value to use for the OpenAPI security scheme and security requirements."""
- description: str = field(default="JWT api-key authentication and authorization.")
- """Description for the OpenAPI security scheme."""
- authentication_middleware_class: type[JWTAuthenticationMiddleware] = field(default=JWTAuthenticationMiddleware)
- """The authentication middleware class to use.
-
- Must inherit from :class:`JWTAuthenticationMiddleware`
- """
-
-
-@dataclass
-class JWTCookieAuth(Generic[UserType], BaseJWTAuth[UserType]):
- """JWT Cookie Authentication Configuration.
-
- This class is an alternate entry point to the library, and it includes all the functionality of the :class:`JWTAuth`
- class and adds support for passing JWT tokens ``HttpOnly`` cookies.
- """
-
- token_secret: str
- """Key with which to generate the token hash.
-
- Notes:
- - This value should be kept as a secret and the standard practice is to inject it into the environment.
- """
- retrieve_user_handler: Callable[[Any, ASGIConnection], SyncOrAsyncUnion[Any | None]]
- """Callable that receives the ``auth`` value from the authentication middleware and returns a ``user`` value.
-
- Notes:
- - User and Auth can be any arbitrary values specified by the security backend.
- - The User and Auth values will be set by the middleware as ``scope["user"]`` and ``scope["auth"]`` respectively.
- Once provided, they can access via the ``connection.user`` and ``connection.auth`` properties.
- - The callable can be sync or async. If it is sync, it will be wrapped to support async.
-
- """
- guards: Iterable[Guard] | None = field(default=None)
- """An iterable of guards to call for requests, providing authorization functionalities."""
- exclude: str | list[str] | None = field(default=None)
- """A pattern or list of patterns to skip in the authentication middleware."""
- exclude_opt_key: str = field(default="exclude_from_auth")
- """An identifier to use on routes to disable authentication and authorization checks for a particular route."""
- scopes: Scopes | None = field(default=None)
- """ASGI scopes processed by the authentication middleware, if ``None``, both ``http`` and ``websocket`` will be
- processed."""
- exclude_http_methods: Sequence[Method] | None = field(
- default_factory=lambda: cast("Sequence[Method]", ["OPTIONS", "HEAD"])
- )
- """A sequence of http methods that do not require authentication. Defaults to ['OPTIONS', 'HEAD']"""
- route_handlers: Iterable[ControllerRouterHandler] | None = field(default=None)
- """An optional iterable of route handlers to register."""
- dependencies: dict[str, Provide] | None = field(default=None)
- """An optional dictionary of dependency providers."""
-
- type_encoders: TypeEncodersMap | None = field(default=None)
- """A mapping of types to callables that transform them into types supported for serialization."""
-
- algorithm: str = field(default="HS256")
- """Algorithm to use for JWT hashing."""
- auth_header: str = field(default="Authorization")
- """Request header key from which to retrieve the token.
-
- E.g. ``Authorization`` or ``X-Api-Key``.
- """
- default_token_expiration: timedelta = field(default_factory=lambda: timedelta(days=1))
- """The default value for token expiration."""
- openapi_security_scheme_name: str = field(default="BearerToken")
- """The value to use for the OpenAPI security scheme and security requirements."""
- key: str = field(default="token")
- """Key for the cookie."""
- path: str = field(default="/")
- """Path fragment that must exist in the request url for the cookie to be valid.
-
- Defaults to ``/``.
- """
- domain: str | None = field(default=None)
- """Domain for which the cookie is valid."""
- secure: bool | None = field(default=None)
- """Https is required for the cookie."""
- samesite: Literal["lax", "strict", "none"] = field(default="lax")
- """Controls whether or not a cookie is sent with cross-site requests. Defaults to ``lax``. """
- description: str = field(default="JWT cookie-based authentication and authorization.")
- """Description for the OpenAPI security scheme."""
- authentication_middleware_class: type[JWTCookieAuthenticationMiddleware] = field( # pyright: ignore
- default=JWTCookieAuthenticationMiddleware
- )
- """The authentication middleware class to use. Must inherit from :class:`JWTCookieAuthenticationMiddleware`
- """
-
- @property
- def openapi_components(self) -> Components:
- """Create OpenAPI documentation for the JWT Cookie auth scheme.
-
- Returns:
- A :class:`Components <litestar.openapi.spec.components.Components>` instance.
- """
- return Components(
- security_schemes={
- self.openapi_security_scheme_name: SecurityScheme(
- type="http",
- scheme="Bearer",
- name=self.key,
- security_scheme_in="cookie",
- bearer_format="JWT",
- description=self.description,
- )
- }
- )
-
- @property
- def middleware(self) -> DefineMiddleware:
- """Create :class:`JWTCookieAuthenticationMiddleware` wrapped in
- :class:`DefineMiddleware <.middleware.base.DefineMiddleware>`.
-
- Returns:
- An instance of :class:`DefineMiddleware <.middleware.base.DefineMiddleware>`.
- """
- return DefineMiddleware(
- self.authentication_middleware_class,
- algorithm=self.algorithm,
- auth_cookie_key=self.key,
- auth_header=self.auth_header,
- exclude=self.exclude,
- exclude_opt_key=self.exclude_opt_key,
- exclude_http_methods=self.exclude_http_methods,
- retrieve_user_handler=self.retrieve_user_handler,
- scopes=self.scopes,
- token_secret=self.token_secret,
- )
-
- def login(
- self,
- identifier: str,
- *,
- response_body: Any = Empty,
- response_media_type: str | MediaType = MediaType.JSON,
- response_status_code: int = HTTP_201_CREATED,
- token_expiration: timedelta | None = None,
- token_issuer: str | None = None,
- token_audience: str | None = None,
- token_unique_jwt_id: str | None = None,
- token_extras: dict[str, Any] | None = None,
- send_token_as_response_body: bool = False,
- ) -> Response[Any]:
- """Create a response with a JWT header.
-
- Args:
- identifier: Unique identifier of the token subject. Usually this is a user ID or equivalent kind of value.
- response_body: An optional response body to send.
- response_media_type: An optional 'Content-Type'. Defaults to 'application/json'.
- response_status_code: An optional status code for the response. Defaults to '201 Created'.
- token_expiration: An optional timedelta for the token expiration.
- token_issuer: An optional value of the token ``iss`` field.
- token_audience: An optional value for the token ``aud`` field.
- token_unique_jwt_id: An optional value for the token ``jti`` field.
- token_extras: An optional dictionary to include in the token ``extras`` field.
- send_token_as_response_body: If ``True`` the response will be a dict including the token: ``{ "token": <token> }``
- will be returned as the response body. Note: if a response body is passed this setting will be ignored.
-
- Returns:
- A :class:`Response <.response.Response>` instance.
- """
-
- encoded_token = self.create_token(
- identifier=identifier,
- token_expiration=token_expiration,
- token_issuer=token_issuer,
- token_audience=token_audience,
- token_unique_jwt_id=token_unique_jwt_id,
- token_extras=token_extras,
- )
- cookie = Cookie(
- key=self.key,
- path=self.path,
- httponly=True,
- value=self.format_auth_header(encoded_token),
- max_age=int((token_expiration or self.default_token_expiration).total_seconds()),
- secure=self.secure,
- samesite=self.samesite,
- domain=self.domain,
- )
-
- if response_body is not Empty:
- body = response_body
- elif send_token_as_response_body:
- body = {"token": encoded_token}
- else:
- body = None
-
- return self.create_response(
- content=body,
- headers={self.auth_header: self.format_auth_header(encoded_token)},
- cookies=[cookie],
- media_type=response_media_type,
- status_code=response_status_code,
- )
-
-
-@dataclass
-class OAuth2Login:
- """OAuth2 Login DTO"""
-
- access_token: str
- """Valid JWT access token"""
- token_type: str
- """Type of the OAuth token used"""
- refresh_token: str | None = field(default=None)
- """Optional valid refresh token JWT"""
- expires_in: int | None = field(default=None)
- """Expiration time of the token in seconds. """
-
-
-@dataclass
-class OAuth2PasswordBearerAuth(Generic[UserType], BaseJWTAuth[UserType]):
- """OAUTH2 Schema for Password Bearer Authentication.
-
- This class implements an OAUTH2 authentication flow entry point to the library, and it includes all the
- functionality of the :class:`JWTAuth` class and adds support for passing JWT tokens ``HttpOnly`` cookies.
-
- ``token_url`` is the only additional argument that is required, and it should point at your login route
- """
-
- token_secret: str
- """Key with which to generate the token hash.
-
- Notes:
- - This value should be kept as a secret and the standard practice is to inject it into the environment.
- """
- token_url: str
- """The URL for retrieving a new token."""
- retrieve_user_handler: Callable[[Any, ASGIConnection], SyncOrAsyncUnion[Any | None]]
- """Callable that receives the ``auth`` value from the authentication middleware and returns a ``user`` value.
-
- Notes:
- - User and Auth can be any arbitrary values specified by the security backend.
- - The User and Auth values will be set by the middleware as ``scope["user"]`` and ``scope["auth"]`` respectively.
- Once provided, they can access via the ``connection.user`` and ``connection.auth`` properties.
- - The callable can be sync or async. If it is sync, it will be wrapped to support async.
-
- """
- guards: Iterable[Guard] | None = field(default=None)
- """An iterable of guards to call for requests, providing authorization functionalities."""
- exclude: str | list[str] | None = field(default=None)
- """A pattern or list of patterns to skip in the authentication middleware."""
- exclude_opt_key: str = field(default="exclude_from_auth")
- """An identifier to use on routes to disable authentication and authorization checks for a particular route."""
- exclude_http_methods: Sequence[Method] | None = field(
- default_factory=lambda: cast("Sequence[Method]", ["OPTIONS", "HEAD"])
- )
- """A sequence of http methods that do not require authentication. Defaults to ['OPTIONS', 'HEAD']"""
- scopes: Scopes | None = field(default=None)
- """ASGI scopes processed by the authentication middleware, if ``None``, both ``http`` and ``websocket`` will be
- processed."""
- route_handlers: Iterable[ControllerRouterHandler] | None = field(default=None)
- """An optional iterable of route handlers to register."""
- dependencies: dict[str, Provide] | None = field(default=None)
- """An optional dictionary of dependency providers."""
- type_encoders: TypeEncodersMap | None = field(default=None)
- """A mapping of types to callables that transform them into types supported for serialization."""
- algorithm: str = field(default="HS256")
- """Algorithm to use for JWT hashing."""
- auth_header: str = field(default="Authorization")
- """Request header key from which to retrieve the token.
-
- E.g. ``Authorization`` or 'X-Api-Key'.
- """
- default_token_expiration: timedelta = field(default_factory=lambda: timedelta(days=1))
- """The default value for token expiration."""
- openapi_security_scheme_name: str = field(default="BearerToken")
- """The value to use for the OpenAPI security scheme and security requirements."""
- oauth_scopes: dict[str, str] | None = field(default=None)
- """Oauth Scopes available for the token."""
- key: str = field(default="token")
- """Key for the cookie."""
- path: str = field(default="/")
- """Path fragment that must exist in the request url for the cookie to be valid.
-
- Defaults to ``/``.
- """
- domain: str | None = field(default=None)
- """Domain for which the cookie is valid."""
- secure: bool | None = field(default=None)
- """Https is required for the cookie."""
- samesite: Literal["lax", "strict", "none"] = field(default="lax")
- """Controls whether or not a cookie is sent with cross-site requests. Defaults to ``lax``. """
- description: str = field(default="OAUTH2 password bearer authentication and authorization.")
- """Description for the OpenAPI security scheme."""
- authentication_middleware_class: type[JWTCookieAuthenticationMiddleware] = field( # pyright: ignore
- default=JWTCookieAuthenticationMiddleware
- )
- """The authentication middleware class to use.
-
- Must inherit from :class:`JWTCookieAuthenticationMiddleware`
- """
-
- @property
- def middleware(self) -> DefineMiddleware:
- """Create ``JWTCookieAuthenticationMiddleware`` wrapped in
- :class:`DefineMiddleware <.middleware.base.DefineMiddleware>`.
-
- Returns:
- An instance of :class:`DefineMiddleware <.middleware.base.DefineMiddleware>`.
- """
- return DefineMiddleware(
- self.authentication_middleware_class,
- algorithm=self.algorithm,
- auth_cookie_key=self.key,
- auth_header=self.auth_header,
- exclude=self.exclude,
- exclude_opt_key=self.exclude_opt_key,
- exclude_http_methods=self.exclude_http_methods,
- retrieve_user_handler=self.retrieve_user_handler,
- scopes=self.scopes,
- token_secret=self.token_secret,
- )
-
- @property
- def oauth_flow(self) -> OAuthFlow:
- """Create an OpenAPI OAuth2 flow for the password bearer authentication scheme.
-
- Returns:
- An :class:`OAuthFlow <litestar.openapi.spec.oauth_flow.OAuthFlow>` instance.
- """
- return OAuthFlow(
- token_url=self.token_url,
- scopes=self.oauth_scopes,
- )
-
- @property
- def openapi_components(self) -> Components:
- """Create OpenAPI documentation for the OAUTH2 Password bearer auth scheme.
-
- Returns:
- An :class:`Components <litestar.openapi.spec.components.Components>` instance.
- """
- return Components(
- security_schemes={
- self.openapi_security_scheme_name: SecurityScheme(
- type="oauth2",
- scheme="Bearer",
- name=self.auth_header,
- security_scheme_in="header",
- flows=OAuthFlows(password=self.oauth_flow), # pyright: ignore[reportGeneralTypeIssues]
- bearer_format="JWT",
- description=self.description,
- )
- }
- )
-
- def login(
- self,
- identifier: str,
- *,
- response_body: Any = Empty,
- response_media_type: str | MediaType = MediaType.JSON,
- response_status_code: int = HTTP_201_CREATED,
- token_expiration: timedelta | None = None,
- token_issuer: str | None = None,
- token_audience: str | None = None,
- token_unique_jwt_id: str | None = None,
- token_extras: dict[str, Any] | None = None,
- send_token_as_response_body: bool = True,
- ) -> Response[Any]:
- """Create a response with a JWT header.
-
- Args:
- identifier: Unique identifier of the token subject. Usually this is a user ID or equivalent kind of value.
- response_body: An optional response body to send.
- response_media_type: An optional ``Content-Type``. Defaults to ``application/json``.
- response_status_code: An optional status code for the response. Defaults to ``201``.
- token_expiration: An optional timedelta for the token expiration.
- token_issuer: An optional value of the token ``iss`` field.
- token_audience: An optional value for the token ``aud`` field.
- token_unique_jwt_id: An optional value for the token ``jti`` field.
- token_extras: An optional dictionary to include in the token ``extras`` field.
- send_token_as_response_body: If ``True`` the response will be an oAuth2 token response dict.
- Note: if a response body is passed this setting will be ignored.
-
- Returns:
- A :class:`Response <.response.Response>` instance.
- """
- encoded_token = self.create_token(
- identifier=identifier,
- token_expiration=token_expiration,
- token_issuer=token_issuer,
- token_audience=token_audience,
- token_unique_jwt_id=token_unique_jwt_id,
- token_extras=token_extras,
- )
- expires_in = int((token_expiration or self.default_token_expiration).total_seconds())
- cookie = Cookie(
- key=self.key,
- path=self.path,
- httponly=True,
- value=self.format_auth_header(encoded_token),
- max_age=expires_in,
- secure=self.secure,
- samesite=self.samesite,
- domain=self.domain,
- )
-
- if response_body is not Empty:
- body = response_body
- elif send_token_as_response_body:
- token_dto = OAuth2Login(
- access_token=encoded_token,
- expires_in=expires_in,
- token_type="bearer", # noqa: S106
- )
- body = asdict(token_dto)
- else:
- body = None
-
- return self.create_response(
- content=body,
- headers={self.auth_header: self.format_auth_header(encoded_token)},
- cookies=[cookie],
- media_type=response_media_type,
- status_code=response_status_code,
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/security/jwt/middleware.py b/venv/lib/python3.11/site-packages/litestar/security/jwt/middleware.py
deleted file mode 100644
index 84326da..0000000
--- a/venv/lib/python3.11/site-packages/litestar/security/jwt/middleware.py
+++ /dev/null
@@ -1,188 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Awaitable, Callable, Sequence
-
-from litestar.exceptions import NotAuthorizedException
-from litestar.middleware.authentication import (
- AbstractAuthenticationMiddleware,
- AuthenticationResult,
-)
-from litestar.security.jwt.token import Token
-
-__all__ = ("JWTAuthenticationMiddleware", "JWTCookieAuthenticationMiddleware")
-
-
-if TYPE_CHECKING:
- from typing import Any
-
- from litestar.connection import ASGIConnection
- from litestar.types import ASGIApp, Method, Scopes
-
-
-class JWTAuthenticationMiddleware(AbstractAuthenticationMiddleware):
- """JWT Authentication middleware.
-
- This class provides JWT authentication functionalities.
- """
-
- __slots__ = (
- "algorithm",
- "auth_header",
- "retrieve_user_handler",
- "token_secret",
- )
-
- def __init__(
- self,
- algorithm: str,
- app: ASGIApp,
- auth_header: str,
- exclude: str | list[str] | None,
- exclude_http_methods: Sequence[Method] | None,
- exclude_opt_key: str,
- retrieve_user_handler: Callable[[Token, ASGIConnection[Any, Any, Any, Any]], Awaitable[Any]],
- scopes: Scopes,
- token_secret: str,
- ) -> None:
- """Check incoming requests for an encoded token in the auth header specified, and if present retrieve the user
- from persistence using the provided function.
-
- Args:
- algorithm: JWT hashing algorithm to use.
- app: An ASGIApp, this value is the next ASGI handler to call in the middleware stack.
- auth_header: Request header key from which to retrieve the token. E.g. ``Authorization`` or ``X-Api-Key``.
- exclude: A pattern or list of patterns to skip.
- exclude_opt_key: An identifier to use on routes to disable authentication for a particular route.
- exclude_http_methods: A sequence of http methods that do not require authentication.
- retrieve_user_handler: A function that receives a :class:`Token <.security.jwt.Token>` and returns a user,
- which can be any arbitrary value.
- scopes: ASGI scopes processed by the authentication middleware.
- token_secret: Secret for decoding the JWT token. This value should be equivalent to the secret used to
- encode it.
- """
- super().__init__(
- app=app,
- exclude=exclude,
- exclude_from_auth_key=exclude_opt_key,
- exclude_http_methods=exclude_http_methods,
- scopes=scopes,
- )
- self.algorithm = algorithm
- self.auth_header = auth_header
- self.retrieve_user_handler = retrieve_user_handler
- self.token_secret = token_secret
-
- async def authenticate_request(self, connection: ASGIConnection[Any, Any, Any, Any]) -> AuthenticationResult:
- """Given an HTTP Connection, parse the JWT api key stored in the header and retrieve the user correlating to the
- token from the DB.
-
- Args:
- connection: An Litestar HTTPConnection instance.
-
- Returns:
- AuthenticationResult
-
- Raises:
- NotAuthorizedException: If token is invalid or user is not found.
- """
- auth_header = connection.headers.get(self.auth_header)
- if not auth_header:
- raise NotAuthorizedException("No JWT token found in request header")
- encoded_token = auth_header.partition(" ")[-1]
- return await self.authenticate_token(encoded_token=encoded_token, connection=connection)
-
- async def authenticate_token(
- self, encoded_token: str, connection: ASGIConnection[Any, Any, Any, Any]
- ) -> AuthenticationResult:
- """Given an encoded JWT token, parse, validate and look up sub within token.
-
- Args:
- encoded_token: Encoded JWT token.
- connection: An ASGI connection instance.
-
- Raises:
- NotAuthorizedException: If token is invalid or user is not found.
-
- Returns:
- AuthenticationResult
- """
- token = Token.decode(
- encoded_token=encoded_token,
- secret=self.token_secret,
- algorithm=self.algorithm,
- )
-
- user = await self.retrieve_user_handler(token, connection)
-
- if not user:
- raise NotAuthorizedException()
-
- return AuthenticationResult(user=user, auth=token)
-
-
-class JWTCookieAuthenticationMiddleware(JWTAuthenticationMiddleware):
- """Cookie based JWT authentication middleware."""
-
- __slots__ = ("auth_cookie_key",)
-
- def __init__(
- self,
- algorithm: str,
- app: ASGIApp,
- auth_cookie_key: str,
- auth_header: str,
- exclude: str | list[str] | None,
- exclude_opt_key: str,
- exclude_http_methods: Sequence[Method] | None,
- retrieve_user_handler: Callable[[Token, ASGIConnection[Any, Any, Any, Any]], Awaitable[Any]],
- scopes: Scopes,
- token_secret: str,
- ) -> None:
- """Check incoming requests for an encoded token in the auth header or cookie name specified, and if present
- retrieves the user from persistence using the provided function.
-
- Args:
- algorithm: JWT hashing algorithm to use.
- app: An ASGIApp, this value is the next ASGI handler to call in the middleware stack.
- auth_cookie_key: Cookie name from which to retrieve the token. E.g. ``token`` or ``accessToken``.
- auth_header: Request header key from which to retrieve the token. E.g. ``Authorization`` or ``X-Api-Key``.
- exclude: A pattern or list of patterns to skip.
- exclude_opt_key: An identifier to use on routes to disable authentication for a particular route.
- exclude_http_methods: A sequence of http methods that do not require authentication.
- retrieve_user_handler: A function that receives a :class:`Token <.security.jwt.Token>` and returns a user,
- which can be any arbitrary value.
- scopes: ASGI scopes processed by the authentication middleware.
- token_secret: Secret for decoding the JWT token. This value should be equivalent to the secret used to
- encode it.
- """
- super().__init__(
- algorithm=algorithm,
- app=app,
- auth_header=auth_header,
- exclude=exclude,
- exclude_http_methods=exclude_http_methods,
- exclude_opt_key=exclude_opt_key,
- retrieve_user_handler=retrieve_user_handler,
- scopes=scopes,
- token_secret=token_secret,
- )
- self.auth_cookie_key = auth_cookie_key
-
- async def authenticate_request(self, connection: ASGIConnection[Any, Any, Any, Any]) -> AuthenticationResult:
- """Given an HTTP Connection, parse the JWT api key stored in the header and retrieve the user correlating to the
- token from the DB.
-
- Args:
- connection: An Litestar HTTPConnection instance.
-
- Raises:
- NotAuthorizedException: If token is invalid or user is not found.
-
- Returns:
- AuthenticationResult
- """
- auth_header = connection.headers.get(self.auth_header) or connection.cookies.get(self.auth_cookie_key)
- if not auth_header:
- raise NotAuthorizedException("No JWT token found in request header or cookies")
- encoded_token = auth_header.partition(" ")[-1]
- return await self.authenticate_token(encoded_token=encoded_token, connection=connection)
diff --git a/venv/lib/python3.11/site-packages/litestar/security/jwt/token.py b/venv/lib/python3.11/site-packages/litestar/security/jwt/token.py
deleted file mode 100644
index 279111a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/security/jwt/token.py
+++ /dev/null
@@ -1,119 +0,0 @@
-from __future__ import annotations
-
-import dataclasses
-from dataclasses import asdict, dataclass, field
-from datetime import datetime, timezone
-from typing import TYPE_CHECKING, Any
-
-from jose import JWSError, JWTError, jwt
-
-from litestar.exceptions import ImproperlyConfiguredException, NotAuthorizedException
-
-if TYPE_CHECKING:
- from typing_extensions import Self
-
-
-__all__ = ("Token",)
-
-
-def _normalize_datetime(value: datetime) -> datetime:
- """Convert the given value into UTC and strip microseconds.
-
- Args:
- value: A datetime instance
-
- Returns:
- A datetime instance
- """
- if value.tzinfo is not None:
- value.astimezone(timezone.utc)
-
- return value.replace(microsecond=0)
-
-
-@dataclass
-class Token:
- """JWT Token DTO."""
-
- exp: datetime
- """Expiration - datetime for token expiration."""
- sub: str
- """Subject - usually a unique identifier of the user or equivalent entity."""
- iat: datetime = field(default_factory=lambda: _normalize_datetime(datetime.now(timezone.utc)))
- """Issued at - should always be current now."""
- iss: str | None = field(default=None)
- """Issuer - optional unique identifier for the issuer."""
- aud: str | None = field(default=None)
- """Audience - intended audience."""
- jti: str | None = field(default=None)
- """JWT ID - a unique identifier of the JWT between different issuers."""
- extras: dict[str, Any] = field(default_factory=dict)
- """Extra fields that were found on the JWT token."""
-
- def __post_init__(self) -> None:
- if len(self.sub) < 1:
- raise ImproperlyConfiguredException("sub must be a string with a length greater than 0")
-
- if isinstance(self.exp, datetime) and (
- (exp := _normalize_datetime(self.exp)).timestamp()
- >= _normalize_datetime(datetime.now(timezone.utc)).timestamp()
- ):
- self.exp = exp
- else:
- raise ImproperlyConfiguredException("exp value must be a datetime in the future")
-
- if isinstance(self.iat, datetime) and (
- (iat := _normalize_datetime(self.iat)).timestamp()
- <= _normalize_datetime(datetime.now(timezone.utc)).timestamp()
- ):
- self.iat = iat
- else:
- raise ImproperlyConfiguredException("iat must be a current or past time")
-
- @classmethod
- def decode(cls, encoded_token: str, secret: str | dict[str, str], algorithm: str) -> Self:
- """Decode a passed in token string and returns a Token instance.
-
- Args:
- encoded_token: A base64 string containing an encoded JWT.
- secret: The secret with which the JWT is encoded. It may optionally be an individual JWK or JWS set dict
- algorithm: The algorithm used to encode the JWT.
-
- Returns:
- A decoded Token instance.
-
- Raises:
- NotAuthorizedException: If the token is invalid.
- """
- try:
- payload = jwt.decode(token=encoded_token, key=secret, algorithms=[algorithm], options={"verify_aud": False})
- exp = datetime.fromtimestamp(payload.pop("exp"), tz=timezone.utc)
- iat = datetime.fromtimestamp(payload.pop("iat"), tz=timezone.utc)
- field_names = {f.name for f in dataclasses.fields(Token)}
- extra_fields = payload.keys() - field_names
- extras = payload.pop("extras", {})
- for key in extra_fields:
- extras[key] = payload.pop(key)
- return cls(exp=exp, iat=iat, **payload, extras=extras)
- except (KeyError, JWTError, ImproperlyConfiguredException) as e:
- raise NotAuthorizedException("Invalid token") from e
-
- def encode(self, secret: str, algorithm: str) -> str:
- """Encode the token instance into a string.
-
- Args:
- secret: The secret with which the JWT is encoded.
- algorithm: The algorithm used to encode the JWT.
-
- Returns:
- An encoded token string.
-
- Raises:
- ImproperlyConfiguredException: If encoding fails.
- """
- try:
- return jwt.encode(
- claims={k: v for k, v in asdict(self).items() if v is not None}, key=secret, algorithm=algorithm
- )
- except (JWTError, JWSError) as e:
- raise ImproperlyConfiguredException("Failed to encode token") from e
diff --git a/venv/lib/python3.11/site-packages/litestar/security/session_auth/__init__.py b/venv/lib/python3.11/site-packages/litestar/security/session_auth/__init__.py
deleted file mode 100644
index 7c83991..0000000
--- a/venv/lib/python3.11/site-packages/litestar/security/session_auth/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from litestar.security.session_auth.auth import SessionAuth
-from litestar.security.session_auth.middleware import SessionAuthMiddleware
-
-__all__ = ("SessionAuth", "SessionAuthMiddleware")
diff --git a/venv/lib/python3.11/site-packages/litestar/security/session_auth/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/security/session_auth/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 95bf5c1..0000000
--- a/venv/lib/python3.11/site-packages/litestar/security/session_auth/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/security/session_auth/__pycache__/auth.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/security/session_auth/__pycache__/auth.cpython-311.pyc
deleted file mode 100644
index 8d4aa6c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/security/session_auth/__pycache__/auth.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/security/session_auth/__pycache__/middleware.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/security/session_auth/__pycache__/middleware.cpython-311.pyc
deleted file mode 100644
index 27e4213..0000000
--- a/venv/lib/python3.11/site-packages/litestar/security/session_auth/__pycache__/middleware.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/security/session_auth/auth.py b/venv/lib/python3.11/site-packages/litestar/security/session_auth/auth.py
deleted file mode 100644
index 7a5c542..0000000
--- a/venv/lib/python3.11/site-packages/litestar/security/session_auth/auth.py
+++ /dev/null
@@ -1,137 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass, field
-from typing import TYPE_CHECKING, Any, Callable, Dict, Generic, Iterable, Sequence, cast
-
-from litestar.middleware.base import DefineMiddleware
-from litestar.middleware.session.base import BaseBackendConfig, BaseSessionBackendT
-from litestar.openapi.spec import Components, SecurityRequirement, SecurityScheme
-from litestar.security.base import AbstractSecurityConfig, UserType
-from litestar.security.session_auth.middleware import MiddlewareWrapper, SessionAuthMiddleware
-
-__all__ = ("SessionAuth",)
-
-if TYPE_CHECKING:
- from litestar.connection import ASGIConnection
- from litestar.di import Provide
- from litestar.types import ControllerRouterHandler, Guard, Method, Scopes, SyncOrAsyncUnion, TypeEncodersMap
-
-
-@dataclass
-class SessionAuth(Generic[UserType, BaseSessionBackendT], AbstractSecurityConfig[UserType, Dict[str, Any]]):
- """Session Based Security Backend."""
-
- session_backend_config: BaseBackendConfig[BaseSessionBackendT] # pyright: ignore
- """A session backend config."""
- retrieve_user_handler: Callable[[Any, ASGIConnection], SyncOrAsyncUnion[Any | None]]
- """Callable that receives the ``auth`` value from the authentication middleware and returns a ``user`` value.
-
- Notes:
- - User and Auth can be any arbitrary values specified by the security backend.
- - The User and Auth values will be set by the middleware as ``scope["user"]`` and ``scope["auth"]`` respectively.
- Once provided, they can access via the ``connection.user`` and ``connection.auth`` properties.
- - The callable can be sync or async. If it is sync, it will be wrapped to support async.
-
- """
-
- authentication_middleware_class: type[SessionAuthMiddleware] = field(default=SessionAuthMiddleware) # pyright: ignore
- """The authentication middleware class to use.
-
- Must inherit from :class:`SessionAuthMiddleware <litestar.security.session_auth.middleware.SessionAuthMiddleware>`
- """
-
- guards: Iterable[Guard] | None = field(default=None)
- """An iterable of guards to call for requests, providing authorization functionalities."""
- exclude: str | list[str] | None = field(default=None)
- """A pattern or list of patterns to skip in the authentication middleware."""
- exclude_opt_key: str = field(default="exclude_from_auth")
- """An identifier to use on routes to disable authentication and authorization checks for a particular route."""
- exclude_http_methods: Sequence[Method] | None = field(
- default_factory=lambda: cast("Sequence[Method]", ["OPTIONS", "HEAD"])
- )
- """A sequence of http methods that do not require authentication. Defaults to ['OPTIONS', 'HEAD']"""
- scopes: Scopes | None = field(default=None)
- """ASGI scopes processed by the authentication middleware, if ``None``, both ``http`` and ``websocket`` will be
- processed."""
- route_handlers: Iterable[ControllerRouterHandler] | None = field(default=None)
- """An optional iterable of route handlers to register."""
- dependencies: dict[str, Provide] | None = field(default=None)
- """An optional dictionary of dependency providers."""
-
- type_encoders: TypeEncodersMap | None = field(default=None)
- """A mapping of types to callables that transform them into types supported for serialization."""
-
- @property
- def middleware(self) -> DefineMiddleware:
- """Use this property to insert the config into a middleware list on one of the application layers.
-
- Examples:
- .. code-block:: python
-
- from typing import Any
- from os import urandom
-
- from litestar import Litestar, Request, get
- from litestar_session import SessionAuth
-
-
- async def retrieve_user_from_session(session: dict[str, Any]) -> Any:
- # implement logic here to retrieve a ``user`` datum given the session dictionary
- ...
-
-
- session_auth_config = SessionAuth(
- secret=urandom(16), retrieve_user_handler=retrieve_user_from_session
- )
-
-
- @get("/")
- def my_handler(request: Request) -> None: ...
-
-
- app = Litestar(route_handlers=[my_handler], middleware=[session_auth_config.middleware])
-
-
- Returns:
- An instance of DefineMiddleware including ``self`` as the config kwarg value.
- """
- return DefineMiddleware(MiddlewareWrapper, config=self)
-
- @property
- def session_backend(self) -> BaseSessionBackendT:
- """Create a session backend.
-
- Returns:
- A subclass of :class:`BaseSessionBackend <litestar.middleware.session.base.BaseSessionBackend>`
- """
- return self.session_backend_config._backend_class(config=self.session_backend_config) # pyright: ignore
-
- @property
- def openapi_components(self) -> Components:
- """Create OpenAPI documentation for the Session Authentication schema used.
-
- Returns:
- An :class:`Components <litestar.openapi.spec.components.Components>` instance.
- """
- return Components(
- security_schemes={
- "sessionCookie": SecurityScheme(
- type="apiKey",
- name=self.session_backend_config.key,
- security_scheme_in="cookie", # pyright: ignore
- description="Session cookie authentication.",
- )
- }
- )
-
- @property
- def security_requirement(self) -> SecurityRequirement:
- """Return OpenAPI 3.1.
-
- :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>` for the auth
- backend.
-
- Returns:
- An OpenAPI 3.1 :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>` dictionary.
- """
- return {"sessionCookie": []}
diff --git a/venv/lib/python3.11/site-packages/litestar/security/session_auth/middleware.py b/venv/lib/python3.11/site-packages/litestar/security/session_auth/middleware.py
deleted file mode 100644
index bb3fce4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/security/session_auth/middleware.py
+++ /dev/null
@@ -1,125 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any, Awaitable, Callable, Sequence
-
-from litestar.exceptions import NotAuthorizedException
-from litestar.middleware.authentication import (
- AbstractAuthenticationMiddleware,
- AuthenticationResult,
-)
-from litestar.middleware.exceptions import ExceptionHandlerMiddleware
-from litestar.types import Empty, Method, Scopes
-
-__all__ = ("MiddlewareWrapper", "SessionAuthMiddleware")
-
-if TYPE_CHECKING:
- from litestar.connection import ASGIConnection
- from litestar.security.session_auth.auth import SessionAuth
- from litestar.types import ASGIApp, Receive, Scope, Send
-
-
-class MiddlewareWrapper:
- """Wrapper class that serves as the middleware entry point."""
-
- def __init__(self, app: ASGIApp, config: SessionAuth[Any, Any]) -> None:
- """Wrap the SessionAuthMiddleware inside ExceptionHandlerMiddleware, and it wraps this inside SessionMiddleware.
- This allows the auth middleware to raise exceptions and still have the response handled, while having the
- session cleared.
-
- Args:
- app: An ASGIApp, this value is the next ASGI handler to call in the middleware stack.
- config: An instance of SessionAuth.
- """
- self.app = app
- self.config = config
- self.has_wrapped_middleware = False
-
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
- """Handle creating a middleware stack and calling it.
-
- Args:
- scope: The ASGI connection scope.
- receive: The ASGI receive function.
- send: The ASGI send function.
-
- Returns:
- None
- """
- if not self.has_wrapped_middleware:
- litestar_app = scope["app"]
- auth_middleware = self.config.authentication_middleware_class(
- app=self.app,
- exclude=self.config.exclude,
- exclude_http_methods=self.config.exclude_http_methods,
- exclude_opt_key=self.config.exclude_opt_key,
- scopes=self.config.scopes,
- retrieve_user_handler=self.config.retrieve_user_handler, # type: ignore[arg-type]
- )
- exception_middleware = ExceptionHandlerMiddleware(
- app=auth_middleware,
- exception_handlers=litestar_app.exception_handlers or {}, # pyright: ignore
- debug=None,
- )
- self.app = self.config.session_backend_config.middleware.middleware(
- app=exception_middleware,
- backend=self.config.session_backend,
- )
- self.has_wrapped_middleware = True
- await self.app(scope, receive, send)
-
-
-class SessionAuthMiddleware(AbstractAuthenticationMiddleware):
- """Session Authentication Middleware."""
-
- def __init__(
- self,
- app: ASGIApp,
- exclude: str | list[str] | None,
- exclude_http_methods: Sequence[Method] | None,
- exclude_opt_key: str,
- retrieve_user_handler: Callable[[dict[str, Any], ASGIConnection[Any, Any, Any, Any]], Awaitable[Any]],
- scopes: Scopes | None,
- ) -> None:
- """Session based authentication middleware.
-
- Args:
- app: An ASGIApp, this value is the next ASGI handler to call in the middleware stack.
- exclude: A pattern or list of patterns to skip in the authentication middleware.
- exclude_http_methods: A sequence of http methods that do not require authentication.
- exclude_opt_key: An identifier to use on routes to disable authentication and authorization checks for a particular route.
- scopes: ASGI scopes processed by the authentication middleware.
- retrieve_user_handler: Callable that receives the ``session`` value from the authentication middleware and returns a ``user`` value.
- """
- super().__init__(
- app=app,
- exclude=exclude,
- exclude_from_auth_key=exclude_opt_key,
- exclude_http_methods=exclude_http_methods,
- scopes=scopes,
- )
- self.retrieve_user_handler = retrieve_user_handler
-
- async def authenticate_request(self, connection: ASGIConnection[Any, Any, Any, Any]) -> AuthenticationResult:
- """Authenticate an incoming connection.
-
- Args:
- connection: An :class:`ASGIConnection <.connection.ASGIConnection>` instance.
-
- Raises:
- NotAuthorizedException: if session data is empty or user is not found.
-
- Returns:
- :class:`AuthenticationResult <.middleware.authentication.AuthenticationResult>`
- """
- if not connection.session or connection.scope["session"] is Empty:
- # the assignment of 'Empty' forces the session middleware to clear session data.
- connection.scope["session"] = Empty
- raise NotAuthorizedException("no session data found")
-
- user = await self.retrieve_user_handler(connection.session, connection)
-
- if not user:
- connection.scope["session"] = Empty
- raise NotAuthorizedException("no user correlating to session found")
-
- return AuthenticationResult(user=user, auth=connection.session)
diff --git a/venv/lib/python3.11/site-packages/litestar/serialization/__init__.py b/venv/lib/python3.11/site-packages/litestar/serialization/__init__.py
deleted file mode 100644
index 0a9189e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/serialization/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from .msgspec_hooks import (
- decode_json,
- decode_msgpack,
- default_deserializer,
- default_serializer,
- encode_json,
- encode_msgpack,
- get_serializer,
-)
-
-__all__ = (
- "default_deserializer",
- "decode_json",
- "decode_msgpack",
- "default_serializer",
- "encode_json",
- "encode_msgpack",
- "get_serializer",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/serialization/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/serialization/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 68fa695..0000000
--- a/venv/lib/python3.11/site-packages/litestar/serialization/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/serialization/__pycache__/msgspec_hooks.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/serialization/__pycache__/msgspec_hooks.cpython-311.pyc
deleted file mode 100644
index 00f6d48..0000000
--- a/venv/lib/python3.11/site-packages/litestar/serialization/__pycache__/msgspec_hooks.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/serialization/msgspec_hooks.py b/venv/lib/python3.11/site-packages/litestar/serialization/msgspec_hooks.py
deleted file mode 100644
index 3d7fdb8..0000000
--- a/venv/lib/python3.11/site-packages/litestar/serialization/msgspec_hooks.py
+++ /dev/null
@@ -1,261 +0,0 @@
-from __future__ import annotations
-
-from collections import deque
-from datetime import date, datetime, time
-from decimal import Decimal
-from functools import partial
-from ipaddress import (
- IPv4Address,
- IPv4Interface,
- IPv4Network,
- IPv6Address,
- IPv6Interface,
- IPv6Network,
-)
-from pathlib import Path, PurePath
-from re import Pattern
-from typing import TYPE_CHECKING, Any, Callable, Mapping, TypeVar, overload
-from uuid import UUID
-
-import msgspec
-
-from litestar.exceptions import SerializationException
-from litestar.types import Empty, EmptyType, Serializer, TypeDecodersSequence
-
-if TYPE_CHECKING:
- from litestar.types import TypeEncodersMap
-
-__all__ = (
- "decode_json",
- "decode_msgpack",
- "default_deserializer",
- "default_serializer",
- "encode_json",
- "encode_msgpack",
- "get_serializer",
-)
-
-T = TypeVar("T")
-
-DEFAULT_TYPE_ENCODERS: TypeEncodersMap = {
- Path: str,
- PurePath: str,
- IPv4Address: str,
- IPv4Interface: str,
- IPv4Network: str,
- IPv6Address: str,
- IPv6Interface: str,
- IPv6Network: str,
- datetime: lambda val: val.isoformat(),
- date: lambda val: val.isoformat(),
- time: lambda val: val.isoformat(),
- deque: list,
- Decimal: lambda val: int(val) if val.as_tuple().exponent >= 0 else float(val),
- Pattern: lambda val: val.pattern,
- # support subclasses of stdlib types, If no previous type matched, these will be
- # the last type in the mro, so we use this to (attempt to) convert a subclass into
- # its base class. # see https://github.com/jcrist/msgspec/issues/248
- # and https://github.com/litestar-org/litestar/issues/1003
- str: str,
- int: int,
- float: float,
- set: set,
- frozenset: frozenset,
- bytes: bytes,
-}
-
-
-def default_serializer(value: Any, type_encoders: Mapping[Any, Callable[[Any], Any]] | None = None) -> Any:
- """Transform values non-natively supported by ``msgspec``
-
- Args:
- value: A value to serialized
- type_encoders: Mapping of types to callables to transforming types
- Returns:
- A serialized value
- Raises:
- TypeError: if value is not supported
- """
- type_encoders = {**DEFAULT_TYPE_ENCODERS, **(type_encoders or {})}
-
- for base in value.__class__.__mro__[:-1]:
- try:
- encoder = type_encoders[base]
- return encoder(value)
- except KeyError:
- continue
-
- raise TypeError(f"Unsupported type: {type(value)!r}")
-
-
-def default_deserializer(
- target_type: Any, value: Any, type_decoders: TypeDecodersSequence | None = None
-) -> Any: # pragma: no cover
- """Transform values non-natively supported by ``msgspec``
-
- Args:
- target_type: Encountered type
- value: Value to coerce
- type_decoders: Optional sequence of type decoders
-
- Returns:
- A ``msgspec``-supported type
- """
-
- from litestar.datastructures.state import ImmutableState
-
- if isinstance(value, target_type):
- return value
-
- if type_decoders:
- for predicate, decoder in type_decoders:
- if predicate(target_type):
- return decoder(target_type, value)
-
- if issubclass(target_type, (Path, PurePath, ImmutableState, UUID)):
- return target_type(value)
-
- raise TypeError(f"Unsupported type: {type(value)!r}")
-
-
-_msgspec_json_encoder = msgspec.json.Encoder(enc_hook=default_serializer)
-_msgspec_json_decoder = msgspec.json.Decoder(dec_hook=default_deserializer)
-_msgspec_msgpack_encoder = msgspec.msgpack.Encoder(enc_hook=default_serializer)
-_msgspec_msgpack_decoder = msgspec.msgpack.Decoder(dec_hook=default_deserializer)
-
-
-def encode_json(value: Any, serializer: Callable[[Any], Any] | None = None) -> bytes:
- """Encode a value into JSON.
-
- Args:
- value: Value to encode
- serializer: Optional callable to support non-natively supported types.
-
- Returns:
- JSON as bytes
-
- Raises:
- SerializationException: If error encoding ``obj``.
- """
- try:
- return msgspec.json.encode(value, enc_hook=serializer) if serializer else _msgspec_json_encoder.encode(value)
- except (TypeError, msgspec.EncodeError) as msgspec_error:
- raise SerializationException(str(msgspec_error)) from msgspec_error
-
-
-@overload
-def decode_json(value: str | bytes) -> Any: ...
-
-
-@overload
-def decode_json(value: str | bytes, type_decoders: TypeDecodersSequence | None) -> Any: ...
-
-
-@overload
-def decode_json(value: str | bytes, target_type: type[T]) -> T: ...
-
-
-@overload
-def decode_json(value: str | bytes, target_type: type[T], type_decoders: TypeDecodersSequence | None) -> T: ...
-
-
-def decode_json( # type: ignore[misc]
- value: str | bytes,
- target_type: type[T] | EmptyType = Empty, # pyright: ignore
- type_decoders: TypeDecodersSequence | None = None,
-) -> Any:
- """Decode a JSON string/bytes into an object.
-
- Args:
- value: Value to decode
- target_type: An optional type to decode the data into
- type_decoders: Optional sequence of type decoders
-
- Returns:
- An object
-
- Raises:
- SerializationException: If error decoding ``value``.
- """
- try:
- if target_type is Empty:
- return _msgspec_json_decoder.decode(value)
- return msgspec.json.decode(
- value, dec_hook=partial(default_deserializer, type_decoders=type_decoders), type=target_type
- )
- except msgspec.DecodeError as msgspec_error:
- raise SerializationException(str(msgspec_error)) from msgspec_error
-
-
-def encode_msgpack(value: Any, serializer: Callable[[Any], Any] | None = default_serializer) -> bytes:
- """Encode a value into MessagePack.
-
- Args:
- value: Value to encode
- serializer: Optional callable to support non-natively supported types
-
- Returns:
- MessagePack as bytes
-
- Raises:
- SerializationException: If error encoding ``obj``.
- """
- try:
- if serializer is None or serializer is default_serializer:
- return _msgspec_msgpack_encoder.encode(value)
- return msgspec.msgpack.encode(value, enc_hook=serializer)
- except (TypeError, msgspec.EncodeError) as msgspec_error:
- raise SerializationException(str(msgspec_error)) from msgspec_error
-
-
-@overload
-def decode_msgpack(value: bytes) -> Any: ...
-
-
-@overload
-def decode_msgpack(value: bytes, type_decoders: TypeDecodersSequence | None) -> Any: ...
-
-
-@overload
-def decode_msgpack(value: bytes, target_type: type[T]) -> T: ...
-
-
-@overload
-def decode_msgpack(value: bytes, target_type: type[T], type_decoders: TypeDecodersSequence | None) -> T: ...
-
-
-def decode_msgpack( # type: ignore[misc]
- value: bytes,
- target_type: type[T] | EmptyType = Empty, # pyright: ignore[reportInvalidTypeVarUse]
- type_decoders: TypeDecodersSequence | None = None,
-) -> Any:
- """Decode a MessagePack string/bytes into an object.
-
- Args:
- value: Value to decode
- target_type: An optional type to decode the data into
- type_decoders: Optional sequence of type decoders
-
- Returns:
- An object
-
- Raises:
- SerializationException: If error decoding ``value``.
- """
- try:
- if target_type is Empty:
- return _msgspec_msgpack_decoder.decode(value)
- return msgspec.msgpack.decode(
- value, dec_hook=partial(default_deserializer, type_decoders=type_decoders), type=target_type
- )
- except msgspec.DecodeError as msgspec_error:
- raise SerializationException(str(msgspec_error)) from msgspec_error
-
-
-def get_serializer(type_encoders: TypeEncodersMap | None = None) -> Serializer:
- """Get the serializer for the given type encoders."""
-
- if type_encoders:
- return partial(default_serializer, type_encoders=type_encoders)
-
- return default_serializer
diff --git a/venv/lib/python3.11/site-packages/litestar/static_files/__init__.py b/venv/lib/python3.11/site-packages/litestar/static_files/__init__.py
deleted file mode 100644
index 3cd4594..0000000
--- a/venv/lib/python3.11/site-packages/litestar/static_files/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from litestar.static_files.base import StaticFiles
-from litestar.static_files.config import StaticFilesConfig, create_static_files_router
-
-__all__ = ("StaticFiles", "StaticFilesConfig", "create_static_files_router")
diff --git a/venv/lib/python3.11/site-packages/litestar/static_files/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/static_files/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 1cc4497..0000000
--- a/venv/lib/python3.11/site-packages/litestar/static_files/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/static_files/__pycache__/base.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/static_files/__pycache__/base.cpython-311.pyc
deleted file mode 100644
index 0ca9dae..0000000
--- a/venv/lib/python3.11/site-packages/litestar/static_files/__pycache__/base.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/static_files/__pycache__/config.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/static_files/__pycache__/config.cpython-311.pyc
deleted file mode 100644
index fd93af6..0000000
--- a/venv/lib/python3.11/site-packages/litestar/static_files/__pycache__/config.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/static_files/base.py b/venv/lib/python3.11/site-packages/litestar/static_files/base.py
deleted file mode 100644
index 9827697..0000000
--- a/venv/lib/python3.11/site-packages/litestar/static_files/base.py
+++ /dev/null
@@ -1,141 +0,0 @@
-from __future__ import annotations
-
-from os.path import commonpath
-from pathlib import Path
-from typing import TYPE_CHECKING, Literal, Sequence
-
-from litestar.enums import ScopeType
-from litestar.exceptions import MethodNotAllowedException, NotFoundException
-from litestar.file_system import FileSystemAdapter
-from litestar.response.file import ASGIFileResponse
-from litestar.status_codes import HTTP_404_NOT_FOUND
-
-__all__ = ("StaticFiles",)
-
-
-if TYPE_CHECKING:
- from litestar.types import Receive, Scope, Send
- from litestar.types.composite_types import PathType
- from litestar.types.file_types import FileInfo, FileSystemProtocol
-
-
-class StaticFiles:
- """ASGI App that handles file sending."""
-
- __slots__ = ("is_html_mode", "directories", "adapter", "send_as_attachment", "headers")
-
- def __init__(
- self,
- is_html_mode: bool,
- directories: Sequence[PathType],
- file_system: FileSystemProtocol,
- send_as_attachment: bool = False,
- resolve_symlinks: bool = True,
- headers: dict[str, str] | None = None,
- ) -> None:
- """Initialize the Application.
-
- Args:
- is_html_mode: Flag dictating whether serving html. If true, the default file will be ``index.html``.
- directories: A list of directories to serve files from.
- file_system: The file_system spec to use for serving files.
- send_as_attachment: Whether to send the file with a ``content-disposition`` header of
- ``attachment`` or ``inline``
- resolve_symlinks: Resolve symlinks to the directories
- headers: Headers that will be sent with every response.
- """
- self.adapter = FileSystemAdapter(file_system)
- self.directories = tuple(Path(p).resolve() if resolve_symlinks else Path(p) for p in directories)
- self.is_html_mode = is_html_mode
- self.send_as_attachment = send_as_attachment
- self.headers = headers
-
- async def get_fs_info(
- self, directories: Sequence[PathType], file_path: PathType
- ) -> tuple[Path, FileInfo] | tuple[None, None]:
- """Return the resolved path and a :class:`stat_result <os.stat_result>`.
-
- Args:
- directories: A list of directory paths.
- file_path: A file path to resolve
-
- Returns:
- A tuple with an optional resolved :class:`Path <anyio.Path>` instance and an optional
- :class:`stat_result <os.stat_result>`.
- """
- for directory in directories:
- try:
- joined_path = Path(directory, file_path)
- file_info = await self.adapter.info(joined_path)
- if file_info and commonpath([str(directory), file_info["name"], joined_path]) == str(directory):
- return joined_path, file_info
- except FileNotFoundError:
- continue
- return None, None
-
- async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
- """ASGI callable.
-
- Args:
- scope: ASGI scope
- receive: ASGI ``receive`` callable
- send: ASGI ``send`` callable
-
- Returns:
- None
- """
- if scope["type"] != ScopeType.HTTP or scope["method"] not in {"GET", "HEAD"}:
- raise MethodNotAllowedException()
-
- res = await self.handle(path=scope["path"], is_head_response=scope["method"] == "HEAD")
- await res(scope=scope, receive=receive, send=send)
-
- async def handle(self, path: str, is_head_response: bool) -> ASGIFileResponse:
- split_path = path.split("/")
- filename = split_path[-1]
- joined_path = Path(*split_path)
- resolved_path, fs_info = await self.get_fs_info(directories=self.directories, file_path=joined_path)
- content_disposition_type: Literal["inline", "attachment"] = (
- "attachment" if self.send_as_attachment else "inline"
- )
-
- if self.is_html_mode and fs_info and fs_info["type"] == "directory":
- filename = "index.html"
- resolved_path, fs_info = await self.get_fs_info(
- directories=self.directories,
- file_path=Path(resolved_path or joined_path) / filename,
- )
-
- if fs_info and fs_info["type"] == "file":
- return ASGIFileResponse(
- file_path=resolved_path or joined_path,
- file_info=fs_info,
- file_system=self.adapter.file_system,
- filename=filename,
- content_disposition_type=content_disposition_type,
- is_head_response=is_head_response,
- headers=self.headers,
- )
-
- if self.is_html_mode:
- # for some reason coverage doesn't catch these two lines
- filename = "404.html" # pragma: no cover
- resolved_path, fs_info = await self.get_fs_info( # pragma: no cover
- directories=self.directories, file_path=filename
- )
-
- if fs_info and fs_info["type"] == "file":
- return ASGIFileResponse(
- file_path=resolved_path or joined_path,
- file_info=fs_info,
- file_system=self.adapter.file_system,
- filename=filename,
- status_code=HTTP_404_NOT_FOUND,
- content_disposition_type=content_disposition_type,
- is_head_response=is_head_response,
- headers=self.headers,
- )
-
- raise NotFoundException(
- f"no file or directory match the path {resolved_path or joined_path} was found"
- ) # pragma: no cover
diff --git a/venv/lib/python3.11/site-packages/litestar/static_files/config.py b/venv/lib/python3.11/site-packages/litestar/static_files/config.py
deleted file mode 100644
index 22b6620..0000000
--- a/venv/lib/python3.11/site-packages/litestar/static_files/config.py
+++ /dev/null
@@ -1,224 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from pathlib import PurePath # noqa: TCH003
-from typing import TYPE_CHECKING, Any, Sequence
-
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.file_system import BaseLocalFileSystem
-from litestar.handlers import asgi, get, head
-from litestar.response.file import ASGIFileResponse # noqa: TCH001
-from litestar.router import Router
-from litestar.static_files.base import StaticFiles
-from litestar.types import Empty
-from litestar.utils import normalize_path, warn_deprecation
-
-__all__ = ("StaticFilesConfig",)
-
-if TYPE_CHECKING:
- from litestar.datastructures import CacheControlHeader
- from litestar.handlers.asgi_handlers import ASGIRouteHandler
- from litestar.openapi.spec import SecurityRequirement
- from litestar.types import (
- AfterRequestHookHandler,
- AfterResponseHookHandler,
- BeforeRequestHookHandler,
- EmptyType,
- ExceptionHandlersMap,
- Guard,
- Middleware,
- PathType,
- )
-
-
-@dataclass
-class StaticFilesConfig:
- """Configuration for static file service.
-
- To enable static files, pass an instance of this class to the :class:`Litestar <litestar.app.Litestar>` constructor using
- the 'static_files_config' key.
- """
-
- path: str
- """Path to serve static files from.
-
- Note that the path cannot contain path parameters.
- """
- directories: list[PathType]
- """A list of directories to serve files from."""
- html_mode: bool = False
- """Flag dictating whether serving html.
-
- If true, the default file will be 'index.html'.
- """
- name: str | None = None
- """An optional string identifying the static files handler."""
- file_system: Any = BaseLocalFileSystem() # noqa: RUF009
- """The file_system spec to use for serving files.
-
- Notes:
- - A file_system is a class that adheres to the
- :class:`FileSystemProtocol <litestar.types.FileSystemProtocol>`.
- - You can use any of the file systems exported from the
- [fsspec](https://filesystem-spec.readthedocs.io/en/latest/) library for this purpose.
- """
- opt: dict[str, Any] | None = None
- """A string key dictionary of arbitrary values that will be added to the static files handler."""
- guards: list[Guard] | None = None
- """A list of :class:`Guard <litestar.types.Guard>` callables."""
- exception_handlers: ExceptionHandlersMap | None = None
- """A dictionary that maps handler functions to status codes and/or exception types."""
- send_as_attachment: bool = False
- """Whether to send the file as an attachment."""
-
- def __post_init__(self) -> None:
- _validate_config(path=self.path, directories=self.directories, file_system=self.file_system)
- self.path = normalize_path(self.path)
- warn_deprecation(
- "2.6.0",
- kind="class",
- deprecated_name="StaticFilesConfig",
- removal_in="3.0",
- alternative="create_static_files_router",
- info='Replace static_files_config=[StaticFilesConfig(path="/static", directories=["assets"])] with '
- 'route_handlers=[..., create_static_files_router(path="/static", directories=["assets"])]',
- )
-
- def to_static_files_app(self) -> ASGIRouteHandler:
- """Return an ASGI app serving static files based on the config.
-
- Returns:
- :class:`StaticFiles <litestar.static_files.StaticFiles>`
- """
- static_files = StaticFiles(
- is_html_mode=self.html_mode,
- directories=self.directories,
- file_system=self.file_system,
- send_as_attachment=self.send_as_attachment,
- )
- return asgi(
- path=self.path,
- name=self.name,
- is_static=True,
- opt=self.opt,
- guards=self.guards,
- exception_handlers=self.exception_handlers,
- )(static_files)
-
-
-def create_static_files_router(
- path: str,
- directories: list[PathType],
- file_system: Any = None,
- send_as_attachment: bool = False,
- html_mode: bool = False,
- name: str = "static",
- after_request: AfterRequestHookHandler | None = None,
- after_response: AfterResponseHookHandler | None = None,
- before_request: BeforeRequestHookHandler | None = None,
- cache_control: CacheControlHeader | None = None,
- exception_handlers: ExceptionHandlersMap | None = None,
- guards: list[Guard] | None = None,
- include_in_schema: bool | EmptyType = Empty,
- middleware: Sequence[Middleware] | None = None,
- opt: dict[str, Any] | None = None,
- security: Sequence[SecurityRequirement] | None = None,
- tags: Sequence[str] | None = None,
- router_class: type[Router] = Router,
- resolve_symlinks: bool = True,
-) -> Router:
- """Create a router with handlers to serve static files.
-
- Args:
- path: Path to serve static files under
- directories: Directories to serve static files from
- file_system: A *file system* implementing
- :class:`~litestar.types.FileSystemProtocol`.
- `fsspec <https://filesystem-spec.readthedocs.io/en/latest/>`_ can be passed
- here as well
- send_as_attachment: Whether to send the file as an attachment
- html_mode: When in HTML:
- - Serve an ``index.html`` file from ``/``
- - Serve ``404.html`` when a file could not be found
- name: Name to pass to the generated handlers
- after_request: ``after_request`` handlers passed to the router
- after_response: ``after_response`` handlers passed to the router
- before_request: ``before_request`` handlers passed to the router
- cache_control: ``cache_control`` passed to the router
- exception_handlers: Exception handlers passed to the router
- guards: Guards passed to the router
- include_in_schema: Include the routes / router in the OpenAPI schema
- middleware: Middlewares passed to the router
- opt: Opts passed to the router
- security: Security options passed to the router
- tags: ``tags`` passed to the router
- router_class: The class used to construct a router from
- resolve_symlinks: Resolve symlinks of ``directories``
- """
-
- if file_system is None:
- file_system = BaseLocalFileSystem()
-
- _validate_config(path=path, directories=directories, file_system=file_system)
- path = normalize_path(path)
-
- headers = None
- if cache_control:
- headers = {cache_control.HEADER_NAME: cache_control.to_header()}
-
- static_files = StaticFiles(
- is_html_mode=html_mode,
- directories=directories,
- file_system=file_system,
- send_as_attachment=send_as_attachment,
- resolve_symlinks=resolve_symlinks,
- headers=headers,
- )
-
- @get("{file_path:path}", name=name)
- async def get_handler(file_path: PurePath) -> ASGIFileResponse:
- return await static_files.handle(path=file_path.as_posix(), is_head_response=False)
-
- @head("/{file_path:path}", name=f"{name}/head")
- async def head_handler(file_path: PurePath) -> ASGIFileResponse:
- return await static_files.handle(path=file_path.as_posix(), is_head_response=True)
-
- handlers = [get_handler, head_handler]
-
- if html_mode:
-
- @get("/", name=f"{name}/index")
- async def index_handler() -> ASGIFileResponse:
- return await static_files.handle(path="/", is_head_response=False)
-
- handlers.append(index_handler)
-
- return router_class(
- after_request=after_request,
- after_response=after_response,
- before_request=before_request,
- cache_control=cache_control,
- exception_handlers=exception_handlers,
- guards=guards,
- include_in_schema=include_in_schema,
- middleware=middleware,
- opt=opt,
- path=path,
- route_handlers=handlers,
- security=security,
- tags=tags,
- )
-
-
-def _validate_config(path: str, directories: list[PathType], file_system: Any) -> None:
- if not path:
- raise ImproperlyConfiguredException("path must be a non-zero length string,")
-
- if not directories or not any(bool(d) for d in directories):
- raise ImproperlyConfiguredException("directories must include at least one path.")
-
- if "{" in path:
- raise ImproperlyConfiguredException("path parameters are not supported for static files")
-
- if not (callable(getattr(file_system, "info", None)) and callable(getattr(file_system, "open", None))):
- raise ImproperlyConfiguredException("file_system must adhere to the FileSystemProtocol type")
diff --git a/venv/lib/python3.11/site-packages/litestar/status_codes.py b/venv/lib/python3.11/site-packages/litestar/status_codes.py
deleted file mode 100644
index 9293365..0000000
--- a/venv/lib/python3.11/site-packages/litestar/status_codes.py
+++ /dev/null
@@ -1,321 +0,0 @@
-from typing import Final
-
-# HTTP Status Codes
-
-HTTP_100_CONTINUE: Final = 100
-"""HTTP status code 'Continue'"""
-
-HTTP_101_SWITCHING_PROTOCOLS: Final = 101
-"""HTTP status code 'Switching Protocols'"""
-
-HTTP_102_PROCESSING: Final = 102
-"""HTTP status code 'Processing'"""
-
-HTTP_103_EARLY_HINTS: Final = 103
-"""HTTP status code 'Early Hints'"""
-
-HTTP_200_OK: Final = 200
-"""HTTP status code 'OK'"""
-
-HTTP_201_CREATED: Final = 201
-"""HTTP status code 'Created'"""
-
-HTTP_202_ACCEPTED: Final = 202
-"""HTTP status code 'Accepted'"""
-
-HTTP_203_NON_AUTHORITATIVE_INFORMATION: Final = 203
-"""HTTP status code 'Non Authoritative Information'"""
-
-HTTP_204_NO_CONTENT: Final = 204
-"""HTTP status code 'No Content'"""
-
-HTTP_205_RESET_CONTENT: Final = 205
-"""HTTP status code 'Reset Content'"""
-
-HTTP_206_PARTIAL_CONTENT: Final = 206
-"""HTTP status code 'Partial Content'"""
-
-HTTP_207_MULTI_STATUS: Final = 207
-"""HTTP status code 'Multi Status'"""
-
-HTTP_208_ALREADY_REPORTED: Final = 208
-"""HTTP status code 'Already Reported'"""
-
-HTTP_226_IM_USED: Final = 226
-"""HTTP status code 'I'm Used'"""
-
-HTTP_300_MULTIPLE_CHOICES: Final = 300
-"""HTTP status code 'Multiple Choices'"""
-
-HTTP_301_MOVED_PERMANENTLY: Final = 301
-"""HTTP status code 'Moved Permanently'"""
-
-HTTP_302_FOUND: Final = 302
-"""HTTP status code 'Found'"""
-
-HTTP_303_SEE_OTHER: Final = 303
-"""HTTP status code 'See Other'"""
-
-HTTP_304_NOT_MODIFIED: Final = 304
-"""HTTP status code 'Not Modified'"""
-
-HTTP_305_USE_PROXY: Final = 305
-"""HTTP status code 'Use Proxy'"""
-
-HTTP_306_RESERVED: Final = 306
-"""HTTP status code 'Reserved'"""
-
-HTTP_307_TEMPORARY_REDIRECT: Final = 307
-"""HTTP status code 'Temporary Redirect'"""
-
-HTTP_308_PERMANENT_REDIRECT: Final = 308
-"""HTTP status code 'Permanent Redirect'"""
-
-HTTP_400_BAD_REQUEST: Final = 400
-"""HTTP status code 'Bad Request'"""
-
-HTTP_401_UNAUTHORIZED: Final = 401
-"""HTTP status code 'Unauthorized'"""
-
-HTTP_402_PAYMENT_REQUIRED: Final = 402
-"""HTTP status code 'Payment Required'"""
-
-HTTP_403_FORBIDDEN: Final = 403
-"""HTTP status code 'Forbidden'"""
-
-HTTP_404_NOT_FOUND: Final = 404
-"""HTTP status code 'Not Found'"""
-
-HTTP_405_METHOD_NOT_ALLOWED: Final = 405
-"""HTTP status code 'Method Not Allowed'"""
-
-HTTP_406_NOT_ACCEPTABLE: Final = 406
-"""HTTP status code 'Not Acceptable'"""
-
-HTTP_407_PROXY_AUTHENTICATION_REQUIRED: Final = 407
-"""HTTP status code 'Proxy Authentication Required'"""
-
-HTTP_408_REQUEST_TIMEOUT: Final = 408
-"""HTTP status code 'Request Timeout'"""
-
-HTTP_409_CONFLICT: Final = 409
-"""HTTP status code 'Conflict'"""
-
-HTTP_410_GONE: Final = 410
-"""HTTP status code 'Gone'"""
-
-HTTP_411_LENGTH_REQUIRED: Final = 411
-"""HTTP status code 'Length Required'"""
-
-HTTP_412_PRECONDITION_FAILED: Final = 412
-"""HTTP status code 'Precondition Failed'"""
-
-HTTP_413_REQUEST_ENTITY_TOO_LARGE: Final = 413
-"""HTTP status code 'Request Entity Too Large'"""
-
-HTTP_414_REQUEST_URI_TOO_LONG: Final = 414
-"""HTTP status code 'Request URI Too Long'"""
-
-HTTP_415_UNSUPPORTED_MEDIA_TYPE: Final = 415
-"""HTTP status code 'Unsupported Media Type'"""
-
-HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE: Final = 416
-"""HTTP status code 'Requested Range Not Satisfiable'"""
-
-HTTP_417_EXPECTATION_FAILED: Final = 417
-"""HTTP status code 'Expectation Failed'"""
-
-HTTP_418_IM_A_TEAPOT: Final = 418
-"""HTTP status code 'I'm A Teapot'"""
-
-HTTP_421_MISDIRECTED_REQUEST: Final = 421
-"""HTTP status code 'Misdirected Request'"""
-
-HTTP_422_UNPROCESSABLE_ENTITY: Final = 422
-"""HTTP status code 'Unprocessable Entity'"""
-
-HTTP_423_LOCKED: Final = 423
-"""HTTP status code 'Locked'"""
-
-HTTP_424_FAILED_DEPENDENCY: Final = 424
-"""HTTP status code 'Failed Dependency'"""
-
-HTTP_425_TOO_EARLY: Final = 425
-"""HTTP status code 'Too Early'"""
-
-HTTP_426_UPGRADE_REQUIRED: Final = 426
-"""HTTP status code 'Upgrade Required'"""
-
-HTTP_428_PRECONDITION_REQUIRED: Final = 428
-"""HTTP status code 'Precondition Required'"""
-
-HTTP_429_TOO_MANY_REQUESTS: Final = 429
-"""HTTP status code 'Too Many Requests'"""
-
-HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE: Final = 431
-"""HTTP status code 'Request Header Fields Too Large'"""
-
-HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS: Final = 451
-"""HTTP status code 'Unavailable For Legal Reasons'"""
-
-HTTP_500_INTERNAL_SERVER_ERROR: Final = 500
-"""HTTP status code 'Internal Server Error'"""
-
-HTTP_501_NOT_IMPLEMENTED: Final = 501
-"""HTTP status code 'Not Implemented'"""
-
-HTTP_502_BAD_GATEWAY: Final = 502
-"""HTTP status code 'Bad Gateway'"""
-
-HTTP_503_SERVICE_UNAVAILABLE: Final = 503
-"""HTTP status code 'Service Unavailable'"""
-
-HTTP_504_GATEWAY_TIMEOUT: Final = 504
-"""HTTP status code 'Gateway Timeout'"""
-
-HTTP_505_HTTP_VERSION_NOT_SUPPORTED: Final = 505
-"""HTTP status code 'Http Version Not Supported'"""
-
-HTTP_506_VARIANT_ALSO_NEGOTIATES: Final = 506
-"""HTTP status code 'Variant Also Negotiates'"""
-
-HTTP_507_INSUFFICIENT_STORAGE: Final = 507
-"""HTTP status code 'Insufficient Storage'"""
-
-HTTP_508_LOOP_DETECTED: Final = 508
-"""HTTP status code 'Loop Detected'"""
-
-HTTP_510_NOT_EXTENDED: Final = 510
-"""HTTP status code 'Not Extended'"""
-
-HTTP_511_NETWORK_AUTHENTICATION_REQUIRED: Final = 511
-"""HTTP status code 'Network Authentication Required'"""
-
-
-# Websocket Codes
-WS_1000_NORMAL_CLOSURE: Final = 1000
-"""WebSocket status code 'Normal Closure'"""
-
-WS_1001_GOING_AWAY: Final = 1001
-"""WebSocket status code 'Going Away'"""
-
-WS_1002_PROTOCOL_ERROR: Final = 1002
-"""WebSocket status code 'Protocol Error'"""
-
-WS_1003_UNSUPPORTED_DATA: Final = 1003
-"""WebSocket status code 'Unsupported Data'"""
-
-WS_1005_NO_STATUS_RECEIVED: Final = 1005
-"""WebSocket status code 'No Status Received'"""
-
-WS_1006_ABNORMAL_CLOSURE: Final = 1006
-"""WebSocket status code 'Abnormal Closure'"""
-
-WS_1007_INVALID_FRAME_PAYLOAD_DATA: Final = 1007
-"""WebSocket status code 'Invalid Frame Payload Data'"""
-
-WS_1008_POLICY_VIOLATION: Final = 1008
-"""WebSocket status code 'Policy Violation'"""
-
-WS_1009_MESSAGE_TOO_BIG: Final = 1009
-"""WebSocket status code 'Message Too Big'"""
-
-WS_1010_MANDATORY_EXT: Final = 1010
-"""WebSocket status code 'Mandatory Ext.'"""
-
-WS_1011_INTERNAL_ERROR: Final = 1011
-"""WebSocket status code 'Internal Error'"""
-
-WS_1012_SERVICE_RESTART: Final = 1012
-"""WebSocket status code 'Service Restart'"""
-
-WS_1013_TRY_AGAIN_LATER: Final = 1013
-"""WebSocket status code 'Try Again Later'"""
-
-WS_1014_BAD_GATEWAY: Final = 1014
-"""WebSocket status code 'Bad Gateway'"""
-
-WS_1015_TLS_HANDSHAKE: Final = 1015
-"""WebSocket status code 'TLS Handshake'"""
-
-
-__all__ = (
- "HTTP_100_CONTINUE",
- "HTTP_101_SWITCHING_PROTOCOLS",
- "HTTP_102_PROCESSING",
- "HTTP_103_EARLY_HINTS",
- "HTTP_200_OK",
- "HTTP_201_CREATED",
- "HTTP_202_ACCEPTED",
- "HTTP_203_NON_AUTHORITATIVE_INFORMATION",
- "HTTP_204_NO_CONTENT",
- "HTTP_205_RESET_CONTENT",
- "HTTP_206_PARTIAL_CONTENT",
- "HTTP_207_MULTI_STATUS",
- "HTTP_208_ALREADY_REPORTED",
- "HTTP_226_IM_USED",
- "HTTP_300_MULTIPLE_CHOICES",
- "HTTP_301_MOVED_PERMANENTLY",
- "HTTP_302_FOUND",
- "HTTP_303_SEE_OTHER",
- "HTTP_304_NOT_MODIFIED",
- "HTTP_305_USE_PROXY",
- "HTTP_306_RESERVED",
- "HTTP_307_TEMPORARY_REDIRECT",
- "HTTP_308_PERMANENT_REDIRECT",
- "HTTP_400_BAD_REQUEST",
- "HTTP_401_UNAUTHORIZED",
- "HTTP_402_PAYMENT_REQUIRED",
- "HTTP_403_FORBIDDEN",
- "HTTP_404_NOT_FOUND",
- "HTTP_405_METHOD_NOT_ALLOWED",
- "HTTP_406_NOT_ACCEPTABLE",
- "HTTP_407_PROXY_AUTHENTICATION_REQUIRED",
- "HTTP_408_REQUEST_TIMEOUT",
- "HTTP_409_CONFLICT",
- "HTTP_410_GONE",
- "HTTP_411_LENGTH_REQUIRED",
- "HTTP_412_PRECONDITION_FAILED",
- "HTTP_413_REQUEST_ENTITY_TOO_LARGE",
- "HTTP_414_REQUEST_URI_TOO_LONG",
- "HTTP_415_UNSUPPORTED_MEDIA_TYPE",
- "HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE",
- "HTTP_417_EXPECTATION_FAILED",
- "HTTP_418_IM_A_TEAPOT",
- "HTTP_421_MISDIRECTED_REQUEST",
- "HTTP_422_UNPROCESSABLE_ENTITY",
- "HTTP_423_LOCKED",
- "HTTP_424_FAILED_DEPENDENCY",
- "HTTP_425_TOO_EARLY",
- "HTTP_426_UPGRADE_REQUIRED",
- "HTTP_428_PRECONDITION_REQUIRED",
- "HTTP_429_TOO_MANY_REQUESTS",
- "HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE",
- "HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS",
- "HTTP_500_INTERNAL_SERVER_ERROR",
- "HTTP_501_NOT_IMPLEMENTED",
- "HTTP_502_BAD_GATEWAY",
- "HTTP_503_SERVICE_UNAVAILABLE",
- "HTTP_504_GATEWAY_TIMEOUT",
- "HTTP_505_HTTP_VERSION_NOT_SUPPORTED",
- "HTTP_506_VARIANT_ALSO_NEGOTIATES",
- "HTTP_507_INSUFFICIENT_STORAGE",
- "HTTP_508_LOOP_DETECTED",
- "HTTP_510_NOT_EXTENDED",
- "HTTP_511_NETWORK_AUTHENTICATION_REQUIRED",
- "WS_1000_NORMAL_CLOSURE",
- "WS_1001_GOING_AWAY",
- "WS_1002_PROTOCOL_ERROR",
- "WS_1003_UNSUPPORTED_DATA",
- "WS_1005_NO_STATUS_RECEIVED",
- "WS_1006_ABNORMAL_CLOSURE",
- "WS_1007_INVALID_FRAME_PAYLOAD_DATA",
- "WS_1008_POLICY_VIOLATION",
- "WS_1009_MESSAGE_TOO_BIG",
- "WS_1010_MANDATORY_EXT",
- "WS_1011_INTERNAL_ERROR",
- "WS_1012_SERVICE_RESTART",
- "WS_1013_TRY_AGAIN_LATER",
- "WS_1014_BAD_GATEWAY",
- "WS_1015_TLS_HANDSHAKE",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/stores/__init__.py b/venv/lib/python3.11/site-packages/litestar/stores/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/venv/lib/python3.11/site-packages/litestar/stores/__init__.py
+++ /dev/null
diff --git a/venv/lib/python3.11/site-packages/litestar/stores/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/stores/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 78604d0..0000000
--- a/venv/lib/python3.11/site-packages/litestar/stores/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/stores/__pycache__/base.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/stores/__pycache__/base.cpython-311.pyc
deleted file mode 100644
index 21d2fb4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/stores/__pycache__/base.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/stores/__pycache__/file.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/stores/__pycache__/file.cpython-311.pyc
deleted file mode 100644
index b39333c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/stores/__pycache__/file.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/stores/__pycache__/memory.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/stores/__pycache__/memory.cpython-311.pyc
deleted file mode 100644
index c8e3b05..0000000
--- a/venv/lib/python3.11/site-packages/litestar/stores/__pycache__/memory.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/stores/__pycache__/redis.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/stores/__pycache__/redis.cpython-311.pyc
deleted file mode 100644
index 21e7e2f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/stores/__pycache__/redis.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/stores/__pycache__/registry.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/stores/__pycache__/registry.cpython-311.pyc
deleted file mode 100644
index c87c31a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/stores/__pycache__/registry.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/stores/base.py b/venv/lib/python3.11/site-packages/litestar/stores/base.py
deleted file mode 100644
index 34aa514..0000000
--- a/venv/lib/python3.11/site-packages/litestar/stores/base.py
+++ /dev/null
@@ -1,145 +0,0 @@
-from __future__ import annotations
-
-from abc import ABC, abstractmethod
-from datetime import datetime, timedelta, timezone
-from typing import TYPE_CHECKING, Optional
-
-from msgspec import Struct
-from msgspec.msgpack import decode as msgpack_decode
-from msgspec.msgpack import encode as msgpack_encode
-
-if TYPE_CHECKING:
- from types import TracebackType
-
- from typing_extensions import Self
-
-
-__all__ = ("Store", "NamespacedStore", "StorageObject")
-
-
-class Store(ABC):
- """Thread and process safe asynchronous key/value store."""
-
- @abstractmethod
- async def set(self, key: str, value: str | bytes, expires_in: int | timedelta | None = None) -> None:
- """Set a value.
-
- Args:
- key: Key to associate the value with
- value: Value to store
- expires_in: Time in seconds before the key is considered expired
-
- Returns:
- ``None``
- """
- raise NotImplementedError
-
- @abstractmethod
- async def get(self, key: str, renew_for: int | timedelta | None = None) -> bytes | None:
- """Get a value.
-
- Args:
- key: Key associated with the value
- renew_for: If given and the value had an initial expiry time set, renew the
- expiry time for ``renew_for`` seconds. If the value has not been set
- with an expiry time this is a no-op
-
- Returns:
- The value associated with ``key`` if it exists and is not expired, else
- ``None``
- """
- raise NotImplementedError
-
- @abstractmethod
- async def delete(self, key: str) -> None:
- """Delete a value.
-
- If no such key exists, this is a no-op.
-
- Args:
- key: Key of the value to delete
- """
- raise NotImplementedError
-
- @abstractmethod
- async def delete_all(self) -> None:
- """Delete all stored values."""
- raise NotImplementedError
-
- @abstractmethod
- async def exists(self, key: str) -> bool:
- """Check if a given ``key`` exists."""
- raise NotImplementedError
-
- @abstractmethod
- async def expires_in(self, key: str) -> int | None:
- """Get the time in seconds ``key`` expires in. If no such ``key`` exists or no
- expiry time was set, return ``None``.
- """
- raise NotImplementedError
-
- async def __aenter__(self) -> None: # noqa: B027
- pass
-
- async def __aexit__( # noqa: B027
- self,
- exc_type: type[BaseException] | None,
- exc_val: BaseException | None,
- exc_tb: TracebackType | None,
- ) -> None:
- pass
-
-
-class NamespacedStore(Store):
- """A subclass of :class:`Store`, offering hierarchical namespacing.
-
- Bulk actions on a parent namespace should affect all child namespaces, whereas other operations on all namespaces
- should be isolated.
- """
-
- @abstractmethod
- def with_namespace(self, namespace: str) -> Self:
- """Return a new instance of :class:`NamespacedStore`, which exists in a child namespace of the current namespace.
- Bulk actions on the parent namespace should affect all child namespaces, whereas other operations on all
- namespaces should be isolated.
- """
-
-
-class StorageObject(Struct):
- """:class:`msgspec.Struct` to store serialized data alongside with their expiry time."""
-
- expires_at: Optional[datetime] # noqa: UP007
- data: bytes
-
- @classmethod
- def new(cls, data: bytes, expires_in: int | timedelta | None) -> StorageObject:
- """Construct a new :class:`StorageObject` instance."""
- if expires_in is not None and not isinstance(expires_in, timedelta):
- expires_in = timedelta(seconds=expires_in)
- return cls(
- data=data,
- expires_at=(datetime.now(tz=timezone.utc) + expires_in) if expires_in else None,
- )
-
- @property
- def expired(self) -> bool:
- """Return if the :class:`StorageObject` is expired"""
- return self.expires_at is not None and datetime.now(tz=timezone.utc) >= self.expires_at
-
- @property
- def expires_in(self) -> int:
- """Return the expiry time of this ``StorageObject`` in seconds. If no expiry time
- was set, return ``-1``.
- """
- if self.expires_at:
- return int(self.expires_at.timestamp() - datetime.now(tz=timezone.utc).timestamp())
- return -1
-
- def to_bytes(self) -> bytes:
- """Encode the instance to bytes"""
- return msgpack_encode(self)
-
- @classmethod
- def from_bytes(cls, raw: bytes) -> StorageObject:
- """Load a previously encoded with :meth:`StorageObject.to_bytes`"""
- return msgpack_decode(raw, type=cls)
diff --git a/venv/lib/python3.11/site-packages/litestar/stores/file.py b/venv/lib/python3.11/site-packages/litestar/stores/file.py
deleted file mode 100644
index 25c52eb..0000000
--- a/venv/lib/python3.11/site-packages/litestar/stores/file.py
+++ /dev/null
@@ -1,170 +0,0 @@
-from __future__ import annotations
-
-import os
-import shutil
-import unicodedata
-from tempfile import mkstemp
-from typing import TYPE_CHECKING
-
-from anyio import Path
-
-from litestar.concurrency import sync_to_thread
-
-from .base import NamespacedStore, StorageObject
-
-__all__ = ("FileStore",)
-
-
-if TYPE_CHECKING:
- from datetime import timedelta
- from os import PathLike
-
-
-def _safe_file_name(name: str) -> str:
- name = unicodedata.normalize("NFKD", name)
- return "".join(c if c.isalnum() else str(ord(c)) for c in name)
-
-
-class FileStore(NamespacedStore):
- """File based, thread and process safe, asynchronous key/value store."""
-
- __slots__ = {"path": "file path"}
-
- def __init__(self, path: PathLike[str]) -> None:
- """Initialize ``FileStorage``.
-
- Args:
- path: Path to store data under
- """
- self.path = Path(path)
-
- def with_namespace(self, namespace: str) -> FileStore:
- """Return a new instance of :class:`FileStore`, using a sub-path of the current store's path."""
- if not namespace.isalnum():
- raise ValueError(f"Invalid namespace: {namespace!r}")
- return FileStore(self.path / namespace)
-
- def _path_from_key(self, key: str) -> Path:
- return self.path / _safe_file_name(key)
-
- @staticmethod
- async def _load_from_path(path: Path) -> StorageObject | None:
- try:
- data = await path.read_bytes()
- return StorageObject.from_bytes(data)
- except FileNotFoundError:
- return None
-
- def _write_sync(self, target_file: Path, storage_obj: StorageObject) -> None:
- try:
- tmp_file_fd, tmp_file_name = mkstemp(dir=self.path, prefix=f"{target_file.name}.tmp")
- renamed = False
- try:
- try:
- os.write(tmp_file_fd, storage_obj.to_bytes())
- finally:
- os.close(tmp_file_fd)
-
- os.replace(tmp_file_name, target_file) # noqa: PTH105
- renamed = True
- finally:
- if not renamed:
- os.unlink(tmp_file_name) # noqa: PTH108
- except OSError:
- pass
-
- async def _write(self, target_file: Path, storage_obj: StorageObject) -> None:
- await sync_to_thread(self._write_sync, target_file, storage_obj)
-
- async def set(self, key: str, value: str | bytes, expires_in: int | timedelta | None = None) -> None:
- """Set a value.
-
- Args:
- key: Key to associate the value with
- value: Value to store
- expires_in: Time in seconds before the key is considered expired
-
- Returns:
- ``None``
- """
-
- await self.path.mkdir(exist_ok=True)
- path = self._path_from_key(key)
- if isinstance(value, str):
- value = value.encode("utf-8")
- storage_obj = StorageObject.new(data=value, expires_in=expires_in)
- await self._write(path, storage_obj)
-
- async def get(self, key: str, renew_for: int | timedelta | None = None) -> bytes | None:
- """Get a value.
-
- Args:
- key: Key associated with the value
- renew_for: If given and the value had an initial expiry time set, renew the
- expiry time for ``renew_for`` seconds. If the value has not been set
- with an expiry time this is a no-op
-
- Returns:
- The value associated with ``key`` if it exists and is not expired, else
- ``None``
- """
- path = self._path_from_key(key)
- storage_obj = await self._load_from_path(path)
-
- if not storage_obj:
- return None
-
- if storage_obj.expired:
- await path.unlink(missing_ok=True)
- return None
-
- if renew_for and storage_obj.expires_at:
- await self.set(key, value=storage_obj.data, expires_in=renew_for)
-
- return storage_obj.data
-
- async def delete(self, key: str) -> None:
- """Delete a value.
-
- If no such key exists, this is a no-op.
-
- Args:
- key: Key of the value to delete
- """
- path = self._path_from_key(key)
- await path.unlink(missing_ok=True)
-
- async def delete_all(self) -> None:
- """Delete all stored values.
-
- Note:
- This deletes and recreates :attr:`FileStore.path`
- """
-
- await sync_to_thread(shutil.rmtree, self.path)
- await self.path.mkdir(exist_ok=True)
-
- async def delete_expired(self) -> None:
- """Delete expired items.
-
- Since expired items are normally only cleared on access (i.e. when calling
- :meth:`.get`), this method should be called in regular intervals
- to free disk space.
- """
- async for file in self.path.iterdir():
- wrapper = await self._load_from_path(file)
- if wrapper and wrapper.expired:
- await file.unlink(missing_ok=True)
-
- async def exists(self, key: str) -> bool:
- """Check if a given ``key`` exists."""
- path = self._path_from_key(key)
- return await path.exists()
-
- async def expires_in(self, key: str) -> int | None:
- """Get the time in seconds ``key`` expires in. If no such ``key`` exists or no
- expiry time was set, return ``None``.
- """
- if storage_obj := await self._load_from_path(self._path_from_key(key)):
- return storage_obj.expires_in
- return None
diff --git a/venv/lib/python3.11/site-packages/litestar/stores/memory.py b/venv/lib/python3.11/site-packages/litestar/stores/memory.py
deleted file mode 100644
index 1da8931..0000000
--- a/venv/lib/python3.11/site-packages/litestar/stores/memory.py
+++ /dev/null
@@ -1,115 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING
-
-import anyio
-from anyio import Lock
-
-from .base import StorageObject, Store
-
-__all__ = ("MemoryStore",)
-
-
-if TYPE_CHECKING:
- from datetime import timedelta
-
-
-class MemoryStore(Store):
- """In memory, atomic, asynchronous key/value store."""
-
- __slots__ = ("_store", "_lock")
-
- def __init__(self) -> None:
- """Initialize :class:`MemoryStore`"""
- self._store: dict[str, StorageObject] = {}
- self._lock = Lock()
-
- async def set(self, key: str, value: str | bytes, expires_in: int | timedelta | None = None) -> None:
- """Set a value.
-
- Args:
- key: Key to associate the value with
- value: Value to store
- expires_in: Time in seconds before the key is considered expired
-
- Returns:
- ``None``
- """
- if isinstance(value, str):
- value = value.encode("utf-8")
- async with self._lock:
- self._store[key] = StorageObject.new(data=value, expires_in=expires_in)
-
- async def get(self, key: str, renew_for: int | timedelta | None = None) -> bytes | None:
- """Get a value.
-
- Args:
- key: Key associated with the value
- renew_for: If given and the value had an initial expiry time set, renew the
- expiry time for ``renew_for`` seconds. If the value has not been set
- with an expiry time this is a no-op
-
- Returns:
- The value associated with ``key`` if it exists and is not expired, else
- ``None``
- """
- async with self._lock:
- storage_obj = self._store.get(key)
-
- if not storage_obj:
- return None
-
- if storage_obj.expired:
- self._store.pop(key)
- return None
-
- if renew_for and storage_obj.expires_at:
- # don't use .set() here, so we can hold onto the lock for the whole operation
- storage_obj = StorageObject.new(data=storage_obj.data, expires_in=renew_for)
- self._store[key] = storage_obj
-
- return storage_obj.data
-
- async def delete(self, key: str) -> None:
- """Delete a value.
-
- If no such key exists, this is a no-op.
-
- Args:
- key: Key of the value to delete
- """
- async with self._lock:
- self._store.pop(key, None)
-
- async def delete_all(self) -> None:
- """Delete all stored values."""
- async with self._lock:
- self._store.clear()
-
- async def delete_expired(self) -> None:
- """Delete expired items.
-
- Since expired items are normally only cleared on access (i.e. when calling
- :meth:`.get`), this method should be called in regular intervals
- to free memory.
- """
- async with self._lock:
- new_store = {}
- for i, (key, storage_obj) in enumerate(self._store.items()):
- if not storage_obj.expired:
- new_store[key] = storage_obj
- if i % 1000 == 0:
- await anyio.sleep(0)
- self._store = new_store
-
- async def exists(self, key: str) -> bool:
- """Check if a given ``key`` exists."""
- return key in self._store
-
- async def expires_in(self, key: str) -> int | None:
- """Get the time in seconds ``key`` expires in. If no such ``key`` exists or no
- expiry time was set, return ``None``.
- """
- if storage_obj := self._store.get(key):
- return storage_obj.expires_in
- return None
diff --git a/venv/lib/python3.11/site-packages/litestar/stores/redis.py b/venv/lib/python3.11/site-packages/litestar/stores/redis.py
deleted file mode 100644
index 6697962..0000000
--- a/venv/lib/python3.11/site-packages/litestar/stores/redis.py
+++ /dev/null
@@ -1,204 +0,0 @@
-from __future__ import annotations
-
-from datetime import timedelta
-from typing import TYPE_CHECKING, cast
-
-from redis.asyncio import Redis
-from redis.asyncio.connection import ConnectionPool
-
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.types import Empty, EmptyType
-from litestar.utils.empty import value_or_default
-
-from .base import NamespacedStore
-
-__all__ = ("RedisStore",)
-
-if TYPE_CHECKING:
- from types import TracebackType
-
-
-class RedisStore(NamespacedStore):
- """Redis based, thread and process safe asynchronous key/value store."""
-
- __slots__ = ("_redis",)
-
- def __init__(
- self, redis: Redis, namespace: str | None | EmptyType = Empty, handle_client_shutdown: bool = False
- ) -> None:
- """Initialize :class:`RedisStore`
-
- Args:
- redis: An :class:`redis.asyncio.Redis` instance
- namespace: A key prefix to simulate a namespace in redis. If not given,
- defaults to ``LITESTAR``. Namespacing can be explicitly disabled by passing
- ``None``. This will make :meth:`.delete_all` unavailable.
- handle_client_shutdown: If ``True``, handle the shutdown of the `redis` instance automatically during the store's lifespan. Should be set to `True` unless the shutdown is handled externally
- """
- self._redis = redis
- self.namespace: str | None = value_or_default(namespace, "LITESTAR")
- self.handle_client_shutdown = handle_client_shutdown
-
- # script to get and renew a key in one atomic step
- self._get_and_renew_script = self._redis.register_script(
- b"""
- local key = KEYS[1]
- local renew = tonumber(ARGV[1])
-
- local data = redis.call('GET', key)
- local ttl = redis.call('TTL', key)
-
- if ttl > 0 then
- redis.call('EXPIRE', key, renew)
- end
-
- return data
- """
- )
-
- # script to delete all keys in the namespace
- self._delete_all_script = self._redis.register_script(
- b"""
- local cursor = 0
-
- repeat
- local result = redis.call('SCAN', cursor, 'MATCH', ARGV[1])
- for _,key in ipairs(result[2]) do
- redis.call('UNLINK', key)
- end
- cursor = tonumber(result[1])
- until cursor == 0
- """
- )
-
- async def _shutdown(self) -> None:
- if self.handle_client_shutdown:
- await self._redis.aclose(close_connection_pool=True) # type: ignore[attr-defined]
-
- async def __aexit__(
- self,
- exc_type: type[BaseException] | None,
- exc_val: BaseException | None,
- exc_tb: TracebackType | None,
- ) -> None:
- await self._shutdown()
-
- @classmethod
- def with_client(
- cls,
- url: str = "redis://localhost:6379",
- *,
- db: int | None = None,
- port: int | None = None,
- username: str | None = None,
- password: str | None = None,
- namespace: str | None | EmptyType = Empty,
- ) -> RedisStore:
- """Initialize a :class:`RedisStore` instance with a new class:`redis.asyncio.Redis` instance.
-
- Args:
- url: Redis URL to connect to
- db: Redis database to use
- port: Redis port to use
- username: Redis username to use
- password: Redis password to use
- namespace: Virtual key namespace to use
- """
- pool = ConnectionPool.from_url(
- url=url,
- db=db,
- decode_responses=False,
- port=port,
- username=username,
- password=password,
- )
- return cls(
- redis=Redis(connection_pool=pool),
- namespace=namespace,
- handle_client_shutdown=True,
- )
-
- def with_namespace(self, namespace: str) -> RedisStore:
- """Return a new :class:`RedisStore` with a nested virtual key namespace.
- The current instances namespace will serve as a prefix for the namespace, so it
- can be considered the parent namespace.
- """
- return type(self)(
- redis=self._redis,
- namespace=f"{self.namespace}_{namespace}" if self.namespace else namespace,
- handle_client_shutdown=self.handle_client_shutdown,
- )
-
- def _make_key(self, key: str) -> str:
- prefix = f"{self.namespace}:" if self.namespace else ""
- return prefix + key
-
- async def set(self, key: str, value: str | bytes, expires_in: int | timedelta | None = None) -> None:
- """Set a value.
-
- Args:
- key: Key to associate the value with
- value: Value to store
- expires_in: Time in seconds before the key is considered expired
-
- Returns:
- ``None``
- """
- if isinstance(value, str):
- value = value.encode("utf-8")
- await self._redis.set(self._make_key(key), value, ex=expires_in)
-
- async def get(self, key: str, renew_for: int | timedelta | None = None) -> bytes | None:
- """Get a value.
-
- Args:
- key: Key associated with the value
- renew_for: If given and the value had an initial expiry time set, renew the
- expiry time for ``renew_for`` seconds. If the value has not been set
- with an expiry time this is a no-op. Atomicity of this step is guaranteed
- by using a lua script to execute fetch and renewal. If ``renew_for`` is
- not given, the script will be bypassed so no overhead will occur
-
- Returns:
- The value associated with ``key`` if it exists and is not expired, else
- ``None``
- """
- key = self._make_key(key)
- if renew_for:
- if isinstance(renew_for, timedelta):
- renew_for = renew_for.seconds
- data = await self._get_and_renew_script(keys=[key], args=[renew_for])
- return cast("bytes | None", data)
- return await self._redis.get(key)
-
- async def delete(self, key: str) -> None:
- """Delete a value.
-
- If no such key exists, this is a no-op.
-
- Args:
- key: Key of the value to delete
- """
- await self._redis.delete(self._make_key(key))
-
- async def delete_all(self) -> None:
- """Delete all stored values in the virtual key namespace.
-
- Raises:
- ImproperlyConfiguredException: If no namespace was configured
- """
- if not self.namespace:
- raise ImproperlyConfiguredException("Cannot perform delete operation: No namespace configured")
-
- await self._delete_all_script(keys=[], args=[f"{self.namespace}*:*"])
-
- async def exists(self, key: str) -> bool:
- """Check if a given ``key`` exists."""
- return await self._redis.exists(self._make_key(key)) == 1
-
- async def expires_in(self, key: str) -> int | None:
- """Get the time in seconds ``key`` expires in. If no such ``key`` exists or no
- expiry time was set, return ``None``.
- """
- ttl = await self._redis.ttl(self._make_key(key))
- return None if ttl == -2 else ttl
diff --git a/venv/lib/python3.11/site-packages/litestar/stores/registry.py b/venv/lib/python3.11/site-packages/litestar/stores/registry.py
deleted file mode 100644
index 11a08c2..0000000
--- a/venv/lib/python3.11/site-packages/litestar/stores/registry.py
+++ /dev/null
@@ -1,64 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Callable
-
-if TYPE_CHECKING:
- from .base import Store
-
-
-from .memory import MemoryStore
-
-__all__ = ("StoreRegistry",)
-
-
-def default_default_factory(name: str) -> Store:
- return MemoryStore()
-
-
-class StoreRegistry:
- """Registry for :class:`Store <.base.Store>` instances."""
-
- __slots__ = ("_stores", "_default_factory")
-
- def __init__(
- self, stores: dict[str, Store] | None = None, default_factory: Callable[[str], Store] = default_default_factory
- ) -> None:
- """Initialize ``StoreRegistry``.
-
- Args:
- stores: A dictionary mapping store names to stores, used to initialize the registry
- default_factory: A callable used by :meth:`StoreRegistry.get` to provide a store, if the requested name hasn't
- been registered yet. This callable receives the requested name and should return a
- :class:`Store <.base.Store>` instance.
- """
- self._stores = stores or {}
- self._default_factory = default_factory
-
- def register(self, name: str, store: Store, allow_override: bool = False) -> None:
- """Register a new :class:`Store <.base.Store>`.
-
- Args:
- name: Name to register the store under
- store: The store to register
- allow_override: Whether to allow overriding an existing store of the same name
-
- Raises:
- ValueError: If a store is already registered under this name and ``override`` is not ``True``
- """
- if not allow_override and name in self._stores:
- raise ValueError(f"Store with the name {name!r} already exists")
- self._stores[name] = store
-
- def get(self, name: str) -> Store:
- """Get a store registered under ``name``. If no such store is registered, create a store using the default
- factory with ``name`` and register the returned store under ``name``.
-
- Args:
- name: Name of the store
-
- Returns:
- A :class:`Store <.base.Store>`
- """
- if not self._stores.get(name):
- self._stores[name] = self._default_factory(name)
- return self._stores[name]
diff --git a/venv/lib/python3.11/site-packages/litestar/template/__init__.py b/venv/lib/python3.11/site-packages/litestar/template/__init__.py
deleted file mode 100644
index 5989cea..0000000
--- a/venv/lib/python3.11/site-packages/litestar/template/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from litestar.template.base import TemplateEngineProtocol, TemplateProtocol
-from litestar.template.config import TemplateConfig
-
-__all__ = ("TemplateEngineProtocol", "TemplateProtocol", "TemplateConfig")
diff --git a/venv/lib/python3.11/site-packages/litestar/template/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/template/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 7270a06..0000000
--- a/venv/lib/python3.11/site-packages/litestar/template/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/template/__pycache__/base.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/template/__pycache__/base.cpython-311.pyc
deleted file mode 100644
index f69e72d..0000000
--- a/venv/lib/python3.11/site-packages/litestar/template/__pycache__/base.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/template/__pycache__/config.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/template/__pycache__/config.cpython-311.pyc
deleted file mode 100644
index 536a922..0000000
--- a/venv/lib/python3.11/site-packages/litestar/template/__pycache__/config.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/template/base.py b/venv/lib/python3.11/site-packages/litestar/template/base.py
deleted file mode 100644
index 3474717..0000000
--- a/venv/lib/python3.11/site-packages/litestar/template/base.py
+++ /dev/null
@@ -1,187 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any, Callable, Mapping, Protocol, TypedDict, TypeVar, cast, runtime_checkable
-
-from typing_extensions import Concatenate, ParamSpec, TypeAlias
-
-from litestar.utils.deprecation import warn_deprecation
-from litestar.utils.empty import value_or_default
-from litestar.utils.scope.state import ScopeState
-
-if TYPE_CHECKING:
- from pathlib import Path
-
- from litestar.connection import Request
-
-__all__ = (
- "TemplateCallableType",
- "TemplateEngineProtocol",
- "TemplateProtocol",
- "csrf_token",
- "url_for",
- "url_for_static_asset",
-)
-
-
-def _get_request_from_context(context: Mapping[str, Any]) -> Request:
- """Get the request from the template context.
-
- Args:
- context: The template context.
-
- Returns:
- The request object.
- """
- return cast("Request", context["request"])
-
-
-def url_for(context: Mapping[str, Any], /, route_name: str, **path_parameters: Any) -> str:
- """Wrap :func:`route_reverse <litestar.app.route_reverse>` to be used in templates.
-
- Args:
- context: The template context.
- route_name: The name of the route handler.
- **path_parameters: Actual values for path parameters in the route.
-
- Raises:
- NoRouteMatchFoundException: If ``route_name`` does not exist, path parameters are missing in **path_parameters
- or have wrong type.
-
- Returns:
- A fully formatted url path.
- """
- return _get_request_from_context(context).app.route_reverse(route_name, **path_parameters)
-
-
-def csrf_token(context: Mapping[str, Any], /) -> str:
- """Set a CSRF token on the template.
-
- Notes:
- - to use this function make sure to pass an instance of :ref:`CSRFConfig <litestar.config.csrf_config.CSRFConfig>` to
- the :class:`Litestar <litestar.app.Litestar>` constructor.
-
- Args:
- context: The template context.
-
- Returns:
- A CSRF token if the app level ``csrf_config`` is set, otherwise an empty string.
- """
- scope = _get_request_from_context(context).scope
- return value_or_default(ScopeState.from_scope(scope).csrf_token, "")
-
-
-def url_for_static_asset(context: Mapping[str, Any], /, name: str, file_path: str) -> str:
- """Wrap :meth:`url_for_static_asset <litestar.app.url_for_static_asset>` to be used in templates.
-
- Args:
- context: The template context object.
- name: A static handler unique name.
- file_path: a string containing path to an asset.
-
- Raises:
- NoRouteMatchFoundException: If static files handler with ``name`` does not exist.
-
- Returns:
- A url path to the asset.
- """
- return _get_request_from_context(context).app.url_for_static_asset(name, file_path)
-
-
-class TemplateProtocol(Protocol):
- """Protocol Defining a ``Template``.
-
- Template is a class that has a render method which renders the template into a string.
- """
-
- def render(self, *args: Any, **kwargs: Any) -> str:
- """Return the rendered template as a string.
-
- Args:
- *args: Positional arguments passed to the TemplateEngine
- **kwargs: A string keyed mapping of values passed to the TemplateEngine
-
- Returns:
- The rendered template string
- """
- raise NotImplementedError
-
-
-P = ParamSpec("P")
-R = TypeVar("R")
-ContextType = TypeVar("ContextType")
-ContextType_co = TypeVar("ContextType_co", covariant=True)
-TemplateType_co = TypeVar("TemplateType_co", bound=TemplateProtocol, covariant=True)
-TemplateCallableType: TypeAlias = Callable[Concatenate[ContextType, P], R]
-
-
-@runtime_checkable
-class TemplateEngineProtocol(Protocol[TemplateType_co, ContextType_co]):
- """Protocol for template engines."""
-
- def __init__(self, directory: Path | list[Path] | None, engine_instance: Any | None) -> None:
- """Initialize the template engine with a directory.
-
- Args:
- directory: Direct path or list of directory paths from which to serve templates, if provided the
- implementation has to create the engine instance.
- engine_instance: A template engine object, if provided the implementation has to use it.
- """
-
- def get_template(self, template_name: str) -> TemplateType_co:
- """Retrieve a template by matching its name (dotted path) with files in the directory or directories provided.
-
- Args:
- template_name: A dotted path
-
- Returns:
- Template instance
-
- Raises:
- TemplateNotFoundException: if no template is found.
- """
- raise NotImplementedError
-
- def render_string(self, template_string: str, context: Mapping[str, Any]) -> str:
- """Render a template from a string with the given context.
-
- Args:
- template_string: The template string to render.
- context: A dictionary of variables to pass to the template.
-
- Returns:
- The rendered template as a string.
- """
- raise NotImplementedError
-
- def register_template_callable(
- self, key: str, template_callable: TemplateCallableType[ContextType_co, P, R]
- ) -> None:
- """Register a callable on the template engine.
-
- Args:
- key: The callable key, i.e. the value to use inside the template to call the callable.
- template_callable: A callable to register.
-
- Returns:
- None
- """
-
-
-class _TemplateContext(TypedDict):
- """Dictionary representing a template context."""
-
- request: Request[Any, Any, Any]
- csrf_input: str
-
-
-def __getattr__(name: str) -> Any:
- if name == "TemplateContext":
- warn_deprecation(
- "2.3.0",
- "TemplateContext",
- "import",
- removal_in="3.0.0",
- alternative="Mapping",
- )
- return _TemplateContext
- raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
diff --git a/venv/lib/python3.11/site-packages/litestar/template/config.py b/venv/lib/python3.11/site-packages/litestar/template/config.py
deleted file mode 100644
index d2aa87c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/template/config.py
+++ /dev/null
@@ -1,57 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass, field
-from functools import cached_property
-from inspect import isclass
-from typing import TYPE_CHECKING, Callable, Generic, TypeVar, cast
-
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.template import TemplateEngineProtocol
-
-__all__ = ("TemplateConfig",)
-
-if TYPE_CHECKING:
- from litestar.types import PathType
-
-EngineType = TypeVar("EngineType", bound=TemplateEngineProtocol)
-
-
-@dataclass
-class TemplateConfig(Generic[EngineType]):
- """Configuration for Templating.
-
- To enable templating, pass an instance of this class to the :class:`Litestar <litestar.app.Litestar>` constructor using the
- 'template_config' key.
- """
-
- engine: type[EngineType] | EngineType | None = field(default=None)
- """A template engine adhering to the :class:`TemplateEngineProtocol <litestar.template.base.TemplateEngineProtocol>`."""
- directory: PathType | list[PathType] | None = field(default=None)
- """A directory or list of directories from which to serve templates."""
- engine_callback: Callable[[EngineType], None] | None = field(default=None)
- """A callback function that allows modifying the instantiated templating protocol."""
- instance: EngineType | None = field(default=None)
- """An instance of the templating protocol."""
-
- def __post_init__(self) -> None:
- """Ensure that directory is set if engine is a class."""
- if isclass(self.engine) and not self.directory:
- raise ImproperlyConfiguredException("directory is a required kwarg when passing a template engine class")
- """Ensure that directory is not set if instance is."""
- if self.instance is not None and self.directory is not None:
- raise ImproperlyConfiguredException("directory cannot be set if instance is")
-
- def to_engine(self) -> EngineType:
- """Instantiate the template engine."""
- template_engine = cast(
- "EngineType",
- self.engine(directory=self.directory, engine_instance=None) if isclass(self.engine) else self.engine,
- )
- if callable(self.engine_callback):
- self.engine_callback(template_engine)
- return template_engine
-
- @cached_property
- def engine_instance(self) -> EngineType:
- """Return the template engine instance."""
- return self.to_engine() if self.instance is None else self.instance
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/__init__.py b/venv/lib/python3.11/site-packages/litestar/testing/__init__.py
deleted file mode 100644
index 55af446..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from litestar.testing.client.async_client import AsyncTestClient
-from litestar.testing.client.base import BaseTestClient
-from litestar.testing.client.sync_client import TestClient
-from litestar.testing.helpers import create_async_test_client, create_test_client
-from litestar.testing.request_factory import RequestFactory
-from litestar.testing.websocket_test_session import WebSocketTestSession
-
-__all__ = (
- "AsyncTestClient",
- "BaseTestClient",
- "create_async_test_client",
- "create_test_client",
- "RequestFactory",
- "TestClient",
- "WebSocketTestSession",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/testing/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 77c7908..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/__pycache__/helpers.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/testing/__pycache__/helpers.cpython-311.pyc
deleted file mode 100644
index a85995f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/__pycache__/helpers.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/__pycache__/life_span_handler.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/testing/__pycache__/life_span_handler.cpython-311.pyc
deleted file mode 100644
index b3ea9ef..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/__pycache__/life_span_handler.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/__pycache__/request_factory.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/testing/__pycache__/request_factory.cpython-311.pyc
deleted file mode 100644
index 9a66826..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/__pycache__/request_factory.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/__pycache__/transport.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/testing/__pycache__/transport.cpython-311.pyc
deleted file mode 100644
index 78a1aa6..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/__pycache__/transport.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/__pycache__/websocket_test_session.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/testing/__pycache__/websocket_test_session.cpython-311.pyc
deleted file mode 100644
index 6b00590..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/__pycache__/websocket_test_session.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/client/__init__.py b/venv/lib/python3.11/site-packages/litestar/testing/client/__init__.py
deleted file mode 100644
index 5d03a7a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/client/__init__.py
+++ /dev/null
@@ -1,36 +0,0 @@
-"""Some code in this module was adapted from https://github.com/encode/starlette/blob/master/starlette/testclient.py.
-
-Copyright © 2018, [Encode OSS Ltd](https://www.encode.io/).
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""
-
-from .async_client import AsyncTestClient
-from .base import BaseTestClient
-from .sync_client import TestClient
-
-__all__ = ("TestClient", "AsyncTestClient", "BaseTestClient")
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/client/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/testing/client/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 18ad148..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/client/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/client/__pycache__/async_client.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/testing/client/__pycache__/async_client.cpython-311.pyc
deleted file mode 100644
index 1ccc805..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/client/__pycache__/async_client.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/client/__pycache__/base.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/testing/client/__pycache__/base.cpython-311.pyc
deleted file mode 100644
index 87d5de7..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/client/__pycache__/base.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/client/__pycache__/sync_client.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/testing/client/__pycache__/sync_client.cpython-311.pyc
deleted file mode 100644
index 29f0576..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/client/__pycache__/sync_client.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/client/async_client.py b/venv/lib/python3.11/site-packages/litestar/testing/client/async_client.py
deleted file mode 100644
index cf66f12..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/client/async_client.py
+++ /dev/null
@@ -1,534 +0,0 @@
-from __future__ import annotations
-
-from contextlib import AsyncExitStack
-from typing import TYPE_CHECKING, Any, Generic, Mapping, TypeVar
-
-from httpx import USE_CLIENT_DEFAULT, AsyncClient, Response
-
-from litestar import HttpMethod
-from litestar.testing.client.base import BaseTestClient
-from litestar.testing.life_span_handler import LifeSpanHandler
-from litestar.testing.transport import TestClientTransport
-from litestar.types import AnyIOBackend, ASGIApp
-
-if TYPE_CHECKING:
- from httpx._client import UseClientDefault
- from httpx._types import (
- AuthTypes,
- CookieTypes,
- HeaderTypes,
- QueryParamTypes,
- RequestContent,
- RequestData,
- RequestFiles,
- TimeoutTypes,
- URLTypes,
- )
- from typing_extensions import Self
-
- from litestar.middleware.session.base import BaseBackendConfig
-
-
-T = TypeVar("T", bound=ASGIApp)
-
-
-class AsyncTestClient(AsyncClient, BaseTestClient, Generic[T]): # type: ignore[misc]
- lifespan_handler: LifeSpanHandler[Any]
- exit_stack: AsyncExitStack
-
- def __init__(
- self,
- app: T,
- base_url: str = "http://testserver.local",
- raise_server_exceptions: bool = True,
- root_path: str = "",
- backend: AnyIOBackend = "asyncio",
- backend_options: Mapping[str, Any] | None = None,
- session_config: BaseBackendConfig | None = None,
- timeout: float | None = None,
- cookies: CookieTypes | None = None,
- ) -> None:
- """An Async client implementation providing a context manager for testing applications asynchronously.
-
- Args:
- app: The instance of :class:`Litestar <litestar.app.Litestar>` under test.
- base_url: URL scheme and domain for test request paths, e.g. ``http://testserver``.
- raise_server_exceptions: Flag for the underlying test client to raise server exceptions instead of
- wrapping them in an HTTP response.
- root_path: Path prefix for requests.
- backend: The async backend to use, options are "asyncio" or "trio".
- backend_options: 'anyio' options.
- session_config: Configuration for Session Middleware class to create raw session cookies for request to the
- route handlers.
- timeout: Request timeout
- cookies: Cookies to set on the client.
- """
- BaseTestClient.__init__(
- self,
- app=app,
- base_url=base_url,
- backend=backend,
- backend_options=backend_options,
- session_config=session_config,
- cookies=cookies,
- )
- AsyncClient.__init__(
- self,
- base_url=base_url,
- headers={"user-agent": "testclient"},
- follow_redirects=True,
- cookies=cookies,
- transport=TestClientTransport( # type: ignore [arg-type]
- client=self,
- raise_server_exceptions=raise_server_exceptions,
- root_path=root_path,
- ),
- timeout=timeout,
- )
-
- async def __aenter__(self) -> Self:
- async with AsyncExitStack() as stack:
- self.blocking_portal = portal = stack.enter_context(self.portal())
- self.lifespan_handler = LifeSpanHandler(client=self)
-
- @stack.callback
- def reset_portal() -> None:
- delattr(self, "blocking_portal")
-
- @stack.callback
- def wait_shutdown() -> None:
- portal.call(self.lifespan_handler.wait_shutdown)
-
- self.exit_stack = stack.pop_all()
- return self
-
- async def __aexit__(self, *args: Any) -> None:
- await self.exit_stack.aclose()
-
- async def request(
- self,
- method: str,
- url: URLTypes,
- *,
- content: RequestContent | None = None,
- data: RequestData | None = None,
- files: RequestFiles | None = None,
- json: Any | None = None,
- params: QueryParamTypes | None = None,
- headers: HeaderTypes | None = None,
- cookies: CookieTypes | None = None,
- auth: AuthTypes | UseClientDefault | None = USE_CLIENT_DEFAULT,
- follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
- timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- extensions: Mapping[str, Any] | None = None,
- ) -> Response:
- """Sends a request.
-
- Args:
- method: An HTTP method.
- url: URL or path for the request.
- content: Request content.
- data: Form encoded data.
- files: Multipart files to send.
- json: JSON data to send.
- params: Query parameters.
- headers: Request headers.
- cookies: Request cookies.
- auth: Auth headers.
- follow_redirects: Whether to follow redirects.
- timeout: Request timeout.
- extensions: Dictionary of ASGI extensions.
-
- Returns:
- An HTTPX Response.
- """
- return await AsyncClient.request(
- self,
- url=self.base_url.join(url),
- method=method.value if isinstance(method, HttpMethod) else method,
- content=content,
- data=data,
- files=files,
- json=json,
- params=params,
- headers=headers,
- cookies=cookies,
- auth=auth,
- follow_redirects=follow_redirects,
- timeout=timeout,
- extensions=None if extensions is None else dict(extensions),
- )
-
- async def get( # type: ignore [override]
- self,
- url: URLTypes,
- *,
- params: QueryParamTypes | None = None,
- headers: HeaderTypes | None = None,
- cookies: CookieTypes | None = None,
- auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
- timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- extensions: Mapping[str, Any] | None = None,
- ) -> Response:
- """Sends a GET request.
-
- Args:
- url: URL or path for the request.
- params: Query parameters.
- headers: Request headers.
- cookies: Request cookies.
- auth: Auth headers.
- follow_redirects: Whether to follow redirects.
- timeout: Request timeout.
- extensions: Dictionary of ASGI extensions.
-
- Returns:
- An HTTPX Response.
- """
- return await AsyncClient.get(
- self,
- url,
- params=params,
- headers=headers,
- cookies=cookies,
- auth=auth,
- follow_redirects=follow_redirects,
- timeout=timeout,
- extensions=None if extensions is None else dict(extensions),
- )
-
- async def options(
- self,
- url: URLTypes,
- *,
- params: QueryParamTypes | None = None,
- headers: HeaderTypes | None = None,
- cookies: CookieTypes | None = None,
- auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
- timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- extensions: Mapping[str, Any] | None = None,
- ) -> Response:
- """Sends an OPTIONS request.
-
- Args:
- url: URL or path for the request.
- params: Query parameters.
- headers: Request headers.
- cookies: Request cookies.
- auth: Auth headers.
- follow_redirects: Whether to follow redirects.
- timeout: Request timeout.
- extensions: Dictionary of ASGI extensions.
-
- Returns:
- An HTTPX Response.
- """
- return await AsyncClient.options(
- self,
- url,
- params=params,
- headers=headers,
- cookies=cookies,
- auth=auth,
- follow_redirects=follow_redirects,
- timeout=timeout,
- extensions=None if extensions is None else dict(extensions),
- )
-
- async def head(
- self,
- url: URLTypes,
- *,
- params: QueryParamTypes | None = None,
- headers: HeaderTypes | None = None,
- cookies: CookieTypes | None = None,
- auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
- timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- extensions: Mapping[str, Any] | None = None,
- ) -> Response:
- """Sends a HEAD request.
-
- Args:
- url: URL or path for the request.
- params: Query parameters.
- headers: Request headers.
- cookies: Request cookies.
- auth: Auth headers.
- follow_redirects: Whether to follow redirects.
- timeout: Request timeout.
- extensions: Dictionary of ASGI extensions.
-
- Returns:
- An HTTPX Response.
- """
- return await AsyncClient.head(
- self,
- url,
- params=params,
- headers=headers,
- cookies=cookies,
- auth=auth,
- follow_redirects=follow_redirects,
- timeout=timeout,
- extensions=None if extensions is None else dict(extensions),
- )
-
- async def post(
- self,
- url: URLTypes,
- *,
- content: RequestContent | None = None,
- data: RequestData | None = None,
- files: RequestFiles | None = None,
- json: Any | None = None,
- params: QueryParamTypes | None = None,
- headers: HeaderTypes | None = None,
- cookies: CookieTypes | None = None,
- auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
- timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- extensions: Mapping[str, Any] | None = None,
- ) -> Response:
- """Sends a POST request.
-
- Args:
- url: URL or path for the request.
- content: Request content.
- data: Form encoded data.
- files: Multipart files to send.
- json: JSON data to send.
- params: Query parameters.
- headers: Request headers.
- cookies: Request cookies.
- auth: Auth headers.
- follow_redirects: Whether to follow redirects.
- timeout: Request timeout.
- extensions: Dictionary of ASGI extensions.
-
- Returns:
- An HTTPX Response.
- """
- return await AsyncClient.post(
- self,
- url,
- content=content,
- data=data,
- files=files,
- json=json,
- params=params,
- headers=headers,
- cookies=cookies,
- auth=auth,
- follow_redirects=follow_redirects,
- timeout=timeout,
- extensions=None if extensions is None else dict(extensions),
- )
-
- async def put(
- self,
- url: URLTypes,
- *,
- content: RequestContent | None = None,
- data: RequestData | None = None,
- files: RequestFiles | None = None,
- json: Any | None = None,
- params: QueryParamTypes | None = None,
- headers: HeaderTypes | None = None,
- cookies: CookieTypes | None = None,
- auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
- timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- extensions: Mapping[str, Any] | None = None,
- ) -> Response:
- """Sends a PUT request.
-
- Args:
- url: URL or path for the request.
- content: Request content.
- data: Form encoded data.
- files: Multipart files to send.
- json: JSON data to send.
- params: Query parameters.
- headers: Request headers.
- cookies: Request cookies.
- auth: Auth headers.
- follow_redirects: Whether to follow redirects.
- timeout: Request timeout.
- extensions: Dictionary of ASGI extensions.
-
- Returns:
- An HTTPX Response.
- """
- return await AsyncClient.put(
- self,
- url,
- content=content,
- data=data,
- files=files,
- json=json,
- params=params,
- headers=headers,
- cookies=cookies,
- auth=auth,
- follow_redirects=follow_redirects,
- timeout=timeout,
- extensions=None if extensions is None else dict(extensions),
- )
-
- async def patch(
- self,
- url: URLTypes,
- *,
- content: RequestContent | None = None,
- data: RequestData | None = None,
- files: RequestFiles | None = None,
- json: Any | None = None,
- params: QueryParamTypes | None = None,
- headers: HeaderTypes | None = None,
- cookies: CookieTypes | None = None,
- auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
- timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- extensions: Mapping[str, Any] | None = None,
- ) -> Response:
- """Sends a PATCH request.
-
- Args:
- url: URL or path for the request.
- content: Request content.
- data: Form encoded data.
- files: Multipart files to send.
- json: JSON data to send.
- params: Query parameters.
- headers: Request headers.
- cookies: Request cookies.
- auth: Auth headers.
- follow_redirects: Whether to follow redirects.
- timeout: Request timeout.
- extensions: Dictionary of ASGI extensions.
-
- Returns:
- An HTTPX Response.
- """
- return await AsyncClient.patch(
- self,
- url,
- content=content,
- data=data,
- files=files,
- json=json,
- params=params,
- headers=headers,
- cookies=cookies,
- auth=auth,
- follow_redirects=follow_redirects,
- timeout=timeout,
- extensions=None if extensions is None else dict(extensions),
- )
-
- async def delete(
- self,
- url: URLTypes,
- *,
- params: QueryParamTypes | None = None,
- headers: HeaderTypes | None = None,
- cookies: CookieTypes | None = None,
- auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
- timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- extensions: Mapping[str, Any] | None = None,
- ) -> Response:
- """Sends a DELETE request.
-
- Args:
- url: URL or path for the request.
- params: Query parameters.
- headers: Request headers.
- cookies: Request cookies.
- auth: Auth headers.
- follow_redirects: Whether to follow redirects.
- timeout: Request timeout.
- extensions: Dictionary of ASGI extensions.
-
- Returns:
- An HTTPX Response.
- """
- return await AsyncClient.delete(
- self,
- url,
- params=params,
- headers=headers,
- cookies=cookies,
- auth=auth,
- follow_redirects=follow_redirects,
- timeout=timeout,
- extensions=None if extensions is None else dict(extensions),
- )
-
- async def get_session_data(self) -> dict[str, Any]:
- """Get session data.
-
- Returns:
- A dictionary containing session data.
-
- Examples:
- .. code-block:: python
-
- from litestar import Litestar, post
- from litestar.middleware.session.memory_backend import MemoryBackendConfig
-
- session_config = MemoryBackendConfig()
-
-
- @post(path="/test")
- def set_session_data(request: Request) -> None:
- request.session["foo"] == "bar"
-
-
- app = Litestar(
- route_handlers=[set_session_data], middleware=[session_config.middleware]
- )
-
- async with AsyncTestClient(app=app, session_config=session_config) as client:
- await client.post("/test")
- assert await client.get_session_data() == {"foo": "bar"}
-
- """
- return await super()._get_session_data()
-
- async def set_session_data(self, data: dict[str, Any]) -> None:
- """Set session data.
-
- Args:
- data: Session data
-
- Returns:
- None
-
- Examples:
- .. code-block:: python
-
- from litestar import Litestar, get
- from litestar.middleware.session.memory_backend import MemoryBackendConfig
-
- session_config = MemoryBackendConfig()
-
-
- @get(path="/test")
- def get_session_data(request: Request) -> Dict[str, Any]:
- return request.session
-
-
- app = Litestar(
- route_handlers=[get_session_data], middleware=[session_config.middleware]
- )
-
- async with AsyncTestClient(app=app, session_config=session_config) as client:
- await client.set_session_data({"foo": "bar"})
- assert await client.get("/test").json() == {"foo": "bar"}
-
- """
- return await super()._set_session_data(data)
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/client/base.py b/venv/lib/python3.11/site-packages/litestar/testing/client/base.py
deleted file mode 100644
index 3c25be1..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/client/base.py
+++ /dev/null
@@ -1,180 +0,0 @@
-from __future__ import annotations
-
-from contextlib import contextmanager
-from http.cookiejar import CookieJar
-from typing import TYPE_CHECKING, Any, Generator, Generic, Mapping, TypeVar, cast
-from warnings import warn
-
-from anyio.from_thread import BlockingPortal, start_blocking_portal
-from httpx import Cookies, Request, Response
-
-from litestar import Litestar
-from litestar.connection import ASGIConnection
-from litestar.datastructures import MutableScopeHeaders
-from litestar.enums import ScopeType
-from litestar.exceptions import (
- ImproperlyConfiguredException,
-)
-from litestar.types import AnyIOBackend, ASGIApp, HTTPResponseStartEvent
-from litestar.utils.scope.state import ScopeState
-
-if TYPE_CHECKING:
- from httpx._types import CookieTypes
-
- from litestar.middleware.session.base import BaseBackendConfig, BaseSessionBackend
- from litestar.types.asgi_types import HTTPScope, Receive, Scope, Send
-
-T = TypeVar("T", bound=ASGIApp)
-
-
-def fake_http_send_message(headers: MutableScopeHeaders) -> HTTPResponseStartEvent:
- headers.setdefault("content-type", "application/text")
- return HTTPResponseStartEvent(type="http.response.start", status=200, headers=headers.headers)
-
-
-def fake_asgi_connection(app: ASGIApp, cookies: dict[str, str]) -> ASGIConnection[Any, Any, Any, Any]:
- scope: HTTPScope = {
- "type": ScopeType.HTTP,
- "path": "/",
- "raw_path": b"/",
- "root_path": "",
- "scheme": "http",
- "query_string": b"",
- "client": ("testclient", 50000),
- "server": ("testserver", 80),
- "headers": [],
- "method": "GET",
- "http_version": "1.1",
- "extensions": {"http.response.template": {}},
- "app": app, # type: ignore[typeddict-item]
- "state": {},
- "path_params": {},
- "route_handler": None, # type: ignore[typeddict-item]
- "asgi": {"version": "3.0", "spec_version": "2.1"},
- "auth": None,
- "session": None,
- "user": None,
- }
- ScopeState.from_scope(scope).cookies = cookies
- return ASGIConnection[Any, Any, Any, Any](scope=scope)
-
-
-def _wrap_app_to_add_state(app: ASGIApp) -> ASGIApp:
- """Wrap an ASGI app to add state to the scope.
-
- Litestar depends on `state` being present in the ASGI connection scope. Scope state is optional in the ASGI spec,
- however, the Litestar app always ensures it is present so that it can be depended on internally.
-
- When the ASGI app that is passed to the test client is _not_ a Litestar app, we need to add
- state to the scope, because httpx does not do this for us.
-
- This assists us in testing Litestar components that rely on state being present in the scope, without having
- to create a Litestar app for every test case.
-
- Args:
- app: The ASGI app to wrap.
-
- Returns:
- The wrapped ASGI app.
- """
-
- async def wrapped(scope: Scope, receive: Receive, send: Send) -> None:
- scope["state"] = {}
- await app(scope, receive, send)
-
- return wrapped
-
-
-class BaseTestClient(Generic[T]):
- __test__ = False
- blocking_portal: BlockingPortal
-
- __slots__ = (
- "app",
- "base_url",
- "backend",
- "backend_options",
- "session_config",
- "_session_backend",
- "cookies",
- )
-
- def __init__(
- self,
- app: T,
- base_url: str = "http://testserver.local",
- backend: AnyIOBackend = "asyncio",
- backend_options: Mapping[str, Any] | None = None,
- session_config: BaseBackendConfig | None = None,
- cookies: CookieTypes | None = None,
- ) -> None:
- if "." not in base_url:
- warn(
- f"The base_url {base_url!r} might cause issues. Try adding a domain name such as .local: "
- f"'{base_url}.local'",
- UserWarning,
- stacklevel=1,
- )
-
- self._session_backend: BaseSessionBackend | None = None
- if session_config:
- self._session_backend = session_config._backend_class(config=session_config)
-
- if not isinstance(app, Litestar):
- app = _wrap_app_to_add_state(app) # type: ignore[assignment]
-
- self.app = cast("T", app) # type: ignore[redundant-cast] # pyright needs this
-
- self.base_url = base_url
- self.backend = backend
- self.backend_options = backend_options
- self.cookies = cookies
-
- @property
- def session_backend(self) -> BaseSessionBackend[Any]:
- if not self._session_backend:
- raise ImproperlyConfiguredException(
- "Session has not been initialized for this TestClient instance. You can"
- "do so by passing a configuration object to TestClient: TestClient(app=app, session_config=...)"
- )
- return self._session_backend
-
- @contextmanager
- def portal(self) -> Generator[BlockingPortal, None, None]:
- """Get a BlockingPortal.
-
- Returns:
- A contextmanager for a BlockingPortal.
- """
- if hasattr(self, "blocking_portal"):
- yield self.blocking_portal
- else:
- with start_blocking_portal(
- backend=self.backend, backend_options=dict(self.backend_options or {})
- ) as portal:
- yield portal
-
- async def _set_session_data(self, data: dict[str, Any]) -> None:
- mutable_headers = MutableScopeHeaders()
- connection = fake_asgi_connection(
- app=self.app,
- cookies=dict(self.cookies), # type: ignore[arg-type]
- )
- session_id = self.session_backend.get_session_id(connection)
- connection._connection_state.session_id = session_id # pyright: ignore [reportGeneralTypeIssues]
- await self.session_backend.store_in_message(
- scope_session=data, message=fake_http_send_message(mutable_headers), connection=connection
- )
- response = Response(200, request=Request("GET", self.base_url), headers=mutable_headers.headers)
-
- cookies = Cookies(CookieJar())
- cookies.extract_cookies(response)
- self.cookies.update(cookies) # type: ignore[union-attr]
-
- async def _get_session_data(self) -> dict[str, Any]:
- return await self.session_backend.load_from_connection(
- connection=fake_asgi_connection(
- app=self.app,
- cookies=dict(self.cookies), # type: ignore[arg-type]
- ),
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/client/sync_client.py b/venv/lib/python3.11/site-packages/litestar/testing/client/sync_client.py
deleted file mode 100644
index d907056..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/client/sync_client.py
+++ /dev/null
@@ -1,593 +0,0 @@
-from __future__ import annotations
-
-from contextlib import ExitStack
-from typing import TYPE_CHECKING, Any, Generic, Mapping, Sequence, TypeVar
-from urllib.parse import urljoin
-
-from httpx import USE_CLIENT_DEFAULT, Client, Response
-
-from litestar import HttpMethod
-from litestar.testing.client.base import BaseTestClient
-from litestar.testing.life_span_handler import LifeSpanHandler
-from litestar.testing.transport import ConnectionUpgradeExceptionError, TestClientTransport
-from litestar.types import AnyIOBackend, ASGIApp
-
-if TYPE_CHECKING:
- from httpx._client import UseClientDefault
- from httpx._types import (
- AuthTypes,
- CookieTypes,
- HeaderTypes,
- QueryParamTypes,
- RequestContent,
- RequestData,
- RequestFiles,
- TimeoutTypes,
- URLTypes,
- )
- from typing_extensions import Self
-
- from litestar.middleware.session.base import BaseBackendConfig
- from litestar.testing.websocket_test_session import WebSocketTestSession
-
-
-T = TypeVar("T", bound=ASGIApp)
-
-
-class TestClient(Client, BaseTestClient, Generic[T]): # type: ignore[misc]
- lifespan_handler: LifeSpanHandler[Any]
- exit_stack: ExitStack
-
- def __init__(
- self,
- app: T,
- base_url: str = "http://testserver.local",
- raise_server_exceptions: bool = True,
- root_path: str = "",
- backend: AnyIOBackend = "asyncio",
- backend_options: Mapping[str, Any] | None = None,
- session_config: BaseBackendConfig | None = None,
- timeout: float | None = None,
- cookies: CookieTypes | None = None,
- ) -> None:
- """A client implementation providing a context manager for testing applications.
-
- Args:
- app: The instance of :class:`Litestar <litestar.app.Litestar>` under test.
- base_url: URL scheme and domain for test request paths, e.g. ``http://testserver``.
- raise_server_exceptions: Flag for the underlying test client to raise server exceptions instead of
- wrapping them in an HTTP response.
- root_path: Path prefix for requests.
- backend: The async backend to use, options are "asyncio" or "trio".
- backend_options: ``anyio`` options.
- session_config: Configuration for Session Middleware class to create raw session cookies for request to the
- route handlers.
- timeout: Request timeout
- cookies: Cookies to set on the client.
- """
- BaseTestClient.__init__(
- self,
- app=app,
- base_url=base_url,
- backend=backend,
- backend_options=backend_options,
- session_config=session_config,
- cookies=cookies,
- )
-
- Client.__init__(
- self,
- base_url=base_url,
- headers={"user-agent": "testclient"},
- follow_redirects=True,
- cookies=cookies,
- transport=TestClientTransport( # type: ignore[arg-type]
- client=self,
- raise_server_exceptions=raise_server_exceptions,
- root_path=root_path,
- ),
- timeout=timeout,
- )
-
- def __enter__(self) -> Self:
- with ExitStack() as stack:
- self.blocking_portal = portal = stack.enter_context(self.portal())
- self.lifespan_handler = LifeSpanHandler(client=self)
-
- @stack.callback
- def reset_portal() -> None:
- delattr(self, "blocking_portal")
-
- @stack.callback
- def wait_shutdown() -> None:
- portal.call(self.lifespan_handler.wait_shutdown)
-
- self.exit_stack = stack.pop_all()
-
- return self
-
- def __exit__(self, *args: Any) -> None:
- self.exit_stack.close()
-
- def request(
- self,
- method: str,
- url: URLTypes,
- *,
- content: RequestContent | None = None,
- data: RequestData | None = None,
- files: RequestFiles | None = None,
- json: Any | None = None,
- params: QueryParamTypes | None = None,
- headers: HeaderTypes | None = None,
- cookies: CookieTypes | None = None,
- auth: AuthTypes | UseClientDefault | None = USE_CLIENT_DEFAULT,
- follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
- timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- extensions: Mapping[str, Any] | None = None,
- ) -> Response:
- """Sends a request.
-
- Args:
- method: An HTTP method.
- url: URL or path for the request.
- content: Request content.
- data: Form encoded data.
- files: Multipart files to send.
- json: JSON data to send.
- params: Query parameters.
- headers: Request headers.
- cookies: Request cookies.
- auth: Auth headers.
- follow_redirects: Whether to follow redirects.
- timeout: Request timeout.
- extensions: Dictionary of ASGI extensions.
-
- Returns:
- An HTTPX Response.
- """
- return Client.request(
- self,
- url=self.base_url.join(url),
- method=method.value if isinstance(method, HttpMethod) else method,
- content=content,
- data=data,
- files=files,
- json=json,
- params=params,
- headers=headers,
- cookies=cookies,
- auth=auth,
- follow_redirects=follow_redirects,
- timeout=timeout,
- extensions=None if extensions is None else dict(extensions),
- )
-
- def get(
- self,
- url: URLTypes,
- *,
- params: QueryParamTypes | None = None,
- headers: HeaderTypes | None = None,
- cookies: CookieTypes | None = None,
- auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
- timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- extensions: Mapping[str, Any] | None = None,
- ) -> Response:
- """Sends a GET request.
-
- Args:
- url: URL or path for the request.
- params: Query parameters.
- headers: Request headers.
- cookies: Request cookies.
- auth: Auth headers.
- follow_redirects: Whether to follow redirects.
- timeout: Request timeout.
- extensions: Dictionary of ASGI extensions.
-
- Returns:
- An HTTPX Response.
- """
- return Client.get(
- self,
- url,
- params=params,
- headers=headers,
- cookies=cookies,
- auth=auth,
- follow_redirects=follow_redirects,
- timeout=timeout,
- extensions=None if extensions is None else dict(extensions),
- )
-
- def options(
- self,
- url: URLTypes,
- *,
- params: QueryParamTypes | None = None,
- headers: HeaderTypes | None = None,
- cookies: CookieTypes | None = None,
- auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
- timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- extensions: Mapping[str, Any] | None = None,
- ) -> Response:
- """Sends an OPTIONS request.
-
- Args:
- url: URL or path for the request.
- params: Query parameters.
- headers: Request headers.
- cookies: Request cookies.
- auth: Auth headers.
- follow_redirects: Whether to follow redirects.
- timeout: Request timeout.
- extensions: Dictionary of ASGI extensions.
-
- Returns:
- An HTTPX Response.
- """
- return Client.options(
- self,
- url,
- params=params,
- headers=headers,
- cookies=cookies,
- auth=auth,
- follow_redirects=follow_redirects,
- timeout=timeout,
- extensions=None if extensions is None else dict(extensions),
- )
-
- def head(
- self,
- url: URLTypes,
- *,
- params: QueryParamTypes | None = None,
- headers: HeaderTypes | None = None,
- cookies: CookieTypes | None = None,
- auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
- timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- extensions: Mapping[str, Any] | None = None,
- ) -> Response:
- """Sends a HEAD request.
-
- Args:
- url: URL or path for the request.
- params: Query parameters.
- headers: Request headers.
- cookies: Request cookies.
- auth: Auth headers.
- follow_redirects: Whether to follow redirects.
- timeout: Request timeout.
- extensions: Dictionary of ASGI extensions.
-
- Returns:
- An HTTPX Response.
- """
- return Client.head(
- self,
- url,
- params=params,
- headers=headers,
- cookies=cookies,
- auth=auth,
- follow_redirects=follow_redirects,
- timeout=timeout,
- extensions=None if extensions is None else dict(extensions),
- )
-
- def post(
- self,
- url: URLTypes,
- *,
- content: RequestContent | None = None,
- data: RequestData | None = None,
- files: RequestFiles | None = None,
- json: Any | None = None,
- params: QueryParamTypes | None = None,
- headers: HeaderTypes | None = None,
- cookies: CookieTypes | None = None,
- auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
- timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- extensions: Mapping[str, Any] | None = None,
- ) -> Response:
- """Sends a POST request.
-
- Args:
- url: URL or path for the request.
- content: Request content.
- data: Form encoded data.
- files: Multipart files to send.
- json: JSON data to send.
- params: Query parameters.
- headers: Request headers.
- cookies: Request cookies.
- auth: Auth headers.
- follow_redirects: Whether to follow redirects.
- timeout: Request timeout.
- extensions: Dictionary of ASGI extensions.
-
- Returns:
- An HTTPX Response.
- """
- return Client.post(
- self,
- url,
- content=content,
- data=data,
- files=files,
- json=json,
- params=params,
- headers=headers,
- cookies=cookies,
- auth=auth,
- follow_redirects=follow_redirects,
- timeout=timeout,
- extensions=None if extensions is None else dict(extensions),
- )
-
- def put(
- self,
- url: URLTypes,
- *,
- content: RequestContent | None = None,
- data: RequestData | None = None,
- files: RequestFiles | None = None,
- json: Any | None = None,
- params: QueryParamTypes | None = None,
- headers: HeaderTypes | None = None,
- cookies: CookieTypes | None = None,
- auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
- timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- extensions: Mapping[str, Any] | None = None,
- ) -> Response:
- """Sends a PUT request.
-
- Args:
- url: URL or path for the request.
- content: Request content.
- data: Form encoded data.
- files: Multipart files to send.
- json: JSON data to send.
- params: Query parameters.
- headers: Request headers.
- cookies: Request cookies.
- auth: Auth headers.
- follow_redirects: Whether to follow redirects.
- timeout: Request timeout.
- extensions: Dictionary of ASGI extensions.
-
- Returns:
- An HTTPX Response.
- """
- return Client.put(
- self,
- url,
- content=content,
- data=data,
- files=files,
- json=json,
- params=params,
- headers=headers,
- cookies=cookies,
- auth=auth,
- follow_redirects=follow_redirects,
- timeout=timeout,
- extensions=None if extensions is None else dict(extensions),
- )
-
- def patch(
- self,
- url: URLTypes,
- *,
- content: RequestContent | None = None,
- data: RequestData | None = None,
- files: RequestFiles | None = None,
- json: Any | None = None,
- params: QueryParamTypes | None = None,
- headers: HeaderTypes | None = None,
- cookies: CookieTypes | None = None,
- auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
- timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- extensions: Mapping[str, Any] | None = None,
- ) -> Response:
- """Sends a PATCH request.
-
- Args:
- url: URL or path for the request.
- content: Request content.
- data: Form encoded data.
- files: Multipart files to send.
- json: JSON data to send.
- params: Query parameters.
- headers: Request headers.
- cookies: Request cookies.
- auth: Auth headers.
- follow_redirects: Whether to follow redirects.
- timeout: Request timeout.
- extensions: Dictionary of ASGI extensions.
-
- Returns:
- An HTTPX Response.
- """
- return Client.patch(
- self,
- url,
- content=content,
- data=data,
- files=files,
- json=json,
- params=params,
- headers=headers,
- cookies=cookies,
- auth=auth,
- follow_redirects=follow_redirects,
- timeout=timeout,
- extensions=None if extensions is None else dict(extensions),
- )
-
- def delete(
- self,
- url: URLTypes,
- *,
- params: QueryParamTypes | None = None,
- headers: HeaderTypes | None = None,
- cookies: CookieTypes | None = None,
- auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
- timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- extensions: Mapping[str, Any] | None = None,
- ) -> Response:
- """Sends a DELETE request.
-
- Args:
- url: URL or path for the request.
- params: Query parameters.
- headers: Request headers.
- cookies: Request cookies.
- auth: Auth headers.
- follow_redirects: Whether to follow redirects.
- timeout: Request timeout.
- extensions: Dictionary of ASGI extensions.
-
- Returns:
- An HTTPX Response.
- """
- return Client.delete(
- self,
- url,
- params=params,
- headers=headers,
- cookies=cookies,
- auth=auth,
- follow_redirects=follow_redirects,
- timeout=timeout,
- extensions=None if extensions is None else dict(extensions),
- )
-
- def websocket_connect(
- self,
- url: str,
- subprotocols: Sequence[str] | None = None,
- params: QueryParamTypes | None = None,
- headers: HeaderTypes | None = None,
- cookies: CookieTypes | None = None,
- auth: AuthTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- follow_redirects: bool | UseClientDefault = USE_CLIENT_DEFAULT,
- timeout: TimeoutTypes | UseClientDefault = USE_CLIENT_DEFAULT,
- extensions: Mapping[str, Any] | None = None,
- ) -> WebSocketTestSession:
- """Sends a GET request to establish a websocket connection.
-
- Args:
- url: Request URL.
- subprotocols: Websocket subprotocols.
- params: Query parameters.
- headers: Request headers.
- cookies: Request cookies.
- auth: Auth headers.
- follow_redirects: Whether to follow redirects.
- timeout: Request timeout.
- extensions: Dictionary of ASGI extensions.
-
- Returns:
- A `WebSocketTestSession <litestar.testing.WebSocketTestSession>` instance.
- """
- url = urljoin("ws://testserver", url)
- default_headers: dict[str, str] = {}
- default_headers.setdefault("connection", "upgrade")
- default_headers.setdefault("sec-websocket-key", "testserver==")
- default_headers.setdefault("sec-websocket-version", "13")
- if subprotocols is not None:
- default_headers.setdefault("sec-websocket-protocol", ", ".join(subprotocols))
- try:
- Client.request(
- self,
- "GET",
- url,
- headers={**dict(headers or {}), **default_headers}, # type: ignore[misc]
- params=params,
- cookies=cookies,
- auth=auth,
- follow_redirects=follow_redirects,
- timeout=timeout,
- extensions=None if extensions is None else dict(extensions),
- )
- except ConnectionUpgradeExceptionError as exc:
- return exc.session
-
- raise RuntimeError("Expected WebSocket upgrade") # pragma: no cover
-
- def set_session_data(self, data: dict[str, Any]) -> None:
- """Set session data.
-
- Args:
- data: Session data
-
- Returns:
- None
-
- Examples:
- .. code-block:: python
-
- from litestar import Litestar, get
- from litestar.middleware.session.memory_backend import MemoryBackendConfig
-
- session_config = MemoryBackendConfig()
-
-
- @get(path="/test")
- def get_session_data(request: Request) -> Dict[str, Any]:
- return request.session
-
-
- app = Litestar(
- route_handlers=[get_session_data], middleware=[session_config.middleware]
- )
-
- with TestClient(app=app, session_config=session_config) as client:
- client.set_session_data({"foo": "bar"})
- assert client.get("/test").json() == {"foo": "bar"}
-
- """
- with self.portal() as portal:
- portal.call(self._set_session_data, data)
-
- def get_session_data(self) -> dict[str, Any]:
- """Get session data.
-
- Returns:
- A dictionary containing session data.
-
- Examples:
- .. code-block:: python
-
- from litestar import Litestar, post
- from litestar.middleware.session.memory_backend import MemoryBackendConfig
-
- session_config = MemoryBackendConfig()
-
-
- @post(path="/test")
- def set_session_data(request: Request) -> None:
- request.session["foo"] == "bar"
-
-
- app = Litestar(
- route_handlers=[set_session_data], middleware=[session_config.middleware]
- )
-
- with TestClient(app=app, session_config=session_config) as client:
- client.post("/test")
- assert client.get_session_data() == {"foo": "bar"}
-
- """
- with self.portal() as portal:
- return portal.call(self._get_session_data)
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/helpers.py b/venv/lib/python3.11/site-packages/litestar/testing/helpers.py
deleted file mode 100644
index 5ac59af..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/helpers.py
+++ /dev/null
@@ -1,561 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any, Callable, Literal, Mapping, Sequence
-
-from litestar.app import DEFAULT_OPENAPI_CONFIG, Litestar
-from litestar.controller import Controller
-from litestar.events import SimpleEventEmitter
-from litestar.testing.client import AsyncTestClient, TestClient
-from litestar.types import Empty
-from litestar.utils.predicates import is_class_and_subclass
-
-if TYPE_CHECKING:
- from contextlib import AbstractAsyncContextManager
-
- from litestar import Request, Response, WebSocket
- from litestar.config.allowed_hosts import AllowedHostsConfig
- from litestar.config.app import ExperimentalFeatures
- from litestar.config.compression import CompressionConfig
- from litestar.config.cors import CORSConfig
- from litestar.config.csrf import CSRFConfig
- from litestar.config.response_cache import ResponseCacheConfig
- from litestar.datastructures import CacheControlHeader, ETag, State
- from litestar.dto import AbstractDTO
- from litestar.events import BaseEventEmitterBackend, EventListener
- from litestar.logging.config import BaseLoggingConfig
- from litestar.middleware.session.base import BaseBackendConfig
- from litestar.openapi.config import OpenAPIConfig
- from litestar.openapi.spec import SecurityRequirement
- from litestar.plugins import PluginProtocol
- from litestar.static_files.config import StaticFilesConfig
- from litestar.stores.base import Store
- from litestar.stores.registry import StoreRegistry
- from litestar.template.config import TemplateConfig
- from litestar.types import (
- AfterExceptionHookHandler,
- AfterRequestHookHandler,
- AfterResponseHookHandler,
- BeforeMessageSendHookHandler,
- BeforeRequestHookHandler,
- ControllerRouterHandler,
- Dependencies,
- EmptyType,
- ExceptionHandlersMap,
- Guard,
- LifespanHook,
- Middleware,
- OnAppInitHandler,
- ParametersMap,
- ResponseCookies,
- ResponseHeaders,
- TypeEncodersMap,
- )
-
-
-def create_test_client(
- route_handlers: ControllerRouterHandler | Sequence[ControllerRouterHandler] | None = None,
- *,
- after_exception: Sequence[AfterExceptionHookHandler] | None = None,
- after_request: AfterRequestHookHandler | None = None,
- after_response: AfterResponseHookHandler | None = None,
- allowed_hosts: Sequence[str] | AllowedHostsConfig | None = None,
- backend: Literal["asyncio", "trio"] = "asyncio",
- backend_options: Mapping[str, Any] | None = None,
- base_url: str = "http://testserver.local",
- before_request: BeforeRequestHookHandler | None = None,
- before_send: Sequence[BeforeMessageSendHookHandler] | None = None,
- cache_control: CacheControlHeader | None = None,
- compression_config: CompressionConfig | None = None,
- cors_config: CORSConfig | None = None,
- csrf_config: CSRFConfig | None = None,
- debug: bool = True,
- dependencies: Dependencies | None = None,
- dto: type[AbstractDTO] | None | EmptyType = Empty,
- etag: ETag | None = None,
- event_emitter_backend: type[BaseEventEmitterBackend] = SimpleEventEmitter,
- exception_handlers: ExceptionHandlersMap | None = None,
- guards: Sequence[Guard] | None = None,
- include_in_schema: bool | EmptyType = Empty,
- listeners: Sequence[EventListener] | None = None,
- logging_config: BaseLoggingConfig | EmptyType | None = Empty,
- middleware: Sequence[Middleware] | None = None,
- multipart_form_part_limit: int = 1000,
- on_app_init: Sequence[OnAppInitHandler] | None = None,
- on_shutdown: Sequence[LifespanHook] | None = None,
- on_startup: Sequence[LifespanHook] | None = None,
- openapi_config: OpenAPIConfig | None = DEFAULT_OPENAPI_CONFIG,
- opt: Mapping[str, Any] | None = None,
- parameters: ParametersMap | None = None,
- plugins: Sequence[PluginProtocol] | None = None,
- lifespan: list[Callable[[Litestar], AbstractAsyncContextManager] | AbstractAsyncContextManager] | None = None,
- raise_server_exceptions: bool = True,
- pdb_on_exception: bool | None = None,
- request_class: type[Request] | None = None,
- response_cache_config: ResponseCacheConfig | None = None,
- response_class: type[Response] | None = None,
- response_cookies: ResponseCookies | None = None,
- response_headers: ResponseHeaders | None = None,
- return_dto: type[AbstractDTO] | None | EmptyType = Empty,
- root_path: str = "",
- security: Sequence[SecurityRequirement] | None = None,
- session_config: BaseBackendConfig | None = None,
- signature_namespace: Mapping[str, Any] | None = None,
- signature_types: Sequence[Any] | None = None,
- state: State | None = None,
- static_files_config: Sequence[StaticFilesConfig] | None = None,
- stores: StoreRegistry | dict[str, Store] | None = None,
- tags: Sequence[str] | None = None,
- template_config: TemplateConfig | None = None,
- timeout: float | None = None,
- type_encoders: TypeEncodersMap | None = None,
- websocket_class: type[WebSocket] | None = None,
- experimental_features: list[ExperimentalFeatures] | None = None,
-) -> TestClient[Litestar]:
- """Create a Litestar app instance and initializes it.
-
- :class:`TestClient <litestar.testing.TestClient>` with it.
-
- Notes:
- - This function should be called as a context manager to ensure async startup and shutdown are
- handled correctly.
-
- Examples:
- .. code-block:: python
-
- from litestar import get
- from litestar.testing import create_test_client
-
-
- @get("/some-path")
- def my_handler() -> dict[str, str]:
- return {"hello": "world"}
-
-
- def test_my_handler() -> None:
- with create_test_client(my_handler) as client:
- response = client.get("/some-path")
- assert response.json() == {"hello": "world"}
-
- Args:
- route_handlers: A single handler or a sequence of route handlers, which can include instances of
- :class:`Router <litestar.router.Router>`, subclasses of :class:`Controller <.controller.Controller>` or
- any function decorated by the route handler decorators.
- backend: The async backend to use, options are "asyncio" or "trio".
- backend_options: ``anyio`` options.
- base_url: URL scheme and domain for test request paths, e.g. ``http://testserver``.
- raise_server_exceptions: Flag for underlying the test client to raise server exceptions instead of wrapping them
- in an HTTP response.
- root_path: Path prefix for requests.
- session_config: Configuration for Session Middleware class to create raw session cookies for request to the
- route handlers.
- after_exception: A sequence of :class:`exception hook handlers <.types.AfterExceptionHookHandler>`. This
- hook is called after an exception occurs. In difference to exception handlers, it is not meant to
- return a response - only to process the exception (e.g. log it, send it to Sentry etc.).
- after_request: A sync or async function executed after the route handler function returned and the response
- object has been resolved. Receives the response object.
- after_response: A sync or async function called after the response has been awaited. It receives the
- :class:`Request <.connection.Request>` object and should not return any values.
- allowed_hosts: A sequence of allowed hosts, or an
- :class:`AllowedHostsConfig <.config.allowed_hosts.AllowedHostsConfig>` instance. Enables the builtin
- allowed hosts middleware.
- before_request: A sync or async function called immediately before calling the route handler. Receives the
- :class:`Request <.connection.Request>` instance and any non-``None`` return value is used for the
- response, bypassing the route handler.
- before_send: A sequence of :class:`before send hook handlers <.types.BeforeMessageSendHookHandler>`. Called
- when the ASGI send function is called.
- cache_control: A ``cache-control`` header of type
- :class:`CacheControlHeader <litestar.datastructures.CacheControlHeader>` to add to route handlers of
- this app. Can be overridden by route handlers.
- compression_config: Configures compression behaviour of the application, this enabled a builtin or user
- defined Compression middleware.
- cors_config: If set, configures :class:`CORSMiddleware <.middleware.cors.CORSMiddleware>`.
- csrf_config: If set, configures :class:`CSRFMiddleware <.middleware.csrf.CSRFMiddleware>`.
- debug: If ``True``, app errors rendered as HTML with a stack trace.
- dependencies: A string keyed mapping of dependency :class:`Providers <.di.Provide>`.
- dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and
- validation of request data.
- etag: An ``etag`` header of type :class:`ETag <.datastructures.ETag>` to add to route handlers of this app.
- Can be overridden by route handlers.
- event_emitter_backend: A subclass of
- :class:`BaseEventEmitterBackend <.events.emitter.BaseEventEmitterBackend>`.
- exception_handlers: A mapping of status codes and/or exception types to handler functions.
- guards: A sequence of :class:`Guard <.types.Guard>` callables.
- include_in_schema: A boolean flag dictating whether the route handler should be documented in the OpenAPI schema.
- lifespan: A list of callables returning async context managers, wrapping the lifespan of the ASGI application
- listeners: A sequence of :class:`EventListener <.events.listener.EventListener>`.
- logging_config: A subclass of :class:`BaseLoggingConfig <.logging.config.BaseLoggingConfig>`.
- middleware: A sequence of :class:`Middleware <.types.Middleware>`.
- multipart_form_part_limit: The maximal number of allowed parts in a multipart/formdata request. This limit
- is intended to protect from DoS attacks.
- on_app_init: A sequence of :class:`OnAppInitHandler <.types.OnAppInitHandler>` instances. Handlers receive
- an instance of :class:`AppConfig <.config.app.AppConfig>` that will have been initially populated with
- the parameters passed to :class:`Litestar <litestar.app.Litestar>`, and must return an instance of same.
- If more than one handler is registered they are called in the order they are provided.
- on_shutdown: A sequence of :class:`LifespanHook <.types.LifespanHook>` called during application
- shutdown.
- on_startup: A sequence of :class:`LifespanHook <litestar.types.LifespanHook>` called during
- application startup.
- openapi_config: Defaults to :attr:`DEFAULT_OPENAPI_CONFIG`
- opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or
- wherever you have access to :class:`Request <litestar.connection.request.Request>` or
- :class:`ASGI Scope <.types.Scope>`.
- parameters: A mapping of :class:`Parameter <.params.Parameter>` definitions available to all application
- paths.
- pdb_on_exception: Drop into the PDB when an exception occurs.
- plugins: Sequence of plugins.
- request_class: An optional subclass of :class:`Request <.connection.Request>` to use for http connections.
- response_class: A custom subclass of :class:`Response <.response.Response>` to be used as the app's default
- response.
- response_cookies: A sequence of :class:`Cookie <.datastructures.Cookie>`.
- response_headers: A string keyed mapping of :class:`ResponseHeader <.datastructures.ResponseHeader>`
- response_cache_config: Configures caching behavior of the application.
- return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing
- outbound response data.
- route_handlers: A sequence of route handlers, which can include instances of
- :class:`Router <.router.Router>`, subclasses of :class:`Controller <.controller.Controller>` or any
- callable decorated by the route handler decorators.
- security: A sequence of dicts that will be added to the schema of all route handlers in the application.
- See
- :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>` for details.
- signature_namespace: A mapping of names to types for use in forward reference resolution during signature modeling.
- signature_types: A sequence of types for use in forward reference resolution during signature modeling.
- These types will be added to the signature namespace using their ``__name__`` attribute.
- state: An optional :class:`State <.datastructures.State>` for application state.
- static_files_config: A sequence of :class:`StaticFilesConfig <.static_files.StaticFilesConfig>`
- stores: Central registry of :class:`Store <.stores.base.Store>` that will be available throughout the
- application. If this is a dictionary to it will be passed to a
- :class:`StoreRegistry <.stores.registry.StoreRegistry>`. If it is a
- :class:`StoreRegistry <.stores.registry.StoreRegistry>`, this instance will be used directly.
- tags: A sequence of string tags that will be appended to the schema of all route handlers under the
- application.
- template_config: An instance of :class:`TemplateConfig <.template.TemplateConfig>`
- timeout: Request timeout
- type_encoders: A mapping of types to callables that transform them into types supported for serialization.
- websocket_class: An optional subclass of :class:`WebSocket <.connection.WebSocket>` to use for websocket
- connections.
- experimental_features: An iterable of experimental features to enable
-
-
- Returns:
- An instance of :class:`TestClient <.testing.TestClient>` with a created app instance.
- """
- route_handlers = () if route_handlers is None else route_handlers
- if is_class_and_subclass(route_handlers, Controller) or not isinstance(route_handlers, Sequence):
- route_handlers = (route_handlers,)
-
- app = Litestar(
- after_exception=after_exception,
- after_request=after_request,
- after_response=after_response,
- allowed_hosts=allowed_hosts,
- before_request=before_request,
- before_send=before_send,
- cache_control=cache_control,
- compression_config=compression_config,
- cors_config=cors_config,
- csrf_config=csrf_config,
- debug=debug,
- dependencies=dependencies,
- dto=dto,
- etag=etag,
- lifespan=lifespan,
- event_emitter_backend=event_emitter_backend,
- exception_handlers=exception_handlers,
- guards=guards,
- include_in_schema=include_in_schema,
- listeners=listeners,
- logging_config=logging_config,
- middleware=middleware,
- multipart_form_part_limit=multipart_form_part_limit,
- on_app_init=on_app_init,
- on_shutdown=on_shutdown,
- on_startup=on_startup,
- openapi_config=openapi_config,
- opt=opt,
- parameters=parameters,
- pdb_on_exception=pdb_on_exception,
- plugins=plugins,
- request_class=request_class,
- response_cache_config=response_cache_config,
- response_class=response_class,
- response_cookies=response_cookies,
- response_headers=response_headers,
- return_dto=return_dto,
- route_handlers=route_handlers,
- security=security,
- signature_namespace=signature_namespace,
- signature_types=signature_types,
- state=state,
- static_files_config=static_files_config,
- stores=stores,
- tags=tags,
- template_config=template_config,
- type_encoders=type_encoders,
- websocket_class=websocket_class,
- experimental_features=experimental_features,
- )
-
- return TestClient[Litestar](
- app=app,
- backend=backend,
- backend_options=backend_options,
- base_url=base_url,
- raise_server_exceptions=raise_server_exceptions,
- root_path=root_path,
- session_config=session_config,
- timeout=timeout,
- )
-
-
-def create_async_test_client(
- route_handlers: ControllerRouterHandler | Sequence[ControllerRouterHandler] | None = None,
- *,
- after_exception: Sequence[AfterExceptionHookHandler] | None = None,
- after_request: AfterRequestHookHandler | None = None,
- after_response: AfterResponseHookHandler | None = None,
- allowed_hosts: Sequence[str] | AllowedHostsConfig | None = None,
- backend: Literal["asyncio", "trio"] = "asyncio",
- backend_options: Mapping[str, Any] | None = None,
- base_url: str = "http://testserver.local",
- before_request: BeforeRequestHookHandler | None = None,
- before_send: Sequence[BeforeMessageSendHookHandler] | None = None,
- cache_control: CacheControlHeader | None = None,
- compression_config: CompressionConfig | None = None,
- cors_config: CORSConfig | None = None,
- csrf_config: CSRFConfig | None = None,
- debug: bool = True,
- dependencies: Dependencies | None = None,
- dto: type[AbstractDTO] | None | EmptyType = Empty,
- etag: ETag | None = None,
- event_emitter_backend: type[BaseEventEmitterBackend] = SimpleEventEmitter,
- exception_handlers: ExceptionHandlersMap | None = None,
- guards: Sequence[Guard] | None = None,
- include_in_schema: bool | EmptyType = Empty,
- lifespan: list[Callable[[Litestar], AbstractAsyncContextManager] | AbstractAsyncContextManager] | None = None,
- listeners: Sequence[EventListener] | None = None,
- logging_config: BaseLoggingConfig | EmptyType | None = Empty,
- middleware: Sequence[Middleware] | None = None,
- multipart_form_part_limit: int = 1000,
- on_app_init: Sequence[OnAppInitHandler] | None = None,
- on_shutdown: Sequence[LifespanHook] | None = None,
- on_startup: Sequence[LifespanHook] | None = None,
- openapi_config: OpenAPIConfig | None = DEFAULT_OPENAPI_CONFIG,
- opt: Mapping[str, Any] | None = None,
- parameters: ParametersMap | None = None,
- pdb_on_exception: bool | None = None,
- plugins: Sequence[PluginProtocol] | None = None,
- raise_server_exceptions: bool = True,
- request_class: type[Request] | None = None,
- response_cache_config: ResponseCacheConfig | None = None,
- response_class: type[Response] | None = None,
- response_cookies: ResponseCookies | None = None,
- response_headers: ResponseHeaders | None = None,
- return_dto: type[AbstractDTO] | None | EmptyType = Empty,
- root_path: str = "",
- security: Sequence[SecurityRequirement] | None = None,
- session_config: BaseBackendConfig | None = None,
- signature_namespace: Mapping[str, Any] | None = None,
- signature_types: Sequence[Any] | None = None,
- state: State | None = None,
- static_files_config: Sequence[StaticFilesConfig] | None = None,
- stores: StoreRegistry | dict[str, Store] | None = None,
- tags: Sequence[str] | None = None,
- template_config: TemplateConfig | None = None,
- timeout: float | None = None,
- type_encoders: TypeEncodersMap | None = None,
- websocket_class: type[WebSocket] | None = None,
- experimental_features: list[ExperimentalFeatures] | None = None,
-) -> AsyncTestClient[Litestar]:
- """Create a Litestar app instance and initializes it.
-
- :class:`AsyncTestClient <litestar.testing.AsyncTestClient>` with it.
-
- Notes:
- - This function should be called as a context manager to ensure async startup and shutdown are
- handled correctly.
-
- Examples:
- .. code-block:: python
-
- from litestar import get
- from litestar.testing import create_async_test_client
-
-
- @get("/some-path")
- def my_handler() -> dict[str, str]:
- return {"hello": "world"}
-
-
- async def test_my_handler() -> None:
- async with create_async_test_client(my_handler) as client:
- response = await client.get("/some-path")
- assert response.json() == {"hello": "world"}
-
- Args:
- route_handlers: A single handler or a sequence of route handlers, which can include instances of
- :class:`Router <litestar.router.Router>`, subclasses of :class:`Controller <.controller.Controller>` or
- any function decorated by the route handler decorators.
- backend: The async backend to use, options are "asyncio" or "trio".
- backend_options: ``anyio`` options.
- base_url: URL scheme and domain for test request paths, e.g. ``http://testserver``.
- raise_server_exceptions: Flag for underlying the test client to raise server exceptions instead of wrapping them
- in an HTTP response.
- root_path: Path prefix for requests.
- session_config: Configuration for Session Middleware class to create raw session cookies for request to the
- route handlers.
- after_exception: A sequence of :class:`exception hook handlers <.types.AfterExceptionHookHandler>`. This
- hook is called after an exception occurs. In difference to exception handlers, it is not meant to
- return a response - only to process the exception (e.g. log it, send it to Sentry etc.).
- after_request: A sync or async function executed after the route handler function returned and the response
- object has been resolved. Receives the response object.
- after_response: A sync or async function called after the response has been awaited. It receives the
- :class:`Request <.connection.Request>` object and should not return any values.
- allowed_hosts: A sequence of allowed hosts, or an
- :class:`AllowedHostsConfig <.config.allowed_hosts.AllowedHostsConfig>` instance. Enables the builtin
- allowed hosts middleware.
- before_request: A sync or async function called immediately before calling the route handler. Receives the
- :class:`Request <.connection.Request>` instance and any non-``None`` return value is used for the
- response, bypassing the route handler.
- before_send: A sequence of :class:`before send hook handlers <.types.BeforeMessageSendHookHandler>`. Called
- when the ASGI send function is called.
- cache_control: A ``cache-control`` header of type
- :class:`CacheControlHeader <litestar.datastructures.CacheControlHeader>` to add to route handlers of
- this app. Can be overridden by route handlers.
- compression_config: Configures compression behaviour of the application, this enabled a builtin or user
- defined Compression middleware.
- cors_config: If set, configures :class:`CORSMiddleware <.middleware.cors.CORSMiddleware>`.
- csrf_config: If set, configures :class:`CSRFMiddleware <.middleware.csrf.CSRFMiddleware>`.
- debug: If ``True``, app errors rendered as HTML with a stack trace.
- dependencies: A string keyed mapping of dependency :class:`Providers <.di.Provide>`.
- dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for (de)serializing and
- validation of request data.
- etag: An ``etag`` header of type :class:`ETag <.datastructures.ETag>` to add to route handlers of this app.
- Can be overridden by route handlers.
- event_emitter_backend: A subclass of
- :class:`BaseEventEmitterBackend <.events.emitter.BaseEventEmitterBackend>`.
- exception_handlers: A mapping of status codes and/or exception types to handler functions.
- guards: A sequence of :class:`Guard <.types.Guard>` callables.
- include_in_schema: A boolean flag dictating whether the route handler should be documented in the OpenAPI schema.
- lifespan: A list of callables returning async context managers, wrapping the lifespan of the ASGI application
- listeners: A sequence of :class:`EventListener <.events.listener.EventListener>`.
- logging_config: A subclass of :class:`BaseLoggingConfig <.logging.config.BaseLoggingConfig>`.
- middleware: A sequence of :class:`Middleware <.types.Middleware>`.
- multipart_form_part_limit: The maximal number of allowed parts in a multipart/formdata request. This limit
- is intended to protect from DoS attacks.
- on_app_init: A sequence of :class:`OnAppInitHandler <.types.OnAppInitHandler>` instances. Handlers receive
- an instance of :class:`AppConfig <.config.app.AppConfig>` that will have been initially populated with
- the parameters passed to :class:`Litestar <litestar.app.Litestar>`, and must return an instance of same.
- If more than one handler is registered they are called in the order they are provided.
- on_shutdown: A sequence of :class:`LifespanHook <.types.LifespanHook>` called during application
- shutdown.
- on_startup: A sequence of :class:`LifespanHook <litestar.types.LifespanHook>` called during
- application startup.
- openapi_config: Defaults to :attr:`DEFAULT_OPENAPI_CONFIG`
- opt: A string keyed mapping of arbitrary values that can be accessed in :class:`Guards <.types.Guard>` or
- wherever you have access to :class:`Request <litestar.connection.request.Request>` or
- :class:`ASGI Scope <.types.Scope>`.
- parameters: A mapping of :class:`Parameter <.params.Parameter>` definitions available to all application
- paths.
- pdb_on_exception: Drop into the PDB when an exception occurs.
- plugins: Sequence of plugins.
- request_class: An optional subclass of :class:`Request <.connection.Request>` to use for http connections.
- response_class: A custom subclass of :class:`Response <.response.Response>` to be used as the app's default
- response.
- response_cookies: A sequence of :class:`Cookie <.datastructures.Cookie>`.
- response_headers: A string keyed mapping of :class:`ResponseHeader <.datastructures.ResponseHeader>`
- response_cache_config: Configures caching behavior of the application.
- return_dto: :class:`AbstractDTO <.dto.base_dto.AbstractDTO>` to use for serializing
- outbound response data.
- route_handlers: A sequence of route handlers, which can include instances of
- :class:`Router <.router.Router>`, subclasses of :class:`Controller <.controller.Controller>` or any
- callable decorated by the route handler decorators.
- security: A sequence of dicts that will be added to the schema of all route handlers in the application.
- See
- :data:`SecurityRequirement <.openapi.spec.SecurityRequirement>` for details.
- signature_namespace: A mapping of names to types for use in forward reference resolution during signature modeling.
- signature_types: A sequence of types for use in forward reference resolution during signature modeling.
- These types will be added to the signature namespace using their ``__name__`` attribute.
- state: An optional :class:`State <.datastructures.State>` for application state.
- static_files_config: A sequence of :class:`StaticFilesConfig <.static_files.StaticFilesConfig>`
- stores: Central registry of :class:`Store <.stores.base.Store>` that will be available throughout the
- application. If this is a dictionary to it will be passed to a
- :class:`StoreRegistry <.stores.registry.StoreRegistry>`. If it is a
- :class:`StoreRegistry <.stores.registry.StoreRegistry>`, this instance will be used directly.
- tags: A sequence of string tags that will be appended to the schema of all route handlers under the
- application.
- template_config: An instance of :class:`TemplateConfig <.template.TemplateConfig>`
- timeout: Request timeout
- type_encoders: A mapping of types to callables that transform them into types supported for serialization.
- websocket_class: An optional subclass of :class:`WebSocket <.connection.WebSocket>` to use for websocket
- connections.
- experimental_features: An iterable of experimental features to enable
-
- Returns:
- An instance of :class:`AsyncTestClient <litestar.testing.AsyncTestClient>` with a created app instance.
- """
- route_handlers = () if route_handlers is None else route_handlers
- if is_class_and_subclass(route_handlers, Controller) or not isinstance(route_handlers, Sequence):
- route_handlers = (route_handlers,)
-
- app = Litestar(
- after_exception=after_exception,
- after_request=after_request,
- after_response=after_response,
- allowed_hosts=allowed_hosts,
- before_request=before_request,
- before_send=before_send,
- cache_control=cache_control,
- compression_config=compression_config,
- cors_config=cors_config,
- csrf_config=csrf_config,
- debug=debug,
- dependencies=dependencies,
- dto=dto,
- etag=etag,
- event_emitter_backend=event_emitter_backend,
- exception_handlers=exception_handlers,
- guards=guards,
- include_in_schema=include_in_schema,
- lifespan=lifespan,
- listeners=listeners,
- logging_config=logging_config,
- middleware=middleware,
- multipart_form_part_limit=multipart_form_part_limit,
- on_app_init=on_app_init,
- on_shutdown=on_shutdown,
- on_startup=on_startup,
- openapi_config=openapi_config,
- opt=opt,
- parameters=parameters,
- pdb_on_exception=pdb_on_exception,
- plugins=plugins,
- request_class=request_class,
- response_cache_config=response_cache_config,
- response_class=response_class,
- response_cookies=response_cookies,
- response_headers=response_headers,
- return_dto=return_dto,
- route_handlers=route_handlers,
- security=security,
- signature_namespace=signature_namespace,
- signature_types=signature_types,
- state=state,
- static_files_config=static_files_config,
- stores=stores,
- tags=tags,
- template_config=template_config,
- type_encoders=type_encoders,
- websocket_class=websocket_class,
- experimental_features=experimental_features,
- )
-
- return AsyncTestClient[Litestar](
- app=app,
- backend=backend,
- backend_options=backend_options,
- base_url=base_url,
- raise_server_exceptions=raise_server_exceptions,
- root_path=root_path,
- session_config=session_config,
- timeout=timeout,
- )
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/life_span_handler.py b/venv/lib/python3.11/site-packages/litestar/testing/life_span_handler.py
deleted file mode 100644
index 8ee7d22..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/life_span_handler.py
+++ /dev/null
@@ -1,78 +0,0 @@
-from __future__ import annotations
-
-from math import inf
-from typing import TYPE_CHECKING, Generic, Optional, TypeVar, cast
-
-from anyio import create_memory_object_stream
-from anyio.streams.stapled import StapledObjectStream
-
-from litestar.testing.client.base import BaseTestClient
-
-if TYPE_CHECKING:
- from litestar.types import (
- LifeSpanReceiveMessage, # noqa: F401
- LifeSpanSendMessage,
- LifeSpanShutdownEvent,
- LifeSpanStartupEvent,
- )
-
-T = TypeVar("T", bound=BaseTestClient)
-
-
-class LifeSpanHandler(Generic[T]):
- __slots__ = "stream_send", "stream_receive", "client", "task"
-
- def __init__(self, client: T) -> None:
- self.client = client
- self.stream_send = StapledObjectStream[Optional["LifeSpanSendMessage"]](*create_memory_object_stream(inf)) # type: ignore[arg-type]
- self.stream_receive = StapledObjectStream["LifeSpanReceiveMessage"](*create_memory_object_stream(inf)) # type: ignore[arg-type]
-
- with self.client.portal() as portal:
- self.task = portal.start_task_soon(self.lifespan)
- portal.call(self.wait_startup)
-
- async def receive(self) -> LifeSpanSendMessage:
- message = await self.stream_send.receive()
- if message is None:
- self.task.result()
- return cast("LifeSpanSendMessage", message)
-
- async def wait_startup(self) -> None:
- event: LifeSpanStartupEvent = {"type": "lifespan.startup"}
- await self.stream_receive.send(event)
-
- message = await self.receive()
- if message["type"] not in (
- "lifespan.startup.complete",
- "lifespan.startup.failed",
- ):
- raise RuntimeError(
- "Received unexpected ASGI message type. Expected 'lifespan.startup.complete' or "
- f"'lifespan.startup.failed'. Got {message['type']!r}",
- )
- if message["type"] == "lifespan.startup.failed":
- await self.receive()
-
- async def wait_shutdown(self) -> None:
- async with self.stream_send:
- lifespan_shutdown_event: LifeSpanShutdownEvent = {"type": "lifespan.shutdown"}
- await self.stream_receive.send(lifespan_shutdown_event)
-
- message = await self.receive()
- if message["type"] not in (
- "lifespan.shutdown.complete",
- "lifespan.shutdown.failed",
- ):
- raise RuntimeError(
- "Received unexpected ASGI message type. Expected 'lifespan.shutdown.complete' or "
- f"'lifespan.shutdown.failed'. Got {message['type']!r}",
- )
- if message["type"] == "lifespan.shutdown.failed":
- await self.receive()
-
- async def lifespan(self) -> None:
- scope = {"type": "lifespan"}
- try:
- await self.client.app(scope, self.stream_receive.receive, self.stream_send.send)
- finally:
- await self.stream_send.send(None)
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/request_factory.py b/venv/lib/python3.11/site-packages/litestar/testing/request_factory.py
deleted file mode 100644
index ccb29c6..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/request_factory.py
+++ /dev/null
@@ -1,565 +0,0 @@
-from __future__ import annotations
-
-import json
-from functools import partial
-from typing import TYPE_CHECKING, Any, cast
-from urllib.parse import urlencode
-
-from httpx._content import encode_json as httpx_encode_json
-from httpx._content import encode_multipart_data, encode_urlencoded_data
-
-from litestar import delete, patch, post, put
-from litestar.app import Litestar
-from litestar.connection import Request
-from litestar.enums import HttpMethod, ParamType, RequestEncodingType, ScopeType
-from litestar.handlers.http_handlers import get
-from litestar.serialization import decode_json, default_serializer, encode_json
-from litestar.types import DataContainerType, HTTPScope, RouteHandlerType
-from litestar.types.asgi_types import ASGIVersion
-from litestar.utils import get_serializer_from_scope
-from litestar.utils.scope.state import ScopeState
-
-if TYPE_CHECKING:
- from httpx._types import FileTypes
-
- from litestar.datastructures.cookie import Cookie
- from litestar.handlers.http_handlers import HTTPRouteHandler
-
-_decorator_http_method_map: dict[HttpMethod, type[HTTPRouteHandler]] = {
- HttpMethod.GET: get,
- HttpMethod.POST: post,
- HttpMethod.DELETE: delete,
- HttpMethod.PATCH: patch,
- HttpMethod.PUT: put,
-}
-
-
-def _create_default_route_handler(
- http_method: HttpMethod, handler_kwargs: dict[str, Any] | None, app: Litestar
-) -> HTTPRouteHandler:
- handler_decorator = _decorator_http_method_map[http_method]
-
- def _default_route_handler() -> None: ...
-
- handler = handler_decorator("/", sync_to_thread=False, **(handler_kwargs or {}))(_default_route_handler)
- handler.owner = app
- return handler
-
-
-def _create_default_app() -> Litestar:
- return Litestar(route_handlers=[])
-
-
-class RequestFactory:
- """Factory to create :class:`Request <litestar.connection.Request>` instances."""
-
- __slots__ = (
- "app",
- "server",
- "port",
- "root_path",
- "scheme",
- "handler_kwargs",
- "serializer",
- )
-
- def __init__(
- self,
- app: Litestar | None = None,
- server: str = "test.org",
- port: int = 3000,
- root_path: str = "",
- scheme: str = "http",
- handler_kwargs: dict[str, Any] | None = None,
- ) -> None:
- """Initialize ``RequestFactory``
-
- Args:
- app: An instance of :class:`Litestar <litestar.app.Litestar>` to set as ``request.scope["app"]``.
- server: The server's domain.
- port: The server's port.
- root_path: Root path for the server.
- scheme: Scheme for the server.
- handler_kwargs: Kwargs to pass to the route handler created for the request
-
- Examples:
- .. code-block:: python
-
- from litestar import Litestar
- from litestar.enums import RequestEncodingType
- from litestar.testing import RequestFactory
-
- from tests import PersonFactory
-
- my_app = Litestar(route_handlers=[])
- my_server = "litestar.org"
-
- # Create a GET request
- query_params = {"id": 1}
- get_user_request = RequestFactory(app=my_app, server=my_server).get(
- "/person", query_params=query_params
- )
-
- # Create a POST request
- new_person = PersonFactory.build()
- create_user_request = RequestFactory(app=my_app, server=my_server).post(
- "/person", data=person
- )
-
- # Create a request with a special header
- headers = {"header1": "value1"}
- request_with_header = RequestFactory(app=my_app, server=my_server).get(
- "/person", query_params=query_params, headers=headers
- )
-
- # Create a request with a media type
- request_with_media_type = RequestFactory(app=my_app, server=my_server).post(
- "/person", data=person, request_media_type=RequestEncodingType.MULTI_PART
- )
-
- """
-
- self.app = app if app is not None else _create_default_app()
- self.server = server
- self.port = port
- self.root_path = root_path
- self.scheme = scheme
- self.handler_kwargs = handler_kwargs
- self.serializer = partial(default_serializer, type_encoders=self.app.type_encoders)
-
- def _create_scope(
- self,
- path: str,
- http_method: HttpMethod,
- session: dict[str, Any] | None = None,
- user: Any = None,
- auth: Any = None,
- query_params: dict[str, str | list[str]] | None = None,
- state: dict[str, Any] | None = None,
- path_params: dict[str, str] | None = None,
- http_version: str | None = "1.1",
- route_handler: RouteHandlerType | None = None,
- ) -> HTTPScope:
- """Create the scope for the :class:`Request <litestar.connection.Request>`.
-
- Args:
- path: The request's path.
- http_method: The request's HTTP method.
- session: A dictionary of session data.
- user: A value for `request.scope["user"]`.
- auth: A value for `request.scope["auth"]`.
- query_params: A dictionary of values from which the request's query will be generated.
- state: Arbitrary request state.
- path_params: A string keyed dictionary of path parameter values.
- http_version: HTTP version. Defaults to "1.1".
- route_handler: A route handler instance or method. If not provided a default handler is set.
-
- Returns:
- A dictionary that can be passed as a scope to the :class:`Request <litestar.connection.Request>` ctor.
- """
- if session is None:
- session = {}
-
- if state is None:
- state = {}
-
- if path_params is None:
- path_params = {}
-
- return HTTPScope(
- type=ScopeType.HTTP,
- method=http_method.value,
- scheme=self.scheme,
- server=(self.server, self.port),
- root_path=self.root_path.rstrip("/"),
- path=path,
- headers=[],
- app=self.app,
- session=session,
- user=user,
- auth=auth,
- query_string=urlencode(query_params, doseq=True).encode() if query_params else b"",
- path_params=path_params,
- client=(self.server, self.port),
- state=state,
- asgi=ASGIVersion(spec_version="3.0", version="3.0"),
- http_version=http_version or "1.1",
- raw_path=path.encode("ascii"),
- route_handler=route_handler
- or _create_default_route_handler(http_method, self.handler_kwargs, app=self.app),
- extensions={},
- )
-
- @classmethod
- def _create_cookie_header(cls, headers: dict[str, str], cookies: list[Cookie] | str | None = None) -> None:
- """Create the cookie header and add it to the ``headers`` dictionary.
-
- Args:
- headers: A dictionary of headers, the cookie header will be added to it.
- cookies: A string representing the cookie header or a list of "Cookie" instances.
- This value can include multiple cookies.
- """
- if not cookies:
- return
-
- if isinstance(cookies, list):
- cookie_header = "; ".join(cookie.to_header(header="") for cookie in cookies)
- headers[ParamType.COOKIE] = cookie_header
- elif isinstance(cookies, str):
- headers[ParamType.COOKIE] = cookies
-
- def _build_headers(
- self,
- headers: dict[str, str] | None = None,
- cookies: list[Cookie] | str | None = None,
- ) -> list[tuple[bytes, bytes]]:
- """Build a list of encoded headers that can be passed to the request scope.
-
- Args:
- headers: A dictionary of headers.
- cookies: A string representing the cookie header or a list of "Cookie" instances.
- This value can include multiple cookies.
-
- Returns:
- A list of encoded headers that can be passed to the request scope.
- """
- headers = headers or {}
- self._create_cookie_header(headers, cookies)
- return [
- ((key.lower()).encode("latin-1", errors="ignore"), value.encode("latin-1", errors="ignore"))
- for key, value in headers.items()
- ]
-
- def _create_request_with_data(
- self,
- http_method: HttpMethod,
- path: str,
- headers: dict[str, str] | None = None,
- cookies: list[Cookie] | str | None = None,
- session: dict[str, Any] | None = None,
- user: Any = None,
- auth: Any = None,
- request_media_type: RequestEncodingType = RequestEncodingType.JSON,
- data: dict[str, Any] | DataContainerType | None = None, # pyright: ignore
- files: dict[str, FileTypes] | list[tuple[str, FileTypes]] | None = None,
- query_params: dict[str, str | list[str]] | None = None,
- state: dict[str, Any] | None = None,
- path_params: dict[str, str] | None = None,
- http_version: str | None = "1.1",
- route_handler: RouteHandlerType | None = None,
- ) -> Request[Any, Any, Any]:
- """Create a :class:`Request <litestar.connection.Request>` instance that has body (data)
-
- Args:
- http_method: The request's HTTP method.
- path: The request's path.
- headers: A dictionary of headers.
- cookies: A string representing the cookie header or a list of "Cookie" instances.
- This value can include multiple cookies.
- session: A dictionary of session data.
- user: A value for `request.scope["user"]`
- auth: A value for `request.scope["auth"]`
- request_media_type: The 'Content-Type' header of the request.
- data: A value for the request's body. Can be any supported serializable type.
- files: A dictionary of files to be sent with the request.
- query_params: A dictionary of values from which the request's query will be generated.
- state: Arbitrary request state.
- path_params: A string keyed dictionary of path parameter values.
- http_version: HTTP version. Defaults to "1.1".
- route_handler: A route handler instance or method. If not provided a default handler is set.
-
- Returns:
- A :class:`Request <litestar.connection.Request>` instance
- """
- scope = self._create_scope(
- path=path,
- http_method=http_method,
- session=session,
- user=user,
- auth=auth,
- query_params=query_params,
- state=state,
- path_params=path_params,
- http_version=http_version,
- route_handler=route_handler,
- )
-
- headers = headers or {}
- body = b""
- if data:
- data = json.loads(encode_json(data, serializer=get_serializer_from_scope(scope)))
-
- if request_media_type == RequestEncodingType.JSON:
- encoding_headers, stream = httpx_encode_json(data)
- elif request_media_type == RequestEncodingType.MULTI_PART:
- encoding_headers, stream = encode_multipart_data( # type: ignore[assignment]
- cast("dict[str, Any]", data), files=files or [], boundary=None
- )
- else:
- encoding_headers, stream = encode_urlencoded_data(decode_json(value=encode_json(data)))
- headers.update(encoding_headers)
- for chunk in stream:
- body += chunk
- ScopeState.from_scope(scope).body = body
- self._create_cookie_header(headers, cookies)
- scope["headers"] = self._build_headers(headers)
- return Request(scope=scope)
-
- def get(
- self,
- path: str = "/",
- headers: dict[str, str] | None = None,
- cookies: list[Cookie] | str | None = None,
- session: dict[str, Any] | None = None,
- user: Any = None,
- auth: Any = None,
- query_params: dict[str, str | list[str]] | None = None,
- state: dict[str, Any] | None = None,
- path_params: dict[str, str] | None = None,
- http_version: str | None = "1.1",
- route_handler: RouteHandlerType | None = None,
- ) -> Request[Any, Any, Any]:
- """Create a GET :class:`Request <litestar.connection.Request>` instance.
-
- Args:
- path: The request's path.
- headers: A dictionary of headers.
- cookies: A string representing the cookie header or a list of "Cookie" instances.
- This value can include multiple cookies.
- session: A dictionary of session data.
- user: A value for `request.scope["user"]`.
- auth: A value for `request.scope["auth"]`.
- query_params: A dictionary of values from which the request's query will be generated.
- state: Arbitrary request state.
- path_params: A string keyed dictionary of path parameter values.
- http_version: HTTP version. Defaults to "1.1".
- route_handler: A route handler instance or method. If not provided a default handler is set.
-
- Returns:
- A :class:`Request <litestar.connection.Request>` instance
- """
- scope = self._create_scope(
- path=path,
- http_method=HttpMethod.GET,
- session=session,
- user=user,
- auth=auth,
- query_params=query_params,
- state=state,
- path_params=path_params,
- http_version=http_version,
- route_handler=route_handler,
- )
-
- scope["headers"] = self._build_headers(headers, cookies)
- return Request(scope=scope)
-
- def post(
- self,
- path: str = "/",
- headers: dict[str, str] | None = None,
- cookies: list[Cookie] | str | None = None,
- session: dict[str, Any] | None = None,
- user: Any = None,
- auth: Any = None,
- request_media_type: RequestEncodingType = RequestEncodingType.JSON,
- data: dict[str, Any] | DataContainerType | None = None, # pyright: ignore
- query_params: dict[str, str | list[str]] | None = None,
- state: dict[str, Any] | None = None,
- path_params: dict[str, str] | None = None,
- http_version: str | None = "1.1",
- route_handler: RouteHandlerType | None = None,
- ) -> Request[Any, Any, Any]:
- """Create a POST :class:`Request <litestar.connection.Request>` instance.
-
- Args:
- path: The request's path.
- headers: A dictionary of headers.
- cookies: A string representing the cookie header or a list of "Cookie" instances.
- This value can include multiple cookies.
- session: A dictionary of session data.
- user: A value for `request.scope["user"]`.
- auth: A value for `request.scope["auth"]`.
- request_media_type: The 'Content-Type' header of the request.
- data: A value for the request's body. Can be any supported serializable type.
- query_params: A dictionary of values from which the request's query will be generated.
- state: Arbitrary request state.
- path_params: A string keyed dictionary of path parameter values.
- http_version: HTTP version. Defaults to "1.1".
- route_handler: A route handler instance or method. If not provided a default handler is set.
-
- Returns:
- A :class:`Request <litestar.connection.Request>` instance
- """
- return self._create_request_with_data(
- auth=auth,
- cookies=cookies,
- data=data,
- headers=headers,
- http_method=HttpMethod.POST,
- path=path,
- query_params=query_params,
- request_media_type=request_media_type,
- session=session,
- user=user,
- state=state,
- path_params=path_params,
- http_version=http_version,
- route_handler=route_handler,
- )
-
- def put(
- self,
- path: str = "/",
- headers: dict[str, str] | None = None,
- cookies: list[Cookie] | str | None = None,
- session: dict[str, Any] | None = None,
- user: Any = None,
- auth: Any = None,
- request_media_type: RequestEncodingType = RequestEncodingType.JSON,
- data: dict[str, Any] | DataContainerType | None = None, # pyright: ignore
- query_params: dict[str, str | list[str]] | None = None,
- state: dict[str, Any] | None = None,
- path_params: dict[str, str] | None = None,
- http_version: str | None = "1.1",
- route_handler: RouteHandlerType | None = None,
- ) -> Request[Any, Any, Any]:
- """Create a PUT :class:`Request <litestar.connection.Request>` instance.
-
- Args:
- path: The request's path.
- headers: A dictionary of headers.
- cookies: A string representing the cookie header or a list of "Cookie" instances.
- This value can include multiple cookies.
- session: A dictionary of session data.
- user: A value for `request.scope["user"]`.
- auth: A value for `request.scope["auth"]`.
- request_media_type: The 'Content-Type' header of the request.
- data: A value for the request's body. Can be any supported serializable type.
- query_params: A dictionary of values from which the request's query will be generated.
- state: Arbitrary request state.
- path_params: A string keyed dictionary of path parameter values.
- http_version: HTTP version. Defaults to "1.1".
- route_handler: A route handler instance or method. If not provided a default handler is set.
-
- Returns:
- A :class:`Request <litestar.connection.Request>` instance
- """
- return self._create_request_with_data(
- auth=auth,
- cookies=cookies,
- data=data,
- headers=headers,
- http_method=HttpMethod.PUT,
- path=path,
- query_params=query_params,
- request_media_type=request_media_type,
- session=session,
- user=user,
- state=state,
- path_params=path_params,
- http_version=http_version,
- route_handler=route_handler,
- )
-
- def patch(
- self,
- path: str = "/",
- headers: dict[str, str] | None = None,
- cookies: list[Cookie] | str | None = None,
- session: dict[str, Any] | None = None,
- user: Any = None,
- auth: Any = None,
- request_media_type: RequestEncodingType = RequestEncodingType.JSON,
- data: dict[str, Any] | DataContainerType | None = None, # pyright: ignore
- query_params: dict[str, str | list[str]] | None = None,
- state: dict[str, Any] | None = None,
- path_params: dict[str, str] | None = None,
- http_version: str | None = "1.1",
- route_handler: RouteHandlerType | None = None,
- ) -> Request[Any, Any, Any]:
- """Create a PATCH :class:`Request <litestar.connection.Request>` instance.
-
- Args:
- path: The request's path.
- headers: A dictionary of headers.
- cookies: A string representing the cookie header or a list of "Cookie" instances.
- This value can include multiple cookies.
- session: A dictionary of session data.
- user: A value for `request.scope["user"]`.
- auth: A value for `request.scope["auth"]`.
- request_media_type: The 'Content-Type' header of the request.
- data: A value for the request's body. Can be any supported serializable type.
- query_params: A dictionary of values from which the request's query will be generated.
- state: Arbitrary request state.
- path_params: A string keyed dictionary of path parameter values.
- http_version: HTTP version. Defaults to "1.1".
- route_handler: A route handler instance or method. If not provided a default handler is set.
-
- Returns:
- A :class:`Request <litestar.connection.Request>` instance
- """
- return self._create_request_with_data(
- auth=auth,
- cookies=cookies,
- data=data,
- headers=headers,
- http_method=HttpMethod.PATCH,
- path=path,
- query_params=query_params,
- request_media_type=request_media_type,
- session=session,
- user=user,
- state=state,
- path_params=path_params,
- http_version=http_version,
- route_handler=route_handler,
- )
-
- def delete(
- self,
- path: str = "/",
- headers: dict[str, str] | None = None,
- cookies: list[Cookie] | str | None = None,
- session: dict[str, Any] | None = None,
- user: Any = None,
- auth: Any = None,
- query_params: dict[str, str | list[str]] | None = None,
- state: dict[str, Any] | None = None,
- path_params: dict[str, str] | None = None,
- http_version: str | None = "1.1",
- route_handler: RouteHandlerType | None = None,
- ) -> Request[Any, Any, Any]:
- """Create a POST :class:`Request <litestar.connection.Request>` instance.
-
- Args:
- path: The request's path.
- headers: A dictionary of headers.
- cookies: A string representing the cookie header or a list of "Cookie" instances.
- This value can include multiple cookies.
- session: A dictionary of session data.
- user: A value for `request.scope["user"]`.
- auth: A value for `request.scope["auth"]`.
- query_params: A dictionary of values from which the request's query will be generated.
- state: Arbitrary request state.
- path_params: A string keyed dictionary of path parameter values.
- http_version: HTTP version. Defaults to "1.1".
- route_handler: A route handler instance or method. If not provided a default handler is set.
-
- Returns:
- A :class:`Request <litestar.connection.Request>` instance
- """
- scope = self._create_scope(
- path=path,
- http_method=HttpMethod.DELETE,
- session=session,
- user=user,
- auth=auth,
- query_params=query_params,
- state=state,
- path_params=path_params,
- http_version=http_version,
- route_handler=route_handler,
- )
- scope["headers"] = self._build_headers(headers, cookies)
- return Request(scope=scope)
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/transport.py b/venv/lib/python3.11/site-packages/litestar/testing/transport.py
deleted file mode 100644
index ffa76a4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/transport.py
+++ /dev/null
@@ -1,192 +0,0 @@
-from __future__ import annotations
-
-from io import BytesIO
-from types import GeneratorType
-from typing import TYPE_CHECKING, Any, Generic, TypedDict, TypeVar, Union, cast
-from urllib.parse import unquote
-
-from anyio import Event
-from httpx import ByteStream, Response
-
-from litestar.status_codes import HTTP_500_INTERNAL_SERVER_ERROR
-from litestar.testing.websocket_test_session import WebSocketTestSession
-
-if TYPE_CHECKING:
- from httpx import Request
-
- from litestar.testing.client import AsyncTestClient, TestClient
- from litestar.types import (
- HTTPDisconnectEvent,
- HTTPRequestEvent,
- Message,
- Receive,
- ReceiveMessage,
- Send,
- WebSocketScope,
- )
-
-
-T = TypeVar("T", bound=Union["AsyncTestClient", "TestClient"])
-
-
-class ConnectionUpgradeExceptionError(Exception):
- def __init__(self, session: WebSocketTestSession) -> None:
- self.session = session
-
-
-class SendReceiveContext(TypedDict):
- request_complete: bool
- response_complete: Event
- raw_kwargs: dict[str, Any]
- response_started: bool
- template: str | None
- context: Any | None
-
-
-class TestClientTransport(Generic[T]):
- def __init__(
- self,
- client: T,
- raise_server_exceptions: bool = True,
- root_path: str = "",
- ) -> None:
- self.client = client
- self.raise_server_exceptions = raise_server_exceptions
- self.root_path = root_path
-
- @staticmethod
- def create_receive(request: Request, context: SendReceiveContext) -> Receive:
- async def receive() -> ReceiveMessage:
- if context["request_complete"]:
- if not context["response_complete"].is_set():
- await context["response_complete"].wait()
- disconnect_event: HTTPDisconnectEvent = {"type": "http.disconnect"}
- return disconnect_event
-
- body = cast("Union[bytes, str, GeneratorType]", (request.read() or b""))
- request_event: HTTPRequestEvent = {"type": "http.request", "body": b"", "more_body": False}
- if isinstance(body, GeneratorType): # pragma: no cover
- try:
- chunk = body.send(None)
- request_event["body"] = chunk if isinstance(chunk, bytes) else chunk.encode("utf-8")
- request_event["more_body"] = True
- except StopIteration:
- context["request_complete"] = True
- else:
- context["request_complete"] = True
- request_event["body"] = body if isinstance(body, bytes) else body.encode("utf-8")
- return request_event
-
- return receive
-
- @staticmethod
- def create_send(request: Request, context: SendReceiveContext) -> Send:
- async def send(message: Message) -> None:
- if message["type"] == "http.response.start":
- assert not context["response_started"], 'Received multiple "http.response.start" messages.' # noqa: S101
- context["raw_kwargs"]["status_code"] = message["status"]
- context["raw_kwargs"]["headers"] = [
- (k.decode("utf-8"), v.decode("utf-8")) for k, v in message.get("headers", [])
- ]
- context["response_started"] = True
- elif message["type"] == "http.response.body":
- assert context["response_started"], 'Received "http.response.body" without "http.response.start".' # noqa: S101
- assert not context[ # noqa: S101
- "response_complete"
- ].is_set(), 'Received "http.response.body" after response completed.'
- body = message.get("body", b"")
- more_body = message.get("more_body", False)
- if request.method != "HEAD":
- context["raw_kwargs"]["stream"].write(body)
- if not more_body:
- context["raw_kwargs"]["stream"].seek(0)
- context["response_complete"].set()
- elif message["type"] == "http.response.template": # type: ignore[comparison-overlap] # pragma: no cover
- context["template"] = message["template"] # type: ignore[unreachable]
- context["context"] = message["context"]
-
- return send
-
- def parse_request(self, request: Request) -> dict[str, Any]:
- scheme = request.url.scheme
- netloc = unquote(request.url.netloc.decode(encoding="ascii"))
- path = request.url.path
- raw_path = request.url.raw_path
- query = request.url.query.decode(encoding="ascii")
- default_port = 433 if scheme in {"https", "wss"} else 80
-
- if ":" in netloc:
- host, port_string = netloc.split(":", 1)
- port = int(port_string)
- else:
- host = netloc
- port = default_port
-
- host_header = request.headers.pop("host", host if port == default_port else f"{host}:{port}")
-
- headers = [(k.lower().encode(), v.encode()) for k, v in (("host", host_header), *request.headers.items())]
-
- return {
- "type": "websocket" if scheme in {"ws", "wss"} else "http",
- "path": unquote(path),
- "raw_path": raw_path,
- "root_path": self.root_path,
- "scheme": scheme,
- "query_string": query.encode(),
- "headers": headers,
- "client": ("testclient", 50000),
- "server": (host, port),
- }
-
- def handle_request(self, request: Request) -> Response:
- scope = self.parse_request(request=request)
- if scope["type"] == "websocket":
- scope.update(
- subprotocols=[value.strip() for value in request.headers.get("sec-websocket-protocol", "").split(",")]
- )
- session = WebSocketTestSession(client=self.client, scope=cast("WebSocketScope", scope)) # type: ignore[arg-type]
- raise ConnectionUpgradeExceptionError(session)
-
- scope.update(method=request.method, http_version="1.1", extensions={"http.response.template": {}})
-
- raw_kwargs: dict[str, Any] = {"stream": BytesIO()}
-
- try:
- with self.client.portal() as portal:
- response_complete = portal.call(Event)
- context: SendReceiveContext = {
- "response_complete": response_complete,
- "request_complete": False,
- "raw_kwargs": raw_kwargs,
- "response_started": False,
- "template": None,
- "context": None,
- }
- portal.call(
- self.client.app,
- scope,
- self.create_receive(request=request, context=context),
- self.create_send(request=request, context=context),
- )
- except BaseException as exc: # noqa: BLE001
- if self.raise_server_exceptions:
- raise exc
- return Response(
- status_code=HTTP_500_INTERNAL_SERVER_ERROR, headers=[], stream=ByteStream(b""), request=request
- )
- else:
- if not context["response_started"]: # pragma: no cover
- if self.raise_server_exceptions:
- assert context["response_started"], "TestClient did not receive any response." # noqa: S101
- return Response(
- status_code=HTTP_500_INTERNAL_SERVER_ERROR, headers=[], stream=ByteStream(b""), request=request
- )
-
- stream = ByteStream(raw_kwargs.pop("stream", BytesIO()).read())
- response = Response(**raw_kwargs, stream=stream, request=request)
- setattr(response, "template", context["template"])
- setattr(response, "context", context["context"])
- return response
-
- async def handle_async_request(self, request: Request) -> Response:
- return self.handle_request(request=request)
diff --git a/venv/lib/python3.11/site-packages/litestar/testing/websocket_test_session.py b/venv/lib/python3.11/site-packages/litestar/testing/websocket_test_session.py
deleted file mode 100644
index 292e8a9..0000000
--- a/venv/lib/python3.11/site-packages/litestar/testing/websocket_test_session.py
+++ /dev/null
@@ -1,248 +0,0 @@
-from __future__ import annotations
-
-from contextlib import ExitStack
-from queue import Queue
-from typing import TYPE_CHECKING, Any, Literal, cast
-
-from anyio import sleep
-
-from litestar.exceptions import WebSocketDisconnect
-from litestar.serialization import decode_json, decode_msgpack, encode_json, encode_msgpack
-from litestar.status_codes import WS_1000_NORMAL_CLOSURE
-
-if TYPE_CHECKING:
- from litestar.testing.client.sync_client import TestClient
- from litestar.types import (
- WebSocketConnectEvent,
- WebSocketDisconnectEvent,
- WebSocketReceiveMessage,
- WebSocketScope,
- WebSocketSendMessage,
- )
-
-
-__all__ = ("WebSocketTestSession",)
-
-
-class WebSocketTestSession:
- exit_stack: ExitStack
-
- def __init__(
- self,
- client: TestClient[Any],
- scope: WebSocketScope,
- ) -> None:
- self.client = client
- self.scope = scope
- self.accepted_subprotocol: str | None = None
- self.receive_queue: Queue[WebSocketReceiveMessage] = Queue()
- self.send_queue: Queue[WebSocketSendMessage | BaseException] = Queue()
- self.extra_headers: list[tuple[bytes, bytes]] | None = None
-
- def __enter__(self) -> WebSocketTestSession:
- self.exit_stack = ExitStack()
-
- portal = self.exit_stack.enter_context(self.client.portal())
-
- try:
- portal.start_task_soon(self.do_asgi_call)
- event: WebSocketConnectEvent = {"type": "websocket.connect"}
- self.receive_queue.put(event)
-
- message = self.receive(timeout=self.client.timeout.read)
- self.accepted_subprotocol = cast("str | None", message.get("subprotocol", None))
- self.extra_headers = cast("list[tuple[bytes, bytes]] | None", message.get("headers", None))
- return self
- except Exception:
- self.exit_stack.close()
- raise
-
- def __exit__(self, *args: Any) -> None:
- try:
- self.close()
- finally:
- self.exit_stack.close()
- while not self.send_queue.empty():
- message = self.send_queue.get()
- if isinstance(message, BaseException):
- raise message
-
- async def do_asgi_call(self) -> None:
- """The sub-thread in which the websocket session runs."""
-
- async def receive() -> WebSocketReceiveMessage:
- while self.receive_queue.empty():
- await sleep(0)
- return self.receive_queue.get()
-
- async def send(message: WebSocketSendMessage) -> None:
- if message["type"] == "websocket.accept":
- headers = message.get("headers", [])
- if headers:
- headers_list = list(self.scope["headers"])
- headers_list.extend(headers)
- self.scope["headers"] = headers_list
- subprotocols = cast("str | None", message.get("subprotocols"))
- if subprotocols: # pragma: no cover
- self.scope["subprotocols"].append(subprotocols)
- self.send_queue.put(message)
-
- try:
- await self.client.app(self.scope, receive, send)
- except BaseException as exc:
- self.send_queue.put(exc)
- raise
-
- def send(self, data: str | bytes, mode: Literal["text", "binary"] = "text", encoding: str = "utf-8") -> None:
- """Sends a "receive" event. This is the inverse of the ASGI send method.
-
- Args:
- data: Either a string or a byte string.
- mode: The key to use - ``text`` or ``bytes``
- encoding: The encoding to use when encoding or decoding data.
-
- Returns:
- None.
- """
- if mode == "text":
- data = data.decode(encoding) if isinstance(data, bytes) else data
- text_event: WebSocketReceiveMessage = {"type": "websocket.receive", "text": data} # type: ignore[assignment]
- self.receive_queue.put(text_event)
- else:
- data = data if isinstance(data, bytes) else data.encode(encoding)
- binary_event: WebSocketReceiveMessage = {"type": "websocket.receive", "bytes": data} # type: ignore[assignment]
- self.receive_queue.put(binary_event)
-
- def send_text(self, data: str, encoding: str = "utf-8") -> None:
- """Sends the data using the ``text`` key.
-
- Args:
- data: Data to send.
- encoding: Encoding to use.
-
- Returns:
- None
- """
- self.send(data=data, encoding=encoding)
-
- def send_bytes(self, data: bytes, encoding: str = "utf-8") -> None:
- """Sends the data using the ``bytes`` key.
-
- Args:
- data: Data to send.
- encoding: Encoding to use.
-
- Returns:
- None
- """
- self.send(data=data, mode="binary", encoding=encoding)
-
- def send_json(self, data: Any, mode: Literal["text", "binary"] = "text") -> None:
- """Sends the given data as JSON.
-
- Args:
- data: The data to send.
- mode: Either ``text`` or ``binary``
-
- Returns:
- None
- """
- self.send(encode_json(data), mode=mode)
-
- def send_msgpack(self, data: Any) -> None:
- """Sends the given data as MessagePack.
-
- Args:
- data: The data to send.
-
- Returns:
- None
- """
- self.send(encode_msgpack(data), mode="binary")
-
- def close(self, code: int = WS_1000_NORMAL_CLOSURE) -> None:
- """Sends an 'websocket.disconnect' event.
-
- Args:
- code: status code for closing the connection.
-
- Returns:
- None.
- """
- event: WebSocketDisconnectEvent = {"type": "websocket.disconnect", "code": code}
- self.receive_queue.put(event)
-
- def receive(self, block: bool = True, timeout: float | None = None) -> WebSocketSendMessage:
- """This is the base receive method.
-
- Args:
- block: Block until a message is received
- timeout: If ``block`` is ``True``, block at most ``timeout`` seconds
-
- Notes:
- - you can use one of the other receive methods to extract the data from the message.
-
- Returns:
- A websocket message.
- """
- message = cast("WebSocketSendMessage", self.send_queue.get(block=block, timeout=timeout))
-
- if isinstance(message, BaseException):
- raise message
-
- if message["type"] == "websocket.close":
- raise WebSocketDisconnect(
- detail=cast("str", message.get("reason", "")),
- code=message.get("code", WS_1000_NORMAL_CLOSURE),
- )
- return message
-
- def receive_text(self, block: bool = True, timeout: float | None = None) -> str:
- """Receive data in ``text`` mode and return a string
-
- Args:
- block: Block until a message is received
- timeout: If ``block`` is ``True``, block at most ``timeout`` seconds
-
- Returns:
- A string value.
- """
- message = self.receive(block=block, timeout=timeout)
- return cast("str", message.get("text", ""))
-
- def receive_bytes(self, block: bool = True, timeout: float | None = None) -> bytes:
- """Receive data in ``binary`` mode and return bytes
-
- Args:
- block: Block until a message is received
- timeout: If ``block`` is ``True``, block at most ``timeout`` seconds
-
- Returns:
- A string value.
- """
- message = self.receive(block=block, timeout=timeout)
- return cast("bytes", message.get("bytes", b""))
-
- def receive_json(
- self, mode: Literal["text", "binary"] = "text", block: bool = True, timeout: float | None = None
- ) -> Any:
- """Receive data in either ``text`` or ``binary`` mode and decode it as JSON.
-
- Args:
- mode: Either ``text`` or ``binary``
- block: Block until a message is received
- timeout: If ``block`` is ``True``, block at most ``timeout`` seconds
-
- Returns:
- An arbitrary value
- """
- message = self.receive(block=block, timeout=timeout)
-
- if mode == "text":
- return decode_json(cast("str", message.get("text", "")))
-
- return decode_json(cast("bytes", message.get("bytes", b"")))
-
- def receive_msgpack(self, block: bool = True, timeout: float | None = None) -> Any:
- message = self.receive(block=block, timeout=timeout)
- return decode_msgpack(cast("bytes", message.get("bytes", b"")))
diff --git a/venv/lib/python3.11/site-packages/litestar/types/__init__.py b/venv/lib/python3.11/site-packages/litestar/types/__init__.py
deleted file mode 100644
index 90e3192..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/__init__.py
+++ /dev/null
@@ -1,169 +0,0 @@
-from .asgi_types import (
- ASGIApp,
- ASGIVersion,
- BaseScope,
- HTTPDisconnectEvent,
- HTTPReceiveMessage,
- HTTPRequestEvent,
- HTTPResponseBodyEvent,
- HTTPResponseStartEvent,
- HTTPScope,
- HTTPSendMessage,
- HTTPServerPushEvent,
- LifeSpanReceive,
- LifeSpanReceiveMessage,
- LifeSpanScope,
- LifeSpanSend,
- LifeSpanSendMessage,
- LifeSpanShutdownCompleteEvent,
- LifeSpanShutdownEvent,
- LifeSpanShutdownFailedEvent,
- LifeSpanStartupCompleteEvent,
- LifeSpanStartupEvent,
- LifeSpanStartupFailedEvent,
- Message,
- Method,
- Receive,
- ReceiveMessage,
- Scope,
- ScopeSession,
- Send,
- WebSocketAcceptEvent,
- WebSocketCloseEvent,
- WebSocketConnectEvent,
- WebSocketDisconnectEvent,
- WebSocketReceiveEvent,
- WebSocketReceiveMessage,
- WebSocketResponseBodyEvent,
- WebSocketResponseStartEvent,
- WebSocketScope,
- WebSocketSendEvent,
- WebSocketSendMessage,
-)
-from .builtin_types import TypedDictClass
-from .callable_types import (
- AfterExceptionHookHandler,
- AfterRequestHookHandler,
- AfterResponseHookHandler,
- AnyCallable,
- AnyGenerator,
- AsyncAnyCallable,
- BeforeMessageSendHookHandler,
- BeforeRequestHookHandler,
- CacheKeyBuilder,
- ExceptionHandler,
- GetLogger,
- Guard,
- LifespanHook,
- OnAppInitHandler,
- OperationIDCreator,
- Serializer,
-)
-from .composite_types import (
- Dependencies,
- ExceptionHandlersMap,
- Middleware,
- ParametersMap,
- PathType,
- ResponseCookies,
- ResponseHeaders,
- Scopes,
- TypeDecodersSequence,
- TypeEncodersMap,
-)
-from .empty import Empty, EmptyType
-from .file_types import FileInfo, FileSystemProtocol
-from .helper_types import AnyIOBackend, MaybePartial, OptionalSequence, SSEData, StreamType, SyncOrAsyncUnion
-from .internal_types import ControllerRouterHandler, ReservedKwargs, RouteHandlerMapItem, RouteHandlerType
-from .protocols import DataclassProtocol, Logger
-from .serialization import DataContainerType, LitestarEncodableType
-
-__all__ = (
- "ASGIApp",
- "ASGIVersion",
- "AfterExceptionHookHandler",
- "AfterRequestHookHandler",
- "AfterResponseHookHandler",
- "AnyCallable",
- "AnyGenerator",
- "AnyIOBackend",
- "AsyncAnyCallable",
- "BaseScope",
- "BeforeMessageSendHookHandler",
- "BeforeRequestHookHandler",
- "CacheKeyBuilder",
- "ControllerRouterHandler",
- "DataContainerType",
- "DataclassProtocol",
- "Dependencies",
- "Empty",
- "EmptyType",
- "ExceptionHandler",
- "ExceptionHandlersMap",
- "FileInfo",
- "FileSystemProtocol",
- "GetLogger",
- "Guard",
- "HTTPDisconnectEvent",
- "HTTPReceiveMessage",
- "HTTPRequestEvent",
- "HTTPResponseBodyEvent",
- "HTTPResponseStartEvent",
- "HTTPScope",
- "HTTPSendMessage",
- "HTTPServerPushEvent",
- "LifeSpanReceive",
- "LifeSpanReceiveMessage",
- "LifeSpanScope",
- "LifeSpanSend",
- "LifeSpanSendMessage",
- "LifeSpanShutdownCompleteEvent",
- "LifeSpanShutdownEvent",
- "LifeSpanShutdownFailedEvent",
- "LifeSpanStartupCompleteEvent",
- "LifeSpanStartupEvent",
- "LifeSpanStartupFailedEvent",
- "LifespanHook",
- "LitestarEncodableType",
- "Logger",
- "MaybePartial",
- "Message",
- "Method",
- "Middleware",
- "OnAppInitHandler",
- "OperationIDCreator",
- "OptionalSequence",
- "ParametersMap",
- "PathType",
- "Receive",
- "ReceiveMessage",
- "ReservedKwargs",
- "ResponseCookies",
- "ResponseHeaders",
- "RouteHandlerMapItem",
- "RouteHandlerType",
- "Scope",
- "ScopeSession",
- "Scopes",
- "Send",
- "Serializer",
- "StreamType",
- "SSEData",
- "SyncOrAsyncUnion",
- "TypeDecodersSequence",
- "TypeEncodersMap",
- "TypedDictClass",
- "WebSocketAcceptEvent",
- "WebSocketCloseEvent",
- "WebSocketConnectEvent",
- "WebSocketDisconnectEvent",
- "WebSocketReceiveEvent",
- "WebSocketReceiveMessage",
- "WebSocketReceiveMessage",
- "WebSocketResponseBodyEvent",
- "WebSocketResponseStartEvent",
- "WebSocketScope",
- "WebSocketSendEvent",
- "WebSocketSendMessage",
- "WebSocketSendMessage",
-)
diff --git a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/types/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index 6f64e92..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/asgi_types.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/types/__pycache__/asgi_types.cpython-311.pyc
deleted file mode 100644
index cbed524..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/asgi_types.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/builtin_types.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/types/__pycache__/builtin_types.cpython-311.pyc
deleted file mode 100644
index 42a633c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/builtin_types.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/callable_types.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/types/__pycache__/callable_types.cpython-311.pyc
deleted file mode 100644
index e956ed6..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/callable_types.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/composite_types.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/types/__pycache__/composite_types.cpython-311.pyc
deleted file mode 100644
index 4761e1c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/composite_types.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/empty.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/types/__pycache__/empty.cpython-311.pyc
deleted file mode 100644
index 1ce4b48..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/empty.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/file_types.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/types/__pycache__/file_types.cpython-311.pyc
deleted file mode 100644
index c2a5ffd..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/file_types.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/helper_types.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/types/__pycache__/helper_types.cpython-311.pyc
deleted file mode 100644
index e0ee6eb..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/helper_types.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/internal_types.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/types/__pycache__/internal_types.cpython-311.pyc
deleted file mode 100644
index 8d0ac7e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/internal_types.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/protocols.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/types/__pycache__/protocols.cpython-311.pyc
deleted file mode 100644
index 1caf78a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/protocols.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/serialization.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/types/__pycache__/serialization.cpython-311.pyc
deleted file mode 100644
index 3bd8dc5..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/__pycache__/serialization.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/types/asgi_types.py b/venv/lib/python3.11/site-packages/litestar/types/asgi_types.py
deleted file mode 100644
index 0a6f77f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/asgi_types.py
+++ /dev/null
@@ -1,343 +0,0 @@
-"""Includes code adapted from https://github.com/django/asgiref/blob/main/asgiref/typing.py.
-
-Copyright (c) Django Software Foundation and individual contributors.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- 3. Neither the name of Django nor the names of its contributors may be used
- to endorse or promote products derived from this software without
- specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-"""
-
-from __future__ import annotations
-
-from typing import (
- TYPE_CHECKING,
- Any,
- Awaitable,
- Callable,
- Dict,
- Iterable,
- List,
- Literal,
- Tuple,
- TypedDict,
- Union,
-)
-
-from litestar.enums import HttpMethod
-
-__all__ = (
- "ASGIApp",
- "ASGIVersion",
- "BaseScope",
- "HeaderScope",
- "HTTPDisconnectEvent",
- "HTTPReceiveMessage",
- "HTTPRequestEvent",
- "HTTPResponseBodyEvent",
- "HTTPResponseStartEvent",
- "HTTPScope",
- "HTTPSendMessage",
- "HTTPServerPushEvent",
- "LifeSpanReceive",
- "LifeSpanReceiveMessage",
- "LifeSpanScope",
- "LifeSpanSend",
- "LifeSpanSendMessage",
- "LifeSpanShutdownCompleteEvent",
- "LifeSpanShutdownEvent",
- "LifeSpanShutdownFailedEvent",
- "LifeSpanStartupCompleteEvent",
- "LifeSpanStartupEvent",
- "LifeSpanStartupFailedEvent",
- "Message",
- "Method",
- "RawHeaders",
- "RawHeadersList",
- "Receive",
- "ReceiveMessage",
- "Scope",
- "ScopeSession",
- "Send",
- "WebSocketAcceptEvent",
- "WebSocketCloseEvent",
- "WebSocketConnectEvent",
- "WebSocketDisconnectEvent",
- "WebSocketMode",
- "WebSocketReceiveEvent",
- "WebSocketReceiveMessage",
- "WebSocketResponseBodyEvent",
- "WebSocketResponseStartEvent",
- "WebSocketScope",
- "WebSocketSendEvent",
- "WebSocketSendMessage",
-)
-
-if TYPE_CHECKING:
- from typing_extensions import TypeAlias
-
- from litestar.app import Litestar
- from litestar.enums import ScopeType
- from litestar.types.empty import EmptyType
-
- from .internal_types import RouteHandlerType
- from .serialization import DataContainerType
-
-Method: TypeAlias = Union[Literal["GET", "POST", "DELETE", "PATCH", "PUT", "HEAD", "TRACE", "OPTIONS"], HttpMethod]
-ScopeSession: TypeAlias = "EmptyType | Dict[str, Any] | DataContainerType | None"
-
-
-class ASGIVersion(TypedDict):
- """ASGI spec version."""
-
- spec_version: str
- version: Literal["3.0"]
-
-
-class HeaderScope(TypedDict):
- """Base class for ASGI-scopes that supports headers."""
-
- headers: RawHeaders
-
-
-class BaseScope(HeaderScope):
- """Base ASGI-scope."""
-
- app: Litestar
- asgi: ASGIVersion
- auth: Any
- client: tuple[str, int] | None
- extensions: dict[str, dict[object, object]] | None
- http_version: str
- path: str
- path_params: dict[str, str]
- query_string: bytes
- raw_path: bytes
- root_path: str
- route_handler: RouteHandlerType
- scheme: str
- server: tuple[str, int | None] | None
- session: ScopeSession
- state: dict[str, Any]
- user: Any
-
-
-class HTTPScope(BaseScope):
- """HTTP-ASGI-scope."""
-
- method: Method
- type: Literal[ScopeType.HTTP]
-
-
-class WebSocketScope(BaseScope):
- """WebSocket-ASGI-scope."""
-
- subprotocols: list[str]
- type: Literal[ScopeType.WEBSOCKET]
-
-
-class LifeSpanScope(TypedDict):
- """Lifespan-ASGI-scope."""
-
- app: Litestar
- asgi: ASGIVersion
- type: Literal["lifespan"]
-
-
-class HTTPRequestEvent(TypedDict):
- """ASGI `http.request` event."""
-
- type: Literal["http.request"]
- body: bytes
- more_body: bool
-
-
-class HTTPResponseStartEvent(HeaderScope):
- """ASGI `http.response.start` event."""
-
- type: Literal["http.response.start"]
- status: int
-
-
-class HTTPResponseBodyEvent(TypedDict):
- """ASGI `http.response.body` event."""
-
- type: Literal["http.response.body"]
- body: bytes
- more_body: bool
-
-
-class HTTPServerPushEvent(HeaderScope):
- """ASGI `http.response.push` event."""
-
- type: Literal["http.response.push"]
- path: str
-
-
-class HTTPDisconnectEvent(TypedDict):
- """ASGI `http.disconnect` event."""
-
- type: Literal["http.disconnect"]
-
-
-class WebSocketConnectEvent(TypedDict):
- """ASGI `websocket.connect` event."""
-
- type: Literal["websocket.connect"]
-
-
-class WebSocketAcceptEvent(HeaderScope):
- """ASGI `websocket.accept` event."""
-
- type: Literal["websocket.accept"]
- subprotocol: str | None
-
-
-class WebSocketReceiveEvent(TypedDict):
- """ASGI `websocket.receive` event."""
-
- type: Literal["websocket.receive"]
- bytes: bytes | None
- text: str | None
-
-
-class WebSocketSendEvent(TypedDict):
- """ASGI `websocket.send` event."""
-
- type: Literal["websocket.send"]
- bytes: bytes | None
- text: str | None
-
-
-class WebSocketResponseStartEvent(HeaderScope):
- """ASGI `websocket.http.response.start` event."""
-
- type: Literal["websocket.http.response.start"]
- status: int
-
-
-class WebSocketResponseBodyEvent(TypedDict):
- """ASGI `websocket.http.response.body` event."""
-
- type: Literal["websocket.http.response.body"]
- body: bytes
- more_body: bool
-
-
-class WebSocketDisconnectEvent(TypedDict):
- """ASGI `websocket.disconnect` event."""
-
- type: Literal["websocket.disconnect"]
- code: int
-
-
-class WebSocketCloseEvent(TypedDict):
- """ASGI `websocket.close` event."""
-
- type: Literal["websocket.close"]
- code: int
- reason: str | None
-
-
-class LifeSpanStartupEvent(TypedDict):
- """ASGI `lifespan.startup` event."""
-
- type: Literal["lifespan.startup"]
-
-
-class LifeSpanShutdownEvent(TypedDict):
- """ASGI `lifespan.shutdown` event."""
-
- type: Literal["lifespan.shutdown"]
-
-
-class LifeSpanStartupCompleteEvent(TypedDict):
- """ASGI `lifespan.startup.complete` event."""
-
- type: Literal["lifespan.startup.complete"]
-
-
-class LifeSpanStartupFailedEvent(TypedDict):
- """ASGI `lifespan.startup.failed` event."""
-
- type: Literal["lifespan.startup.failed"]
- message: str
-
-
-class LifeSpanShutdownCompleteEvent(TypedDict):
- """ASGI `lifespan.shutdown.complete` event."""
-
- type: Literal["lifespan.shutdown.complete"]
-
-
-class LifeSpanShutdownFailedEvent(TypedDict):
- """ASGI `lifespan.shutdown.failed` event."""
-
- type: Literal["lifespan.shutdown.failed"]
- message: str
-
-
-HTTPReceiveMessage: TypeAlias = Union[
- HTTPRequestEvent,
- HTTPDisconnectEvent,
-]
-WebSocketReceiveMessage: TypeAlias = Union[
- WebSocketConnectEvent,
- WebSocketReceiveEvent,
- WebSocketDisconnectEvent,
-]
-LifeSpanReceiveMessage: TypeAlias = Union[
- LifeSpanStartupEvent,
- LifeSpanShutdownEvent,
-]
-HTTPSendMessage: TypeAlias = Union[
- HTTPResponseStartEvent,
- HTTPResponseBodyEvent,
- HTTPServerPushEvent,
- HTTPDisconnectEvent,
-]
-WebSocketSendMessage: TypeAlias = Union[
- WebSocketAcceptEvent,
- WebSocketSendEvent,
- WebSocketResponseStartEvent,
- WebSocketResponseBodyEvent,
- WebSocketCloseEvent,
-]
-LifeSpanSendMessage: TypeAlias = Union[
- LifeSpanStartupCompleteEvent,
- LifeSpanStartupFailedEvent,
- LifeSpanShutdownCompleteEvent,
- LifeSpanShutdownFailedEvent,
-]
-LifeSpanReceive: TypeAlias = Callable[..., Awaitable[LifeSpanReceiveMessage]]
-LifeSpanSend: TypeAlias = Callable[[LifeSpanSendMessage], Awaitable[None]]
-Message: TypeAlias = Union[HTTPSendMessage, WebSocketSendMessage]
-ReceiveMessage: TypeAlias = Union[HTTPReceiveMessage, WebSocketReceiveMessage]
-Scope: TypeAlias = Union[HTTPScope, WebSocketScope]
-Receive: TypeAlias = Callable[..., Awaitable[Union[HTTPReceiveMessage, WebSocketReceiveMessage]]]
-Send: TypeAlias = Callable[[Message], Awaitable[None]]
-ASGIApp: TypeAlias = Callable[[Scope, Receive, Send], Awaitable[None]]
-RawHeaders: TypeAlias = Iterable[Tuple[bytes, bytes]]
-RawHeadersList: TypeAlias = List[Tuple[bytes, bytes]]
-WebSocketMode: TypeAlias = Literal["text", "binary"]
diff --git a/venv/lib/python3.11/site-packages/litestar/types/builtin_types.py b/venv/lib/python3.11/site-packages/litestar/types/builtin_types.py
deleted file mode 100644
index 335dedd..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/builtin_types.py
+++ /dev/null
@@ -1,25 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Type, Union
-
-from typing_extensions import _TypedDictMeta # type: ignore[attr-defined]
-
-if TYPE_CHECKING:
- from typing_extensions import TypeAlias
-
-__all__ = (
- "NoneType",
- "UnionType",
- "UnionTypes",
- "TypedDictClass",
-)
-
-NoneType: type[None] = type(None)
-
-try:
- from types import UnionType # type: ignore[attr-defined]
-except ImportError:
- UnionType: TypeAlias = Union # type: ignore[no-redef]
-
-UnionTypes = {UnionType, Union}
-TypedDictClass: TypeAlias = Type[_TypedDictMeta]
diff --git a/venv/lib/python3.11/site-packages/litestar/types/callable_types.py b/venv/lib/python3.11/site-packages/litestar/types/callable_types.py
deleted file mode 100644
index 36055d7..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/callable_types.py
+++ /dev/null
@@ -1,40 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any, AsyncGenerator, Awaitable, Callable, Generator, TypeVar
-
-if TYPE_CHECKING:
- from typing_extensions import TypeAlias
-
- from litestar.app import Litestar
- from litestar.config.app import AppConfig
- from litestar.connection.base import ASGIConnection
- from litestar.connection.request import Request
- from litestar.handlers.base import BaseRouteHandler
- from litestar.handlers.http_handlers import HTTPRouteHandler
- from litestar.response.base import Response
- from litestar.types.asgi_types import ASGIApp, Message, Method, Scope
- from litestar.types.helper_types import SyncOrAsyncUnion
- from litestar.types.internal_types import PathParameterDefinition
- from litestar.types.protocols import Logger
-
-ExceptionT = TypeVar("ExceptionT", bound=Exception)
-
-AfterExceptionHookHandler: TypeAlias = "Callable[[ExceptionT, Scope], SyncOrAsyncUnion[None]]"
-AfterRequestHookHandler: TypeAlias = (
- "Callable[[ASGIApp], SyncOrAsyncUnion[ASGIApp]] | Callable[[Response], SyncOrAsyncUnion[Response]]"
-)
-AfterResponseHookHandler: TypeAlias = "Callable[[Request], SyncOrAsyncUnion[None]]"
-AsyncAnyCallable: TypeAlias = Callable[..., Awaitable[Any]]
-AnyCallable: TypeAlias = Callable[..., Any]
-AnyGenerator: TypeAlias = "Generator[Any, Any, Any] | AsyncGenerator[Any, Any]"
-BeforeMessageSendHookHandler: TypeAlias = "Callable[[Message, Scope], SyncOrAsyncUnion[None]]"
-BeforeRequestHookHandler: TypeAlias = "Callable[[Request], Any | Awaitable[Any]]"
-CacheKeyBuilder: TypeAlias = "Callable[[Request], str]"
-ExceptionHandler: TypeAlias = "Callable[[Request, ExceptionT], Response]"
-ExceptionLoggingHandler: TypeAlias = "Callable[[Logger, Scope, list[str]], None]"
-GetLogger: TypeAlias = "Callable[..., Logger]"
-Guard: TypeAlias = "Callable[[ASGIConnection, BaseRouteHandler], SyncOrAsyncUnion[None]]"
-LifespanHook: TypeAlias = "Callable[[Litestar], SyncOrAsyncUnion[Any]] | Callable[[], SyncOrAsyncUnion[Any]]"
-OnAppInitHandler: TypeAlias = "Callable[[AppConfig], AppConfig]"
-OperationIDCreator: TypeAlias = "Callable[[HTTPRouteHandler, Method, list[str | PathParameterDefinition]], str]"
-Serializer: TypeAlias = Callable[[Any], Any]
diff --git a/venv/lib/python3.11/site-packages/litestar/types/composite_types.py b/venv/lib/python3.11/site-packages/litestar/types/composite_types.py
deleted file mode 100644
index afd905f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/composite_types.py
+++ /dev/null
@@ -1,56 +0,0 @@
-from __future__ import annotations
-
-from typing import (
- TYPE_CHECKING,
- Any,
- Callable,
- Dict,
- Iterator,
- Literal,
- Mapping,
- MutableMapping,
- Sequence,
- Tuple,
- Type,
- Union,
-)
-
-__all__ = (
- "Dependencies",
- "ExceptionHandlersMap",
- "Middleware",
- "ParametersMap",
- "PathType",
- "ResponseCookies",
- "ResponseHeaders",
- "Scopes",
- "TypeEncodersMap",
-)
-
-
-if TYPE_CHECKING:
- from os import PathLike
- from pathlib import Path
-
- from typing_extensions import TypeAlias
-
- from litestar.datastructures.cookie import Cookie
- from litestar.datastructures.response_header import ResponseHeader
- from litestar.di import Provide
- from litestar.enums import ScopeType
- from litestar.middleware.base import DefineMiddleware, MiddlewareProtocol
- from litestar.params import ParameterKwarg
-
- from .asgi_types import ASGIApp
- from .callable_types import AnyCallable, ExceptionHandler
-
-Dependencies: TypeAlias = "Mapping[str, Union[Provide, AnyCallable]]"
-ExceptionHandlersMap: TypeAlias = "MutableMapping[Union[int, Type[Exception]], ExceptionHandler]"
-Middleware: TypeAlias = "Union[Callable[..., ASGIApp], DefineMiddleware, Iterator[Tuple[ASGIApp, Dict[str, Any]]], Type[MiddlewareProtocol]]"
-ParametersMap: TypeAlias = "Mapping[str, ParameterKwarg]"
-PathType: TypeAlias = "Union[Path, PathLike, str]"
-ResponseCookies: TypeAlias = "Union[Sequence[Cookie], Mapping[str, str]]"
-ResponseHeaders: TypeAlias = "Union[Sequence[ResponseHeader], Mapping[str, str]]"
-Scopes: TypeAlias = "set[Literal[ScopeType.HTTP, ScopeType.WEBSOCKET]]"
-TypeDecodersSequence: TypeAlias = "Sequence[tuple[Callable[[Any], bool], Callable[[Any, Any], Any]]]"
-TypeEncodersMap: TypeAlias = "Mapping[Any, Callable[[Any], Any]]"
diff --git a/venv/lib/python3.11/site-packages/litestar/types/empty.py b/venv/lib/python3.11/site-packages/litestar/types/empty.py
deleted file mode 100644
index dee9bc1..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/empty.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from __future__ import annotations
-
-__all__ = ("Empty", "EmptyType")
-
-from enum import Enum
-from typing import Final, Literal
-
-
-class _EmptyEnum(Enum):
- """A sentinel enum used as placeholder."""
-
- EMPTY = 0
-
-
-EmptyType = Literal[_EmptyEnum.EMPTY]
-Empty: Final = _EmptyEnum.EMPTY
diff --git a/venv/lib/python3.11/site-packages/litestar/types/file_types.py b/venv/lib/python3.11/site-packages/litestar/types/file_types.py
deleted file mode 100644
index 7848721..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/file_types.py
+++ /dev/null
@@ -1,106 +0,0 @@
-from __future__ import annotations
-
-from typing import (
- IO,
- TYPE_CHECKING,
- Any,
- AnyStr,
- Awaitable,
- Literal,
- Protocol,
- TypedDict,
- overload,
-)
-
-__all__ = ("FileInfo", "FileSystemProtocol")
-
-
-if TYPE_CHECKING:
- from _typeshed import OpenBinaryMode, OpenTextMode
- from anyio import AsyncFile
- from typing_extensions import NotRequired
-
- from litestar.types.composite_types import PathType
-
-
-class FileInfo(TypedDict):
- """File information gathered from a file system."""
-
- created: float
- """Created time stamp, equal to 'stat_result.st_ctime'."""
- destination: NotRequired[bytes | None]
- """Output of loading a symbolic link."""
- gid: int
- """Group ID of owner."""
- ino: int
- """inode value."""
- islink: bool
- """True if the file is a symbolic link."""
- mode: int
- """Protection mode."""
- mtime: float
- """Modified time stamp."""
- name: str
- """The path of the file."""
- nlink: int
- """Number of hard links."""
- size: int
- """Total size, in bytes."""
- type: Literal["file", "directory", "other"]
- """The type of the file system object."""
- uid: int
- """User ID of owner."""
-
-
-class FileSystemProtocol(Protocol):
- """Base protocol used to interact with a file-system.
-
- This protocol is commensurable with the file systems
- exported by the `fsspec <https://filesystem-spec.readthedocs.io/en/latest/>` library.
- """
-
- def info(self, path: PathType, **kwargs: Any) -> FileInfo | Awaitable[FileInfo]:
- """Retrieve information about a given file path.
-
- Args:
- path: A file path.
- **kwargs: Any additional kwargs.
-
- Returns:
- A dictionary of file info.
- """
- ...
-
- @overload
- def open(
- self,
- file: PathType,
- mode: OpenBinaryMode,
- buffering: int = -1,
- ) -> IO[bytes] | Awaitable[AsyncFile[bytes]]: ...
-
- @overload
- def open(
- self,
- file: PathType,
- mode: OpenTextMode,
- buffering: int = -1,
- ) -> IO[str] | Awaitable[AsyncFile[str]]: ...
-
- def open( # pyright: ignore
- self,
- file: PathType,
- mode: str,
- buffering: int = -1,
- ) -> IO[AnyStr] | Awaitable[AsyncFile[AnyStr]]:
- """Return a file-like object from the filesystem.
-
- Notes:
- - The return value must function correctly in a context ``with`` block.
-
- Args:
- file: Path to the target file.
- mode: Mode, similar to the built ``open``.
- buffering: Buffer size.
- """
- ...
diff --git a/venv/lib/python3.11/site-packages/litestar/types/helper_types.py b/venv/lib/python3.11/site-packages/litestar/types/helper_types.py
deleted file mode 100644
index 588ae54..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/helper_types.py
+++ /dev/null
@@ -1,47 +0,0 @@
-from __future__ import annotations
-
-from functools import partial
-from typing import (
- TYPE_CHECKING,
- Any,
- AsyncIterable,
- AsyncIterator,
- Awaitable,
- Dict,
- Iterable,
- Iterator,
- Literal,
- Optional,
- Sequence,
- TypeVar,
- Union,
-)
-
-if TYPE_CHECKING:
- from typing_extensions import TypeAlias
-
- from litestar.response.sse import ServerSentEventMessage
-
-
-T = TypeVar("T")
-
-__all__ = ("OptionalSequence", "SyncOrAsyncUnion", "AnyIOBackend", "StreamType", "MaybePartial", "SSEData")
-
-OptionalSequence: TypeAlias = Optional[Sequence[T]]
-"""Types 'T' as union of Sequence[T] and None."""
-
-SyncOrAsyncUnion: TypeAlias = Union[T, Awaitable[T]]
-"""Types 'T' as a union of T and awaitable T."""
-
-
-AnyIOBackend: TypeAlias = Literal["asyncio", "trio"]
-"""Anyio backend names."""
-
-StreamType: TypeAlias = Union[Iterable[T], Iterator[T], AsyncIterable[T], AsyncIterator[T]]
-"""A stream type."""
-
-MaybePartial: TypeAlias = Union[T, partial]
-"""A potentially partial callable."""
-
-SSEData: TypeAlias = Union[int, str, bytes, Dict[str, Any], "ServerSentEventMessage"]
-"""A type alias for SSE data."""
diff --git a/venv/lib/python3.11/site-packages/litestar/types/internal_types.py b/venv/lib/python3.11/site-packages/litestar/types/internal_types.py
deleted file mode 100644
index d473c22..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/internal_types.py
+++ /dev/null
@@ -1,58 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any, Callable, Literal, NamedTuple
-
-from litestar.utils.deprecation import warn_deprecation
-
-__all__ = (
- "ControllerRouterHandler",
- "PathParameterDefinition",
- "PathParameterDefinition",
- "ReservedKwargs",
- "RouteHandlerMapItem",
- "RouteHandlerType",
-)
-
-if TYPE_CHECKING:
- from typing_extensions import TypeAlias
-
- from litestar.app import Litestar
- from litestar.controller import Controller
- from litestar.handlers.asgi_handlers import ASGIRouteHandler
- from litestar.handlers.http_handlers import HTTPRouteHandler
- from litestar.handlers.websocket_handlers import WebsocketRouteHandler
- from litestar.router import Router
- from litestar.template import TemplateConfig
- from litestar.template.config import EngineType
- from litestar.types import Method
-
-ReservedKwargs: TypeAlias = Literal["request", "socket", "headers", "query", "cookies", "state", "data"]
-RouteHandlerType: TypeAlias = "HTTPRouteHandler | WebsocketRouteHandler | ASGIRouteHandler"
-ControllerRouterHandler: TypeAlias = "type[Controller] | RouteHandlerType | Router | Callable[..., Any]"
-RouteHandlerMapItem: TypeAlias = 'dict[Method | Literal["websocket", "asgi"], RouteHandlerType]'
-TemplateConfigType: TypeAlias = "TemplateConfig[EngineType]"
-
-# deprecated
-_LitestarType: TypeAlias = "Litestar"
-
-
-class PathParameterDefinition(NamedTuple):
- """Path parameter tuple."""
-
- name: str
- full: str
- type: type
- parser: Callable[[str], Any] | None
-
-
-def __getattr__(name: str) -> Any:
- if name == "LitestarType":
- warn_deprecation(
- "2.2.1",
- "LitestarType",
- "import",
- removal_in="3.0.0",
- alternative="Litestar",
- )
- return _LitestarType
- raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
diff --git a/venv/lib/python3.11/site-packages/litestar/types/protocols.py b/venv/lib/python3.11/site-packages/litestar/types/protocols.py
deleted file mode 100644
index 4e509ee..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/protocols.py
+++ /dev/null
@@ -1,113 +0,0 @@
-from __future__ import annotations
-
-from typing import Any, ClassVar, Collection, Iterable, Protocol, TypeVar, runtime_checkable
-
-__all__ = (
- "DataclassProtocol",
- "InstantiableCollection",
- "Logger",
-)
-
-
-class Logger(Protocol):
- """Logger protocol."""
-
- def debug(self, event: str, *args: Any, **kwargs: Any) -> Any:
- """Output a log message at 'DEBUG' level.
-
- Args:
- event: Log message.
- *args: Any args.
- **kwargs: Any kwargs.
- """
-
- def info(self, event: str, *args: Any, **kwargs: Any) -> Any:
- """Output a log message at 'INFO' level.
-
- Args:
- event: Log message.
- *args: Any args.
- **kwargs: Any kwargs.
- """
-
- def warning(self, event: str, *args: Any, **kwargs: Any) -> Any:
- """Output a log message at 'WARNING' level.
-
- Args:
- event: Log message.
- *args: Any args.
- **kwargs: Any kwargs.
- """
-
- def warn(self, event: str, *args: Any, **kwargs: Any) -> Any:
- """Output a log message at 'WARN' level.
-
- Args:
- event: Log message.
- *args: Any args.
- **kwargs: Any kwargs.
- """
-
- def error(self, event: str, *args: Any, **kwargs: Any) -> Any:
- """Output a log message at 'ERROR' level.
-
- Args:
- event: Log message.
- *args: Any args.
- **kwargs: Any kwargs.
- """
-
- def fatal(self, event: str, *args: Any, **kwargs: Any) -> Any:
- """Output a log message at 'FATAL' level.
-
- Args:
- event: Log message.
- *args: Any args.
- **kwargs: Any kwargs.
- """
-
- def exception(self, event: str, *args: Any, **kwargs: Any) -> Any:
- """Log a message with level 'ERROR' on this logger. The arguments are interpreted as for debug(). Exception info
- is added to the logging message.
-
- Args:
- event: Log message.
- *args: Any args.
- **kwargs: Any kwargs.
- """
-
- def critical(self, event: str, *args: Any, **kwargs: Any) -> Any:
- """Output a log message at 'INFO' level.
-
- Args:
- event: Log message.
- *args: Any args.
- **kwargs: Any kwargs.
- """
-
- def setLevel(self, level: int) -> None: # noqa: N802
- """Set the log level
-
- Args:
- level: Log level to set as an integer
-
- Returns:
- None
- """
-
-
-@runtime_checkable
-class DataclassProtocol(Protocol):
- """Protocol for instance checking dataclasses"""
-
- __dataclass_fields__: ClassVar[dict[str, Any]]
-
-
-T_co = TypeVar("T_co", covariant=True)
-
-
-@runtime_checkable
-class InstantiableCollection(Collection[T_co], Protocol[T_co]): # pyright: ignore
- """A protocol for instantiable collection types."""
-
- def __init__(self, iterable: Iterable[T_co], /) -> None: ...
diff --git a/venv/lib/python3.11/site-packages/litestar/types/serialization.py b/venv/lib/python3.11/site-packages/litestar/types/serialization.py
deleted file mode 100644
index 0f61e10..0000000
--- a/venv/lib/python3.11/site-packages/litestar/types/serialization.py
+++ /dev/null
@@ -1,59 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any
-
-if TYPE_CHECKING:
- from collections import deque
- from collections.abc import Collection
- from datetime import date, datetime, time
- from decimal import Decimal
- from enum import Enum, IntEnum
- from ipaddress import (
- IPv4Address,
- IPv4Interface,
- IPv4Network,
- IPv6Address,
- IPv6Interface,
- IPv6Network,
- )
- from pathlib import Path, PurePath
- from re import Pattern
- from uuid import UUID
-
- from msgspec import Raw, Struct
- from msgspec.msgpack import Ext
- from typing_extensions import TypeAlias
-
- from litestar.types import DataclassProtocol, TypedDictClass
-
- try:
- from pydantic import BaseModel
- except ImportError:
- BaseModel = Any # type: ignore[assignment, misc]
-
- try:
- from attrs import AttrsInstance
- except ImportError:
- AttrsInstance = Any # type: ignore[assignment, misc]
-
-__all__ = (
- "LitestarEncodableType",
- "EncodableBuiltinType",
- "EncodableBuiltinCollectionType",
- "EncodableStdLibType",
- "EncodableStdLibIPType",
- "EncodableMsgSpecType",
- "DataContainerType",
-)
-
-EncodableBuiltinType: TypeAlias = "None | bool | int | float | str | bytes | bytearray"
-EncodableBuiltinCollectionType: TypeAlias = "list | tuple | set | frozenset | dict | Collection"
-EncodableStdLibType: TypeAlias = (
- "date | datetime | deque | time | UUID | Decimal | Enum | IntEnum | DataclassProtocol | Path | PurePath | Pattern"
-)
-EncodableStdLibIPType: TypeAlias = (
- "IPv4Address | IPv4Interface | IPv4Network | IPv6Address | IPv6Interface | IPv6Network"
-)
-EncodableMsgSpecType: TypeAlias = "Ext | Raw | Struct"
-LitestarEncodableType: TypeAlias = "EncodableBuiltinType | EncodableBuiltinCollectionType | EncodableStdLibType | EncodableStdLibIPType | EncodableMsgSpecType | BaseModel | AttrsInstance" # pyright: ignore
-DataContainerType: TypeAlias = "Struct | BaseModel | AttrsInstance | TypedDictClass | DataclassProtocol" # pyright: ignore
diff --git a/venv/lib/python3.11/site-packages/litestar/typing.py b/venv/lib/python3.11/site-packages/litestar/typing.py
deleted file mode 100644
index 3a27557..0000000
--- a/venv/lib/python3.11/site-packages/litestar/typing.py
+++ /dev/null
@@ -1,636 +0,0 @@
-from __future__ import annotations
-
-from collections import abc, deque
-from copy import deepcopy
-from dataclasses import dataclass, is_dataclass, replace
-from inspect import Parameter, Signature
-from typing import (
- Any,
- AnyStr,
- Callable,
- Collection,
- ForwardRef,
- Literal,
- Mapping,
- Protocol,
- Sequence,
- TypeVar,
- cast,
-)
-
-from msgspec import UnsetType
-from typing_extensions import NotRequired, Required, Self, get_args, get_origin, get_type_hints, is_typeddict
-
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.openapi.spec import Example
-from litestar.params import BodyKwarg, DependencyKwarg, KwargDefinition, ParameterKwarg
-from litestar.types import Empty
-from litestar.types.builtin_types import NoneType, UnionTypes
-from litestar.utils.predicates import (
- is_annotated_type,
- is_any,
- is_class_and_subclass,
- is_generic,
- is_non_string_iterable,
- is_non_string_sequence,
- is_union,
-)
-from litestar.utils.typing import (
- get_instantiable_origin,
- get_safe_generic_origin,
- get_type_hints_with_generics_resolved,
- make_non_optional_union,
- unwrap_annotation,
-)
-
-__all__ = ("FieldDefinition",)
-
-T = TypeVar("T", bound=KwargDefinition)
-
-
-class _KwargMetaExtractor(Protocol):
- @staticmethod
- def matches(annotation: Any, name: str | None, default: Any) -> bool: ...
-
- @staticmethod
- def extract(annotation: Any, default: Any) -> Any: ...
-
-
-_KWARG_META_EXTRACTORS: set[_KwargMetaExtractor] = set()
-
-
-def _unpack_predicate(value: Any) -> dict[str, Any]:
- try:
- from annotated_types import Predicate
-
- if isinstance(value, Predicate):
- if value.func == str.islower:
- return {"lower_case": True}
- if value.func == str.isupper:
- return {"upper_case": True}
- if value.func == str.isascii:
- return {"pattern": "[[:ascii:]]"}
- if value.func == str.isdigit:
- return {"pattern": "[[:digit:]]"}
- except ImportError:
- pass
-
- return {}
-
-
-def _parse_metadata(value: Any, is_sequence_container: bool, extra: dict[str, Any] | None) -> dict[str, Any]:
- """Parse metadata from a value.
-
- Args:
- value: A metadata value from annotation, namely anything stored under Annotated[x, metadata...]
- is_sequence_container: Whether the type is a sequence container (list, tuple etc...)
- extra: Extra key values to parse.
-
- Returns:
- A dictionary of constraints, which fulfill the kwargs of a KwargDefinition class.
- """
- extra = {
- **cast("dict[str, Any]", extra or getattr(value, "extra", None) or {}),
- **(getattr(value, "json_schema_extra", None) or {}),
- }
- example_list: list[Any] | None
- if example := extra.pop("example", None):
- example_list = [Example(value=example)]
- elif examples := getattr(value, "examples", None):
- example_list = [Example(value=example) for example in cast("list[str]", examples)]
- else:
- example_list = None
-
- return {
- k: v
- for k, v in {
- "gt": getattr(value, "gt", None),
- "ge": getattr(value, "ge", None),
- "lt": getattr(value, "lt", None),
- "le": getattr(value, "le", None),
- "multiple_of": getattr(value, "multiple_of", None),
- "min_length": None if is_sequence_container else getattr(value, "min_length", None),
- "max_length": None if is_sequence_container else getattr(value, "max_length", None),
- "description": getattr(value, "description", None),
- "examples": example_list,
- "title": getattr(value, "title", None),
- "lower_case": getattr(value, "to_lower", None),
- "upper_case": getattr(value, "to_upper", None),
- "pattern": getattr(value, "regex", getattr(value, "pattern", None)),
- "min_items": getattr(value, "min_items", getattr(value, "min_length", None))
- if is_sequence_container
- else None,
- "max_items": getattr(value, "max_items", getattr(value, "max_length", None))
- if is_sequence_container
- else None,
- "const": getattr(value, "const", None) is not None,
- **extra,
- }.items()
- if v is not None
- }
-
-
-def _traverse_metadata(
- metadata: Sequence[Any], is_sequence_container: bool, extra: dict[str, Any] | None
-) -> dict[str, Any]:
- """Recursively traverse metadata from a value.
-
- Args:
- metadata: A list of metadata values from annotation, namely anything stored under Annotated[x, metadata...]
- is_sequence_container: Whether the container is a sequence container (list, tuple etc...)
- extra: Extra key values to parse.
-
- Returns:
- A dictionary of constraints, which fulfill the kwargs of a KwargDefinition class.
- """
- constraints: dict[str, Any] = {}
- for value in metadata:
- if isinstance(value, (list, set, frozenset, deque)):
- constraints.update(
- _traverse_metadata(
- metadata=cast("Sequence[Any]", value), is_sequence_container=is_sequence_container, extra=extra
- )
- )
- elif is_annotated_type(value) and (type_args := [v for v in get_args(value) if v is not None]):
- # annotated values can be nested inside other annotated values
- # this behaviour is buggy in python 3.8, hence we need to guard here.
- if len(type_args) > 1:
- constraints.update(
- _traverse_metadata(metadata=type_args[1:], is_sequence_container=is_sequence_container, extra=extra)
- )
- elif unpacked_predicate := _unpack_predicate(value):
- constraints.update(unpacked_predicate)
- else:
- constraints.update(_parse_metadata(value=value, is_sequence_container=is_sequence_container, extra=extra))
- return constraints
-
-
-def _create_metadata_from_type(
- metadata: Sequence[Any], model: type[T], annotation: Any, extra: dict[str, Any] | None
-) -> tuple[T | None, dict[str, Any]]:
- is_sequence_container = is_non_string_sequence(annotation)
- result = _traverse_metadata(metadata=metadata, is_sequence_container=is_sequence_container, extra=extra)
-
- constraints = {k: v for k, v in result.items() if k in dir(model)}
- extra = {k: v for k, v in result.items() if k not in constraints}
- return model(**constraints) if constraints else None, extra
-
-
-@dataclass(frozen=True)
-class FieldDefinition:
- """Represents a function parameter or type annotation."""
-
- __slots__ = (
- "annotation",
- "args",
- "default",
- "extra",
- "inner_types",
- "instantiable_origin",
- "kwarg_definition",
- "metadata",
- "name",
- "origin",
- "raw",
- "safe_generic_origin",
- "type_wrappers",
- )
-
- raw: Any
- """The annotation exactly as received."""
- annotation: Any
- """The annotation with any "wrapper" types removed, e.g. Annotated."""
- type_wrappers: tuple[type, ...]
- """A set of all "wrapper" types, e.g. Annotated."""
- origin: Any
- """The result of calling ``get_origin(annotation)`` after unwrapping Annotated, e.g. list."""
- args: tuple[Any, ...]
- """The result of calling ``get_args(annotation)`` after unwrapping Annotated, e.g. (int,)."""
- metadata: tuple[Any, ...]
- """Any metadata associated with the annotation via ``Annotated``."""
- instantiable_origin: Any
- """An equivalent type to ``origin`` that can be safely instantiated. E.g., ``Sequence`` -> ``list``."""
- safe_generic_origin: Any
- """An equivalent type to ``origin`` that can be safely used as a generic type across all supported Python versions.
-
- This is to serve safely rebuilding a generic outer type with different args at runtime.
- """
- inner_types: tuple[FieldDefinition, ...]
- """The type's generic args parsed as ``FieldDefinition``, if applicable."""
- default: Any
- """Default value of the field."""
- extra: dict[str, Any]
- """A mapping of extra values."""
- kwarg_definition: KwargDefinition | DependencyKwarg | None
- """Kwarg Parameter."""
- name: str
- """Field name."""
-
- def __deepcopy__(self, memo: dict[str, Any]) -> Self:
- return type(self)(**{attr: deepcopy(getattr(self, attr)) for attr in self.__slots__})
-
- def __eq__(self, other: Any) -> bool:
- if not isinstance(other, FieldDefinition):
- return False
-
- if self.origin:
- return self.origin == other.origin and self.inner_types == other.inner_types
-
- return self.annotation == other.annotation # type: ignore[no-any-return]
-
- def __hash__(self) -> int:
- return hash((self.name, self.raw, self.annotation, self.origin, self.inner_types))
-
- @classmethod
- def _extract_metadata(
- cls, annotation: Any, name: str | None, default: Any, metadata: tuple[Any, ...], extra: dict[str, Any] | None
- ) -> tuple[KwargDefinition | None, dict[str, Any]]:
- model = BodyKwarg if name == "data" else ParameterKwarg
-
- for extractor in _KWARG_META_EXTRACTORS:
- if extractor.matches(annotation=annotation, name=name, default=default):
- return _create_metadata_from_type(
- extractor.extract(annotation=annotation, default=default),
- model=model,
- annotation=annotation,
- extra=extra,
- )
-
- if any(isinstance(arg, KwargDefinition) for arg in get_args(annotation)):
- return next(arg for arg in get_args(annotation) if isinstance(arg, KwargDefinition)), extra or {}
-
- if metadata:
- return _create_metadata_from_type(metadata=metadata, model=model, annotation=annotation, extra=extra)
-
- return None, {}
-
- @property
- def has_default(self) -> bool:
- """Check if the field has a default value.
-
- Returns:
- True if the default is not Empty or Ellipsis otherwise False.
- """
- return self.default is not Empty and self.default is not Ellipsis
-
- @property
- def is_non_string_iterable(self) -> bool:
- """Check if the field type is an Iterable.
-
- If ``self.annotation`` is an optional union, only the non-optional members of the union are evaluated.
-
- See: https://github.com/litestar-org/litestar/issues/1106
- """
- annotation = self.annotation
- if self.is_optional:
- annotation = make_non_optional_union(annotation)
- return is_non_string_iterable(annotation)
-
- @property
- def is_non_string_sequence(self) -> bool:
- """Check if the field type is a non-string Sequence.
-
- If ``self.annotation`` is an optional union, only the non-optional members of the union are evaluated.
-
- See: https://github.com/litestar-org/litestar/issues/1106
- """
- annotation = self.annotation
- if self.is_optional:
- annotation = make_non_optional_union(annotation)
- return is_non_string_sequence(annotation)
-
- @property
- def is_any(self) -> bool:
- """Check if the field type is Any."""
- return is_any(self.annotation)
-
- @property
- def is_generic(self) -> bool:
- """Check if the field type is a custom class extending Generic."""
- return is_generic(self.annotation)
-
- @property
- def is_simple_type(self) -> bool:
- """Check if the field type is a singleton value (e.g. int, str etc.)."""
- return not (
- self.is_generic or self.is_optional or self.is_union or self.is_mapping or self.is_non_string_iterable
- )
-
- @property
- def is_parameter_field(self) -> bool:
- """Check if the field type is a parameter kwarg value."""
- return isinstance(self.kwarg_definition, ParameterKwarg)
-
- @property
- def is_const(self) -> bool:
- """Check if the field is defined as constant value."""
- return bool(self.kwarg_definition and getattr(self.kwarg_definition, "const", False))
-
- @property
- def is_required(self) -> bool:
- """Check if the field should be marked as a required parameter."""
- if Required in self.type_wrappers: # type: ignore[comparison-overlap]
- return True
-
- if NotRequired in self.type_wrappers or UnsetType in self.args: # type: ignore[comparison-overlap]
- return False
-
- if isinstance(self.kwarg_definition, ParameterKwarg) and self.kwarg_definition.required is not None:
- return self.kwarg_definition.required
-
- return not self.is_optional and not self.is_any and (not self.has_default or self.default is None)
-
- @property
- def is_annotated(self) -> bool:
- """Check if the field type is Annotated."""
- return bool(self.metadata)
-
- @property
- def is_literal(self) -> bool:
- """Check if the field type is Literal."""
- return self.origin is Literal
-
- @property
- def is_forward_ref(self) -> bool:
- """Whether the annotation is a forward reference or not."""
- return isinstance(self.annotation, (str, ForwardRef))
-
- @property
- def is_mapping(self) -> bool:
- """Whether the annotation is a mapping or not."""
- return self.is_subclass_of(Mapping)
-
- @property
- def is_tuple(self) -> bool:
- """Whether the annotation is a ``tuple`` or not."""
- return self.is_subclass_of(tuple)
-
- @property
- def is_type_var(self) -> bool:
- """Whether the annotation is a TypeVar or not."""
- return isinstance(self.annotation, TypeVar)
-
- @property
- def is_union(self) -> bool:
- """Whether the annotation is a union type or not."""
- return self.origin in UnionTypes
-
- @property
- def is_optional(self) -> bool:
- """Whether the annotation is Optional or not."""
- return bool(self.is_union and NoneType in self.args)
-
- @property
- def is_none_type(self) -> bool:
- """Whether the annotation is NoneType or not."""
- return self.annotation is NoneType
-
- @property
- def is_collection(self) -> bool:
- """Whether the annotation is a collection type or not."""
- return self.is_subclass_of(Collection)
-
- @property
- def is_non_string_collection(self) -> bool:
- """Whether the annotation is a non-string collection type or not."""
- return self.is_collection and not self.is_subclass_of((str, bytes))
-
- @property
- def bound_types(self) -> tuple[FieldDefinition, ...] | None:
- """A tuple of bound types - if the annotation is a TypeVar with bound types, otherwise None."""
- if self.is_type_var and (bound := getattr(self.annotation, "__bound__", None)):
- if is_union(bound):
- return tuple(FieldDefinition.from_annotation(t) for t in get_args(bound))
- return (FieldDefinition.from_annotation(bound),)
- return None
-
- @property
- def generic_types(self) -> tuple[FieldDefinition, ...] | None:
- """A tuple of generic types passed into the annotation - if its generic."""
- if not (bases := getattr(self.annotation, "__orig_bases__", None)):
- return None
- args: list[FieldDefinition] = []
- for base_args in [getattr(base, "__args__", ()) for base in bases]:
- for arg in base_args:
- field_definition = FieldDefinition.from_annotation(arg)
- if field_definition.generic_types:
- args.extend(field_definition.generic_types)
- else:
- args.append(field_definition)
- return tuple(args)
-
- @property
- def is_dataclass_type(self) -> bool:
- """Whether the annotation is a dataclass type or not."""
-
- return is_dataclass(cast("type", self.origin or self.annotation))
-
- @property
- def is_typeddict_type(self) -> bool:
- """Whether the type is TypedDict or not."""
-
- return is_typeddict(self.origin or self.annotation)
-
- @property
- def type_(self) -> Any:
- """The type of the annotation with all the wrappers removed, including the generic types."""
-
- return self.origin or self.annotation
-
- def is_subclass_of(self, cl: type[Any] | tuple[type[Any], ...]) -> bool:
- """Whether the annotation is a subclass of the given type.
-
- Where ``self.annotation`` is a union type, this method will return ``True`` when all members of the union are
- a subtype of ``cl``, otherwise, ``False``.
-
- Args:
- cl: The type to check, or tuple of types. Passed as 2nd argument to ``issubclass()``.
-
- Returns:
- Whether the annotation is a subtype of the given type(s).
- """
- if self.origin:
- if self.origin in UnionTypes:
- return all(t.is_subclass_of(cl) for t in self.inner_types)
-
- return self.origin not in UnionTypes and is_class_and_subclass(self.origin, cl)
-
- if self.annotation is AnyStr:
- return is_class_and_subclass(str, cl) or is_class_and_subclass(bytes, cl)
-
- return self.annotation is not Any and not self.is_type_var and is_class_and_subclass(self.annotation, cl)
-
- def has_inner_subclass_of(self, cl: type[Any] | tuple[type[Any], ...]) -> bool:
- """Whether any generic args are a subclass of the given type.
-
- Args:
- cl: The type to check, or tuple of types. Passed as 2nd argument to ``issubclass()``.
-
- Returns:
- Whether any of the type's generic args are a subclass of the given type.
- """
- return any(t.is_subclass_of(cl) for t in self.inner_types)
-
- def get_type_hints(self, *, include_extras: bool = False, resolve_generics: bool = False) -> dict[str, Any]:
- """Get the type hints for the annotation.
-
- Args:
- include_extras: Flag to indicate whether to include ``Annotated[T, ...]`` or not.
- resolve_generics: Flag to indicate whether to resolve the generic types in the type hints or not.
-
- Returns:
- The type hints.
- """
-
- if self.origin is not None or self.is_generic:
- if resolve_generics:
- return get_type_hints_with_generics_resolved(self.annotation, include_extras=include_extras)
- return get_type_hints(self.origin or self.annotation, include_extras=include_extras)
-
- return get_type_hints(self.annotation, include_extras=include_extras)
-
- @classmethod
- def from_annotation(cls, annotation: Any, **kwargs: Any) -> FieldDefinition:
- """Initialize FieldDefinition.
-
- Args:
- annotation: The type annotation. This should be extracted from the return of
- ``get_type_hints(..., include_extras=True)`` so that forward references are resolved and recursive
- ``Annotated`` types are flattened.
- **kwargs: Additional keyword arguments to pass to the ``FieldDefinition`` constructor.
-
- Returns:
- FieldDefinition
- """
-
- unwrapped, metadata, wrappers = unwrap_annotation(annotation if annotation is not Empty else Any)
- origin = get_origin(unwrapped)
-
- args = () if origin is abc.Callable else get_args(unwrapped)
-
- if not kwargs.get("kwarg_definition"):
- if isinstance(kwargs.get("default"), (KwargDefinition, DependencyKwarg)):
- kwargs["kwarg_definition"] = kwargs.pop("default")
- elif any(isinstance(v, (KwargDefinition, DependencyKwarg)) for v in metadata):
- kwargs["kwarg_definition"] = next( # pragma: no cover
- # see https://github.com/nedbat/coveragepy/issues/475
- v
- for v in metadata
- if isinstance(v, (KwargDefinition, DependencyKwarg))
- )
- metadata = tuple(v for v in metadata if not isinstance(v, (KwargDefinition, DependencyKwarg)))
- elif (extra := kwargs.get("extra", {})) and "kwarg_definition" in extra:
- kwargs["kwarg_definition"] = extra.pop("kwarg_definition")
- else:
- kwargs["kwarg_definition"], kwargs["extra"] = cls._extract_metadata(
- annotation=annotation,
- name=kwargs.get("name", ""),
- default=kwargs.get("default", Empty),
- metadata=metadata,
- extra=kwargs.get("extra"),
- )
-
- kwargs.setdefault("annotation", unwrapped)
- kwargs.setdefault("args", args)
- kwargs.setdefault("default", Empty)
- kwargs.setdefault("extra", {})
- kwargs.setdefault("inner_types", tuple(FieldDefinition.from_annotation(arg) for arg in args))
- kwargs.setdefault("instantiable_origin", get_instantiable_origin(origin, unwrapped))
- kwargs.setdefault("kwarg_definition", None)
- kwargs.setdefault("metadata", metadata)
- kwargs.setdefault("name", "")
- kwargs.setdefault("origin", origin)
- kwargs.setdefault("raw", annotation)
- kwargs.setdefault("safe_generic_origin", get_safe_generic_origin(origin, unwrapped))
- kwargs.setdefault("type_wrappers", wrappers)
-
- instance = FieldDefinition(**kwargs)
- if not instance.has_default and instance.kwarg_definition:
- return replace(instance, default=instance.kwarg_definition.default)
-
- return instance
-
- @classmethod
- def from_kwarg(
- cls,
- annotation: Any,
- name: str,
- default: Any = Empty,
- inner_types: tuple[FieldDefinition, ...] | None = None,
- kwarg_definition: KwargDefinition | DependencyKwarg | None = None,
- extra: dict[str, Any] | None = None,
- ) -> FieldDefinition:
- """Create a new FieldDefinition instance.
-
- Args:
- annotation: The type of the kwarg.
- name: Field name.
- default: A default value.
- inner_types: A tuple of FieldDefinition instances representing the inner types, if any.
- kwarg_definition: Kwarg Parameter.
- extra: A mapping of extra values.
-
- Returns:
- FieldDefinition instance.
- """
-
- return cls.from_annotation(
- annotation,
- name=name,
- default=default,
- **{
- k: v
- for k, v in {
- "inner_types": inner_types,
- "kwarg_definition": kwarg_definition,
- "extra": extra,
- }.items()
- if v is not None
- },
- )
-
- @classmethod
- def from_parameter(cls, parameter: Parameter, fn_type_hints: dict[str, Any]) -> FieldDefinition:
- """Initialize ParsedSignatureParameter.
-
- Args:
- parameter: inspect.Parameter
- fn_type_hints: mapping of names to types. Should be result of ``get_type_hints()``, preferably via the
- :attr:``get_fn_type_hints() <.utils.signature_parsing.get_fn_type_hints>`` helper.
-
- Returns:
- ParsedSignatureParameter.
-
- """
- from litestar.datastructures import ImmutableState
-
- try:
- annotation = fn_type_hints[parameter.name]
- except KeyError as e:
- raise ImproperlyConfiguredException(
- f"'{parameter.name}' does not have a type annotation. If it should receive any value, use 'Any'."
- ) from e
-
- if parameter.name == "state" and not issubclass(annotation, ImmutableState):
- raise ImproperlyConfiguredException(
- f"The type annotation `{annotation}` is an invalid type for the 'state' reserved kwarg. "
- "It must be typed to a subclass of `litestar.datastructures.ImmutableState` or "
- "`litestar.datastructures.State`."
- )
-
- return FieldDefinition.from_kwarg(
- annotation=annotation,
- name=parameter.name,
- default=Empty if parameter.default is Signature.empty else parameter.default,
- )
-
- def match_predicate_recursively(self, predicate: Callable[[FieldDefinition], bool]) -> bool:
- """Recursively test the passed in predicate against the field and any of its inner fields.
-
- Args:
- predicate: A callable that receives a field definition instance as an arg and returns a boolean.
-
- Returns:
- A boolean.
- """
- return predicate(self) or any(t.match_predicate_recursively(predicate) for t in self.inner_types)
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/__init__.py b/venv/lib/python3.11/site-packages/litestar/utils/__init__.py
deleted file mode 100644
index 3f62792..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/__init__.py
+++ /dev/null
@@ -1,86 +0,0 @@
-from typing import Any
-
-from litestar.utils.deprecation import deprecated, warn_deprecation
-
-from .helpers import get_enum_string_value, get_name, unique_name_for_scope, url_quote
-from .path import join_paths, normalize_path
-from .predicates import (
- _is_sync_or_async_generator,
- is_annotated_type,
- is_any,
- is_async_callable,
- is_attrs_class,
- is_class_and_subclass,
- is_class_var,
- is_dataclass_class,
- is_dataclass_instance,
- is_generic,
- is_mapping,
- is_non_string_iterable,
- is_non_string_sequence,
- is_optional_union,
- is_undefined_sentinel,
- is_union,
-)
-from .scope import ( # type: ignore[attr-defined]
- _delete_litestar_scope_state,
- _get_litestar_scope_state,
- _set_litestar_scope_state,
- get_serializer_from_scope,
-)
-from .sequence import find_index, unique
-from .sync import AsyncIteratorWrapper, ensure_async_callable
-from .typing import get_origin_or_inner_type, make_non_optional_union
-
-__all__ = (
- "ensure_async_callable",
- "AsyncIteratorWrapper",
- "deprecated",
- "find_index",
- "get_enum_string_value",
- "get_name",
- "get_origin_or_inner_type",
- "get_serializer_from_scope",
- "is_annotated_type",
- "is_any",
- "is_async_callable",
- "is_attrs_class",
- "is_class_and_subclass",
- "is_class_var",
- "is_dataclass_class",
- "is_dataclass_instance",
- "is_generic",
- "is_mapping",
- "is_non_string_iterable",
- "is_non_string_sequence",
- "is_optional_union",
- "is_undefined_sentinel",
- "is_union",
- "join_paths",
- "make_non_optional_union",
- "normalize_path",
- "unique",
- "unique_name_for_scope",
- "url_quote",
- "warn_deprecation",
-)
-
-_deprecated_names = {
- "get_litestar_scope_state": _get_litestar_scope_state,
- "set_litestar_scope_state": _set_litestar_scope_state,
- "delete_litestar_scope_state": _delete_litestar_scope_state,
- "is_sync_or_async_generator": _is_sync_or_async_generator,
-}
-
-
-def __getattr__(name: str) -> Any:
- if name in _deprecated_names:
- warn_deprecation(
- deprecated_name=f"litestar.utils.{name}",
- version="2.4",
- kind="import",
- removal_in="3.0",
- info=f"'litestar.utils.{name}' is deprecated.",
- )
- return globals()["_deprecated_names"][name]
- raise AttributeError(f"module {__name__!r} has no attribute {name!r}") # pragma: no cover
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index da9ad02..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/compat.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/compat.cpython-311.pyc
deleted file mode 100644
index 39d39d6..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/compat.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/dataclass.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/dataclass.cpython-311.pyc
deleted file mode 100644
index addf140..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/dataclass.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/deprecation.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/deprecation.cpython-311.pyc
deleted file mode 100644
index ddf3b7c..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/deprecation.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/empty.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/empty.cpython-311.pyc
deleted file mode 100644
index 2b358ad..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/empty.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/helpers.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/helpers.cpython-311.pyc
deleted file mode 100644
index 9db59c4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/helpers.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/module_loader.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/module_loader.cpython-311.pyc
deleted file mode 100644
index f32ca7e..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/module_loader.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/path.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/path.cpython-311.pyc
deleted file mode 100644
index 6602b02..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/path.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/predicates.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/predicates.cpython-311.pyc
deleted file mode 100644
index 983250b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/predicates.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/sequence.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/sequence.cpython-311.pyc
deleted file mode 100644
index b2f8c1a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/sequence.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/signature.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/signature.cpython-311.pyc
deleted file mode 100644
index d81050f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/signature.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/sync.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/sync.cpython-311.pyc
deleted file mode 100644
index 8a18dfb..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/sync.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/typing.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/typing.cpython-311.pyc
deleted file mode 100644
index 53db129..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/typing.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/version.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/version.cpython-311.pyc
deleted file mode 100644
index f656ef4..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/version.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/warnings.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/warnings.cpython-311.pyc
deleted file mode 100644
index 3fa1cf1..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/__pycache__/warnings.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/compat.py b/venv/lib/python3.11/site-packages/litestar/utils/compat.py
deleted file mode 100644
index 384db76..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/compat.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, TypeVar
-
-from litestar.types import Empty, EmptyType
-
-__all__ = ("async_next",)
-
-
-if TYPE_CHECKING:
- from typing import Any, AsyncGenerator
-
-T = TypeVar("T")
-D = TypeVar("D")
-
-try:
- async_next = anext # type: ignore[name-defined]
-except NameError:
-
- async def async_next(gen: AsyncGenerator[T, Any], default: D | EmptyType = Empty) -> T | D:
- """Backwards compatibility shim for Python<3.10."""
- try:
- return await gen.__anext__()
- except StopAsyncIteration as exc:
- if default is not Empty:
- return default
- raise exc
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/dataclass.py b/venv/lib/python3.11/site-packages/litestar/utils/dataclass.py
deleted file mode 100644
index 597465d..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/dataclass.py
+++ /dev/null
@@ -1,115 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import Field, fields
-from typing import TYPE_CHECKING
-
-from litestar.types import Empty
-from litestar.utils.predicates import is_dataclass_instance
-
-if TYPE_CHECKING:
- from typing import AbstractSet, Any, Iterable
-
- from litestar.types.protocols import DataclassProtocol
-
-__all__ = (
- "extract_dataclass_fields",
- "extract_dataclass_items",
- "simple_asdict",
-)
-
-
-def extract_dataclass_fields(
- dt: DataclassProtocol,
- exclude_none: bool = False,
- exclude_empty: bool = False,
- include: AbstractSet[str] | None = None,
- exclude: AbstractSet[str] | None = None,
-) -> tuple[Field[Any], ...]:
- """Extract dataclass fields.
-
- Args:
- dt: A dataclass instance.
- exclude_none: Whether to exclude None values.
- exclude_empty: Whether to exclude Empty values.
- include: An iterable of fields to include.
- exclude: An iterable of fields to exclude.
-
-
- Returns:
- A tuple of dataclass fields.
- """
- include = include or set()
- exclude = exclude or set()
-
- if common := (include & exclude):
- raise ValueError(f"Fields {common} are both included and excluded.")
-
- dataclass_fields: Iterable[Field[Any]] = fields(dt)
- if exclude_none:
- dataclass_fields = (field for field in dataclass_fields if getattr(dt, field.name) is not None)
- if exclude_empty:
- dataclass_fields = (field for field in dataclass_fields if getattr(dt, field.name) is not Empty)
- if include:
- dataclass_fields = (field for field in dataclass_fields if field.name in include)
- if exclude:
- dataclass_fields = (field for field in dataclass_fields if field.name not in exclude)
-
- return tuple(dataclass_fields)
-
-
-def extract_dataclass_items(
- dt: DataclassProtocol,
- exclude_none: bool = False,
- exclude_empty: bool = False,
- include: AbstractSet[str] | None = None,
- exclude: AbstractSet[str] | None = None,
-) -> tuple[tuple[str, Any], ...]:
- """Extract dataclass name, value pairs.
-
- Unlike the 'asdict' method exports by the stlib, this function does not pickle values.
-
- Args:
- dt: A dataclass instance.
- exclude_none: Whether to exclude None values.
- exclude_empty: Whether to exclude Empty values.
- include: An iterable of fields to include.
- exclude: An iterable of fields to exclude.
-
- Returns:
- A tuple of key/value pairs.
- """
- dataclass_fields = extract_dataclass_fields(dt, exclude_none, exclude_empty, include, exclude)
- return tuple((field.name, getattr(dt, field.name)) for field in dataclass_fields)
-
-
-def simple_asdict(
- obj: DataclassProtocol,
- exclude_none: bool = False,
- exclude_empty: bool = False,
- convert_nested: bool = True,
- exclude: set[str] | None = None,
-) -> dict[str, Any]:
- """Convert a dataclass to a dictionary.
-
- This method has important differences to the standard library version:
- - it does not deepcopy values
- - it does not recurse into collections
-
- Args:
- obj: A dataclass instance.
- exclude_none: Whether to exclude None values.
- exclude_empty: Whether to exclude Empty values.
- convert_nested: Whether to recursively convert nested dataclasses.
- exclude: An iterable of fields to exclude.
-
- Returns:
- A dictionary of key/value pairs.
- """
- ret = {}
- for field in extract_dataclass_fields(obj, exclude_none, exclude_empty, exclude=exclude):
- value = getattr(obj, field.name)
- if is_dataclass_instance(value) and convert_nested:
- ret[field.name] = simple_asdict(value, exclude_none, exclude_empty)
- else:
- ret[field.name] = getattr(obj, field.name)
- return ret
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/deprecation.py b/venv/lib/python3.11/site-packages/litestar/utils/deprecation.py
deleted file mode 100644
index b1b8725..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/deprecation.py
+++ /dev/null
@@ -1,111 +0,0 @@
-from __future__ import annotations
-
-import inspect
-from functools import wraps
-from typing import Callable, Literal, TypeVar
-from warnings import warn
-
-from typing_extensions import ParamSpec
-
-__all__ = ("deprecated", "warn_deprecation")
-
-
-T = TypeVar("T")
-P = ParamSpec("P")
-DeprecatedKind = Literal["function", "method", "classmethod", "attribute", "property", "class", "parameter", "import"]
-
-
-def warn_deprecation(
- version: str,
- deprecated_name: str,
- kind: DeprecatedKind,
- *,
- removal_in: str | None = None,
- alternative: str | None = None,
- info: str | None = None,
- pending: bool = False,
-) -> None:
- """Warn about a call to a (soon to be) deprecated function.
-
- Args:
- version: Litestar version where the deprecation will occur
- deprecated_name: Name of the deprecated function
- removal_in: Litestar version where the deprecated function will be removed
- alternative: Name of a function that should be used instead
- info: Additional information
- pending: Use ``PendingDeprecationWarning`` instead of ``DeprecationWarning``
- kind: Type of the deprecated thing
- """
- parts = []
-
- if kind == "import":
- access_type = "Import of"
- elif kind in {"function", "method"}:
- access_type = "Call to"
- else:
- access_type = "Use of"
-
- if pending:
- parts.append(f"{access_type} {kind} awaiting deprecation {deprecated_name!r}")
- else:
- parts.append(f"{access_type} deprecated {kind} {deprecated_name!r}")
-
- parts.extend(
- (
- f"Deprecated in litestar {version}",
- f"This {kind} will be removed in {removal_in or 'the next major version'}",
- )
- )
- if alternative:
- parts.append(f"Use {alternative!r} instead")
-
- if info:
- parts.append(info)
-
- text = ". ".join(parts)
- warning_class = PendingDeprecationWarning if pending else DeprecationWarning
-
- warn(text, warning_class, stacklevel=2)
-
-
-def deprecated(
- version: str,
- *,
- removal_in: str | None = None,
- alternative: str | None = None,
- info: str | None = None,
- pending: bool = False,
- kind: Literal["function", "method", "classmethod", "property"] | None = None,
-) -> Callable[[Callable[P, T]], Callable[P, T]]:
- """Create a decorator wrapping a function, method or property with a warning call about a (pending) deprecation.
-
- Args:
- version: Litestar version where the deprecation will occur
- removal_in: Litestar version where the deprecated function will be removed
- alternative: Name of a function that should be used instead
- info: Additional information
- pending: Use ``PendingDeprecationWarning`` instead of ``DeprecationWarning``
- kind: Type of the deprecated callable. If ``None``, will use ``inspect`` to figure
- out if it's a function or method
-
- Returns:
- A decorator wrapping the function call with a warning
- """
-
- def decorator(func: Callable[P, T]) -> Callable[P, T]:
- @wraps(func)
- def wrapped(*args: P.args, **kwargs: P.kwargs) -> T:
- warn_deprecation(
- version=version,
- deprecated_name=func.__name__,
- info=info,
- alternative=alternative,
- pending=pending,
- removal_in=removal_in,
- kind=kind or ("method" if inspect.ismethod(func) else "function"),
- )
- return func(*args, **kwargs)
-
- return wrapped
-
- return decorator
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/empty.py b/venv/lib/python3.11/site-packages/litestar/utils/empty.py
deleted file mode 100644
index cdde871..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/empty.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, TypeVar
-
-from litestar.types.empty import Empty
-
-if TYPE_CHECKING:
- from litestar.types.empty import EmptyType
-
-ValueT = TypeVar("ValueT")
-DefaultT = TypeVar("DefaultT")
-
-
-def value_or_default(value: ValueT | EmptyType, default: DefaultT) -> ValueT | DefaultT:
- """Return `value` handling the case where it is empty.
-
- If `value` is `Empty`, `default` is returned.
-
- Args:
- value: The value to check.
- default: The default value to return if `value` is `Empty`.
-
- Returns:
- The value or default value.
- """
- return default if value is Empty else value
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/helpers.py b/venv/lib/python3.11/site-packages/litestar/utils/helpers.py
deleted file mode 100644
index c25fe35..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/helpers.py
+++ /dev/null
@@ -1,103 +0,0 @@
-from __future__ import annotations
-
-from enum import Enum
-from functools import partial
-from typing import TYPE_CHECKING, TypeVar, cast
-from urllib.parse import quote
-
-from litestar.utils.typing import get_origin_or_inner_type
-
-if TYPE_CHECKING:
- from collections.abc import Container
-
- from litestar.types import MaybePartial
-
-__all__ = (
- "get_enum_string_value",
- "get_name",
- "unwrap_partial",
- "url_quote",
- "unique_name_for_scope",
-)
-
-T = TypeVar("T")
-
-
-def get_name(value: object) -> str:
- """Get the ``__name__`` of an object.
-
- Args:
- value: An arbitrary object.
-
- Returns:
- A name string.
- """
-
- name = getattr(value, "__name__", None)
- if name is not None:
- return cast("str", name)
-
- # On Python 3.8 and 3.9, Foo[int] does not have the __name__ attribute.
- if origin := get_origin_or_inner_type(value):
- return cast("str", origin.__name__)
-
- return type(value).__name__
-
-
-def get_enum_string_value(value: Enum | str) -> str:
- """Return the string value of a string enum.
-
- See: https://github.com/litestar-org/litestar/pull/633#issuecomment-1286519267
-
- Args:
- value: An enum or string.
-
- Returns:
- A string.
- """
- return value.value if isinstance(value, Enum) else value # type: ignore[no-any-return]
-
-
-def unwrap_partial(value: MaybePartial[T]) -> T:
- """Unwraps a partial, returning the underlying callable.
-
- Args:
- value: A partial function.
-
- Returns:
- Callable
- """
- from litestar.utils.sync import AsyncCallable
-
- return cast("T", value.func if isinstance(value, (partial, AsyncCallable)) else value)
-
-
-def url_quote(value: str | bytes) -> str:
- """Quote a URL.
-
- Args:
- value: A URL.
-
- Returns:
- A quoted URL.
- """
- return quote(value, safe="/#%[]=:;$&()+,!?*@'~")
-
-
-def unique_name_for_scope(base_name: str, scope: Container[str]) -> str:
- """Create a name derived from ``base_name`` that's unique within ``scope``"""
- i = 0
- while True:
- if (unique_name := f"{base_name}_{i}") not in scope:
- return unique_name
- i += 1
-
-
-def get_exception_group() -> type[BaseException]:
- """Get the exception group class with version compatibility."""
- try:
- return cast("type[BaseException]", ExceptionGroup) # type:ignore[name-defined]
- except NameError:
- from exceptiongroup import ExceptionGroup as _ExceptionGroup # pyright: ignore
-
- return cast("type[BaseException]", _ExceptionGroup)
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/module_loader.py b/venv/lib/python3.11/site-packages/litestar/utils/module_loader.py
deleted file mode 100644
index 09dbf9f..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/module_loader.py
+++ /dev/null
@@ -1,92 +0,0 @@
-"""General utility functions."""
-
-from __future__ import annotations
-
-import os.path
-import sys
-from importlib import import_module
-from importlib.util import find_spec
-from pathlib import Path
-from typing import TYPE_CHECKING, Any
-
-if TYPE_CHECKING:
- from types import ModuleType
-
-__all__ = (
- "import_string",
- "module_to_os_path",
-)
-
-
-def module_to_os_path(dotted_path: str = "app") -> Path:
- """Find Module to OS Path.
-
- Return a path to the base directory of the project or the module
- specified by `dotted_path`.
-
- Args:
- dotted_path: The path to the module. Defaults to "app".
-
- Raises:
- TypeError: The module could not be found.
-
- Returns:
- Path: The path to the module.
- """
- try:
- if (src := find_spec(dotted_path)) is None: # pragma: no cover
- raise TypeError(f"Couldn't find the path for {dotted_path}")
- except ModuleNotFoundError as e:
- raise TypeError(f"Couldn't find the path for {dotted_path}") from e
-
- return Path(str(src.origin).rsplit(os.path.sep + "__init__.py", maxsplit=1)[0])
-
-
-def import_string(dotted_path: str) -> Any:
- """Dotted Path Import.
-
- Import a dotted module path and return the attribute/class designated by the
- last name in the path. Raise ImportError if the import failed.
-
- Args:
- dotted_path: The path of the module to import.
-
- Raises:
- ImportError: Could not import the module.
-
- Returns:
- object: The imported object.
- """
-
- def _is_loaded(module: ModuleType | None) -> bool:
- spec = getattr(module, "__spec__", None)
- initializing = getattr(spec, "_initializing", False)
- return bool(module and spec and not initializing)
-
- def _cached_import(module_path: str, class_name: str) -> Any:
- """Import and cache a class from a module.
-
- Args:
- module_path: dotted path to module.
- class_name: Class or function name.
-
- Returns:
- object: The imported class or function
- """
- # Check whether module is loaded and fully initialized.
- module = sys.modules.get(module_path)
- if not _is_loaded(module):
- module = import_module(module_path)
- return getattr(module, class_name)
-
- try:
- module_path, class_name = dotted_path.rsplit(".", 1)
- except ValueError as e:
- msg = "%s doesn't look like a module path"
- raise ImportError(msg, dotted_path) from e
-
- try:
- return _cached_import(module_path, class_name)
- except AttributeError as e:
- msg = "Module '%s' does not define a '%s' attribute/class"
- raise ImportError(msg, module_path, class_name) from e
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/path.py b/venv/lib/python3.11/site-packages/litestar/utils/path.py
deleted file mode 100644
index 76b43af..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/path.py
+++ /dev/null
@@ -1,35 +0,0 @@
-from __future__ import annotations
-
-import re
-from typing import Iterable
-
-__all__ = ("join_paths", "normalize_path")
-
-
-multi_slash_pattern = re.compile("//+")
-
-
-def normalize_path(path: str) -> str:
- """Normalize a given path by ensuring it starts with a slash and does not end with a slash.
-
- Args:
- path: Path string
-
- Returns:
- Path string
- """
- path = path.strip("/")
- path = f"/{path}"
- return multi_slash_pattern.sub("/", path)
-
-
-def join_paths(paths: Iterable[str]) -> str:
- """Normalize and joins path fragments.
-
- Args:
- paths: An iterable of path fragments.
-
- Returns:
- A normalized joined path string.
- """
- return normalize_path("/".join(paths))
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/predicates.py b/venv/lib/python3.11/site-packages/litestar/utils/predicates.py
deleted file mode 100644
index 11d5f79..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/predicates.py
+++ /dev/null
@@ -1,339 +0,0 @@
-from __future__ import annotations
-
-from asyncio import iscoroutinefunction
-from collections import defaultdict, deque
-from collections.abc import Iterable as CollectionsIterable
-from dataclasses import is_dataclass
-from inspect import isasyncgenfunction, isclass, isgeneratorfunction
-from typing import (
- TYPE_CHECKING,
- Any,
- Awaitable,
- Callable,
- ClassVar,
- DefaultDict,
- Deque,
- Dict,
- FrozenSet,
- Generic,
- Iterable,
- List,
- Mapping,
- Optional,
- Sequence,
- Set,
- Tuple,
- TypeVar,
-)
-
-from typing_extensions import (
- ParamSpec,
- TypeGuard,
- _AnnotatedAlias,
- get_args,
-)
-
-from litestar.constants import UNDEFINED_SENTINELS
-from litestar.types import Empty
-from litestar.types.builtin_types import NoneType, UnionTypes
-from litestar.utils.deprecation import warn_deprecation
-from litestar.utils.helpers import unwrap_partial
-from litestar.utils.typing import get_origin_or_inner_type
-
-if TYPE_CHECKING:
- from litestar.types.callable_types import AnyGenerator
- from litestar.types.protocols import DataclassProtocol
-
-try:
- import attrs
-except ImportError:
- attrs = Empty # type: ignore[assignment]
-
-__all__ = (
- "is_annotated_type",
- "is_any",
- "is_async_callable",
- "is_attrs_class",
- "is_class_and_subclass",
- "is_class_var",
- "is_dataclass_class",
- "is_dataclass_instance",
- "is_generic",
- "is_mapping",
- "is_non_string_iterable",
- "is_non_string_sequence",
- "is_optional_union",
- "is_undefined_sentinel",
- "is_union",
-)
-
-P = ParamSpec("P")
-T = TypeVar("T")
-
-
-def is_async_callable(value: Callable[P, T]) -> TypeGuard[Callable[P, Awaitable[T]]]:
- """Extend :func:`asyncio.iscoroutinefunction` to additionally detect async :func:`functools.partial` objects and
- class instances with ``async def __call__()`` defined.
-
- Args:
- value: Any
-
- Returns:
- Bool determining if type of ``value`` is an awaitable.
- """
- value = unwrap_partial(value)
-
- return iscoroutinefunction(value) or (
- callable(value) and iscoroutinefunction(value.__call__) # type: ignore[operator]
- )
-
-
-def is_dataclass_instance(obj: Any) -> TypeGuard[DataclassProtocol]:
- """Check if an object is a dataclass instance.
-
- Args:
- obj: An object to check.
-
- Returns:
- True if the object is a dataclass instance.
- """
- return hasattr(type(obj), "__dataclass_fields__")
-
-
-def is_dataclass_class(annotation: Any) -> TypeGuard[type[DataclassProtocol]]:
- """Wrap :func:`is_dataclass <dataclasses.is_dataclass>` in a :data:`typing.TypeGuard`.
-
- Args:
- annotation: tested to determine if instance or type of :class:`dataclasses.dataclass`.
-
- Returns:
- ``True`` if instance or type of ``dataclass``.
- """
- try:
- origin = get_origin_or_inner_type(annotation)
- annotation = origin or annotation
-
- return isclass(annotation) and is_dataclass(annotation)
- except TypeError: # pragma: no cover
- return False
-
-
-def is_class_and_subclass(annotation: Any, type_or_type_tuple: type[T] | tuple[type[T], ...]) -> TypeGuard[type[T]]:
- """Return ``True`` if ``value`` is a ``class`` and is a subtype of ``t_type``.
-
- See https://github.com/litestar-org/litestar/issues/367
-
- Args:
- annotation: The value to check if is class and subclass of ``t_type``.
- type_or_type_tuple: Type used for :func:`issubclass` check of ``value``
-
- Returns:
- bool
- """
- origin = get_origin_or_inner_type(annotation)
- if not origin and not isclass(annotation):
- return False
- try:
- return issubclass(origin or annotation, type_or_type_tuple)
- except TypeError: # pragma: no cover
- return False
-
-
-def is_generic(annotation: Any) -> bool:
- """Given a type annotation determine if the annotation is a generic class.
-
- Args:
- annotation: A type.
-
- Returns:
- True if the annotation is a subclass of :data:`Generic <typing.Generic>` otherwise ``False``.
- """
- return is_class_and_subclass(annotation, Generic) # type: ignore[arg-type]
-
-
-def is_mapping(annotation: Any) -> TypeGuard[Mapping[Any, Any]]:
- """Given a type annotation determine if the annotation is a mapping type.
-
- Args:
- annotation: A type.
-
- Returns:
- A typeguard determining whether the type can be cast as :class:`Mapping <typing.Mapping>`.
- """
- _type = get_origin_or_inner_type(annotation) or annotation
- return isclass(_type) and issubclass(_type, (dict, defaultdict, DefaultDict, Mapping))
-
-
-def is_non_string_iterable(annotation: Any) -> TypeGuard[Iterable[Any]]:
- """Given a type annotation determine if the annotation is an iterable.
-
- Args:
- annotation: A type.
-
- Returns:
- A typeguard determining whether the type can be cast as :class:`Iterable <typing.Iterable>` that is not a string.
- """
- origin = get_origin_or_inner_type(annotation)
- if not origin and not isclass(annotation):
- return False
- try:
- return not issubclass(origin or annotation, (str, bytes)) and (
- issubclass(origin or annotation, (Iterable, CollectionsIterable, Dict, dict, Mapping))
- or is_non_string_sequence(annotation)
- )
- except TypeError: # pragma: no cover
- return False
-
-
-def is_non_string_sequence(annotation: Any) -> TypeGuard[Sequence[Any]]:
- """Given a type annotation determine if the annotation is a sequence.
-
- Args:
- annotation: A type.
-
- Returns:
- A typeguard determining whether the type can be cast as :class`Sequence <typing.Sequence>` that is not a string.
- """
- origin = get_origin_or_inner_type(annotation)
- if not origin and not isclass(annotation):
- return False
- try:
- return not issubclass(origin or annotation, (str, bytes)) and issubclass(
- origin or annotation,
- ( # type: ignore[arg-type]
- Tuple,
- List,
- Set,
- FrozenSet,
- Deque,
- Sequence,
- list,
- tuple,
- deque,
- set,
- frozenset,
- ),
- )
- except TypeError: # pragma: no cover
- return False
-
-
-def is_any(annotation: Any) -> TypeGuard[Any]:
- """Given a type annotation determine if the annotation is Any.
-
- Args:
- annotation: A type.
-
- Returns:
- A typeguard determining whether the type is :data:`Any <typing.Any>`.
- """
- return (
- annotation is Any
- or getattr(annotation, "_name", "") == "typing.Any"
- or (get_origin_or_inner_type(annotation) in UnionTypes and Any in get_args(annotation))
- )
-
-
-def is_union(annotation: Any) -> bool:
- """Given a type annotation determine if the annotation infers an optional union.
-
- Args:
- annotation: A type.
-
- Returns:
- A boolean determining whether the type is :data:`Union typing.Union>`.
- """
- return get_origin_or_inner_type(annotation) in UnionTypes
-
-
-def is_optional_union(annotation: Any) -> TypeGuard[Any | None]:
- """Given a type annotation determine if the annotation infers an optional union.
-
- Args:
- annotation: A type.
-
- Returns:
- A typeguard determining whether the type is :data:`Union typing.Union>` with a
- None value or :data:`Optional <typing.Optional>` which is equivalent.
- """
- origin = get_origin_or_inner_type(annotation)
- return origin is Optional or (
- get_origin_or_inner_type(annotation) in UnionTypes and NoneType in get_args(annotation)
- )
-
-
-def is_attrs_class(annotation: Any) -> TypeGuard[type[attrs.AttrsInstance]]: # pyright: ignore
- """Given a type annotation determine if the annotation is a class that includes an attrs attribute.
-
- Args:
- annotation: A type.
-
- Returns:
- A typeguard determining whether the type is an attrs class.
- """
- return attrs.has(annotation) if attrs is not Empty else False # type: ignore[comparison-overlap]
-
-
-def is_class_var(annotation: Any) -> bool:
- """Check if the given annotation is a ClassVar.
-
- Args:
- annotation: A type annotation
-
- Returns:
- A boolean.
- """
- annotation = get_origin_or_inner_type(annotation) or annotation
- return annotation is ClassVar
-
-
-def _is_sync_or_async_generator(obj: Any) -> TypeGuard[AnyGenerator]:
- """Check if the given annotation is a sync or async generator.
-
- Args:
- obj: type to be tested for sync or async generator.
-
- Returns:
- A boolean.
- """
- return isgeneratorfunction(obj) or isasyncgenfunction(obj)
-
-
-def is_annotated_type(annotation: Any) -> bool:
- """Check if the given annotation is an Annotated.
-
- Args:
- annotation: A type annotation
-
- Returns:
- A boolean.
- """
- return isinstance(annotation, _AnnotatedAlias) and getattr(annotation, "__args__", None) is not None
-
-
-def is_undefined_sentinel(value: Any) -> bool:
- """Check if the given value is the undefined sentinel.
-
- Args:
- value: A value to be tested for undefined sentinel.
-
- Returns:
- A boolean.
- """
- return any(v is value for v in UNDEFINED_SENTINELS)
-
-
-_deprecated_names = {"is_sync_or_async_generator": _is_sync_or_async_generator}
-
-
-def __getattr__(name: str) -> Any:
- if name in _deprecated_names:
- warn_deprecation(
- deprecated_name=f"litestar.utils.scope.{name}",
- version="2.4",
- kind="import",
- removal_in="3.0",
- info=f"'litestar.utils.predicates.{name}' is deprecated.",
- )
- return globals()["_deprecated_names"][name]
- raise AttributeError(f"module {__name__!r} has no attribute {name!r}") # pragma: no cover
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/scope/__init__.py b/venv/lib/python3.11/site-packages/litestar/utils/scope/__init__.py
deleted file mode 100644
index e5757d3..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/scope/__init__.py
+++ /dev/null
@@ -1,62 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING, Any
-
-from litestar.serialization import get_serializer
-from litestar.utils.deprecation import warn_deprecation
-from litestar.utils.scope.state import delete_litestar_scope_state as _delete_litestar_scope_state
-from litestar.utils.scope.state import get_litestar_scope_state as _get_litestar_scope_state
-from litestar.utils.scope.state import set_litestar_scope_state as _set_litestar_scope_state
-
-if TYPE_CHECKING:
- from litestar.types import Scope, Serializer
-
-__all__ = ("get_serializer_from_scope",)
-
-
-def get_serializer_from_scope(scope: Scope) -> Serializer:
- """Return a serializer given a scope object.
-
- Args:
- scope: The ASGI connection scope.
-
- Returns:
- A serializer function
- """
- route_handler = scope["route_handler"]
- app = scope["app"]
-
- if hasattr(route_handler, "resolve_type_encoders"):
- type_encoders = route_handler.resolve_type_encoders()
- else:
- type_encoders = app.type_encoders or {}
-
- if response_class := (
- route_handler.resolve_response_class() # pyright: ignore
- if hasattr(route_handler, "resolve_response_class")
- else app.response_class
- ):
- type_encoders = {**type_encoders, **(response_class.type_encoders or {})}
-
- return get_serializer(type_encoders)
-
-
-_deprecated_names = {
- "get_litestar_scope_state": _get_litestar_scope_state,
- "set_litestar_scope_state": _set_litestar_scope_state,
- "delete_litestar_scope_state": _delete_litestar_scope_state,
-}
-
-
-def __getattr__(name: str) -> Any:
- if name in _deprecated_names:
- warn_deprecation(
- deprecated_name=f"litestar.utils.scope.{name}",
- version="2.4",
- kind="import",
- removal_in="3.0",
- info=f"'litestar.utils.scope.{name}' is deprecated. The Litestar scope state is private and should not be "
- f"used. Plugin authors should maintain their own scope state namespace.",
- )
- return globals()["_deprecated_names"][name]
- raise AttributeError(f"module {__name__!r} has no attribute {name!r}") # pragma: no cover
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/scope/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/utils/scope/__pycache__/__init__.cpython-311.pyc
deleted file mode 100644
index ee218d5..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/scope/__pycache__/__init__.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/scope/__pycache__/state.cpython-311.pyc b/venv/lib/python3.11/site-packages/litestar/utils/scope/__pycache__/state.cpython-311.pyc
deleted file mode 100644
index 4615004..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/scope/__pycache__/state.cpython-311.pyc
+++ /dev/null
Binary files differ
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/scope/state.py b/venv/lib/python3.11/site-packages/litestar/utils/scope/state.py
deleted file mode 100644
index bed4394..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/scope/state.py
+++ /dev/null
@@ -1,158 +0,0 @@
-from __future__ import annotations
-
-from dataclasses import dataclass
-from typing import TYPE_CHECKING, Any, Final
-
-from litestar.types import Empty, EmptyType
-from litestar.utils.empty import value_or_default
-
-if TYPE_CHECKING:
- from typing_extensions import Self
-
- from litestar.datastructures import URL, Accept, Headers
- from litestar.types.asgi_types import Scope
-
-CONNECTION_STATE_KEY: Final = "_ls_connection_state"
-
-
-@dataclass
-class ScopeState:
- """An object for storing connection state.
-
- This is an internal API, and subject to change without notice.
-
- All types are a union with `EmptyType` and are seeded with the `Empty` value.
- """
-
- __slots__ = (
- "accept",
- "base_url",
- "body",
- "content_type",
- "cookies",
- "csrf_token",
- "dependency_cache",
- "do_cache",
- "form",
- "headers",
- "is_cached",
- "json",
- "log_context",
- "msgpack",
- "parsed_query",
- "response_compressed",
- "session_id",
- "url",
- "_compat_ns",
- )
-
- def __init__(self) -> None:
- self.accept = Empty
- self.base_url = Empty
- self.body = Empty
- self.content_type = Empty
- self.cookies = Empty
- self.csrf_token = Empty
- self.dependency_cache = Empty
- self.do_cache = Empty
- self.form = Empty
- self.headers = Empty
- self.is_cached = Empty
- self.json = Empty
- self.log_context: dict[str, Any] = {}
- self.msgpack = Empty
- self.parsed_query = Empty
- self.response_compressed = Empty
- self.session_id = Empty
- self.url = Empty
- self._compat_ns: dict[str, Any] = {}
-
- accept: Accept | EmptyType
- base_url: URL | EmptyType
- body: bytes | EmptyType
- content_type: tuple[str, dict[str, str]] | EmptyType
- cookies: dict[str, str] | EmptyType
- csrf_token: str | EmptyType
- dependency_cache: dict[str, Any] | EmptyType
- do_cache: bool | EmptyType
- form: dict[str, str | list[str]] | EmptyType
- headers: Headers | EmptyType
- is_cached: bool | EmptyType
- json: Any | EmptyType
- log_context: dict[str, Any]
- msgpack: Any | EmptyType
- parsed_query: tuple[tuple[str, str], ...] | EmptyType
- response_compressed: bool | EmptyType
- session_id: str | None | EmptyType
- url: URL | EmptyType
- _compat_ns: dict[str, Any]
-
- @classmethod
- def from_scope(cls, scope: Scope) -> Self:
- """Create a new `ConnectionState` object from a scope.
-
- Object is cached in the scope's state under the `SCOPE_STATE_NAMESPACE` key.
-
- Args:
- scope: The ASGI connection scope.
-
- Returns:
- A `ConnectionState` object.
- """
- base_scope_state = scope.setdefault("state", {})
- if (state := base_scope_state.get(CONNECTION_STATE_KEY)) is None:
- state = base_scope_state[CONNECTION_STATE_KEY] = cls()
- return state
-
-
-def get_litestar_scope_state(scope: Scope, key: str, default: Any = None, pop: bool = False) -> Any:
- """Get an internal value from connection scope state.
-
- Args:
- scope: The connection scope.
- key: Key to get from internal namespace in scope state.
- default: Default value to return.
- pop: Boolean flag dictating whether the value should be deleted from the state.
-
- Returns:
- Value mapped to ``key`` in internal connection scope namespace.
- """
- scope_state = ScopeState.from_scope(scope)
- try:
- val = value_or_default(getattr(scope_state, key), default)
- if pop:
- setattr(scope_state, key, Empty)
- return val
- except AttributeError:
- if pop:
- return scope_state._compat_ns.pop(key, default)
- return scope_state._compat_ns.get(key, default)
-
-
-def set_litestar_scope_state(scope: Scope, key: str, value: Any) -> None:
- """Set an internal value in connection scope state.
-
- Args:
- scope: The connection scope.
- key: Key to set under internal namespace in scope state.
- value: Value for key.
- """
- scope_state = ScopeState.from_scope(scope)
- if hasattr(scope_state, key):
- setattr(scope_state, key, value)
- else:
- scope_state._compat_ns[key] = value
-
-
-def delete_litestar_scope_state(scope: Scope, key: str) -> None:
- """Delete an internal value from connection scope state.
-
- Args:
- scope: The connection scope.
- key: Key to set under internal namespace in scope state.
- """
- scope_state = ScopeState.from_scope(scope)
- if hasattr(scope_state, key):
- setattr(scope_state, key, Empty)
- else:
- del scope_state._compat_ns[key]
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/sequence.py b/venv/lib/python3.11/site-packages/litestar/utils/sequence.py
deleted file mode 100644
index 01ef1a8..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/sequence.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from __future__ import annotations
-
-from typing import Callable, Sequence, TypeVar
-
-__all__ = ("find_index", "unique")
-
-
-T = TypeVar("T")
-
-
-def find_index(target_list: Sequence[T], predicate: Callable[[T], bool]) -> int:
- """Find element in list given a key and value.
-
- List elements can be dicts or classes
- """
- return next((i for i, element in enumerate(target_list) if predicate(element)), -1)
-
-
-def unique(value: Sequence[T]) -> list[T]:
- """Return all unique values in a given sequence or iterator."""
- try:
- return list(set(value))
- except TypeError:
- output: list[T] = []
- for element in value:
- if element not in output:
- output.append(element)
- return output
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/signature.py b/venv/lib/python3.11/site-packages/litestar/utils/signature.py
deleted file mode 100644
index eb58599..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/signature.py
+++ /dev/null
@@ -1,267 +0,0 @@
-from __future__ import annotations
-
-import sys
-import typing
-from copy import deepcopy
-from dataclasses import dataclass, replace
-from inspect import Signature, getmembers, isclass, ismethod
-from itertools import chain
-from typing import TYPE_CHECKING, Any, Union
-
-from typing_extensions import Annotated, Self, get_args, get_origin, get_type_hints
-
-from litestar import connection, datastructures, types
-from litestar.exceptions import ImproperlyConfiguredException
-from litestar.types import Empty
-from litestar.typing import FieldDefinition
-from litestar.utils.typing import unwrap_annotation
-
-if TYPE_CHECKING:
- from typing import Sequence
-
- from litestar.types import AnyCallable
-
-if sys.version_info < (3, 11):
- from typing import _get_defaults # type: ignore[attr-defined]
-else:
-
- def _get_defaults(_: Any) -> Any: ...
-
-
-__all__ = (
- "add_types_to_signature_namespace",
- "get_fn_type_hints",
- "ParsedSignature",
-)
-
-_GLOBAL_NAMES = {
- namespace: export
- for namespace, export in chain(
- tuple(getmembers(types)), tuple(getmembers(connection)), tuple(getmembers(datastructures))
- )
- if namespace[0].isupper() and namespace in chain(types.__all__, connection.__all__, datastructures.__all__) # pyright: ignore
-}
-"""A mapping of names used for handler signature forward-ref resolution.
-
-This allows users to include these names within an `if TYPE_CHECKING:` block in their handler module.
-"""
-
-
-def _unwrap_implicit_optional_hints(defaults: dict[str, Any], hints: dict[str, Any]) -> dict[str, Any]:
- """Unwrap implicit optional hints.
-
- On Python<3.11, if a function parameter annotation has a ``None`` default, it is unconditionally wrapped in an
- ``Optional`` type.
-
- If the annotation is not annotated, then any nested unions are flattened, e.g.,:
-
- .. code-block:: python
-
- def foo(a: Optional[Union[str, int]] = None): ...
-
- ...will become `Union[str, int, NoneType]`.
-
- However, if the annotation is annotated, then we end up with an optional union around the annotated type, e.g.,:
-
- .. code-block:: python
-
- def foo(a: Annotated[Optional[Union[str, int]], ...] = None): ...
-
- ... becomes `Union[Annotated[Union[str, int, NoneType], ...], NoneType]`
-
- This function makes the latter case consistent with the former by either removing the outer union if it is redundant
- or flattening the union if it is not. The latter case would become `Annotated[Union[str, int, NoneType], ...]`.
-
- Args:
- defaults: Mapping of names to default values.
- hints: Mapping of names to types.
-
- Returns:
- Mapping of names to types.
- """
-
- def _is_two_arg_optional(origin_: Any, args_: Any) -> bool:
- """Check if a type is a two-argument optional type.
-
- If the type has been wrapped in `Optional` by `get_type_hints()` it will always be a union of a type and
- `NoneType`.
-
- See: https://github.com/litestar-org/litestar/pull/2516
- """
- return origin_ is Union and len(args_) == 2 and args_[1] is type(None)
-
- def _is_any_optional(origin_: Any, args_: tuple[Any, ...]) -> bool:
- """Detect if a type is a union with `NoneType`.
-
- After detecting that a type is a two-argument optional type, this function can be used to detect if the
- inner type is a union with `NoneType` at all.
-
- We only want to perform the unwrapping of the optional union if the inner type is optional as well.
- """
- return origin_ is Union and any(arg is type(None) for arg in args_)
-
- for name, default in defaults.items():
- if default is not None:
- continue
-
- hint = hints[name]
- origin = get_origin(hint)
- args = get_args(hint)
-
- if _is_two_arg_optional(origin, args):
- unwrapped_inner, meta, wrappers = unwrap_annotation(args[0])
-
- if Annotated not in wrappers:
- continue
-
- inner_args = get_args(unwrapped_inner)
-
- if not _is_any_optional(get_origin(unwrapped_inner), inner_args):
- # this is where hint is like `Union[Annotated[Union[str, int], ...], NoneType]`, we add the outer union
- # into the inner one, and re-wrap with Annotated
- union_args = (*(inner_args or (unwrapped_inner,)), type(None))
- # calling `__class_getitem__` directly as in earlier py vers it is a syntax error to unpack into
- # the getitem brackets, e.g., Annotated[T, *meta].
- hints[name] = Annotated.__class_getitem__((Union[union_args], *meta)) # type: ignore[attr-defined]
- continue
-
- # this is where hint is like `Union[Annotated[Union[str, NoneType], ...], NoneType]`, we remove the
- # redundant outer union
- hints[name] = args[0]
- return hints
-
-
-def get_fn_type_hints(fn: Any, namespace: dict[str, Any] | None = None) -> dict[str, Any]:
- """Resolve type hints for ``fn``.
-
- Args:
- fn: Callable that is being inspected
- namespace: Extra names for resolution of forward references.
-
- Returns:
- Mapping of names to types.
- """
- fn_to_inspect: Any = fn
-
- module_name = fn_to_inspect.__module__
-
- if isclass(fn_to_inspect):
- fn_to_inspect = fn_to_inspect.__init__
-
- # detect objects that are not functions and that have a `__call__` method
- if callable(fn_to_inspect) and ismethod(fn_to_inspect.__call__):
- fn_to_inspect = fn_to_inspect.__call__
-
- # inspect the underlying function for methods
- if hasattr(fn_to_inspect, "__func__"):
- fn_to_inspect = fn_to_inspect.__func__
-
- # Order important. If a litestar name has been overridden in the function module, we want
- # to use that instead of the litestar one.
- namespace = {
- **_GLOBAL_NAMES,
- **vars(typing),
- **vars(sys.modules[module_name]),
- **(namespace or {}),
- }
- hints = get_type_hints(fn_to_inspect, globalns=namespace, include_extras=True)
-
- if sys.version_info < (3, 11):
- # see https://github.com/litestar-org/litestar/pull/2516
- defaults = _get_defaults(fn_to_inspect)
- hints = _unwrap_implicit_optional_hints(defaults, hints)
-
- return hints
-
-
-@dataclass(frozen=True)
-class ParsedSignature:
- """Parsed signature.
-
- This object is the primary source of handler/dependency signature information.
-
- The only post-processing that occurs is the conversion of any forward referenced type annotations.
- """
-
- __slots__ = ("parameters", "return_type", "original_signature")
-
- parameters: dict[str, FieldDefinition]
- """A mapping of parameter names to ParsedSignatureParameter instances."""
- return_type: FieldDefinition
- """The return annotation of the callable."""
- original_signature: Signature
- """The raw signature as returned by :func:`inspect.signature`"""
-
- def __deepcopy__(self, memo: dict[str, Any]) -> Self:
- return type(self)(
- parameters={k: deepcopy(v) for k, v in self.parameters.items()},
- return_type=deepcopy(self.return_type),
- original_signature=deepcopy(self.original_signature),
- )
-
- @classmethod
- def from_fn(cls, fn: AnyCallable, signature_namespace: dict[str, Any]) -> Self:
- """Parse a function signature.
-
- Args:
- fn: Any callable.
- signature_namespace: mapping of names to types for forward reference resolution
-
- Returns:
- ParsedSignature
- """
- signature = Signature.from_callable(fn)
- fn_type_hints = get_fn_type_hints(fn, namespace=signature_namespace)
-
- return cls.from_signature(signature, fn_type_hints)
-
- @classmethod
- def from_signature(cls, signature: Signature, fn_type_hints: dict[str, type]) -> Self:
- """Parse an :class:`inspect.Signature` instance.
-
- Args:
- signature: An :class:`inspect.Signature` instance.
- fn_type_hints: mapping of types
-
- Returns:
- ParsedSignature
- """
-
- parameters = tuple(
- FieldDefinition.from_parameter(parameter=parameter, fn_type_hints=fn_type_hints)
- for name, parameter in signature.parameters.items()
- if name not in ("self", "cls")
- )
-
- return_type = FieldDefinition.from_annotation(fn_type_hints.get("return", Any))
-
- return cls(
- parameters={p.name: p for p in parameters},
- return_type=return_type if "return" in fn_type_hints else replace(return_type, annotation=Empty),
- original_signature=signature,
- )
-
-
-def add_types_to_signature_namespace(
- signature_types: Sequence[Any], signature_namespace: dict[str, Any]
-) -> dict[str, Any]:
- """Add types to ith signature namespace mapping.
-
- Types are added mapped to their `__name__` attribute.
-
- Args:
- signature_types: A list of types to add to the signature namespace.
- signature_namespace: The signature namespace to add types to.
-
- Raises:
- ImproperlyConfiguredException: If a type is already defined in the signature namespace.
- AttributeError: If a type does not have a `__name__` attribute.
-
- Returns:
- The updated signature namespace.
- """
- for typ in signature_types:
- if (name := typ.__name__) in signature_namespace:
- raise ImproperlyConfiguredException(f"Type '{name}' is already defined in the signature namespace")
- signature_namespace[name] = typ
- return signature_namespace
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/sync.py b/venv/lib/python3.11/site-packages/litestar/utils/sync.py
deleted file mode 100644
index 02acabf..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/sync.py
+++ /dev/null
@@ -1,79 +0,0 @@
-from __future__ import annotations
-
-from typing import (
- AsyncGenerator,
- Awaitable,
- Callable,
- Generic,
- Iterable,
- Iterator,
- TypeVar,
-)
-
-from typing_extensions import ParamSpec
-
-from litestar.concurrency import sync_to_thread
-from litestar.utils.predicates import is_async_callable
-
-__all__ = ("ensure_async_callable", "AsyncIteratorWrapper", "AsyncCallable", "is_async_callable")
-
-
-P = ParamSpec("P")
-T = TypeVar("T")
-
-
-def ensure_async_callable(fn: Callable[P, T]) -> Callable[P, Awaitable[T]]:
- """Ensure that ``fn`` is an asynchronous callable.
- If it is an asynchronous, return the original object, else wrap it in an
- ``AsyncCallable``
- """
- if is_async_callable(fn):
- return fn
- return AsyncCallable(fn) # pyright: ignore
-
-
-class AsyncCallable:
- """Wrap a given callable to be called in a thread pool using
- ``anyio.to_thread.run_sync``, keeping a reference to the original callable as
- :attr:`func`
- """
-
- def __init__(self, fn: Callable[P, T]) -> None: # pyright: ignore
- self.func = fn
-
- def __call__(self, *args: P.args, **kwargs: P.kwargs) -> Awaitable[T]: # pyright: ignore
- return sync_to_thread(self.func, *args, **kwargs) # pyright: ignore
-
-
-class AsyncIteratorWrapper(Generic[T]):
- """Asynchronous generator, wrapping an iterable or iterator."""
-
- __slots__ = ("iterator", "generator")
-
- def __init__(self, iterator: Iterator[T] | Iterable[T]) -> None:
- """Take a sync iterator or iterable and yields values from it asynchronously.
-
- Args:
- iterator: A sync iterator or iterable.
- """
- self.iterator = iterator if isinstance(iterator, Iterator) else iter(iterator)
- self.generator = self._async_generator()
-
- def _call_next(self) -> T:
- try:
- return next(self.iterator)
- except StopIteration as e:
- raise ValueError from e
-
- async def _async_generator(self) -> AsyncGenerator[T, None]:
- while True:
- try:
- yield await sync_to_thread(self._call_next)
- except ValueError:
- return
-
- def __aiter__(self) -> AsyncIteratorWrapper[T]:
- return self
-
- async def __anext__(self) -> T:
- return await self.generator.__anext__()
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/typing.py b/venv/lib/python3.11/site-packages/litestar/utils/typing.py
deleted file mode 100644
index 9da6c2a..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/typing.py
+++ /dev/null
@@ -1,284 +0,0 @@
-from __future__ import annotations
-
-import re
-from collections import abc, defaultdict, deque
-from typing import (
- AbstractSet,
- Any,
- AsyncGenerator,
- AsyncIterable,
- AsyncIterator,
- Awaitable,
- Collection,
- Container,
- Coroutine,
- DefaultDict,
- Deque,
- Dict,
- FrozenSet,
- Generator,
- ItemsView,
- Iterable,
- Iterator,
- KeysView,
- List,
- Mapping,
- MappingView,
- MutableMapping,
- MutableSequence,
- MutableSet,
- Reversible,
- Sequence,
- Set,
- Tuple,
- TypeVar,
- Union,
- ValuesView,
- cast,
-)
-
-from typing_extensions import Annotated, NotRequired, Required, get_args, get_origin, get_type_hints
-
-from litestar.types.builtin_types import NoneType, UnionTypes
-
-__all__ = (
- "get_instantiable_origin",
- "get_origin_or_inner_type",
- "get_safe_generic_origin",
- "instantiable_type_mapping",
- "make_non_optional_union",
- "safe_generic_origin_map",
- "unwrap_annotation",
-)
-
-
-T = TypeVar("T")
-UnionT = TypeVar("UnionT", bound="Union")
-
-tuple_types_regex = re.compile(
- "^"
- + "|".join(
- [*[repr(x) for x in (List, Sequence, Iterable, Iterator, Tuple, Deque)], "tuple", "list", "collections.deque"]
- )
-)
-
-instantiable_type_mapping = {
- AbstractSet: set,
- DefaultDict: defaultdict,
- Deque: deque,
- Dict: dict,
- FrozenSet: frozenset,
- List: list,
- Mapping: dict,
- MutableMapping: dict,
- MutableSequence: list,
- MutableSet: set,
- Sequence: list,
- Set: set,
- Tuple: tuple,
- abc.Mapping: dict,
- abc.MutableMapping: dict,
- abc.MutableSequence: list,
- abc.MutableSet: set,
- abc.Sequence: list,
- abc.Set: set,
- defaultdict: defaultdict,
- deque: deque,
- dict: dict,
- frozenset: frozenset,
- list: list,
- set: set,
- tuple: tuple,
-}
-
-safe_generic_origin_map = {
- set: AbstractSet,
- defaultdict: DefaultDict,
- deque: Deque,
- dict: Dict,
- frozenset: FrozenSet,
- list: List,
- tuple: Tuple,
- abc.Mapping: Mapping,
- abc.MutableMapping: MutableMapping,
- abc.MutableSequence: MutableSequence,
- abc.MutableSet: MutableSet,
- abc.Sequence: Sequence,
- abc.Set: AbstractSet,
- abc.Collection: Collection,
- abc.Container: Container,
- abc.ItemsView: ItemsView,
- abc.KeysView: KeysView,
- abc.MappingView: MappingView,
- abc.ValuesView: ValuesView,
- abc.Iterable: Iterable,
- abc.Iterator: Iterator,
- abc.Generator: Generator,
- abc.Reversible: Reversible,
- abc.Coroutine: Coroutine,
- abc.AsyncGenerator: AsyncGenerator,
- abc.AsyncIterable: AsyncIterable,
- abc.AsyncIterator: AsyncIterator,
- abc.Awaitable: Awaitable,
- **{union_t: Union for union_t in UnionTypes},
-}
-"""A mapping of types to equivalent types that are safe to be used as generics across all Python versions.
-
-This is necessary because occasionally we want to rebuild a generic outer type with different args, and types such as
-``collections.abc.Mapping``, are not valid generic types in Python 3.8.
-"""
-
-wrapper_type_set = {Annotated, Required, NotRequired}
-"""Types that always contain a wrapped type annotation as their first arg."""
-
-
-def normalize_type_annotation(annotation: Any) -> Any:
- """Normalize a type annotation to a standard form."""
- return instantiable_type_mapping.get(annotation, annotation)
-
-
-def make_non_optional_union(annotation: UnionT | None) -> UnionT:
- """Make a :data:`Union <typing.Union>` type that excludes ``NoneType``.
-
- Args:
- annotation: A type annotation.
-
- Returns:
- The union with all original members, except ``NoneType``.
- """
- args = tuple(tp for tp in get_args(annotation) if tp is not NoneType)
- return cast("UnionT", Union[args]) # pyright: ignore
-
-
-def unwrap_annotation(annotation: Any) -> tuple[Any, tuple[Any, ...], set[Any]]:
- """Remove "wrapper" annotation types, such as ``Annotated``, ``Required``, and ``NotRequired``.
-
- Note:
- ``annotation`` should have been retrieved from :func:`get_type_hints()` with ``include_extras=True``. This
- ensures that any nested ``Annotated`` types are flattened according to the PEP 593 specification.
-
- Args:
- annotation: A type annotation.
-
- Returns:
- A tuple of the unwrapped annotation and any ``Annotated`` metadata, and a set of any wrapper types encountered.
- """
- origin = get_origin(annotation)
- wrappers = set()
- metadata = []
- while origin in wrapper_type_set:
- wrappers.add(origin)
- annotation, *meta = get_args(annotation)
- metadata.extend(meta)
- origin = get_origin(annotation)
- return annotation, tuple(metadata), wrappers
-
-
-def get_origin_or_inner_type(annotation: Any) -> Any:
- """Get origin or unwrap it. Returns None for non-generic types.
-
- Args:
- annotation: A type annotation.
-
- Returns:
- Any type.
- """
- origin = get_origin(annotation)
- if origin in wrapper_type_set:
- inner, _, _ = unwrap_annotation(annotation)
- # we need to recursively call here 'get_origin_or_inner_type' because we might be dealing
- # with a generic type alias e.g. Annotated[dict[str, list[int]]
- origin = get_origin_or_inner_type(inner)
- return instantiable_type_mapping.get(origin, origin)
-
-
-def get_safe_generic_origin(origin_type: Any, annotation: Any) -> Any:
- """Get a type that is safe to use as a generic type across all supported Python versions.
-
- If a builtin collection type is annotated without generic args, e.g, ``a: dict``, then the origin type will be
- ``None``. In this case, we can use the annotation to determine the correct generic type, if one exists.
-
- Args:
- origin_type: A type - would be the return value of :func:`get_origin()`.
- annotation: Type annotation associated with the origin type. Should be unwrapped from any wrapper types, such
- as ``Annotated``.
-
- Returns:
- The ``typing`` module equivalent of the given type, if it exists. Otherwise, the original type is returned.
- """
- if origin_type is None:
- return safe_generic_origin_map.get(annotation)
- return safe_generic_origin_map.get(origin_type, origin_type)
-
-
-def get_instantiable_origin(origin_type: Any, annotation: Any) -> Any:
- """Get a type that is safe to instantiate for the given origin type.
-
- If a builtin collection type is annotated without generic args, e.g, ``a: dict``, then the origin type will be
- ``None``. In this case, we can use the annotation to determine the correct instantiable type, if one exists.
-
- Args:
- origin_type: A type - would be the return value of :func:`get_origin()`.
- annotation: Type annotation associated with the origin type. Should be unwrapped from any wrapper types, such
- as ``Annotated``.
-
- Returns:
- A builtin type that is safe to instantiate for the given origin type.
- """
- if origin_type is None:
- return instantiable_type_mapping.get(annotation)
- return instantiable_type_mapping.get(origin_type, origin_type)
-
-
-def get_type_hints_with_generics_resolved(
- annotation: Any,
- globalns: dict[str, Any] | None = None,
- localns: dict[str, Any] | None = None,
- include_extras: bool = False,
- type_hints: dict[str, Any] | None = None,
-) -> dict[str, Any]:
- """Get the type hints for the given object after resolving the generic types as much as possible.
-
- Args:
- annotation: A type annotation.
- globalns: The global namespace.
- localns: The local namespace.
- include_extras: A flag indicating whether to include the ``Annotated[T, ...]`` or not.
- type_hints: Already resolved type hints
- """
- origin = get_origin(annotation)
-
- if origin is None:
- # Implies the generic types have not been specified in the annotation
- if type_hints is None: # pragma: no cover
- type_hints = get_type_hints(annotation, globalns=globalns, localns=localns, include_extras=include_extras)
- typevar_map = {p: p for p in annotation.__parameters__}
- else:
- if type_hints is None: # pragma: no cover
- type_hints = get_type_hints(origin, globalns=globalns, localns=localns, include_extras=include_extras)
- # the __parameters__ is only available on the origin itself and not the annotation
- typevar_map = dict(zip(origin.__parameters__, get_args(annotation)))
-
- return {n: _substitute_typevars(type_, typevar_map) for n, type_ in type_hints.items()}
-
-
-def _substitute_typevars(obj: Any, typevar_map: Mapping[Any, Any]) -> Any:
- if params := getattr(obj, "__parameters__", None):
- args = tuple(_substitute_typevars(typevar_map.get(p, p), typevar_map) for p in params)
- return obj[args]
-
- if isinstance(obj, TypeVar):
- # If there's a mapped type for the TypeVar already, then it should be returned instead
- # of considering __constraints__ or __bound__. For a generic `Foo[T]`, if Foo[int] is given
- # then int should be returned and if `Foo` is given then the __bounds__ and __constraints__
- # should be considered.
- if (type_ := typevar_map.get(obj, None)) is not None and not isinstance(type_, TypeVar):
- return type_
-
- if obj.__bound__ is not None:
- return obj.__bound__
-
- if obj.__constraints__:
- return Union[obj.__constraints__] # pyright: ignore
-
- return obj
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/version.py b/venv/lib/python3.11/site-packages/litestar/utils/version.py
deleted file mode 100644
index d7974eb..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/version.py
+++ /dev/null
@@ -1,62 +0,0 @@
-from __future__ import annotations
-
-import re
-import sys
-from typing import Literal, NamedTuple
-
-__all__ = ("Version", "get_version", "parse_version")
-
-
-if sys.version_info >= (3, 10):
- import importlib.metadata as importlib_metadata
-else:
- import importlib_metadata
-
-
-_ReleaseLevel = Literal["alpha", "beta", "rc", "final"]
-_PRE_RELEASE_TAGS = {"alpha", "a", "beta", "b", "rc"}
-_PRE_RELEASE_TAGS_CONVERSIONS: dict[str, _ReleaseLevel] = {"a": "alpha", "b": "beta"}
-
-_VERSION_PARTS_RE = re.compile(r"(\d+|[a-z]+|\.)")
-
-
-class Version(NamedTuple):
- """Litestar version information"""
-
- major: int
- minor: int
- patch: int
- release_level: _ReleaseLevel
- serial: int
-
- def formatted(self, short: bool = False) -> str:
- version = f"{self.major}.{self.minor}.{self.patch}"
- if not short:
- version += f"{self.release_level}{self.serial}"
- return version
-
-
-def parse_version(raw_version: str) -> Version:
- """Parse a version string into a :class:`Version`"""
- parts = [p for p in _VERSION_PARTS_RE.split(raw_version) if p and p != "."]
- release_level: _ReleaseLevel = "final"
- serial = "0"
-
- if len(parts) == 3:
- major, minor, patch = parts
- elif len(parts) == 5:
- major, minor, patch, release_level, serial = parts # type: ignore[assignment]
- if release_level not in _PRE_RELEASE_TAGS:
- raise ValueError(f"Invalid release level: {release_level}")
- release_level = _PRE_RELEASE_TAGS_CONVERSIONS.get(release_level, release_level)
- else:
- raise ValueError(f"Invalid version: {raw_version}")
-
- return Version(
- major=int(major), minor=int(minor), patch=int(patch), release_level=release_level, serial=int(serial)
- )
-
-
-def get_version() -> Version:
- """Get the version of the installed litestar package"""
- return parse_version(importlib_metadata.version("litestar"))
diff --git a/venv/lib/python3.11/site-packages/litestar/utils/warnings.py b/venv/lib/python3.11/site-packages/litestar/utils/warnings.py
deleted file mode 100644
index e20484b..0000000
--- a/venv/lib/python3.11/site-packages/litestar/utils/warnings.py
+++ /dev/null
@@ -1,51 +0,0 @@
-import os
-import warnings
-
-from litestar.exceptions import LitestarWarning
-from litestar.types import AnyCallable, AnyGenerator
-
-
-def warn_implicit_sync_to_thread(source: AnyCallable, stacklevel: int = 2) -> None:
- if os.getenv("LITESTAR_WARN_IMPLICIT_SYNC_TO_THREAD") == "0":
- return
-
- warnings.warn(
- f"Use of a synchronous callable {source} without setting sync_to_thread is "
- "discouraged since synchronous callables can block the main thread if they "
- "perform blocking operations. If the callable is guaranteed to be non-blocking, "
- "you can set sync_to_thread=False to skip this warning, or set the environment"
- "variable LITESTAR_WARN_IMPLICIT_SYNC_TO_THREAD=0 to disable warnings of this "
- "type entirely.",
- category=LitestarWarning,
- stacklevel=stacklevel,
- )
-
-
-def warn_sync_to_thread_with_async_callable(source: AnyCallable, stacklevel: int = 2) -> None:
- if os.getenv("LITESTAR_WARN_SYNC_TO_THREAD_WITH_ASYNC") == "0":
- return
-
- warnings.warn(
- f"Use of an asynchronous callable {source} with sync_to_thread; sync_to_thread "
- "has no effect on async callable. You can disable this warning by setting "
- "LITESTAR_WARN_SYNC_TO_THREAD_WITH_ASYNC=0",
- category=LitestarWarning,
- stacklevel=stacklevel,
- )
-
-
-def warn_sync_to_thread_with_generator(source: AnyGenerator, stacklevel: int = 2) -> None:
- if os.getenv("LITESTAR_WARN_SYNC_TO_THREAD_WITH_GENERATOR") == "0":
- return
-
- warnings.warn(
- f"Use of generator {source} with sync_to_thread; sync_to_thread has no effect "
- "on generators. You can disable this warning by setting "
- "LITESTAR_WARN_SYNC_TO_THREAD_WITH_GENERATOR=0",
- category=LitestarWarning,
- stacklevel=stacklevel,
- )
-
-
-def warn_pdb_on_exception(stacklevel: int = 2) -> None:
- warnings.warn("Python Debugger on exception enabled", category=LitestarWarning, stacklevel=stacklevel)