| Index: third_party/google-endpoints/requests/packages/urllib3/util/url.py
|
| diff --git a/third_party/google-endpoints/requests/packages/urllib3/util/url.py b/third_party/google-endpoints/requests/packages/urllib3/util/url.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..61a326e4411426513824503afb2417056240faec
|
| --- /dev/null
|
| +++ b/third_party/google-endpoints/requests/packages/urllib3/util/url.py
|
| @@ -0,0 +1,226 @@
|
| +from __future__ import absolute_import
|
| +from collections import namedtuple
|
| +
|
| +from ..exceptions import LocationParseError
|
| +
|
| +
|
| +url_attrs = ['scheme', 'auth', 'host', 'port', 'path', 'query', 'fragment']
|
| +
|
| +
|
| +class Url(namedtuple('Url', url_attrs)):
|
| + """
|
| + Datastructure for representing an HTTP URL. Used as a return value for
|
| + :func:`parse_url`. Both the scheme and host are normalized as they are
|
| + both case-insensitive according to RFC 3986.
|
| + """
|
| + __slots__ = ()
|
| +
|
| + def __new__(cls, scheme=None, auth=None, host=None, port=None, path=None,
|
| + query=None, fragment=None):
|
| + if path and not path.startswith('/'):
|
| + path = '/' + path
|
| + if scheme:
|
| + scheme = scheme.lower()
|
| + if host:
|
| + host = host.lower()
|
| + return super(Url, cls).__new__(cls, scheme, auth, host, port, path,
|
| + query, fragment)
|
| +
|
| + @property
|
| + def hostname(self):
|
| + """For backwards-compatibility with urlparse. We're nice like that."""
|
| + return self.host
|
| +
|
| + @property
|
| + def request_uri(self):
|
| + """Absolute path including the query string."""
|
| + uri = self.path or '/'
|
| +
|
| + if self.query is not None:
|
| + uri += '?' + self.query
|
| +
|
| + return uri
|
| +
|
| + @property
|
| + def netloc(self):
|
| + """Network location including host and port"""
|
| + if self.port:
|
| + return '%s:%d' % (self.host, self.port)
|
| + return self.host
|
| +
|
| + @property
|
| + def url(self):
|
| + """
|
| + Convert self into a url
|
| +
|
| + This function should more or less round-trip with :func:`.parse_url`. The
|
| + returned url may not be exactly the same as the url inputted to
|
| + :func:`.parse_url`, but it should be equivalent by the RFC (e.g., urls
|
| + with a blank port will have : removed).
|
| +
|
| + Example: ::
|
| +
|
| + >>> U = parse_url('http://google.com/mail/')
|
| + >>> U.url
|
| + 'http://google.com/mail/'
|
| + >>> Url('http', 'username:password', 'host.com', 80,
|
| + ... '/path', 'query', 'fragment').url
|
| + 'http://username:password@host.com:80/path?query#fragment'
|
| + """
|
| + scheme, auth, host, port, path, query, fragment = self
|
| + url = ''
|
| +
|
| + # We use "is not None" we want things to happen with empty strings (or 0 port)
|
| + if scheme is not None:
|
| + url += scheme + '://'
|
| + if auth is not None:
|
| + url += auth + '@'
|
| + if host is not None:
|
| + url += host
|
| + if port is not None:
|
| + url += ':' + str(port)
|
| + if path is not None:
|
| + url += path
|
| + if query is not None:
|
| + url += '?' + query
|
| + if fragment is not None:
|
| + url += '#' + fragment
|
| +
|
| + return url
|
| +
|
| + def __str__(self):
|
| + return self.url
|
| +
|
| +
|
| +def split_first(s, delims):
|
| + """
|
| + Given a string and an iterable of delimiters, split on the first found
|
| + delimiter. Return two split parts and the matched delimiter.
|
| +
|
| + If not found, then the first part is the full input string.
|
| +
|
| + Example::
|
| +
|
| + >>> split_first('foo/bar?baz', '?/=')
|
| + ('foo', 'bar?baz', '/')
|
| + >>> split_first('foo/bar?baz', '123')
|
| + ('foo/bar?baz', '', None)
|
| +
|
| + Scales linearly with number of delims. Not ideal for large number of delims.
|
| + """
|
| + min_idx = None
|
| + min_delim = None
|
| + for d in delims:
|
| + idx = s.find(d)
|
| + if idx < 0:
|
| + continue
|
| +
|
| + if min_idx is None or idx < min_idx:
|
| + min_idx = idx
|
| + min_delim = d
|
| +
|
| + if min_idx is None or min_idx < 0:
|
| + return s, '', None
|
| +
|
| + return s[:min_idx], s[min_idx + 1:], min_delim
|
| +
|
| +
|
| +def parse_url(url):
|
| + """
|
| + Given a url, return a parsed :class:`.Url` namedtuple. Best-effort is
|
| + performed to parse incomplete urls. Fields not provided will be None.
|
| +
|
| + Partly backwards-compatible with :mod:`urlparse`.
|
| +
|
| + Example::
|
| +
|
| + >>> parse_url('http://google.com/mail/')
|
| + Url(scheme='http', host='google.com', port=None, path='/mail/', ...)
|
| + >>> parse_url('google.com:80')
|
| + Url(scheme=None, host='google.com', port=80, path=None, ...)
|
| + >>> parse_url('/foo?bar')
|
| + Url(scheme=None, host=None, port=None, path='/foo', query='bar', ...)
|
| + """
|
| +
|
| + # While this code has overlap with stdlib's urlparse, it is much
|
| + # simplified for our needs and less annoying.
|
| + # Additionally, this implementations does silly things to be optimal
|
| + # on CPython.
|
| +
|
| + if not url:
|
| + # Empty
|
| + return Url()
|
| +
|
| + scheme = None
|
| + auth = None
|
| + host = None
|
| + port = None
|
| + path = None
|
| + fragment = None
|
| + query = None
|
| +
|
| + # Scheme
|
| + if '://' in url:
|
| + scheme, url = url.split('://', 1)
|
| +
|
| + # Find the earliest Authority Terminator
|
| + # (http://tools.ietf.org/html/rfc3986#section-3.2)
|
| + url, path_, delim = split_first(url, ['/', '?', '#'])
|
| +
|
| + if delim:
|
| + # Reassemble the path
|
| + path = delim + path_
|
| +
|
| + # Auth
|
| + if '@' in url:
|
| + # Last '@' denotes end of auth part
|
| + auth, url = url.rsplit('@', 1)
|
| +
|
| + # IPv6
|
| + if url and url[0] == '[':
|
| + host, url = url.split(']', 1)
|
| + host += ']'
|
| +
|
| + # Port
|
| + if ':' in url:
|
| + _host, port = url.split(':', 1)
|
| +
|
| + if not host:
|
| + host = _host
|
| +
|
| + if port:
|
| + # If given, ports must be integers. No whitespace, no plus or
|
| + # minus prefixes, no non-integer digits such as ^2 (superscript).
|
| + if not port.isdigit():
|
| + raise LocationParseError(url)
|
| + try:
|
| + port = int(port)
|
| + except ValueError:
|
| + raise LocationParseError(url)
|
| + else:
|
| + # Blank ports are cool, too. (rfc3986#section-3.2.3)
|
| + port = None
|
| +
|
| + elif not host and url:
|
| + host = url
|
| +
|
| + if not path:
|
| + return Url(scheme, auth, host, port, path, query, fragment)
|
| +
|
| + # Fragment
|
| + if '#' in path:
|
| + path, fragment = path.split('#', 1)
|
| +
|
| + # Query
|
| + if '?' in path:
|
| + path, query = path.split('?', 1)
|
| +
|
| + return Url(scheme, auth, host, port, path, query, fragment)
|
| +
|
| +
|
| +def get_host(url):
|
| + """
|
| + Deprecated. Use :func:`parse_url` instead.
|
| + """
|
| + p = parse_url(url)
|
| + return p.scheme or 'http', p.hostname, p.port
|
|
|