Merge lp:~james-w/requestsplus/optional-elapsed into lp:requestsplus

Proposed by James Westby
Status: Merged
Approved by: James Westby
Approved revision: 12
Merged at revision: 11
Proposed branch: lp:~james-w/requestsplus/optional-elapsed
Merge into: lp:requestsplus
Diff against target: 90 lines (+32/-3)
2 files modified
requestsplus/__init__.py (+9/-2)
requestsplus/tests/__init__.py (+23/-1)
To merge this branch: bzr merge lp:~james-w/requestsplus/optional-elapsed
Reviewer Review Type Date Requested Status
Michael Nelson (community) Approve
Review via email: mp+239562@code.launchpad.net

Commit message

Don't rely on requests providing the elapsed attribute.

To post a comment you must log in.
12. By James Westby

Only set elapsed if requests doesn't.

Revision history for this message
Michael Nelson (michael.nelson) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'requestsplus/__init__.py'
2--- requestsplus/__init__.py 2014-10-22 19:19:54 +0000
3+++ requestsplus/__init__.py 2014-10-24 13:47:34 +0000
4@@ -1,4 +1,5 @@
5 from contextlib import contextmanager
6+from datetime import datetime
7
8 from requests import Session as _Session
9
10@@ -36,7 +37,13 @@
11 kwargs.setdefault('headers', {})
12 kwargs['headers'][REQUEST_ID_HEADER] = request_id
13 with maybe_timeline(self.timeline_factory, method, url) as action:
14+ start_time = datetime.utcnow()
15 resp = super(Session, self).request(method, url, **kwargs)
16+ if getattr(resp, 'elapsed', None) is None:
17+ # Older requests doesn't record elapsed, so we fake it.
18+ # We can drop this when we make requests 1.2 the minimum
19+ # version
20+ resp.elapsed = datetime.utcnow() - start_time
21 if action is not None:
22 action.detail += " {}".format(resp.status_code)
23 if self.logger:
24@@ -90,11 +97,11 @@
25
26 logger.info(
27 "%(method)s %(url)s returned %(status_code)s "
28- "in %(duration)s %(extra)s",
29+ "in %(duration)sms %(extra)s",
30 dict(method=request.method,
31 url=request.url,
32 status_code=response.status_code,
33- duration=str(response.elapsed),
34+ duration=int(response.elapsed.total_seconds()*1000),
35 extra=["{}={}".format(key, value)
36 for key, value in sorted(extra.items())],
37 )
38
39=== modified file 'requestsplus/tests/__init__.py'
40--- requestsplus/tests/__init__.py 2014-10-22 19:19:54 +0000
41+++ requestsplus/tests/__init__.py 2014-10-24 13:47:34 +0000
42@@ -8,6 +8,7 @@
43 Request,
44 Response,
45 )
46+from requests.adapters import HTTPAdapter
47 from timeline import Timeline
48
49 from .. import (
50@@ -192,6 +193,14 @@
51 self.assertEqual(request_id, get_request_id(request))
52
53
54+class NoElapsedAdapter(HTTPAdapter):
55+
56+ def build_response(self, req, resp):
57+ resp = super(NoElapsedAdapter, self).build_response(req, resp)
58+ del resp.elapsed
59+ return resp
60+
61+
62 class SessionTests(TestCase):
63
64 def test_sends_request_id_header(self):
65@@ -253,7 +262,7 @@
66 s.get('http://localhost')
67 self.assertEqual(
68 "GET http://localhost/ returned 200 "
69- "in 0:00:00 ['Content-Type=text/plain']\n",
70+ "in 0ms ['Content-Type=text/plain']\n",
71 log_capture.output)
72
73 def test_uses_timeline_factory(self):
74@@ -280,3 +289,16 @@
75 with responses:
76 s.get(url)
77 self.assertEqual(4, len(statsd.timings))
78+
79+ def test_missing_elapsed_attr(self):
80+ # Old versions of requests don't have response.elapsed
81+ # so we have to work around it.
82+ statsd = MockStatsd()
83+ s = Session(statsd=statsd, statsd_prefix='a')
84+ s.mount('http://', NoElapsedAdapter())
85+ responses = RequestsMock()
86+ url = 'http://localhost'
87+ responses.add('GET', url)
88+ with responses:
89+ s.get(url)
90+ self.assertEqual(4, len(statsd.timings))

Subscribers

People subscribed via source and target branches