From bcad8947e8192448ab3bd59489444efb567f8793 Mon Sep 17 00:00:00 2001 From: Andrew Baxter Date: Mon, 3 Jun 2019 20:41:02 +0900 Subject: [PATCH] Support inherited private method names --- scrapy/utils/reqser.py | 9 +++++++-- tests/test_utils_reqser.py | 16 +++++++++++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/scrapy/utils/reqser.py b/scrapy/utils/reqser.py index 40223661f..d1f472e6e 100644 --- a/scrapy/utils/reqser.py +++ b/scrapy/utils/reqser.py @@ -81,8 +81,13 @@ def _find_method(obj, func): if func_self is obj: name = six.get_method_function(func).__name__ if _is_private_method(name): - classname = obj.__class__.__name__.lstrip('_') - name = '_%s%s' % (classname, name) + qualname = getattr(func, '__qualname__', None) + if qualname is None: + classname = obj.__class__.__name__.lstrip('_') + name = '_%s%s' % (classname, name) + else: + splits = qualname.split('.') + name = '_%s%s' % (splits[-2], splits[-1]) return name raise ValueError("Function %s is not a method of: %s" % (func, obj)) diff --git a/tests/test_utils_reqser.py b/tests/test_utils_reqser.py index fad5b6003..31577bc8c 100644 --- a/tests/test_utils_reqser.py +++ b/tests/test_utils_reqser.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- import unittest +import sys from scrapy.http import Request, FormRequest from scrapy.spiders import Spider @@ -74,6 +75,14 @@ class RequestSerializationTest(unittest.TestCase): errback=self.spider.handle_error) self._assert_serializes_ok(r, spider=self.spider) + def test_mixin_private_callback_serialization(self): + if sys.version_info[0] < 3: + return + r = Request("http://www.example.com", + callback=self.spider._TestSpiderMixin__mixin_callback, + errback=self.spider.handle_error) + self._assert_serializes_ok(r, spider=self.spider) + def test_private_callback_name_matching(self): self.assertTrue(_is_private_method('__a')) self.assertTrue(_is_private_method('__a_')) @@ -106,7 +115,12 @@ class RequestSerializationTest(unittest.TestCase): self.assertRaises(ValueError, request_to_dict, r) -class TestSpider(Spider): +class TestSpiderMixin(object): + def __mixin_callback(self, response): + pass + + +class TestSpider(Spider, TestSpiderMixin): name = 'test' def parse_item(self, response):