litestar-org/litestar

Bug: schema_extra does not recognize upstream JSONSchema property/key names

charles-dyfis-net opened this issue · 1 comments

Description

With code generated for other (non-litestar) JSONSchema consumers, using upstream names (such as uniqueItems instead of unique_items) inside of schema_extra results in a ValueError.

URL to code causing the issue

No response

MCVE

from typing import Annotated, Any, Dict
import pydantic

from litestar import Litestar, get

# Presume that this type's JSONSchema is used by consumers other than litestar, and needs to be spec-compliant
class RandomType(pydantic.BaseModel):
    # uniqueItems is per spec -- see https://json-schema.org/understanding-json-schema/reference/array
    unique_items: Annotated[list[str], pydantic.Field(json_schema_extra={"uniqueItems": True})]

@get("/")
async def hello_world() -> RandomType:
    """Route Handler that outputs hello world."""
    return RandomType(unique_items=["hi", "bye"])

app = Litestar(route_handlers=[hello_world])

Steps to reproduce

1. Run `litestar --app app:app run --debug`
2. Load `http://localhost:8000/schema`
3. Watch the resulting stack trace

Screenshots

No response

Logs

ERROR - 2024-09-29 21:52:29,271 - litestar - config - Uncaught exception (connection_type=http, path=/schema):
Traceback (most recent call last):
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/middleware/_internal/exceptions/middleware.py", line 159, in __call__
    await self.app(scope, receive, capture_response_started)
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/_asgi/asgi_router.py", line 100, in __call__
    await asgi_app(scope, receive, send)
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/routes/http.py", line 80, in handle
    response = await self._get_response_for_request(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/routes/http.py", line 132, in _get_response_for_request
    return await self._call_handler_function(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/routes/http.py", line 152, in _call_handler_function
    response_data, cleanup_group = await self._get_response_data(
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/routes/http.py", line 195, in _get_response_data
    data = route_handler.fn(**parsed_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/_openapi/plugin.py", line 161, in _handler
    return plugin_.render(request, self.provide_openapi_schema())
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/_openapi/plugin.py", line 99, in provide_openapi_schema
    self._openapi_schema = self.provide_openapi().to_schema()
                           ^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/_openapi/plugin.py", line 94, in provide_openapi
    self._openapi = self._build_openapi()
                    ^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/_openapi/plugin.py", line 83, in _build_openapi
    path_item = create_path_item_for_route(context, route)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/_openapi/path_item.py", line 139, in create_path_item_for_route
    return path_item_factory.create_path_item()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/_openapi/path_item.py", line 44, in create_path_item
    operation = self.create_operation_for_handler_method(route_handler, HttpMethod(http_method))
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/_openapi/path_item.py", line 73, in create_operation_for_handler_method
    responses = create_responses_for_handler(
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/_openapi/responses.py", line 340, in create_responses_for_handler
    return ResponseFactory(context, route_handler).create_responses(raises_validation_error=raises_validation_error)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/_openapi/responses.py", line 91, in create_responses
    str(self.route_handler.status_code): self.create_success_response(),
                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/_openapi/responses.py", line 150, in create_success_response
    result = self.schema_creator.for_field_definition(field_def)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py", line 333, in for_field_definition
    result = self.for_plugin(field_definition, plugin_for_annotation)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py", line 515, in for_plugin
    schema = plugin.to_openapi_schema(field_definition=field_definition, schema_creator=self)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/contrib/pydantic/pydantic_schema_plugin.py", line 235, in to_openapi_schema
    return self.for_pydantic_model(field_definition=field_definition, schema_creator=schema_creator)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/contrib/pydantic/pydantic_schema_plugin.py", line 252, in for_pydantic_model
    return schema_creator.create_component_schema(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py", line 645, in create_component_schema
    schema.properties = {k: self.for_field_definition(v) for k, v in property_fields.items()}
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py", line 361, in for_field_definition
    return self.process_schema_result(field_definition, result) if isinstance(result, Schema) else result
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py", line 596, in process_schema_result
    raise ValueError(
ValueError: `schema_extra` declares key `uniqueItems` which does not exist in `Schema` object
> /nix/store/abpcb2xnkhh64yh30nkc6nv19nv720y4-python3-3.12.4-env/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py(596)process_schema_result()

Litestar Version

2.12.1

Platform

  • Linux
  • Mac
  • Windows
  • Other (Please specify in the description above)

Note

While we are open for sponsoring on GitHub Sponsors and
OpenCollective, we also utilize Polar.sh to engage in pledge-based sponsorship.

Check out all issues funded or available for funding on our Polar.sh dashboard

  • 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.
Fund with Polar

A fix for this issue has been released in v2.13.0