24
24
import re
25
25
import datetime as dt
26
26
import collections
27
+ import numbers
28
+ import typing
27
29
28
30
from .parameterized import (
29
31
Parameterized , Parameter , String , ParameterizedFunction , ParamOverrides ,
@@ -692,7 +694,6 @@ def _force(self,obj,objtype=None):
692
694
return gen
693
695
694
696
695
- import numbers
696
697
def _is_number (obj ):
697
698
if isinstance (obj , numbers .Number ): return True
698
699
# The extra check is for classes that behave like numbers, such as those
@@ -752,6 +753,10 @@ def __init__(self, default=b"", regex=None, allow_None=False, **kwargs):
752
753
self .allow_None = (default is None or allow_None )
753
754
self ._validate (default )
754
755
756
+ @property
757
+ def pytype (self ):
758
+ return typing .Union [bytes , None ] if self .allow_None else bytes
759
+
755
760
def _validate_regex (self , val , regex ):
756
761
if (val is None and self .allow_None ):
757
762
return
@@ -834,6 +839,10 @@ def __init__(self, default=0.0, bounds=None, softbounds=None,
834
839
self .step = step
835
840
self ._validate (default )
836
841
842
+ @property
843
+ def pytype (self ):
844
+ return typing .Union [numbers .Number , None ] if self .allow_None else numbers .Number
845
+
837
846
def __get__ (self , obj , objtype ):
838
847
"""
839
848
Same as the superclass's __get__, but if the value was
@@ -963,6 +972,10 @@ class Integer(Number):
963
972
def __init__ (self , default = 0 , ** params ):
964
973
Number .__init__ (self , default = default , ** params )
965
974
975
+ @property
976
+ def pytype (self ):
977
+ return typing .Union [int , None ] if self .allow_None else int
978
+
966
979
def _validate_value (self , val , allow_None ):
967
980
if callable (val ):
968
981
return
@@ -1000,6 +1013,10 @@ def __init__(self, default=False, bounds=(0,1), **params):
1000
1013
self .bounds = bounds
1001
1014
super (Boolean , self ).__init__ (default = default , ** params )
1002
1015
1016
+ @property
1017
+ def pytype (self ):
1018
+ return typing .Union [bool , None ] if self .allow_None else bool
1019
+
1003
1020
def _validate_value (self , val , allow_None ):
1004
1021
if allow_None :
1005
1022
if not isinstance (val , bool ) and val is not None :
@@ -1034,6 +1051,14 @@ def __init__(self, default=(0,0), length=None, **params):
1034
1051
self .length = length
1035
1052
self ._validate (default )
1036
1053
1054
+ @property
1055
+ def pytype (self ):
1056
+ if self .length :
1057
+ pytype = typing .Tuple [(typing .Any ,)* self .length ]
1058
+ else :
1059
+ ptype = typing .Tuple [typing .Any , ...]
1060
+ return typing .Union [pytype , None ] if self .allow_None else pytype
1061
+
1037
1062
def _validate_value (self , val , allow_None ):
1038
1063
if val is None and allow_None :
1039
1064
return
@@ -1071,6 +1096,14 @@ def deserialize(cls, value):
1071
1096
class NumericTuple (Tuple ):
1072
1097
"""A numeric tuple Parameter (e.g. (4.5,7.6,3)) with a fixed tuple length."""
1073
1098
1099
+ @property
1100
+ def pytype (self ):
1101
+ if self .length :
1102
+ pytype = typing .Tuple [(numbers .Number ,)* self .length ]
1103
+ else :
1104
+ ptype = typing .Tuple [numbers .Number , ...]
1105
+ return typing .Union [pytype , None ] if self .allow_None else pytype
1106
+
1074
1107
def _validate_value (self , val , allow_None ):
1075
1108
super (NumericTuple , self )._validate_value (val , allow_None )
1076
1109
if allow_None and val is None :
@@ -1088,6 +1121,11 @@ class XYCoordinates(NumericTuple):
1088
1121
def __init__ (self , default = (0.0 , 0.0 ), ** params ):
1089
1122
super (XYCoordinates ,self ).__init__ (default = default , length = 2 , ** params )
1090
1123
1124
+ @property
1125
+ def pytype (self ):
1126
+ pytype = typing .Tuple [numbers .Number , numbers .Number ]
1127
+ return typing .Union [pytype , None ] if self .allow_None else pytype
1128
+
1091
1129
1092
1130
class Callable (Parameter ):
1093
1131
"""
@@ -1099,6 +1137,11 @@ class Callable(Parameter):
1099
1137
2.4, so instantiate must be False for those values.
1100
1138
"""
1101
1139
1140
+ @proprty
1141
+ def pytype (self ):
1142
+ ctype = typing .Callable [..., typing .Any ]
1143
+ return typing .Union [ctype , None ] if self .allow_None else ctype
1144
+
1102
1145
def _validate_value (self , val , allow_None ):
1103
1146
if (allow_None and val is None ) or callable (val ):
1104
1147
return
@@ -1197,6 +1240,11 @@ class SelectorBase(Parameter):
1197
1240
1198
1241
__abstract = True
1199
1242
1243
+ @proprty
1244
+ def pytype (self ):
1245
+ literal = typing .Literal [tuple (self .get_range ().values ())]
1246
+ return typing .Union [literal , None ] if self .allow_None else literal
1247
+
1200
1248
def get_range (self ):
1201
1249
raise NotImplementedError ("get_range() must be implemented in subclasses." )
1202
1250
@@ -1433,6 +1481,17 @@ def __init__(self, default=[], class_=None, item_type=None,
1433
1481
** params )
1434
1482
self ._validate (default )
1435
1483
1484
+ @property
1485
+ def pytype (self ):
1486
+ if isinstance (self .item_type , tuple ):
1487
+ item_type = typing .Union [self .item_type ]
1488
+ elif self .item_type is not None :
1489
+ item_type = self .item_type
1490
+ else :
1491
+ item_type = typing .Any
1492
+ list_type = typing .List [item_type ]
1493
+ return typing .Union [list_type , None ] if self .allow_None else list_type
1494
+
1436
1495
def _validate (self , val ):
1437
1496
"""
1438
1497
Checks that the value is numeric and that it is within the hard
@@ -1487,6 +1546,11 @@ class HookList(List):
1487
1546
"""
1488
1547
__slots__ = ['class_' , 'bounds' ]
1489
1548
1549
+ @property
1550
+ def pytype (self ):
1551
+ list_type = typing .List [typing .Callable [[], None ]]
1552
+ return typing .Union [list_type , None ] if self .allow_None else list_type
1553
+
1490
1554
def _validate_value (self , val , allow_None ):
1491
1555
super (HookList , self )._validate_value (val , allow_None )
1492
1556
if allow_None and val is None :
@@ -1506,16 +1570,27 @@ class Dict(ClassSelector):
1506
1570
def __init__ (self , default = None , ** params ):
1507
1571
super (Dict , self ).__init__ (dict , default = default , ** params )
1508
1572
1573
+ @property
1574
+ def pytype (self ):
1575
+ dict_type = typing .Dict [typing .Hashable , typing .Any ]
1576
+ return typing .Union [dict_type , None ] if self .allow_None else dict_type
1577
+
1578
+
1509
1579
1510
1580
class Array (ClassSelector ):
1511
1581
"""
1512
1582
Parameter whose value is a numpy array.
1513
1583
"""
1514
1584
1515
1585
def __init__ (self , default = None , ** params ):
1516
- from numpy import ndarray
1586
+
1517
1587
super (Array , self ).__init__ (ndarray , allow_None = True , default = default , ** params )
1518
1588
1589
+ @property
1590
+ def pytype (self ):
1591
+ from numpy import ndarray
1592
+ return ndarray
1593
+
1519
1594
@classmethod
1520
1595
def serialize (cls , value ):
1521
1596
if value is None :
@@ -1559,6 +1634,11 @@ def __init__(self, default=None, rows=None, columns=None, ordered=None, **params
1559
1634
super (DataFrame ,self ).__init__ (pdDFrame , default = default , ** params )
1560
1635
self ._validate (self .default )
1561
1636
1637
+ @property
1638
+ def pytype (self ):
1639
+ from pandas import DataFrame
1640
+ return DataFrame
1641
+
1562
1642
def _length_bounds_check (self , bounds , length , name ):
1563
1643
message = '{name} length {length} does not match declared bounds of {bounds}'
1564
1644
if not isinstance (bounds , tuple ):
@@ -1635,6 +1715,11 @@ def __init__(self, default=None, rows=None, allow_None=False, **params):
1635
1715
** params )
1636
1716
self ._validate (self .default )
1637
1717
1718
+ @property
1719
+ def pytype (self ):
1720
+ from pandas import Series
1721
+ return Series
1722
+
1638
1723
def _length_bounds_check (self , bounds , length , name ):
1639
1724
message = '{name} length {length} does not match declared bounds of {bounds}'
1640
1725
if not isinstance (bounds , tuple ):
@@ -1778,6 +1863,13 @@ def __init__(self, default=None, search_paths=None, **params):
1778
1863
self .search_paths = search_paths
1779
1864
super (Path ,self ).__init__ (default ,** params )
1780
1865
1866
+ @property
1867
+ def pytype (self ):
1868
+ path_types = (str , pathlib .Path )
1869
+ if self .allow_None :
1870
+ path_types += (None ,)
1871
+ return typing .Union [path_types ]
1872
+
1781
1873
def _resolve (self , path ):
1782
1874
return resolve_path (path , path_to_file = None , search_paths = self .search_paths )
1783
1875
@@ -1904,6 +1996,12 @@ def __init__(self, default=None, objects=None, **kwargs):
1904
1996
super (ListSelector ,self ).__init__ (
1905
1997
objects = objects , default = default , empty_default = True , ** kwargs )
1906
1998
1999
+ @property
2000
+ def pytype (self ):
2001
+ literal = typing .Literal [tuple (self .get_range ().values ())]
2002
+ ltype = typing .List [literal ]
2003
+ return typing .Union [ltype , None ] if self .allow_None else ltype
2004
+
1907
2005
def compute_default (self ):
1908
2006
if self .default is None and callable (self .compute_default_fn ):
1909
2007
self .default = self .compute_default_fn ()
@@ -1954,6 +2052,14 @@ class Date(Number):
1954
2052
def __init__ (self , default = None , ** kwargs ):
1955
2053
super (Date , self ).__init__ (default = default , ** kwargs )
1956
2054
2055
+ @property
2056
+ def pytype (self ):
2057
+ if self .allow_None :
2058
+ date_types = dt_types + (None ,)
2059
+ else :
2060
+ date_types = dt_types
2061
+ return typing .Union [date_types ]
2062
+
1957
2063
def _validate_value (self , val , allow_None ):
1958
2064
"""
1959
2065
Checks that the value is numeric and that it is within the hard
@@ -1998,6 +2104,10 @@ class CalendarDate(Number):
1998
2104
def __init__ (self , default = None , ** kwargs ):
1999
2105
super (CalendarDate , self ).__init__ (default = default , ** kwargs )
2000
2106
2107
+ @property
2108
+ def pytype (self ):
2109
+ return typing .Union [dt .datetime , None ] if self .allow_None else dt .datetime
2110
+
2001
2111
def _validate_value (self , val , allow_None ):
2002
2112
"""
2003
2113
Checks that the value is numeric and that it is within the hard
@@ -2076,6 +2186,10 @@ def __init__(self, default=None, allow_named=True, **kwargs):
2076
2186
self .allow_named = allow_named
2077
2187
self ._validate (default )
2078
2188
2189
+ @property
2190
+ def pytype (self ):
2191
+ return typing .Union [str , None ] if self .allow_None else str
2192
+
2079
2193
def _validate (self , val ):
2080
2194
self ._validate_value (val , self .allow_None )
2081
2195
self ._validate_allow_named (val , self .allow_named )
@@ -2151,6 +2265,12 @@ class DateRange(Range):
2151
2265
Bounds must be specified as datetime or date types (see param.dt_types).
2152
2266
"""
2153
2267
2268
+ @property
2269
+ def pytype (self ):
2270
+ date_type = typing .Union [dt_types ]
2271
+ range_type = typing .Tuple [date_type , date_type ]
2272
+ return typing .Union [range_type , None ] if self .allow_None else range_type
2273
+
2154
2274
def _validate_value (self , val , allow_None ):
2155
2275
# Cannot use super()._validate_value as DateRange inherits from
2156
2276
# NumericTuple which check that the tuple values are numbers and
@@ -2205,6 +2325,7 @@ def deserialize(cls, value):
2205
2325
# As JSON has no tuple representation
2206
2326
return tuple (deserialized )
2207
2327
2328
+
2208
2329
class CalendarDateRange (Range ):
2209
2330
"""
2210
2331
A date range specified as (start_date, end_date).
@@ -2281,6 +2402,10 @@ def __init__(self,default=False,bounds=(0,1),**params):
2281
2402
# back to False while triggered callbacks are executing
2282
2403
super (Event , self ).__init__ (default = default ,** params )
2283
2404
2405
+ @property
2406
+ def pytype (self ):
2407
+ return bool
2408
+
2284
2409
def _reset_event (self , obj , val ):
2285
2410
val = False
2286
2411
if obj is None :
0 commit comments