diff --git a/.travis.yml b/.travis.yml index 6bededb8..700deca1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,13 @@ +sudo: true language: python - python: - - 2.6 - - 2.7 + - "2.7" + - "3.6" + - "3.7-dev" # 3.7 development branch install: - - pip install -r requirements_dev.txt --use-mirrors - - python setup.py install + - pip install -r requirements.txt -script: python setup.py test +script : + - python setup.py install + # - python setup.py test \ No newline at end of file diff --git a/bootstrap.py b/bootstrap.py index d0ebf6d7..6ce668b2 100644 --- a/bootstrap.py +++ b/bootstrap.py @@ -20,7 +20,7 @@ $Id$ """ -import os, shutil, sys, tempfile, urllib2 +import os, shutil, sys, tempfile, urllib.request, urllib.error, urllib.parse from optparse import OptionParser tmpeggs = tempfile.mkdtemp() @@ -62,12 +62,12 @@ except ImportError: ez = {} if USE_DISTRIBUTE: - exec urllib2.urlopen('http://python-distribute.org/distribute_setup.py' - ).read() in ez + exec(urllib.request.urlopen('http://python-distribute.org/distribute_setup.py' + ).read(), ez) ez['use_setuptools'](to_dir=tmpeggs, download_delay=0, no_fake=True) else: - exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py' - ).read() in ez + exec(urllib.request.urlopen('http://peak.telecommunity.com/dist/ez_setup.py' + ).read(), ez) ez['use_setuptools'](to_dir=tmpeggs, download_delay=0) if to_reload: diff --git a/doc/conf.py b/doc/conf.py index 7e9d1147..775f92c5 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -20,8 +20,8 @@ source_suffix = '.rst' master_doc = 'index' -project = u'restkit' -copyright = u'2008-2013 Benoît Chesneau ' +project = 'restkit' +copyright = '2008-2013 Benoît Chesneau ' version = restkit.__version__ release = version @@ -43,6 +43,6 @@ htmlhelp_basename = 'restkitdoc' latex_documents = [ - ('index', 'restkit.tex', u'restkit Documentation', - u'Benoît Chesneau', 'manual'), + ('index', 'restkit.tex', 'restkit Documentation', + 'Benoît Chesneau', 'manual'), ] diff --git a/doc/sitemap_gen.py b/doc/sitemap_gen.py index e270a39d..79d35fb2 100755 --- a/doc/sitemap_gen.py +++ b/doc/sitemap_gen.py @@ -55,8 +55,8 @@ # entire file has been parsed. import sys if sys.hexversion < 0x02020000: - print 'This script requires Python 2.2 or later.' - print 'Currently run with version: %s' % sys.version + print('This script requires Python 2.2 or later.') + print(('Currently run with version: %s' % sys.version)) sys.exit(1) import fnmatch @@ -68,8 +68,8 @@ import stat import time import types -import urllib -import urlparse +import urllib.request, urllib.parse, urllib.error +import urllib.parse import xml.sax # True and False were introduced in Python2.2.2 @@ -113,7 +113,7 @@ ) # Match patterns for lastmod attributes -DATE_PATTERNS = map(re.compile, [ +DATE_PATTERNS = list(map(re.compile, [ r'^\d\d\d\d$', r'^\d\d\d\d-\d\d$', r'^\d\d\d\d-\d\d-\d\d$', @@ -121,7 +121,7 @@ r'^\d\d\d\d-\d\d-\d\dT\d\d:\d\d[+-]\d\d:\d\d$', r'^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?Z$', r'^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?[+-]\d\d:\d\d$', - ]) + ])) # Match patterns for changefreq attributes CHANGEFREQ_PATTERNS = [ @@ -286,7 +286,7 @@ def SetUserEncoding(self, encoding): def NarrowText(self, text, encoding): """ Narrow a piece of arbitrary text """ - if type(text) != types.UnicodeType: + if type(text) != str: return text # Try the passed in preference @@ -338,13 +338,13 @@ def MaybeNarrowPath(self, text): def WidenText(self, text, encoding): """ Widen a piece of arbitrary text """ - if type(text) != types.StringType: + if type(text) != bytes: return text # Try the passed in preference if encoding: try: - result = unicode(text, encoding) + result = str(text, encoding) if not encoding in self._learned: self._learned.append(encoding) return result @@ -356,7 +356,7 @@ def WidenText(self, text, encoding): # Try the user preference if self._user: try: - return unicode(text, self._user) + return str(text, self._user) except UnicodeError: pass except LookupError: @@ -367,13 +367,13 @@ def WidenText(self, text, encoding): # Look through learned defaults, knock any failing ones out of the list while self._learned: try: - return unicode(text, self._learned[0]) + return str(text, self._learned[0]) except: del self._learned[0] # When all other defaults are exhausted, use UTF-8 try: - return unicode(text, ENC_UTF8) + return str(text, ENC_UTF8) except UnicodeError: pass @@ -418,7 +418,7 @@ def Log(self, text, level): if text: text = encoder.NarrowText(text, None) if self._verbose >= level: - print text + print(text) #end def Log def Warn(self, text): @@ -426,9 +426,9 @@ def Warn(self, text): if text: text = encoder.NarrowText(text, None) hash = md5.new(text).digest() - if not self._warns_shown.has_key(hash): + if hash not in self._warns_shown: self._warns_shown[hash] = 1 - print '[WARNING] ' + text + print(('[WARNING] ' + text)) else: self.Log('(suppressed) [WARNING] ' + text, 3) self.num_warns = self.num_warns + 1 @@ -439,9 +439,9 @@ def Error(self, text): if text: text = encoder.NarrowText(text, None) hash = md5.new(text).digest() - if not self._errors_shown.has_key(hash): + if hash not in self._errors_shown: self._errors_shown[hash] = 1 - print '[ERROR] ' + text + print(('[ERROR] ' + text)) else: self.Log('(suppressed) [ERROR] ' + text, 3) self.num_errors = self.num_errors + 1 @@ -451,16 +451,16 @@ def Fatal(self, text): """ Output an error and terminate the program. """ if text: text = encoder.NarrowText(text, None) - print '[FATAL] ' + text + print(('[FATAL] ' + text)) else: - print 'Fatal error.' + print('Fatal error.') sys.exit(1) #end def Fatal def SetVerbose(self, level): """ Sets the verbose level. """ try: - if type(level) != types.IntType: + if type(level) != int: level = int(level) if (level >= 0) and (level <= 3): self._verbose = level @@ -510,7 +510,7 @@ def IsAbsolute(loc): if not loc: return False narrow = encoder.NarrowText(loc, None) - (scheme, netloc, path, query, frag) = urlparse.urlsplit(narrow) + (scheme, netloc, path, query, frag) = urllib.parse.urlsplit(narrow) if (not scheme) or (not netloc): return False return True @@ -526,21 +526,21 @@ def Canonicalize(loc): narrow = encoder.NarrowText(loc, None) # Escape components individually - (scheme, netloc, path, query, frag) = urlparse.urlsplit(narrow) + (scheme, netloc, path, query, frag) = urllib.parse.urlsplit(narrow) unr = '-._~' sub = '!$&\'()*+,;=' - netloc = urllib.quote(netloc, unr + sub + '%:@/[]') - path = urllib.quote(path, unr + sub + '%:@/') - query = urllib.quote(query, unr + sub + '%:@/?') - frag = urllib.quote(frag, unr + sub + '%:@/?') + netloc = urllib.parse.quote(netloc, unr + sub + '%:@/[]') + path = urllib.parse.quote(path, unr + sub + '%:@/') + query = urllib.parse.quote(query, unr + sub + '%:@/?') + frag = urllib.parse.quote(frag, unr + sub + '%:@/?') # Try built-in IDNA encoding on the netloc try: - (ignore, widenetloc, ignore, ignore, ignore) = urlparse.urlsplit(loc) + (ignore, widenetloc, ignore, ignore, ignore) = urllib.parse.urlsplit(loc) for c in widenetloc: - if c >= unichr(128): + if c >= chr(128): netloc = widenetloc.encode(ENC_IDNA) - netloc = urllib.quote(netloc, unr + sub + '%:@/[]') + netloc = urllib.parse.quote(netloc, unr + sub + '%:@/[]') break except UnicodeError: # urlsplit must have failed, based on implementation differences in the @@ -557,7 +557,7 @@ def Canonicalize(loc): bad_netloc = True # Put it all back together - narrow = urlparse.urlunsplit((scheme, netloc, path, query, frag)) + narrow = urllib.parse.urlunsplit((scheme, netloc, path, query, frag)) # I let '%' through. Fix any that aren't pre-existing escapes. HEXDIG = '0123456789abcdefABCDEF' @@ -596,14 +596,14 @@ def VerifyDate(self, date, metatag): def Validate(self, base_url, allow_fragment): """ Verify the data in this URL is well-formed, and override if not. """ - assert type(base_url) == types.StringType + assert type(base_url) == bytes # Test (and normalize) the ref if not self.loc: output.Warn('Empty URL') return False if allow_fragment: - self.loc = urlparse.urljoin(base_url, self.loc) + self.loc = urllib.parse.urljoin(base_url, self.loc) if not self.loc.startswith(base_url): output.Warn('Discarded URL for not starting with the base_url: %s' % self.loc) @@ -674,9 +674,9 @@ def WriteXML(self, file): for attribute in self.__slots__: value = getattr(self, attribute) if value: - if type(value) == types.UnicodeType: + if type(value) == str: value = encoder.NarrowText(value, None) - elif type(value) != types.StringType: + elif type(value) != bytes: value = str(value) value = xml.sax.saxutils.escape(value) out = out + (' <%s>%s\n' % (attribute, value, attribute)) @@ -700,7 +700,7 @@ def __init__(self): def Validate(self, base_url, allow_fragment): """ Verify the data in this News URL is well-formed, and override if not. """ - assert type(base_url) == types.StringType + assert type(base_url) == bytes if not URL.Validate(self, base_url, allow_fragment): return False @@ -722,9 +722,9 @@ def WriteXML(self, file): for attribute in self.__slots__: value = getattr(self, attribute) if value: - if type(value) == types.UnicodeType: + if type(value) == str: value = encoder.NarrowText(value, None) - elif type(value) != types.StringType: + elif type(value) != bytes: value = str(value) value = xml.sax.saxutils.escape(value) if attribute in NEWS_SPECIFIC_TAGS: @@ -840,7 +840,7 @@ def __init__(self, attributes): return url = URL() - for attr in attributes.keys(): + for attr in list(attributes.keys()): if attr == 'href': url.TrySetAttribute('loc', attributes[attr]) else: @@ -1086,7 +1086,7 @@ def __init__(self, attributes, base_url): if not url.endswith('/'): url = url + '/' if not url.startswith(base_url): - url = urlparse.urljoin(base_url, url) + url = urllib.parse.urljoin(base_url, url) if not url.startswith(base_url): output.Error('The directory URL "%s" is not relative to the ' 'base_url: %s' % (url, base_url)) @@ -1461,7 +1461,7 @@ def Preload(self, path): def GeneratePath(self, instance): """ Generates the iterations, as described above. """ prefix = self._path + self._prefix - if type(instance) == types.IntType: + if type(instance) == int: if instance: return '%s%d%s' % (prefix, instance, self._suffix) return prefix + self._suffix @@ -1472,7 +1472,7 @@ def GenerateURL(self, instance, root_url): """ Generates iterations, but as a URL instead of a path. """ prefix = root_url + self._prefix retval = None - if type(instance) == types.IntType: + if type(instance) == int: if instance: retval = '%s%d%s' % (prefix, instance, self._suffix) else: @@ -1502,13 +1502,13 @@ def __init__(self): def Consume(self, url): """ Log some stats for the URL. At the moment, that means extension. """ if url and url.loc: - (scheme, netloc, path, query, frag) = urlparse.urlsplit(url.loc) + (scheme, netloc, path, query, frag) = urllib.parse.urlsplit(url.loc) if not path: return # Recognize directories if path.endswith('/'): - if self._extensions.has_key('/'): + if '/' in self._extensions: self._extensions['/'] = self._extensions['/'] + 1 else: self._extensions['/'] = 1 @@ -1525,12 +1525,12 @@ def Consume(self, url): if i > 0: assert i < len(path) ext = path[i:].lower() - if self._extensions.has_key(ext): + if ext in self._extensions: self._extensions[ext] = self._extensions[ext] + 1 else: self._extensions[ext] = 1 else: - if self._extensions.has_key('(no extension)'): + if '(no extension)' in self._extensions: self._extensions['(no extension)'] = self._extensions[ '(no extension)'] + 1 else: @@ -1541,7 +1541,7 @@ def Log(self): """ Dump out stats to the output. """ if len(self._extensions): output.Log('Count of file extensions on URLs:', 1) - set = self._extensions.keys() + set = list(self._extensions.keys()) set.sort() for ext in set: output.Log(' %7d %s' % (self._extensions[ext], ext), 1) @@ -1617,8 +1617,8 @@ def ValidateBasicConfig(self): # Unify various forms of False if all_good: if self._suppress: - if (type(self._suppress) == types.StringType) or (type(self._suppress) - == types.UnicodeType): + if (type(self._suppress) == bytes) or (type(self._suppress) + == str): if (self._suppress == '0') or (self._suppress.lower() == 'false'): self._suppress = False @@ -1702,7 +1702,7 @@ def ConsumeURL(self, url, allow_fragment): # Note the sighting hash = url.MakeHash() - if self._urls.has_key(hash): + if hash in self._urls: dup = self._urls[hash] if dup > 0: dup = dup + 1 @@ -1780,7 +1780,7 @@ def FlushSet(self): file = None except IOError: output.Fatal('Couldn\'t write out to file: %s' % filename) - os.chmod(filename, 0644) + os.chmod(filename, 0o644) # Flush self._set = [] @@ -1821,7 +1821,7 @@ def WriteIndex(self): fd = None except IOError: output.Fatal('Couldn\'t write out to file: %s' % filename) - os.chmod(filename, 0644) + os.chmod(filename, 0o644) #end def WriteIndex def NotifySearch(self): @@ -1839,8 +1839,8 @@ def http_error_default(self, url, fp, errcode, errmsg, headers): raise IOError #end def http_error_default #end class ExceptionURLOpener - old_opener = urllib._urlopener - urllib._urlopener = ExceptionURLopener() + old_opener = urllib.request._urlopener + urllib.request._urlopener = ExceptionURLopener() # Build the URL we want to send in if self._sitemaps > 1: @@ -1850,7 +1850,7 @@ def http_error_default(self, url, fp, errcode, errmsg, headers): # Test if we can hit it ourselves try: - u = urllib.urlopen(url) + u = urllib.request.urlopen(url) u.close() except IOError: output.Error('When attempting to access our generated Sitemap at the ' @@ -1866,21 +1866,21 @@ def http_error_default(self, url, fp, errcode, errmsg, headers): query_map = ping[3] query_attr = ping[5] query_map[query_attr] = url - query = urllib.urlencode(query_map) - notify = urlparse.urlunsplit((ping[0], ping[1], ping[2], query, ping[4])) + query = urllib.parse.urlencode(query_map) + notify = urllib.parse.urlunsplit((ping[0], ping[1], ping[2], query, ping[4])) # Send the notification output.Log('Notifying: %s' % ping[1], 0) output.Log('Notification URL: %s' % notify, 2) try: - u = urllib.urlopen(notify) + u = urllib.request.urlopen(notify) u.read() u.close() except IOError: output.Warn('Cannot contact: %s' % ping[1]) if old_opener: - urllib._urlopener = old_opener + urllib.request._urlopener = old_opener #end def NotifySearch def startElement(self, tag, attributes): @@ -1912,7 +1912,7 @@ def startElement(self, tag, attributes): self._filters.append(Filter(attributes)) elif tag == 'url': - print type(attributes) + print((type(attributes))) self._inputs.append(InputURL(attributes)) elif tag == 'urllist': @@ -1955,7 +1955,7 @@ def ValidateAttributes(tag, attributes, goodattributes): """ Makes sure 'attributes' does not contain any attribute not listed in 'goodattributes' """ all_good = True - for attr in attributes.keys(): + for attr in list(attributes.keys()): if not attr in goodattributes: output.Error('Unknown %s attribute: %s' % (tag, attr)) all_good = False @@ -1977,9 +1977,9 @@ def ExpandPathAttribute(src, attrib): return [src] # If this isn't actually a dictionary, make it one - if type(src) != types.DictionaryType: + if type(src) != dict: tmp = {} - for key in src.keys(): + for key in list(src.keys()): tmp[key] = src[key] src = tmp # Create N new dictionaries @@ -2036,7 +2036,7 @@ def CreateSitemapFromFile(configpath, suppress_notify): xml.sax.parse(configpath, sitemap) except IOError: output.Error('Cannot read configuration file: %s' % configpath) - except xml.sax._exceptions.SAXParseException, e: + except xml.sax._exceptions.SAXParseException as e: output.Error('XML error in the config file (line %d, column %d): %s' % (e._linenum, e._colnum, e.getMessage())) except xml.sax._exceptions.SAXReaderNotAvailable: @@ -2065,9 +2065,9 @@ def ProcessCommandFlags(args): for a in args: try: rcg = rc.search(a).groupdict() - if rcg.has_key('key'): + if 'key' in rcg: flags[rcg['key']] = rcg['value'] - if rcg.has_key('option'): + if 'option' in rcg: flags[rcg['option']] = rcg['option'] except AttributeError: return None @@ -2081,10 +2081,10 @@ def ProcessCommandFlags(args): if __name__ == '__main__': flags = ProcessCommandFlags(sys.argv[1:]) - if not flags or not flags.has_key('config') or flags.has_key('help'): + if not flags or 'config' not in flags or 'help' in flags: output.Log(__usage__, 0) else: - suppress_notify = flags.has_key('testing') + suppress_notify = 'testing' in flags sitemap = CreateSitemapFromFile(flags['config'], suppress_notify) if not sitemap: output.Log('Configuration file errors -- exiting.', 0) diff --git a/doc/sphinxtogithub.py b/doc/sphinxtogithub.py index b91717b3..91597a9e 100755 --- a/doc/sphinxtogithub.py +++ b/doc/sphinxtogithub.py @@ -288,12 +288,12 @@ def sphinx_extension(app, exception): if not app.config.sphinx_to_github: if app.config.sphinx_to_github_verbose: - print "Sphinx-to-github: Disabled, doing nothing." + print("Sphinx-to-github: Disabled, doing nothing.") return if exception: if app.config.sphinx_to_github_verbose: - print "Sphinx-to-github: Exception raised in main build, doing nothing." + print("Sphinx-to-github: Exception raised in main build, doing nothing.") return dir_helper = DirHelper( diff --git a/examples/couchdbproxy.py b/examples/couchdbproxy.py index ff1e0624..49744ad3 100644 --- a/examples/couchdbproxy.py +++ b/examples/couchdbproxy.py @@ -3,7 +3,7 @@ # This file is part of restkit released under the MIT license. # See the NOTICE for more information. -import urlparse +import urllib.parse from webob import Request from restkit.contrib.wsgi_proxy import HostProxy @@ -22,7 +22,7 @@ def application(environ, start_response): req = Request(environ) if 'RAW_URI' in req.environ: # gunicorn so we use real path non encoded - u = urlparse.urlparse(req.environ['RAW_URI']) + u = urllib.parse.urlparse(req.environ['RAW_URI']) req.environ['PATH_INFO'] = u.path # do smth like adding oauth headers .. diff --git a/examples/test_eventlet.py b/examples/test_eventlet.py index adf7f904..695a2a5f 100644 --- a/examples/test_eventlet.py +++ b/examples/test_eventlet.py @@ -26,7 +26,7 @@ def fetch(u): r = request(u, follow_redirect=True, pool=pool) - print "RESULT: %s: %s (%s)" % (u, r.status, len(r.body_string())) + print(("RESULT: %s: %s (%s)" % (u, r.status, len(r.body_string())))) def extract(): for url in allurls: @@ -34,4 +34,4 @@ def extract(): epool.waitall() t = timeit.Timer(stmt=extract) -print "%.2f s" % t.timeit(number=1) +print(("%.2f s" % t.timeit(number=1))) diff --git a/examples/test_gevent.py b/examples/test_gevent.py index c99aa713..aa9aefd9 100644 --- a/examples/test_gevent.py +++ b/examples/test_gevent.py @@ -24,7 +24,7 @@ def fetch(u): r = request(u, follow_redirect=True, pool=pool) - print "RESULT: %s: %s (%s)" % (u, r.status, len(r.body_string())) + print(("RESULT: %s: %s (%s)" % (u, r.status, len(r.body_string())))) def extract(): @@ -32,4 +32,4 @@ def extract(): gevent.joinall(jobs) t = timeit.Timer(stmt=extract) -print "%.2f s" % t.timeit(number=1) +print(("%.2f s" % t.timeit(number=1))) diff --git a/examples/test_threads.py b/examples/test_threads.py index 16fdb5b7..eee079c0 100644 --- a/examples/test_threads.py +++ b/examples/test_threads.py @@ -17,7 +17,7 @@ def fetch(u): r = request(u, follow_redirect=True) - print "RESULT: %s: %s (%s)" % (u, r.status, len(r.body_string())) + print(("RESULT: %s: %s (%s)" % (u, r.status, len(r.body_string())))) def spawn(u): t = threading.Thread(target=fetch, args=[u]) @@ -30,4 +30,4 @@ def extract(): [t.join() for t in threads] t = timeit.Timer(stmt=extract) -print "%.2f s" % t.timeit(number=1) +print(("%.2f s" % t.timeit(number=1))) diff --git a/restkit/__init__.py b/restkit/__init__.py index f05b9d3b..65cad05a 100644 --- a/restkit/__init__.py +++ b/restkit/__init__.py @@ -18,7 +18,7 @@ import traceback traceback.print_exc() -import urlparse +import urllib.parse import logging LOG_LEVELS = { @@ -85,11 +85,11 @@ def request(url, method='GET', body=None, headers=None, **kwargs): """ # detect credentials from url - u = urlparse.urlparse(url) + u = urllib.parse.urlparse(url) if u.username is not None: password = u.password or "" filters = kwargs.get('filters') or [] - url = urlparse.urlunparse((u.scheme, u.netloc.split("@")[-1], + url = urllib.parse.urlunparse((u.scheme, u.netloc.split("@")[-1], u.path, u.params, u.query, u.fragment)) filters.append(BasicAuth(u.username, password)) diff --git a/restkit/client.py b/restkit/client.py index b953fe48..0116fd5c 100644 --- a/restkit/client.py +++ b/restkit/client.py @@ -11,7 +11,7 @@ import ssl import traceback import types -import urlparse +import urllib.parse try: from http_parser.http import ( @@ -200,7 +200,7 @@ def proxy_connection(self, request, req_addr, is_ssl): request.is_proxied = True proxy_settings, proxy_auth = _get_proxy_auth(proxy_settings) - addr = parse_netloc(urlparse.urlparse(proxy_settings)) + addr = parse_netloc(urllib.parse.urlparse(proxy_settings)) if is_ssl: if proxy_auth: @@ -268,7 +268,7 @@ def make_headers_string(self, request, extra_headers=None): ] lheaders.extend(["%s: %s\r\n" % (k, str(v)) for k, v in \ - headers.items() if k.lower() not in \ + list(headers.items()) if k.lower() not in \ ('user-agent', 'host', 'accept-encoding',)]) if log.isEnabledFor(logging.DEBUG): log.debug("Send headers: %s" % lheaders) @@ -324,7 +324,7 @@ def perform(self, request): log.debug("send body (chunked: %s)" % chunked) - if isinstance(request.body, types.StringTypes): + if isinstance(request.body, str): if msg is not None: conn.send(msg + to_bytestring(request.body), chunked) @@ -346,15 +346,15 @@ def perform(self, request): conn.send(msg) return self.get_response(request, conn) - except socket.gaierror, e: + except socket.gaierror as e: if conn is not None: conn.release(True) raise RequestError(str(e)) - except socket.timeout, e: + except socket.timeout as e: if conn is not None: conn.release(True) raise RequestTimeout(str(e)) - except socket.error, e: + except socket.error as e: if log.isEnabledFor(logging.DEBUG): log.debug("socket error: %s" % str(e)) if conn is not None: @@ -368,7 +368,7 @@ def perform(self, request): # should raised an exception in other cases request.maybe_rewind(msg=str(e)) - except NoMoreData, e: + except NoMoreData as e: if conn is not None: conn.release(True) @@ -505,10 +505,10 @@ def _get_proxy_auth(proxy_settings): proxy_password = proxy_password or "" if not proxy_username: - u = urlparse.urlparse(proxy_settings) + u = urllib.parse.urlparse(proxy_settings) if u.username: proxy_password = u.password or proxy_password - proxy_settings = urlparse.urlunparse((u.scheme, + proxy_settings = urllib.parse.urlunparse((u.scheme, u.netloc.split("@")[-1], u.path, u.params, u.query, u.fragment)) diff --git a/restkit/conn.py b/restkit/conn.py index 332c99e2..31f15a3b 100644 --- a/restkit/conn.py +++ b/restkit/conn.py @@ -9,7 +9,7 @@ import socket import ssl import time -import cStringIO +import io from socketpool import Connector from socketpool.util import is_connected @@ -33,7 +33,7 @@ def __init__(self, host, port, backend_mod=None, pool=None, self._s.connect((host, port)) if proxy_pieces: self._s.sendall(proxy_pieces) - response = cStringIO.StringIO() + response = io.StringIO() while response.getvalue()[-4:] != '\r\n\r\n': response.write(self._s.recv(1)) response.close() diff --git a/restkit/contrib/console.py b/restkit/contrib/console.py index be46ad83..58ee7e13 100644 --- a/restkit/contrib/console.py +++ b/restkit/contrib/console.py @@ -3,7 +3,7 @@ # This file is part of restkit released under the MIT license. # See the NOTICE for more information. -from __future__ import with_statement + import os import optparse as op import sys @@ -186,8 +186,8 @@ def main(): try: from restkit.contrib import ipython_shell as shell shell.main(options=opts, *args) - except Exception, e: - print >>sys.stderr, str(e) + except Exception as e: + print(str(e), file=sys.stderr) sys.exit(1) return @@ -243,29 +243,29 @@ def main(): else: if opts.server_response: if opts.prettify: - print "\n\033[0m\033[95mServer response from %s:\n\033[0m" % ( - resp.final_url) + print("\n\033[0m\033[95mServer response from %s:\n\033[0m" % ( + resp.final_url)) for k, v in resp.headerslist: - print "\033[94m%s\033[0m: %s" % (k, v) - print "\033[0m" + print("\033[94m%s\033[0m: %s" % (k, v)) + print("\033[0m") else: - print "Server response from %s:\n" % (resp.final_url) + print("Server response from %s:\n" % (resp.final_url)) for k, v in resp.headerslist: - print "%s: %s" % (k, v) - print "" + print("%s: %s" % (k, v)) + print("") if opts.output == '-': if opts.prettify: - print prettify(resp) + print(prettify(resp)) else: - print resp.body_string() + print(resp.body_string()) else: if opts.prettify: - print prettify(resp) + print(prettify(resp)) else: - print resp.body_string() + print(resp.body_string()) - except Exception, e: + except Exception as e: sys.stderr.write("An error happened: %s" % str(e)) sys.stderr.flush() sys.exit(1) diff --git a/restkit/contrib/ipython_shell.py b/restkit/contrib/ipython_shell.py index c152af6f..a22b85d8 100644 --- a/restkit/contrib/ipython_shell.py +++ b/restkit/contrib/ipython_shell.py @@ -3,8 +3,8 @@ # This file is part of restkit released under the MIT license. # See the NOTICE for more information. -from StringIO import StringIO -import urlparse +from io import StringIO +import urllib.parse try: from IPython.config.loader import Config @@ -47,7 +47,7 @@ def __str__(self, skip_body=True): skip_body = False return BaseResponse.__str__(self, skip_body=skip_body) def __call__(self): - print self + print(self) class Request(BaseRequest): @@ -60,7 +60,7 @@ def get_response(self, *args, **kwargs): stream = a a.seek(0) continue - elif isinstance(a, basestring): + elif isinstance(a, str): if a.startswith('http'): url = a elif a.startswith('/'): @@ -72,10 +72,10 @@ def get_response(self, *args, **kwargs): self.body_file = stream self.content_length = stream.len if self.method == 'GET' and kwargs: - for k, v in kwargs.items(): + for k, v in list(kwargs.items()): self.GET[k] = v elif self.method == 'POST' and kwargs: - for k, v in kwargs.items(): + for k, v in list(kwargs.items()): self.GET[k] = v return BaseRequest.get_response(self) @@ -85,7 +85,7 @@ def __str__(self, skip_body=True): return BaseRequest.__str__(self, skip_body=skip_body) def __call__(self): - print self + print(self) class ContentTypes(object): @@ -173,9 +173,9 @@ def req(*args, **kwargs): resp = self.request(k.upper(), *args, **kwargs) self.shell.user_ns.update(dict(resp=resp)) - print resp + print(resp) return resp - req.func_name = k + req.__name__ = k req.__name__ = k req.__doc__ = """send a HTTP %s""" % k.upper() return req @@ -208,8 +208,8 @@ def help(self): doc = ' >>> %s(%s)' % (k, args) methods += '%-65.65s # send a HTTP %s\n' % (doc, k) ns['methods'] = methods - print HELP.strip() % ns - print '' + print((HELP.strip() % ns)) + print('') def __repr__(self): return '' diff --git a/restkit/contrib/webob_api.py b/restkit/contrib/webob_api.py index 1c5ab152..92d48c3a 100644 --- a/restkit/contrib/webob_api.py +++ b/restkit/contrib/webob_api.py @@ -5,9 +5,9 @@ # See the NOTICE for more information. import base64 -from StringIO import StringIO -import urlparse -import urllib +from io import StringIO +import urllib.parse +import urllib.request, urllib.parse, urllib.error try: from webob import Request as BaseRequest @@ -63,7 +63,7 @@ def get_response(self): if self.method in ('DELETE', 'GET'): self.body = '' elif self.method == 'POST' and self.POST: - body = urllib.urlencode(self.POST.copy()) + body = urllib.parse.urlencode(self.POST.copy()) stream = StringIO(body) stream.seek(0) self.body_file = stream @@ -80,7 +80,7 @@ def set_url(self, url): path = url.lstrip('/') if url.startswith("http://") or url.startswith("https://"): - u = urlparse.urlsplit(url) + u = urllib.parse.urlsplit(url) if u.username is not None: password = u.password or "" encode = base64.b64encode("%s:%s" % (u.username, password)) @@ -90,7 +90,7 @@ def set_url(self, url): self.host = u.netloc.split("@")[-1] self.path_info = u.path or "/" self.query_string = u.query - url = urlparse.urlunsplit((u.scheme, u.netloc.split("@")[-1], + url = urllib.parse.urlunsplit((u.scheme, u.netloc.split("@")[-1], u.path, u.query, u.fragment)) else: @@ -100,5 +100,5 @@ def set_url(self, url): url = self.url - self.scheme, self.host, self.path_info = urlparse.urlparse(url)[0:3] + self.scheme, self.host, self.path_info = urllib.parse.urlparse(url)[0:3] diff --git a/restkit/contrib/wsgi_proxy.py b/restkit/contrib/wsgi_proxy.py index 2e7d51ef..aceb9306 100644 --- a/restkit/contrib/wsgi_proxy.py +++ b/restkit/contrib/wsgi_proxy.py @@ -3,12 +3,12 @@ # This file is part of restkit released under the MIT license. # See the NOTICE for more information. -import urlparse +import urllib.parse try: - from cStringIO import StringIO + from io import StringIO except ImportError: - from StringIO import StringIO + from io import StringIO from restkit.client import Client from restkit.conn import MAX_BODY @@ -73,7 +73,7 @@ def __call__(self, environ, start_response): uri = host_uri + path_info new_headers = {} - for k, v in environ.items(): + for k, v in list(environ.items()): if k.startswith('HTTP_'): k = k[5:].replace('_', '-').title() new_headers[k] = v @@ -141,7 +141,7 @@ class HostProxy(Proxy): def __init__(self, uri, **kwargs): super(HostProxy, self).__init__(**kwargs) self.uri = uri.rstrip('/') - self.scheme, self.net_loc = urlparse.urlparse(self.uri)[0:2] + self.scheme, self.net_loc = urllib.parse.urlparse(self.uri)[0:2] def extract_uri(self, environ): environ['HTTP_HOST'] = self.net_loc diff --git a/restkit/datastructures.py b/restkit/datastructures.py index 46e2168f..c9168673 100644 --- a/restkit/datastructures.py +++ b/restkit/datastructures.py @@ -24,16 +24,16 @@ def __init__(self, *args, **kw): if isinstance(args[0], MultiDict): items = args[0]._items elif hasattr(args[0], 'iteritems'): - items = list(args[0].iteritems()) + items = list(args[0].items()) elif hasattr(args[0], 'items'): - items = args[0].items() + items = list(args[0].items()) else: items = list(args[0]) self._items = items else: self._items = [] if kw: - self._items.extend(kw.iteritems()) + self._items.extend(iter(list(kw.items()))) @classmethod def from_fieldstorage(cls, fs): @@ -104,7 +104,7 @@ def mixed(self): """ result = {} multi = {} - for key, value in self.iteritems(): + for key, value in list(self.items()): if key in result: # We do this to not clobber any lists that are # *actual* values in this dictionary: @@ -122,7 +122,7 @@ def dict_of_lists(self): Returns a dictionary where each key is associated with a list of values. """ r = {} - for key, val in self.iteritems(): + for key, val in list(self.items()): r.setdefault(key, []).append(val) return r @@ -159,8 +159,8 @@ def setdefault(self, key, default=None): def pop(self, key, *args): if len(args) > 1: - raise TypeError, "pop expected at most 2 arguments, got "\ - + repr(1 + len(args)) + raise TypeError("pop expected at most 2 arguments, got "\ + + repr(1 + len(args))) for i in range(len(self._items)): if self._items[i][0] == key: v = self._items[i][1] @@ -174,8 +174,8 @@ def pop(self, key, *args): def ipop(self, key, *args): """ like pop but case insensitive """ if len(args) > 1: - raise TypeError, "pop expected at most 2 arguments, got "\ - + repr(1 + len(args)) + raise TypeError("pop expected at most 2 arguments, got "\ + + repr(1 + len(args))) lkey = key.lower() for i, item in enumerate(self._items): @@ -195,9 +195,9 @@ def extend(self, other=None, **kwargs): if other is None: pass elif hasattr(other, 'items'): - self._items.extend(other.items()) + self._items.extend(list(other.items())) elif hasattr(other, 'keys'): - for k in other.keys(): + for k in list(other.keys()): self._items.append((k, other[k])) else: for k, v in other: @@ -206,7 +206,7 @@ def extend(self, other=None, **kwargs): self.update(kwargs) def __repr__(self): - items = ', '.join(['(%r, %r)' % v for v in self.iteritems()]) + items = ', '.join(['(%r, %r)' % v for v in list(self.items())]) return '%s([%s])' % (self.__class__.__name__, items) def __len__(self): diff --git a/restkit/errors.py b/restkit/errors.py index 6949cb4b..210e6811 100644 --- a/restkit/errors.py +++ b/restkit/errors.py @@ -29,7 +29,7 @@ def __str__(self): return self.msg try: return str(self.__dict__) - except (NameError, ValueError, KeyError), e: + except (NameError, ValueError, KeyError) as e: return 'Unprintable exception %s: %s' \ % (self.__class__.__name__, str(e)) diff --git a/restkit/filters.py b/restkit/filters.py index 49f2e5d1..5aa961fe 100644 --- a/restkit/filters.py +++ b/restkit/filters.py @@ -6,10 +6,10 @@ import base64 import re try: - from urlparse import parse_qsl + from urllib.parse import parse_qsl except ImportError: from cgi import parse_qsl -from urlparse import urlunparse +from urllib.parse import urlunparse from restkit.oauth2 import Request, SignatureMethod_HMAC_SHA1 diff --git a/restkit/forms.py b/restkit/forms.py index 56e6ce61..3c4243d2 100644 --- a/restkit/forms.py +++ b/restkit/forms.py @@ -7,7 +7,7 @@ import mimetypes import os import re -import urllib +import urllib.request, urllib.parse, urllib.error from restkit.util import to_bytestring, url_quote, url_encode @@ -30,7 +30,7 @@ def __init__(self, name, value, fname=None, filetype=None, filesize=None, self.size = len(value) self.value = value if fname is not None: - if isinstance(fname, unicode): + if isinstance(fname, str): fname = fname.encode("utf-8").encode("string_escape").replace('"', '\\"') else: fname = fname.encode("string_escape").replace('"', '\\"') @@ -105,14 +105,14 @@ def __init__(self, params, boundary, headers, bitem_cls=BoundaryItem, self._clen = headers.get('Content-Length') if hasattr(params, 'items'): - params = params.items() + params = list(params.items()) for param in params: name, value = param if hasattr(value, "read"): fname = getattr(value, 'name') if fname is not None: - filetype = ';'.join(filter(None, mimetypes.guess_type(fname))) + filetype = ';'.join([_f for _f in mimetypes.guess_type(fname) if _f]) else: filetype = None if not isinstance(value, file) and self._clen is None: diff --git a/restkit/oauth2.py b/restkit/oauth2.py index 1591574c..bad03b82 100644 --- a/restkit/oauth2.py +++ b/restkit/oauth2.py @@ -4,15 +4,15 @@ # See the NOTICE for more information. import base64 -import urllib +import urllib.request, urllib.parse, urllib.error import time import random -import urlparse +import urllib.parse import hmac import binascii try: - from urlparse import parse_qs, parse_qsl + from urllib.parse import parse_qs, parse_qsl except ImportError: from cgi import parse_qs, parse_qsl @@ -66,7 +66,7 @@ def build_xoauth_string(url, consumer, token=None): request.sign_request(signing_method, consumer, token) params = [] - for k, v in sorted(request.iteritems()): + for k, v in sorted(request.items()): if v is not None: params.append('%s="%s"' % (k, escape(v))) @@ -76,12 +76,12 @@ def build_xoauth_string(url, consumer, token=None): def to_unicode(s): """ Convert to unicode, raise exception with instructive error message if s is not unicode, ascii, or utf-8. """ - if not isinstance(s, unicode): + if not isinstance(s, str): if not isinstance(s, str): raise TypeError('You are required to pass either unicode or string here, not: %r (%s)' % (type(s), s)) try: s = s.decode('utf-8') - except UnicodeDecodeError, le: + except UnicodeDecodeError as le: raise TypeError('You are required to pass either a unicode object or a utf-8 string here. You passed a Python string object which contained non-utf-8: %r. The UnicodeDecodeError that resulted from attempting to interpret it as utf-8 was: %s' % (s, le,)) return s @@ -89,13 +89,13 @@ def to_utf8(s): return to_unicode(s).encode('utf-8') def to_unicode_if_string(s): - if isinstance(s, basestring): + if isinstance(s, str): return to_unicode(s) else: return s def to_utf8_if_string(s): - if isinstance(s, basestring): + if isinstance(s, str): return to_utf8(s) else: return s @@ -105,12 +105,12 @@ def to_unicode_optional_iterator(x): Raise TypeError if x is a str containing non-utf8 bytes or if x is an iterable which contains such a str. """ - if isinstance(x, basestring): + if isinstance(x, str): return to_unicode(x) try: l = list(x) - except TypeError, e: + except TypeError as e: assert 'is not iterable' in str(e) return x else: @@ -121,12 +121,12 @@ def to_utf8_optional_iterator(x): Raise TypeError if x is a str or if x is an iterable which contains a str. """ - if isinstance(x, basestring): + if isinstance(x, str): return to_utf8(x) try: l = list(x) - except TypeError, e: + except TypeError as e: assert 'is not iterable' in str(e) return x else: @@ -134,7 +134,7 @@ def to_utf8_optional_iterator(x): def escape(s): """Escape a URL including any /.""" - return urllib.quote(s.encode('utf-8'), safe='~') + return urllib.parse.quote(s.encode('utf-8'), safe='~') def generate_timestamp(): """Get seconds since epoch (UTC).""" @@ -185,7 +185,7 @@ def __str__(self): data = {'oauth_consumer_key': self.key, 'oauth_consumer_secret': self.secret} - return urllib.urlencode(data) + return urllib.parse.urlencode(data) class Token(object): @@ -229,13 +229,13 @@ def set_verifier(self, verifier=None): def get_callback_url(self): if self.callback and self.verifier: # Append the oauth_verifier. - parts = urlparse.urlparse(self.callback) + parts = urllib.parse.urlparse(self.callback) scheme, netloc, path, params, query, fragment = parts[:6] if query: query = '%s&oauth_verifier=%s' % (query, self.verifier) else: query = 'oauth_verifier=%s' % self.verifier - return urlparse.urlunparse((scheme, netloc, path, params, + return urllib.parse.urlunparse((scheme, netloc, path, params, query, fragment)) return self.callback @@ -253,7 +253,7 @@ def to_string(self): if self.callback_confirmed is not None: data['oauth_callback_confirmed'] = self.callback_confirmed - return urllib.urlencode(data) + return urllib.parse.urlencode(data) @staticmethod def from_string(s): @@ -324,7 +324,7 @@ def __init__(self, method=HTTP_METHOD, url=None, parameters=None, self.url = to_unicode(url) self.method = method if parameters is not None: - for k, v in parameters.iteritems(): + for k, v in list(parameters.items()): k = to_unicode(k) v = to_unicode_optional_iterator(v) self[k] = v @@ -336,7 +336,7 @@ def __init__(self, method=HTTP_METHOD, url=None, parameters=None, def url(self, value): self.__dict__['url'] = value if value is not None: - scheme, netloc, path, params, query, fragment = urlparse.urlparse(value) + scheme, netloc, path, params, query, fragment = urllib.parse.urlparse(value) # Exclude default port numbers. if scheme == 'http' and netloc[-3:] == ':80': @@ -347,7 +347,7 @@ def url(self, value): raise ValueError("Unsupported URL %s (%s)." % (value, scheme)) # Normalized URL excludes params, query, and fragment. - self.normalized_url = urlparse.urlunparse((scheme, netloc, path, None, None, None)) + self.normalized_url = urllib.parse.urlunparse((scheme, netloc, path, None, None, None)) else: self.normalized_url = None self.__dict__['url'] = None @@ -361,12 +361,12 @@ def _get_timestamp_nonce(self): def get_nonoauth_parameters(self): """Get any non-OAuth parameters.""" - return dict([(k, v) for k, v in self.iteritems() + return dict([(k, v) for k, v in list(self.items()) if not k.startswith('oauth_')]) def to_header(self, realm=''): """Serialize as a header for an HTTPAuth request.""" - oauth_params = ((k, v) for k, v in self.items() + oauth_params = ((k, v) for k, v in list(self.items()) if k.startswith('oauth_')) stringy_params = ((k, escape(str(v))) for k, v in oauth_params) header_params = ('%s="%s"' % (k, v) for k, v in stringy_params) @@ -381,25 +381,25 @@ def to_header(self, realm=''): def to_postdata(self): """Serialize as post data for a POST request.""" d = {} - for k, v in self.iteritems(): + for k, v in list(self.items()): d[k.encode('utf-8')] = to_utf8_optional_iterator(v) # tell urlencode to deal with sequence values and map them correctly # to resulting querystring. for example self["k"] = ["v1", "v2"] will # result in 'k=v1&k=v2' and not k=%5B%27v1%27%2C+%27v2%27%5D - return urllib.urlencode(d, True).replace('+', '%20') + return urllib.parse.urlencode(d, True).replace('+', '%20') def to_url(self): """Serialize as a URL for a GET request.""" - base_url = urlparse.urlparse(self.url) + base_url = urllib.parse.urlparse(self.url) try: query = base_url.query except AttributeError: # must be python <2.5 query = base_url[4] query = parse_qs(query) - for k, v in self.items(): - if isinstance(v, unicode): + for k, v in list(self.items()): + if isinstance(v, str): v = v.encode("utf-8") query.setdefault(k, []).append(v) @@ -418,8 +418,8 @@ def to_url(self): fragment = base_url[5] url = (scheme, netloc, path, params, - urllib.urlencode(query, True), fragment) - return urlparse.urlunparse(url) + urllib.parse.urlencode(query, True), fragment) + return urllib.parse.urlunparse(url) def get_parameter(self, parameter): ret = self.get(parameter) @@ -431,31 +431,31 @@ def get_parameter(self, parameter): def get_normalized_parameters(self): """Return a string that contains the parameters that must be signed.""" items = [] - for key, value in self.iteritems(): + for key, value in list(self.items()): if key == 'oauth_signature': continue # 1.0a/9.1.1 states that kvp must be sorted by key, then by value, # so we unpack sequence values into multiple items for sorting. - if isinstance(value, basestring): + if isinstance(value, str): items.append((to_utf8_if_string(key), to_utf8(value))) else: try: value = list(value) - except TypeError, e: + except TypeError as e: assert 'is not iterable' in str(e) items.append((to_utf8_if_string(key), to_utf8_if_string(value))) else: items.extend((to_utf8_if_string(key), to_utf8_if_string(item)) for item in value) # Include any query string parameters from the provided URL - query = urlparse.urlparse(self.url)[4] + query = urllib.parse.urlparse(self.url)[4] - url_items = self._split_url_string(query).items() + url_items = list(self._split_url_string(query).items()) url_items = [(to_utf8(k), to_utf8(v)) for k, v in url_items if k != 'oauth_signature' ] items.extend(url_items) items.sort() - encoded_str = urllib.urlencode(items) + encoded_str = urllib.parse.urlencode(items) # Encode signature parameters per Oauth Core 1.0 protocol # spec draft 7, section 3.6 # (http://tools.ietf.org/html/draft-hammer-oauth-07#section-3.6) @@ -519,7 +519,7 @@ def from_request(cls, http_method, http_url, headers=None, parameters=None, parameters.update(query_params) # URL parameters. - param_str = urlparse.urlparse(http_url)[4] # query + param_str = urllib.parse.urlparse(http_url)[4] # query url_params = cls._split_url_string(param_str) parameters.update(url_params) @@ -581,15 +581,15 @@ def _split_header(header): # Split key-value. param_parts = param.split('=', 1) # Remove quotes and unescape the value. - params[param_parts[0]] = urllib.unquote(param_parts[1].strip('\"')) + params[param_parts[0]] = urllib.parse.unquote(param_parts[1].strip('\"')) return params @staticmethod def _split_url_string(param_str): """Turn URL string into parameters.""" parameters = parse_qs(param_str.encode('utf-8'), keep_blank_values=True) - for k, v in parameters.iteritems(): - parameters[k] = urllib.unquote(v[0]) + for k, v in list(parameters.items()): + parameters[k] = urllib.parse.unquote(v[0]) return parameters diff --git a/restkit/resource.py b/restkit/resource.py index 5b485b2f..11198c5d 100644 --- a/restkit/resource.py +++ b/restkit/resource.py @@ -11,7 +11,7 @@ This module provide a common interface for all HTTP request. """ from copy import copy -import urlparse +import urllib.parse from restkit.errors import ResourceNotFound, Unauthorized, \ RequestFailed, ResourceGone @@ -55,7 +55,7 @@ def __init__(self, uri, **client_opts): self.uri = uri if self.basic_auth_url: # detect credentials from url - u = urlparse.urlparse(uri) + u = urllib.parse.urlparse(uri) if u.username: password = u.password or "" @@ -65,7 +65,7 @@ def __init__(self, uri, **client_opts): client_opts['filters'] = filters # update uri - self.uri = urlparse.urlunparse((u.scheme, u.netloc.split("@")[-1], + self.uri = urllib.parse.urlunparse((u.scheme, u.netloc.split("@")[-1], u.path, u.params, u.query, u.fragment)) self.client_opts = client_opts diff --git a/restkit/tee.py b/restkit/tee.py index b3f452d3..0f41fcca 100644 --- a/restkit/tee.py +++ b/restkit/tee.py @@ -13,9 +13,9 @@ import copy import os try: - from cStringIO import StringIO + from io import StringIO except ImportError: - from StringIO import StringIO + from io import StringIO import tempfile from restkit import conn @@ -28,7 +28,7 @@ def __init__(self, stream): self.buf = StringIO() self.eof = False - if isinstance(stream, basestring): + if isinstance(stream, str): stream = StringIO(stream) self.tmp = StringIO() else: @@ -135,7 +135,7 @@ def close(self): self._close_unreader() return self.tmp.close() - def next(self): + def __next__(self): r = self.readline() if not r: raise StopIteration diff --git a/restkit/util.py b/restkit/util.py index f3c18705..cd4503b2 100644 --- a/restkit/util.py +++ b/restkit/util.py @@ -6,12 +6,13 @@ import os import re import time -import urllib -import urlparse +import urllib.request, urllib.parse, urllib.error +import urllib.parse import warnings -import Cookie +import http.cookies from restkit.errors import InvalidUrl +import collections absolute_http_url_re = re.compile(r"^https?://", re.I) @@ -84,20 +85,20 @@ def parse_netloc(uri): return (host, port) def to_bytestring(s): - if not isinstance(s, basestring): + if not isinstance(s, str): raise TypeError("value should be a str or unicode") - if isinstance(s, unicode): + if isinstance(s, str): return s.encode('utf-8') return s def url_quote(s, charset='utf-8', safe='/:'): """URL encode a single string with a given encoding.""" - if isinstance(s, unicode): + if isinstance(s, str): s = s.encode(charset) elif not isinstance(s, str): s = str(s) - return urllib.quote(s, safe=safe) + return urllib.parse.quote(s, safe=safe) def url_encode(obj, charset="utf8", encode_keys=False): @@ -119,15 +120,15 @@ def url_encode(obj, charset="utf8", encode_keys=False): for v1 in v: if v1 is None: v1 = '' - elif callable(v1): + elif isinstance(v1, collections.Callable): v1 = encode(v1(), charset) else: v1 = encode(v1, charset) - tmp.append('%s=%s' % (urllib.quote(k), urllib.quote_plus(v1))) + tmp.append('%s=%s' % (urllib.parse.quote(k), urllib.parse.quote_plus(v1))) return '&'.join(tmp) def encode(v, charset="utf8"): - if isinstance(v, unicode): + if isinstance(v, str): v = v.encode(charset) else: v = str(v) @@ -155,7 +156,7 @@ def make_uri(base, *args, **kwargs): _path = [] trailing_slash = False for s in args: - if s is not None and isinstance(s, basestring): + if s is not None and isinstance(s, str): if len(s) > 1 and s.endswith('/'): trailing_slash = True else: @@ -182,15 +183,15 @@ def make_uri(base, *args, **kwargs): def rewrite_location(host_uri, location, prefix_path=None): prefix_path = prefix_path or '' - url = urlparse.urlparse(location) - host_url = urlparse.urlparse(host_uri) + url = urllib.parse.urlparse(location) + host_url = urllib.parse.urlparse(host_uri) if not absolute_http_url_re.match(location): # remote server doesn't follow rfc2616 proxy_uri = '%s%s' % (host_uri, prefix_path) - return urlparse.urljoin(proxy_uri, location) + return urllib.parse.urljoin(proxy_uri, location) elif url.scheme == host_url.scheme and url.netloc == host_url.netloc: - return urlparse.urlunparse((host_url.scheme, host_url.netloc, + return urllib.parse.urlunparse((host_url.scheme, host_url.netloc, prefix_path + url.path, url.params, url.query, url.fragment)) return location @@ -221,7 +222,7 @@ def replace_headers(new_headers, headers): if len(found) == len(new_headers): return - for k, v in new_headers.items(): + for k, v in list(new_headers.items()): if k not in found: headers.append((k.title(), v)) return headers @@ -231,11 +232,11 @@ def parse_cookie(cookie, final_url): if cookie == '': return {} - if not isinstance(cookie, Cookie.BaseCookie): + if not isinstance(cookie, http.cookies.BaseCookie): try: - c = Cookie.SimpleCookie() + c = http.cookies.SimpleCookie() c.load(cookie) - except Cookie.CookieError: + except http.cookies.CookieError: # Invalid cookie return {} else: @@ -243,7 +244,7 @@ def parse_cookie(cookie, final_url): cookiedict = {} - for key in c.keys(): + for key in list(c.keys()): cook = c.get(key) cookiedict[key] = cook.value return cookiedict diff --git a/restkit/wrappers.py b/restkit/wrappers.py index 8f9ede3c..06a57919 100644 --- a/restkit/wrappers.py +++ b/restkit/wrappers.py @@ -8,9 +8,9 @@ import logging import mimetypes import os -from StringIO import StringIO +from io import StringIO import types -import urlparse +import urllib.parse import uuid from restkit.datastructures import MultiDict @@ -51,14 +51,14 @@ def _headers__set(self, value): def _parsed_url(self): if self.url is None: raise ValueError("url isn't set") - return urlparse.urlparse(self.url) + return urllib.parse.urlparse(self.url) parsed_url = property(_parsed_url, doc="parsed url") def _path__get(self): parsed_url = self.parsed_url path = parsed_url.path or '/' - return urlparse.urlunparse(('','', path, parsed_url.params, + return urllib.parse.urlunparse(('','', path, parsed_url.params, parsed_url.query, parsed_url.fragment)) path = property(_path__get) @@ -123,7 +123,7 @@ def _set_body(self, body): elif hasattr(self._body, 'getvalue') and not \ self.is_chunked(): clen = len(self._body.getvalue()) - elif isinstance(self._body, types.StringTypes): + elif isinstance(self._body, str): self._body = to_bytestring(self._body) clen = len(self._body) @@ -143,7 +143,7 @@ def _get_body(self): def maybe_rewind(self, msg=""): if self.body is not None: if not hasattr(self.body, 'seek') and \ - not isinstance(self.body, types.StringTypes): + not isinstance(self.body, str): raise RequestError("error: '%s', body can't be rewind." % msg) if log.isEnabledFor(logging.DEBUG): @@ -179,9 +179,9 @@ def close(self): def __iter__(self): return self - def next(self): + def __next__(self): try: - return self.body.next() + return next(self.body) except StopIteration: self.eof = True self.close() @@ -225,7 +225,7 @@ def __init__(self, connection, request, resp): self.status = resp.status() self.status_int = resp.status_code() self.version = resp.version() - self.headerslist = self.headers.items() + self.headerslist = list(self.headers.items()) self.location = self.headers.get('location') self.final_url = request.url self.should_close = not resp.should_keep_alive() @@ -257,7 +257,7 @@ def __contains__(self, key): return key in self.headers def __iter__(self): - return self.headers.iteritems() + return iter(list(self.headers.items())) def can_read(self): return not self._already_read diff --git a/setup.py b/setup.py index c4d7d3c0..084b49f2 100755 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ # This file is part of restkit released under the MIT license. # See the NOTICE for more information. -from __future__ import with_statement + from setuptools import setup, find_packages import glob diff --git a/tests/004-test-client.py b/tests/004-test-client.py index bff92b1e..e1caa35f 100644 --- a/tests/004-test-client.py +++ b/tests/004-test-client.py @@ -3,20 +3,20 @@ # This file is part of restkit released under the MIT license. # See the NOTICE for more information. -from __future__ import with_statement + import cgi import imghdr import os import socket import threading -import Queue -import urlparse +import queue +import urllib.parse import sys import tempfile import time -import t +from . import t from restkit.filters import BasicAuth @@ -84,7 +84,7 @@ def test_001(u, c): @t.client_request("/unicode") def test_002(u, c): r = c.request(u) - t.eq(r.body_string(charset="utf-8"), u"éàù@") + t.eq(r.body_string(charset="utf-8"), "éàù@") @t.client_request("/éàù") def test_003(u, c): @@ -115,7 +115,7 @@ def test_006(u, c): @t.client_request('http://e-engura.com/images/logo.gif') def test_007(u, c): r = c.request(u) - print r.status + print((r.status)) t.eq(r.status_int, 200) fd, fname = tempfile.mkstemp(suffix='.gif') f = os.fdopen(fd, "wb") @@ -162,7 +162,7 @@ def test_011(u, c): @t.client_request('/unicode') def test_012(u, c): - r = c.request(u, 'POST', body=u"éàù@") + r = c.request(u, 'POST', body="éàù@") t.eq(r.body_string(), "éàù@") diff --git a/tests/005-test-resource.py b/tests/005-test-resource.py index 597abf99..ab0e9df0 100644 --- a/tests/005-test-resource.py +++ b/tests/005-test-resource.py @@ -4,12 +4,12 @@ # See the NOTICE for more information. -import t +from . import t from restkit.errors import RequestFailed, ResourceNotFound, \ Unauthorized from restkit.resource import Resource -from _server_test import HOST, PORT +from ._server_test import HOST, PORT @t.resource_request() def test_001(res): @@ -30,9 +30,9 @@ def test_003(res): @t.resource_request() def test_004(res): - r = res.get(u'/test') + r = res.get('/test') t.eq(r.status_int, 200) - r = res.get(u'/éàù') + r = res.get('/éàù') t.eq(r.status_int, 200) @t.resource_request() @@ -65,11 +65,11 @@ def test_009(res): @t.resource_request() def test_010(res): - r = res.post('/unicode', payload=u"éàù@") + r = res.post('/unicode', payload="éàù@") t.eq(r.body_string(), "éàù@") - print "ok" - r = res.post('/unicode', payload=u"éàù@") - t.eq(r.body_string(charset="utf-8"), u"éàù@") + print("ok") + r = res.post('/unicode', payload="éàù@") + t.eq(r.body_string(charset="utf-8"), "éàù@") @t.resource_request() def test_011(res): @@ -115,8 +115,8 @@ def test_017(res): @t.resource_request() def test_018(res): content_length = len("test") - import StringIO - content = StringIO.StringIO("test") + import io + content = io.StringIO("test") r = res.post('/json', payload=content, headers={ 'Content-Type': 'application/json', @@ -126,8 +126,8 @@ def test_018(res): @t.resource_request() def test_019(res): - import StringIO - content = StringIO.StringIO("test") + import io + content = io.StringIO("test") t.raises(RequestFailed, res.post, '/json', payload=content, headers={'Content-Type': 'text/plain'}) @@ -184,9 +184,9 @@ def test_024(res): @t.resource_request() def test_025(res): - import StringIO + import io content = 'éàù@' - f = StringIO.StringIO('éàù@') + f = io.StringIO('éàù@') f.name = 'test.txt' b = {'a':'aa','b':'éàù@', 'f':f} h = {'content-type':"multipart/form-data"} diff --git a/tests/007-test-util.py b/tests/007-test-util.py index c7c93562..ed501b57 100644 --- a/tests/007-test-util.py +++ b/tests/007-test-util.py @@ -4,7 +4,7 @@ # See the NOTICE for more information. -import t +from . import t from restkit import util def test_001(): diff --git a/tests/008-test-request.py b/tests/008-test-request.py index 6e083e7b..cf2d8223 100644 --- a/tests/008-test-request.py +++ b/tests/008-test-request.py @@ -5,11 +5,11 @@ import os import uuid -import t +from . import t from restkit import request from restkit.forms import multipart_form_encode -from _server_test import HOST, PORT +from ._server_test import HOST, PORT LONG_BODY_PART = """This is a relatively long body, that we send to the client... This is a relatively long body, that we send to the client... @@ -127,10 +127,10 @@ def test_006(): t.eq(r.body_string(), content) def test_007(): - import StringIO + import io u = "http://%s:%s/multipart4" % (HOST, PORT) content = 'éàù@' - f = StringIO.StringIO('éàù@') + f = io.StringIO('éàù@') f.name = 'test.txt' b = {'a':'aa','b':'éàù@', 'f':f} h = {'content-type':"multipart/form-data"} diff --git a/tests/009-test-oauth_filter.py b/tests/009-test-oauth_filter.py index f92393e4..ce4cce49 100644 --- a/tests/009-test-oauth_filter.py +++ b/tests/009-test-oauth_filter.py @@ -13,14 +13,14 @@ # Secret: 0e9e6413a9ef49510a4f68ed02cd try: - from urlparse import parse_qs, parse_qsl + from urllib.parse import parse_qs, parse_qsl except ImportError: from cgi import parse_qs, parse_qsl -import urllib +import urllib.request, urllib.parse, urllib.error from restkit import request, OAuthFilter from restkit.oauth2 import Consumer -import t +from . import t class oauth_request(object): @@ -50,8 +50,8 @@ def __init__(self, utype): def __call__(self, func): def run(): o = OAuthFilter('*', self.consumer) - func(o, self.url, urllib.urlencode(self.body)) - run.func_name = func.func_name + func(o, self.url, urllib.parse.urlencode(self.body)) + run.__name__ = func.__name__ return run @oauth_request('request_token') @@ -73,7 +73,7 @@ def test_003(o, u, b): r = request(u, "POST", body=b, filters=[o], headers={"Content-type": "application/x-www-form-urlencoded"}) import sys - print >>sys.stderr, r.body_string() + print(r.body_string(), file=sys.stderr) t.eq(r.status_int, 200) # Because this is a POST and an application/x-www-form-urlencoded, the OAuth # can include the OAuth parameters directly into the body of the form, however diff --git a/tests/010-test-proxies.py b/tests/010-test-proxies.py index 58b3fff8..3ebba13e 100644 --- a/tests/010-test-proxies.py +++ b/tests/010-test-proxies.py @@ -3,8 +3,8 @@ # This file is part of restkit released under the MIT license. # See the NOTICE for more information. -import t -from _server_test import HOST, PORT +from . import t +from ._server_test import HOST, PORT from restkit.contrib import wsgi_proxy root_uri = "http://%s:%s" % (HOST, PORT) @@ -15,7 +15,7 @@ def wrapper(*args, **kwargs): req = Request.blank('/') req.environ['SERVER_NAME'] = '%s:%s' % (HOST, PORT) return func(req) - wrapper.func_name = func.func_name + wrapper.__name__ = func.__name__ return wrapper @with_webob @@ -95,7 +95,7 @@ def test_007(req): resp = req.get_response(proxy) body = resp.body - print resp.location + print((resp.location)) assert resp.location == '%s/complete_redirect' % root_uri, str(resp) @with_webob diff --git a/tests/_server_test.py b/tests/_server_test.py index 136a54fb..6e483034 100644 --- a/tests/_server_test.py +++ b/tests/_server_test.py @@ -16,21 +16,21 @@ # import base64 -from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer +from http.server import BaseHTTPRequestHandler, HTTPServer import cgi import os import socket import tempfile import threading import unittest -import urlparse -import Cookie +import urllib.parse +import http.cookies try: - from urlparse import parse_qsl, parse_qs + from urllib.parse import parse_qsl, parse_qs except ImportError: from cgi import parse_qsl, parse_qs -import urllib +import urllib.request, urllib.parse, urllib.error from restkit.util import to_bytestring HOST = 'localhost' @@ -45,7 +45,7 @@ def __init__(self, request, client_address, server): def do_GET(self): - self.parsed_uri = urlparse.urlparse(urllib.unquote(self.path)) + self.parsed_uri = urllib.parse.urlparse(urllib.parse.unquote(self.path)) self.query = {} for k, v in parse_qsl(self.parsed_uri[4]): self.query[k] = v.decode('utf-8') @@ -57,7 +57,7 @@ def do_GET(self): elif path == "/unicode": extra_headers = [('Content-type', 'text/plain')] - self._respond(200, extra_headers, u"éàù@") + self._respond(200, extra_headers, "éàù@") elif path == "/json": content_type = self.headers.get('content-type', 'text/plain') @@ -122,21 +122,21 @@ def do_GET(self): self._respond(200, extra_headers, "ok") elif path == "/cookie": - c = Cookie.SimpleCookie() + c = http.cookies.SimpleCookie() c["fig"] = "newton" c['fig']['path'] = "/" - for k in c.keys(): + for k in list(c.keys()): extra_headers = [('Set-Cookie', str(c[k].output(header='')))] self._respond(200, extra_headers, "ok") elif path == "/cookies": - c = Cookie.SimpleCookie() + c = http.cookies.SimpleCookie() c["fig"] = "newton" c['fig']['path'] = "/" c["sugar"] = "wafer" c['sugar']['path'] = "/" extra_headers = [] - for k in c.keys(): + for k in list(c.keys()): extra_headers.append(('Set-Cookie', str(c[k].output(header='')))) self._respond(200, extra_headers, "ok") @@ -146,7 +146,7 @@ def do_GET(self): def do_POST(self): - self.parsed_uri = urlparse.urlparse(self.path) + self.parsed_uri = urllib.parse.urlparse(self.path) self.query = {} for k, v in parse_qsl(self.parsed_uri[4]): self.query[k] = v.decode('utf-8') diff --git a/tests/t.py b/tests/t.py index 3bae49e6..84f48007 100644 --- a/tests/t.py +++ b/tests/t.py @@ -4,10 +4,10 @@ # This file is part of gunicorn released under the MIT license. # See the NOTICE for more information. -from __future__ import with_statement + import os -from StringIO import StringIO +from io import StringIO import tempfile dirname = os.path.dirname(__file__) @@ -15,7 +15,7 @@ from restkit.client import Client from restkit.resource import Resource -from _server_test import HOST, PORT, run_server_test +from ._server_test import HOST, PORT, run_server_test run_server_test() def data_source(fname): @@ -71,7 +71,7 @@ def __call__(self, func): def run(): cli = Client(timeout=300) func(self.url, cli) - run.func_name = func.func_name + run.__name__ = func.__name__ return run class resource_request(object): @@ -86,7 +86,7 @@ def __call__(self, func): def run(): res = Resource(self.url) func(res) - run.func_name = func.func_name + run.__name__ = func.__name__ return run diff --git a/tests/treq.py b/tests/treq.py index 7d216f6b..e2d61763 100644 --- a/tests/treq.py +++ b/tests/treq.py @@ -3,15 +3,15 @@ # This file is part of the pywebmachine package released # under the MIT license. -from __future__ import with_statement -import t + +from . import t import inspect import os import random -from StringIO import StringIO -import urlparse +from io import StringIO +import urllib.parse from restkit.datastructures import MultiDict from restkit.errors import ParseException @@ -28,7 +28,7 @@ def _data(self): if not self.iter: return "" try: - return self.iter.next() + return next(self.iter) except StopIteration: self.iter = None return "" @@ -39,7 +39,7 @@ def _data(self): def uri(data): ret = {"raw": data} - parts = urlparse.urlparse(data) + parts = urllib.parse.urlparse(data) ret["scheme"] = parts.scheme or None ret["host"] = parts.netloc.rsplit(":", 1)[0] or None ret["port"] = parts.port or 80 @@ -60,7 +60,7 @@ def uri(data): def load_response_py(fname): config = globals().copy() config["uri"] = uri - execfile(fname, config) + exec(compile(open(fname).read(), fname, 'exec'), config) return config["response"] class response(object): @@ -209,7 +209,7 @@ def match_iter(self, req, body, sizes): if len(body): raise AssertionError("Failed to read entire body: %r" % body) try: - data = iter(req.body).next() + data = next(iter(req.body)) raise AssertionError("Read data after body finished: %r" % data) except StopIteration: pass @@ -232,9 +232,9 @@ def get_funs(p): ret = [] for (mt, sz, sn) in cfgs: - mtn = mt.func_name[6:] - szn = sz.func_name[5:] - snn = sn.func_name[5:] + mtn = mt.__name__[6:] + szn = sz.__name__[5:] + snn = sn.__name__[5:] def test_req(sn, sz, mt): self.check(sn, sz, mt) desc = "%s: MT: %s SZ: %s SN: %s" % (self.name, mtn, szn, snn)