2323import os
2424import sys
2525
26+ from robot .utils import PY_VERSION
27+
2628try :
2729 import typing
2830except ImportError :
@@ -245,9 +247,7 @@ def _get_types(cls, function):
245247 types = getattr (function , 'robot_types' , ())
246248 if types is None or types :
247249 return types
248- if not types :
249- types = cls ._get_typing_hints (function )
250- return types
250+ return cls ._get_typing_hints (function )
251251
252252 @classmethod
253253 def _get_typing_hints (cls , function ):
@@ -257,16 +257,17 @@ def _get_typing_hints(cls, function):
257257 hints = typing .get_type_hints (function )
258258 except Exception :
259259 hints = function .__annotations__
260- all_args = cls ._args_as_list (function )
260+ arg_spec = cls ._get_arg_spec (function )
261+ all_args = cls ._args_as_list (function , arg_spec )
261262 for arg_with_hint in list (hints ):
262263 # remove return and self statements
263264 if arg_with_hint not in all_args :
264265 hints .pop (arg_with_hint )
265- return hints
266+ default = cls ._get_defaults (arg_spec )
267+ return cls ._remove_optional_none_type_hints (hints , default )
266268
267269 @classmethod
268- def _args_as_list (cls , function ):
269- arg_spec = cls ._get_arg_spec (function )
270+ def _args_as_list (cls , function , arg_spec ):
270271 function_args = []
271272 function_args .extend (cls ._drop_self_from_args (function , arg_spec ))
272273 if arg_spec .varargs :
@@ -276,6 +277,34 @@ def _args_as_list(cls, function):
276277 function_args .append (arg_spec .varkw )
277278 return function_args
278279
280+ # Copied from: robot.running.arguments.argumentparser
281+ @classmethod
282+ def _remove_optional_none_type_hints (cls , type_hints , defaults ):
283+ # If argument has None as a default, typing.get_type_hints adds
284+ # optional None to the information it returns. We don't want that.
285+ for arg , default in defaults :
286+ if default is None and arg in type_hints :
287+ type_ = type_hints [arg ]
288+ if cls ._is_union (type_ ):
289+ types = type_ .__args__
290+ if len (types ) == 2 and types [1 ] is type (None ): # noqa
291+ type_hints [arg ] = types [0 ]
292+ return type_hints
293+
294+ # Copied from: robot.running.arguments.argumentparser
295+ @classmethod
296+ def _is_union (cls , typing_type ):
297+ if PY_VERSION >= (3 , 7 ) and hasattr (typing_type , '__origin__' ):
298+ typing_type = typing_type .__origin__
299+ return isinstance (typing_type , type (typing .Union ))
300+
301+ @classmethod
302+ def _get_defaults (cls , arg_spec ):
303+ if not arg_spec .defaults :
304+ return {}
305+ names = arg_spec .args [- len (arg_spec .defaults ):]
306+ return zip (names , arg_spec .defaults )
307+
279308
280309class KeywordSpecification (object ):
281310
0 commit comments