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: OpenAPI error: type object '<MyInputModel>' has no attribute '__parameters__' #3651

Open
1 of 4 tasks
aedify-swi opened this issue Aug 2, 2024 · 3 comments
Open
1 of 4 tasks
Labels
Bug 🐛 This is something that is not working as expected OpenAPI This is related to our OpenAPI schema Triage Required 🏥 This requires triage

Comments

@aedify-swi
Copy link
Contributor

aedify-swi commented Aug 2, 2024

Description

Hello, I come to you with an annoying little bug which cannot reproduce. 🤷

When trying to browse to http://127.0.0.1:8080/schema I get this wonderful error:

AttributeError on GET /schema
type object 'MyInputModel' has no attribute '__parameters__'

.venv/lib/python3.12/site-packages/litestar/utils/typing.py</span> in get_type_hints_with_generics_resolved at line 263:
    origin = get_origin(annotation)
    if origin is None:
        # Implies the generic types have not been specified in the annotation
        if type_hints is None:  # pragma: no cover
            type_hints = get_type_hints(annotation, globalns=globalns, localns=localns, include_extras=include_extras)
        typevar_map = {p: p for p in annotation.__parameters__}
    else:
        if type_hints is None:  # pragma: no cover
            type_hints = get_type_hints(origin, globalns=globalns, localns=localns, include_extras=include_extras)
        # the __parameters__ is only available on the origin itself and not the annotation
        typevar_map = dict(zip(origin.__parameters__, get_args(annotation)))
    return {n: _substitute_typevars(type_, typevar_map) for n, type_ in type_hints.items()}

The cause seems to be a generic class (see MyInputModel in MCVE). When debugging into the litestar code that model does indeed not have a __parameters__ attribute. If I understand this and this correctly, __parameters__ might not always exist. Read: "Note that generics with ParamSpec may not have correct parameters after substitution in some cases because they are intended primarily for static type checking."

Unfortunately, I cannot reproduce this (the model in the MCVE has the same structure, but always has __parameters__ when I test it). Nonetheless, it seems that get_type_hints_with_generics_resolved should account for that.

My non-reproducible example model works, if I replace line 263 in litestar/utils/typing.py:

-        typevar_map = {p: p for p in annotation.__parameters__}
+        typevar_map = {p: p for p in annotation.__type_params__}

I assume it is not as straight forward as that, as __type_params__ seems not to be available before python 3.12 PEP 695. But I am no expert so, maybe it is. ;)

Cheers

URL to code causing the issue

No response

MCVE

import litestar
import msgspec
import uvicorn


class Base(msgspec.Struct, frozen=True):
    field: int = 0


class A(Base, frozen=True, kw_only=True):
    x: int


class B(Base, frozen=True, kw_only=True):
    x: str


class OtherModel(Base, frozen=True, kw_only=True):
    x: float


class MyInputModel[T: A | B](Base, frozen=True, kw_only=True):
    items: list[T]


@litestar.post()
async def handler(data: MyInputModel | OtherModel) -> None:
    if isinstance(data, OtherModel):
        data = MyInputModel(items=[A(x=0, field=0)], field=0)
    print(data)


app = litestar.Litestar(route_handlers=[handler])


uvicorn.run(app, host="127.0.0.1", port=8000)

Steps to reproduce

Unknown

Screenshots

No response

Logs

No response

Litestar Version

2.10.0

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
@aedify-swi aedify-swi added the Bug 🐛 This is something that is not working as expected label Aug 2, 2024
@aedify-swi aedify-swi changed the title Bug: type object 'MyInputModel' has no attribute '__parameters__' Bug: OpenAPI error: type object '<MyInputModel>' has no attribute '__parameters__' Aug 5, 2024
@JacobCoffee JacobCoffee added the Triage Required 🏥 This requires triage label Aug 5, 2024
@JacobCoffee JacobCoffee added the OpenAPI This is related to our OpenAPI schema label Aug 12, 2024
@aedify-swi
Copy link
Contributor Author

Is there anything else I can do?

@provinzkraut
Copy link
Member

provinzkraut commented Sep 14, 2024

@aedify-swi, sorry for the delay, we're all a bit short on time at the moment. I'm trying to catch up with the backlog now though.

What Python version are you running this on? I can't reproduce this with 3.12.4

@aedify-swi
Copy link
Contributor Author

We were on 3.12.1 when I created the issue and just upgraded to 3.12.6 and I still get the described error.

As I wrote above, I cannot reproduce this error either. When setting up a bare-bones project, this does not happen. But our project is rather complex now with quite a few dependencies and I do not know where/why this is introduced. I wonder if it is feasible for you to conditionally use __type_params__ vs. __parameters__ depending on the runtime version of python? I would of course be willing to do the PR.

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 OpenAPI This is related to our OpenAPI schema Triage Required 🏥 This requires triage
Projects
None yet
Development

No branches or pull requests

3 participants