We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Pydantic 1.9.1 deepcopy breaks Redis caching, possibly other things
I'm open to the possibility that this should be treated as an issue in Pydantic because it's a breaking change there, and https://github.com/samuelcolvin/pydantic/issues/4184 appears to be a variation of this.

I have a Starlite application which configures its caching as follows (excerpt from my actual `app.py`):

```python
import redis
import starlite

from .config import settings

cache_config = (
    starlite.CacheConfig(backend=redis.from_url(settings.CACHE_URL))
    if settings.CACHE_URL is not None
    else starlite.app.DEFAULT_CACHE_CONFIG
)
```

`config.settings` in this case is a `pydantic.BaseSettings` instance which reads the Redis URL from an environment variable, if set. The fallback logic is for local development where a Redis instance may not be running.

I recently did an upgrade of my dependency tree which moved from Pydantic 1.9.0 to Pydantic 1.9.1, and my web worker processes now fail to boot. Reverting to Pydantic 1.9.0 resolves this.

The failure occurs at instantiating the `Starlite` application object:

```python
File /opt/venv/lib/python3.10/site-packages/pydantic/decorator.py:40, in pydantic.decorator.validate_arguments.validate.wrapper_function()

File /opt/venv/lib/python3.10/site-packages/pydantic/decorator.py:133, in pydantic.decorator.ValidatedFunction.call()

File /opt/venv/lib/python3.10/site-packages/pydantic/decorator.py:130, in pydantic.decorator.ValidatedFunction.init_model_instance()

File /opt/venv/lib/python3.10/site-packages/pydantic/main.py:341, in pydantic.main.BaseModel.__init__()

ValidationError: 1 validation error for Init
cache_config
  cannot pickle '_thread.lock' object (type=type_error)
```

The root of the issue appears to be that in Pydantic 1.9.1, Pydantic defaults to performing a `copy.deepcopy()` of model members during validation, which in turn fails on encountering any non-pickle-able object (as in the above traceback where it attempts to `deepcopy()` a Redis client instance). Pydantic 1.9.0 performed only a shallow copy.

This behavior can be disabled by setting the `copy_on_model_validation` option to a false-y value in the config for a Pydantic model class, or by passing it in the `config` dictionary of the `validate_arguments` decorator, and that may be the simplest workaround to apply for now while Pydantic decides what to do about this. It may also be the correct long-term choice since it's likely that non-pickle-able objects, such as caching clients, will be passed in arguments to the `Starlite` constructor from time to time.

This issue appears to be present in any version of Starlite which decorates `Starlite.__init__()` with `validate_arguments`, when using Pydantic 1.9.1 (I've tested Starlite 1.7.3 and 1.3.3), and disappears on reverting to Pydantic 1.9.0.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `starlite/exceptions/utils.py`
Content:
```
1 from typing import Any, Dict, List, Optional, Union
2 
3 from pydantic import BaseModel
4 from starlette.exceptions import HTTPException as StarletteHTTPException
5 from starlette.status import HTTP_500_INTERNAL_SERVER_ERROR  # noqa: TC002
6 
7 from starlite.enums import MediaType
8 from starlite.response import Response
9 
10 from .exceptions import HTTPException
11 
12 __all__ = ["create_exception_response"]
13 
14 
15 class ExceptionResponseContent(BaseModel):
16     detail: Optional[str]
17     extra: Optional[Union[Dict[str, Any], List[Any]]]
18     status_code: int = HTTP_500_INTERNAL_SERVER_ERROR
19 
20 
21 def create_exception_response(exc: Exception) -> Response:
22     """
23     Constructs a response from an exception.
24 
25     For instances of either `starlite.exceptions.HTTPException` or `starlette.exceptions.HTTPException` the response
26     status code is drawn from the exception, otherwise response status is `HTTP_500_INTERNAL_SERVER_ERROR`.
27 
28     Args:
29         exc (Exception): Any exception.
30 
31     Returns:
32         Response
33     """
34     if isinstance(exc, (HTTPException, StarletteHTTPException)):
35         content = ExceptionResponseContent(detail=exc.detail, status_code=exc.status_code)
36         if isinstance(exc, HTTPException):
37             content.extra = exc.extra
38     else:
39         content = ExceptionResponseContent(detail=repr(exc))
40     return Response(
41         media_type=MediaType.JSON,
42         content=content.dict(exclude_none=True),
43         status_code=content.status_code,
44     )
45
```

Path: `starlite/config.py`
Content:
```
1 from enum import Enum
2 from typing import (
3     TYPE_CHECKING,
4     Any,
5     Callable,
6     Dict,
7     List,
8     Optional,
9     Tuple,
10     Type,
11     Union,
12 )
13 from urllib.parse import urlencode
14 
15 from pydantic import AnyUrl, BaseModel, DirectoryPath, constr, validator
16 from pydantic_openapi_schema.utils import construct_open_api_with_schema_class
17 from pydantic_openapi_schema.v3_1_0.contact import Contact
18 from pydantic_openapi_schema.v3_1_0.external_documentation import ExternalDocumentation
19 from pydantic_openapi_schema.v3_1_0.info import Info
20 from pydantic_openapi_schema.v3_1_0.license import License
21 from pydantic_openapi_schema.v3_1_0.open_api import OpenAPI
22 from pydantic_openapi_schema.v3_1_0.path_item import PathItem
23 from pydantic_openapi_schema.v3_1_0.reference import Reference
24 from pydantic_openapi_schema.v3_1_0.security_requirement import SecurityRequirement
25 from pydantic_openapi_schema.v3_1_0.server import Server
26 from pydantic_openapi_schema.v3_1_0.tag import Tag
27 
28 from starlite.cache import CacheBackendProtocol, SimpleCacheBackend
29 from starlite.openapi.controller import OpenAPIController
30 from starlite.openapi.path_item import create_path_item
31 from starlite.routes import HTTPRoute
32 from starlite.template import TemplateEngineProtocol
33 from starlite.types import CacheKeyBuilder
34 
35 if TYPE_CHECKING:
36     from starlite.app import Starlite
37     from starlite.connection import Request
38 
39 
40 class CORSConfig(BaseModel):
41     allow_origins: List[str] = ["*"]
42     allow_methods: List[str] = ["*"]
43     allow_headers: List[str] = ["*"]
44     allow_credentials: bool = False
45     allow_origin_regex: Optional[str] = None
46     expose_headers: List[str] = []
47     max_age: int = 600
48 
49 
50 class CompressionBackend(str, Enum):
51     """CompressionBackend is an enum that defines the available compression backends."""
52 
53     GZIP = "gzip"
54     BROTLI = "brotli"
55 
56 
57 class BrotliMode(str, Enum):
58     """BrotliMode is an enum that defines the available brotli compression optimization modes."""
59 
60     GENERIC = "generic"
61     TEXT = "text"
62     FONT = "font"
63 
64 
65 class CompressionConfig(BaseModel):
66     """Class containing the configuration for request compression."""
67 
68     backend: Union[CompressionBackend, str]
69     minimum_size: int = 500
70     gzip_compress_level: int = 9
71     brotli_quality: int = 5
72     brotli_mode: Union[BrotliMode, str] = BrotliMode.TEXT
73     brotli_lgwin: int = 22
74     brotli_lgblock: int = 0
75     brotli_gzip_fallback: bool = True
76 
77     @validator("backend", pre=True, always=True)
78     def backend_must_be_supported(  # pylint: disable=no-self-argument
79         cls, v: Union[CompressionBackend, str]
80     ) -> CompressionBackend:
81         """Compression Backend Validation
82 
83         Args:
84             v (CompressionBackend|str): Holds the selected compression backend
85 
86         Raises:
87             ValueError: Value is not a valid compression backend
88 
89         Returns:
90             _type_: CompressionBackend
91         """
92         if isinstance(v, str):
93             try:
94                 v = CompressionBackend[v.upper()]
95             except KeyError as e:
96                 raise ValueError(f"{v} is not a valid compression backend") from e
97         return v
98 
99     @validator("brotli_mode", pre=True, always=True)
100     def brotli_mode_must_be_valid(cls, v: Union[BrotliMode, str]) -> BrotliMode:  # pylint: disable=no-self-argument
101         """Compression Backend Validation
102 
103         Args:
104             v (CompressionBackend|str): Holds the selected compression backend
105 
106         Raises:
107             ValueError: Value is not a valid compression backend
108 
109         Returns:
110             _type_: CompressionBackend
111         """
112         if isinstance(v, str):
113             try:
114                 v = BrotliMode[v.upper()]
115             except KeyError as e:
116                 raise ValueError(f"{v} is not a valid compression optimization mode") from e
117         return v
118 
119     def dict(self, *args, **kwargs) -> Dict[str, Any]:  # type: ignore[no-untyped-def]
120         """Returns a dictionary representation of the CompressionConfig.
121 
122         Returns:
123             Dict[str, Any]: dictionary representation of the selected CompressionConfig.  Only columns for the selected backend are included
124         """
125         brotli_keys = {
126             "minimum_size",
127             "brotli_quality",
128             "brotli_mode",
129             "brotli_lgwin",
130             "brotli_lgblock",
131             "brotli_gzip_fallback",
132         }
133         gzip_keys = {"minimum_size", "gzip_compress_level"}
134         if self.backend == CompressionBackend.GZIP:
135             kwargs["include"] = gzip_keys
136         elif self.backend == CompressionBackend.BROTLI:
137             kwargs["include"] = brotli_keys
138         else:
139             kwargs["include"] = brotli_keys.union(gzip_keys)
140 
141         return super().dict(*args, **kwargs)
142 
143 
144 class OpenAPIConfig(BaseModel):
145     """Class containing Settings and Schema Properties"""
146 
147     create_examples: bool = False
148     openapi_controller: Type[OpenAPIController] = OpenAPIController
149 
150     title: str
151     version: str
152     contact: Optional[Contact] = None
153     description: Optional[str] = None
154     external_docs: Optional[ExternalDocumentation] = None
155     license: Optional[License] = None
156     security: Optional[List[SecurityRequirement]] = None
157     servers: List[Server] = [Server(url="/")]
158     summary: Optional[str] = None
159     tags: Optional[List[Tag]] = None
160     terms_of_service: Optional[AnyUrl] = None
161     use_handler_docstrings: bool = False
162     webhooks: Optional[Dict[str, Union[PathItem, Reference]]] = None
163 
164     def to_openapi_schema(self) -> OpenAPI:
165         """Generates an OpenAPI model"""
166         return OpenAPI(
167             externalDocs=self.external_docs,
168             security=self.security,
169             servers=self.servers,
170             tags=self.tags,
171             webhooks=self.webhooks,
172             info=Info(
173                 title=self.title,
174                 version=self.version,
175                 description=self.description,
176                 contact=self.contact,
177                 license=self.license,
178                 summary=self.summary,
179                 termsOfService=self.terms_of_service,
180             ),
181         )
182 
183     def create_openapi_schema_model(self, app: "Starlite") -> OpenAPI:
184         """
185         Creates `OpenAPI` instance for the given `router`.
186 
187         Args:
188             app (Starlite)
189 
190         Returns:
191             OpenAPI
192         """
193         schema = self.to_openapi_schema()
194         schema.paths = {}
195         for route in app.routes:
196             if (
197                 isinstance(route, HTTPRoute)
198                 and any(route_handler.include_in_schema for route_handler, _ in route.route_handler_map.values())
199                 and (route.path_format or "/") not in schema.paths
200             ):
201                 schema.paths[route.path_format or "/"] = create_path_item(
202                     route=route,
203                     create_examples=self.create_examples,
204                     plugins=app.plugins,
205                     use_handler_docstrings=self.use_handler_docstrings,
206                 )
207         return construct_open_api_with_schema_class(schema)
208 
209 
210 class StaticFilesConfig(BaseModel):
211     path: constr(min_length=1)  # type: ignore
212     directories: List[DirectoryPath]
213     html_mode: bool = False
214 
215 
216 class TemplateConfig(BaseModel):
217     class Config:
218         arbitrary_types_allowed = True
219 
220     directory: Union[DirectoryPath, List[DirectoryPath]]
221     engine: Type[TemplateEngineProtocol]
222     engine_callback: Optional[Callable[[Any], Any]]
223 
224 
225 def default_cache_key_builder(request: "Request") -> str:
226     """
227     Given a request object, returns a cache key by combining the path with the sorted query params
228     """
229     qp: List[Tuple[str, Any]] = list(request.query_params.items())
230     qp.sort(key=lambda x: x[0])
231     return request.url.path + urlencode(qp, doseq=True)
232 
233 
234 class CacheConfig(BaseModel):
235     class Config:
236         arbitrary_types_allowed = True
237 
238     backend: CacheBackendProtocol = SimpleCacheBackend()
239     expiration: int = 60  # value in seconds
240     cache_key_builder: CacheKeyBuilder = default_cache_key_builder
241
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/starlite/config.py b/starlite/config.py
--- a/starlite/config.py
+++ b/starlite/config.py
@@ -12,7 +12,7 @@
 )
 from urllib.parse import urlencode
 
-from pydantic import AnyUrl, BaseModel, DirectoryPath, constr, validator
+from pydantic import AnyUrl, BaseConfig, BaseModel, DirectoryPath, constr, validator
 from pydantic_openapi_schema.utils import construct_open_api_with_schema_class
 from pydantic_openapi_schema.v3_1_0.contact import Contact
 from pydantic_openapi_schema.v3_1_0.external_documentation import ExternalDocumentation
@@ -144,6 +144,9 @@
 class OpenAPIConfig(BaseModel):
     """Class containing Settings and Schema Properties"""
 
+    class Config(BaseConfig):
+        copy_on_model_validation = False
+
     create_examples: bool = False
     openapi_controller: Type[OpenAPIController] = OpenAPIController
 
@@ -214,8 +217,9 @@
 
 
 class TemplateConfig(BaseModel):
-    class Config:
+    class Config(BaseConfig):
         arbitrary_types_allowed = True
+        copy_on_model_validation = False
 
     directory: Union[DirectoryPath, List[DirectoryPath]]
     engine: Type[TemplateEngineProtocol]
@@ -232,8 +236,9 @@
 
 
 class CacheConfig(BaseModel):
-    class Config:
+    class Config(BaseConfig):
         arbitrary_types_allowed = True
+        copy_on_model_validation = False
 
     backend: CacheBackendProtocol = SimpleCacheBackend()
     expiration: int = 60  # value in seconds
diff --git a/starlite/exceptions/utils.py b/starlite/exceptions/utils.py
--- a/starlite/exceptions/utils.py
+++ b/starlite/exceptions/utils.py
@@ -2,7 +2,7 @@
 
 from pydantic import BaseModel
 from starlette.exceptions import HTTPException as StarletteHTTPException
-from starlette.status import HTTP_500_INTERNAL_SERVER_ERROR  # noqa: TC002
+from starlette.status import HTTP_500_INTERNAL_SERVER_ERROR
 
 from starlite.enums import MediaType
 from starlite.response import Response

{"golden_diff": "diff --git a/starlite/config.py b/starlite/config.py\n--- a/starlite/config.py\n+++ b/starlite/config.py\n@@ -12,7 +12,7 @@\n )\n from urllib.parse import urlencode\n \n-from pydantic import AnyUrl, BaseModel, DirectoryPath, constr, validator\n+from pydantic import AnyUrl, BaseConfig, BaseModel, DirectoryPath, constr, validator\n from pydantic_openapi_schema.utils import construct_open_api_with_schema_class\n from pydantic_openapi_schema.v3_1_0.contact import Contact\n from pydantic_openapi_schema.v3_1_0.external_documentation import ExternalDocumentation\n@@ -144,6 +144,9 @@\n class OpenAPIConfig(BaseModel):\n     \"\"\"Class containing Settings and Schema Properties\"\"\"\n \n+    class Config(BaseConfig):\n+        copy_on_model_validation = False\n+\n     create_examples: bool = False\n     openapi_controller: Type[OpenAPIController] = OpenAPIController\n \n@@ -214,8 +217,9 @@\n \n \n class TemplateConfig(BaseModel):\n-    class Config:\n+    class Config(BaseConfig):\n         arbitrary_types_allowed = True\n+        copy_on_model_validation = False\n \n     directory: Union[DirectoryPath, List[DirectoryPath]]\n     engine: Type[TemplateEngineProtocol]\n@@ -232,8 +236,9 @@\n \n \n class CacheConfig(BaseModel):\n-    class Config:\n+    class Config(BaseConfig):\n         arbitrary_types_allowed = True\n+        copy_on_model_validation = False\n \n     backend: CacheBackendProtocol = SimpleCacheBackend()\n     expiration: int = 60  # value in seconds\ndiff --git a/starlite/exceptions/utils.py b/starlite/exceptions/utils.py\n--- a/starlite/exceptions/utils.py\n+++ b/starlite/exceptions/utils.py\n@@ -2,7 +2,7 @@\n \n from pydantic import BaseModel\n from starlette.exceptions import HTTPException as StarletteHTTPException\n-from starlette.status import HTTP_500_INTERNAL_SERVER_ERROR  # noqa: TC002\n+from starlette.status import HTTP_500_INTERNAL_SERVER_ERROR\n \n from starlite.enums import MediaType\n from starlite.response import Response\n", "issue": "Pydantic 1.9.1 deepcopy breaks Redis caching, possibly other things\nI'm open to the possibility that this should be treated as an issue in Pydantic because it's a breaking change there, and https://github.com/samuelcolvin/pydantic/issues/4184 appears to be a variation of this.\r\n\r\nI have a Starlite application which configures its caching as follows (excerpt from my actual `app.py`):\r\n\r\n```python\r\nimport redis\r\nimport starlite\r\n\r\nfrom .config import settings\r\n\r\ncache_config = (\r\n    starlite.CacheConfig(backend=redis.from_url(settings.CACHE_URL))\r\n    if settings.CACHE_URL is not None\r\n    else starlite.app.DEFAULT_CACHE_CONFIG\r\n)\r\n```\r\n\r\n`config.settings` in this case is a `pydantic.BaseSettings` instance which reads the Redis URL from an environment variable, if set. The fallback logic is for local development where a Redis instance may not be running.\r\n\r\nI recently did an upgrade of my dependency tree which moved from Pydantic 1.9.0 to Pydantic 1.9.1, and my web worker processes now fail to boot. Reverting to Pydantic 1.9.0 resolves this.\r\n\r\nThe failure occurs at instantiating the `Starlite` application object:\r\n\r\n```python\r\nFile /opt/venv/lib/python3.10/site-packages/pydantic/decorator.py:40, in pydantic.decorator.validate_arguments.validate.wrapper_function()\r\n\r\nFile /opt/venv/lib/python3.10/site-packages/pydantic/decorator.py:133, in pydantic.decorator.ValidatedFunction.call()\r\n\r\nFile /opt/venv/lib/python3.10/site-packages/pydantic/decorator.py:130, in pydantic.decorator.ValidatedFunction.init_model_instance()\r\n\r\nFile /opt/venv/lib/python3.10/site-packages/pydantic/main.py:341, in pydantic.main.BaseModel.__init__()\r\n\r\nValidationError: 1 validation error for Init\r\ncache_config\r\n  cannot pickle '_thread.lock' object (type=type_error)\r\n```\r\n\r\nThe root of the issue appears to be that in Pydantic 1.9.1, Pydantic defaults to performing a `copy.deepcopy()` of model members during validation, which in turn fails on encountering any non-pickle-able object (as in the above traceback where it attempts to `deepcopy()` a Redis client instance). Pydantic 1.9.0 performed only a shallow copy.\r\n\r\nThis behavior can be disabled by setting the `copy_on_model_validation` option to a false-y value in the config for a Pydantic model class, or by passing it in the `config` dictionary of the `validate_arguments` decorator, and that may be the simplest workaround to apply for now while Pydantic decides what to do about this. It may also be the correct long-term choice since it's likely that non-pickle-able objects, such as caching clients, will be passed in arguments to the `Starlite` constructor from time to time.\r\n\r\nThis issue appears to be present in any version of Starlite which decorates `Starlite.__init__()` with `validate_arguments`, when using Pydantic 1.9.1 (I've tested Starlite 1.7.3 and 1.3.3), and disappears on reverting to Pydantic 1.9.0.\n", "before_files": [{"content": "from typing import Any, Dict, List, Optional, Union\n\nfrom pydantic import BaseModel\nfrom starlette.exceptions import HTTPException as StarletteHTTPException\nfrom starlette.status import HTTP_500_INTERNAL_SERVER_ERROR  # noqa: TC002\n\nfrom starlite.enums import MediaType\nfrom starlite.response import Response\n\nfrom .exceptions import HTTPException\n\n__all__ = [\"create_exception_response\"]\n\n\nclass ExceptionResponseContent(BaseModel):\n    detail: Optional[str]\n    extra: Optional[Union[Dict[str, Any], List[Any]]]\n    status_code: int = HTTP_500_INTERNAL_SERVER_ERROR\n\n\ndef create_exception_response(exc: Exception) -> Response:\n    \"\"\"\n    Constructs a response from an exception.\n\n    For instances of either `starlite.exceptions.HTTPException` or `starlette.exceptions.HTTPException` the response\n    status code is drawn from the exception, otherwise response status is `HTTP_500_INTERNAL_SERVER_ERROR`.\n\n    Args:\n        exc (Exception): Any exception.\n\n    Returns:\n        Response\n    \"\"\"\n    if isinstance(exc, (HTTPException, StarletteHTTPException)):\n        content = ExceptionResponseContent(detail=exc.detail, status_code=exc.status_code)\n        if isinstance(exc, HTTPException):\n            content.extra = exc.extra\n    else:\n        content = ExceptionResponseContent(detail=repr(exc))\n    return Response(\n        media_type=MediaType.JSON,\n        content=content.dict(exclude_none=True),\n        status_code=content.status_code,\n    )\n", "path": "starlite/exceptions/utils.py"}, {"content": "from enum import Enum\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Callable,\n    Dict,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    Union,\n)\nfrom urllib.parse import urlencode\n\nfrom pydantic import AnyUrl, BaseModel, DirectoryPath, constr, validator\nfrom pydantic_openapi_schema.utils import construct_open_api_with_schema_class\nfrom pydantic_openapi_schema.v3_1_0.contact import Contact\nfrom pydantic_openapi_schema.v3_1_0.external_documentation import ExternalDocumentation\nfrom pydantic_openapi_schema.v3_1_0.info import Info\nfrom pydantic_openapi_schema.v3_1_0.license import License\nfrom pydantic_openapi_schema.v3_1_0.open_api import OpenAPI\nfrom pydantic_openapi_schema.v3_1_0.path_item import PathItem\nfrom pydantic_openapi_schema.v3_1_0.reference import Reference\nfrom pydantic_openapi_schema.v3_1_0.security_requirement import SecurityRequirement\nfrom pydantic_openapi_schema.v3_1_0.server import Server\nfrom pydantic_openapi_schema.v3_1_0.tag import Tag\n\nfrom starlite.cache import CacheBackendProtocol, SimpleCacheBackend\nfrom starlite.openapi.controller import OpenAPIController\nfrom starlite.openapi.path_item import create_path_item\nfrom starlite.routes import HTTPRoute\nfrom starlite.template import TemplateEngineProtocol\nfrom starlite.types import CacheKeyBuilder\n\nif TYPE_CHECKING:\n    from starlite.app import Starlite\n    from starlite.connection import Request\n\n\nclass CORSConfig(BaseModel):\n    allow_origins: List[str] = [\"*\"]\n    allow_methods: List[str] = [\"*\"]\n    allow_headers: List[str] = [\"*\"]\n    allow_credentials: bool = False\n    allow_origin_regex: Optional[str] = None\n    expose_headers: List[str] = []\n    max_age: int = 600\n\n\nclass CompressionBackend(str, Enum):\n    \"\"\"CompressionBackend is an enum that defines the available compression backends.\"\"\"\n\n    GZIP = \"gzip\"\n    BROTLI = \"brotli\"\n\n\nclass BrotliMode(str, Enum):\n    \"\"\"BrotliMode is an enum that defines the available brotli compression optimization modes.\"\"\"\n\n    GENERIC = \"generic\"\n    TEXT = \"text\"\n    FONT = \"font\"\n\n\nclass CompressionConfig(BaseModel):\n    \"\"\"Class containing the configuration for request compression.\"\"\"\n\n    backend: Union[CompressionBackend, str]\n    minimum_size: int = 500\n    gzip_compress_level: int = 9\n    brotli_quality: int = 5\n    brotli_mode: Union[BrotliMode, str] = BrotliMode.TEXT\n    brotli_lgwin: int = 22\n    brotli_lgblock: int = 0\n    brotli_gzip_fallback: bool = True\n\n    @validator(\"backend\", pre=True, always=True)\n    def backend_must_be_supported(  # pylint: disable=no-self-argument\n        cls, v: Union[CompressionBackend, str]\n    ) -> CompressionBackend:\n        \"\"\"Compression Backend Validation\n\n        Args:\n            v (CompressionBackend|str): Holds the selected compression backend\n\n        Raises:\n            ValueError: Value is not a valid compression backend\n\n        Returns:\n            _type_: CompressionBackend\n        \"\"\"\n        if isinstance(v, str):\n            try:\n                v = CompressionBackend[v.upper()]\n            except KeyError as e:\n                raise ValueError(f\"{v} is not a valid compression backend\") from e\n        return v\n\n    @validator(\"brotli_mode\", pre=True, always=True)\n    def brotli_mode_must_be_valid(cls, v: Union[BrotliMode, str]) -> BrotliMode:  # pylint: disable=no-self-argument\n        \"\"\"Compression Backend Validation\n\n        Args:\n            v (CompressionBackend|str): Holds the selected compression backend\n\n        Raises:\n            ValueError: Value is not a valid compression backend\n\n        Returns:\n            _type_: CompressionBackend\n        \"\"\"\n        if isinstance(v, str):\n            try:\n                v = BrotliMode[v.upper()]\n            except KeyError as e:\n                raise ValueError(f\"{v} is not a valid compression optimization mode\") from e\n        return v\n\n    def dict(self, *args, **kwargs) -> Dict[str, Any]:  # type: ignore[no-untyped-def]\n        \"\"\"Returns a dictionary representation of the CompressionConfig.\n\n        Returns:\n            Dict[str, Any]: dictionary representation of the selected CompressionConfig.  Only columns for the selected backend are included\n        \"\"\"\n        brotli_keys = {\n            \"minimum_size\",\n            \"brotli_quality\",\n            \"brotli_mode\",\n            \"brotli_lgwin\",\n            \"brotli_lgblock\",\n            \"brotli_gzip_fallback\",\n        }\n        gzip_keys = {\"minimum_size\", \"gzip_compress_level\"}\n        if self.backend == CompressionBackend.GZIP:\n            kwargs[\"include\"] = gzip_keys\n        elif self.backend == CompressionBackend.BROTLI:\n            kwargs[\"include\"] = brotli_keys\n        else:\n            kwargs[\"include\"] = brotli_keys.union(gzip_keys)\n\n        return super().dict(*args, **kwargs)\n\n\nclass OpenAPIConfig(BaseModel):\n    \"\"\"Class containing Settings and Schema Properties\"\"\"\n\n    create_examples: bool = False\n    openapi_controller: Type[OpenAPIController] = OpenAPIController\n\n    title: str\n    version: str\n    contact: Optional[Contact] = None\n    description: Optional[str] = None\n    external_docs: Optional[ExternalDocumentation] = None\n    license: Optional[License] = None\n    security: Optional[List[SecurityRequirement]] = None\n    servers: List[Server] = [Server(url=\"/\")]\n    summary: Optional[str] = None\n    tags: Optional[List[Tag]] = None\n    terms_of_service: Optional[AnyUrl] = None\n    use_handler_docstrings: bool = False\n    webhooks: Optional[Dict[str, Union[PathItem, Reference]]] = None\n\n    def to_openapi_schema(self) -> OpenAPI:\n        \"\"\"Generates an OpenAPI model\"\"\"\n        return OpenAPI(\n            externalDocs=self.external_docs,\n            security=self.security,\n            servers=self.servers,\n            tags=self.tags,\n            webhooks=self.webhooks,\n            info=Info(\n                title=self.title,\n                version=self.version,\n                description=self.description,\n                contact=self.contact,\n                license=self.license,\n                summary=self.summary,\n                termsOfService=self.terms_of_service,\n            ),\n        )\n\n    def create_openapi_schema_model(self, app: \"Starlite\") -> OpenAPI:\n        \"\"\"\n        Creates `OpenAPI` instance for the given `router`.\n\n        Args:\n            app (Starlite)\n\n        Returns:\n            OpenAPI\n        \"\"\"\n        schema = self.to_openapi_schema()\n        schema.paths = {}\n        for route in app.routes:\n            if (\n                isinstance(route, HTTPRoute)\n                and any(route_handler.include_in_schema for route_handler, _ in route.route_handler_map.values())\n                and (route.path_format or \"/\") not in schema.paths\n            ):\n                schema.paths[route.path_format or \"/\"] = create_path_item(\n                    route=route,\n                    create_examples=self.create_examples,\n                    plugins=app.plugins,\n                    use_handler_docstrings=self.use_handler_docstrings,\n                )\n        return construct_open_api_with_schema_class(schema)\n\n\nclass StaticFilesConfig(BaseModel):\n    path: constr(min_length=1)  # type: ignore\n    directories: List[DirectoryPath]\n    html_mode: bool = False\n\n\nclass TemplateConfig(BaseModel):\n    class Config:\n        arbitrary_types_allowed = True\n\n    directory: Union[DirectoryPath, List[DirectoryPath]]\n    engine: Type[TemplateEngineProtocol]\n    engine_callback: Optional[Callable[[Any], Any]]\n\n\ndef default_cache_key_builder(request: \"Request\") -> str:\n    \"\"\"\n    Given a request object, returns a cache key by combining the path with the sorted query params\n    \"\"\"\n    qp: List[Tuple[str, Any]] = list(request.query_params.items())\n    qp.sort(key=lambda x: x[0])\n    return request.url.path + urlencode(qp, doseq=True)\n\n\nclass CacheConfig(BaseModel):\n    class Config:\n        arbitrary_types_allowed = True\n\n    backend: CacheBackendProtocol = SimpleCacheBackend()\n    expiration: int = 60  # value in seconds\n    cache_key_builder: CacheKeyBuilder = default_cache_key_builder\n", "path": "starlite/config.py"}], "after_files": [{"content": "from typing import Any, Dict, List, Optional, Union\n\nfrom pydantic import BaseModel\nfrom starlette.exceptions import HTTPException as StarletteHTTPException\nfrom starlette.status import HTTP_500_INTERNAL_SERVER_ERROR\n\nfrom starlite.enums import MediaType\nfrom starlite.response import Response\n\nfrom .exceptions import HTTPException\n\n__all__ = [\"create_exception_response\"]\n\n\nclass ExceptionResponseContent(BaseModel):\n    detail: Optional[str]\n    extra: Optional[Union[Dict[str, Any], List[Any]]]\n    status_code: int = HTTP_500_INTERNAL_SERVER_ERROR\n\n\ndef create_exception_response(exc: Exception) -> Response:\n    \"\"\"\n    Constructs a response from an exception.\n\n    For instances of either `starlite.exceptions.HTTPException` or `starlette.exceptions.HTTPException` the response\n    status code is drawn from the exception, otherwise response status is `HTTP_500_INTERNAL_SERVER_ERROR`.\n\n    Args:\n        exc (Exception): Any exception.\n\n    Returns:\n        Response\n    \"\"\"\n    if isinstance(exc, (HTTPException, StarletteHTTPException)):\n        content = ExceptionResponseContent(detail=exc.detail, status_code=exc.status_code)\n        if isinstance(exc, HTTPException):\n            content.extra = exc.extra\n    else:\n        content = ExceptionResponseContent(detail=repr(exc))\n    return Response(\n        media_type=MediaType.JSON,\n        content=content.dict(exclude_none=True),\n        status_code=content.status_code,\n    )\n", "path": "starlite/exceptions/utils.py"}, {"content": "from enum import Enum\nfrom typing import (\n    TYPE_CHECKING,\n    Any,\n    Callable,\n    Dict,\n    List,\n    Optional,\n    Tuple,\n    Type,\n    Union,\n)\nfrom urllib.parse import urlencode\n\nfrom pydantic import AnyUrl, BaseConfig, BaseModel, DirectoryPath, constr, validator\nfrom pydantic_openapi_schema.utils import construct_open_api_with_schema_class\nfrom pydantic_openapi_schema.v3_1_0.contact import Contact\nfrom pydantic_openapi_schema.v3_1_0.external_documentation import ExternalDocumentation\nfrom pydantic_openapi_schema.v3_1_0.info import Info\nfrom pydantic_openapi_schema.v3_1_0.license import License\nfrom pydantic_openapi_schema.v3_1_0.open_api import OpenAPI\nfrom pydantic_openapi_schema.v3_1_0.path_item import PathItem\nfrom pydantic_openapi_schema.v3_1_0.reference import Reference\nfrom pydantic_openapi_schema.v3_1_0.security_requirement import SecurityRequirement\nfrom pydantic_openapi_schema.v3_1_0.server import Server\nfrom pydantic_openapi_schema.v3_1_0.tag import Tag\n\nfrom starlite.cache import CacheBackendProtocol, SimpleCacheBackend\nfrom starlite.openapi.controller import OpenAPIController\nfrom starlite.openapi.path_item import create_path_item\nfrom starlite.routes import HTTPRoute\nfrom starlite.template import TemplateEngineProtocol\nfrom starlite.types import CacheKeyBuilder\n\nif TYPE_CHECKING:\n    from starlite.app import Starlite\n    from starlite.connection import Request\n\n\nclass CORSConfig(BaseModel):\n    allow_origins: List[str] = [\"*\"]\n    allow_methods: List[str] = [\"*\"]\n    allow_headers: List[str] = [\"*\"]\n    allow_credentials: bool = False\n    allow_origin_regex: Optional[str] = None\n    expose_headers: List[str] = []\n    max_age: int = 600\n\n\nclass CompressionBackend(str, Enum):\n    \"\"\"CompressionBackend is an enum that defines the available compression backends.\"\"\"\n\n    GZIP = \"gzip\"\n    BROTLI = \"brotli\"\n\n\nclass BrotliMode(str, Enum):\n    \"\"\"BrotliMode is an enum that defines the available brotli compression optimization modes.\"\"\"\n\n    GENERIC = \"generic\"\n    TEXT = \"text\"\n    FONT = \"font\"\n\n\nclass CompressionConfig(BaseModel):\n    \"\"\"Class containing the configuration for request compression.\"\"\"\n\n    backend: Union[CompressionBackend, str]\n    minimum_size: int = 500\n    gzip_compress_level: int = 9\n    brotli_quality: int = 5\n    brotli_mode: Union[BrotliMode, str] = BrotliMode.TEXT\n    brotli_lgwin: int = 22\n    brotli_lgblock: int = 0\n    brotli_gzip_fallback: bool = True\n\n    @validator(\"backend\", pre=True, always=True)\n    def backend_must_be_supported(  # pylint: disable=no-self-argument\n        cls, v: Union[CompressionBackend, str]\n    ) -> CompressionBackend:\n        \"\"\"Compression Backend Validation\n\n        Args:\n            v (CompressionBackend|str): Holds the selected compression backend\n\n        Raises:\n            ValueError: Value is not a valid compression backend\n\n        Returns:\n            _type_: CompressionBackend\n        \"\"\"\n        if isinstance(v, str):\n            try:\n                v = CompressionBackend[v.upper()]\n            except KeyError as e:\n                raise ValueError(f\"{v} is not a valid compression backend\") from e\n        return v\n\n    @validator(\"brotli_mode\", pre=True, always=True)\n    def brotli_mode_must_be_valid(cls, v: Union[BrotliMode, str]) -> BrotliMode:  # pylint: disable=no-self-argument\n        \"\"\"Compression Backend Validation\n\n        Args:\n            v (CompressionBackend|str): Holds the selected compression backend\n\n        Raises:\n            ValueError: Value is not a valid compression backend\n\n        Returns:\n            _type_: CompressionBackend\n        \"\"\"\n        if isinstance(v, str):\n            try:\n                v = BrotliMode[v.upper()]\n            except KeyError as e:\n                raise ValueError(f\"{v} is not a valid compression optimization mode\") from e\n        return v\n\n    def dict(self, *args, **kwargs) -> Dict[str, Any]:  # type: ignore[no-untyped-def]\n        \"\"\"Returns a dictionary representation of the CompressionConfig.\n\n        Returns:\n            Dict[str, Any]: dictionary representation of the selected CompressionConfig.  Only columns for the selected backend are included\n        \"\"\"\n        brotli_keys = {\n            \"minimum_size\",\n            \"brotli_quality\",\n            \"brotli_mode\",\n            \"brotli_lgwin\",\n            \"brotli_lgblock\",\n            \"brotli_gzip_fallback\",\n        }\n        gzip_keys = {\"minimum_size\", \"gzip_compress_level\"}\n        if self.backend == CompressionBackend.GZIP:\n            kwargs[\"include\"] = gzip_keys\n        elif self.backend == CompressionBackend.BROTLI:\n            kwargs[\"include\"] = brotli_keys\n        else:\n            kwargs[\"include\"] = brotli_keys.union(gzip_keys)\n\n        return super().dict(*args, **kwargs)\n\n\nclass OpenAPIConfig(BaseModel):\n    \"\"\"Class containing Settings and Schema Properties\"\"\"\n\n    class Config(BaseConfig):\n        copy_on_model_validation = False\n\n    create_examples: bool = False\n    openapi_controller: Type[OpenAPIController] = OpenAPIController\n\n    title: str\n    version: str\n    contact: Optional[Contact] = None\n    description: Optional[str] = None\n    external_docs: Optional[ExternalDocumentation] = None\n    license: Optional[License] = None\n    security: Optional[List[SecurityRequirement]] = None\n    servers: List[Server] = [Server(url=\"/\")]\n    summary: Optional[str] = None\n    tags: Optional[List[Tag]] = None\n    terms_of_service: Optional[AnyUrl] = None\n    use_handler_docstrings: bool = False\n    webhooks: Optional[Dict[str, Union[PathItem, Reference]]] = None\n\n    def to_openapi_schema(self) -> OpenAPI:\n        \"\"\"Generates an OpenAPI model\"\"\"\n        return OpenAPI(\n            externalDocs=self.external_docs,\n            security=self.security,\n            servers=self.servers,\n            tags=self.tags,\n            webhooks=self.webhooks,\n            info=Info(\n                title=self.title,\n                version=self.version,\n                description=self.description,\n                contact=self.contact,\n                license=self.license,\n                summary=self.summary,\n                termsOfService=self.terms_of_service,\n            ),\n        )\n\n    def create_openapi_schema_model(self, app: \"Starlite\") -> OpenAPI:\n        \"\"\"\n        Creates `OpenAPI` instance for the given `router`.\n\n        Args:\n            app (Starlite)\n\n        Returns:\n            OpenAPI\n        \"\"\"\n        schema = self.to_openapi_schema()\n        schema.paths = {}\n        for route in app.routes:\n            if (\n                isinstance(route, HTTPRoute)\n                and any(route_handler.include_in_schema for route_handler, _ in route.route_handler_map.values())\n                and (route.path_format or \"/\") not in schema.paths\n            ):\n                schema.paths[route.path_format or \"/\"] = create_path_item(\n                    route=route,\n                    create_examples=self.create_examples,\n                    plugins=app.plugins,\n                    use_handler_docstrings=self.use_handler_docstrings,\n                )\n        return construct_open_api_with_schema_class(schema)\n\n\nclass StaticFilesConfig(BaseModel):\n    path: constr(min_length=1)  # type: ignore\n    directories: List[DirectoryPath]\n    html_mode: bool = False\n\n\nclass TemplateConfig(BaseModel):\n    class Config(BaseConfig):\n        arbitrary_types_allowed = True\n        copy_on_model_validation = False\n\n    directory: Union[DirectoryPath, List[DirectoryPath]]\n    engine: Type[TemplateEngineProtocol]\n    engine_callback: Optional[Callable[[Any], Any]]\n\n\ndef default_cache_key_builder(request: \"Request\") -> str:\n    \"\"\"\n    Given a request object, returns a cache key by combining the path with the sorted query params\n    \"\"\"\n    qp: List[Tuple[str, Any]] = list(request.query_params.items())\n    qp.sort(key=lambda x: x[0])\n    return request.url.path + urlencode(qp, doseq=True)\n\n\nclass CacheConfig(BaseModel):\n    class Config(BaseConfig):\n        arbitrary_types_allowed = True\n        copy_on_model_validation = False\n\n    backend: CacheBackendProtocol = SimpleCacheBackend()\n    expiration: int = 60  # value in seconds\n    cache_key_builder: CacheKeyBuilder = default_cache_key_builder\n", "path": "starlite/config.py"}]}