Python 3 support for classmethod call targets
There were two problems with detection and handling of class methods as call targets in Python 3: * Methods no longer define `im_self` -- this is now only `__self__` * The `types` module no longer defines a `ClassType` The universally-compatible (v2.6+) solution was to switch to using the `inspect` module -- whose interface has been stable -- and to checking the method attribute `__self__`. (It doesn't hurt that `inspect` checks are more brief and we now no longer need the `types` module here.)
This commit is contained in:
parent
e2e2a06c00
commit
3453d4d7d0
|
@ -47,7 +47,6 @@ import termios
|
||||||
import textwrap
|
import textwrap
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import types
|
|
||||||
import zlib
|
import zlib
|
||||||
|
|
||||||
# Absolute imports for <2.5.
|
# Absolute imports for <2.5.
|
||||||
|
@ -490,9 +489,8 @@ def upgrade_router(econtext):
|
||||||
|
|
||||||
|
|
||||||
def make_call_msg(fn, *args, **kwargs):
|
def make_call_msg(fn, *args, **kwargs):
|
||||||
if isinstance(fn, types.MethodType) and \
|
if inspect.ismethod(fn) and inspect.isclass(fn.__self__):
|
||||||
isinstance(fn.im_self, (type, types.ClassType)):
|
klass = mitogen.core.to_text(fn.__self__.__name__)
|
||||||
klass = mitogen.core.to_text(fn.im_self.__name__)
|
|
||||||
else:
|
else:
|
||||||
klass = None
|
klass = None
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,17 @@ def func_accepts_returns_sender(sender):
|
||||||
return sender
|
return sender
|
||||||
|
|
||||||
|
|
||||||
|
class TargetClass:
|
||||||
|
|
||||||
|
offset = 100
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def add_numbers_with_offset(cls, x, y):
|
||||||
|
return cls.offset + x + y
|
||||||
|
|
||||||
|
|
||||||
class CallFunctionTest(testlib.RouterMixin, testlib.TestCase):
|
class CallFunctionTest(testlib.RouterMixin, testlib.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(CallFunctionTest, self).setUp()
|
super(CallFunctionTest, self).setUp()
|
||||||
self.local = self.router.fork()
|
self.local = self.router.fork()
|
||||||
|
@ -44,6 +54,12 @@ class CallFunctionTest(testlib.RouterMixin, testlib.TestCase):
|
||||||
def test_succeeds(self):
|
def test_succeeds(self):
|
||||||
self.assertEqual(3, self.local.call(function_that_adds_numbers, 1, 2))
|
self.assertEqual(3, self.local.call(function_that_adds_numbers, 1, 2))
|
||||||
|
|
||||||
|
def test_succeeds_class_method(self):
|
||||||
|
self.assertEqual(
|
||||||
|
self.local.call(TargetClass.add_numbers_with_offset, 1, 2),
|
||||||
|
103,
|
||||||
|
)
|
||||||
|
|
||||||
def test_crashes(self):
|
def test_crashes(self):
|
||||||
exc = self.assertRaises(mitogen.core.CallError,
|
exc = self.assertRaises(mitogen.core.CallError,
|
||||||
lambda: self.local.call(function_that_fails))
|
lambda: self.local.call(function_that_fails))
|
||||||
|
|
Loading…
Reference in New Issue