3838import  re 
3939import  sys 
4040import  codecs 
41- from  typing  import  Optional , Union , AnyStr , IO , Mapping 
41+ from  typing  import  (
42+     Dict ,
43+     Any ,
44+     cast ,
45+     Optional ,
46+     Union ,
47+     AnyStr ,
48+     IO ,
49+     Mapping ,
50+     Callable ,
51+     TypeVar ,
52+     MutableMapping ,
53+     Type ,
54+     List ,
55+     Mapping ,
56+ )
4257
4358try :
4459    from  urllib  import  quote   # type: ignore 
4863
4964import  isodate   # type: ignore 
5065
51- from  typing  import  Dict , Any , cast 
52- 
5366from  azure .core .exceptions  import  DeserializationError , SerializationError , raise_with_traceback 
67+ from  azure .core .serialization  import  NULL  as  AzureCoreNull 
5468
5569_BOM  =  codecs .BOM_UTF8 .decode (encoding = "utf-8" )
5670
71+ ModelType  =  TypeVar ("ModelType" , bound = "Model" )
72+ JSON  =  MutableMapping [str , Any ]
73+ 
5774
5875class  RawDeserializer :
5976
@@ -277,8 +294,8 @@ class Model(object):
277294    _attribute_map : Dict [str , Dict [str , Any ]] =  {}
278295    _validation : Dict [str , Dict [str , Any ]] =  {}
279296
280-     def  __init__ (self , ** kwargs ) :
281-         self .additional_properties  =  {}
297+     def  __init__ (self , ** kwargs :  Any )  ->   None :
298+         self .additional_properties :  Dict [ str ,  Any ]  =  {}
282299        for  k  in  kwargs :
283300            if  k  not  in self ._attribute_map :
284301                _LOGGER .warning ("%s is not a known attribute of class %s and will be ignored" , k , self .__class__ )
@@ -287,25 +304,25 @@ def __init__(self, **kwargs):
287304            else :
288305                setattr (self , k , kwargs [k ])
289306
290-     def  __eq__ (self , other ) :
307+     def  __eq__ (self , other :  Any )  ->   bool :
291308        """Compare objects by comparing all attributes.""" 
292309        if  isinstance (other , self .__class__ ):
293310            return  self .__dict__  ==  other .__dict__ 
294311        return  False 
295312
296-     def  __ne__ (self , other ) :
313+     def  __ne__ (self , other :  Any )  ->   bool :
297314        """Compare objects by comparing all attributes.""" 
298315        return  not  self .__eq__ (other )
299316
300-     def  __str__ (self ):
317+     def  __str__ (self )  ->   str :
301318        return  str (self .__dict__ )
302319
303320    @classmethod  
304-     def  enable_additional_properties_sending (cls ):
321+     def  enable_additional_properties_sending (cls )  ->   None :
305322        cls ._attribute_map ["additional_properties" ] =  {"key" : "" , "type" : "{object}" }
306323
307324    @classmethod  
308-     def  is_xml_model (cls ):
325+     def  is_xml_model (cls )  ->   bool :
309326        try :
310327            cls ._xml_map   # type: ignore 
311328        except  AttributeError :
@@ -322,7 +339,7 @@ def _create_xml_node(cls):
322339
323340        return  _create_xml_node (xml_map .get ("name" , cls .__name__ ), xml_map .get ("prefix" , None ), xml_map .get ("ns" , None ))
324341
325-     def  serialize (self , keep_readonly = False , ** kwargs ) :
342+     def  serialize (self , keep_readonly :  bool   =   False , ** kwargs :  Any )  ->   JSON :
326343        """Return the JSON that would be sent to azure from this model. 
327344
328345        This is an alias to `as_dict(full_restapi_key_transformer, keep_readonly=False)`. 
@@ -336,8 +353,13 @@ def serialize(self, keep_readonly=False, **kwargs):
336353        serializer  =  Serializer (self ._infer_class_models ())
337354        return  serializer ._serialize (self , keep_readonly = keep_readonly , ** kwargs )
338355
339-     def  as_dict (self , keep_readonly = True , key_transformer = attribute_transformer , ** kwargs ):
340-         """Return a dict that can be JSONify using json.dump. 
356+     def  as_dict (
357+         self ,
358+         keep_readonly : bool  =  True ,
359+         key_transformer : Callable [[str , Dict [str , Any ], Any ], Any ] =  attribute_transformer ,
360+         ** kwargs : Any 
361+     ) ->  JSON :
362+         """Return a dict that can be serialized using json.dump. 
341363
342364        Advanced usage might optionally use a callback as parameter: 
343365
@@ -384,7 +406,7 @@ def _infer_class_models(cls):
384406        return  client_models 
385407
386408    @classmethod  
387-     def  deserialize (cls , data , content_type = None ):
409+     def  deserialize (cls :  Type [ ModelType ] , data :  Any , content_type :  Optional [ str ]  =   None )  ->   ModelType :
388410        """Parse a str using the RestAPI syntax and return a model. 
389411
390412        :param str data: A str using RestAPI structure. JSON by default. 
@@ -396,7 +418,12 @@ def deserialize(cls, data, content_type=None):
396418        return  deserializer (cls .__name__ , data , content_type = content_type )
397419
398420    @classmethod  
399-     def  from_dict (cls , data , key_extractors = None , content_type = None ):
421+     def  from_dict (
422+         cls : Type [ModelType ],
423+         data : Any ,
424+         key_extractors : Optional [Callable [[str , Dict [str , Any ], Any ], Any ]] =  None ,
425+         content_type : Optional [str ] =  None ,
426+     ) ->  ModelType :
400427        """Parse a dict using given key extractor return a model. 
401428
402429        By default consider key 
@@ -409,8 +436,8 @@ def from_dict(cls, data, key_extractors=None, content_type=None):
409436        :raises: DeserializationError if something went wrong 
410437        """ 
411438        deserializer  =  Deserializer (cls ._infer_class_models ())
412-         deserializer .key_extractors  =  (
413-             [
439+         deserializer .key_extractors  =  (   # type: ignore 
440+             [   # type: ignore 
414441                attribute_key_case_insensitive_extractor ,
415442                rest_key_case_insensitive_extractor ,
416443                last_rest_key_case_insensitive_extractor ,
@@ -518,7 +545,7 @@ class Serializer(object):
518545        "multiple" : lambda  x , y : x  %  y  !=  0 ,
519546    }
520547
521-     def  __init__ (self , classes = None ):
548+     def  __init__ (self , classes :  Optional [ Mapping [ str ,  Type [ ModelType ]]]  =   None ):
522549        self .serialize_type  =  {
523550            "iso-8601" : Serializer .serialize_iso ,
524551            "rfc-1123" : Serializer .serialize_rfc ,
@@ -534,7 +561,7 @@ def __init__(self, classes=None):
534561            "[]" : self .serialize_iter ,
535562            "{}" : self .serialize_dict ,
536563        }
537-         self .dependencies  =  dict (classes ) if  classes  else  {}
564+         self .dependencies :  Dict [ str ,  Type [ ModelType ]]  =  dict (classes ) if  classes  else  {}
538565        self .key_transformer  =  full_restapi_key_transformer 
539566        self .client_side_validation  =  True 
540567
@@ -626,8 +653,7 @@ def _serialize(self, target_obj, data_type=None, **kwargs):
626653                            serialized .append (local_node )  # type: ignore 
627654                    else :  # JSON 
628655                        for  k  in  reversed (keys ):  # type: ignore 
629-                             unflattened  =  {k : new_attr }
630-                             new_attr  =  unflattened 
656+                             new_attr  =  {k : new_attr }
631657
632658                        _new_attr  =  new_attr 
633659                        _serialized  =  serialized 
@@ -656,8 +682,8 @@ def body(self, data, data_type, **kwargs):
656682        """ 
657683
658684        # Just in case this is a dict 
659-         internal_data_type  =  data_type .strip ("[]{}" )
660-         internal_data_type  =  self .dependencies .get (internal_data_type , None )
685+         internal_data_type_str  =  data_type .strip ("[]{}" )
686+         internal_data_type  =  self .dependencies .get (internal_data_type_str , None )
661687        try :
662688            is_xml_model_serialization  =  kwargs ["is_xml" ]
663689        except  KeyError :
@@ -777,6 +803,8 @@ def serialize_data(self, data, data_type, **kwargs):
777803            raise  ValueError ("No value for given attribute" )
778804
779805        try :
806+             if  data  is  AzureCoreNull :
807+                 return  None 
780808            if  data_type  in  self .basic_types .values ():
781809                return  self .serialize_basic (data , data_type , ** kwargs )
782810
@@ -1161,7 +1189,8 @@ def rest_key_extractor(attr, attr_desc, data):
11611189    working_data  =  data 
11621190
11631191    while  "."  in  key :
1164-         dict_keys  =  _FLATTEN .split (key )
1192+         # Need the cast, as for some reasons "split" is typed as list[str | Any] 
1193+         dict_keys  =  cast (List [str ], _FLATTEN .split (key ))
11651194        if  len (dict_keys ) ==  1 :
11661195            key  =  _decode_attribute_map_key (dict_keys [0 ])
11671196            break 
@@ -1332,7 +1361,7 @@ class Deserializer(object):
13321361
13331362    valid_date  =  re .compile (r"\d{4}[-]\d{2}[-]\d{2}T\d{2}:\d{2}:\d{2}"  r"\.?\d*Z?[-+]?[\d{2}]?:?[\d{2}]?" )
13341363
1335-     def  __init__ (self , classes = None ):
1364+     def  __init__ (self , classes :  Optional [ Mapping [ str ,  Type [ ModelType ]]]  =   None ):
13361365        self .deserialize_type  =  {
13371366            "iso-8601" : Deserializer .deserialize_iso ,
13381367            "rfc-1123" : Deserializer .deserialize_rfc ,
@@ -1352,7 +1381,7 @@ def __init__(self, classes=None):
13521381            "duration" : (isodate .Duration , datetime .timedelta ),
13531382            "iso-8601" : (datetime .datetime ),
13541383        }
1355-         self .dependencies  =  dict (classes ) if  classes  else  {}
1384+         self .dependencies :  Dict [ str ,  Type [ ModelType ]]  =  dict (classes ) if  classes  else  {}
13561385        self .key_extractors  =  [rest_key_extractor , xml_key_extractor ]
13571386        # Additional properties only works if the "rest_key_extractor" is used to 
13581387        # extract the keys. Making it to work whatever the key extractor is too much 
@@ -1471,7 +1500,7 @@ def _classify_target(self, target, data):
14711500        Once classification has been determined, initialize object. 
14721501
14731502        :param str target: The target object type to deserialize to. 
1474-         :param str/dict data: The response data to deseralize . 
1503+         :param str/dict data: The response data to deserialize . 
14751504        """ 
14761505        if  target  is  None :
14771506            return  None , None 
@@ -1486,7 +1515,7 @@ def _classify_target(self, target, data):
14861515            target  =  target ._classify (data , self .dependencies )
14871516        except  AttributeError :
14881517            pass   # Target is not a Model, no classify 
1489-         return  target , target .__class__ .__name__ 
1518+         return  target , target .__class__ .__name__    # type: ignore 
14901519
14911520    def  failsafe_deserialize (self , target_obj , data , content_type = None ):
14921521        """Ignores any errors encountered in deserialization, 
@@ -1496,7 +1525,7 @@ def failsafe_deserialize(self, target_obj, data, content_type=None):
14961525        a deserialization error. 
14971526
14981527        :param str target_obj: The target object type to deserialize to. 
1499-         :param str/dict data: The response data to deseralize . 
1528+         :param str/dict data: The response data to deserialize . 
15001529        :param str content_type: Swagger "produces" if available. 
15011530        """ 
15021531        try :
0 commit comments