@@ -840,7 +840,7 @@ def decorated(*args, **kwargs):
840
840
841
841
class ValueMapper (abc .ABC , Generic [T ]):
842
842
@abc .abstractmethod
843
- def map (self , value : Any ) -> T :
843
+ def map (self , value : Any ) -> Optional [ T ] :
844
844
pass
845
845
846
846
@@ -850,12 +850,16 @@ def map(self, value) -> Optional[Any]:
850
850
851
851
852
852
class DecimalValueMapper (ValueMapper [Decimal ]):
853
- def map (self , value ) -> Decimal :
853
+ def map (self , value ) -> Optional [Decimal ]:
854
+ if value is None :
855
+ return None
854
856
return Decimal (value )
855
857
856
858
857
859
class DoubleValueMapper (ValueMapper [float ]):
858
- def map (self , value ) -> float :
860
+ def map (self , value ) -> Optional [float ]:
861
+ if value is None :
862
+ return None
859
863
if value == 'Infinity' :
860
864
return float ("inf" )
861
865
if value == '-Infinity' :
@@ -886,14 +890,18 @@ def __init__(self, column):
886
890
self .pattern = pattern
887
891
self .time_size = 9 + ms_size - ms_to_trim
888
892
889
- def map (self , value ) -> time :
893
+ def map (self , value ) -> Optional [time ]:
894
+ if value is None :
895
+ return None
890
896
return datetime .strptime (value [:self .time_size ], self .pattern ).time ()
891
897
892
898
893
899
class TimeWithTimeZoneValueMapper (TimeValueMapper ):
894
900
PATTERN = r'^(.*)([\+\-])(\d{2}):(\d{2})$'
895
901
896
- def map (self , value ) -> time :
902
+ def map (self , value ) -> Optional [time ]:
903
+ if value is None :
904
+ return None
897
905
matches = re .match (TimeWithTimeZoneValueMapper .PATTERN , value )
898
906
assert matches is not None
899
907
assert len (matches .groups ()) == 4
@@ -905,7 +913,9 @@ def map(self, value) -> time:
905
913
906
914
907
915
class DateValueMapper (ValueMapper [date ]):
908
- def map (self , value ) -> date :
916
+ def map (self , value ) -> Optional [date ]:
917
+ if value is None :
918
+ return None
909
919
return datetime .strptime (value , '%Y-%m-%d' ).date ()
910
920
911
921
@@ -920,41 +930,51 @@ def __init__(self, column):
920
930
self .dt_size = datetime_default_size + ms_size - ms_to_trim
921
931
self .dt_tz_offset = datetime_default_size + ms_size
922
932
923
- def map (self , value ) -> datetime :
933
+ def map (self , value ) -> Optional [datetime ]:
934
+ if value is None :
935
+ return None
924
936
return datetime .strptime (value [:self .dt_size ] + value [self .dt_tz_offset :], self .pattern )
925
937
926
938
927
939
class TimestampWithTimeZoneValueMapper (TimestampValueMapper ):
928
- def map (self , value ) -> datetime :
940
+ def map (self , value ) -> Optional [datetime ]:
941
+ if value is None :
942
+ return None
929
943
dt , tz = value .rsplit (' ' , 1 )
930
944
if tz .startswith ('+' ) or tz .startswith ('-' ):
931
945
return datetime .strptime (value [:self .dt_size ] + value [self .dt_tz_offset :], self .pattern + ' %z' )
932
946
date_str = dt [:self .dt_size ] + dt [self .dt_tz_offset :]
933
947
return datetime .strptime (date_str , self .pattern ).replace (tzinfo = pytz .timezone (tz ))
934
948
935
949
936
- class ArrayValueMapper (ValueMapper [List [Any ]]):
950
+ class ArrayValueMapper (ValueMapper [List [Optional [ Any ] ]]):
937
951
def __init__ (self , mapper : ValueMapper [Any ]):
938
952
self .mapper = mapper
939
953
940
- def map (self , values : List [Any ]) -> List [Any ]:
954
+ def map (self , values : List [Any ]) -> Optional [List [Any ]]:
955
+ if values is None :
956
+ return None
941
957
return [self .mapper .map (value ) for value in values ]
942
958
943
959
944
960
class RowValueMapper (ValueMapper [Tuple [Optional [Any ], ...]]):
945
961
def __init__ (self , mappers : List [ValueMapper [Any ]]):
946
962
self .mappers = mappers
947
963
948
- def map (self , values : List [Any ]) -> Tuple [Any , ...]:
964
+ def map (self , values : List [Any ]) -> Optional [Tuple [Optional [Any ], ...]]:
965
+ if values is None :
966
+ return None
949
967
return tuple (self .mappers [index ].map (value ) for index , value in enumerate (values ))
950
968
951
969
952
- class MapValueMapper (ValueMapper [Dict [Any , Any ]]):
970
+ class MapValueMapper (ValueMapper [Dict [Any , Optional [ Any ] ]]):
953
971
def __init__ (self , key_mapper : ValueMapper [Any ], value_mapper : ValueMapper [Any ]):
954
972
self .key_mapper = key_mapper
955
973
self .value_mapper = value_mapper
956
974
957
- def map (self , values : Any ) -> Dict [Any , Any ]:
975
+ def map (self , values : Any ) -> Optional [Dict [Any , Optional [Any ]]]:
976
+ if values is None :
977
+ return None
958
978
return {
959
979
self .key_mapper .map (key ): self .value_mapper .map (value ) for key , value in values .items ()
960
980
}
@@ -1032,9 +1052,6 @@ def _map_row(self, row):
1032
1052
return [self ._map_value (value , self .columns [index ]) for index , value in enumerate (row )]
1033
1053
1034
1054
def _map_value (self , value , value_mapper : ValueMapper [T ]) -> Optional [T ]:
1035
- if value is None :
1036
- return None
1037
-
1038
1055
try :
1039
1056
return value_mapper .map (value )
1040
1057
except ValueError as e :
0 commit comments