Merge branch 'feature/config' into develop

This commit is contained in:
Kenneth Reitz
2011-10-22 20:32:11 -04:00
8 changed files with 145 additions and 113 deletions
+1
View File
@@ -7,6 +7,7 @@ History
* Sessions are now the primary interface.
* Deprecated InvalidMethodException.
* PATCH fix.
* New config system (no more global settings).
0.6.6 (2011-10-19)
+2 -2
View File
@@ -39,8 +39,8 @@ Sessions can also be used to provide default data to the request methods::
.. admonition:: Global Settings
Certain parameters are best set at the ``request.config`` level
(e.g.. a global proxy, user agent header).
Certain parameters are best set in the ``config`` dictionary
(e.g. user agent header).
Asynchronous Requests
-1
View File
@@ -27,7 +27,6 @@ from .models import HTTPError, Request, Response
from .api import request, get, head, post, patch, put, delete
from .sessions import session
from .status_codes import codes
from .config import settings
from .exceptions import (
RequestException, AuthenticationError, Timeout, URLRequired,
TooManyRedirects
+14 -3
View File
@@ -17,13 +17,24 @@ __all__ = ('request', 'get', 'head', 'post', 'patch', 'put', 'delete')
def request(method, url,
params=None, data=None, headers=None, cookies=None, files=None, auth=None,
timeout=None, allow_redirects=False, proxies=None, hooks=None, return_response=True):
params=None,
data=None,
headers=None,
cookies=None,
files=None,
auth=None,
timeout=None,
allow_redirects=False,
proxies=None,
hooks=None,
return_response=True,
config=None):
s = session()
return s.request(
method, url, params, data, headers, cookies, files, auth,
timeout, allow_redirects, proxies, hooks, return_response
timeout, allow_redirects, proxies, hooks, return_response,
config
)
-68
View File
@@ -1,68 +0,0 @@
# -*- coding: utf-8 -*-
"""
requests.config
~~~~~~~~~~~~~~~
This module provides the Requests settings feature set.
"""
class Settings(object):
_singleton = {}
# attributes with defaults
__attrs__ = []
def __init__(self, **kwargs):
super(Settings, self).__init__()
self.__dict__ = self._singleton
def __call__(self, *args, **kwargs):
# new instance of class to call
r = self.__class__()
# cache previous settings for __exit__
r.__cache = self.__dict__.copy()
map(self.__cache.setdefault, self.__attrs__)
# set new settings
self.__dict__.update(*args, **kwargs)
return r
def __enter__(self):
pass
def __exit__(self, *args):
# restore cached copy
self.__dict__.update(self.__cache.copy())
del self.__cache
def __getattribute__(self, key):
if key in object.__getattribute__(self, '__attrs__'):
try:
return object.__getattribute__(self, key)
except AttributeError:
return None
return object.__getattribute__(self, key)
settings = Settings()
settings.base_headers = {'User-Agent': 'python-requests.org'}
settings.accept_gzip = True
settings.proxies = None
settings.verbose = None
settings.timeout = None
settings.max_redirects = 30
settings.decode_unicode = True
#: Use socket.setdefaulttimeout() as fallback?
settings.timeout_fallback = True
+48
View File
@@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
"""
requests.defaults
~~~~~~~~~~~~~~~~~
This module provides the Requests configuration defaults.
settings parameters:
- :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?
"""
from . import __version__
defaults = dict()
defaults['base_headers'] = {
'User-Agent': 'python-requests/{0}'.format(__version__),
'Accept-Encoding': ', '.join([ 'identity', 'deflate', 'compress', 'gzip' ]),
}
# defaults['accept_gzip'] = True
defaults['proxies'] = {}
defaults['verbose'] = None
defaults['timeout'] = None
defaults['max_redirects'] = 30
defaults['decode_unicode'] = True
defaults['timeout_fallback'] = True
# defaults['keep_alive'] = True
# defaults['max_connections'] = 10
# defaults['hooks'] = {
# 'args': list(),
# 'pre_request': list(),
# 'post_request': list(),
# 'response': list()
# }
+46 -22
View File
@@ -9,22 +9,22 @@ requests.models
import urllib
import urllib2
import socket
import codecs
import zlib
from urllib2 import HTTPError
from urlparse import urlparse, urlunparse, urljoin
from datetime import datetime
from .config import settings
from .monkeys import Request as _Request, HTTPBasicAuthHandler, HTTPForcedBasicAuthHandler, HTTPDigestAuthHandler, HTTPRedirectHandler
from .structures import CaseInsensitiveDict
from .packages.poster.encode import multipart_encode
from .packages.poster.streaminghttp import register_openers, get_handlers
from .utils import dict_from_cookiejar, get_unicode_from_response, stream_decode_response_unicode, decode_gzip, stream_decode_gzip
from .utils import (dict_from_cookiejar, get_unicode_from_response, stream_decode_response_unicode, decode_gzip, stream_decode_gzip)
from .status_codes import codes
from .exceptions import Timeout, URLRequired, TooManyRedirects
from .monkeys import Request as _Request
from .monkeys import (
HTTPBasicAuthHandler, HTTPForcedBasicAuthHandler,
HTTPDigestAuthHandler, HTTPRedirectHandler)
REDIRECT_STATI = (codes.moved, codes.found, codes.other, codes.temporary_moved)
@@ -37,9 +37,20 @@ class Request(object):
"""
def __init__(self,
url=None, headers=dict(), files=None, method=None, data=dict(),
params=dict(), auth=None, cookies=None, timeout=None, redirect=False,
allow_redirects=False, proxies=None, hooks=None):
url=None,
headers=dict(),
files=None,
method=None,
data=dict(),
params=dict(),
auth=None,
cookies=None,
timeout=None,
redirect=False,
allow_redirects=False,
proxies=None,
hooks=None,
config=None):
#: Float describes the timeout of the request.
# (Use socket.setdefaulttimeout() as fallback)
@@ -93,6 +104,9 @@ class Request(object):
#: CookieJar to attach to :class:`Request <Request>`.
self.cookies = cookies
#: Dictionary of configurations for this request.
self.config = config
#: True if Request has been sent.
self.sent = False
@@ -100,16 +114,15 @@ class Request(object):
self.hooks = hooks
# Header manipulation and defaults.
if settings.accept_gzip:
settings.base_headers.update({'Accept-Encoding': 'gzip'})
if self.config.get('accept_gzip'):
self.headers.update({'Accept-Encoding': 'gzip'})
if headers:
headers = CaseInsensitiveDict(self.headers)
else:
headers = CaseInsensitiveDict()
for (k, v) in settings.base_headers.items():
for (k, v) in self.config.get('base_headers', {}).items():
if k not in headers:
headers[k] = v
@@ -185,6 +198,7 @@ class Request(object):
def build(resp):
response = Response()
response.config = self.config
response.status_code = getattr(resp, 'code', None)
try:
@@ -219,7 +233,7 @@ class Request(object):
r.raw.close()
if not len(history) < settings.max_redirects:
if not len(history) < self.config.get('max_redirects'):
raise TooManyRedirects()
history.append(r)
@@ -243,9 +257,16 @@ class Request(object):
method = self.method
request = Request(
url, self.headers, self.files, method,
self.data, self.params, self.auth, self.cookies,
redirect=True
url=url,
headers=self.headers,
files=self.files,
method=method,
# data=self.data,
# params=self.params,
auth=self.auth,
cookies=self.cookies,
redirect=True,
config=self.config
)
request.send()
r = request.response
@@ -313,8 +334,8 @@ class Request(object):
self._checks()
# Logging
if settings.verbose:
settings.verbose.write('%s %s %s\n' % (
if self.config.get('verbose'):
self.config.get('verbose').write('%s %s %s\n' % (
datetime.now().isoformat(), self.method, self.url
))
@@ -353,14 +374,14 @@ class Request(object):
if not 'timeout' in str(err):
raise
if settings.timeout_fallback:
if self.config.get('timeout_fallback'):
# fall-back and use global socket timeout (This is not thread-safe!)
old_timeout = socket.getdefaulttimeout()
socket.setdefaulttimeout(self.timeout)
resp = opener(req)
if settings.timeout_fallback:
if self.config.get('timeout_fallback'):
# restore global timeout
socket.setdefaulttimeout(old_timeout)
@@ -429,6 +450,9 @@ class Response(object):
#: A dictionary of Cookies the server sent back.
self.cookies = None
#: Dictionary of configurations for this request.
self.config = None
def __repr__(self):
return '<Response [%s]>' % (self.status_code)
@@ -460,7 +484,7 @@ class Response(object):
if 'gzip' in self.headers.get('content-encoding', ''):
gen = stream_decode_gzip(gen)
if decode_unicode is None:
decode_unicode = settings.decode_unicode
decode_unicode = self.config.get('decode_unicode')
if decode_unicode:
gen = stream_decode_response_unicode(gen, self)
return gen
@@ -489,7 +513,7 @@ class Response(object):
pass
# Decode unicode content.
if settings.decode_unicode:
if self.config.get('decode_unicode'):
self._content = get_unicode_from_response(self)
self._content_consumed = True
+34 -17
View File
@@ -11,7 +11,7 @@ requests (cookies, auth, proxies).
import cookielib
from . import config
from .defaults import defaults
from .models import Request
from .hooks import dispatch_hook
from .utils import add_dict_to_cookiejar, cookiejar_from_dict, header_expand
@@ -51,7 +51,7 @@ def merge_kwargs(local_kwarg, default_kwarg):
class Session(object):
"""A Requests session."""
__attrs__ = ['headers', 'cookies', 'auth', 'timeout', 'proxies', 'hooks', 'params']
__attrs__ = ['headers', 'cookies', 'auth', 'timeout', 'proxies', 'hooks', 'params', 'config']
def __init__(self,
@@ -61,7 +61,8 @@ class Session(object):
timeout=None,
proxies=None,
hooks=None,
params=None):
params=None,
config=None):
self.headers = headers or {}
self.cookies = cookies or {}
@@ -70,6 +71,10 @@ class Session(object):
self.proxies = proxies or {}
self.hooks = hooks or {}
self.params = params or {}
self.config = config or {}
for (k, v) in defaults.items():
self.config.setdefault(k, v)
# Set up a CookieJar to be used by default
self.cookies = cookielib.FileCookieJar()
@@ -84,8 +89,18 @@ class Session(object):
pass
def request(self, method, url,
params=None, data=None, headers=None, cookies=None, files=None, auth=None,
timeout=None, allow_redirects=False, proxies=None, hooks=None, return_response=True):
params=None,
data=None,
headers=None,
cookies=None,
files=None,
auth=None,
timeout=None,
allow_redirects=False,
proxies=None,
hooks=None,
return_response=True,
config=None):
"""Constructs and sends a :class:`Request <Request>`.
Returns :class:`Response <Response>` object.
@@ -102,6 +117,7 @@ class Session(object):
:param allow_redirects: (optional) Boolean. Set to True if POST/PUT/DELETE redirect following is allowed.
:param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.
:param return_response: (optional) If False, an un-sent Request object will returned.
:param config: (optional) A configuration dictionary.
"""
method = str(method).upper()
@@ -120,18 +136,19 @@ class Session(object):
headers[k] = header_expand(v)
args = dict(
method = method,
url = url,
data = data,
params = params,
headers = headers,
cookies = cookies,
files = files,
auth = auth,
hooks = hooks,
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,
cookies=cookies,
files=files,
auth=auth,
hooks=hooks,
timeout=timeout,
allow_redirects=allow_redirects,
proxies=proxies,
config=config
)
for attr in self.__attrs__: