Merge ~chad.smith/cloud-init:unittest-oauthlib-import into cloud-init:master

Proposed by Chad Smith
Status: Merged
Approved by: Scott Moser
Approved revision: b1a44ee8f90214d348198c6bd81288e4888acbef
Merged at revision: b931a6473ee929193c0048640bf34876ce831a15
Proposed branch: ~chad.smith/cloud-init:unittest-oauthlib-import
Merge into: cloud-init:master
Diff against target: 79 lines (+43/-7)
3 files modified
cloudinit/tests/__init__.py (+0/-0)
cloudinit/tests/test_url_helper.py (+40/-0)
cloudinit/url_helper.py (+3/-7)
Reviewer Review Type Date Requested Status
Scott Moser Approve
Server Team CI bot continuous-integration Approve
Review via email: mp+329872@code.launchpad.net

Description of the change

url_helper: dynamically import oauthlib import from inside oauth_headers

oauth_headers is the only function which requires oauthlib, move the
import and ImportError handling inside this function to only attempt
loading at runtime if called. This will allow us to build on platforms
that don't have python-oauthlib installed by default. Add simple unittests
around the missing oauthlib dependencies to make sure the function
performs as intended and raises and NotImplementedError if oauthlib can't
be imported.

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

FAILED: Continuous integration, rev:87973cd2f2bbaed380c01dbb082246d90a76446d
https://jenkins.ubuntu.com/server/job/cloud-init-ci/226/
Executed test runs:
    SUCCESS: Checkout
    FAILED: Unit & Style Tests

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/226/rebuild

review: Needs Fixing (continuous-integration)
b1a44ee... by Chad Smith

flakes

Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:b1a44ee8f90214d348198c6bd81288e4888acbef
https://jenkins.ubuntu.com/server/job/cloud-init-ci/227/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    SUCCESS: MAAS Compatability Testing
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/227/rebuild

review: Approve (continuous-integration)
Revision history for this message
Scott Moser (smoser) wrote :

I approve.
the removal of the single time 'import' does make it somewhat slower, but oh well.

>>> timeit.timeit("bool(oauth1 is None)", setup="import oauthlib.oauth1 as oauth1")
0.2964163040742278
>>> timeit.timeit("import oauthlib.oauth1 as oauth1")
0.531060776906088

so its not all that bad. (that is 1M runs).

review: Approve
Revision history for this message
Scott Moser (smoser) wrote :

i further realized that my timeit didnt make any sense.
I was only testing the positive path. So that is slightly slower than comparing a boolean.

The "not available" path would probably be much slower, but we're not really ever going to be in a loop on that because the NotImplementedError will raise exception.

So... Approve. and I'll grab.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/cloudinit/tests/__init__.py b/cloudinit/tests/__init__.py
2new file mode 100644
3index 0000000..e69de29
4--- /dev/null
5+++ b/cloudinit/tests/__init__.py
6diff --git a/cloudinit/tests/test_url_helper.py b/cloudinit/tests/test_url_helper.py
7new file mode 100644
8index 0000000..349110d
9--- /dev/null
10+++ b/cloudinit/tests/test_url_helper.py
11@@ -0,0 +1,40 @@
12+# This file is part of cloud-init. See LICENSE file for license information.
13+
14+from cloudinit.url_helper import oauth_headers
15+from tests.unittests.helpers import CiTestCase, mock, skipIf
16+
17+
18+try:
19+ import oauthlib
20+ assert oauthlib # avoid pyflakes error F401: import unused
21+ _missing_oauthlib_dep = False
22+except ImportError:
23+ _missing_oauthlib_dep = True
24+
25+
26+class TestOAuthHeaders(CiTestCase):
27+
28+ def test_oauth_headers_raises_not_implemented_when_oathlib_missing(self):
29+ """oauth_headers raises a NotImplemented error when oauth absent."""
30+ with mock.patch.dict('sys.modules', {'oauthlib': None}):
31+ with self.assertRaises(NotImplementedError) as context_manager:
32+ oauth_headers(1, 2, 3, 4, 5)
33+ self.assertEqual(
34+ 'oauth support is not available',
35+ str(context_manager.exception))
36+
37+ @skipIf(_missing_oauthlib_dep, "No python-oauthlib dependency")
38+ @mock.patch('oauthlib.oauth1.Client')
39+ def test_oauth_headers_calls_oathlibclient_when_available(self, m_client):
40+ """oauth_headers calls oaut1.hClient.sign with the provided url."""
41+ class fakeclient(object):
42+ def sign(self, url):
43+ # The first and 3rd item of the client.sign tuple are ignored
44+ return ('junk', url, 'junk2')
45+
46+ m_client.return_value = fakeclient()
47+
48+ return_value = oauth_headers(
49+ 'url', 'consumer_key', 'token_key', 'token_secret',
50+ 'consumer_secret')
51+ self.assertEqual('url', return_value)
52diff --git a/cloudinit/url_helper.py b/cloudinit/url_helper.py
53index c83061a..0e0f5b4 100644
54--- a/cloudinit/url_helper.py
55+++ b/cloudinit/url_helper.py
56@@ -17,11 +17,6 @@ import time
57 from email.utils import parsedate
58 from functools import partial
59
60-try:
61- import oauthlib.oauth1 as oauth1
62-except ImportError:
63- oauth1 = None
64-
65 from requests import exceptions
66
67 from six.moves.urllib.parse import (
68@@ -492,8 +487,9 @@ class OauthUrlHelper(object):
69
70 def oauth_headers(url, consumer_key, token_key, token_secret, consumer_secret,
71 timestamp=None):
72-
73- if oauth1 is None:
74+ try:
75+ import oauthlib.oauth1 as oauth1
76+ except ImportError:
77 raise NotImplementedError('oauth support is not available')
78
79 if timestamp:

Subscribers

People subscribed via source and target branches