Commit af7e89c5 authored by Jason Madden's avatar Jason Madden Committed by GitHub

Merge pull request #1267 from gevent/issue1266

Don't double-descriptor @staticmethod objects. Fixes #1266
parents d0aa959f 371afee9
......@@ -12,6 +12,10 @@
3.7 or they will crash. Reported by Alexey Stepanov in :issue:`1260`
and pkittenis in :issue:`1261`.
- :class:`gevent.local.local` subclasses correctly supports
``@staticmethod`` functions. Reported by Brendan Powers in
:issue:`1266`.
1.3.5 (2018-07-16)
==================
......
......@@ -5,15 +5,15 @@ wheel
# 0.28 is faster, and (important!) lets us specify the target module
# name to be created so that we can have both foo.py and _foo.so
# at the same time.
Cython >= 0.28.1
Cython >= 0.28.5
# Python 3.7 requires at least 0.4.14, which is ABI incompatible with earlier
greenlet>=0.4.14 ; platform_python_implementation == "CPython"
pylint>=1.8.0 ; python_version < "3.4"
pylint >= 2.0.0.dev2 ; python_version >= "3.4"
# pylint 2 needs astroid 2; unfortunately, it uses `typed_ast`
# which has a C extension that doesn't build on PyPy
astroid >= 2.0.0.dev1 ; python_version >= "3.4" and platform_python_implementation == "CPython"
pylint >= 2.1.1 ; python_version >= "3.4" and platform_python_implementation == "CPython"
astroid >= 2.0.2 ; python_version >= "3.4" and platform_python_implementation == "CPython"
# See version requirements in setup.py
cffi >= 1.11.5 ; platform_python_implementation == "CPython"
......
......@@ -54,7 +54,7 @@ class SSLContext(orig_SSLContext):
suppress_ragged_eofs=True,
server_hostname=None,
session=None):
# pylint:disable=arguments-differ
# pylint:disable=arguments-differ,not-callable
# (3.6 adds session)
# Sadly, using *args and **kwargs doesn't work
return self.sslsocket_class(
......
......@@ -37,6 +37,7 @@ class LoopExit(Exception):
"""
def __repr__(self):
# pylint:disable=unsubscriptable-object
if len(self.args) == 3: # From the hub
import pprint
return "%s\n\tHub: %s\n\tHandles:\n%s" % (
......
......@@ -438,13 +438,23 @@ class local(object):
return dct[name]
if name in self._local_type_vars:
type_attr = getattr(self._local_type, name)
# It's not in the dict at all. Is it in the type?
# Not in the dictionary, but is found in the type. It could be
# a non-data descriptor still. Some descriptors, like @staticmethod,
# return objects (functions, in this case), that are *themselves*
# descriptors, which when invoked, again, would do the wrong thing.
# So we can't rely on getattr() on the type for them, we have to
# look through the MRO dicts ourself.
if name not in self._local_type_get_descriptors:
# Not a descriptor, can't execute code
return type_attr
return type(type_attr).__get__(type_attr, self, self._local_type)
# Not a descriptor, can't execute code. So all we need is
# the return value of getattr() on our type.
return getattr(self._local_type, name)
for base in self._local_type.mro():
bd = base.__dict__
if name in bd:
attr_on_type = bd[name]
result = type(attr_on_type).__get__(attr_on_type, self, self._local_type)
return result
# It wasn't in the dict and it wasn't in the type.
# So the next step is to invoke type(self)__getattr__, if it
......
......@@ -83,6 +83,20 @@ class LocalWithABC(local, Mapping):
def __len__(self):
return len(self.d)
class LocalWithStaticMethod(local):
@staticmethod
def a_staticmethod():
return 42
class LocalWithClassMethod(local):
@classmethod
def a_classmethod(cls):
return cls
class TestGeventLocal(greentest.TestCase):
# pylint:disable=attribute-defined-outside-init,blacklisted-name
......@@ -352,6 +366,14 @@ class TestGeventLocal(greentest.TestCase):
self.assertIn('a', x.d)
self.assertEqual(['a'], list(x.keys()))
def test_local_with_staticmethod(self):
x = LocalWithStaticMethod()
self.assertEqual(42, x.a_staticmethod())
def test_local_with_classmethod(self):
x = LocalWithClassMethod()
self.assertIs(LocalWithClassMethod, x.a_classmethod())
try:
from zope import interface
except ImportError:
......
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