|  | # Copyright 2012 Canonical Ltd.  This software is licensed under the | 
|  | # GNU Affero General Public License version 3 (see the file LICENSE). | 
|  |  | 
|  | """Remote API library.""" | 
|  |  | 
|  | from __future__ import ( | 
|  | absolute_import, | 
|  | print_function, | 
|  | unicode_literals, | 
|  | ) | 
|  |  | 
|  | str = None | 
|  |  | 
|  | __metaclass__ = type | 
|  | __all__ = [ | 
|  | "ascii_url", | 
|  | "urlencode", | 
|  | ] | 
|  |  | 
|  |  | 
|  | from urllib import quote_plus | 
|  | from urlparse import urlparse | 
|  |  | 
|  |  | 
|  | def ascii_url(url): | 
|  | """Encode `url` as ASCII if it isn't already.""" | 
|  | if isinstance(url, unicode): | 
|  | urlparts = urlparse(url) | 
|  | urlparts = urlparts._replace( | 
|  | netloc=urlparts.netloc.encode("idna")) | 
|  | url = urlparts.geturl() | 
|  | return url.encode("ascii") | 
|  |  | 
|  |  | 
|  | def urlencode(data): | 
|  | """A version of `urllib.urlencode` that isn't insane. | 
|  |  | 
|  | This only cares that `data` is an iterable of iterables. Each sub-iterable | 
|  | must be of overall length 2, i.e. a name/value pair. | 
|  |  | 
|  | Unicode strings will be encoded to UTF-8. This is what Django expects; see | 
|  | `smart_text` in the Django documentation. | 
|  | """ | 
|  | enc = lambda string: quote_plus( | 
|  | string.encode("utf-8") if isinstance(string, unicode) else string) | 
|  | return b"&".join( | 
|  | b"%s=%s" % (enc(name), enc(value)) | 
|  | for name, value in data) |