diff --git a/scrapy/crawler.py b/scrapy/crawler.py index 692a896be..82d94144d 100644 --- a/scrapy/crawler.py +++ b/scrapy/crawler.py @@ -3,9 +3,11 @@ import signal import warnings from twisted.internet import reactor, defer +from zope.interface.verify import verifyClass from scrapy.core.engine import ExecutionEngine from scrapy.resolver import CachingThreadedResolver +from scrapy.interfaces import ISpiderManager from scrapy.extension import ExtensionManager from scrapy.signalmanager import SignalManager from scrapy.exceptions import ScrapyDeprecationWarning @@ -78,6 +80,7 @@ class CrawlerRunner(object): def __init__(self, settings): self.settings = settings smcls = load_object(settings['SPIDER_MANAGER_CLASS']) + verifyClass(ISpiderManager, smcls) self.spiders = smcls.from_settings(settings.frozencopy()) self.crawlers = set() self._active = set() diff --git a/tests/test_crawler.py b/tests/test_crawler.py index 34fc1a367..2cf860593 100644 --- a/tests/test_crawler.py +++ b/tests/test_crawler.py @@ -2,6 +2,7 @@ import warnings import unittest from twisted.internet import defer +from zope.interface.verify import DoesNotImplement from scrapy.crawler import Crawler, CrawlerRunner from scrapy.settings import Settings @@ -42,3 +43,19 @@ class CrawlerTestCase(unittest.TestCase): self.assertFalse(settings.frozen) self.assertTrue(crawler.settings.frozen) + + +def SpiderManagerWithWrongInterface(object): + + def unneeded_method(self): + pass + + +class CrawlerRunnerTestCase(unittest.TestCase): + + def test_spider_manager_verify_interface(self): + settings = Settings({ + 'SPIDER_MANAGER_CLASS': 'tests.test_crawler.SpiderManagerWithWrongInterface' + }) + with self.assertRaises(DoesNotImplement): + CrawlerRunner(settings)