Merge lp:~brian.curtin/ubuntu-sso-client/remove-SyncTimestampChecker into lp:ubuntu-sso-client

Proposed by Brian Curtin on 2012-08-08
Status: Merged
Approved by: Alejandro J. Cura on 2012-08-14
Approved revision: 997
Merged at revision: 991
Proposed branch: lp:~brian.curtin/ubuntu-sso-client/remove-SyncTimestampChecker
Merge into: lp:ubuntu-sso-client
Diff against target: 360 lines (+8/-277)
3 files modified
ubuntu_sso/tests/test_account.py (+8/-2)
ubuntu_sso/utils/__init__.py (+0/-104)
ubuntu_sso/utils/tests/test_common.py (+0/-171)
To merge this branch: bzr merge lp:~brian.curtin/ubuntu-sso-client/remove-SyncTimestampChecker
Reviewer Review Type Date Requested Status
Alejandro J. Cura (community) 2012-08-08 Approve on 2012-08-14
Mike McCracken (community) Approve on 2012-08-14
Review via email: mp+118826@code.launchpad.net

Commit Message

- Remove SyncTimestampChecker as it is no longer used.

Description of the Change

While discussing issues holding back a Python 3 branch, it was found that SyncTimestampChecker and its associated uses and tests should be removed. It has been covered by webclient for some time.

To post a comment you must log in.
Alejandro J. Cura (alecu) wrote :

The branch looks very good.
Please remove also the associated imports used in this code.

review: Needs Fixing
991. By Brian Curtin on 2012-08-08

Remove unused code and imports

992. By Brian Curtin on 2012-08-08

Remove unused imports

993. By Brian Curtin on 2012-08-08

Patch the urlopen function from within urllib2/urllib.request itself, rather than depending on it having been imported in utils

Brian Curtin (brian.curtin) wrote :

The above three changes should have this taken care of. I removed a bunch of unused imports from the code and tests, and then changed the way another test was depending on a now removed import.

Note: none of those unused imports were showing up in my lint warnings, so if you find anymore, please let me know where they are.

994. By Brian Curtin on 2012-08-09

Removed unused time import

995. By Brian Curtin on 2012-08-09

Fix redefined name warnings, unused utils import

Alejandro J. Cura (alecu) wrote :

Pylint keeps complaining like this:

ubuntu_sso/tests/test_account.py:
    40: [F0401] Unable to import 'urllib.request'
    40: [E0611] No name 'request' in module 'urllib'
    107: [W0621, FakeWebClient.request] Redefining name 'url' from outer scope (line 40)
    220: [W0621, AccountTestCase.setUp.fake_urlopen] Redefining name 'url' from outer scope (line 40)

review: Needs Fixing
996. By Brian Curtin on 2012-08-14

Add lint warning disable/enable pairs

997. By Brian Curtin on 2012-08-14

Rename import so it doesn't cause redefinition collisions

Mike McCracken (mikemc) wrote :

+1 - tests pass, and after some diffing and futzing with pyflakes and pylint I determined that this branch doesn't add any pyflakes complaints that weren't in trunk, and we don't care about pylint anymore.

review: Approve
Alejandro J. Cura (alecu) wrote :

Looks good, and no pylint warnings now.

review: Approve
Alejandro J. Cura (alecu) wrote :

> +1 - tests pass, and after some diffing and futzing with pyflakes and pylint I
> determined that this branch doesn't add any pyflakes complaints that weren't
> in trunk, and we don't care about pylint anymore.

@mmcc: afaict, we still use pylint in this project; though we do use pyflakes elsewhere.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ubuntu_sso/tests/test_account.py'
2--- ubuntu_sso/tests/test_account.py 2012-07-25 20:56:33 +0000
3+++ ubuntu_sso/tests/test_account.py 2012-08-14 16:26:21 +0000
4@@ -35,11 +35,17 @@
5
6 import os
7
8+# pylint: disable=W0621,F0401,E0611
9+try:
10+ import urllib.request as url_lib
11+except ImportError:
12+ import urllib2 as url_lib
13+# pylint: enable=W0621,F0401,E0611
14+
15 from twisted.trial.unittest import TestCase
16 from twisted.internet import defer
17
18 from ubuntu_sso import account
19-from ubuntu_sso import utils
20 from ubuntu_sso.account import (
21 Account,
22 AuthenticationError,
23@@ -217,7 +223,7 @@
24 self.addCleanup(f.close)
25 return f
26
27- self.patch(utils, 'urlopen', fake_urlopen) # fd to the path
28+ self.patch(url_lib, 'urlopen', fake_urlopen) # fd to the path
29 self.processor = Account()
30 self.register_kwargs = dict(email=EMAIL, password=PASSWORD,
31 displayname=NAME,
32
33=== modified file 'ubuntu_sso/utils/__init__.py'
34--- ubuntu_sso/utils/__init__.py 2012-07-13 20:45:14 +0000
35+++ ubuntu_sso/utils/__init__.py 2012-08-14 16:26:21 +0000
36@@ -28,22 +28,10 @@
37 # files in the program, then also delete it here.
38 """Utility modules that may find use outside ubuntu_sso."""
39
40-import cgi
41 import os
42 import sys
43-import time
44
45 from dirspec.utils import get_program_path
46-from oauth import oauth
47-
48-try:
49- # pylint: disable=E0611,F0401
50- from urllib.parse import urlparse
51- from urllib.request import Request, urlopen
52- # pylint: enable=E0611,F0401
53-except ImportError:
54- from urlparse import urlparse
55- from urllib2 import Request, urlopen
56
57 from twisted.internet import defer
58
59@@ -150,98 +138,6 @@
60 return cmd_args
61
62
63-class RequestHead(Request):
64- """A request with the method set to HEAD."""
65-
66- _request_method = "HEAD"
67-
68- def get_method(self):
69- """Return the desired method."""
70- return self._request_method
71-
72-
73-class SyncTimestampChecker(object):
74- """A timestamp that's regularly checked with a server."""
75-
76- CHECKING_INTERVAL = 60 * 60 # in seconds
77- ERROR_INTERVAL = 30 # in seconds
78- SERVER_URL = "http://one.ubuntu.com/api/time"
79-
80- def __init__(self):
81- """Initialize this instance."""
82- self.next_check = time.time()
83- self.skew = 0
84-
85- def get_server_time(self):
86- """Get the time at the server."""
87- headers = {"Cache-Control": "no-cache"}
88- request = RequestHead(self.SERVER_URL, headers=headers)
89- response = urlopen(request)
90- date_string = response.info()["Date"]
91- # delay import, otherwise a default reactor gets installed
92- from twisted.web import http
93- timestamp = http.stringToDatetime(date_string)
94- return timestamp
95-
96- def get_faithful_time(self):
97- """Get an accurate timestamp."""
98- local_time = time.time()
99- if local_time >= self.next_check:
100- try:
101- server_time = self.get_server_time()
102- self.next_check = local_time + self.CHECKING_INTERVAL
103- self.skew = server_time - local_time
104- logger.debug("Calculated server-local time skew: %r",
105- self.skew)
106- #pylint: disable=W0703
107- except Exception as server_error:
108- logger.debug("Error while verifying the server time skew: %r",
109- server_error)
110- self.next_check = local_time + self.ERROR_INTERVAL
111-
112- # delay import, otherwise a default reactor gets installed
113- from twisted.web import http
114- logger.debug("Using corrected timestamp: %r",
115- http.datetimeToString(local_time + self.skew))
116- return int(local_time + self.skew)
117-
118-
119-# pylint: disable=C0103
120-timestamp_checker = SyncTimestampChecker()
121-# pylint: enable=C0103
122-
123-
124-def oauth_headers(url, credentials, http_method='GET'):
125- """Sign 'url' using 'credentials'.
126-
127- * 'url' must be a valid unicode url.
128- * 'credentials' must be a valid OAuth token.
129-
130- Return oauth headers that can be pass to any Request like object.
131-
132- """
133- assert isinstance(url, unicode)
134- url = url.encode('utf-8')
135- _, _, _, _, query, _ = urlparse(url)
136- parameters = dict(cgi.parse_qsl(query))
137- parameters["oauth_timestamp"] = timestamp_checker.get_faithful_time()
138-
139- consumer = oauth.OAuthConsumer(credentials['consumer_key'],
140- credentials['consumer_secret'])
141- token = oauth.OAuthToken(credentials['token'],
142- credentials['token_secret'])
143- kwargs = dict(oauth_consumer=consumer, token=token,
144- http_method=http_method, http_url=url,
145- parameters=parameters)
146- get_request = oauth.OAuthRequest.from_consumer_and_token
147- oauth_req = get_request(**kwargs)
148- hmac_sha1 = oauth.OAuthSignatureMethod_HMAC_SHA1()
149- oauth_req.sign_request(hmac_sha1, consumer, token)
150- headers = oauth_req.to_header()
151-
152- return headers
153-
154-
155 @defer.inlineCallbacks
156 def ping_url(url, email, credentials):
157 """Ping the 'url' with the 'email' attached to it.
158
159=== modified file 'ubuntu_sso/utils/tests/test_common.py'
160--- ubuntu_sso/utils/tests/test_common.py 2012-07-12 15:54:13 +0000
161+++ ubuntu_sso/utils/tests/test_common.py 2012-08-14 16:26:21 +0000
162@@ -30,21 +30,14 @@
163
164 import logging
165 import sys
166-import time
167
168 from twisted.internet import defer
169-from twisted.internet.threads import deferToThread
170 from twisted.web import resource
171 from ubuntuone.devtools.handlers import MementoHandler
172 from ubuntuone.devtools.testing.txwebserver import HTTPWebServer
173
174 from ubuntu_sso import utils
175 from ubuntu_sso.tests import TestCase, EMAIL, TOKEN
176-from ubuntu_sso.utils import (
177- oauth,
178- oauth_headers,
179- SyncTimestampChecker,
180-)
181
182 CONSTANTS_MODULE = 'ubuntu_sso.constants'
183 NOT_DEFINED = object()
184@@ -188,97 +181,6 @@
185 self.assertEqual(expected, result)
186
187
188-class SignWithCredentialsTestCase(TestCase):
189- """Test suite for the oauth_headers method."""
190-
191- url = u'http://example.com'
192- fake_timestamp_value = 1
193-
194- @defer.inlineCallbacks
195- def setUp(self):
196- """Initialize this test suite."""
197- yield super(SignWithCredentialsTestCase, self).setUp()
198- self.timestamp_called = False
199-
200- def fake_timestamp():
201- """A fake timestamp that records the call."""
202- self.timestamp_called = True
203- return self.fake_timestamp_value
204-
205- self.patch(utils.timestamp_checker, "get_faithful_time",
206- fake_timestamp)
207-
208- def build_header(self, url, http_method='GET'):
209- """Build an Oauth header for comparison."""
210- consumer = oauth.OAuthConsumer(TOKEN['consumer_key'],
211- TOKEN['consumer_secret'])
212- token = oauth.OAuthToken(TOKEN['token'],
213- TOKEN['token_secret'])
214- get_request = oauth.OAuthRequest.from_consumer_and_token
215- oauth_req = get_request(oauth_consumer=consumer, token=token,
216- http_method=http_method, http_url=url)
217- oauth_req.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(),
218- consumer, token)
219- return oauth_req.to_header()
220-
221- def dictify_header(self, header):
222- """Convert an OAuth header into a dict."""
223- result = {}
224- fields = header.split(', ')
225- for field in fields:
226- key, value = field.split('=')
227- result[key] = value.strip('"')
228-
229- return result
230-
231- def assert_header_equal(self, expected, actual):
232- """Is 'expected' equals to 'actual'?"""
233- expected = self.dictify_header(expected['Authorization'])
234- actual = self.dictify_header(actual['Authorization'])
235- for header in (expected, actual):
236- header.pop('oauth_nonce')
237- header.pop('oauth_timestamp')
238- header.pop('oauth_signature')
239-
240- self.assertEqual(expected, actual)
241-
242- def assert_method_called(self, path, query_str='', http_method='GET'):
243- """Assert that the url build by joining 'paths' was called."""
244- expected = (self.url, path, query_str)
245- expected = ''.join(expected).encode('utf8')
246- expected = self.build_header(expected, http_method=http_method)
247- actual = oauth_headers(url=self.url + path, credentials=TOKEN)
248- self.assert_header_equal(expected, actual)
249-
250- def test_call(self):
251- """Calling 'get' triggers an OAuth signed GET request."""
252- path = u'/test/'
253- self.assert_method_called(path)
254-
255- def test_quotes_path(self):
256- """Calling 'get' quotes the path."""
257- path = u'/test me more, sí!/'
258- self.assert_method_called(path)
259-
260- def test_adds_parameters_to_oauth_request(self):
261- """The query string from the path is used in the oauth request."""
262- self.patch(oauth, 'OAuthRequest', FakedOAuthRequest)
263-
264- path = u'/test/something?foo=bar'
265- oauth_headers(url=self.url + path, credentials=TOKEN)
266-
267- self.assertIn('parameters', FakedOAuthRequest.params)
268- params = FakedOAuthRequest.params['parameters']
269- del(params["oauth_timestamp"])
270- self.assertEqual(params, {'foo': 'bar'})
271-
272- def test_oauth_headers_uses_timestamp_checker(self):
273- """The oauth_headers function uses the timestamp_checker."""
274- oauth_headers(u"http://protocultura.net", TOKEN)
275- self.assertTrue(self.timestamp_called,
276- "the timestamp MUST be requested.")
277-
278-
279 class RootResource(resource.Resource):
280 """A root resource that logs the number of calls."""
281
282@@ -312,79 +214,6 @@
283 """A mock, test, sample, and fake exception."""
284
285
286-class TimestampCheckerTestCase(TestCase):
287- """Tests for the timestamp checker."""
288-
289- @defer.inlineCallbacks
290- def setUp(self):
291- """Initialize a fake webserver."""
292- yield super(TimestampCheckerTestCase, self).setUp()
293- self.ws = MockWebServer()
294- self.ws.start()
295- self.addCleanup(self.ws.stop)
296- self.patch(SyncTimestampChecker, "SERVER_URL", self.ws.get_iri())
297-
298- @defer.inlineCallbacks
299- def test_returned_value_is_int(self):
300- """The returned value is an integer."""
301- checker = SyncTimestampChecker()
302- timestamp = yield deferToThread(checker.get_faithful_time)
303- self.assertEqual(type(timestamp), int)
304-
305- @defer.inlineCallbacks
306- def test_first_call_does_head(self):
307- """The first call gets the clock from our web."""
308- checker = SyncTimestampChecker()
309- yield deferToThread(checker.get_faithful_time)
310- self.assertEqual(self.ws.root.count, 1)
311-
312- @defer.inlineCallbacks
313- def test_second_call_is_cached(self):
314- """For the second call, the time is cached."""
315- checker = SyncTimestampChecker()
316- yield deferToThread(checker.get_faithful_time)
317- yield deferToThread(checker.get_faithful_time)
318- self.assertEqual(self.ws.root.count, 1)
319-
320- @defer.inlineCallbacks
321- def test_after_timeout_cache_expires(self):
322- """After some time, the cache expires."""
323- fake_timestamp = 1
324- self.patch(time, "time", lambda: fake_timestamp)
325- checker = SyncTimestampChecker()
326- yield deferToThread(checker.get_faithful_time)
327- fake_timestamp += SyncTimestampChecker.CHECKING_INTERVAL
328- yield deferToThread(checker.get_faithful_time)
329- self.assertEqual(self.ws.root.count, 2)
330-
331- @defer.inlineCallbacks
332- def test_server_date_sends_nocache_headers(self):
333- """Getting the server date sends the no-cache headers."""
334- checker = SyncTimestampChecker()
335- yield deferToThread(checker.get_server_time)
336- assert len(self.ws.root.request_headers) == 1
337- headers = self.ws.root.request_headers[0]
338- result = headers.getRawHeaders("Cache-Control")
339- self.assertEqual(result, ["no-cache"])
340-
341- @defer.inlineCallbacks
342- def test_server_error_means_skew_not_updated(self):
343- """When server can't be reached, the skew is not updated."""
344- fake_timestamp = 1
345- self.patch(time, "time", lambda: fake_timestamp)
346- checker = SyncTimestampChecker()
347-
348- def failing_get_server_time():
349- """Let's fail while retrieving the server time."""
350- raise FakedError()
351-
352- self.patch(checker, "get_server_time", failing_get_server_time)
353- yield deferToThread(checker.get_faithful_time)
354- self.assertEqual(checker.skew, 0)
355- self.assertEqual(checker.next_check,
356- fake_timestamp + SyncTimestampChecker.ERROR_INTERVAL)
357-
358-
359 class PingUrlTestCase(TestCase):
360 """Test suite for the URL pinging."""
361

Subscribers

People subscribed via source and target branches