-
-
Notifications
You must be signed in to change notification settings - Fork 7.4k
Python sdk anyof allof root model #22955
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
base: master
Are you sure you want to change the base?
Changes from all commits
825b528
9e2e0d5
294b05d
59e8dbc
9bfe0f7
06f5b7c
a925bbd
b651020
1dc5983
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,177 +1,61 @@ | ||||||
| from __future__ import annotations | ||||||
| from inspect import getfullargspec | ||||||
| import json | ||||||
| import pprint | ||||||
| import re # noqa: F401 | ||||||
| {{#vendorExtensions.x-py-other-imports}} | ||||||
| {{{.}}} | ||||||
| {{/vendorExtensions.x-py-other-imports}} | ||||||
| {{#vendorExtensions.x-py-model-imports}} | ||||||
| {{{.}}} | ||||||
| {{/vendorExtensions.x-py-model-imports}} | ||||||
| from pydantic import Field, RootModel | ||||||
| from typing import Union, Any, List, Set, TYPE_CHECKING, Optional, Dict | ||||||
| from typing_extensions import Literal, Self | ||||||
| from pydantic import Field | ||||||
|
|
||||||
| {{#lambda.uppercase}}{{{classname}}}{{/lambda.uppercase}}_ANY_OF_SCHEMAS = [{{#anyOf}}"{{.}}"{{^-last}}, {{/-last}}{{/anyOf}}] | ||||||
|
|
||||||
| class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}): | ||||||
|
|
||||||
| class {{classname}}(RootModel[Union[{{#anyOf}}{{.}}{{^-last}}, {{/-last}}{{/anyOf}}]]): | ||||||
| """ | ||||||
| {{{description}}}{{^description}}{{{classname}}}{{/description}} | ||||||
| """ | ||||||
| root: Union[{{#anyOf}}{{.}}{{^-last}}, {{/-last}}{{/anyOf}}{{#isNullable}}, None{{/isNullable}}] = Field( | ||||||
| {{#isNullable}}None{{/isNullable}}{{^isNullable}}...{{/isNullable}}{{#discriminator}}{{/discriminator}} | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Discriminated unions in Pydantic v2 require Prompt for AI agents
Suggested change
|
||||||
| ) | ||||||
|
|
||||||
| {{#composedSchemas.anyOf}} | ||||||
| # data type: {{{dataType}}} | ||||||
| {{vendorExtensions.x-py-name}}: {{{vendorExtensions.x-py-typing}}} | ||||||
| {{/composedSchemas.anyOf}} | ||||||
| if TYPE_CHECKING: | ||||||
| actual_instance: Optional[Union[{{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}]] = None | ||||||
| else: | ||||||
| actual_instance: Any = None | ||||||
| any_of_schemas: Set[str] = { {{#anyOf}}"{{.}}"{{^-last}}, {{/-last}}{{/anyOf}} } | ||||||
|
|
||||||
| model_config = { | ||||||
| "validate_assignment": True, | ||||||
| "protected_namespaces": (), | ||||||
| } | ||||||
| {{#discriminator}} | ||||||
|
|
||||||
| discriminator_value_class_map: Dict[str, str] = { | ||||||
| {{#children}} | ||||||
| '{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}': '{{{classname}}}'{{^-last}},{{/-last}} | ||||||
| {{/children}} | ||||||
| } | ||||||
| {{/discriminator}} | ||||||
| def __getattr__(self, name): | ||||||
| """ | ||||||
| Delegate attribute access to the root model if the attribute | ||||||
| doesn't exist on the main class. | ||||||
| """ | ||||||
|
|
||||||
| def __init__(self, *args, **kwargs) -> None: | ||||||
| if args: | ||||||
| if len(args) > 1: | ||||||
| raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") | ||||||
| if kwargs: | ||||||
| raise ValueError("If a position argument is used, keyword arguments cannot be used.") | ||||||
| super().__init__(actual_instance=args[0]) | ||||||
| else: | ||||||
| super().__init__(**kwargs) | ||||||
| if name in self.__dict__: | ||||||
| return super().__getattribute__(name) | ||||||
|
|
||||||
| @field_validator('actual_instance') | ||||||
| def actual_instance_must_validate_anyof(cls, v): | ||||||
| {{#isNullable}} | ||||||
| if v is None: | ||||||
| return v | ||||||
| root = self.__dict__.get('root') | ||||||
| if root is not None: | ||||||
| return getattr(root, name) | ||||||
|
|
||||||
| {{/isNullable}} | ||||||
| instance = {{{classname}}}.model_construct() | ||||||
| error_messages = [] | ||||||
| {{#composedSchemas.anyOf}} | ||||||
| # validate data type: {{{dataType}}} | ||||||
| {{#isContainer}} | ||||||
| try: | ||||||
| instance.{{vendorExtensions.x-py-name}} = v | ||||||
| return v | ||||||
| except (ValidationError, ValueError) as e: | ||||||
| error_messages.append(str(e)) | ||||||
| {{/isContainer}} | ||||||
| {{^isContainer}} | ||||||
| {{#isPrimitiveType}} | ||||||
| try: | ||||||
| instance.{{vendorExtensions.x-py-name}} = v | ||||||
| return v | ||||||
| except (ValidationError, ValueError) as e: | ||||||
| error_messages.append(str(e)) | ||||||
| {{/isPrimitiveType}} | ||||||
| {{^isPrimitiveType}} | ||||||
| if not isinstance(v, {{{dataType}}}): | ||||||
| error_messages.append(f"Error! Input type `{type(v)}` is not `{{{dataType}}}`") | ||||||
| else: | ||||||
| return v | ||||||
|
|
||||||
| {{/isPrimitiveType}} | ||||||
| {{/isContainer}} | ||||||
| {{/composedSchemas.anyOf}} | ||||||
| if error_messages: | ||||||
| # no match | ||||||
| raise ValueError("No match found when setting the actual_instance in {{{classname}}} with anyOf schemas: {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}. Details: " + ", ".join(error_messages)) | ||||||
| else: | ||||||
| return v | ||||||
| raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'") | ||||||
|
|
||||||
| @classmethod | ||||||
| def from_dict(cls, obj: Dict[str, Any]) -> Self: | ||||||
| return cls.from_json(json.dumps(obj)) | ||||||
| """Returns the object represented by the Dict""" | ||||||
| return cls.model_validate(obj, strict=True) | ||||||
|
|
||||||
| @classmethod | ||||||
| def from_json(cls, json_str: str) -> Self: | ||||||
| """Returns the object represented by the json string""" | ||||||
| instance = cls.model_construct() | ||||||
| {{#isNullable}} | ||||||
| if json_str is None: | ||||||
| return instance | ||||||
|
|
||||||
| {{/isNullable}} | ||||||
| error_messages = [] | ||||||
| {{#composedSchemas.anyOf}} | ||||||
| {{#isContainer}} | ||||||
| # deserialize data into {{{dataType}}} | ||||||
| try: | ||||||
| # validation | ||||||
| instance.{{vendorExtensions.x-py-name}} = json.loads(json_str) | ||||||
| # assign value to actual_instance | ||||||
| instance.actual_instance = instance.{{vendorExtensions.x-py-name}} | ||||||
| return instance | ||||||
| except (ValidationError, ValueError) as e: | ||||||
| error_messages.append(str(e)) | ||||||
| {{/isContainer}} | ||||||
| {{^isContainer}} | ||||||
| {{#isPrimitiveType}} | ||||||
| # deserialize data into {{{dataType}}} | ||||||
| try: | ||||||
| # validation | ||||||
| instance.{{vendorExtensions.x-py-name}} = json.loads(json_str) | ||||||
| # assign value to actual_instance | ||||||
| instance.actual_instance = instance.{{vendorExtensions.x-py-name}} | ||||||
| return instance | ||||||
| except (ValidationError, ValueError) as e: | ||||||
| error_messages.append(str(e)) | ||||||
| {{/isPrimitiveType}} | ||||||
| {{^isPrimitiveType}} | ||||||
| # {{vendorExtensions.x-py-name}}: {{{vendorExtensions.x-py-typing}}} | ||||||
| try: | ||||||
| instance.actual_instance = {{{dataType}}}.from_json(json_str) | ||||||
| return instance | ||||||
| except (ValidationError, ValueError) as e: | ||||||
| error_messages.append(str(e)) | ||||||
| {{/isPrimitiveType}} | ||||||
| {{/isContainer}} | ||||||
| {{/composedSchemas.anyOf}} | ||||||
| return cls.model_validate_json(json_str) | ||||||
|
|
||||||
| if error_messages: | ||||||
| # no match | ||||||
| raise ValueError("No match found when deserializing the JSON string into {{{classname}}} with anyOf schemas: {{#anyOf}}{{{.}}}{{^-last}}, {{/-last}}{{/anyOf}}. Details: " + ", ".join(error_messages)) | ||||||
| else: | ||||||
| return instance | ||||||
|
|
||||||
| def to_json(self) -> str: | ||||||
| """Returns the JSON representation of the actual instance""" | ||||||
| if self.actual_instance is None: | ||||||
| return "null" | ||||||
|
|
||||||
| if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): | ||||||
| return self.actual_instance.to_json() | ||||||
| else: | ||||||
| return json.dumps(self.actual_instance) | ||||||
|
|
||||||
| def to_dict(self) -> Optional[Union[Dict[str, Any], {{#anyOf}}{{.}}{{^-last}}, {{/-last}}{{/anyOf}}]]: | ||||||
| def to_dict(self, exclude_unset: bool = True) -> Dict[str, Any]: | ||||||
| """Returns the dict representation of the actual instance""" | ||||||
| if self.actual_instance is None: | ||||||
| return None | ||||||
| return self.model_dump(by_alias=True, exclude_unset=exclude_unset) | ||||||
|
|
||||||
| if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): | ||||||
| return self.actual_instance.to_dict() | ||||||
| else: | ||||||
| return self.actual_instance | ||||||
| def to_json(self, exclude_unset: bool = True) -> str: | ||||||
| """Returns the JSON representation of the actual instance""" | ||||||
| return json.dumps(self.model_dump(by_alias=True, exclude_unset=exclude_unset, mode="json")) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: json and pprint are used in to_json/to_str but are no longer imported in this template, causing NameError at runtime in generated models. Prompt for AI agents |
||||||
|
|
||||||
| def to_str(self) -> str: | ||||||
| """Returns the string representation of the actual instance""" | ||||||
| return pprint.pformat(self.model_dump()) | ||||||
| """Returns the string representation of the model using alias""" | ||||||
| return pprint.pformat(self.to_dict(exclude_unset=False)) | ||||||
|
|
||||||
| {{#vendorExtensions.x-py-postponed-model-imports.size}} | ||||||
| {{#vendorExtensions.x-py-postponed-model-imports}} | ||||||
|
|
||||||
Uh oh!
There was an error while loading. Please reload this page.