diff --git a/scrapy/crawler.py b/scrapy/crawler.py index 04aee18ed..ee00d27b4 100644 --- a/scrapy/crawler.py +++ b/scrapy/crawler.py @@ -7,6 +7,7 @@ import sys from twisted.internet import reactor, defer from zope.interface.verify import verifyClass, DoesNotImplement +from scrapy import Spider from scrapy.core.engine import ExecutionEngine from scrapy.resolver import CachingThreadedResolver from scrapy.interfaces import ISpiderLoader @@ -27,6 +28,10 @@ logger = logging.getLogger(__name__) class Crawler(object): def __init__(self, spidercls, settings=None): + if isinstance(spidercls, Spider): + raise ValueError( + 'The spidercls argument must be a class, not an object') + if isinstance(settings, dict) or settings is None: settings = Settings(settings) @@ -168,6 +173,10 @@ class CrawlerRunner(object): :param dict kwargs: keyword arguments to initialize the spider """ + if isinstance(crawler_or_spidercls, Spider): + raise ValueError( + 'The crawler_or_spidercls argument cannot be a spider object, ' + 'it must be a spider class (or a Crawler object)') crawler = self.create_crawler(crawler_or_spidercls) return self._crawl(crawler, *args, **kwargs) @@ -195,6 +204,10 @@ class CrawlerRunner(object): a spider with this name in a Scrapy project (using spider loader), then creates a Crawler instance for it. """ + if isinstance(crawler_or_spidercls, Spider): + raise ValueError( + 'The crawler_or_spidercls argument cannot be a spider object, ' + 'it must be a spider class (or a Crawler object)') if isinstance(crawler_or_spidercls, Crawler): return crawler_or_spidercls return self._create_crawler(crawler_or_spidercls) diff --git a/tests/test_crawler.py b/tests/test_crawler.py index 268948a70..37cea3ad3 100644 --- a/tests/test_crawler.py +++ b/tests/test_crawler.py @@ -4,6 +4,7 @@ import warnings from twisted.internet import defer from twisted.trial import unittest +from pytest import raises import scrapy from scrapy.crawler import Crawler, CrawlerRunner, CrawlerProcess @@ -66,6 +67,10 @@ class CrawlerTestCase(BaseCrawlerTest): crawler = Crawler(DefaultSpider) self.assertOptionIsDefault(crawler.settings, 'RETRY_ENABLED') + def test_crawler_rejects_spider_objects(self): + with raises(ValueError): + Crawler(DefaultSpider()) + class SpiderSettingsTestCase(unittest.TestCase): def test_spider_custom_settings(self): @@ -177,6 +182,14 @@ class CrawlerRunnerTestCase(BaseCrawlerTest): self.assertEqual(len(w), 1) self.assertIn('Please use SPIDER_LOADER_CLASS', str(w[0].message)) + def test_crawl_rejects_spider_objects(self): + with raises(ValueError): + CrawlerRunner().crawl(DefaultSpider()) + + def test_create_crawler_rejects_spider_objects(self): + with raises(ValueError): + CrawlerRunner().create_crawler(DefaultSpider()) + class CrawlerProcessTest(BaseCrawlerTest): def test_crawler_process_accepts_dict(self): diff --git a/tests/test_downloadermiddleware_httpproxy.py b/tests/test_downloadermiddleware_httpproxy.py index 537126613..30920b2da 100644 --- a/tests/test_downloadermiddleware_httpproxy.py +++ b/tests/test_downloadermiddleware_httpproxy.py @@ -25,7 +25,7 @@ class TestHttpProxyMiddleware(TestCase): def test_not_enabled(self): settings = Settings({'HTTPPROXY_ENABLED': False}) - crawler = Crawler(spider, settings) + crawler = Crawler(Spider, settings) self.assertRaises(NotConfigured, partial(HttpProxyMiddleware.from_crawler, crawler)) def test_no_environment_proxies(self):