diff --git a/scrapy/contracts/__init__.py b/scrapy/contracts/__init__.py index 536bbdafb..b3f02a291 100644 --- a/scrapy/contracts/__init__.py +++ b/scrapy/contracts/__init__.py @@ -92,7 +92,7 @@ class ContractsManager(object): @wraps(cb) def cb_wrapper(response): try: - output = cb(response) + output = cb(response, **request.cb_kwargs) output = list(iterate_spider_output(output)) except Exception: case = _create_testcase(method, 'callback') @@ -133,7 +133,7 @@ class Contract(object): else: results.addSuccess(self.testcase_pre) finally: - return list(iterate_spider_output(cb(response))) + return list(iterate_spider_output(cb(response, **request.cb_kwargs))) request.callback = wrapper @@ -145,7 +145,7 @@ class Contract(object): @wraps(cb) def wrapper(response): - output = list(iterate_spider_output(cb(response))) + output = list(iterate_spider_output(cb(response, **request.cb_kwargs))) try: results.startTest(self.testcase_post) self.post_process(output) diff --git a/scrapy/contracts/default.py b/scrapy/contracts/default.py index 7745959a7..24f6c2e77 100644 --- a/scrapy/contracts/default.py +++ b/scrapy/contracts/default.py @@ -1,3 +1,5 @@ +import json + from scrapy.item import BaseItem from scrapy.http import Request from scrapy.exceptions import ContractFail @@ -18,6 +20,20 @@ class UrlContract(Contract): return args +class CallbackKeywordArgumentsContract(Contract): + """ Contract to set the keyword arguments for the request. + The value should be a JSON-encoded dictionary, e.g.: + + @cb_kwargs {"arg1": "some value"} + """ + + name = 'cb_kwargs' + + def adjust_request_args(self, args): + args['cb_kwargs'] = json.loads(' '.join(self.args)) + return args + + class ReturnsContract(Contract): """ Contract to check the output of a callback diff --git a/scrapy/settings/default_settings.py b/scrapy/settings/default_settings.py index 5884dfc60..52a701edf 100644 --- a/scrapy/settings/default_settings.py +++ b/scrapy/settings/default_settings.py @@ -291,6 +291,7 @@ TELNETCONSOLE_PASSWORD = None SPIDER_CONTRACTS = {} SPIDER_CONTRACTS_BASE = { 'scrapy.contracts.default.UrlContract': 1, - 'scrapy.contracts.default.ReturnsContract': 2, - 'scrapy.contracts.default.ScrapesContract': 3, + 'scrapy.contracts.default.CallbackKeywordArgumentsContract': 2, + 'scrapy.contracts.default.ReturnsContract': 3, + 'scrapy.contracts.default.ScrapesContract': 4, }