1
1
import base64
2
2
from datetime import datetime
3
- import httplib
4
3
import logging
5
4
import socket
6
5
import ssl
7
6
import sys
8
- from urllib import urlencode
9
- from urlparse import urlsplit , urljoin
10
7
from xml .etree import ElementTree
11
8
12
9
import iso8601
13
- import backports . ssl_match_hostname
10
+ import six
14
11
15
12
import recurly
16
13
import recurly .errors
17
14
from recurly .link_header import parse_link_value
15
+ from six .moves import http_client
16
+ from six .moves .urllib .parse import urlencode , urljoin , urlsplit
17
+
18
+
19
+ if six .PY3 :
20
+ from ssl import match_hostname
21
+ else :
22
+ from backports .ssl_match_hostname import match_hostname
18
23
19
24
20
25
class Money (object ):
@@ -46,7 +51,7 @@ def add_to_element(self, elem):
46
51
for currency , amount in self .currencies .items ():
47
52
currency_el = ElementTree .Element (currency )
48
53
currency_el .attrib ['type' ] = 'integer'
49
- currency_el .text = unicode (amount )
54
+ currency_el .text = six . text_type (amount )
50
55
elem .append (currency_el )
51
56
52
57
def __getitem__ (self , name ):
@@ -158,7 +163,7 @@ def page_for_value(cls, resp, value):
158
163
page = cls (value )
159
164
page .record_size = resp .getheader ('X-Records' )
160
165
links = parse_link_value (resp .getheader ('Link' ))
161
- for url , data in links .iteritems ():
166
+ for url , data in six .iteritems (links ):
162
167
if data .get ('rel' ) == 'start' :
163
168
page .start_url = url
164
169
if data .get ('rel' ) == 'next' :
@@ -167,9 +172,9 @@ def page_for_value(cls, resp, value):
167
172
return page
168
173
169
174
170
- class _ValidatedHTTPSConnection (httplib .HTTPSConnection ):
175
+ class _ValidatedHTTPSConnection (http_client .HTTPSConnection ):
171
176
172
- """An `httplib .HTTPSConnection` that validates the SSL connection by
177
+ """An `http_client .HTTPSConnection` that validates the SSL connection by
173
178
requiring certificate validation and checking the connection's intended
174
179
hostname again the validated certificate's possible hosts."""
175
180
@@ -190,7 +195,7 @@ def connect(self):
190
195
ca_certs = recurly .CA_CERTS_FILE )
191
196
192
197
# Let the CertificateError for failure be raised to the caller.
193
- backports . ssl_match_hostname . match_hostname (ssl_sock .getpeercert (), self .host )
198
+ match_hostname (ssl_sock .getpeercert (), self .host )
194
199
195
200
self .sock = ssl_sock
196
201
@@ -230,13 +235,13 @@ def __init__(self, **kwargs):
230
235
except AttributeError :
231
236
self .currency = recurly .DEFAULT_CURRENCY
232
237
233
- for key , value in kwargs .iteritems ():
238
+ for key , value in six .iteritems (kwargs ):
234
239
setattr (self , key , value )
235
240
236
241
@classmethod
237
242
def http_request (cls , url , method = 'GET' , body = None , headers = None ):
238
243
"""Make an HTTP request with the given method to the given URL,
239
- returning the resulting `httplib .HTTPResponse` instance.
244
+ returning the resulting `http_client .HTTPResponse` instance.
240
245
241
246
If the `body` argument is a `Resource` instance, it is serialized
242
247
to XML by calling its `to_element()` method before submitting it.
@@ -250,9 +255,9 @@ def http_request(cls, url, method='GET', body=None, headers=None):
250
255
"""
251
256
urlparts = urlsplit (url )
252
257
if urlparts .scheme != 'https' :
253
- connection = httplib .HTTPConnection (urlparts .netloc )
258
+ connection = http_client .HTTPConnection (urlparts .netloc )
254
259
elif recurly .CA_CERTS_FILE is None :
255
- connection = httplib .HTTPSConnection (urlparts .netloc )
260
+ connection = http_client .HTTPSConnection (urlparts .netloc )
256
261
else :
257
262
connection = _ValidatedHTTPSConnection (urlparts .netloc )
258
263
@@ -263,12 +268,12 @@ def http_request(cls, url, method='GET', body=None, headers=None):
263
268
})
264
269
if recurly .API_KEY is None :
265
270
raise recurly .UnauthorizedError ('recurly.API_KEY not set' )
266
- headers ['Authorization' ] = 'Basic %s' % base64 .b64encode ('%s:' % recurly .API_KEY )
271
+ headers ['Authorization' ] = 'Basic %s' % base64 .b64encode (six . b ( '%s:' % recurly .API_KEY )). decode ( )
267
272
268
273
log = logging .getLogger ('recurly.http.request' )
269
274
if log .isEnabledFor (logging .DEBUG ):
270
275
log .debug ("%s %s HTTP/1.1" , method , url )
271
- for header , value in headers .iteritems ():
276
+ for header , value in six .iteritems (headers ):
272
277
if header == 'Authorization' :
273
278
value = '<redacted>'
274
279
log .debug ("%s: %s" , header , value )
@@ -290,8 +295,11 @@ def http_request(cls, url, method='GET', body=None, headers=None):
290
295
log = logging .getLogger ('recurly.http.response' )
291
296
if log .isEnabledFor (logging .DEBUG ):
292
297
log .debug ("HTTP/1.1 %d %s" , resp .status , resp .reason )
293
- for header in resp .msg .headers :
294
- log .debug (header .rstrip ('\n ' ))
298
+ if six .PY2 :
299
+ for header in resp .msg .headers :
300
+ log .debug (header .rstrip ('\n ' ))
301
+ else :
302
+ log .debug (resp .msg ._headers )
295
303
log .debug ('' )
296
304
297
305
return resp
@@ -306,7 +314,7 @@ def as_log_output(self):
306
314
"""
307
315
elem = self .to_element ()
308
316
for attrname in self .sensitive_attributes :
309
- for sensitive_el in elem .getiterator (attrname ):
317
+ for sensitive_el in elem .iter (attrname ):
310
318
sensitive_el .text = 'XXXXXXXXXXXXXXXX'
311
319
return ElementTree .tostring (elem , encoding = 'UTF-8' )
312
320
@@ -341,7 +349,7 @@ def get(cls, uuid):
341
349
@classmethod
342
350
def element_for_url (cls , url ):
343
351
"""Return the resource at the given URL, as a
344
- (`httplib .HTTPResponse`, `xml.etree.ElementTree.Element`) tuple
352
+ (`http_client .HTTPResponse`, `xml.etree.ElementTree.Element`) tuple
345
353
resulting from a ``GET`` request to that URL."""
346
354
response = cls .http_request (url )
347
355
if response .status != 200 :
@@ -462,7 +470,7 @@ def element_for_value(cls, attrname, value):
462
470
elif isinstance (value , Money ):
463
471
value .add_to_element (el )
464
472
else :
465
- el .text = unicode (value )
473
+ el .text = six . text_type (value )
466
474
467
475
return el
468
476
@@ -641,7 +649,7 @@ def delete(self):
641
649
@classmethod
642
650
def raise_http_error (cls , response ):
643
651
"""Raise a `ResponseError` of the appropriate subclass in
644
- reaction to the given `httplib .HTTPResponse`."""
652
+ reaction to the given `http_client .HTTPResponse`."""
645
653
response_xml = response .read ()
646
654
logging .getLogger ('recurly.http.response' ).debug (response_xml )
647
655
exc_class = recurly .errors .error_class_for_http_status (response .status )
@@ -661,7 +669,7 @@ def to_element(self):
661
669
continue
662
670
663
671
if attrname in self .xml_attribute_attributes :
664
- elem .attrib [attrname ] = unicode (value )
672
+ elem .attrib [attrname ] = six . text_type (value )
665
673
else :
666
674
sub_elem = self .element_for_value (attrname , value )
667
675
elem .append (sub_elem )
0 commit comments