Merge pull request #4756 from ivanprado/master

Support for delegated methods as callbacks
This commit is contained in:
Mikhail Korobov 2020-08-26 00:10:43 +05:00 committed by GitHub
commit 0ccaf89a6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 19 deletions

View File

@ -71,25 +71,20 @@ def request_from_dict(d, spider=None):
def _find_method(obj, func):
if obj:
try:
func_self = func.__self__
except AttributeError: # func has no __self__
pass
else:
if func_self is obj:
members = inspect.getmembers(obj, predicate=inspect.ismethod)
for name, obj_func in members:
# We need to use __func__ to access the original
# function object because instance method objects
# are generated each time attribute is retrieved from
# instance.
#
# Reference: The standard type hierarchy
# https://docs.python.org/3/reference/datamodel.html
if obj_func.__func__ is func.__func__:
return name
raise ValueError("Function %s is not a method of: %s" % (func, obj))
# Only instance methods contain ``__func__``
if obj and hasattr(func, '__func__'):
members = inspect.getmembers(obj, predicate=inspect.ismethod)
for name, obj_func in members:
# We need to use __func__ to access the original
# function object because instance method objects
# are generated each time attribute is retrieved from
# instance.
#
# Reference: The standard type hierarchy
# https://docs.python.org/3/reference/datamodel.html
if obj_func.__func__ is func.__func__:
return name
raise ValueError("Function %s is not an instance method in: %s" % (func, obj))
def _get_method(obj, name):

View File

@ -102,6 +102,12 @@ class RequestSerializationTest(unittest.TestCase):
errback=self.spider.handle_error)
self._assert_serializes_ok(r, spider=self.spider)
def test_delegated_callback_serialization(self):
r = Request("http://www.example.com",
callback=self.spider.delegated_callback,
errback=self.spider.handle_error)
self._assert_serializes_ok(r, spider=self.spider)
def test_unserializable_callback1(self):
r = Request("http://www.example.com", callback=lambda x: x)
self.assertRaises(ValueError, request_to_dict, r)
@ -132,6 +138,11 @@ class TestSpiderMixin:
pass
class TestSpiderDelegation:
def delegated_callback(self, response):
pass
def parse_item(response):
pass
@ -155,6 +166,9 @@ class TestSpider(Spider, TestSpiderMixin):
__parse_item_reference = private_parse_item
__handle_error_reference = private_handle_error
def __init__(self):
self.delegated_callback = TestSpiderDelegation().delegated_callback
def parse_item(self, response):
pass