Merge lp:~barry/piston-mini-client/lp1077083 into lp:piston-mini-client

Proposed by Barry Warsaw on 2012-11-21
Status: Merged
Merged at revision: 65
Proposed branch: lp:~barry/piston-mini-client/lp1077083
Merge into: lp:piston-mini-client
Diff against target: 165 lines (+44/-27) 6 files modified
To merge this branch: bzr merge lp:~barry/piston-mini-client/lp1077083
Reviewer Review Type Date Requested Status
Michael Vogt 2012-11-21 Approve on 2012-11-27
Review via email: mp+135449@code.launchpad.net

Description of the Change

Switches from the long abandoned and not-Python-3-compatible python-oauth library to the well-supported-upstream and Python 3 compatible python-oauthlib library. Fixes a bogus dictionary order dependency which breaks Python 3.3. Re-enables a Python 3 test.

To post a comment you must log in.
Barry Warsaw (barry) wrote :

Note that you will have some trouble testing this on today's Raring. The problem is that tox is not yet in Raring (it will soon land in Debian and then be synced to Raring), and the python-virtualenv version that is currently in Raring is not compatible with Python 3.3. This should be fixed upstream today and will make it into Ubuntu shortly thereafter.

To test this on Raring, your best bet is to install virtualenv from upstream git (where the Python 3.3 bug is fixed), create a Python 2.7 and separate Python 3.3 virtualenvs, install the dependencies into them (via pip), and then run nosetests into the virtualenv.

Hopefully by next week you'll be able to just run `tox -e py27,py33` in Raring.

Michael Vogt (mvo) wrote :

Thanks for this branch. Looks good to me, +1

review: Approve
Anthony Lenton (elachuni) wrote :

Thanks Barry!!

Preview Diff

1=== modified file 'README'
2--- README 2012-07-31 16:33:45 +0000
3+++ README 2012-11-21 15:46:35 +0000
4@@ -29,8 +29,7 @@
5 tox
6
7 This will ensure the tests run on Python 2.6, 2.7 and 3.2, and the docs build
8-correctly. Tests pass against Python 3, but oauth tests are skipped as the
9-oauth module still doesn't have Python 3 support.
10+correctly.
11
12 Building the docs locally
13 =========================
14
15=== modified file 'doc/index.rst'
16--- doc/index.rst 2012-04-02 18:21:11 +0000
17+++ doc/index.rst 2012-11-21 15:46:35 +0000
18@@ -33,8 +33,8 @@
19
20 * It should have a small set of dependencies. We depend on httplib2 mainly
21 because it provides caching, but you should not need to install a pile of
22- packages just to use a rest client. Other dependencies like ``oauth`` and
23- ``socks`` are only imported if you need to use oauth authentication or
24+ packages just to use a rest client. Other dependencies like ``oauthlib``
25+ and ``socks`` are only imported if you need to use oauth authentication or
26 support proxies, respectively.
27
28 * Errors should be informative. Backtraces should point you in the right
29
30=== modified file 'piston_mini_client/auth.py'
31--- piston_mini_client/auth.py 2012-07-30 17:09:26 +0000
32+++ piston_mini_client/auth.py 2012-11-21 15:46:35 +0000
33@@ -8,11 +8,15 @@
34 instantiate a ``PistonAPI`` object.
35 """
36
37-from functools import wraps
38-
39 import base64
40
41
42+def _unicodeify(s):
43+ if isinstance(s, bytes):
44+ return s.decode('utf-8')
45+ return s
46+
47+
48 class OAuthAuthorizer(object):
49 """Authenticate to OAuth protected APIs."""
50 def __init__(self, token_key, token_secret, consumer_key, consumer_secret,
51@@ -23,25 +27,33 @@
52 ``consumer_secret`` are required for signing OAuth requests. The
53 ``oauth_realm`` to use is optional.
54 """
55- self.token_key = token_key
56- self.token_secret = token_secret
57- self.consumer_key = consumer_key
58- self.consumer_secret = consumer_secret
59+ # 2012-11-19 BAW: python-oauthlib requires unicodes for its tokens and
60+ # secrets. Assume utf-8 values.
61+ # https://github.com/idan/oauthlib/issues/68
62+ self.token_key = _unicodeify(token_key)
63+ self.token_secret = _unicodeify(token_secret)
64+ self.consumer_key = _unicodeify(consumer_key)
65+ self.consumer_secret = _unicodeify(consumer_secret)
66 self.oauth_realm = oauth_realm
67
68 def sign_request(self, url, method, body, headers):
69 """Sign a request with OAuth credentials."""
70- # Import oauth here so that you don't need it if you're not going
71+ # 2012-11-19 BAW: In order to preserve API backward compatibility,
72+ # convert empty string body to None. The old python-oauth library
73+ # would treat the empty string as "no body", but python-oauthlib
74+ # requires None.
75+ if not body:
76+ body = None
77+ # Import oauthlib here so that you don't need it if you're not going
78 # to use it. Plan B: move this out into a separate oauth module.
79- from oauth.oauth import (OAuthRequest, OAuthConsumer, OAuthToken,
80- OAuthSignatureMethod_PLAINTEXT)
81- consumer = OAuthConsumer(self.consumer_key, self.consumer_secret)
82- token = OAuthToken(self.token_key, self.token_secret)
83- oauth_request = OAuthRequest.from_consumer_and_token(
84- consumer, token, http_url=url)
85- oauth_request.sign_request(OAuthSignatureMethod_PLAINTEXT(),
86- consumer, token)
87- headers.update(oauth_request.to_header(self.oauth_realm))
88+ from oauthlib.oauth1 import Client, SIGNATURE_PLAINTEXT
89+ oauth_client = Client(self.consumer_key, self.consumer_secret,
90+ self.token_key, self.token_secret,
91+ signature_method=SIGNATURE_PLAINTEXT,
92+ realm=self.oauth_realm)
93+ uri, signed_headers, body = oauth_client.sign(
94+ url, method, body, headers)
95+ headers.update(signed_headers)
96
97
98 class BasicAuthorizer(object):
99
100=== modified file 'piston_mini_client/tests/test_auth.py'
101--- piston_mini_client/tests/test_auth.py 2012-07-30 17:09:26 +0000
102+++ piston_mini_client/tests/test_auth.py 2012-11-21 15:46:35 +0000
103@@ -2,7 +2,6 @@
104 # Copyright 2010-2012 Canonical Ltd. This software is licensed under the
105 # GNU Lesser General Public License version 3 (see the file LICENSE).
106
107-import sys
108 from piston_mini_client.auth import OAuthAuthorizer, BasicAuthorizer
109 from unittest import TestCase
110
111@@ -20,10 +19,6 @@
112
113 class OAuthAuthorizerTestCase(TestCase):
114 def test_sign_request(self):
115- if sys.version_info[0] == 3:
116- # Skip on Python 3 as oauth is still broken there.
117- # don't use skipIf as it's missing on python2.6
118- return
119 auth = OAuthAuthorizer('tkey', 'tsecret', 'ckey', 'csecret')
120 url = 'http://example.com/api'
121 headers = {}
122
123=== modified file 'piston_mini_client/tests/test_serializers.py'
124--- piston_mini_client/tests/test_serializers.py 2012-07-30 17:09:26 +0000
125+++ piston_mini_client/tests/test_serializers.py 2012-11-21 15:46:35 +0000
126@@ -7,6 +7,13 @@
127 from piston_mini_client.serializers import JSONSerializer, FormSerializer
128 from piston_mini_client import PistonSerializable
129
130+try:
131+ # Python 3.
132+ from urllib.parse import parse_qs
133+except ImportError:
134+ # Python 2.
135+ from urlparse import parse_qs
136+
137
138 class JSONSerializerTestCase(TestCase):
139 def test_simple_serialize(self):
140@@ -38,7 +45,11 @@
141
142 myarg = MySerializable(foo='baz', bar=42)
143 serializer = FormSerializer()
144- self.assertEqual('foo=baz&bar=42', serializer.serialize(myarg))
145+ # Argument order is undefined, so parse these into dictionaries which
146+ # can be compared.
147+ want = parse_qs('foo=baz&bar=42')
148+ got = parse_qs(serializer.serialize(myarg))
149+ self.assertEqual(want, got)
150
151 def test_serialize_nested(self):
152 # Maybe we should flatly refuse to serialize nested structures?
153
154=== modified file 'setup.py'
155--- setup.py 2012-09-24 13:22:12 +0000
156+++ setup.py 2012-11-21 15:46:35 +0000
157@@ -11,7 +11,7 @@
158 packages=['piston_mini_client'],
159 license='LGPLv3',
160 install_requires=[
161- 'oauth',
162+ 'oauthlib',
163 'httplib2',
164 ],
165 )

Subscribers

People subscribed via source and target branches