1+ """Methods for resolving types to fields."""
12import datetime
23import enum
34import pathlib
45import re
56import uuid
6- from typing import Any , Sequence , Dict , Type , Union , get_origin , List
7+ from typing import Any , Sequence , Dict , Type , Union , get_origin , List , Final
78
89try :
910 # Handle the change in typing between 3.8 and later releases
2728 ListField ,
2829 DictField ,
2930)
31+ from ..fields .virtual import ConstantField
3032from ..resources import ResourceBase
3133
3234
3335class Options :
34- """
35- Define options for a field
36- """
36+ """Define options for a field"""
3737
3838 __slots__ = (
3939 "field_type" ,
@@ -78,18 +78,14 @@ def __init__(
7878 }
7979
8080 def _kwargs (self ):
81- """
82- Build kwargs used to instantiate field
83- """
81+ """Build kwargs used to instantiate field"""
8482 final_args = self .base_args
8583 if issubclass (self .field_type , Field ):
8684 final_args .update (self .field_args )
8785 return final_args
8886
8987 def _improve_error (self , ex : TypeError ):
90- """
91- Attempt to provide more context for the error
92- """
88+ """Attempt to provide more context for the error"""
9389 message = str (ex )
9490
9591 for check in (
@@ -103,16 +99,16 @@ def _improve_error(self, ex: TypeError):
10399 )
104100
105101 def init_field (self ):
106- """
107- Instantiate field object
108- """
102+ """Instantiate field object"""
109103 if self .field_type :
110104 try :
111105 return self .field_type (** self ._kwargs ())
112106 except TypeError as ex :
113107 self ._improve_error (ex )
114108 raise
115- raise ResourceDefError ("Field type could not be resolved" )
109+ raise ResourceDefError (
110+ f"Field type `{ self .base_args .get ('name' , 'Unknown!' )} ` could not be resolved"
111+ )
116112
117113
118114SIMPLE_TYPE_MAP = {
@@ -138,9 +134,7 @@ def init_field(self):
138134
139135
140136def _resolve_field_from_type (options : Options , type_ : type ):
141- """
142- Resolve a field from a basic type
143- """
137+ """Resolve a field from a basic type"""
144138 if field_type := SIMPLE_TYPE_MAP .get (type_ , None ):
145139 options .field_type = field_type
146140
@@ -159,19 +153,15 @@ def _resolve_field_from_type(options: Options, type_: type):
159153
160154
161155def is_optional (type_ : Union ) -> bool :
162- """
163- Field is an optional type
164- """
156+ """Field is an optional type"""
165157 args = type_ .__args__
166158 return (
167159 len (args ) == 2 and type (None ) in args
168160 ) # pylint: disable=unidiomatic-typecheck
169161
170162
171163def _resolve_list_from_sub_scripted_type (args : Sequence [Any ], options : Options ):
172- """
173- Handle the various types of sequence type
174- """
164+ """Handle the various types of sequence type"""
175165 options .field_args ["default" ] = list
176166
177167 (field ,) = args
@@ -189,9 +179,7 @@ def _resolve_list_from_sub_scripted_type(args: Sequence[Any], options: Options):
189179
190180
191181def _resolve_dict_from_sub_scripted_type (args : Sequence [Any ], options : Options ):
192- """
193- Handle the various types of sequence type
194- """
182+ """Handle the various types of sequence type"""
195183 options .field_args ["default" ] = dict
196184
197185 key_field , value_field = args
@@ -214,9 +202,7 @@ def _resolve_dict_from_sub_scripted_type(args: Sequence[Any], options: Options):
214202
215203
216204def _resolve_field_from_sub_scripted_type (origin : Type , options : Options , type_ ):
217- """
218- Resolve a field from a generic type
219- """
205+ """Resolve a field from a generic type"""
220206 args = getattr (type_ , "__args__" , None )
221207 if not args :
222208 # This occurs with the plain List and Dict types which are essentially
@@ -229,6 +215,17 @@ def _resolve_field_from_sub_scripted_type(origin: Type, options: Options, type_)
229215 if is_optional (type_ ):
230216 options .field_args ["null" ] = True
231217 return _resolve_field_from_annotation (options , args [0 ])
218+ else :
219+ pass # Resolve
220+
221+ elif origin is Final :
222+ # Constant
223+ options .field_type = ConstantField
224+ value = options .field_args ["default" ]
225+ if value is NotProvided :
226+ raise ResourceDefError (f"Final fields require a value" )
227+ options .base_args ["value" ] = value
228+ return
232229
233230 elif issubclass (origin , List ):
234231 return _resolve_list_from_sub_scripted_type (args , options )
@@ -267,9 +264,7 @@ def process_attribute(
267264 * ,
268265 _base_field : Type [BaseField ] = BaseField ,
269266) -> BaseField :
270- """
271- Process an individual attribute and generate a field based off values passed
272- """
267+ """Process an individual attribute and generate a field based off values passed"""
273268
274269 # Attribute is already a field object
275270 if isinstance (value , _base_field ):
0 commit comments