@@ -1109,64 +1109,95 @@ def convert(
11091109 )
11101110
11111111
1112- def convert_type (ty : t .Any | None , default : t .Any | None = None ) -> ParamType :
1112+ def _guess_type (
1113+ ty : type [t .Any ] | ParamType | None ,
1114+ default : t .Any | None ,
1115+ ) -> type [t .Any ] | tuple [type [t .Any ], ...] | ParamType | None :
1116+ """Infer a type from *ty* or *default*.
1117+
1118+ Returns *ty* unchanged when it is not ``None``. Otherwise inspects
1119+ *default* to produce a ``type``, a ``tuple`` of types (for tuple
1120+ defaults), or ``None``.
1121+ """
1122+ if ty is not None :
1123+ return ty
1124+
1125+ if default is None :
1126+ return None
1127+
1128+ if not isinstance (default , (tuple , list )):
1129+ return type (default )
1130+
1131+ # If the default is empty, return None so convert_type falls
1132+ # through to STRING.
1133+ if not default :
1134+ return None
1135+
1136+ item = default [0 ]
1137+
1138+ # A sequence of iterables needs to detect the inner types.
1139+ # Can't call convert_type recursively because that would
1140+ # incorrectly unwind the tuple to a single type.
1141+ if isinstance (item , (tuple , list )):
1142+ return tuple (map (type , item ))
1143+
1144+ return type (item )
1145+
1146+
1147+ @t .overload
1148+ def convert_type (ty : None , default : None = None ) -> StringParamType : ...
1149+
1150+
1151+ @t .overload
1152+ def convert_type (
1153+ ty : type [t .Any ] | ParamType , default : t .Any | None = None
1154+ ) -> ParamType : ...
1155+
1156+
1157+ @t .overload
1158+ def convert_type (ty : t .Any | None , default : t .Any | None = None ) -> ParamType : ...
1159+
1160+
1161+ def convert_type (ty : t .Any | None = None , default : t .Any | None = None ) -> ParamType :
11131162 """Find the most appropriate :class:`ParamType` for the given Python
11141163 type. If the type isn't provided, it can be inferred from a default
11151164 value.
11161165 """
1117- guessed_type = False
1118-
1119- if ty is None and default is not None :
1120- if isinstance (default , (tuple , list )):
1121- # If the default is empty, ty will remain None and will
1122- # return STRING.
1123- if default :
1124- item = default [0 ]
1125-
1126- # A tuple of tuples needs to detect the inner types.
1127- # Can't call convert recursively because that would
1128- # incorrectly unwind the tuple to a single type.
1129- if isinstance (item , (tuple , list )):
1130- ty = tuple (map (type , item ))
1131- else :
1132- ty = type (item )
1133- else :
1134- ty = type (default )
1166+ guessed = _guess_type (ty , default )
1167+ is_guessed = guessed is not ty
11351168
1136- guessed_type = True
1169+ if isinstance (guessed , tuple ):
1170+ return Tuple (guessed )
11371171
1138- if isinstance (ty , tuple ):
1139- return Tuple (ty )
1140-
1141- if isinstance (ty , ParamType ):
1142- return ty
1172+ if isinstance (guessed , ParamType ):
1173+ return guessed
11431174
1144- if ty is str or ty is None :
1175+ if guessed is str or guessed is None :
11451176 return STRING
11461177
1147- if ty is int :
1178+ if guessed is int :
11481179 return INT
11491180
1150- if ty is float :
1181+ if guessed is float :
11511182 return FLOAT
11521183
1153- if ty is bool :
1184+ if guessed is bool :
11541185 return BOOL
11551186
1156- if guessed_type :
1187+ if is_guessed :
11571188 return STRING
11581189
11591190 if __debug__ :
11601191 try :
1161- if issubclass (ty , ParamType ):
1192+ if issubclass (guessed , ParamType ):
11621193 raise AssertionError (
1163- f"Attempted to use an uninstantiated parameter type ({ ty } )."
1194+ f"Attempted to use an uninstantiated parameter type ({ guessed } )."
11641195 )
11651196 except TypeError :
1166- # ty is an instance (correct), so issubclass fails.
1197+ # guessed is an instance (correct), so issubclass fails.
11671198 pass
11681199
1169- return FuncParamType (ty )
1200+ return FuncParamType (guessed )
11701201
11711202
11721203#: A dummy parameter type that just does nothing. From a user's
0 commit comments