Skip to content

Commit d650e4f

Browse files
committed
add tech design for resolving union annotaion.
1 parent f6935e8 commit d650e4f

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

devlog/25-8-resolve-union.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Add support for Union
2+
3+
current this case will raise exception becuase A, B inside C is not walked during analysis
4+
5+
which means they are not stored at metadata.
6+
7+
and then during resolving it will attempt to read A and B from metadata then exceptions are raised.
8+
9+
this feature aims to fix this bug.
10+
11+
```python
12+
class A(BaseModel):
13+
id: int
14+
name: str
15+
16+
class B(BaseModel):
17+
id: int
18+
age: int
19+
20+
class C(BaseModel):
21+
items: List[Union[A, B]] = []
22+
def resolve(self):
23+
return [A(id=1, name='n'), B(id=1, age=21)]
24+
```
25+
26+
for Union[A, B] pydantic-resolve will dive into A, B and store them in metadata.
27+
28+
## plan
29+
30+
- add `get_core_types` in types.py, will replace `shelling_type`
31+
- check the code using `shelling_type` and their deps
32+
- class_utils.py
33+
- get_pydantic_fields: change the return type from type -> tuple of type
34+
- get_dataclass_fields
35+
- update_forward_refs
36+
- update_pydantic_forward_refs
37+
- update_dataclass_forward_refs
38+
- analysis.py
39+
- scan_and_store_metadata
40+
- \_get_all_fields_and_object_fields
41+
- object_field_pairs from \_get_all_fields_and_object_fields
42+
- \_get_request_type_for_loader: calculate receiver types for dataloader
43+
44+
## details
45+
46+
```python
47+
def get_pydantic_fields(kls) -> Tuple[str, List[Type[BaseModel]]]:
48+
items = class_util.get_pydantic_field_items(kls)
49+
50+
for name, v in items:
51+
t = get_type(v)
52+
53+
shelled_types = get_core_types(t)
54+
expected_types = [t for t in shelled_types if is_acceptable_kls(t)]
55+
if expected_types:
56+
yield (name, expected_types) # type_ is the most inner type
57+
```
58+
59+
object_fields and object_field_pairs will be affected
60+
61+
```python
62+
all_fields, object_fields, object_field_pairs = _get_all_fields_and_object_fields(kls)
63+
```
64+
65+
object_fields:
66+
67+
```python
68+
69+
object_fields_without_resolver = [a[0] for a in object_fields if a[0] not in fields_with_resolver]
70+
71+
info: KlsMetaType = {
72+
'resolve': resolve_fields,
73+
'resolve_params': resolve_params,
74+
'post': post_fields,
75+
'post_params': post_params,
76+
'post_default_handler_params': post_default_handler_params,
77+
'raw_object_fields': object_fields_without_resolver, # <----- here
78+
'object_fields': [],
79+
'expose_dict': expose_dict,
80+
'collect_dict': collect_dict,
81+
'kls': kls,
82+
'has_context': has_context,
83+
'should_traverse': False
84+
}
85+
86+
for field, shelled_type in (obj for obj in object_fields if obj[0] in object_fields_without_resolver):
87+
walker(shelled_type, ancestors + [(field, kls_name)])
88+
```

0 commit comments

Comments
 (0)