Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

AttributeError: 'ModelField' object has no attribute 'annotation' in openai-python 1.52.0 #2155

Copy link
Copy link
Closed
@sumit-gangwar1

Description

@sumit-gangwar1
Issue body actions

Describe the bug

I encountered an issue while using openai-python version 1.52.0. The error started occurring today, whereas the same code was working fine before. The error occurs in the following line in file src/openai/_models.py:
if field_info.annotation and is_literal_type(field_info.annotation):

Error:
AttributeError: 'ModelField' object has no attribute 'annotation'

To resolve this issue, I modified the code as follows:

if hasattr(field_info, 'annotation') and is_literal_type(field_info.annotation):

After this change, my service started working again as expected.

Key Concerns:

  • Possible Regression: The issue was not present in earlier versions but started occurring after openai-python 1.65.0 was released.
  • Backward Compatibility: Can you confirm if recent changes have introduced an incompatibility with older versions?
  • Priority Investigation: Since this issue affects previously stable versions, it could impact multiple users relying on openai-python.

To Reproduce

Using Python 3.9 and pydantic 1.9.0, run the following:

run = await self.client.beta.threads.runs.create_and_poll(
thread_id=thread_id,
assistant_id=assistant_id,
)

messages = await self.client.beta.threads.messages.list(
thread_id=thread_id, run_id=run.id
)

Expected Behavior:
The code should execute successfully and return messages from the assistant's thread.

Actual Behavior:
The error AttributeError: 'ModelField' object has no attribute 'annotation' is raised.

Code snippets

def _build_discriminated_union_meta(*, union: type, meta_annotations: tuple[Any, ...]) -> DiscriminatorDetails | None:
    if isinstance(union, CachedDiscriminatorType):
        return union.__discriminator__

    discriminator_field_name: str | None = None

    for annotation in meta_annotations:
        if isinstance(annotation, PropertyInfo) and annotation.discriminator is not None:
            discriminator_field_name = annotation.discriminator
            break

    if not discriminator_field_name:
        return None

    mapping: dict[str, type] = {}
    discriminator_alias: str | None = None

    for variant in get_args(union):
        variant = strip_annotated_type(variant)
        if is_basemodel_type(variant):
            if PYDANTIC_V2:
                field = _extract_field_schema_pv2(variant, discriminator_field_name)
                if not field:
                    continue

                # Note: if one variant defines an alias then they all should
                discriminator_alias = field.get("serialization_alias")

                field_schema = field["schema"]

                if field_schema["type"] == "literal":
                    for entry in cast("LiteralSchema", field_schema)["expected"]:
                        if isinstance(entry, str):
                            mapping[entry] = variant
            else:
                field_info = cast("dict[str, FieldInfo]", variant.__fields__).get(discriminator_field_name)  # pyright: ignore[reportDeprecated, reportUnnecessaryCast]
                if not field_info:
                    continue

                # Note: if one variant defines an alias then they all should
                discriminator_alias = field_info.alias

                if hasattr(field_info, 'annotation')  and is_literal_type(field_info.annotation):
                    for entry in get_args(field_info.annotation):
                        if isinstance(entry, str):
                            mapping[entry] = variant

    if not mapping:
        return None

    details = DiscriminatorDetails(
        mapping=mapping,
        discriminator_field=discriminator_field_name,
        discriminator_alias=discriminator_alias,
    )
    cast(CachedDiscriminatorType, union).__discriminator__ = details
    return details

OS

mac 15.3.1

Python version

3.9.0

Library version

1.52.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.