diff --git a/invoke/tasks.py b/invoke/tasks.py index 8138d6f39..32496c46c 100644 --- a/invoke/tasks.py +++ b/invoke/tasks.py @@ -132,10 +132,19 @@ def argspec(self, body): # TODO: __call__ exhibits the 'self' arg; do we manually nix 1st result # in argspec, or is there a way to get the "really callable" spec? func = body if isinstance(body, types.FunctionType) else body.__call__ - spec = inspect.getargspec(func) - arg_names = spec.args[:] - matched_args = [reversed(x) for x in [spec.args, spec.defaults or []]] - spec_dict = dict(zip_longest(*matched_args, fillvalue=NO_DEFAULT)) + if six.PY3: + sig = inspect.signature(func) + arg_names = [k for k, v in sig.parameters.items()] + spec_dict = {} + for k, v in sig.parameters.items(): + value = v.default if not v.default == sig.empty else NO_DEFAULT + spec_dict.update({k: value}) + else: + spec = inspect.getargspec(func) + arg_names = spec.args[:] + matched_args = [ + reversed(x) for x in [spec.args, spec.defaults or []]] + spec_dict = dict(zip_longest(*matched_args, fillvalue=NO_DEFAULT)) # Pop context argument try: context_arg = arg_names.pop(0) diff --git a/tests/collection.py b/tests/collection.py index 2890c794b..f1ac7cc95 100644 --- a/tests/collection.py +++ b/tests/collection.py @@ -229,7 +229,7 @@ def prefers_task_name_attr_over_function_name(self): def raises_ValueError_if_no_name_found(self): # Can't use a lambda here as they are technically real functions. class Callable(object): - def __call__(self): + def __call__(self, ctx): pass self.c.add_task(Task(Callable()))