@@ -58,6 +58,11 @@ def field1(self, value):
58
58
except ImportError :
59
59
pass
60
60
61
+ try :
62
+ import pytimeparse
63
+ except ImportError as ex :
64
+ pass
65
+
61
66
from . import (
62
67
NONE , NOT_SET , ERROR , IGNORE , ctx , ContextMixin , Close , Source , SourceError , DefaultSource , Types ,
63
68
)
@@ -731,16 +736,12 @@ def _validate(self, value):
731
736
return True
732
737
733
738
734
- class Number ( Field ):
739
+ class RangeMixin ( object ):
735
740
736
- def __init__ (self , * args , ** kwargs ):
737
- range_value = kwargs .pop ('range' , None )
738
- if range_value is not None :
739
- self .min_value , self .max_value = range_value
740
- else :
741
- self .min_value = kwargs .pop ('min_value' , None )
742
- self .max_value = kwargs .pop ('max_value' , None )
743
- super (Number , self ).__init__ (* args , ** kwargs )
741
+
742
+ min_value = None
743
+
744
+ max_value = None
744
745
745
746
def min (self , value ):
746
747
self .min_value = value
@@ -753,9 +754,7 @@ def max(self, value):
753
754
def range (self , l , r ):
754
755
return self .min (l ).max (r )
755
756
756
- def _validate (self , value ):
757
- if not super (Number , self )._validate (value ):
758
- return False
757
+ def validate (self , value ):
759
758
if value is not None :
760
759
if self .min_value is not None and value < self .min_value :
761
760
self .ctx .errors .invalid ('"{0}" must be >= {1}' .format (
@@ -769,6 +768,22 @@ def _validate(self, value):
769
768
return False
770
769
return True
771
770
771
+ class Number (Field , RangeMixin ):
772
+
773
+ def __init__ (self , * args , ** kwargs ):
774
+ range_value = kwargs .pop ('range' , None )
775
+ if range_value is not None :
776
+ self .min_value , self .max_value = range_value
777
+ else :
778
+ self .min_value = kwargs .pop ('min_value' , None )
779
+ self .max_value = kwargs .pop ('max_value' , None )
780
+ super (Number , self ).__init__ (* args , ** kwargs )
781
+
782
+ def _validate (self , value ):
783
+ if not super (Number , self )._validate (value ):
784
+ return False
785
+ return RangeMixin .validate (self , value )
786
+
772
787
773
788
class Integer (Number ):
774
789
@@ -836,7 +851,7 @@ def _parse(self, path):
836
851
Bool = Boolean
837
852
838
853
839
- class RangeMixin (object ):
854
+ class TimeRangeMixin (object ):
840
855
841
856
def after (self , value ):
842
857
self .after_value = value
@@ -850,7 +865,7 @@ def between(self, l, r):
850
865
return self .after (l ).before (r )
851
866
852
867
853
- class Date (Field , RangeMixin ):
868
+ class Date (Field , TimeRangeMixin ):
854
869
855
870
def __init__ (self , * args , ** kwargs ):
856
871
self .after_value = kwargs .pop ('after' , None )
@@ -910,7 +925,7 @@ def _validate(self, value):
910
925
return True
911
926
912
927
913
- class Time (Field , RangeMixin ):
928
+ class Time (Field , TimeRangeMixin ):
914
929
915
930
def __init__ (self , * args , ** kwargs ):
916
931
self .after_value = kwargs .pop ('after' , None )
@@ -949,7 +964,7 @@ def _validate(self, value):
949
964
return True
950
965
951
966
952
- class Datetime (Field , RangeMixin ):
967
+ class Datetime (Field , TimeRangeMixin ):
953
968
954
969
def __init__ (self , * args , ** kwargs ):
955
970
self .after_value = kwargs .pop ('after' , None )
@@ -993,6 +1008,43 @@ def _validate(self, value):
993
1008
return True
994
1009
995
1010
1011
+ class TimeDelta (Field , RangeMixin ):
1012
+
1013
+ def __init__ (self , * args , ** kwargs ):
1014
+ range_value = kwargs .pop ('range' , None )
1015
+ if range_value is not None :
1016
+ self .min_value , self .max_value = range_value
1017
+ else :
1018
+ self .min_value = kwargs .pop ('min_value' , None )
1019
+ self .max_value = kwargs .pop ('max_value' , None )
1020
+ self ._format = kwargs .pop ('format' , 'human' )
1021
+ super (TimeDelta , self ).__init__ (* args , ** kwargs )
1022
+
1023
+ def format (self , value ):
1024
+ self ._format = value
1025
+ return self
1026
+
1027
+ def _parse (self , path ):
1028
+ if isinstance (path .value , datetime .datetime ):
1029
+ return path .value
1030
+ value = path .primitive (basestring )
1031
+ if self ._format == 'human' :
1032
+ parsed = pytimeparse .parse (value )
1033
+ if parsed is None :
1034
+ self .ctx .errors .invalid ('Not a time-delta expression' )
1035
+ return ERROR
1036
+ parsed = datetime .timedelta (seconds = parsed )
1037
+ else :
1038
+ self .ctx .errors .invalid ('No format for value "{0}"' .format (value ))
1039
+ return ERROR
1040
+ return parsed
1041
+
1042
+ def _validate (self , value ):
1043
+ if not super (TimeDelta , self )._validate (value ):
1044
+ return False
1045
+ return RangeMixin .validate (self , value )
1046
+
1047
+
996
1048
class Tuple (Field ):
997
1049
998
1050
def __init__ (self , * args , ** kwargs ):
0 commit comments