Merge lp:~xnox/lazr.restfulclient/fixes into lp:lazr.restfulclient

Proposed by Dimitri John Ledkov on 2014-06-30
Status: Merged
Merged at revision: 137
Proposed branch: lp:~xnox/lazr.restfulclient/fixes
Merge into: lp:lazr.restfulclient
Diff against target: 743 lines (+84/-310)
9 files modified
buildout.cfg (+1/-1)
ez_setup.py (+0/-241)
setup.py (+6/-7)
src/lazr/restfulclient/_browser.py (+14/-23)
src/lazr/restfulclient/authorize/oauth.py (+2/-1)
src/lazr/restfulclient/resource.py (+22/-12)
src/lazr/restfulclient/tests/test_atomicfilecache.py (+29/-15)
src/lazr/restfulclient/tests/test_error.py (+2/-2)
src/lazr/restfulclient/tests/test_oauth.py (+8/-8)
To merge this branch: bzr merge lp:~xnox/lazr.restfulclient/fixes
Reviewer Review Type Date Requested Status
Barry Warsaw 2014-07-14 Needs Information on 2014-07-14
LAZR Developers 2014-06-30 Pending
Review via email: mp+224945@code.launchpad.net

Commit message

Simplify setup.py and fix one python3 syntax error.

To post a comment you must log in.
lp:~xnox/lazr.restfulclient/fixes updated on 2014-07-04
139. By Dimitri John Ledkov on 2014-06-30

SSLHandshakeError is gone in python3, add compat.

140. By Dimitri John Ledkov on 2014-07-03

Resurect bootstrap.py

141. By Dimitri John Ledkov on 2014-07-03

Depreciation warning readfp -> read_file

142. By Dimitri John Ledkov on 2014-07-03

Take 1 at unicode

143. By Dimitri John Ledkov on 2014-07-04

More stuff

144. By Dimitri John Ledkov on 2014-07-04

Distch six

145. By Dimitri John Ledkov on 2014-07-04

Fix standalone buildout

146. By Dimitri John Ledkov on 2014-07-04

drop unused things

147. By Dimitri John Ledkov on 2014-07-04

Revert to minimise diff

148. By Dimitri John Ledkov on 2014-07-04

url must be string

149. By Dimitri John Ledkov on 2014-07-04

More crap

Barry Warsaw (barry) wrote :

A few minor comments and one important question. (inline of course)

review: Needs Information
Dimitri John Ledkov (xnox) wrote :

Replied.

Barry Warsaw (barry) wrote :

On Jul 14, 2014, at 10:20 PM, Dimitri John Ledkov wrote:

>> try:
>> + from httplib2 import SSLHandshakeError
>> +except ImportError:
>> + from httplib2 import HttpLib2Error as SSLHandshakeError
>> +try:
>
>yes, it does. But it's only used to catch the error, and re-raise it with a
>helpful message that "there is an option to ignore ssl certificate
>errors". The actual class of the error has changed, but i believe the text of
>the error comes from the underlying library. This keeps compat in python2,
>and the worst case scenario the error is re-raised regardless.

So I had a look at the actual code where this is used. Ug.

>Maybe I should remove all error catching and thus not use either
>SSLHandshakeError nor HttpLib2Error?

That does seem better. Then release notes or documentation can describe
LP_DISABLE_SSL_CERTIFICATE_VALIDATION.

lp:~xnox/lazr.restfulclient/fixes updated on 2014-07-28
150. By Dimitri John Ledkov on 2014-07-28

Whitespace and review fixes, drop SSLHandshakeError handling.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'buildout.cfg'
2--- buildout.cfg 2012-06-19 13:28:22 +0000
3+++ buildout.cfg 2014-07-28 15:39:09 +0000
4@@ -17,7 +17,7 @@
5
6 [standalone_test]
7 recipe = zc.recipe.testrunner
8-eggs = lazr.restfulclient
9+eggs = lazr.restfulclient [test]
10 defaults = '--tests-pattern ^tests --exit-with-status --suite-name standalone_tests'.split()
11
12 [docs]
13
14=== removed file 'ez_setup.py'
15--- ez_setup.py 2010-03-24 15:14:12 +0000
16+++ ez_setup.py 1970-01-01 00:00:00 +0000
17@@ -1,241 +0,0 @@
18-#!python
19-"""Bootstrap setuptools installation
20-
21-If you want to use setuptools in your package's setup.py, just include this
22-file in the same directory with it, and add this to the top of your setup.py::
23-
24- from ez_setup import use_setuptools
25- use_setuptools()
26-
27-If you want to require a specific version of setuptools, set a download
28-mirror, or use an alternate download directory, you can do so by supplying
29-the appropriate options to ``use_setuptools()``.
30-
31-This file can also be run as a script to install or upgrade setuptools.
32-"""
33-import sys
34-DEFAULT_VERSION = "0.6c11"
35-DEFAULT_URL = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3]
36-
37-md5_data = {
38- 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
39- 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
40- 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',
41- 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',
42- 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',
43- 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',
44- 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',
45- 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',
46- 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',
47- 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',
48- 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27',
49- 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277',
50- 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa',
51- 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e',
52- 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e',
53- 'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f',
54- 'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2',
55- 'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc',
56- 'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167',
57- 'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64',
58- 'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d',
59- 'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20',
60- 'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab',
61- 'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53',
62- 'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2',
63- 'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e',
64- 'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372',
65- 'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902',
66- 'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de',
67- 'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b',
68-}
69-
70-import sys, os
71-
72-def _validate_md5(egg_name, data):
73- if egg_name in md5_data:
74- from md5 import md5
75- digest = md5(data).hexdigest()
76- if digest != md5_data[egg_name]:
77- print >>sys.stderr, (
78- "md5 validation of %s failed! (Possible download problem?)"
79- % egg_name
80- )
81- sys.exit(2)
82- return data
83-
84-
85-def use_setuptools(
86- version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
87- download_delay=15, min_version=None
88-):
89- """Automatically find/download setuptools and make it available on sys.path
90-
91- `version` should be a valid setuptools version number that is available
92- as an egg for download under the `download_base` URL (which should end with
93- a '/'). `to_dir` is the directory where setuptools will be downloaded, if
94- it is not already available. If `download_delay` is specified, it should
95- be the number of seconds that will be paused before initiating a download,
96- should one be required. If an older version of setuptools is installed,
97- this routine will print a message to ``sys.stderr`` and raise SystemExit in
98- an attempt to abort the calling script.
99- """
100- # Work around a hack in the ez_setup.py file from simplejson==1.7.3.
101- if min_version:
102- version = min_version
103-
104- was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules
105- def do_download():
106- egg = download_setuptools(version, download_base, to_dir, download_delay)
107- sys.path.insert(0, egg)
108- import setuptools; setuptools.bootstrap_install_from = egg
109- try:
110- import pkg_resources
111- except ImportError:
112- return do_download()
113- try:
114- pkg_resources.require("setuptools>="+version); return
115- except pkg_resources.VersionConflict, e:
116- if was_imported:
117- print >>sys.stderr, (
118- "The required version of setuptools (>=%s) is not available, and\n"
119- "can't be installed while this script is running. Please install\n"
120- " a more recent version first, using 'easy_install -U setuptools'."
121- "\n\n(Currently using %r)"
122- ) % (version, e.args[0])
123- sys.exit(2)
124- else:
125- del pkg_resources, sys.modules['pkg_resources'] # reload ok
126- return do_download()
127- except pkg_resources.DistributionNotFound:
128- return do_download()
129-
130-def download_setuptools(
131- version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
132- delay = 15
133-):
134- """Download setuptools from a specified location and return its filename
135-
136- `version` should be a valid setuptools version number that is available
137- as an egg for download under the `download_base` URL (which should end
138- with a '/'). `to_dir` is the directory where the egg will be downloaded.
139- `delay` is the number of seconds to pause before an actual download attempt.
140- """
141- import urllib2, shutil
142- egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
143- url = download_base + egg_name
144- saveto = os.path.join(to_dir, egg_name)
145- src = dst = None
146- if not os.path.exists(saveto): # Avoid repeated downloads
147- try:
148- from distutils import log
149- if delay:
150- log.warn("""
151----------------------------------------------------------------------------
152-This script requires setuptools version %s to run (even to display
153-help). I will attempt to download it for you (from
154-%s), but
155-you may need to enable firewall access for this script first.
156-I will start the download in %d seconds.
157-
158-(Note: if this machine does not have network access, please obtain the file
159-
160- %s
161-
162-and place it in this directory before rerunning this script.)
163----------------------------------------------------------------------------""",
164- version, download_base, delay, url
165- ); from time import sleep; sleep(delay)
166- log.warn("Downloading %s", url)
167- src = urllib2.urlopen(url)
168- # Read/write all in one block, so we don't create a corrupt file
169- # if the download is interrupted.
170- data = _validate_md5(egg_name, src.read())
171- dst = open(saveto,"wb"); dst.write(data)
172- finally:
173- if src: src.close()
174- if dst: dst.close()
175- return os.path.realpath(saveto)
176-
177-def main(argv, version=DEFAULT_VERSION):
178- """Install or upgrade setuptools and EasyInstall"""
179- try:
180- import setuptools
181- except ImportError:
182- egg = None
183- try:
184- egg = download_setuptools(version, delay=0)
185- sys.path.insert(0,egg)
186- from setuptools.command.easy_install import main
187- return main(list(argv)+[egg]) # we're done here
188- finally:
189- if egg and os.path.exists(egg):
190- os.unlink(egg)
191- else:
192- if setuptools.__version__ == '0.0.1':
193- print >>sys.stderr, (
194- "You have an obsolete version of setuptools installed. Please\n"
195- "remove it from your system entirely before rerunning this script."
196- )
197- sys.exit(2)
198-
199- req = "setuptools>="+version
200- import pkg_resources
201- try:
202- pkg_resources.require(req)
203- except pkg_resources.VersionConflict:
204- try:
205- from setuptools.command.easy_install import main
206- except ImportError:
207- from easy_install import main
208- main(list(argv)+[download_setuptools(delay=0)])
209- sys.exit(0) # try to force an exit
210- else:
211- if argv:
212- from setuptools.command.easy_install import main
213- main(argv)
214- else:
215- print "Setuptools version",version,"or greater has been installed."
216- print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
217-
218-def update_md5(filenames):
219- """Update our built-in md5 registry"""
220-
221- import re
222- from md5 import md5
223-
224- for name in filenames:
225- base = os.path.basename(name)
226- f = open(name,'rb')
227- md5_data[base] = md5(f.read()).hexdigest()
228- f.close()
229-
230- data = [" %r: %r,\n" % it for it in md5_data.items()]
231- data.sort()
232- repl = "".join(data)
233-
234- import inspect
235- srcfile = inspect.getsourcefile(sys.modules[__name__])
236- f = open(srcfile, 'rb'); src = f.read(); f.close()
237-
238- match = re.search("\nmd5_data = {\n([^}]+)}", src)
239- if not match:
240- print >>sys.stderr, "Internal error!"
241- sys.exit(2)
242-
243- src = src[:match.start(1)] + repl + src[match.end(1):]
244- f = open(srcfile,'w')
245- f.write(src)
246- f.close()
247-
248-
249-if __name__=='__main__':
250- if len(sys.argv)>2 and sys.argv[1]=='--md5update':
251- update_md5(sys.argv[2:])
252- else:
253- main(sys.argv[1:])
254-
255-
256-
257-
258-
259
260=== modified file 'setup.py'
261--- setup.py 2014-06-05 11:25:42 +0000
262+++ setup.py 2014-07-28 15:39:09 +0000
263@@ -16,9 +16,6 @@
264 # You should have received a copy of the GNU Lesser General Public License
265 # along with lazr.restfulclient. If not, see <http://www.gnu.org/licenses/>.
266
267-import ez_setup
268-ez_setup.use_setuptools()
269-
270 import sys
271 from setuptools import setup, find_packages
272
273@@ -45,6 +42,7 @@
274 namespace_packages=['lazr'],
275 packages=find_packages('src'),
276 package_dir={'':'src'},
277+ package_data={'lazr.restfulclient': ['version.txt']},
278 include_package_data=True,
279 zip_safe=False,
280 maintainer='LAZR Developers',
281@@ -56,11 +54,9 @@
282 license='LGPL v3',
283 install_requires=[
284 'httplib2',
285- 'lazr.authentication',
286 'oauth',
287 'setuptools',
288 'wadllib>=1.1.4',
289- 'wsgi_intercept',
290 ],
291 url='https://launchpad.net/lazr.restfulclient',
292 download_url= 'https://launchpad.net/lazr.restfulclient/+download',
293@@ -73,8 +69,11 @@
294 extras_require=dict(
295 docs=['Sphinx',
296 'z3c.recipe.sphinxdoc'],
297- test=['lazr.restful>=0.11.0',
298- 'van.testing'],
299+ test=[
300+ 'lazr.authentication',
301+ 'lazr.restful>=0.11.0',
302+ 'wsgi_intercept',
303+ ],
304 ),
305 test_suite='lazr.restfulclient.tests',
306 )
307
308=== modified file 'src/lazr/restfulclient/_browser.py'
309--- src/lazr/restfulclient/_browser.py 2014-06-05 11:25:42 +0000
310+++ src/lazr/restfulclient/_browser.py 2014-07-28 15:39:09 +0000
311@@ -41,7 +41,6 @@
312 from time import sleep
313 from httplib2 import (
314 Http,
315- SSLHandshakeError,
316 urlnorm,
317 )
318 try:
319@@ -86,7 +85,12 @@
320 """
321
322 try:
323- if re_url_scheme.match(filename):
324+ if isinstance(filename, unicode_type):
325+ filename_match = filename.encode('utf-8')
326+ else:
327+ filename_match = filename
328+
329+ if re_url_scheme.match(filename_match):
330 if isinstance(filename, bytes):
331 filename = filename.decode('utf-8')
332 filename = filename.encode('idna')
333@@ -97,8 +101,8 @@
334 if isinstance(filename, unicode_type):
335 filename = filename.encode('utf-8')
336 filemd5 = _md5(filename).hexdigest()
337- filename = re_url_scheme.sub("", filename)
338- filename = re_slash.sub(",", filename)
339+ filename = re_url_scheme.sub(b"", filename)
340+ filename = re_slash.sub(b",", filename)
341
342 # This is the part that we changed. In stock httplib2, the
343 # filename is trimmed if it's longer than 200 characters, and then
344@@ -118,7 +122,7 @@
345 maximum_length_before_md5_sum = maximum_filename_length - 32 - 1
346 if len(filename) > maximum_length_before_md5_sum:
347 filename=filename[:maximum_length_before_md5_sum]
348- return ",".join((filename, filemd5))
349+ return ",".join((filename.decode('utf-8'), filemd5))
350
351
352 def ssl_certificate_validation_disabled():
353@@ -162,7 +166,7 @@
354 def _request(self, conn, host, absolute_uri, request_uri, method, body,
355 headers, redirections, cachekey):
356 """Use the authorizer to authorize an outgoing request."""
357- if headers.has_key('authorization'):
358+ if 'authorization' in headers:
359 # There's an authorization header left over from a
360 # previous request that resulted in a redirect. Resources
361 # protected by OAuth or HTTP Digest must send a distinct
362@@ -308,7 +312,6 @@
363 key = key + '-' + self.request_media_type
364 return safename(key)
365
366-
367 def _getCachedHeader(self, uri, header):
368 """Retrieve a cached value for an HTTP header."""
369 (scheme, authority, request_uri, cachekey) = urlnorm(uri)
370@@ -370,25 +373,15 @@
371 "don't have the server-side permission to see.")
372
373 # Add extra headers for the request.
374- headers = {'Accept' : media_type}
375+ headers = {'Accept': media_type}
376 if self.user_agent is not None:
377 headers['User-Agent'] = self.user_agent
378 if isinstance(self._connection.cache, MultipleRepresentationCache):
379 self._connection.cache.request_media_type = media_type
380 if extra_headers is not None:
381 headers.update(extra_headers)
382- # Make the request.
383- try:
384- response, content = self._request_and_retry(
385- str(url), method=method, body=data, headers=headers)
386- except SSLHandshakeError, e:
387- msg = str(e)
388- if "SSL3_GET_SERVER_CERTIFICATE:certificate verify failed" in msg:
389- raise SSLHandshakeError(
390- "%s: perhaps set LP_DISABLE_SSL_CERTIFICATE_VALIDATION if "
391- "certificate validation failed and you genuinely trust the "
392- "remote server." % (e,))
393- raise
394+ response, content = self._request_and_retry(
395+ str(url), method=method, body=data, headers=headers)
396 if response.status == 304:
397 # The resource didn't change.
398 if content == '':
399@@ -447,10 +440,8 @@
400 wadl_type = 'application/vnd.sun.wadl+xml'
401 response, content = self._request(url, media_type=wadl_type)
402 url = str(url)
403- if not isinstance(url, bytes):
404- url = url.encode('utf-8')
405 if not isinstance(content, bytes):
406- content = content.encode('utf-8')
407+ content = content.encode('utf-8')
408 return Application(url, content)
409
410 def post(self, url, method_name, **kws):
411
412=== modified file 'src/lazr/restfulclient/authorize/oauth.py'
413--- src/lazr/restfulclient/authorize/oauth.py 2012-06-04 19:54:58 +0000
414+++ src/lazr/restfulclient/authorize/oauth.py 2014-07-28 15:39:09 +0000
415@@ -159,7 +159,8 @@
416 """
417 # Attempt to load the access token from the file.
418 parser = SafeConfigParser()
419- parser.readfp(readable_file)
420+ reader = getattr(parser, 'read_file', parser.readfp)
421+ reader(readable_file)
422 # Check the version number and extract the access token and
423 # secret. Then convert these to the appropriate instances.
424 if not parser.has_section(CREDENTIALS_FILE_VERSION):
425
426=== modified file 'src/lazr/restfulclient/resource.py'
427--- src/lazr/restfulclient/resource.py 2014-06-06 23:21:56 +0000
428+++ src/lazr/restfulclient/resource.py 2014-07-28 15:39:09 +0000
429@@ -55,6 +55,14 @@
430 import types
431 import urllib
432
433+import sys
434+if sys.version_info[0] >= 3:
435+ text_type = str
436+ binary_type = bytes
437+else:
438+ text_type = unicode
439+ binary_type = str
440+
441 from lazr.uri import URI
442 from wadllib.application import Resource as WadlResource
443
444@@ -371,7 +379,9 @@
445 if self._wadl_resource.representation is None:
446 # Get a representation of the linked resource.
447 representation = self._root._browser.get(self._wadl_resource)
448- representation = loads(unicode(representation))
449+ if isinstance(representation, binary_type):
450+ representation = representation.decode('utf-8')
451+ representation = loads(text_type(representation))
452
453 # In rare cases, the resource type served by the
454 # server conflicts with the type the client thought
455@@ -381,7 +391,7 @@
456 # XXX This should probably be moved into a hook method
457 # defined by Entry, since it's not relevant to other
458 # resource types.
459- if type(representation) == types.DictType:
460+ if isinstance(representation, dict):
461 type_link = representation['resource_type_link']
462 if (type_link is not None
463 and type_link != self._wadl_resource.type_url):
464@@ -521,7 +531,7 @@
465 url = str(self._root_uri.append(url))
466 document = self._browser.get(url)
467 try:
468- representation = loads(unicode(document))
469+ representation = loads(text_type(document))
470 except ValueError:
471 raise ValueError("%s doesn't serve a JSON document." % url)
472 type_link = representation.get("resource_type_link")
473@@ -574,7 +584,7 @@
474 # and option values (because JSON-encoding them will screw
475 # up wadllib's parameter validation). The option value thing
476 # is a little hacky, but it's the best solution for now.
477- if not key in send_as_is_params:
478+ if key not in send_as_is_params:
479 args[key] = dumps(value, cls=DatetimeJSONEncoder)
480 if http_method in ('get', 'head', 'delete'):
481 url = self.wadl_method.build_request_url(**args)
482@@ -616,7 +626,7 @@
483 HeaderDictionary(response))
484 wadl_parameter = wadl_response.get_parameter('Location')
485 wadl_resource = wadl_parameter.linked_resource
486- # Fetch a representation of the new resource.
487+ # Fetch a representation of the new resource.
488 response, content = self.root._browser._request(
489 wadl_resource.url)
490 # Return an instance of the appropriate lazr.restful
491@@ -637,13 +647,13 @@
492 # The operation returned a document with nothing
493 # special about it.
494 if content_type == self.JSON_MEDIA_TYPE:
495- return loads(unicode(content))
496+ return loads(text_type(content))
497 # We don't know how to process the content.
498 return content
499
500 # The operation returned a representation of some
501 # resource. Instantiate a Resource object for it.
502- document = loads(unicode(content))
503+ document = loads(text_type(content))
504 if document is None:
505 # The operation returned a null value.
506 return document
507@@ -767,7 +777,7 @@
508 if response.status == 209 and content_type == self.JSON_MEDIA_TYPE:
509 # The server sent back a new representation of the object.
510 # Use it in preference to the existing representation.
511- new_representation = loads(unicode(content))
512+ new_representation = loads(text_type(content))
513 self._wadl_resource.representation = new_representation
514 self._wadl_resource.media_type = content_type
515
516@@ -786,7 +796,7 @@
517 :rtype: int
518 """
519 total_size = self.total_size
520- if type(total_size) == types.IntType:
521+ if isinstance(total_size, int):
522 # The size was a number present in the collection
523 # representation.
524 return total_size
525@@ -813,7 +823,7 @@
526 if next_link is None:
527 break
528 current_page = loads(
529- unicode(self._root._browser.get(URI(next_link))))
530+ text_type(self._root._browser.get(URI(next_link))))
531
532 def __getitem__(self, key):
533 """Look up a slice, or a subordinate resource by index.
534@@ -886,7 +896,7 @@
535 # Iterate over pages until we have the correct number of entries.
536 while more_needed > 0 and page_url is not None:
537 representation = loads(
538- unicode(self._root._browser.get(page_url)))
539+ text_type(self._root._browser.get(page_url)))
540 current_page_entries = representation['entries']
541 entry_dicts += current_page_entries[:more_needed]
542 more_needed = desired_size - len(entry_dicts)
543@@ -1011,7 +1021,7 @@
544 # the resource describes itself.
545 try:
546 representation = loads(
547- unicode(self._root._browser.get(url)))
548+ text_type(self._root._browser.get(url)))
549 except HTTPError as error:
550 # There's no resource corresponding to the given ID.
551 if error.response.status == 404:
552
553=== modified file 'src/lazr/restfulclient/tests/test_atomicfilecache.py'
554--- src/lazr/restfulclient/tests/test_atomicfilecache.py 2012-06-04 19:54:58 +0000
555+++ src/lazr/restfulclient/tests/test_atomicfilecache.py 2014-07-28 15:39:09 +0000
556@@ -23,6 +23,13 @@
557 import tempfile
558 import unittest
559
560+import sys
561+PY3 = sys.version_info[0] >= 3
562+if PY3:
563+ binary_type = bytes
564+else:
565+ binary_type = str
566+
567 import httplib2
568
569 from lazr.restfulclient._browser import AtomicFileCache
570@@ -56,15 +63,15 @@
571 def test_set_key(self):
572 # A key set with set() can be got by get().
573 cache = self.make_file_cache()
574- cache.set('key', 'value')
575- self.assertEqual('value', cache.get('key'))
576+ cache.set('key', b'value')
577+ self.assertEqual(b'value', cache.get('key'))
578
579 def test_set_twice_overrides(self):
580 # Setting a key again overrides the value.
581 cache = self.make_file_cache()
582- cache.set('key', 'value')
583- cache.set('key', 'new-value')
584- self.assertEqual('new-value', cache.get('key'))
585+ cache.set('key', b'value')
586+ cache.set('key', b'new-value')
587+ self.assertEqual(b'new-value', cache.get('key'))
588
589 def test_delete_absent_key(self):
590 # Deleting a key that's not there does nothing.
591@@ -76,7 +83,7 @@
592 # A key once set can be deleted. Further attempts to get that key
593 # return None.
594 cache = self.make_file_cache()
595- cache.set('key', 'value')
596+ cache.set('key', b'value')
597 cache.delete('key')
598 self.assertIs(None, cache.get('key'))
599
600@@ -101,7 +108,7 @@
601 # probably a bug in httplib2.FileCache.
602 cache = self.make_file_cache()
603 self.assertRaises(TypeError, cache.set, 'answer', 42)
604- self.assertEqual('', cache.get('answer'))
605+ self.assertEqual(b'', cache.get('answer'))
606
607 def test_get_unicode(self):
608 # get() can retrieve unicode keys.
609@@ -110,19 +117,20 @@
610
611 def test_set_unicode_keys(self):
612 cache = self.make_file_cache()
613- cache.set(self.unicode_text, 'value')
614- self.assertEqual('value', cache.get(self.unicode_text))
615+ cache.set(self.unicode_text, b'value')
616+ self.assertEqual(b'value', cache.get(self.unicode_text))
617
618 def test_set_unicode_value(self):
619 # set() cannot store unicode values. Values must be bytes.
620 cache = self.make_file_cache()
621+ error = TypeError if PY3 else UnicodeEncodeError
622 self.assertRaises(
623- UnicodeEncodeError, cache.set, 'key', self.unicode_text)
624+ error, cache.set, 'key', self.unicode_text)
625
626 def test_delete_unicode(self):
627 # delete() can remove unicode keys.
628 cache = self.make_file_cache()
629- cache.set(self.unicode_text, 'value')
630+ cache.set(self.unicode_text, b'value')
631 cache.delete(self.unicode_text)
632 self.assertIs(None, cache.get(self.unicode_text))
633
634@@ -132,6 +140,12 @@
635
636 file_cache_factory = AtomicFileCache
637
638+ @staticmethod
639+ def prefix_safename(x):
640+ if isinstance(x, binary_type):
641+ x = x.decode('utf-8')
642+ return AtomicFileCache.TEMPFILE_PREFIX + x
643+
644 def test_set_non_string_value(self):
645 # set() raises TypeError if asked to set a key to a non-string value.
646 # Attempts to retrieve that value act is if it were never set.
647@@ -144,16 +158,16 @@
648 # Implementation-specific tests follow.
649
650 def test_bad_safename_get(self):
651- safename = lambda x: AtomicFileCache.TEMPFILE_PREFIX + x
652+ safename = self.prefix_safename
653 cache = AtomicFileCache(self.cache_dir, safename)
654 self.assertRaises(ValueError, cache.get, 'key')
655
656 def test_bad_safename_set(self):
657- safename = lambda x: AtomicFileCache.TEMPFILE_PREFIX + x
658+ safename = self.prefix_safename
659 cache = AtomicFileCache(self.cache_dir, safename)
660- self.assertRaises(ValueError, cache.set, 'key', 'value')
661+ self.assertRaises(ValueError, cache.set, 'key', b'value')
662
663 def test_bad_safename_delete(self):
664- safename = lambda x: AtomicFileCache.TEMPFILE_PREFIX + x
665+ safename = self.prefix_safename
666 cache = AtomicFileCache(self.cache_dir, safename)
667 self.assertRaises(ValueError, cache.delete, 'key')
668
669=== modified file 'src/lazr/restfulclient/tests/test_error.py'
670--- src/lazr/restfulclient/tests/test_error.py 2010-07-19 14:15:11 +0000
671+++ src/lazr/restfulclient/tests/test_error.py 2014-07-28 15:39:09 +0000
672@@ -39,10 +39,10 @@
673 request = DummyRequest(status)
674 error = error_for(request, content)
675 if expected_error is None:
676- self.assertEquals(error, None)
677+ self.assertIsNone(error)
678 else:
679 self.assertTrue(isinstance(error, expected_error))
680- self.assertEquals(content, error.content)
681+ self.assertEqual(content, error.content)
682
683 def test_no_error_for_2xx(self):
684 """Make sure a 2xx response code yields no error."""
685
686=== modified file 'src/lazr/restfulclient/tests/test_oauth.py'
687--- src/lazr/restfulclient/tests/test_oauth.py 2010-10-28 22:22:32 +0000
688+++ src/lazr/restfulclient/tests/test_oauth.py 2014-07-28 15:39:09 +0000
689@@ -39,14 +39,14 @@
690
691 def test_data_fields(self):
692 consumer = Consumer("key", "secret", "application")
693- self.assertEquals(consumer.key, "key")
694- self.assertEquals(consumer.secret, "secret")
695- self.assertEquals(consumer.application_name, "application")
696+ self.assertEqual(consumer.key, "key")
697+ self.assertEqual(consumer.secret, "secret")
698+ self.assertEqual(consumer.application_name, "application")
699
700 def test_default_application_name(self):
701 # Application name defaults to None
702 consumer = Consumer("key", "secret")
703- self.assertEquals(consumer.application_name, None)
704+ self.assertEqual(consumer.application_name, None)
705
706
707 class TestSystemWideConsumer(unittest.TestCase):
708@@ -105,7 +105,7 @@
709 self._set_platform(('Fooix', 'String2', 'String3'), 'FooOS')
710 self._set_hostname("foo")
711 consumer = oauth.SystemWideConsumer("app name")
712- self.assertEquals(
713+ self.assertEqual(
714 consumer.key, 'System-wide: Fooix (foo)')
715
716 def test_empty_linux_distribution(self):
717@@ -115,7 +115,7 @@
718 self._set_platform(('', '', ''), 'BarOS')
719 self._set_hostname("bar")
720 consumer = oauth.SystemWideConsumer("app name")
721- self.assertEquals(
722+ self.assertEqual(
723 consumer.key, 'System-wide: BarOS (bar)')
724
725 def test_broken_linux_distribution(self):
726@@ -125,7 +125,7 @@
727 self._set_platform(self._broken, 'BazOS')
728 self._set_hostname("baz")
729 consumer = oauth.SystemWideConsumer("app name")
730- self.assertEquals(
731+ self.assertEqual(
732 consumer.key, 'System-wide: BazOS (baz)')
733
734
735@@ -150,7 +150,7 @@
736
737 # Make sure the file is readable and writable by the user, but
738 # not by anyone else.
739- self.assertEquals(stat.S_IMODE(os.stat(credentials_path).st_mode),
740+ self.assertEqual(stat.S_IMODE(os.stat(credentials_path).st_mode),
741 stat.S_IREAD | stat.S_IWRITE)
742
743 loaded_credentials = OAuthAuthorizer.load_from_path(credentials_path)

Subscribers

People subscribed via source and target branches