diff --git a/Lib/test/test_extcall.py b/Lib/test/test_extcall.py index 10e4d6c3931..7dddabca65c 100644 --- a/Lib/test/test_extcall.py +++ b/Lib/test/test_extcall.py @@ -144,3 +144,21 @@ for i in range(512): d[key] = i a, b = f2(1, *(2, 3), **d) print len(a), len(b), b == d + +class Foo: + def method(self, arg1, arg2): + return arg1 + arg2 + +x = Foo() +print Foo.method(*(x, 1, 2)) +print Foo.method(x, *(1, 2)) +try: + print Foo.method(*(1, 2, 3)) +except TypeError, err: + print err +try: + print Foo.method(1, *(2, 3)) +except TypeError, err: + print err + + diff --git a/Python/ceval.c b/Python/ceval.c index df057b763c0..ad6e7920a59 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1822,7 +1822,7 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, na++; n++; } - else { + else if (!((flags & 1) && na == 0)) { /* Unbound methods must be called with an instance of the class (or a derived class) as first argument */ @@ -1895,6 +1895,20 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals, if (nstar < 0) { goto extcall_fail; } + if (class && self == NULL && na == 0) { + /* * arg is first argument of method, + so check it is isinstance of class */ + self = PyTuple_GET_ITEM(stararg, 0); + if (!(PyInstance_Check(self) && + PyClass_IsSubclass((PyObject *) + (((PyInstanceObject *)self)->in_class), + class))) { + PyErr_SetString(PyExc_TypeError, + "unbound method must be called with instance as first argument"); + x = NULL; + break; + } + } } if (nk > 0) { if (kwdict == NULL) {