11import base64
22from datetime import datetime
3- import httplib
43import logging
54import socket
65import ssl
76import sys
8- from urllib import urlencode
9- from urlparse import urlsplit , urljoin
107from xml .etree import ElementTree
118
129import iso8601
13- import backports . ssl_match_hostname
10+ import six
1411
1512import recurly
1613import recurly .errors
1714from 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
1823
1924
2025class Money (object ):
@@ -46,7 +51,7 @@ def add_to_element(self, elem):
4651 for currency , amount in self .currencies .items ():
4752 currency_el = ElementTree .Element (currency )
4853 currency_el .attrib ['type' ] = 'integer'
49- currency_el .text = unicode (amount )
54+ currency_el .text = six . text_type (amount )
5055 elem .append (currency_el )
5156
5257 def __getitem__ (self , name ):
@@ -158,7 +163,7 @@ def page_for_value(cls, resp, value):
158163 page = cls (value )
159164 page .record_size = resp .getheader ('X-Records' )
160165 links = parse_link_value (resp .getheader ('Link' ))
161- for url , data in links .iteritems ():
166+ for url , data in six .iteritems (links ):
162167 if data .get ('rel' ) == 'start' :
163168 page .start_url = url
164169 if data .get ('rel' ) == 'next' :
@@ -167,9 +172,9 @@ def page_for_value(cls, resp, value):
167172 return page
168173
169174
170- class _ValidatedHTTPSConnection (httplib .HTTPSConnection ):
175+ class _ValidatedHTTPSConnection (http_client .HTTPSConnection ):
171176
172- """An `httplib .HTTPSConnection` that validates the SSL connection by
177+ """An `http_client .HTTPSConnection` that validates the SSL connection by
173178 requiring certificate validation and checking the connection's intended
174179 hostname again the validated certificate's possible hosts."""
175180
@@ -190,7 +195,7 @@ def connect(self):
190195 ca_certs = recurly .CA_CERTS_FILE )
191196
192197 # 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 )
194199
195200 self .sock = ssl_sock
196201
@@ -230,13 +235,13 @@ def __init__(self, **kwargs):
230235 except AttributeError :
231236 self .currency = recurly .DEFAULT_CURRENCY
232237
233- for key , value in kwargs .iteritems ():
238+ for key , value in six .iteritems (kwargs ):
234239 setattr (self , key , value )
235240
236241 @classmethod
237242 def http_request (cls , url , method = 'GET' , body = None , headers = None ):
238243 """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.
240245
241246 If the `body` argument is a `Resource` instance, it is serialized
242247 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):
250255 """
251256 urlparts = urlsplit (url )
252257 if urlparts .scheme != 'https' :
253- connection = httplib .HTTPConnection (urlparts .netloc )
258+ connection = http_client .HTTPConnection (urlparts .netloc )
254259 elif recurly .CA_CERTS_FILE is None :
255- connection = httplib .HTTPSConnection (urlparts .netloc )
260+ connection = http_client .HTTPSConnection (urlparts .netloc )
256261 else :
257262 connection = _ValidatedHTTPSConnection (urlparts .netloc )
258263
@@ -263,12 +268,12 @@ def http_request(cls, url, method='GET', body=None, headers=None):
263268 })
264269 if recurly .API_KEY is None :
265270 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 ( )
267272
268273 log = logging .getLogger ('recurly.http.request' )
269274 if log .isEnabledFor (logging .DEBUG ):
270275 log .debug ("%s %s HTTP/1.1" , method , url )
271- for header , value in headers .iteritems ():
276+ for header , value in six .iteritems (headers ):
272277 if header == 'Authorization' :
273278 value = '<redacted>'
274279 log .debug ("%s: %s" , header , value )
@@ -290,8 +295,11 @@ def http_request(cls, url, method='GET', body=None, headers=None):
290295 log = logging .getLogger ('recurly.http.response' )
291296 if log .isEnabledFor (logging .DEBUG ):
292297 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 )
295303 log .debug ('' )
296304
297305 return resp
@@ -306,7 +314,7 @@ def as_log_output(self):
306314 """
307315 elem = self .to_element ()
308316 for attrname in self .sensitive_attributes :
309- for sensitive_el in elem .getiterator (attrname ):
317+ for sensitive_el in elem .iter (attrname ):
310318 sensitive_el .text = 'XXXXXXXXXXXXXXXX'
311319 return ElementTree .tostring (elem , encoding = 'UTF-8' )
312320
@@ -341,7 +349,7 @@ def get(cls, uuid):
341349 @classmethod
342350 def element_for_url (cls , url ):
343351 """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
345353 resulting from a ``GET`` request to that URL."""
346354 response = cls .http_request (url )
347355 if response .status != 200 :
@@ -462,7 +470,7 @@ def element_for_value(cls, attrname, value):
462470 elif isinstance (value , Money ):
463471 value .add_to_element (el )
464472 else :
465- el .text = unicode (value )
473+ el .text = six . text_type (value )
466474
467475 return el
468476
@@ -641,7 +649,7 @@ def delete(self):
641649 @classmethod
642650 def raise_http_error (cls , response ):
643651 """Raise a `ResponseError` of the appropriate subclass in
644- reaction to the given `httplib .HTTPResponse`."""
652+ reaction to the given `http_client .HTTPResponse`."""
645653 response_xml = response .read ()
646654 logging .getLogger ('recurly.http.response' ).debug (response_xml )
647655 exc_class = recurly .errors .error_class_for_http_status (response .status )
@@ -661,7 +669,7 @@ def to_element(self):
661669 continue
662670
663671 if attrname in self .xml_attribute_attributes :
664- elem .attrib [attrname ] = unicode (value )
672+ elem .attrib [attrname ] = six . text_type (value )
665673 else :
666674 sub_elem = self .element_for_value (attrname , value )
667675 elem .append (sub_elem )
0 commit comments