@@ -48,7 +48,7 @@ def validate_parameter_constraints(parameter_constraints, params, caller_name):
4848 - the string "boolean"
4949 - the string "verbose"
5050 - the string "cv_object"
51- - the string "missing_values"
51+ - a MissingValues object representing markers for missing values
5252 - a HasMethods object, representing method(s) an object must have
5353 - a Hidden object, representing a constraint not meant to be exposed to the user
5454
@@ -125,14 +125,14 @@ def make_constraint(constraint):
125125 return _NoneConstraint ()
126126 if isinstance (constraint , type ):
127127 return _InstancesOf (constraint )
128- if isinstance (constraint , (Interval , StrOptions , Options , HasMethods )):
128+ if isinstance (
129+ constraint , (Interval , StrOptions , Options , HasMethods , MissingValues )
130+ ):
129131 return constraint
130132 if isinstance (constraint , str ) and constraint == "boolean" :
131133 return _Booleans ()
132134 if isinstance (constraint , str ) and constraint == "verbose" :
133135 return _VerboseHelper ()
134- if isinstance (constraint , str ) and constraint == "missing_values" :
135- return _MissingValues ()
136136 if isinstance (constraint , str ) and constraint == "cv_object" :
137137 return _CVObjects ()
138138 if isinstance (constraint , Hidden ):
@@ -609,31 +609,40 @@ def __str__(self):
609609 )
610610
611611
612- class _MissingValues (_Constraint ):
612+ class MissingValues (_Constraint ):
613613 """Helper constraint for the `missing_values` parameters.
614614
615615 Convenience for
616616 [
617617 Integral,
618618 Interval(Real, None, None, closed="both"),
619- str,
620- None,
619+ str, # when numeric_only is False
620+ None, # when numeric_only is False
621621 _NanConstraint(),
622622 _PandasNAConstraint(),
623623 ]
624+
625+ Parameters
626+ ----------
627+ numeric_only : bool, default=False
628+ Whether to consider only numeric missing value markers.
629+
624630 """
625631
626- def __init__ (self ):
632+ def __init__ (self , numeric_only = False ):
627633 super ().__init__ ()
634+
635+ self .numeric_only = numeric_only
636+
628637 self ._constraints = [
629638 _InstancesOf (Integral ),
630639 # we use an interval of Real to ignore np.nan that has its own constraint
631640 Interval (Real , None , None , closed = "both" ),
632- _InstancesOf (str ),
633- _NoneConstraint (),
634641 _NanConstraint (),
635642 _PandasNAConstraint (),
636643 ]
644+ if not self .numeric_only :
645+ self ._constraints .extend ([_InstancesOf (str ), _NoneConstraint ()])
637646
638647 def is_satisfied_by (self , val ):
639648 return any (c .is_satisfied_by (val ) for c in self ._constraints )
@@ -752,7 +761,7 @@ def generate_invalid_param_val(constraint):
752761 if isinstance (constraint , StrOptions ):
753762 return f"not { ' or ' .join (constraint .options )} "
754763
755- if isinstance (constraint , _MissingValues ):
764+ if isinstance (constraint , MissingValues ):
756765 return np .array ([1 , 2 , 3 ])
757766
758767 if isinstance (constraint , _VerboseHelper ):
@@ -841,9 +850,12 @@ def generate_valid_param(constraint):
841850 if isinstance (constraint , _VerboseHelper ):
842851 return 1
843852
844- if isinstance (constraint , _MissingValues ) :
853+ if isinstance (constraint , MissingValues ) and constraint . numeric_only :
845854 return np .nan
846855
856+ if isinstance (constraint , MissingValues ) and not constraint .numeric_only :
857+ return "missing"
858+
847859 if isinstance (constraint , HasMethods ):
848860 return type (
849861 "ValidHasMethods" , (), {m : lambda self : None for m in constraint .methods }
0 commit comments