Browse Source

Use inspect.signature() if available

inspect.signature() was added to Python 3.3. inspect.getargspec() is
deprecated since Python 3.0 and doesn't support keyword-only
parameters.

Change-Id: I09dd8a38cc3166bc55917bc0813185457b43a971
Victor Stinner 2 years ago
parent
commit
4a85ff0ec4
1 changed files with 59 additions and 16 deletions
  1. 59
    16
      mox3/mox.py

+ 59
- 16
mox3/mox.py View File

@@ -905,15 +905,7 @@ class MethodSignatureChecker(object):
905 905
                         possible. Some methods and functions like built-ins
906 906
                         can't be inspected.
907 907
         """
908
-        try:
909
-            self._args, varargs, varkw, defaults = inspect.getargspec(method)
910
-        except TypeError:
911
-            raise ValueError('Could not get argument specification for %r'
912
-                             % (method,))
913
-        if (inspect.ismethod(method) or class_to_bind or (
914
-                hasattr(self, '_args') and len(self._args) > 0
915
-                and self._args[0] == 'self')):
916
-            self._args = self._args[1:]    # Skip 'self'.
908
+
917 909
         self._method = method
918 910
         self._instance = None    # May contain the instance this is bound to.
919 911
         self._instance = getattr(method, "__self__", None)
@@ -925,14 +917,65 @@ class MethodSignatureChecker(object):
925 917
             self._bounded_to = class_to_bind or getattr(method, "im_class",
926 918
                                                         None)
927 919
 
928
-        self._has_varargs = varargs is not None
929
-        self._has_varkw = varkw is not None
930
-        if defaults is None:
931
-            self._required_args = self._args
932
-            self._default_args = []
920
+        # inspect.getargspec() is deprecated since Python 3.0, prefer
921
+        # inspect.signature() (available since Python 3.3) which supports
922
+        # also Python 3 keyword-only arguments.
923
+        if hasattr(inspect, 'signature'):
924
+            try:
925
+                signature = inspect.signature(method)
926
+                params = list(signature.parameters.values())
927
+            except TypeError:
928
+                raise ValueError('Could not get signature for %r'
929
+                                 % (method,))
930
+
931
+            Parameter = inspect.Parameter
932
+            self._has_varargs = any(param.kind == Parameter.VAR_POSITIONAL
933
+                                    for param in params)
934
+            self._has_varkw = any(param.kind == Parameter.VAR_KEYWORD
935
+                                  for param in params)
936
+
937
+            if (inspect.ismethod(method) or class_to_bind
938
+               or (params and params[0].name == 'self')):
939
+                params = params[1:]
940
+
941
+            # Truncate params at the first *args or **kwargs parameter
942
+            for index, param in enumerate(params):
943
+                if param.kind in (Parameter.VAR_POSITIONAL,
944
+                                  Parameter.VAR_KEYWORD):
945
+                    del params[index:]
946
+                    break
947
+
948
+            required = 0
949
+            for param in params:
950
+                if param.default is not Parameter.empty:
951
+                    break
952
+                required += 1
953
+
954
+            self._args = [param.name for param in params]
955
+            self._required_args = self._args[:required]
956
+            self._default_args = self._args[required:]
933 957
         else:
934
-            self._required_args = self._args[:-len(defaults)]
935
-            self._default_args = self._args[-len(defaults):]
958
+            try:
959
+                argspec = inspect.getargspec(method)
960
+            except TypeError:
961
+                raise ValueError('Could not get argument specification for %r'
962
+                                 % (method,))
963
+
964
+            args = argspec.args
965
+            if (inspect.ismethod(method) or class_to_bind or (
966
+                    args and args[0] == 'self')):
967
+                args = args[1:]    # Skip 'self'.
968
+
969
+            self._has_varargs = (argspec.varargs is not None)
970
+            self._has_varkw = (argspec.keywords is not None)
971
+            self._args = args
972
+            if argspec.defaults:
973
+                pos = -len(argspec.defaults)
974
+                self._required_args = args[:pos]
975
+                self._default_args = args[pos:]
976
+            else:
977
+                self._required_args = args
978
+                self._default_args = []
936 979
 
937 980
     def _RecordArgumentGiven(self, arg_name, arg_status):
938 981
         """Mark an argument as being given.

Loading…
Cancel
Save