Commit 420c4d6c authored by Jason Madden's avatar Jason Madden

Simplify getting the repr for greenlet functions and return the args/kwargs in more circumstances.

parent 8a2c50e2
...@@ -88,10 +88,12 @@ ...@@ -88,10 +88,12 @@
- Greenlet objects now keep track of their spawning parent greenlet - Greenlet objects now keep track of their spawning parent greenlet
and the code location that spawned them, in addition to maintaining and the code location that spawned them, in addition to maintaining
a "spawn tree local" mapping. Based on a proposal from PayPal and a "spawn tree local" mapping. Based on a proposal from PayPal and
comments by Mahmoud Hashemi and Kurt Rose. See :issue:`755`. comments by Mahmoud Hashemi and Kurt Rose. See :issue:`755` and
:pr:`1115`.
- The :mod:`gevent.greenlet` module is now compiled with Cython to - The :mod:`gevent.greenlet` module is now compiled with Cython to
offset any performance loss due to :issue:`755`. offset any performance decrease due to :issue:`755`. Please open
issues for any compatibility concerns. See :pr:`1115`.
1.3a1 (2018-01-27) 1.3a1 (2018-01-27)
================== ==================
......
...@@ -49,12 +49,14 @@ cdef class Greenlet(greenlet): ...@@ -49,12 +49,14 @@ cdef class Greenlet(greenlet):
cdef object _notifier cdef object _notifier
cdef object _start_event cdef object _start_event
cdef dict _kwargs cdef dict _kwargs
cdef str _formatted_info
cpdef bint has_links(self) cpdef bint has_links(self)
cpdef join(self, timeout=*) cpdef join(self, timeout=*)
cpdef bint ready(self) cpdef bint ready(self)
cpdef bint successful(self) cpdef bint successful(self)
cpdef rawlink(self, object callback) cpdef rawlink(self, object callback)
cpdef str _formatinfo(self)
cdef bint __started_but_aborted(self) cdef bint __started_but_aborted(self)
cdef bint __start_cancelled_by_kill(self) cdef bint __start_cancelled_by_kill(self)
......
...@@ -9,7 +9,6 @@ from weakref import ref as wref ...@@ -9,7 +9,6 @@ from weakref import ref as wref
from greenlet import greenlet from greenlet import greenlet
from greenlet import getcurrent from greenlet import getcurrent
from gevent._compat import PY3
from gevent._compat import PYPY from gevent._compat import PYPY
from gevent._compat import reraise from gevent._compat import reraise
from gevent._tblib import dump_traceback from gevent._tblib import dump_traceback
...@@ -244,6 +243,7 @@ class Greenlet(greenlet): ...@@ -244,6 +243,7 @@ class Greenlet(greenlet):
self._kwargs = kwargs self._kwargs = kwargs
self.value = None self.value = None
self._notifier = None self._notifier = None
self._formatted_info = None
self._links = [] self._links = []
# Initial state: None. # Initial state: None.
...@@ -393,19 +393,24 @@ class Greenlet(greenlet): ...@@ -393,19 +393,24 @@ class Greenlet(greenlet):
result += ': ' + formatted result += ': ' + formatted
return result + '>' return result + '>'
_formatted_info = None
def _formatinfo(self): def _formatinfo(self):
info = self._formatted_info info = self._formatted_info
if info is not None: if info is not None:
return info return info
try: # Are we running an arbitrary function provided to the constructor,
result = getfuncname(self.__dict__['_run']) # or did a subclass override _run?
except Exception: # pylint:disable=broad-except func = self._run
# Don't cache im_self = getattr(func, '__self__', None)
return '' if im_self is self:
funcname = '_run'
elif im_self is not None:
funcname = repr(func)
else:
funcname = getattr(func, '__name__', '') or repr(func)
result = funcname
args = [] args = []
if self.args: if self.args:
args = [repr(x)[:50] for x in self.args] args = [repr(x)[:50] for x in self.args]
...@@ -672,7 +677,7 @@ class Greenlet(greenlet): ...@@ -672,7 +677,7 @@ class Greenlet(greenlet):
self._report_result(result) self._report_result(result)
finally: finally:
self.__dict__.pop('_run', None) self.__dict__.pop('_run', None)
self.args = None self.args = ()
self._kwargs = None self._kwargs = None
def _run(self): def _run(self):
...@@ -880,21 +885,3 @@ def killall(greenlets, exception=GreenletExit, block=True, timeout=None): ...@@ -880,21 +885,3 @@ def killall(greenlets, exception=GreenletExit, block=True, timeout=None):
t.cancel() t.cancel()
else: else:
loop.run_callback(_killall, greenlets, exception) loop.run_callback(_killall, greenlets, exception)
if PY3:
_meth_self = "__self__"
else:
_meth_self = "im_self"
def getfuncname(func):
if not hasattr(func, _meth_self):
try:
funcname = func.__name__
except AttributeError:
pass
else:
if funcname != '<lambda>':
return funcname
return repr(func)
...@@ -405,6 +405,8 @@ class A(object): ...@@ -405,6 +405,8 @@ class A(object):
hexobj = re.compile('-?0x[0123456789abcdef]+L?', re.I) hexobj = re.compile('-?0x[0123456789abcdef]+L?', re.I)
class Subclass(gevent.Greenlet):
pass
class TestStr(greentest.TestCase): class TestStr(greentest.TestCase):
...@@ -428,6 +430,17 @@ class TestStr(greentest.TestCase): ...@@ -428,6 +430,17 @@ class TestStr(greentest.TestCase):
str_g = str_g.replace(__name__, 'module') str_g = str_g.replace(__name__, 'module')
self.assertEqual(str_g, '<Greenlet at X: <bound method A.method of <module.A object at X>>>') self.assertEqual(str_g, '<Greenlet at X: <bound method A.method of <module.A object at X>>>')
def test_subclass(self):
g = Subclass()
str_g = hexobj.sub('X', str(g))
str_g = str_g.replace(__name__, 'module')
self.assertEqual(str_g, '<Subclass at X: _run>')
g = Subclass(None, 'question', answer=42)
str_g = hexobj.sub('X', str(g))
str_g = str_g.replace(__name__, 'module')
self.assertEqual(str_g, "<Subclass at X: _run('question', answer=42)>")
class TestJoin(AbstractGenericWaitTestCase): class TestJoin(AbstractGenericWaitTestCase):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment