diff --git a/scrapy/crawler.py b/scrapy/crawler.py index b4706919a..174a5ad74 100644 --- a/scrapy/crawler.py +++ b/scrapy/crawler.py @@ -3,7 +3,7 @@ import signal import warnings from twisted.internet import reactor, defer -from zope.interface.verify import verifyClass +from zope.interface.verify import verifyClass, DoesNotImplement from scrapy.core.engine import ExecutionEngine from scrapy.resolver import CachingThreadedResolver @@ -195,5 +195,13 @@ def _get_spider_loader(settings): cls_path = settings.get('SPIDER_MANAGER_CLASS', settings.get('SPIDER_LOADER_CLASS')) loader_cls = load_object(cls_path) - verifyClass(ISpiderLoader, loader_cls) + try: + verifyClass(ISpiderLoader, loader_cls) + except DoesNotImplement: + warnings.warn( + 'SPIDER_LOADER_CLASS (previously named SPIDER_MANAGER_CLASS) does ' + 'not fully implement scrapy.interfaces.ISpiderLoader interface. ' + 'Please add all missing methods to avoid unexpected runtime errors.', + category=ScrapyDeprecationWarning, stacklevel=2 + ) return loader_cls.from_settings(settings.frozencopy()) diff --git a/tests/test_crawler.py b/tests/test_crawler.py index 6a282ed84..906573887 100644 --- a/tests/test_crawler.py +++ b/tests/test_crawler.py @@ -1,8 +1,6 @@ import warnings import unittest -from zope.interface.verify import DoesNotImplement - from scrapy.crawler import Crawler, CrawlerRunner from scrapy.settings import Settings, default_settings from scrapy.spiderloader import SpiderLoader @@ -71,8 +69,12 @@ class CrawlerRunnerTestCase(unittest.TestCase): settings = Settings({ 'SPIDER_LOADER_CLASS': 'tests.test_crawler.SpiderLoaderWithWrongInterface' }) - with self.assertRaises(DoesNotImplement): + with warnings.catch_warnings(record=True) as w, \ + self.assertRaises(AttributeError): CrawlerRunner(settings) + self.assertEqual(len(w), 1) + self.assertIn("SPIDER_LOADER_CLASS", str(w[0].message)) + self.assertIn("scrapy.interfaces.ISpiderLoader", str(w[0].message)) def test_crawler_runner_accepts_dict(self): runner = CrawlerRunner({'foo': 'bar'})