diff --git a/httpretty/__init__.py b/httpretty/__init__.py index b8e2059..751198a 100644 --- a/httpretty/__init__.py +++ b/httpretty/__init__.py @@ -320,7 +320,6 @@ class fakesock(object): for matcher, value in HTTPretty._entries.items(): if matcher.matches(info): entries = value - info = matcher.info break if not entries: @@ -328,6 +327,13 @@ class fakesock(object): return self._entry = matcher.get_next_entry(method) + # Attach more info to the entry + # So the callback can be more clever about what to do + # This does also fix the case where the callback + # would be handed a compiled regex as uri instead of the + # real uri + self._entry.info = info + self._entry.request = request def debug(*a, **kw): frame = inspect.stack()[0][0] @@ -466,17 +472,23 @@ class Entry(Py3kObject): self.method = method self.uri = uri + self.info = None + self.request = None - if isinstance(body, types.FunctionType): - self.body = body(method, uri, headers) - else: - self.body = body + self.body_is_callable = False + if hasattr(body,"__call__"): + self.callable_body = body + self.body = None + self.body_is_callable = True + + self.body = body self.streaming = streaming - if not streaming: + if not streaming and not self.body_is_callable: self.body_length = len(self.body or '') else: self.body_length = 0 + self.adding_headers = adding_headers or {} self.forcing_headers = forcing_headers or {} self.status = int(status) @@ -543,8 +555,11 @@ class Entry(Py3kObject): headers.update(self.normalize_headers(self.adding_headers)) headers = self.normalize_headers(headers) - status = headers.get('status', self.status) + if self.body_is_callable: + status, headers, self.body = self.callable_body(self.request,self.info.full_url(),headers) + headers.update({'content-length':len(self.body)}) + string_list = [ 'HTTP/1.1 %d %s' % (status, STATUSES[status]), ] diff --git a/tests/functional/test_httplib2.py b/tests/functional/test_httplib2.py index 2f927fa..271b254 100644 --- a/tests/functional/test_httplib2.py +++ b/tests/functional/test_httplib2.py @@ -266,8 +266,8 @@ def test_callback_response(now): (u"HTTPretty should all a callback function to be set as the body with" " httplib2") - def request_callback(method, uri, headers): - return "The {0} response from {1}".format(decode_utf8(method), uri) + def request_callback(request, uri, headers): + return [200,headers,"The {0} response from {1}".format(decode_utf8(request.method), uri)] HTTPretty.register_uri( HTTPretty.GET, "https://api.yahoo.com/test", diff --git a/tests/functional/test_requests.py b/tests/functional/test_requests.py index b682927..bdf43d6 100644 --- a/tests/functional/test_requests.py +++ b/tests/functional/test_requests.py @@ -391,11 +391,11 @@ def test_multipart(): @httprettified @within(two=microseconds) def test_callback_response(now): - (u"HTTPretty should all a callback function to be set as the body with" + (u"HTTPretty should call a callback function and set its return value as the body of the response" " requests") - def request_callback(method, uri, headers): - return "The {0} response from {1}".format(decode_utf8(method), uri) + def request_callback(request, uri, headers): + return [200, headers,"The {0} response from {1}".format(decode_utf8(request.method), uri)] HTTPretty.register_uri( HTTPretty.GET, "https://api.yahoo.com/test", @@ -416,6 +416,72 @@ def test_callback_response(now): expect(response.text).to.equal("The POST response from https://api.yahoo.com/test_post") +@httprettified +@within(two=microseconds) +def test_callback_body_remains_callable_for_any_subsequent_requests(now): + (u"HTTPretty should call a callback function more than one" + " requests") + + def request_callback(request, uri, headers): + return [200, headers,"The {0} response from {1}".format(decode_utf8(request.method), uri)] + + HTTPretty.register_uri( + HTTPretty.GET, "https://api.yahoo.com/test", + body=request_callback) + + response = requests.get('https://api.yahoo.com/test') + expect(response.text).to.equal("The GET response from https://api.yahoo.com/test") + + response = requests.get('https://api.yahoo.com/test') + expect(response.text).to.equal("The GET response from https://api.yahoo.com/test") + +@httprettified +@within(two=microseconds) +def test_callback_setting_headers_and_status_response(now): + (u"HTTPretty should call a callback function and uses it retur tuple as status code, headers and body" + " requests") + + def request_callback(request, uri, headers): + headers.update({'a':'b'}) + return [418,headers,"The {0} response from {1}".format(decode_utf8(request.method), uri)] + + HTTPretty.register_uri( + HTTPretty.GET, "https://api.yahoo.com/test", + body=request_callback) + + response = requests.get('https://api.yahoo.com/test') + expect(response.text).to.equal("The GET response from https://api.yahoo.com/test") + expect(response.headers).to.have.key('a').being.equal("b") + expect(response.status_code).to.be(418) + + HTTPretty.register_uri( + HTTPretty.POST, "https://api.yahoo.com/test_post", + body=request_callback) + + response = requests.post( + "https://api.yahoo.com/test_post", + {"username": "gabrielfalcao"} + ) + + expect(response.text).to.equal("The POST response from https://api.yahoo.com/test_post") + expect(response.headers).to.have.key('a').being.equal("b") + expect(response.status_code).to.be(418) + +@httprettified +def test_httpretty_should_allow_registering_regexes_and_give_a_proper_match_to_the_callback(): + u"HTTPretty should allow registering regexes with requests and giva a proper match to the callback" + + HTTPretty.register_uri( + HTTPretty.GET, + re.compile("https://api.yipit.com/v1/deal;brand=(?P\w+)"), + body=lambda method,uri,headers: [200,headers,uri] + ) + + response = requests.get('https://api.yipit.com/v1/deal;brand=gap?first_name=chuck&last_name=norris') + + expect(response.text).to.equal('https://api.yipit.com/v1/deal;brand=gap?first_name=chuck&last_name=norris') + expect(HTTPretty.last_request.method).to.equal('GET') + expect(HTTPretty.last_request.path).to.equal('/v1/deal;brand=gap?first_name=chuck&last_name=norris') @httprettified def test_httpretty_should_allow_registering_regexes(): diff --git a/tests/functional/test_urllib2.py b/tests/functional/test_urllib2.py index 95b0490..b04cefb 100644 --- a/tests/functional/test_urllib2.py +++ b/tests/functional/test_urllib2.py @@ -285,8 +285,8 @@ def test_callback_response(now): (u"HTTPretty should all a callback function to be set as the body with" " urllib2") - def request_callback(method, uri, headers): - return "The {0} response from {1}".format(decode_utf8(method), uri) + def request_callback(request, uri, headers): + return [200, headers, "The {0} response from {1}".format(decode_utf8(request.method), uri)] HTTPretty.register_uri( HTTPretty.GET, "https://api.yahoo.com/test",