Repository: litestar-org/litestar

Issue:
Bug: OpenAPI docs fail to generate with certain validators and pydantic v1
### Description

OpenAPI docs fail to generate when a request payload is a pydantic v1 model and has a str field with a validator combination of a default(or default_factory) and max_length. Removing any of the validators resolves the issue; it's only reproducible with their combination.
Reproducible with:
Python: 3.11.6
Litestar: 2.8.2
Pydantic: 1.10.15

### URL to code causing the issue

_No response_

### MCVE

```python
from litestar import Controller, post
from pydantic.fields import Field
from pydantic.main import BaseModel

OPENAPI_CONTROLLER_TAG = "OpenApiTest"


class TestDto(BaseModel):
    test_str: str = Field(default="some_default", max_length=100)


class OpenApiTestController(Controller):
    path = "/test-openapi"

    @post(
        path="/test",
        tags=[OPENAPI_CONTROLLER_TAG],
        summary="Test",
    )
    async def test(self, data: TestDto) -> str:
        return "success"
```


### Steps to reproduce

```bash
1. Add the above controller to your litestar app.
2. Load any variation of OpenAPI UI(I reproduced with swagger, redoc, rapiddoc).
```


### Screenshots

```bash
"![SCREENSHOT_DESCRIPTION](SCREENSHOT_LINK.png)"
```


### Logs

```bash
ERROR - 2024-05-05 09:36:30,092 - litestar - config - exception raised on http connection to route /schema/redoc

Traceback (most recent call last):
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/serialization/msgspec_hooks.py", line 141, in encode_json
    return msgspec.json.encode(value, enc_hook=serializer) if serializer else _msgspec_json_encoder.encode(value)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/serialization/msgspec_hooks.py", line 88, in default_serializer
    raise TypeError(f"Unsupported type: {type(value)!r}")
TypeError: Unsupported type: <class 'method_descriptor'>

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/middleware/exceptions/middleware.py", line 219, in __call__
    await self.app(scope, receive, send)
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/routes/http.py", line 82, in handle
    response = await self._get_response_for_request(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/routes/http.py", line 134, in _get_response_for_request
    return await self._call_handler_function(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/routes/http.py", line 154, in _call_handler_function
    response_data, cleanup_group = await self._get_response_data(
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/routes/http.py", line 205, in _get_response_data
    data = route_handler.fn(**parsed_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/_openapi/plugin.py", line 161, in _handler
    return plugin_.render(request, self.provide_openapi_schema())
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/openapi/plugins.py", line 310, in render
    self.render_json(request, openapi_schema),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/openapi/plugins.py", line 70, in render_json
    return encode_json(openapi_schema, serializer=get_serializer(request.route_handler.resolve_type_encoders()))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/serialization/msgspec_hooks.py", line 143, in encode_json
    raise SerializationException(str(msgspec_error)) from msgspec_error
litestar.exceptions.base_exceptions.SerializationException: Unsupported type: <class 'method_descriptor'>
Traceback (most recent call last):
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/serialization/msgspec_hooks.py", line 141, in encode_json
    return msgspec.json.encode(value, enc_hook=serializer) if serializer else _msgspec_json_encoder.encode(value)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/serialization/msgspec_hooks.py", line 88, in default_serializer
    raise TypeError(f"Unsupported type: {type(value)!r}")
TypeError: Unsupported type: <class 'method_descriptor'>

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/middleware/exceptions/middleware.py", line 219, in __call__
    await self.app(scope, receive, send)
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/routes/http.py", line 82, in handle
    response = await self._get_response_for_request(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/routes/http.py", line 134, in _get_response_for_request
    return await self._call_handler_function(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/routes/http.py", line 154, in _call_handler_function
    response_data, cleanup_group = await self._get_response_data(
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/routes/http.py", line 205, in _get_response_data
    data = route_handler.fn(**parsed_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/_openapi/plugin.py", line 161, in _handler
    return plugin_.render(request, self.provide_openapi_schema())
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/openapi/plugins.py", line 310, in render
    self.render_json(request, openapi_schema),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/openapi/plugins.py", line 70, in render_json
    return encode_json(openapi_schema, serializer=get_serializer(request.route_handler.resolve_type_encoders()))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/serialization/msgspec_hooks.py", line 143, in encode_json
    raise SerializationException(str(msgspec_error)) from msgspec_error
litestar.exceptions.base_exceptions.SerializationException: Unsupported type: <class 'method_descriptor'>
INFO:     127.0.0.1:61936 - "GET /schema/redoc HTTP/1.1" 500 Internal Server Error
INFO:     127.0.0.1:61936 - "GET /favicon.ico HTTP/1.1" 404 Not Found
ERROR - 2024-05-05 09:36:30,309 - litestar - config - exception raised on http connection to route /favicon.ico

Traceback (most recent call last):
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/traversal.py", line 153, in parse_path_to_route
    node, path_parameters, path = traverse_route_map(
                                  ^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/traversal.py", line 54, in traverse_route_map
    raise NotFoundException()
litestar.exceptions.http_exceptions.NotFoundException: 404: Not Found

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/middleware/exceptions/middleware.py", line 219, in __call__
    await self.app(scope, receive, send)
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/_asgi/asgi_router.py", line 86, in __call__
    asgi_app, scope["route_handler"], scope["path"], scope["path_params"] = self.handle_routing(
                                                                            ^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/_asgi/asgi_router.py", line 102, in handle_routing
    return parse_path_to_route(
           ^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/traversal.py", line 170, in parse_path_to_route
    raise NotFoundException() from e
litestar.exceptions.http_exceptions.NotFoundException: 404: Not Found
Traceback (most recent call last):
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/traversal.py", line 153, in parse_path_to_route
    node, path_parameters, path = traverse_route_map(
                                  ^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/traversal.py", line 54, in traverse_route_map
    raise NotFoundException()
litestar.exceptions.http_exceptions.NotFoundException: 404: Not Found

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/middleware/exceptions/middleware.py", line 219, in __call__
    await self.app(scope, receive, send)
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/_asgi/asgi_router.py", line 86, in __call__
    asgi_app, scope["route_handler"], scope["path"], scope["path_params"] = self.handle_routing(
                                                                            ^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/_asgi/asgi_router.py", line 102, in handle_routing
    return parse_path_to_route(
           ^^^^^^^^^^^^^^^^^^^^
  File "{project_parent_dir}/litestar-playground/.venv/lib/python3.11/site-packages/litestar/_asgi/routing_trie/traversal.py", line 170, in parse_path_to_route
    raise NotFoundException() from e
litestar.exceptions.http_exceptions.NotFoundException: 404: Not Found
```


### Litestar Version

2.8.2

### Platform

- [X] Linux
- [X] Mac
- [ ] Windows
- [ ] Other (Please specify in the description above)

<!-- POLAR PLEDGE BADGE START -->
---
> [!NOTE]  
> While we are open for sponsoring on [GitHub Sponsors](https://github.com/sponsors/litestar-org/) and 
> [OpenCollective](https://opencollective.com/litestar), we also utilize [Polar.sh](https://polar.sh/) to engage in pledge-based sponsorship.
>
> Check out all issues funded or available for funding [on our Polar.sh dashboard](https://polar.sh/litestar-org)
> * If you would like to see an issue prioritized, make a pledge towards it!
> * We receive the pledge once the issue is completed & verified
> * This, along with engagement in the community, helps us know which features are a priority to our users.

<a href="https://polar.sh/litestar-org/litestar/issues/3471">
<picture>
  <source media="(prefers-color-scheme: dark)" srcset="https://polar.sh/api/github/litestar-org/litestar/issues/3471/pledge.svg?darkmode=1">
  <img alt="Fund with Polar" src="https://polar.sh/api/github/litestar-org/litestar/issues/3471/pledge.svg">
</picture>
</a>
<!-- POLAR PLEDGE BADGE END -->



Discussion:

Resolving patch:
diff --git a/litestar/contrib/pydantic/pydantic_schema_plugin.py b/litestar/contrib/pydantic/pydantic_schema_plugin.py
--- a/litestar/contrib/pydantic/pydantic_schema_plugin.py
+++ b/litestar/contrib/pydantic/pydantic_schema_plugin.py
@@ -286,7 +286,8 @@ def for_pydantic_model(cls, field_definition: FieldDefinition, schema_creator: S
         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()
+                k: f.outer_type_ if f.required or f.default else Optional[f.outer_type_]
+                for k, f in model.__fields__.items()
             }
 
         if is_generic_model:


Test patch:
diff --git a/tests/e2e/test_pydantic.py b/tests/e2e/test_pydantic.py
--- a/tests/e2e/test_pydantic.py
+++ b/tests/e2e/test_pydantic.py
@@ -1,6 +1,7 @@
 import pydantic
+from pydantic import v1 as pydantic_v1
 
-from litestar import get
+from litestar import get, post
 from litestar.testing import create_test_client
 
 
@@ -22,3 +23,80 @@ def handler_v2() -> ModelV2:
     with create_test_client([handler_v1, handler_v2]) as client:
         assert client.get("/v1").json() == {"foo": "bar"}
         assert client.get("/v2").json() == {"foo": "bar"}
+
+
+def test_pydantic_v1_model_with_field_default() -> None:
+    # https://github.com/litestar-org/litestar/issues/3471
+
+    class TestDto(pydantic_v1.BaseModel):
+        test_str: str = pydantic_v1.Field(default="some_default", max_length=100)
+
+    @post(path="/test")
+    async def test(data: TestDto) -> str:
+        return "success"
+
+    with create_test_client(route_handlers=[test]) as client:
+        response = client.get("/schema/openapi.json")
+        assert response.status_code == 200
+        assert response.json() == {
+            "components": {
+                "schemas": {
+                    "test_pydantic_v1_model_with_field_default.TestDto": {
+                        "properties": {"test_str": {"default": "some_default", "maxLength": 100, "type": "string"}},
+                        "required": [],
+                        "title": "TestDto",
+                        "type": "object",
+                    }
+                }
+            },
+            "info": {"title": "Litestar API", "version": "1.0.0"},
+            "openapi": "3.1.0",
+            "paths": {
+                "/test": {
+                    "post": {
+                        "deprecated": False,
+                        "operationId": "TestTest",
+                        "requestBody": {
+                            "content": {
+                                "application/json": {
+                                    "schema": {
+                                        "$ref": "#/components/schemas/test_pydantic_v1_model_with_field_default.TestDto"
+                                    }
+                                }
+                            },
+                            "required": True,
+                        },
+                        "responses": {
+                            "201": {
+                                "content": {"text/plain": {"schema": {"type": "string"}}},
+                                "description": "Document " "created, " "URL " "follows",
+                                "headers": {},
+                            },
+                            "400": {
+                                "content": {
+                                    "application/json": {
+                                        "schema": {
+                                            "description": "Validation " "Exception",
+                                            "examples": [{"detail": "Bad " "Request", "extra": {}, "status_code": 400}],
+                                            "properties": {
+                                                "detail": {"type": "string"},
+                                                "extra": {
+                                                    "additionalProperties": {},
+                                                    "type": ["null", "object", "array"],
+                                                },
+                                                "status_code": {"type": "integer"},
+                                            },
+                                            "required": ["detail", "status_code"],
+                                            "type": "object",
+                                        }
+                                    }
+                                },
+                                "description": "Bad " "request " "syntax or " "unsupported " "method",
+                            },
+                        },
+                        "summary": "Test",
+                    }
+                }
+            },
+            "servers": [{"url": "/"}],
+        }