summaryrefslogtreecommitdiff
path: root/venv/lib/python3.11/site-packages/litestar/contrib
diff options
context:
space:
mode:
Diffstat (limited to 'venv/lib/python3.11/site-packages/litestar/contrib')
-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.pycbin0 -> 200 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/jinja.cpython-311.pycbin0 -> 5921 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/mako.cpython-311.pycbin0 -> 7742 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/minijinja.cpython-311.pycbin0 -> 11427 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/minijnja.cpython-311.pycbin0 -> 871 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/piccolo.cpython-311.pycbin0 -> 6290 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.pycbin0 -> 297 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/attrs/__pycache__/attrs_schema_plugin.cpython-311.pycbin0 -> 3570 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.pycbin0 -> 205 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/_utils.cpython-311.pycbin0 -> 6781 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/request.cpython-311.pycbin0 -> 7932 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/response.cpython-311.pycbin0 -> 11070 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/types.cpython-311.pycbin0 -> 2382 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.pycbin0 -> 1090 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/jwt_auth.cpython-311.pycbin0 -> 481 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/jwt_token.cpython-311.pycbin0 -> 354 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/middleware.cpython-311.pycbin0 -> 432 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.pycbin0 -> 395 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/_utils.cpython-311.pycbin0 -> 1365 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/config.cpython-311.pycbin0 -> 4141 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/middleware.cpython-311.pycbin0 -> 3440 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.pycbin0 -> 447 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/config.cpython-311.pycbin0 -> 3378 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/controller.cpython-311.pycbin0 -> 2540 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/middleware.cpython-311.pycbin0 -> 11494 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.pycbin0 -> 3609 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/config.cpython-311.pycbin0 -> 207 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_di_plugin.cpython-311.pycbin0 -> 2541 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_dto_factory.cpython-311.pycbin0 -> 6096 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_init_plugin.cpython-311.pycbin0 -> 11810 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_schema_plugin.cpython-311.pycbin0 -> 14566 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/utils.cpython-311.pycbin0 -> 10487 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.pycbin0 -> 1212 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/exceptions.cpython-311.pycbin0 -> 1258 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/filters.cpython-311.pycbin0 -> 1242 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/handlers.cpython-311.pycbin0 -> 1248 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/testing.cpython-311.pycbin0 -> 1269 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.pycbin0 -> 1231 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.pycbin0 -> 211 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/base.cpython-311.pycbin0 -> 1044 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/dto.cpython-311.pycbin0 -> 412 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/types.cpython-311.pycbin0 -> 487 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.pycbin0 -> 895 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/__pycache__/serialization.cpython-311.pycbin0 -> 414 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.pycbin0 -> 734 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/__pycache__/plugin.cpython-311.pycbin0 -> 403 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.pycbin0 -> 720 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/asyncio.cpython-311.pycbin0 -> 1166 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/common.cpython-311.pycbin0 -> 684 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/compat.cpython-311.pycbin0 -> 1819 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/engine.cpython-311.pycbin0 -> 388 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/sync.cpython-311.pycbin0 -> 1136 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.pycbin0 -> 525 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/_async.cpython-311.pycbin0 -> 389 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/_sync.cpython-311.pycbin0 -> 389 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/_util.cpython-311.pycbin0 -> 446 bytes
-rw-r--r--venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/types.cpython-311.pycbin0 -> 501 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
114 files changed, 3020 insertions, 0 deletions
diff --git a/venv/lib/python3.11/site-packages/litestar/contrib/__init__.py b/venv/lib/python3.11/site-packages/litestar/contrib/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/__init__.py
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
new file mode 100644
index 0000000..fc2f5bc
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/__init__.cpython-311.pyc
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
new file mode 100644
index 0000000..f58d015
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/jinja.cpython-311.pyc
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
new file mode 100644
index 0000000..09bede9
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/mako.cpython-311.pyc
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
new file mode 100644
index 0000000..05ada30
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/minijinja.cpython-311.pyc
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
new file mode 100644
index 0000000..3006e82
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/minijnja.cpython-311.pyc
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
new file mode 100644
index 0000000..20ea290
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/__pycache__/piccolo.cpython-311.pyc
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
new file mode 100644
index 0000000..ddd2a3f
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/attrs/__init__.py
@@ -0,0 +1,3 @@
+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
new file mode 100644
index 0000000..a224be6
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/attrs/__pycache__/__init__.cpython-311.pyc
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
new file mode 100644
index 0000000..730252a
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/attrs/__pycache__/attrs_schema_plugin.cpython-311.pyc
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
new file mode 100644
index 0000000..cf67fe4
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/attrs/attrs_schema_plugin.py
@@ -0,0 +1,49 @@
+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
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__init__.py
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
new file mode 100644
index 0000000..31d4982
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/__init__.cpython-311.pyc
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
new file mode 100644
index 0000000..d860774
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/_utils.cpython-311.pyc
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
new file mode 100644
index 0000000..65b99d9
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/request.cpython-311.pyc
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
new file mode 100644
index 0000000..0bb64b8
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/response.cpython-311.pyc
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
new file mode 100644
index 0000000..0af7128
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/__pycache__/types.cpython-311.pyc
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
new file mode 100644
index 0000000..894fd25
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/_utils.py
@@ -0,0 +1,148 @@
+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
new file mode 100644
index 0000000..b4fad18
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/request.py
@@ -0,0 +1,113 @@
+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
new file mode 100644
index 0000000..0a56e1f
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/response.py
@@ -0,0 +1,200 @@
+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
new file mode 100644
index 0000000..aa8f9cd
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/htmx/types.py
@@ -0,0 +1,54 @@
+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
new file mode 100644
index 0000000..4e8057b
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/jinja.py
@@ -0,0 +1,114 @@
+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
new file mode 100644
index 0000000..70a4f75
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__init__.py
@@ -0,0 +1,32 @@
+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
new file mode 100644
index 0000000..1515862
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/__init__.cpython-311.pyc
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
new file mode 100644
index 0000000..44907f6
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/jwt_auth.cpython-311.pyc
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
new file mode 100644
index 0000000..2ffdb24
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/jwt_token.cpython-311.pyc
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
new file mode 100644
index 0000000..334e3fa
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/jwt/__pycache__/middleware.cpython-311.pyc
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
new file mode 100644
index 0000000..e8ffb48
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/jwt/jwt_auth.py
@@ -0,0 +1,5 @@
+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
new file mode 100644
index 0000000..882373f
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/jwt/jwt_token.py
@@ -0,0 +1,5 @@
+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
new file mode 100644
index 0000000..e0ad413
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/jwt/middleware.py
@@ -0,0 +1,5 @@
+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
new file mode 100644
index 0000000..9cb4c47
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/mako.py
@@ -0,0 +1,146 @@
+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
new file mode 100644
index 0000000..6007a18
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/minijinja.py
@@ -0,0 +1,216 @@
+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
new file mode 100644
index 0000000..13c295a
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/minijnja.py
@@ -0,0 +1,18 @@
+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
new file mode 100644
index 0000000..3f93611
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__init__.py
@@ -0,0 +1,4 @@
+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
new file mode 100644
index 0000000..799a915
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/__init__.cpython-311.pyc
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
new file mode 100644
index 0000000..c401f9c
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/_utils.cpython-311.pyc
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
new file mode 100644
index 0000000..b41bc7e
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/config.cpython-311.pyc
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
new file mode 100644
index 0000000..291b510
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/__pycache__/middleware.cpython-311.pyc
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
new file mode 100644
index 0000000..0ba7cb9
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/_utils.py
@@ -0,0 +1,31 @@
+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
new file mode 100644
index 0000000..c0cce8a
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/config.py
@@ -0,0 +1,102 @@
+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
new file mode 100644
index 0000000..762bae9
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/opentelemetry/middleware.py
@@ -0,0 +1,60 @@
+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
new file mode 100644
index 0000000..73bd271
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/piccolo.py
@@ -0,0 +1,107 @@
+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
new file mode 100644
index 0000000..1ccb494
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__init__.py
@@ -0,0 +1,5 @@
+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
new file mode 100644
index 0000000..c6c5558
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/__init__.cpython-311.pyc
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
new file mode 100644
index 0000000..a998104
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/config.cpython-311.pyc
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
new file mode 100644
index 0000000..012b4be
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/controller.cpython-311.pyc
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
new file mode 100644
index 0000000..2c08508
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/__pycache__/middleware.cpython-311.pyc
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
new file mode 100644
index 0000000..b77dab0
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/config.py
@@ -0,0 +1,64 @@
+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
new file mode 100644
index 0000000..15f5bf1
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/controller.py
@@ -0,0 +1,53 @@
+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
new file mode 100644
index 0000000..50bc7cb
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/prometheus/middleware.py
@@ -0,0 +1,181 @@
+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
new file mode 100644
index 0000000..9bab707
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__init__.py
@@ -0,0 +1,69 @@
+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
new file mode 100644
index 0000000..a62eb0f
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/__init__.cpython-311.pyc
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
new file mode 100644
index 0000000..5515df6
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/config.cpython-311.pyc
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
new file mode 100644
index 0000000..f8c4e00
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_di_plugin.cpython-311.pyc
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
new file mode 100644
index 0000000..490108e
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_dto_factory.cpython-311.pyc
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
new file mode 100644
index 0000000..13788d4
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_init_plugin.cpython-311.pyc
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
new file mode 100644
index 0000000..8b0946b
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/pydantic_schema_plugin.cpython-311.pyc
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
new file mode 100644
index 0000000..dbb0e54
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/__pycache__/utils.cpython-311.pyc
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
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/config.py
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
new file mode 100644
index 0000000..2096fd4
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_di_plugin.py
@@ -0,0 +1,26 @@
+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
new file mode 100644
index 0000000..d61f95d
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_dto_factory.py
@@ -0,0 +1,110 @@
+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
new file mode 100644
index 0000000..1261cd8
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_init_plugin.py
@@ -0,0 +1,182 @@
+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
new file mode 100644
index 0000000..2c189e4
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/pydantic_schema_plugin.py
@@ -0,0 +1,317 @@
+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
new file mode 100644
index 0000000..6aee322
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/pydantic/utils.py
@@ -0,0 +1,214 @@
+# 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
new file mode 100644
index 0000000..3a329c9
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/repository/__init__.py
@@ -0,0 +1,20 @@
+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
new file mode 100644
index 0000000..1b3c01a
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/__init__.cpython-311.pyc
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
new file mode 100644
index 0000000..29868c6
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/exceptions.cpython-311.pyc
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
new file mode 100644
index 0000000..a69925c
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/filters.cpython-311.pyc
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
new file mode 100644
index 0000000..5d82074
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/handlers.cpython-311.pyc
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
new file mode 100644
index 0000000..474bdcf
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/repository/__pycache__/testing.cpython-311.pyc
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
new file mode 100644
index 0000000..17efc1b
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/repository/abc/__init__.py
@@ -0,0 +1,20 @@
+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
new file mode 100644
index 0000000..666c136
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/repository/abc/__pycache__/__init__.cpython-311.pyc
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
new file mode 100644
index 0000000..1e7e738
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/repository/exceptions.py
@@ -0,0 +1,20 @@
+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
new file mode 100644
index 0000000..3736a76
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/repository/filters.py
@@ -0,0 +1,20 @@
+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
new file mode 100644
index 0000000..b1174e4
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/repository/handlers.py
@@ -0,0 +1,20 @@
+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
new file mode 100644
index 0000000..b78fea8
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/repository/testing.py
@@ -0,0 +1,20 @@
+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
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__init__.py
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
new file mode 100644
index 0000000..1b0f40a
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/__init__.cpython-311.pyc
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
new file mode 100644
index 0000000..199862b
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/base.cpython-311.pyc
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
new file mode 100644
index 0000000..5467843
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/dto.cpython-311.pyc
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
new file mode 100644
index 0000000..09819d1
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/__pycache__/types.cpython-311.pyc
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
new file mode 100644
index 0000000..9ce9608
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/base.py
@@ -0,0 +1,38 @@
+"""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
new file mode 100644
index 0000000..beea75d
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/dto.py
@@ -0,0 +1,5 @@
+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
new file mode 100644
index 0000000..5bc913c
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/__init__.py
@@ -0,0 +1,28 @@
+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
new file mode 100644
index 0000000..019ff72
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/__pycache__/__init__.cpython-311.pyc
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
new file mode 100644
index 0000000..7bd0360
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/__pycache__/serialization.cpython-311.pyc
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
new file mode 100644
index 0000000..2e507c1
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/__init__.py
@@ -0,0 +1,23 @@
+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
new file mode 100644
index 0000000..43da1aa
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/__pycache__/__init__.cpython-311.pyc
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
new file mode 100644
index 0000000..e06ec42
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/__pycache__/plugin.cpython-311.pyc
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
new file mode 100644
index 0000000..f2e39da
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__init__.py
@@ -0,0 +1,16 @@
+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
new file mode 100644
index 0000000..2a316ef
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/__init__.cpython-311.pyc
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
new file mode 100644
index 0000000..23fe455
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/asyncio.cpython-311.pyc
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
new file mode 100644
index 0000000..6e83a95
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/common.cpython-311.pyc
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
new file mode 100644
index 0000000..4ba72bb
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/compat.cpython-311.pyc
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
new file mode 100644
index 0000000..1d4553b
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/engine.cpython-311.pyc
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
new file mode 100644
index 0000000..d777bb9
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/__pycache__/sync.cpython-311.pyc
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
new file mode 100644
index 0000000..434c761
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/asyncio.py
@@ -0,0 +1,24 @@
+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
new file mode 100644
index 0000000..9afc48c
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/common.py
@@ -0,0 +1,15 @@
+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
new file mode 100644
index 0000000..d76dea7
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/compat.py
@@ -0,0 +1,22 @@
+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
new file mode 100644
index 0000000..31c3f5e
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/engine.py
@@ -0,0 +1,5 @@
+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
new file mode 100644
index 0000000..48a029b
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/config/sync.py
@@ -0,0 +1,24 @@
+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
new file mode 100644
index 0000000..dbf814b
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/init/plugin.py
@@ -0,0 +1,5 @@
+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
new file mode 100644
index 0000000..539b194
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/plugins/serialization.py
@@ -0,0 +1,5 @@
+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
new file mode 100644
index 0000000..64a8359
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__init__.py
@@ -0,0 +1,11 @@
+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
new file mode 100644
index 0000000..3e6dacf
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/__init__.cpython-311.pyc
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
new file mode 100644
index 0000000..461fbad
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/_async.cpython-311.pyc
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
new file mode 100644
index 0000000..bd6d80f
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/_sync.cpython-311.pyc
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
new file mode 100644
index 0000000..561fd53
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/_util.cpython-311.pyc
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
new file mode 100644
index 0000000..fa8191e
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/__pycache__/types.cpython-311.pyc
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
new file mode 100644
index 0000000..417ec35
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/_async.py
@@ -0,0 +1,5 @@
+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
new file mode 100644
index 0000000..58ccbb8
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/_sync.py
@@ -0,0 +1,7 @@
+# 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
new file mode 100644
index 0000000..c0ce747
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/_util.py
@@ -0,0 +1,8 @@
+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
new file mode 100644
index 0000000..2a4204c
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/repository/types.py
@@ -0,0 +1,15 @@
+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
new file mode 100644
index 0000000..61fb75a
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/litestar/contrib/sqlalchemy/types.py
@@ -0,0 +1,11 @@
+from __future__ import annotations
+
+from advanced_alchemy.types import GUID, ORA_JSONB, BigIntIdentity, DateTimeUTC, JsonB
+
+__all__ = (
+ "GUID",
+ "ORA_JSONB",
+ "DateTimeUTC",
+ "BigIntIdentity",
+ "JsonB",
+)