Skip to content

Commit 202ae40

Browse files
committed
Use inspect.signature with Py3 argument parsing.
inspect.getfullargspec doesn't support positional-only arguments (robotframework#3695). This commit doesn't yet enable that support.
1 parent ced27fc commit 202ae40

File tree

1 file changed

+42
-31
lines changed

1 file changed

+42
-31
lines changed

src/robot/running/arguments/py3argumentparser.py

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515

16-
from inspect import getfullargspec, ismethod, unwrap
16+
import inspect
1717
import typing
1818

1919
from robot.utils import PY_VERSION
@@ -27,53 +27,64 @@ def __init__(self, type='Keyword'):
2727
self._type = type
2828

2929
def parse(self, handler, name=None):
30-
args, varargs, kws, defaults, kwo, kwo_defaults, annotations \
31-
= self._get_arg_spec(handler)
32-
if ismethod(handler) or handler.__name__ == '__init__':
33-
args = args[1:] # Drop 'self'.
30+
positional, varargs, kwonly, kwargs, defaults = self._get_arg_spec(handler)
3431
spec = ArgumentSpec(
3532
name,
3633
self._type,
37-
positional=args,
34+
positional=positional,
3835
varargs=varargs,
39-
kwargs=kws,
40-
kwonlyargs=kwo,
41-
defaults=self._get_defaults(args, defaults, kwo_defaults)
36+
kwonlyargs=kwonly,
37+
kwargs=kwargs,
38+
defaults=defaults
4239
)
43-
spec.types = self._get_types(handler, annotations, spec)
40+
spec.types = self._get_types(handler, spec)
4441
return spec
4542

4643
def _get_arg_spec(self, handler):
47-
handler = unwrap(handler)
4844
try:
49-
if handler.__name__ == 'po':
50-
print(getfullargspec(handler))
51-
return getfullargspec(handler)
52-
except TypeError: # Can occur w/ C functions (incl. many builtins).
53-
return [], 'args', None, None, [], None, {}
45+
signature = inspect.signature(handler)
46+
except ValueError: # Can occur w/ C functions (incl. many builtins).
47+
return [], 'args', [], None, {}
48+
parameters = list(signature.parameters.values())
49+
# `inspect.signature` drops `self` with bound methods and that's the case when
50+
# inspecting keywords. `__init__` is got directly from class (i.e. isn't bound)
51+
# so we need to handle that case ourselves.
52+
if handler.__name__ == '__init__':
53+
parameters = parameters[1:]
54+
return self._parse_params(parameters)
5455

55-
def _get_defaults(self, args, default_values, kwo_defaults):
56-
if default_values:
57-
defaults = dict(zip(args[-len(default_values):], default_values))
58-
else:
59-
defaults = {}
60-
if kwo_defaults:
61-
defaults.update(kwo_defaults)
62-
return defaults
56+
def _parse_params(self, parameters):
57+
positional = []
58+
varargs = None
59+
kwonly = []
60+
kwargs = None
61+
defaults = {}
62+
for param in parameters:
63+
if param.kind in (param.POSITIONAL_ONLY, param.POSITIONAL_OR_KEYWORD):
64+
positional.append(param.name)
65+
elif param.kind == param.VAR_POSITIONAL:
66+
varargs = param.name
67+
elif param.kind == param.KEYWORD_ONLY:
68+
kwonly.append(param.name)
69+
elif param.kind == param.VAR_KEYWORD:
70+
kwargs = param.name
71+
if param.default is not param.empty:
72+
defaults[param.name] = param.default
73+
return positional, varargs, kwonly, kwargs, defaults
6374

64-
def _get_types(self, handler, annotations, spec):
75+
def _get_types(self, handler, spec):
6576
types = getattr(handler, 'robot_types', ())
66-
if types is None:
67-
return None
68-
if types:
77+
# If types are set using the `@keyword` decorator, use them. Including when
78+
# types are explicitly disabled with `@keyword(types=None)`.
79+
if types or types is None:
6980
return types
70-
return self._get_type_hints(handler, annotations, spec)
81+
return self._get_type_hints(handler, spec)
7182

72-
def _get_type_hints(self, handler, annotations, spec):
83+
def _get_type_hints(self, handler, spec):
7384
try:
7485
type_hints = typing.get_type_hints(handler)
7586
except Exception: # Can raise pretty much anything
76-
return annotations
87+
return handler.__annotations__
7788
self._remove_mismatching_type_hints(type_hints, spec.argument_names)
7889
self._remove_optional_none_type_hints(type_hints, spec.defaults)
7990
return type_hints

0 commit comments

Comments
 (0)