1- import bitly_http
21import hashlib
3- try :
4- import json
5- except ImportError :
6- import simplejson as json
2+ import json
73import sys
84import time
95import types
10- import urllib
116import warnings
127
8+ try :
9+ from urllib .request import build_opener , HTTPRedirectHandler
10+ from urllib .parse import urlencode
11+ from urllib .error import URLError , HTTPError
12+ string_types = str ,
13+ integer_types = int ,
14+ numeric_types = (int , float )
15+ text_type = str
16+ binary_type = bytes
17+ except ImportError as e :
18+ from urllib2 import build_opener , HTTPRedirectHandler , URLError , HTTPError
19+ from urllib import urlencode
20+ string_types = basestring ,
21+ integer_types = (int , long )
22+ numeric_types = (int , long , float )
23+ text_type = unicode
24+ binary_type = str
25+
26+
27+ class DontRedirect (HTTPRedirectHandler ):
28+ def redirect_response (self , req , fp , code , msg , headers , newurl ):
29+ if code in (301 , 302 , 303 , 307 ):
30+ raise HTTPError (req .get_full_url (), code , msg , headers , fp )
31+
1332
1433class Error (Exception ):
1534 pass
@@ -22,9 +41,9 @@ def __init__(self, code, message):
2241
2342
2443def _utf8 (s ):
25- if isinstance (s , unicode ):
44+ if isinstance (s , text_type ):
2645 s = s .encode ('utf-8' )
27- assert isinstance (s , str )
46+ assert isinstance (s , binary_type )
2847 return s
2948
3049
@@ -35,7 +54,7 @@ def _utf8_params(params):
3554 for k , v in params .items ():
3655 if v is None :
3756 continue
38- if isinstance (v , ( int , long , float ) ):
57+ if isinstance (v , numeric_types ):
3958 v = str (v )
4059 if isinstance (v , (list , tuple )):
4160 v = [_utf8 (x ) for x in v ]
@@ -314,26 +333,26 @@ def user_link_history(self, created_before=None, created_after=None,
314333 private = None ):
315334 params = dict ()
316335 if created_before is not None :
317- assert isinstance (limit , int )
336+ assert isinstance (limit , integer_types )
318337 params ["created_before" ] = created_before
319338 if created_after is not None :
320- assert isinstance (limit , int )
339+ assert isinstance (limit , integer_types )
321340 params ["created_after" ] = created_after
322341 if archived is not None :
323- assert isinstance (archived , str )
342+ assert isinstance (archived , string_types )
324343 archived = archived .lower ()
325344 assert archived is "on" or "off" or "both"
326345 params ["archived" ] = archived
327346 if private is not None :
328- assert isinstance (private , str )
347+ assert isinstance (private , string_types )
329348 private = private .lower ()
330349 assert private is "on" or "off" or "both"
331350 params ["private" ] = private
332351 if limit is not None :
333- assert isinstance (limit , int )
352+ assert isinstance (limit , integer_types )
334353 params ["limit" ] = str (limit )
335354 if offset is not None :
336- assert isinstance (offset , int )
355+ assert isinstance (offset , integer_types )
337356 params ["offset" ] = str (offset )
338357 data = self ._call_oauth2 ("v3/user/link_history" , params )
339358 return data ["link_history" ]
@@ -346,10 +365,10 @@ def user_network_history(self, offset=None, expand_client_id=False,
346365 if expand_user is True :
347366 params ["expand_user" ] = "true"
348367 if offset is not None :
349- assert isinstance (offset , int )
368+ assert isinstance (offset , integer_types )
350369 params ["offset" ] = str (offset )
351370 if limit is not None :
352- assert isinstance (limit , int )
371+ assert isinstance (limit , integer_types )
353372 params ["limit" ] = str (limit )
354373 data = self ._call_oauth2 ("v3/user/network_history" , params )
355374 return data
@@ -508,10 +527,10 @@ def bundle_create(self, private=False, title=None, description=None):
508527 if private :
509528 params ["private" ] = "true"
510529 if title is not None :
511- assert isinstance (title , str )
530+ assert isinstance (title , string_types )
512531 params ["title" ] = title
513532 if description is not None :
514- assert isinstance (description , str )
533+ assert isinstance (description , string_types )
515534 params ["description" ] = description
516535 data = self ._call_oauth2_metrics ("v3/bundle/create" , params )
517536 return data
@@ -521,13 +540,13 @@ def bundle_edit(self, bundle_link, edit=None, title=None, description=None,
521540 """edit a bundle for the authenticated user"""
522541 params = dict (bundle_link = bundle_link )
523542 if edit :
524- assert isinstance (edit , str )
543+ assert isinstance (edit , string_types )
525544 params ["edit" ] = edit
526545 if title :
527- assert isinstance (title , str )
546+ assert isinstance (title , string_types )
528547 params ["title" ] = title
529548 if description :
530- assert isinstance (description , str )
549+ assert isinstance (description , string_types )
531550 params ["description" ] = description
532551 if private is not None :
533552 if private :
@@ -540,7 +559,7 @@ def bundle_edit(self, bundle_link, edit=None, title=None, description=None,
540559 else :
541560 params ["preview" ] = "false"
542561 if og_image :
543- assert isinstance (og_image , str )
562+ assert isinstance (og_image , string_types )
544563 params ["og_image" ] = og_image
545564 data = self ._call_oauth2_metrics ("v3/bundle/edit" , params )
546565 return data
@@ -549,7 +568,7 @@ def bundle_link_add(self, bundle_link, link, title=None):
549568 """add a link to a bundle"""
550569 params = dict (bundle_link = bundle_link , link = link )
551570 if title :
552- assert isinstance (title , str )
571+ assert isinstance (title , string_types )
553572 params ["title" ] = title
554573 data = self ._call_oauth2_metrics ("v3/bundle/link_add" , params )
555574 return data
@@ -581,7 +600,7 @@ def bundle_link_edit(self, bundle_link, link, edit, title=None,
581600 params = dict (bundle_link = bundle_link , link = link )
582601 if edit == "title" :
583602 params ["edit" ] = edit
584- assert isinstance (title , str )
603+ assert isinstance (title , string_types )
585604 params ["title" ] = title
586605 elif edit == "preview" :
587606 params ["edit" ] = edit
@@ -681,16 +700,16 @@ def search(self, query, offset=None, cities=None, domain=None, fields=None,
681700 limit = 10 , lang = 'en' ):
682701 params = dict (query = query , lang = lang )
683702 if offset :
684- assert isinstance (offset , int )
703+ assert isinstance (offset , integer_types )
685704 params ["offset" ] = str (offset )
686705 if cities : # TODO: check format
687- assert isinstance (cities , str )
706+ assert isinstance (cities , string_types )
688707 params ["cities" ] = cities
689708 if domain :
690- assert isinstance (domain , str )
709+ assert isinstance (domain , string_types )
691710 params ["domain" ] = domain
692711 if fields :
693- assert isinstance (fields , str )
712+ assert isinstance (fields , string_types )
694713 params ["fields" ] = fields
695714 data = self ._call_oauth2_metrics ("v3/search" , params , limit = limit )
696715 return data ['results' ]
@@ -723,26 +742,27 @@ def _call_oauth2_metrics(self, endpoint, params, unit=None, units=None,
723742 assert unit in ("minute" , "hour" , "day" , "week" , "mweek" , "month" )
724743 params ["unit" ] = unit
725744 if units is not None :
726- assert isinstance (units , int ), "Unit (%r) must be integer" % units
745+ assert isinstance (units , integer_types ), \
746+ "Unit (%r) must be integer" % units
727747 params ["units" ] = units
728748 if tz_offset is not None :
729749 # tz_offset can either be a hour offset, or a timezone like
730750 # North_America/New_York
731- if isinstance (tz_offset , int ):
751+ if isinstance (tz_offset , integer_types ):
732752 msg = "integer tz_offset must be between -12 and 12"
733753 assert - 12 <= tz_offset <= 12 , msg
734754 else :
735- assert isinstance (tz_offset , ( str , unicode ) )
755+ assert isinstance (tz_offset , string_types )
736756 params ["tz_offset" ] = tz_offset
737757 if rollup is not None :
738758 assert isinstance (rollup , bool )
739759 params ["rollup" ] = "true" if rollup else "false"
740760 if limit is not None :
741- assert isinstance (limit , int )
761+ assert isinstance (limit , integer_types )
742762 params ["limit" ] = limit
743763 if unit_reference_ts is not None :
744764 assert (unit_reference_ts == 'now' or
745- isinstance (unit_reference_ts , ( int , long ) ))
765+ isinstance (unit_reference_ts , integer_types ))
746766 params ["unit_reference_ts" ] = unit_reference_ts
747767
748768 return self ._call_oauth2 (endpoint , params )
@@ -773,21 +793,28 @@ def _call(self, host, method, params, secret=None, timeout=5000):
773793 'scheme' : scheme ,
774794 'host' : host ,
775795 'method' : method ,
776- 'params' : urllib . urlencode (params , doseq = 1 )
796+ 'params' : urlencode (params , doseq = 1 )
777797 }
778798
779799 try :
780- http_response = bitly_http .get (request , timeout ,
781- user_agent = self .user_agent )
782- if http_response ['http_status_code' ] != 200 :
783- raise BitlyError (500 , http_response ['result' ])
784- if not http_response ['result' ].startswith ('{' ):
785- raise BitlyError (500 , http_response ['result' ])
786- data = json .loads (http_response ['result' ])
800+ opener = build_opener (DontRedirect ())
801+ opener .addheaders = [('User-agent' , self .user_agent + ' urllib' )]
802+ response = opener .open (request )
803+ code = response .code
804+ result = response .read ().decode ('utf-8' )
805+ if code != 200 :
806+ raise BitlyError (500 , result )
807+ if not result .startswith ('{' ):
808+ raise BitlyError (500 , result )
809+ data = json .loads (result )
787810 if data .get ('status_code' , 500 ) != 200 :
788811 raise BitlyError (data .get ('status_code' , 500 ),
789812 data .get ('status_txt' , 'UNKNOWN_ERROR' ))
790813 return data
814+ except URLError as e :
815+ raise BitlyError (500 , str (e ))
816+ except HTTPError as e :
817+ raise BitlyError (e .code , e .read ())
791818 except BitlyError :
792819 raise
793820 except Exception :
0 commit comments