Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Schema generation fails for model with Annotated NewType. #3614

Closed
1 of 4 tasks
sherbang opened this issue Jul 8, 2024 · 2 comments · Fixed by #3615
Closed
1 of 4 tasks

Bug: Schema generation fails for model with Annotated NewType. #3614

sherbang opened this issue Jul 8, 2024 · 2 comments · Fixed by #3615
Labels
Bug 🐛 This is something that is not working as expected

Comments

@sherbang
Copy link
Contributor

sherbang commented Jul 8, 2024

Description

Schema generation gets in an infinite loop on a model like this:

TestId = NewType("TestId", str)

@dataclasses.dataclass
class TestModel:
    id: Annotated[TestId, "foo"]

The repository linked below has a minimal example with a failing pytest.

Note: actual code is using sqlalchemy, using Mapped[Annotated[IdType, mapped_column(primary_key=True)]].

URL to code causing the issue

https://github.com/sherbang/litestar-test

MCVE

No response

Steps to reproduce

No response

Screenshots

No response

Logs

litestar-test/pytests/test_schema.py::test_schema failed: def test_schema():
        # Test that health check and schema endpoints work from different root paths
        # Also confirms that there are no schema generation errors
        from test.app import app
    
        app.debug = True
        with TestClient(app=app) as test_client:
            resp = test_client.get("/schema")
>           assert resp.status_code == 200, resp.text
E           AssertionError: Traceback (most recent call last):
E               File "/home/sherbang/.pyenv/versions/3.12.4/lib/python3.12/pathlib.py", line 572, in _tail
E                 return self._tail_cached
E                        ^^^^^^^^^^^^^^^^^
E             AttributeError: 'PurePosixPath' object has no attribute '_tail_cached'
E             
E             During handling of the above exception, another exception occurred:
E             
E             Traceback (most recent call last):
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/middleware/_internal/exceptions/middleware.py", line 159, in __call__
E                 await self.app(scope, receive, capture_response_started)
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_asgi/asgi_router.py", line 99, in __call__
E                 await asgi_app(scope, receive, send)
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/routes/http.py", line 80, in handle
E                 response = await self._get_response_for_request(
E                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/routes/http.py", line 132, in _get_response_for_request
E                 return await self._call_handler_function(
E                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/routes/http.py", line 152, in _call_handler_function
E                 response_data, cleanup_group = await self._get_response_data(
E                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/routes/http.py", line 203, in _get_response_data
E                 data = route_handler.fn(**parsed_kwargs)
E                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/plugin.py", line 161, in _handler
E                 return plugin_.render(request, self.provide_openapi_schema())
E                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/plugin.py", line 99, in provide_openapi_schema
E                 self._openapi_schema = self.provide_openapi().to_schema()
E                                        ^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/plugin.py", line 94, in provide_openapi
E                 self._openapi = self._build_openapi()
E                                 ^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/plugin.py", line 83, in _build_openapi
E                 path_item = create_path_item_for_route(context, route)
E                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/path_item.py", line 139, in create_path_item_for_route
E                 return path_item_factory.create_path_item()
E                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/path_item.py", line 44, in create_path_item
E                 operation = self.create_operation_for_handler_method(route_handler, HttpMethod(http_method))
E                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/path_item.py", line 73, in create_operation_for_handler_method
E                 responses = create_responses_for_handler(
E                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/responses.py", line 335, in create_responses_for_handler
E                 return ResponseFactory(context, route_handler).create_responses(raises_validation_error=raises_validation_error)
E                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/responses.py", line 91, in create_responses
E                 str(self.route_handler.status_code): self.create_success_response(),
E                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/responses.py", line 150, in create_success_response
E                 result = self.schema_creator.for_field_definition(field_def)
E                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py", line 332, in for_field_definition
E                 result = self.for_plugin(field_definition, plugin_for_annotation)
E                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py", line 503, in for_plugin
E                 schema = plugin.to_openapi_schema(field_definition=field_definition, schema_creator=self)
E                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/schema_generation/plugins/dataclass.py", line 24, in to_openapi_schema
E                 return schema_creator.create_component_schema(
E                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py", line 639, in create_component_schema
E                 schema.properties = {k: self.for_field_definition(v) for k, v in property_fields.items()}
E                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py", line 330, in for_field_definition
E                 result = self.for_new_type(field_definition)
E                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py", line 361, in for_new_type
E                 return self.for_field_definition(
E                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py", line 330, in for_field_definition
E                 result = self.for_new_type(field_definition)
E                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py", line 361, in for_new_type
E                 return self.for_field_definition(
E                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py", line 330, in for_field_definition
E                 result = self.for_new_type(field_definition)
E                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py", line 361, in for_new_type
E                 return self.for_field_definition(
E                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
...
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py", line 330, in for_field_definition
E                 result = self.for_new_type(field_definition)
E                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py", line 361, in for_new_type
E                 return self.for_field_definition(
E                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py", line 330, in for_field_definition
E                 result = self.for_new_type(field_definition)
E                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/_openapi/schema_generation/schema.py", line 362, in for_new_type
E                 FieldDefinition.from_kwarg(
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/typing.py", line 592, in from_kwarg
E                 return cls.from_annotation(
E                        ^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/typing.py", line 540, in from_annotation
E                 kwargs["kwarg_definition"], kwargs["extra"] = cls._extract_metadata(
E                                                               ^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/typing.py", line 252, in _extract_metadata
E                 return _create_metadata_from_type(metadata=metadata, model=model, annotation=annotation, extra=extra)
E                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/typing.py", line 161, in _create_metadata_from_type
E                 result = _traverse_metadata(metadata=metadata, is_sequence_container=is_sequence_container, extra=extra)
E                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/typing.py", line 150, in _traverse_metadata
E                 elif unpacked_predicate := _unpack_predicate(value):
E                                            ^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/litestar/typing.py", line 53, in _unpack_predicate
E                 from annotated_types import Predicate
E               File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
E               File "<frozen importlib._bootstrap>", line 1322, in _find_and_load_unlocked
E               File "<frozen importlib._bootstrap>", line 1262, in _find_spec
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/_pytest/assertion/rewrite.py", line 102, in find_spec
E                 if self._early_rewrite_bailout(name, state):
E                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/devel/litestar-test/.venv/lib/python3.12/site-packages/_pytest/assertion/rewrite.py", line 203, in _early_rewrite_bailout
E                 path = PurePath(*parts).with_suffix(".py")
E                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/.pyenv/versions/3.12.4/lib/python3.12/pathlib.py", line 652, in with_suffix
E                 name = self.name
E                        ^^^^^^^^^
E               File "/home/sherbang/.pyenv/versions/3.12.4/lib/python3.12/pathlib.py", line 586, in name
E                 tail = self._tail
E                        ^^^^^^^^^^
E               File "/home/sherbang/.pyenv/versions/3.12.4/lib/python3.12/pathlib.py", line 574, in _tail
E                 self._load_parts()
E               File "/home/sherbang/.pyenv/versions/3.12.4/lib/python3.12/pathlib.py", line 415, in _load_parts
E                 drv, root, tail = self._parse_path(path)
E                                   ^^^^^^^^^^^^^^^^^^^^^^
E               File "/home/sherbang/.pyenv/versions/3.12.4/lib/python3.12/pathlib.py", line 395, in _parse_path
E                 drv, root, rel = cls._flavour.splitroot(path)
E                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E             RecursionError: maximum recursion depth exceeded
E             
E           assert 500 == 200
E            +  where 500 = <Response [500 Internal Server Error]>.status_code

pytests/test_schema.py:12: AssertionError

Litestar Version

2.9.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
@sherbang sherbang added the Bug 🐛 This is something that is not working as expected label Jul 8, 2024
@sherbang
Copy link
Contributor Author

sherbang commented Jul 8, 2024

This problem was introduced with #3580

Copy link

github-actions bot commented Jan 8, 2025

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug 🐛 This is something that is not working as expected
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant