- Rick Mak
- Johan Bergström
- Josselin Jacquard
+- Michael Van Veen <michael@mvanveen.net>
- Mike Waldner
-- Serge Domkowski
\ No newline at end of file
+- Serge Domkowski
headers[k] = header_expand(v)
args = dict(
- method = method,
- url = url,
- data = data,
- params = params,
- headers = headers,
- cookiejar = cookies,
- files = files,
- auth = auth,
- timeout = timeout or config.settings.timeout,
- allow_redirects = allow_redirects,
- proxies = proxies or config.settings.proxies,
+ method=method,
+ url=url,
+ data=data,
+ params=params,
+ headers=headers,
+ cookiejar=cookies,
+ files=files,
+ auth=auth,
+ timeout=timeout or config.settings.timeout,
+ allow_redirects=allow_redirects,
+ proxies=proxies or config.settings.proxies,
)
# Arguments manipulation hook.
This module provides the Requests settings feature set.
+settings parameters:
+
+TODO: Verify!!!
+TODO: Make sure format is acceptabl/cool
+- :base_headers: - Sets default User-Agent to `python-requests.org`
+- :accept_gzip: - Whether or not to accept gzip-compressed data
+- :proxies: - http proxies?
+- :verbose: - display verbose information?
+- :timeout: - timeout time until request terminates
+- :max_redirects: - maximum number of allowed redirects?
+- :decode_unicode: - whether or not to accept unicode?
+
+Used globally
+
"""
+
class Settings(object):
def __init__(self, **kwargs):
from status_codes import codes
from config import settings
-import utils
\ No newline at end of file
+import utils
"""
+
class RequestException(Exception):
"""There was an ambiguous exception that occured while handling your
request."""
+
class AuthenticationError(RequestException):
"""The authentication credentials provided were invalid."""
-
+
+
class Timeout(RequestException):
"""The request timed out."""
+
class URLRequired(RequestException):
"""A valid URL is required to make a request."""
+
class InvalidMethod(RequestException):
"""An inappropriate method was attempted."""
+
class TooManyRedirects(RequestException):
"""Too many redirects."""
REDIRECT_STATI = (codes.moved, codes.found, codes.other, codes.temporary_moved)
-
class Request(object):
"""The :class:`Request <Request>` object. It carries out all functionality of
Requests. Recommended interface is with the Requests functions.
#: True if Request has been sent.
self.sent = False
-
# Header manipulation and defaults.
if settings.accept_gzip:
self.headers = headers
-
def __repr__(self):
return '<Request [%s]>' % (self.method)
-
def _checks(self):
"""Deterministic checks for consistency."""
if not self.url:
raise URLRequired
-
def _get_opener(self):
"""Creates appropriate opener object for urllib2."""
return opener.open
-
def _build_response(self, resp, is_error=False):
"""Build internal :class:`Response <Response>` object
from given response.
"""
-
def build(resp):
response = Response()
response.cookies = dict_from_cookiejar(self.cookiejar)
-
except AttributeError:
pass
return response
-
history = []
r = build(resp)
self.response = r
self.response.request = self
-
@staticmethod
def _encode_params(data):
"""Encode parameters in a piece of data.
for k, vs in data.items():
for v in isinstance(vs, list) and vs or [vs]:
result.append((k.encode('utf-8') if isinstance(k, unicode) else k,
- v.encode('utf-8') if isinstance(v, unicode) else v))
- return result, urllib.urlencode(result, doseq=True)
+ v.encode('utf-8') if isinstance(v, unicode) else v)
+ )
+ return (result, urllib.urlencode(result, doseq=True))
+
else:
return data, data
-
def _build_url(self):
"""Build the actual URL to use."""
# Support for unicode domain names and paths.
scheme, netloc, path, params, query, fragment = urlparse(self.url)
netloc = netloc.encode('idna')
+
if isinstance(path, unicode):
path = path.encode('utf-8')
+
path = urllib.quote(path, safe="%/:=&?~#+!$,;'@()*[]")
- self.url = str(urlunparse([ scheme, netloc, path, params, query, fragment ]))
+
+ self.url = str(urlunparse(
+ [scheme, netloc, path, params, query, fragment]
+ ))
if self._enc_params:
if urlparse(self.url).query:
else:
return self.url
-
def send(self, anyway=False):
"""Sends the request. Returns True of successful, false if not.
If there was an HTTPError during transmission,
datetime.now().isoformat(), self.method, self.url
))
-
url = self._build_url()
if self.method in ('GET', 'HEAD', 'DELETE'):
req = _Request(url, method=self.method)
req = _Request(url, data=self._enc_data, method=self.method)
if self.headers:
- for k,v in self.headers.iteritems():
+ for k, v in self.headers.iteritems():
req.add_header(k, v)
if not self.sent or anyway:
self._build_response(resp)
self.response.ok = True
-
self.sent = self.response.ok
return self.sent
class Response(object):
- """The core :class:`Response <Response>` object. All
- :class:`Request <Request>` objects contain a
- :class:`response <Response>` attribute, which is an instance
- of this class.
+ """The core :class:`Response <Response>` object.
+
+
+ All :class:`Request <Request>` objects contain a :class:`response
+ <Response>` attribute, which is an instance of this class.
"""
def __init__(self):
#: A dictionary of Cookies the server sent back.
self.cookies = None
-
def __repr__(self):
return '<Response [%s]>' % (self.status_code)
-
def __nonzero__(self):
"""Returns true if :attr:`status_code` is 'OK'."""
self._content_consumed = True
return self._content
-
def raise_for_status(self):
"""Raises stored :class:`HTTPError` or :class:`URLError`, if one occured."""
if self.error:
raise self.error
-
class AuthManager(object):
"""Requests Authentication Manager."""
return singleton
-
def __init__(self):
self.passwd = {}
self._auth = {}
-
def __repr__(self):
return '<AuthManager [%s]>' % (self.method)
-
def add_auth(self, uri, auth):
"""Registers AuthObject to AuthManager."""
self._auth[uri] = auth
-
def add_password(self, realm, uri, user, passwd):
"""Adds password to AuthManager."""
# uri could be a single URI or a sequence
self.passwd[reduced_uri] = {}
self.passwd[reduced_uri] = (user, passwd)
-
def find_user_password(self, realm, authuri):
for uris, authinfo in self.passwd.iteritems():
reduced_authuri = self.reduce_uri(authuri, False)
return (None, None)
-
def get_auth(self, uri):
(in_domain, in_path) = self.reduce_uri(uri, False)
if path in in_path:
return authority
-
def reduce_uri(self, uri, default_port=True):
"""Accept authority or URI and extract only the authority and path."""
return authority, path
-
def is_suburi(self, base, test):
"""Check if test is below base in a URI tree
return True
return False
-
def empty(self):
self.passwd = {}
-
def remove(self, uri, realm=None):
# uri could be a single URI or a sequence
if isinstance(uri, basestring):
reduced_uri = tuple([self.reduce_uri(u, default_port) for u in uri])
del self.passwd[reduced_uri][realm]
-
def __contains__(self, uri):
# uri could be a single URI or a sequence
if isinstance(uri, basestring):
auth_manager = AuthManager()
-
class AuthObject(object):
- """The :class:`AuthObject` is a simple HTTP Authentication token. When
- given to a Requests function, it enables Basic HTTP Authentication for that
- Request. You can also enable Authorization for domain realms with AutoAuth.
- See AutoAuth for more details.
+ """The :class:`AuthObject` is a simple HTTP Authentication token.
+
+ When given to a Requests function, it enables Basic HTTP Authentication
+ for that Request. You can also enable Authorization for domain realms
+ with AutoAuth. See AutoAuth for more details.
:param username: Username to authenticate with.
:param password: Password for given username.
"""
-import urllib2
import re
+import urllib2
+
class Request(urllib2.Request):
"""Hidden wrapper around the urllib2.Request object. Allows for manual
http_error_302 = http_error_303 = http_error_307 = http_error_301
-
class HTTPBasicAuthHandler(urllib2.HTTPBasicAuthHandler):
"""HTTP Basic Auth Handler with authentication loop fixes."""
self.retried_req = None
self.retried = 0
-
def reset_retry_count(self):
# Python 2.6.5 will call this on 401 or 407 errors and thus loop
# forever. We disable reset_retry_count completely and reset in
# http_error_auth_reqed instead.
pass
-
def http_error_auth_reqed(self, auth_header, host, req, headers):
# Reset the retry counter once for each request.
if req is not self.retried_req:
)
-
class HTTPForcedBasicAuthHandler(HTTPBasicAuthHandler):
"""HTTP Basic Auth Handler with forced Authentication."""
rx = re.compile('(?:.*,)*[ \t]*([^ \t]+)[ \t]+'
'realm=(["\'])(.*?)\\2', re.I)
- def __init__(self, *args, **kwargs):
+ def __init__(self, *args, **kwargs):
HTTPBasicAuthHandler.__init__(self, *args, **kwargs)
-
def http_error_401(self, req, fp, code, msg, headers):
url = req.get_full_url()
response = self._http_error_auth_reqed('www-authenticate', url, req, headers)
http_error_404 = http_error_401
-
def _http_error_auth_reqed(self, authreq, host, req, headers):
authreq = headers.get(authreq, None)
return response
-
class HTTPDigestAuthHandler(urllib2.HTTPDigestAuthHandler):
def __init__(self, *args, **kwargs):
arg = inst.args[0]
if arg.startswith("AbstractDigestAuthHandler doesn't know "):
return
- raise
\ No newline at end of file
+ raise
from .utils import add_dict_to_cookiejar
-
class Session(object):
"""A Requests session."""
__attrs__ = ['headers', 'cookies', 'auth', 'timeout', 'proxies', 'hooks']
-
def __init__(self, **kwargs):
# Set up a CookieJar to be used by default
# Map and wrap requests.api methods
self._map_api_methods()
-
def __repr__(self):
return '<requests-client at 0x%x>' % (id(self))
# print args
pass
-
def _map_api_methods(self):
"""Reads each available method from requests.api and decorates
them with a wrapper, which inserts any instance-local attributes
def session(**kwargs):
"""Returns a :class:`Session` for context-managment."""
- return Session(**kwargs)
\ No newline at end of file
+ return Session(**kwargs)
for title in titles:
setattr(codes, title, code)
if not title.startswith('\\'):
- setattr(codes, title.upper(), code)
\ No newline at end of file
+ setattr(codes, title.upper(), code)
"""
+
class CaseInsensitiveDict(dict):
"""Case-insensitive Dictionary
else:
return default
+
class LookupDict(dict):
"""Dictionary lookup object."""
return self.__dict__.get(key, None)
def get(self, key, default=None):
- return self.__dict__.get(key, default)
\ No newline at end of file
+ return self.__dict__.get(key, default)
collector.append('; '.join(_params))
- if not len(headers) == i+1:
+ if not len(headers) == i + 1:
collector.append(', ')
-
# Remove trailing seperators.
if collector[-1] in (', ', '; '):
del collector[-1]
return ''.join(collector)
-
def dict_from_cookiejar(cj):
"""Returns a key/value dictionary from a CookieJar.
:param content: bytestring to gzip-decode.
"""
- return zlib.decompress(content, 16+zlib.MAX_WBITS)
- return zlib.decompress(content, 16+zlib.MAX_WBITS)
+ return zlib.decompress(content, 16 + zlib.MAX_WBITS)
+ return zlib.decompress(content, 16 + zlib.MAX_WBITS)
return zlib.decompress(content, 16 + zlib.MAX_WBITS)
except zlib.error:
pass
+
def curl_from_request(request):
"""Returns a curl command from the request.
#: -u/--user - Specify the user name and password to use for server auth.
#: Basic Auth only for now
auth = ''
+
if request.auth is not None:
- auth = '-u "%s:%s" ' % (request.auth.username, request.auth.password)
+
+ auth = '-u "%s:%s" ' % (request.auth.username, request.auth.password)
method = ''
+
if request.method.upper() == 'HEAD':
#: -I/--head - fetch headers only.
method = '-I '
#: Params handled in _build_url
return curl + auth + method + header + cookies + form + '"' + request._build_url() + '"'
-