Skip to content

Commit 66e5eeb

Browse files
fix(specs): more accurate composition behavior typing (generated)
algolia/api-clients-automation#5892 Co-authored-by: algolia-bot <accounts+algolia-api-client-bot@algolia.com> Co-authored-by: Gavin Wade <gavin.wade12@gmail.com>
1 parent d81f27e commit 66e5eeb

4 files changed

Lines changed: 261 additions & 55 deletions

File tree

algoliasearch/composition/models/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
from .composition import Composition
2727
from .composition_behavior import CompositionBehavior
2828
from .composition_id_ranking_info import CompositionIdRankingInfo
29+
from .composition_injection_behavior import CompositionInjectionBehavior
30+
from .composition_multifeed_behavior import CompositionMultifeedBehavior
2931
from .composition_rule import CompositionRule
3032
from .composition_rule_consequence import CompositionRuleConsequence
3133
from .composition_rules_batch_params import CompositionRulesBatchParams
@@ -138,6 +140,8 @@
138140
"Composition",
139141
"CompositionBehavior",
140142
"CompositionIdRankingInfo",
143+
"CompositionInjectionBehavior",
144+
"CompositionMultifeedBehavior",
141145
"CompositionRule",
142146
"CompositionRuleConsequence",
143147
"CompositionRulesBatchParams",

algoliasearch/composition/models/composition_behavior.py

Lines changed: 97 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6,83 +6,125 @@
66

77
from __future__ import annotations
88

9-
from json import loads
9+
from json import dumps
1010
from sys import version_info
11-
from typing import Any, Dict, Optional
11+
from typing import Any, Dict, Optional, Set, Union
1212

13-
from pydantic import BaseModel, ConfigDict
13+
from pydantic import BaseModel, Field, ValidationError, model_serializer
1414

1515
if version_info >= (3, 11):
1616
from typing import Self
1717
else:
1818
from typing_extensions import Self
1919

2020

21-
from algoliasearch.composition.models.injection import Injection
22-
from algoliasearch.composition.models.multifeed import Multifeed
23-
24-
_ALIASES = {
25-
"injection": "injection",
26-
"multifeed": "multifeed",
27-
}
28-
29-
30-
def _alias_generator(name: str) -> str:
31-
return _ALIASES.get(name, name)
21+
from algoliasearch.composition.models.composition_injection_behavior import (
22+
CompositionInjectionBehavior,
23+
)
24+
from algoliasearch.composition.models.composition_multifeed_behavior import (
25+
CompositionMultifeedBehavior,
26+
)
3227

3328

3429
class CompositionBehavior(BaseModel):
3530
"""
3631
An object containing either an `injection` or `multifeed` behavior schema, but not both.
3732
"""
3833

39-
injection: Optional[Injection] = None
40-
multifeed: Optional[Multifeed] = None
41-
42-
model_config = ConfigDict(
43-
strict=False,
44-
use_enum_values=True,
45-
populate_by_name=True,
46-
validate_assignment=True,
47-
protected_namespaces=(),
48-
alias_generator=_alias_generator,
49-
extra="allow",
34+
oneof_schema_1_validator: Optional[CompositionInjectionBehavior] = Field(
35+
default=None
5036
)
5137

52-
def to_json(self) -> str:
53-
return self.model_dump_json(by_alias=True, exclude_unset=True)
38+
oneof_schema_2_validator: Optional[CompositionMultifeedBehavior] = Field(
39+
default=None
40+
)
41+
42+
actual_instance: Union[
43+
CompositionInjectionBehavior, CompositionMultifeedBehavior, None
44+
] = None
45+
one_of_schemas: Set[str] = {
46+
"CompositionInjectionBehavior",
47+
"CompositionMultifeedBehavior",
48+
}
49+
50+
def __init__(self, *args, **kwargs) -> None:
51+
if args:
52+
if len(args) > 1:
53+
raise ValueError(
54+
"If a position argument is used, only 1 is allowed to set `actual_instance`"
55+
)
56+
if kwargs:
57+
raise ValueError(
58+
"If a position argument is used, keyword arguments cannot be used."
59+
)
60+
super().__init__(actual_instance=args[0]) # pyright: ignore
61+
else:
62+
super().__init__(**kwargs)
63+
64+
@model_serializer
65+
def unwrap_actual_instance(
66+
self,
67+
) -> Union[CompositionInjectionBehavior, CompositionMultifeedBehavior, Self, None]:
68+
"""
69+
Unwraps the `actual_instance` when calling the `to_json` method.
70+
"""
71+
return self.actual_instance if hasattr(self, "actual_instance") else self
5472

5573
@classmethod
56-
def from_json(cls, json_str: str) -> Optional[Self]:
74+
def from_dict(cls, obj: Union[str, Dict[str, Any]]) -> Self:
5775
"""Create an instance of CompositionBehavior from a JSON string"""
58-
return cls.from_dict(loads(json_str))
59-
60-
def to_dict(self) -> Dict[str, Any]:
61-
"""Return the dictionary representation of the model using alias."""
62-
return self.model_dump(
63-
by_alias=True,
64-
exclude_none=True,
65-
exclude_unset=True,
66-
)
76+
return cls.from_json(dumps(obj))
6777

6878
@classmethod
69-
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
70-
"""Create an instance of CompositionBehavior from a dict"""
71-
if obj is None:
72-
return None
73-
74-
if not isinstance(obj, dict):
75-
return cls.model_validate(obj)
76-
77-
obj["injection"] = (
78-
Injection.from_dict(obj["injection"])
79-
if obj.get("injection") is not None
80-
else None
81-
)
82-
obj["multifeed"] = (
83-
Multifeed.from_dict(obj["multifeed"])
84-
if obj.get("multifeed") is not None
85-
else None
79+
def from_json(cls, json_str: str) -> Self:
80+
"""Returns the object represented by the json string"""
81+
instance = cls.model_construct()
82+
error_messages = []
83+
84+
try:
85+
instance.actual_instance = CompositionInjectionBehavior.from_json(json_str)
86+
87+
return instance
88+
except (ValidationError, ValueError) as e:
89+
error_messages.append(str(e))
90+
try:
91+
instance.actual_instance = CompositionMultifeedBehavior.from_json(json_str)
92+
93+
return instance
94+
except (ValidationError, ValueError) as e:
95+
error_messages.append(str(e))
96+
97+
raise ValueError(
98+
"No match found when deserializing the JSON string into CompositionBehavior with oneOf schemas: CompositionInjectionBehavior, CompositionMultifeedBehavior. Details: "
99+
+ ", ".join(error_messages)
86100
)
87101

88-
return cls.model_validate(obj)
102+
def to_json(self) -> str:
103+
"""Returns the JSON representation of the actual instance"""
104+
if self.actual_instance is None:
105+
return "null"
106+
107+
if hasattr(self.actual_instance, "to_json") and callable(
108+
self.actual_instance.to_json # pyright: ignore
109+
):
110+
return self.actual_instance.to_json() # pyright: ignore
111+
else:
112+
return dumps(self.actual_instance)
113+
114+
def to_dict(
115+
self,
116+
) -> Optional[
117+
Union[
118+
Dict[str, Any], CompositionInjectionBehavior, CompositionMultifeedBehavior
119+
]
120+
]:
121+
"""Returns the dict representation of the actual instance"""
122+
if self.actual_instance is None:
123+
return None
124+
125+
if hasattr(self.actual_instance, "to_dict") and callable(
126+
self.actual_instance.to_dict # pyright: ignore
127+
):
128+
return self.actual_instance.to_dict() # pyright: ignore
129+
else:
130+
return self.actual_instance # pyright: ignore
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# coding: utf-8
2+
3+
"""
4+
Code generated by OpenAPI Generator (https://openapi-generator.tech), manual changes will be lost - read more on https://github.com/algolia/api-clients-automation. DO NOT EDIT.
5+
"""
6+
7+
from __future__ import annotations
8+
9+
from json import loads
10+
from sys import version_info
11+
from typing import Any, Dict, Optional
12+
13+
from pydantic import BaseModel, ConfigDict
14+
15+
if version_info >= (3, 11):
16+
from typing import Self
17+
else:
18+
from typing_extensions import Self
19+
20+
21+
from algoliasearch.composition.models.injection import Injection
22+
23+
_ALIASES = {
24+
"injection": "injection",
25+
}
26+
27+
28+
def _alias_generator(name: str) -> str:
29+
return _ALIASES.get(name, name)
30+
31+
32+
class CompositionInjectionBehavior(BaseModel):
33+
"""
34+
An object containing an `injection` behavior.
35+
"""
36+
37+
injection: Injection
38+
39+
model_config = ConfigDict(
40+
strict=False,
41+
use_enum_values=True,
42+
populate_by_name=True,
43+
validate_assignment=True,
44+
protected_namespaces=(),
45+
alias_generator=_alias_generator,
46+
extra="allow",
47+
)
48+
49+
def to_json(self) -> str:
50+
return self.model_dump_json(by_alias=True, exclude_unset=True)
51+
52+
@classmethod
53+
def from_json(cls, json_str: str) -> Optional[Self]:
54+
"""Create an instance of CompositionInjectionBehavior from a JSON string"""
55+
return cls.from_dict(loads(json_str))
56+
57+
def to_dict(self) -> Dict[str, Any]:
58+
"""Return the dictionary representation of the model using alias."""
59+
return self.model_dump(
60+
by_alias=True,
61+
exclude_none=True,
62+
exclude_unset=True,
63+
)
64+
65+
@classmethod
66+
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
67+
"""Create an instance of CompositionInjectionBehavior from a dict"""
68+
if obj is None:
69+
return None
70+
71+
if not isinstance(obj, dict):
72+
return cls.model_validate(obj)
73+
74+
obj["injection"] = (
75+
Injection.from_dict(obj["injection"])
76+
if obj.get("injection") is not None
77+
else None
78+
)
79+
80+
return cls.model_validate(obj)
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# coding: utf-8
2+
3+
"""
4+
Code generated by OpenAPI Generator (https://openapi-generator.tech), manual changes will be lost - read more on https://github.com/algolia/api-clients-automation. DO NOT EDIT.
5+
"""
6+
7+
from __future__ import annotations
8+
9+
from json import loads
10+
from sys import version_info
11+
from typing import Any, Dict, Optional
12+
13+
from pydantic import BaseModel, ConfigDict
14+
15+
if version_info >= (3, 11):
16+
from typing import Self
17+
else:
18+
from typing_extensions import Self
19+
20+
21+
from algoliasearch.composition.models.multifeed import Multifeed
22+
23+
_ALIASES = {
24+
"multifeed": "multifeed",
25+
}
26+
27+
28+
def _alias_generator(name: str) -> str:
29+
return _ALIASES.get(name, name)
30+
31+
32+
class CompositionMultifeedBehavior(BaseModel):
33+
"""
34+
An object containing a `multifeed` behavior.
35+
"""
36+
37+
multifeed: Multifeed
38+
39+
model_config = ConfigDict(
40+
strict=False,
41+
use_enum_values=True,
42+
populate_by_name=True,
43+
validate_assignment=True,
44+
protected_namespaces=(),
45+
alias_generator=_alias_generator,
46+
extra="allow",
47+
)
48+
49+
def to_json(self) -> str:
50+
return self.model_dump_json(by_alias=True, exclude_unset=True)
51+
52+
@classmethod
53+
def from_json(cls, json_str: str) -> Optional[Self]:
54+
"""Create an instance of CompositionMultifeedBehavior from a JSON string"""
55+
return cls.from_dict(loads(json_str))
56+
57+
def to_dict(self) -> Dict[str, Any]:
58+
"""Return the dictionary representation of the model using alias."""
59+
return self.model_dump(
60+
by_alias=True,
61+
exclude_none=True,
62+
exclude_unset=True,
63+
)
64+
65+
@classmethod
66+
def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
67+
"""Create an instance of CompositionMultifeedBehavior from a dict"""
68+
if obj is None:
69+
return None
70+
71+
if not isinstance(obj, dict):
72+
return cls.model_validate(obj)
73+
74+
obj["multifeed"] = (
75+
Multifeed.from_dict(obj["multifeed"])
76+
if obj.get("multifeed") is not None
77+
else None
78+
)
79+
80+
return cls.model_validate(obj)

0 commit comments

Comments
 (0)