1
1
import contextlib
2
2
import logging
3
- from typing import Optional , Any , List , Dict , get_args , get_origin , ClassVar
3
+ from typing import (
4
+ Optional ,
5
+ Any ,
6
+ List ,
7
+ Dict ,
8
+ Union ,
9
+ get_args ,
10
+ get_origin ,
11
+ ClassVar
12
+ )
4
13
from types import GenericAlias
5
14
from collections import OrderedDict
6
15
from collections .abc import Callable
@@ -59,9 +68,10 @@ def _dc_method_setattr_(self, name: str, value: Any) -> None:
59
68
This version separates the known-field assignment (with optional validation)
60
69
from the “extra field” assignment and uses a helper to perform conversion/validation.
61
70
"""
62
- # Ensure that the __values__ dict is present.
63
- if not hasattr (self , '__values__' ):
64
- object .__setattr__ (self , '__values__' , {})
71
+ if (name .startswith ('__' ) and name .endswith ('__' )):
72
+ # or check explicitly if name in ('__values__', '__valid__', ...)
73
+ object .__setattr__ (self , name , value )
74
+ return
65
75
66
76
# Check whether we are assigning to a known field.
67
77
if name in self .__fields__ :
@@ -84,8 +94,6 @@ def _dc_method_setattr_(self, name: str, value: Any) -> None:
84
94
# For extra attributes, store them as usual.
85
95
# (Note: here we “neutralize” any callable value to None if needed.)
86
96
object .__setattr__ (self , name , None if callable (value ) else value )
87
- if name == '__values__' :
88
- return
89
97
90
98
# If the field isn’t known yet:
91
99
if name not in self .__fields__ :
@@ -245,6 +253,7 @@ def _initialize_fields(attrs, annotations, strict):
245
253
_type_category = 'dataclass'
246
254
elif _is_typing or _is_alias : # noqa
247
255
if df .origin is not None and (df .origin is list and df .args ):
256
+ df ._inner_targs = df .args
248
257
df ._inner_type = args [0 ]
249
258
df ._inner_origin = get_origin (df ._inner_type )
250
259
df ._typing_args = get_args (df ._inner_type )
@@ -254,11 +263,19 @@ def _initialize_fields(attrs, annotations, strict):
254
263
except (TypeError , KeyError ):
255
264
df ._encoder_fn = None
256
265
if origin is list :
257
- inner_type = args [0 ]
266
+ df ._inner_targs = df .args
267
+ df ._inner_type = args [0 ]
258
268
try :
259
- df ._encoder_fn = encoders [inner_type ]
269
+ df ._encoder_fn = encoders [df . _inner_type ]
260
270
except (TypeError , KeyError ):
261
271
df ._encoder_fn = None
272
+ elif origin is Union :
273
+ df ._inner_targs = df .args
274
+ df ._inner_type = args [0 ]
275
+ df ._inner_is_dc = is_dataclass (df ._inner_type )
276
+ df ._inner_priv = is_primitive (df ._inner_type )
277
+ df ._inner_origin = get_origin (df ._inner_type )
278
+ df ._typing_args = get_args (df ._inner_type )
262
279
_type_category = 'typing'
263
280
elif isclass (_type ):
264
281
_type_category = 'class'
@@ -341,10 +358,10 @@ def _initialize_fields(attrs, annotations, strict):
341
358
# Set additional attributes:
342
359
dc .__columns__ = cols
343
360
dc .__fields__ = list (_columns )
344
- dc .__values__ = {}
345
361
dc .__encoder__ = JSONContent
346
362
dc .__valid__ = False
347
- dc .__errors__ = None
363
+ dc .__errors__ = {}
364
+ dc .__values__ = {}
348
365
dc .__frozen__ = strict
349
366
dc .__initialised__ = False
350
367
dc .__field_types__ = _types
0 commit comments