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.
diff --git a/funcsigs/__init__.py b/funcsigs/__init__.py
index b9ba326..fd2f47b 100644
--- a/funcsigs/__init__.py
+++ b/funcsigs/__init__.py
@@ -59,10 +59,20 @@
         raise TypeError('{0!r} is not a callable object'.format(obj))
 
     if isinstance(obj, types.MethodType):
-        # In this case we skip the first parameter of the underlying
-        # function (usually `self` or `cls`).
         sig = signature(obj.__func__)
-        return sig.replace(parameters=tuple(sig.parameters.values())[1:])
+        if obj.__self__ is None:
+            # Unbound method: the first parameter becomes positional-only
+            if sig.parameters:
+                first = sig.parameters.values()[0].replace(
+                    kind=_POSITIONAL_ONLY)
+                return sig.replace(
+                    parameters=(first,) + tuple(sig.parameters.values())[1:])
+            else:
+                return sig
+        else:
+            # In this case we skip the first parameter of the underlying
+            # function (usually `self` or `cls`).
+            return sig.replace(parameters=tuple(sig.parameters.values())[1:])
 
     try:
         sig = obj.__signature__
diff --git a/tests/test_funcsigs.py b/tests/test_funcsigs.py
index c904caf..eecc0a8 100644
--- a/tests/test_funcsigs.py
+++ b/tests/test_funcsigs.py
@@ -6,6 +6,7 @@
     import unittest
 
 import doctest
+import sys
 
 import funcsigs as inspect
 
@@ -70,6 +71,23 @@
     def test_readme(self):
         doctest.testfile('../README.rst')
 
+    def test_unbound_method(self):
+        if sys.version_info < (3,):
+            self_kind = "positional_only"
+        else:
+            self_kind = "positional_or_keyword"
+        class Test(object):
+            def method(self):
+                pass
+            def method_with_args(self, a):
+                pass
+        self.assertEqual(self.signature(Test.method),
+                (((('self', Ellipsis, Ellipsis, self_kind)),), Ellipsis))
+        self.assertEqual(self.signature(Test.method_with_args), ((
+                ('self', Ellipsis, Ellipsis, self_kind),
+                ('a', Ellipsis, Ellipsis, "positional_or_keyword"),
+                ), Ellipsis))
+
 
 if __name__ == "__main__":
     unittest.begin()