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] TypeError: Subscripted generics cannot be used with class and instance checks #1124

Open
slavashvets opened this issue Feb 17, 2025 · 0 comments

Comments

@slavashvets
Copy link

Describe the bug

When using Python 3.12 with Beanie and a Pydantic (v2) model that has a union-typed field using a discriminated union (via Annotated), Beanie's internal encoder raises a TypeError because it attempts to do an isinstance() check against subscripted generics.

See https://bugs.python.org/issue44529

To Reproduce

from typing import Annotated
from pydantic import BaseModel, Field
from pydantic_ai.messages import ModelRequest, ModelResponse
from beanie import Document

class MyBase(BaseModel):
    # A discriminated union
    data: Annotated[ModelRequest | ModelResponse, "kind"] = Field(...)

class ChatMessage(MyBase, Document):
    class Settings:
        # ...
        pass

Expected behavior
Handle these union-typed fields without errors.

Actual behavior

TypeError: Subscripted generics cannot be used with class and instance checks

Because Beanie's internal _get_encoder does something like:

isinstance(obj, Union[ModelRequest, ModelResponse])

Additional context
I've had to monkey-patch Beanie's _get_encoder to work around this issue:

from typing import get_args, get_origin

import beanie.odm.utils.encoder as encoder_module

_original_get_encoder = encoder_module._get_encoder

def _get_encoder_patched(obj, custom_encoders):

    encoder = custom_encoders.get(type(obj))
    if encoder is not None:
        return encoder

    for cls, encoder in custom_encoders.items():
        origin = get_origin(cls)
        if origin is not None:
            for arg in get_args(cls):
                if isinstance(arg, type) and isinstance(obj, arg):
                    return encoder
        else:
            if isinstance(obj, cls):
                return encoder
    return None

encoder_module._get_encoder = _get_encoder_patched
@slavashvets slavashvets changed the title [BUG] [BUG] TypeError: Subscripted generics cannot be used with class and instance checks Feb 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant