diff --git a/docs/topics/api.rst b/docs/topics/api.rst index 2055682dc..48347120b 100644 --- a/docs/topics/api.rst +++ b/docs/topics/api.rst @@ -344,22 +344,22 @@ Settings API Alias for a :meth:`~freeze` call in the object returned by :meth:`copy` -.. _topics-api-spidermanager: +.. _topics-api-spiderloader: -SpiderManager API -================= +SpiderLoader API +================ -.. module:: scrapy.spidermanager - :synopsis: The spider manager +.. module:: scrapy.loader + :synopsis: The spider loader -.. class:: SpiderManager +.. class:: SpiderLoader This class is in charge of retrieving and handling the spider classes defined across the project. - Custom spider managers can be employed by specifying their path in the - :setting:`SPIDER_MANAGER_CLASS` project setting. They must fully implement - the :class:`scrapy.interfaces.ISpiderManager` interface to guarantee an + Custom spider loaders can be employed by specifying their path in the + :setting:`SPIDER_LOADER_CLASS` project setting. They must fully implement + the :class:`scrapy.interfaces.ISpiderLoader` interface to guarantee an errorless execution. .. method:: from_settings(settings) @@ -486,7 +486,7 @@ class (which they all inherit from). Set the given value for the given key only if current value for the same key is lower than value. If there is no current value for the - given key, the value is always set. + given key, the value is always set. .. method:: min_value(key, value) diff --git a/docs/topics/settings.rst b/docs/topics/settings.rst index 1986b2f3e..7deb6e0c6 100644 --- a/docs/topics/settings.rst +++ b/docs/topics/settings.rst @@ -853,15 +853,15 @@ A dict containing the scrapy contracts enabled by default in Scrapy. You should never modify this setting in your project, modify :setting:`SPIDER_CONTRACTS` instead. For more info see :ref:`topics-contracts`. -.. setting:: SPIDER_MANAGER_CLASS +.. setting:: SPIDER_LOADER_CLASS -SPIDER_MANAGER_CLASS --------------------- +SPIDER_LOADER_CLASS +------------------- -Default: ``'scrapy.spidermanager.SpiderManager'`` +Default: ``'scrapy.spiderloader.SpiderLoader'`` -The class that will be used for handling spiders, which must implement the -:ref:`topics-api-spidermanager`. +The class that will be used for loading spiders, which must implement the +:ref:`topics-api-spiderloader`. .. setting:: SPIDER_MIDDLEWARES diff --git a/scrapy/commands/check.py b/scrapy/commands/check.py index 014b00eeb..bf07f360f 100644 --- a/scrapy/commands/check.py +++ b/scrapy/commands/check.py @@ -69,10 +69,10 @@ class Command(ScrapyCommand): # contract requests contract_reqs = defaultdict(list) - spiders = self.crawler_process.spiders + spider_loader = self.crawler_process.spider_loader - for spidername in args or spiders.list(): - spidercls = spiders.load(spidername) + for spidername in args or spider_loader.list(): + spidercls = spider_loader.load(spidername) spidercls.start_requests = lambda s: conman.from_spider(s, result) tested_methods = conman.tested_methods_from_spidercls(spidercls) diff --git a/scrapy/commands/edit.py b/scrapy/commands/edit.py index e20e7c2e5..016c98d2d 100644 --- a/scrapy/commands/edit.py +++ b/scrapy/commands/edit.py @@ -27,7 +27,7 @@ class Command(ScrapyCommand): editor = self.settings['EDITOR'] try: - spidercls = self.crawler_process.spiders.load(args[0]) + spidercls = self.crawler_process.spider_loader.load(args[0]) except KeyError: return self._err("Spider not found: %s" % args[0]) diff --git a/scrapy/commands/fetch.py b/scrapy/commands/fetch.py index ca9fd57f5..89809a177 100644 --- a/scrapy/commands/fetch.py +++ b/scrapy/commands/fetch.py @@ -48,10 +48,10 @@ class Command(ScrapyCommand): request.meta['handle_httpstatus_all'] = True spidercls = DefaultSpider - spiders = self.crawler_process.spiders + spider_loader = self.crawler_process.spider_loader if opts.spider: - spidercls = spiders.load(opts.spider) + spidercls = spider_loader.load(opts.spider) else: - spidercls = spidercls_for_request(spiders, request, spidercls) + spidercls = spidercls_for_request(spider_loader, request, spidercls) self.crawler_process.crawl(spidercls, start_requests=lambda: [request]) self.crawler_process.start() diff --git a/scrapy/commands/genspider.py b/scrapy/commands/genspider.py index 52c5d9f94..9d68ec845 100644 --- a/scrapy/commands/genspider.py +++ b/scrapy/commands/genspider.py @@ -65,7 +65,7 @@ class Command(ScrapyCommand): return try: - spidercls = self.crawler_process.spiders.load(name) + spidercls = self.crawler_process.spider_loader.load(name) except KeyError: pass else: diff --git a/scrapy/commands/list.py b/scrapy/commands/list.py index 2d55d59bd..3b35cbb92 100644 --- a/scrapy/commands/list.py +++ b/scrapy/commands/list.py @@ -10,5 +10,5 @@ class Command(ScrapyCommand): return "List available spiders" def run(self, args, opts): - for s in sorted(self.crawler_process.spiders.list()): + for s in sorted(self.crawler_process.spider_loader.list()): print(s) diff --git a/scrapy/commands/parse.py b/scrapy/commands/parse.py index b8cc140d4..3e006ede3 100644 --- a/scrapy/commands/parse.py +++ b/scrapy/commands/parse.py @@ -124,15 +124,15 @@ class Command(ScrapyCommand): level=log.ERROR, spider=spider.name) def set_spidercls(self, url, opts): - spiders = self.crawler_process.spiders + spider_loader = self.crawler_process.spider_loader if opts.spider: try: - self.spidercls = spiders.load(opts.spider) + self.spidercls = spider_loader.load(opts.spider) except KeyError: log.msg(format='Unable to find spider: %(spider)s', level=log.ERROR, spider=opts.spider) else: - self.spidercls = spidercls_for_request(spiders, Request(url)) + self.spidercls = spidercls_for_request(spider_loader, Request(url)) if not self.spidercls: log.msg(format='Unable to find spider for: %(url)s', level=log.ERROR, url=url) diff --git a/scrapy/commands/shell.py b/scrapy/commands/shell.py index 7c0706482..f8ad8a491 100644 --- a/scrapy/commands/shell.py +++ b/scrapy/commands/shell.py @@ -42,13 +42,13 @@ class Command(ScrapyCommand): def run(self, args, opts): url = args[0] if args else None - spiders = self.crawler_process.spiders + spider_loader = self.crawler_process.spider_loader spidercls = DefaultSpider if opts.spider: - spidercls = spiders.load(opts.spider) + spidercls = spider_loader.load(opts.spider) elif url: - spidercls = spidercls_for_request(spiders, Request(url), + spidercls = spidercls_for_request(spider_loader, Request(url), spidercls, log_multiple=True) # The crawler is created this way since the Shell manually handles the diff --git a/scrapy/crawler.py b/scrapy/crawler.py index 3d0576081..dab1043ec 100644 --- a/scrapy/crawler.py +++ b/scrapy/crawler.py @@ -7,7 +7,7 @@ from zope.interface.verify import verifyClass from scrapy.core.engine import ExecutionEngine from scrapy.resolver import CachingThreadedResolver -from scrapy.interfaces import ISpiderManager +from scrapy.interfaces import ISpiderLoader from scrapy.extension import ExtensionManager from scrapy.settings import Settings from scrapy.signalmanager import SignalManager @@ -43,12 +43,11 @@ class Crawler(object): def spiders(self): if not hasattr(self, '_spiders'): warnings.warn("Crawler.spiders is deprecated, use " - "CrawlerRunner.spiders or instantiate " - "scrapy.spidermanager.SpiderManager with your " + "CrawlerRunner.spider_loader or instantiate " + "scrapy.spiderloader.SpiderLoader with your " "settings.", category=ScrapyDeprecationWarning, stacklevel=2) - spman_cls = load_object(self.settings['SPIDER_MANAGER_CLASS']) - self._spiders = spman_cls.from_settings(self.settings) + self._spiders = _get_spider_loader(self.settings.frozencopy()) return self._spiders @defer.inlineCallbacks @@ -85,12 +84,17 @@ class CrawlerRunner(object): if isinstance(settings, dict): settings = Settings(settings) self.settings = settings - smcls = load_object(settings['SPIDER_MANAGER_CLASS']) - verifyClass(ISpiderManager, smcls) - self.spiders = smcls.from_settings(settings.frozencopy()) + self.spider_loader = _get_spider_loader(settings) self.crawlers = set() self._active = set() + @property + def spiders(self): + warnings.warn("CrawlerRunner.spiders attribute is renamed to " + "CrawlerRunner.spider_loader.", + category=ScrapyDeprecationWarning, stacklevel=2) + return self.spider_loader + def crawl(self, crawler_or_spidercls, *args, **kwargs): crawler = crawler_or_spidercls if not isinstance(crawler_or_spidercls, Crawler): @@ -110,7 +114,7 @@ class CrawlerRunner(object): def _create_crawler(self, spidercls): if isinstance(spidercls, six.string_types): - spidercls = self.spiders.load(spidercls) + spidercls = self.spider_loader.load(spidercls) return Crawler(spidercls, self.settings) def _setup_crawler_logging(self, crawler): @@ -178,3 +182,18 @@ class CrawlerProcess(CrawlerRunner): reactor.stop() except RuntimeError: # raised if already stopped or in shutdown stage pass + + +def _get_spider_loader(settings): + """ Get SpiderLoader instance from settings """ + if settings.get('SPIDER_MANAGER_CLASS'): + warnings.warn( + 'SPIDER_MANAGER_CLASS option is deprecated. ' + 'Please use SPIDER_LOADER_CLASS.', + category=ScrapyDeprecationWarning, stacklevel=2 + ) + cls_path = settings.get('SPIDER_LOADER_CLASS', + settings.get('SPIDER_MANAGER_CLASS')) + loader_cls = load_object(cls_path) + verifyClass(ISpiderLoader, loader_cls) + return loader_cls.from_settings(settings.frozencopy()) diff --git a/scrapy/interfaces.py b/scrapy/interfaces.py index d4596407e..eb93c6f7e 100644 --- a/scrapy/interfaces.py +++ b/scrapy/interfaces.py @@ -1,12 +1,12 @@ from zope.interface import Interface -class ISpiderManager(Interface): +class ISpiderLoader(Interface): def from_settings(settings): - """Returns an instance of the class for the given settings""" + """Return an instance of the class for the given settings""" def load(spider_name): - """Returns the Spider class for the given spider name. If the spider + """Return the Spider class for the given spider name. If the spider name is not found, it must raise a KeyError.""" def list(): @@ -14,4 +14,9 @@ class ISpiderManager(Interface): project""" def find_by_request(request): - """Returns the list of spiders names that can handle the given request""" + """Return the list of spiders names that can handle the given request""" + + +# ISpiderManager is deprecated, don't use it! +# An alias is kept for backwards compatibility. +ISpiderManager = ISpiderLoader diff --git a/scrapy/settings/default_settings.py b/scrapy/settings/default_settings.py index 22005eb5d..0a5afc7e6 100644 --- a/scrapy/settings/default_settings.py +++ b/scrapy/settings/default_settings.py @@ -215,7 +215,7 @@ SCHEDULER = 'scrapy.core.scheduler.Scheduler' SCHEDULER_DISK_QUEUE = 'scrapy.squeue.PickleLifoDiskQueue' SCHEDULER_MEMORY_QUEUE = 'scrapy.squeue.LifoMemoryQueue' -SPIDER_MANAGER_CLASS = 'scrapy.spidermanager.SpiderManager' +SPIDER_LOADER_CLASS = 'scrapy.spiderloader.SpiderLoader' SPIDER_MIDDLEWARES = {} diff --git a/scrapy/spider.py b/scrapy/spider.py index dada6236b..a2d091804 100644 --- a/scrapy/spider.py +++ b/scrapy/spider.py @@ -97,7 +97,9 @@ class ObsoleteClass(object): def __getattr__(self, name): raise AttributeError(self.message) -spiders = ObsoleteClass(""" -"from scrapy.spider import spiders" no longer works - use "from scrapy.spidermanager import SpiderManager" and instantiate it with your project settings" -""") +spiders = ObsoleteClass( + '"from scrapy.spider import spiders" no longer works - use ' + '"from scrapy.spiderloader import SpiderLoader" and instantiate ' + 'it with your project settings"' +) diff --git a/scrapy/spiderloader.py b/scrapy/spiderloader.py new file mode 100644 index 000000000..a88db27c8 --- /dev/null +++ b/scrapy/spiderloader.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +from __future__ import absolute_import + +from zope.interface import implementer + +from scrapy.interfaces import ISpiderLoader +from scrapy.utils.misc import walk_modules +from scrapy.utils.spider import iter_spider_classes + + +@implementer(ISpiderLoader) +class SpiderLoader(object): + """ + SpiderLoader is a class which locates and loads spiders + in a Scrapy project. + """ + def __init__(self, settings): + self.spider_modules = settings.getlist('SPIDER_MODULES') + self._spiders = {} + for name in self.spider_modules: + for module in walk_modules(name): + self._load_spiders(module) + + def _load_spiders(self, module): + for spcls in iter_spider_classes(module): + self._spiders[spcls.name] = spcls + + @classmethod + def from_settings(cls, settings): + return cls(settings) + + def load(self, spider_name): + """ + Return the Spider class for the given spider name. If the spider + name is not found, raise a KeyError. + """ + try: + return self._spiders[spider_name] + except KeyError: + raise KeyError("Spider not found: {}".format(spider_name)) + + def find_by_request(self, request): + """ + Return the list of spider names that can handle the given request. + """ + return [name for name, cls in self._spiders.items() + if cls.handles_request(request)] + + def list(self): + """ + Return a list with the names of all spiders available in the project. + """ + return list(self._spiders.keys()) diff --git a/scrapy/spidermanager.py b/scrapy/spidermanager.py index 93e91bcb4..220257bb1 100644 --- a/scrapy/spidermanager.py +++ b/scrapy/spidermanager.py @@ -1,43 +1,7 @@ """ -SpiderManager is the class which locates and manages all website-specific -spiders +Backwards compatibility shim. Use scrapy.spiderloader instead. """ +from scrapy.spiderloader import SpiderLoader +from scrapy.utils.deprecate import create_deprecated_class -from zope.interface import implementer -import six - -from scrapy.interfaces import ISpiderManager -from scrapy.utils.misc import walk_modules -from scrapy.utils.spider import iter_spider_classes - - -@implementer(ISpiderManager) -class SpiderManager(object): - - def __init__(self, settings): - self.spider_modules = settings.getlist('SPIDER_MODULES') - self._spiders = {} - for name in self.spider_modules: - for module in walk_modules(name): - self._load_spiders(module) - - def _load_spiders(self, module): - for spcls in iter_spider_classes(module): - self._spiders[spcls.name] = spcls - - @classmethod - def from_settings(cls, settings): - return cls(settings) - - def load(self, spider_name): - try: - return self._spiders[spider_name] - except KeyError: - raise KeyError("Spider not found: {}".format(spider_name)) - - def find_by_request(self, request): - return [name for name, cls in six.iteritems(self._spiders) - if cls.handles_request(request)] - - def list(self): - return list(self._spiders.keys()) +SpiderManager = create_deprecated_class('SpiderManager', SpiderLoader) diff --git a/scrapy/telnet.py b/scrapy/telnet.py index 7b73a42ac..d7cd601a2 100644 --- a/scrapy/telnet.py +++ b/scrapy/telnet.py @@ -72,7 +72,6 @@ class TelnetConsole(protocol.ServerFactory): 'crawler': self.crawler, 'extensions': self.crawler.extensions, 'stats': self.crawler.stats, - 'spiders': self.crawler.spiders, 'settings': self.crawler.settings, 'est': lambda: print_engine_status(self.crawler.engine), 'p': pprint.pprint, diff --git a/scrapy/utils/spider.py b/scrapy/utils/spider.py index 40ebbefc3..44f098f05 100644 --- a/scrapy/utils/spider.py +++ b/scrapy/utils/spider.py @@ -26,21 +26,21 @@ def iter_spider_classes(module): getattr(obj, 'name', None): yield obj -def spidercls_for_request(spidermanager, request, default_spidercls=None, +def spidercls_for_request(spider_loader, request, default_spidercls=None, log_none=False, log_multiple=False): """Return a spider class that handles the given Request. This will look for the spiders that can handle the given request (using - the spider manager) and return a Spider class if (and only if) there is + the spider loader) and return a Spider class if (and only if) there is only one Spider able to handle the Request. If multiple spiders (or no spider) are found, it will return the default_spidercls passed. It can optionally log if multiple or no spiders are found. """ - snames = spidermanager.find_by_request(request) + snames = spider_loader.find_by_request(request) if len(snames) == 1: - return spidermanager.load(snames[0]) + return spider_loader.load(snames[0]) if len(snames) > 1 and log_multiple: log.msg(format='More than one spider can handle: %(request)s - %(snames)s', diff --git a/tests/py3-ignores.txt b/tests/py3-ignores.txt index 0e7b10386..7a150b281 100644 --- a/tests/py3-ignores.txt +++ b/tests/py3-ignores.txt @@ -43,13 +43,13 @@ tests/test_selector_csstranslator.py tests/test_selector_lxmldocument.py tests/test_selector.py tests/test_settings/__init__.py -tests/test_spidermanager/__init__.py -tests/test_spidermanager/test_spiders/__init__.py -tests/test_spidermanager/test_spiders/spider0.py -tests/test_spidermanager/test_spiders/spider1.py -tests/test_spidermanager/test_spiders/spider2.py -tests/test_spidermanager/test_spiders/spider3.py -tests/test_spidermanager/test_spiders/spider4.py +tests/test_spiderloader/__init__.py +tests/test_spiderloader/test_spiders/__init__.py +tests/test_spiderloader/test_spiders/spider0.py +tests/test_spiderloader/test_spiders/spider1.py +tests/test_spiderloader/test_spiders/spider2.py +tests/test_spiderloader/test_spiders/spider3.py +tests/test_spiderloader/test_spiders/spider4.py tests/test_spidermiddleware_depth.py tests/test_spidermiddleware_httperror.py tests/test_spidermiddleware_offsite.py diff --git a/tests/test_crawler.py b/tests/test_crawler.py index 20467833f..50da01e73 100644 --- a/tests/test_crawler.py +++ b/tests/test_crawler.py @@ -19,8 +19,8 @@ class CrawlerTestCase(unittest.TestCase): spiders = self.crawler.spiders self.assertEqual(len(w), 1) self.assertIn("Crawler.spiders", str(w[0].message)) - sm_cls = load_object(self.crawler.settings['SPIDER_MANAGER_CLASS']) - self.assertIsInstance(spiders, sm_cls) + sl_cls = load_object(self.crawler.settings['SPIDER_LOADER_CLASS']) + self.assertIsInstance(spiders, sl_cls) self.crawler.spiders self.assertEqual(len(w), 1, "Warn deprecated access only once") @@ -54,7 +54,7 @@ class CrawlerTestCase(unittest.TestCase): -def SpiderManagerWithWrongInterface(object): +class SpiderLoaderWithWrongInterface(object): def unneeded_method(self): pass @@ -64,7 +64,7 @@ class CrawlerRunnerTestCase(unittest.TestCase): def test_spider_manager_verify_interface(self): settings = Settings({ - 'SPIDER_MANAGER_CLASS': 'tests.test_crawler.SpiderManagerWithWrongInterface' + 'SPIDER_LOADER_CLASS': 'tests.test_crawler.SpiderLoaderWithWrongInterface' }) with self.assertRaises(DoesNotImplement): CrawlerRunner(settings) @@ -78,3 +78,12 @@ class CrawlerRunnerTestCase(unittest.TestCase): ) self.assertIsInstance(runner.settings, Settings) + def test_deprecated_attribute_spiders(self): + with warnings.catch_warnings(record=True) as w: + runner = CrawlerRunner(Settings()) + spiders = runner.spiders + self.assertEqual(len(w), 1) + self.assertIn("CrawlerRunner.spiders", str(w[0].message)) + self.assertIn("CrawlerRunner.spider_loader", str(w[0].message)) + sl_cls = load_object(runner.settings['SPIDER_LOADER_CLASS']) + self.assertIsInstance(spiders, sl_cls) diff --git a/tests/test_spidermanager/__init__.py b/tests/test_spiderloader/__init__.py similarity index 50% rename from tests/test_spidermanager/__init__.py rename to tests/test_spiderloader/__init__.py index 94b8a1dc8..42f2f29b3 100644 --- a/tests/test_spidermanager/__init__.py +++ b/tests/test_spiderloader/__init__.py @@ -8,14 +8,15 @@ from twisted.trial import unittest # ugly hack to avoid cyclic imports of scrapy.spider when running this test # alone -from scrapy.interfaces import ISpiderManager -from scrapy.spidermanager import SpiderManager +from scrapy.interfaces import ISpiderLoader +from scrapy.spiderloader import SpiderLoader from scrapy.settings import Settings from scrapy.http import Request module_dir = os.path.dirname(os.path.abspath(__file__)) -class SpiderManagerTest(unittest.TestCase): + +class SpiderLoaderTest(unittest.TestCase): def setUp(self): orig_spiders_dir = os.path.join(module_dir, 'test_spiders') @@ -25,53 +26,53 @@ class SpiderManagerTest(unittest.TestCase): shutil.copytree(orig_spiders_dir, self.spiders_dir) sys.path.append(self.tmpdir) settings = Settings({'SPIDER_MODULES': ['test_spiders_xxx']}) - self.spiderman = SpiderManager.from_settings(settings) + self.spider_loader = SpiderLoader.from_settings(settings) def tearDown(self): - del self.spiderman + del self.spider_loader del sys.modules['test_spiders_xxx'] sys.path.remove(self.tmpdir) def test_interface(self): - verifyObject(ISpiderManager, self.spiderman) + verifyObject(ISpiderLoader, self.spider_loader) def test_list(self): - self.assertEqual(set(self.spiderman.list()), + self.assertEqual(set(self.spider_loader.list()), set(['spider1', 'spider2', 'spider3'])) def test_load(self): - spider1 = self.spiderman.load("spider1") + spider1 = self.spider_loader.load("spider1") self.assertEqual(spider1.__name__, 'Spider1') def test_find_by_request(self): - self.assertEqual(self.spiderman.find_by_request(Request('http://scrapy1.org/test')), + self.assertEqual(self.spider_loader.find_by_request(Request('http://scrapy1.org/test')), ['spider1']) - self.assertEqual(self.spiderman.find_by_request(Request('http://scrapy2.org/test')), + self.assertEqual(self.spider_loader.find_by_request(Request('http://scrapy2.org/test')), ['spider2']) - self.assertEqual(set(self.spiderman.find_by_request(Request('http://scrapy3.org/test'))), + self.assertEqual(set(self.spider_loader.find_by_request(Request('http://scrapy3.org/test'))), set(['spider1', 'spider2'])) - self.assertEqual(self.spiderman.find_by_request(Request('http://scrapy999.org/test')), + self.assertEqual(self.spider_loader.find_by_request(Request('http://scrapy999.org/test')), []) - self.assertEqual(self.spiderman.find_by_request(Request('http://spider3.com')), + self.assertEqual(self.spider_loader.find_by_request(Request('http://spider3.com')), []) - self.assertEqual(self.spiderman.find_by_request(Request('http://spider3.com/onlythis')), + self.assertEqual(self.spider_loader.find_by_request(Request('http://spider3.com/onlythis')), ['spider3']) def test_load_spider_module(self): - module = 'tests.test_spidermanager.test_spiders.spider1' + module = 'tests.test_spiderloader.test_spiders.spider1' settings = Settings({'SPIDER_MODULES': [module]}) - self.spiderman = SpiderManager.from_settings(settings) - assert len(self.spiderman._spiders) == 1 + self.spider_loader = SpiderLoader.from_settings(settings) + assert len(self.spider_loader._spiders) == 1 def test_load_spider_module(self): - prefix = 'tests.test_spidermanager.test_spiders.' + prefix = 'tests.test_spiderloader.test_spiders.' module = ','.join(prefix + s for s in ('spider1', 'spider2')) settings = Settings({'SPIDER_MODULES': module}) - self.spiderman = SpiderManager.from_settings(settings) - assert len(self.spiderman._spiders) == 2 + self.spider_loader = SpiderLoader.from_settings(settings) + assert len(self.spider_loader._spiders) == 2 def test_load_base_spider(self): - module = 'tests.test_spidermanager.test_spiders.spider0' + module = 'tests.test_spiderloader.test_spiders.spider0' settings = Settings({'SPIDER_MODULES': [module]}) - self.spiderman = SpiderManager.from_settings(settings) - assert len(self.spiderman._spiders) == 0 + self.spider_loader = SpiderLoader.from_settings(settings) + assert len(self.spider_loader._spiders) == 0 diff --git a/tests/test_spidermanager/test_spiders/__init__.py b/tests/test_spiderloader/test_spiders/__init__.py similarity index 100% rename from tests/test_spidermanager/test_spiders/__init__.py rename to tests/test_spiderloader/test_spiders/__init__.py diff --git a/tests/test_spidermanager/test_spiders/spider0.py b/tests/test_spiderloader/test_spiders/spider0.py similarity index 100% rename from tests/test_spidermanager/test_spiders/spider0.py rename to tests/test_spiderloader/test_spiders/spider0.py diff --git a/tests/test_spidermanager/test_spiders/spider1.py b/tests/test_spiderloader/test_spiders/spider1.py similarity index 100% rename from tests/test_spidermanager/test_spiders/spider1.py rename to tests/test_spiderloader/test_spiders/spider1.py diff --git a/tests/test_spidermanager/test_spiders/spider2.py b/tests/test_spiderloader/test_spiders/spider2.py similarity index 100% rename from tests/test_spidermanager/test_spiders/spider2.py rename to tests/test_spiderloader/test_spiders/spider2.py diff --git a/tests/test_spidermanager/test_spiders/spider3.py b/tests/test_spiderloader/test_spiders/spider3.py similarity index 100% rename from tests/test_spidermanager/test_spiders/spider3.py rename to tests/test_spiderloader/test_spiders/spider3.py