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

Proposed by Brian Curtin
Status: Merged
Approved by: Alejandro J. Cura
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) Approve
Mike McCracken (community) Approve
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.
Revision history for this message
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

Remove unused code and imports

992. By Brian Curtin

Remove unused imports

993. By Brian Curtin

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

Revision history for this message
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

Removed unused time import

995. By Brian Curtin

Fix redefined name warnings, unused utils import

Revision history for this message
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

Add lint warning disable/enable pairs

997. By Brian Curtin

Rename import so it doesn't cause redefinition collisions

Revision history for this message
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
Revision history for this message
Alejandro J. Cura (alecu) wrote :

Looks good, and no pylint warnings now.

review: Approve
Revision history for this message
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