Skip to content

Commit 769506e

Browse files
committed
Merge pull request #3 from epsy/unbound
Fixed unbound methods getting their first parameter curried Ensures the the 'self' argument of methods on un-instantiated classes appear in the function signature on both Python2 and Python3. Also ensures self is identified correctly as a positional-only parameter.
2 parents 59ab8ac + 50d63cb commit 769506e

File tree

2 files changed

+31
-3
lines changed

2 files changed

+31
-3
lines changed

funcsigs/__init__.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,20 @@ def signature(obj):
5959
raise TypeError('{0!r} is not a callable object'.format(obj))
6060

6161
if isinstance(obj, types.MethodType):
62-
# In this case we skip the first parameter of the underlying
63-
# function (usually `self` or `cls`).
6462
sig = signature(obj.__func__)
65-
return sig.replace(parameters=tuple(sig.parameters.values())[1:])
63+
if obj.__self__ is None:
64+
# Unbound method: the first parameter becomes positional-only
65+
if sig.parameters:
66+
first = sig.parameters.values()[0].replace(
67+
kind=_POSITIONAL_ONLY)
68+
return sig.replace(
69+
parameters=(first,) + tuple(sig.parameters.values())[1:])
70+
else:
71+
return sig
72+
else:
73+
# In this case we skip the first parameter of the underlying
74+
# function (usually `self` or `cls`).
75+
return sig.replace(parameters=tuple(sig.parameters.values())[1:])
6676

6777
try:
6878
sig = obj.__signature__

tests/test_funcsigs.py

+18
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import unittest
77

88
import doctest
9+
import sys
910

1011
import funcsigs as inspect
1112

@@ -70,6 +71,23 @@ def test_has_version(self):
7071
def test_readme(self):
7172
doctest.testfile('../README.rst')
7273

74+
def test_unbound_method(self):
75+
if sys.version_info < (3,):
76+
self_kind = "positional_only"
77+
else:
78+
self_kind = "positional_or_keyword"
79+
class Test(object):
80+
def method(self):
81+
pass
82+
def method_with_args(self, a):
83+
pass
84+
self.assertEqual(self.signature(Test.method),
85+
(((('self', Ellipsis, Ellipsis, self_kind)),), Ellipsis))
86+
self.assertEqual(self.signature(Test.method_with_args), ((
87+
('self', Ellipsis, Ellipsis, self_kind),
88+
('a', Ellipsis, Ellipsis, "positional_or_keyword"),
89+
), Ellipsis))
90+
7391

7492
if __name__ == "__main__":
7593
unittest.begin()

0 commit comments

Comments
 (0)