Allow passing Python objects to middleware dict settings

This commit is contained in:
Jakob de Maeyer 2015-07-15 17:27:57 +02:00
parent 54216d7afe
commit cfed9b6659
4 changed files with 26 additions and 3 deletions

View File

@ -1,4 +1,5 @@
from collections import defaultdict
from inspect import isclass
import logging
import pprint
@ -31,7 +32,9 @@ class MiddlewareManager(object):
for clspath in mwlist:
try:
mwcls = load_object(clspath)
if crawler and hasattr(mwcls, 'from_crawler'):
if not isclass(mwcls):
mw = mwcls
elif crawler and hasattr(mwcls, 'from_crawler'):
mw = mwcls.from_crawler(crawler)
elif hasattr(mwcls, 'from_settings'):
mw = mwcls.from_settings(settings)

View File

@ -31,10 +31,15 @@ def arg_to_iter(arg):
def load_object(path):
"""Load an object given its absolute object path, and return it.
object can be a class, function, variable o instance.
If ``path`` is not a string, it will be returned.
The object can be a class, function, variable, or instance.
path ie: 'scrapy.downloadermiddlewares.redirect.RedirectMiddleware'
"""
if not isinstance(path, six.string_types):
return path
try:
dot = path.rindex('.')
except ValueError:

View File

@ -91,3 +91,16 @@ class MiddlewareManagerTest(unittest.TestCase):
mwman = TestMiddlewareManager.from_settings(settings)
classes = [x.__class__ for x in mwman.middlewares]
self.assertEqual(classes, [M1, M3])
def test_instances_from_settings(self):
settings = Settings()
myM3 = M3()
class InstanceTestMiddlewareManager(MiddlewareManager):
@classmethod
def _get_mwlist_from_settings(cls, settings):
return [ 'tests.test_middleware.M1', M2, myM3 ]
mwman = InstanceTestMiddlewareManager.from_settings(settings)
self.assertIsInstance(mwman.middlewares[0], M1)
self.assertIsInstance(mwman.middlewares[1], M2)
self.assertIs(mwman.middlewares[2], myM3)

View File

@ -11,7 +11,9 @@ class UtilsMiscTestCase(unittest.TestCase):
def test_load_object(self):
obj = load_object('scrapy.utils.misc.load_object')
assert obj is load_object
self.assertIs(obj, load_object)
not_a_string = int(1000)
self.assertIs(load_object(not_a_string), not_a_string)
self.assertRaises(ImportError, load_object, 'nomodule999.mod.function')
self.assertRaises(NameError, load_object, 'scrapy.utils.misc.load_object999')