mirror of
https://github.com/kennethreitz/requests.git
synced 2026-06-05 22:50:18 +00:00
Reverted hooks from sub-package to module.
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
requests.hooks
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
This module provides the capabilities for the Requests hooks system.
|
||||
|
||||
Available hooks:
|
||||
|
||||
``args``:
|
||||
A dictionary of the arguments being sent to Request().
|
||||
|
||||
``pre_request``:
|
||||
The Request object, directly before being sent.
|
||||
|
||||
``post_request``:
|
||||
The Request object, directly after being sent.
|
||||
|
||||
``response``:
|
||||
The response generated from a Request.
|
||||
|
||||
"""
|
||||
|
||||
import warnings
|
||||
from collections import Iterable
|
||||
import config
|
||||
import zlib
|
||||
import bz2
|
||||
from cgi import parse_header
|
||||
|
||||
def setup_hooks(supplied):
|
||||
"""Setup a hooks mapping, based on the supplied argument. Eache mapping
|
||||
value will be list of hooks that will extend the **default_hooks**.
|
||||
|
||||
:param supplied: a dictionary of hooks. Each value can either be a callable
|
||||
or a list of callables.
|
||||
:type supplied: dict
|
||||
:returns: a dictionary of hooks that extends the **default_hooks** dictionary.
|
||||
:rtype: dict
|
||||
"""
|
||||
|
||||
# Copy the default hooks settings.
|
||||
default = config.settings.default_hooks
|
||||
dispatching = dict([(k, v[:]) for k, v in default.items()])
|
||||
|
||||
# I abandoned the idea of a dictionary of sets because sets may not keep
|
||||
# insertion order, while it may be important. Also, there is no real reason
|
||||
# to force hooks to run once.
|
||||
for hooks, values in supplied.items():
|
||||
hook_list = values if isinstance(values, Iterable) else [values]
|
||||
dispatching[hooks].extend(hook_list)
|
||||
|
||||
# If header is set by config, maybe response is encoded.
|
||||
if config.settings.base_headers.get('Accept-Encoding', ''):
|
||||
if not decode_encoding in dispatching['response']:
|
||||
# It's safer to put decoding as first hook.
|
||||
dispatching['response'].insert(0, decode_encoding)
|
||||
|
||||
if config.settings.decode_unicode:
|
||||
try:
|
||||
# Try unicode encoding just after content decoding...
|
||||
index = dispatching['response'].index(decode_encoding) + 1
|
||||
except ValueError:
|
||||
# ... Or as first hook
|
||||
index = 0
|
||||
dispatching['response'].insert(index, decode_unicode)
|
||||
|
||||
return dispatching
|
||||
|
||||
def dispatch_hooks(hooks, data):
|
||||
"""Dispatches multiple hooks on a given piece of data.
|
||||
|
||||
:param key: the hooks group to lookup
|
||||
:type key: str
|
||||
:param hooks: the hooks dictionary. The value of each key can be a callable
|
||||
object, or a list of callable objects.
|
||||
:type hooks: dict
|
||||
:param data: the object on witch the hooks should be applied
|
||||
:type data: object
|
||||
"""
|
||||
for hook in hooks:
|
||||
try:
|
||||
# hook must be a callable.
|
||||
data = hook(data)
|
||||
|
||||
except Exception, why:
|
||||
|
||||
# Letting users to choose a policy may be an idea. It can be as
|
||||
# simple as "be gracefull, or not":
|
||||
#
|
||||
# config.settings.gracefull_hooks = True | False
|
||||
if not config.settings.gracefull_hooks: raise
|
||||
|
||||
warnings.warn(str(why))
|
||||
|
||||
return data
|
||||
|
||||
#: Example response hook that turns a JSON formatted
|
||||
#: :py:class:`requests.models.Response.content` into a dumped data structure::
|
||||
#:
|
||||
#: try:
|
||||
#: import json
|
||||
#: except ImportError:
|
||||
#: try:
|
||||
#: import simplejson as json
|
||||
#: except ImportError:
|
||||
#: json = False
|
||||
#:
|
||||
#: if json:
|
||||
#: def json_content(r):
|
||||
#: """Turns content into a dumped JSON structure."""
|
||||
#: r._content = json.dumps(r.content)
|
||||
#: return r
|
||||
#:
|
||||
#: Example response hook that turns an XML formatted
|
||||
#: :py:class:`requests.models.Response.content` into an ElementTree::
|
||||
#:
|
||||
#: try:
|
||||
#: from lxml import etree
|
||||
#: except ImportError:
|
||||
#: try:
|
||||
#: import xml.etree.cElementTree as etree
|
||||
#: except ImportError:
|
||||
#: try:
|
||||
#: import xml.etree.ElementTree as etree
|
||||
#: except ImportError:
|
||||
#: try:
|
||||
#: import cElementTree as etree
|
||||
#: except ImportError:
|
||||
#: try:
|
||||
#: import elementtree.ElementTree as etree
|
||||
#: except ImportError:
|
||||
#: etree = False
|
||||
#:
|
||||
#: if etree:
|
||||
#: def etree_content(r):
|
||||
#: """Turns content into an ElementTree structure."""
|
||||
#: r._content = etree.fromstring(r.content)
|
||||
#: return r
|
||||
|
||||
def decode_unicode(r):
|
||||
"""Encode content into unicode string.
|
||||
|
||||
:param r: response object
|
||||
:type r: :py:class:`requests.models.Response`
|
||||
:returns: the same input object.
|
||||
:rtype: :py:class:`requests.models.Response`
|
||||
"""
|
||||
content_type, params = parse_header(r.headers['content-type'])
|
||||
charset = params.get('charset', '').strip("'\"")
|
||||
r._content = unicode(r.content, charset) if charset else unicode(r.content)
|
||||
return r
|
||||
|
||||
def decode_encoding(r):
|
||||
"""Decode content using Contetn-Encoding header.
|
||||
|
||||
:param r: response object
|
||||
:type r: :py:class:`requests.models.Response`
|
||||
:returns: the same input object.
|
||||
:rtype: :py:class:`requests.models.Response`
|
||||
"""
|
||||
|
||||
# Dictionary of content decoders.
|
||||
decode = {
|
||||
# No decoding applied.
|
||||
'identity': lambda content: content,
|
||||
# Decode Response content compressed with deflate.
|
||||
'deflate': lambda content: zlib.decompress(content),
|
||||
# Decode Response content compressed with gzip.
|
||||
'gzip': lambda content: zlib.decompress(content, 16+zlib.MAX_WBITS),
|
||||
# Decode Response content compressed with bz2.
|
||||
# Not a standard Content-Encoding value, but..
|
||||
'bzip2': lambda content: bz2.decompress(content),
|
||||
}
|
||||
# Decode Response content compressed with compress.
|
||||
# If I understood zlib...
|
||||
decode['compress'] = decode['deflate']
|
||||
|
||||
# Apply decoding only if the header is set.
|
||||
encoding = r.headers['content-encoding']
|
||||
if encoding:
|
||||
r._content = decode[encoding](r.content)
|
||||
return r
|
||||
@@ -1,97 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
requests.hooks
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
This module provides the capabilities for the Requests hooks system.
|
||||
|
||||
Available hooks:
|
||||
|
||||
``args``:
|
||||
A dictionary of the arguments being sent to Request().
|
||||
|
||||
``pre_request``:
|
||||
The Request object, directly before being sent.
|
||||
|
||||
``post_request``:
|
||||
The Request object, directly after being sent.
|
||||
|
||||
``response``:
|
||||
The response generated from a Request.
|
||||
|
||||
"""
|
||||
|
||||
import warnings
|
||||
from collections import Iterable
|
||||
from .. import config
|
||||
from . import args
|
||||
from . import pre_request
|
||||
from . import post_request
|
||||
from . import response
|
||||
|
||||
def setup_hooks(supplied):
|
||||
"""Setup the supplied dictionary of hooks.
|
||||
Each value is a list of hooks and will extend **default_hooks**.
|
||||
|
||||
:param supplied: a dictionary of hooks. Each value can either be a callable
|
||||
or a list of callables.
|
||||
:type supplied: dict
|
||||
:returns: a dictionary of hooks that extends the **default_hooks** dictionary.
|
||||
:rtype: dict
|
||||
"""
|
||||
|
||||
# Copy the default hooks settings.
|
||||
default = config.settings.default_hooks
|
||||
dispatching = dict([(k, v[:]) for k, v in default.items()])
|
||||
|
||||
# I abandoned the idea of a dictionary of sets because sets may not keep
|
||||
# insertion order, while it may be important. Also, there is no real reason
|
||||
# to force hooks to run once.
|
||||
for hooks, values in supplied.items():
|
||||
hook_list = values if isinstance(values, Iterable) else [values]
|
||||
dispatching[hooks].extends(hook_list)
|
||||
|
||||
# If header is set, maybe response is encoded. Whatever hook you want to
|
||||
# run on response, content decoding should be first.
|
||||
if config.settings.base_headers.get('Accept-Encoding', ''):
|
||||
dispatching['response'].insert(0, response.decode_encoding)
|
||||
|
||||
if config.settings.decode_unicode:
|
||||
try:
|
||||
# Try unicode encoding just after content decoding...
|
||||
index = dispatching['response'].index(response.decode_encoding) + 1
|
||||
except ValueError:
|
||||
# ... Or as first hook
|
||||
index = 0
|
||||
dispatching['response'].insert(index, response.decode_unicode)
|
||||
|
||||
return dispatching
|
||||
|
||||
def dispatch_hooks(hooks, data):
|
||||
"""Dispatches multiple hooks on a given piece of data.
|
||||
|
||||
:param key: the hooks group to lookup
|
||||
:type key: str
|
||||
:param hooks: the hooks dictionary. The value of each key can be a callable
|
||||
object, or a list of callable objects.
|
||||
:type hooks: dict
|
||||
:param data: the object on witch the hooks should be applied
|
||||
:type data: object
|
||||
"""
|
||||
for hook in hooks:
|
||||
try:
|
||||
# hook must be a callable.
|
||||
data = hook(data)
|
||||
|
||||
except Exception, why:
|
||||
|
||||
# Letting users to choose a policy may be an idea. It can be as
|
||||
# simple as "be gracefull, or not":
|
||||
#
|
||||
# config.settings.gracefull_hooks = True | False
|
||||
if not config.settings.gracefull_hooks: raise
|
||||
|
||||
warnings.warn(str(why))
|
||||
|
||||
return data
|
||||
@@ -1,7 +0,0 @@
|
||||
"""
|
||||
request.hooks.args
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This module provide a collection of args hooks.
|
||||
"""
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
"""
|
||||
request.hooks.post_request
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This module provide a collection of post_request hooks.
|
||||
"""
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
"""
|
||||
request.hooks.pre_request
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This module provide a collection of pre_request hooks.
|
||||
"""
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
"""
|
||||
request.hooks.response
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This module provide a collection of response hooks.
|
||||
"""
|
||||
import zlib
|
||||
import bz2
|
||||
from cgi import parse_header
|
||||
|
||||
try:
|
||||
import json
|
||||
except ImportError:
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
json = False
|
||||
try:
|
||||
from lxml import etree
|
||||
except ImportError:
|
||||
try:
|
||||
import xml.etree.cElementTree as etree
|
||||
except ImportError:
|
||||
try:
|
||||
import xml.etree.ElementTree as etree
|
||||
except ImportError:
|
||||
try:
|
||||
import cElementTree as etree
|
||||
except ImportError:
|
||||
try:
|
||||
import elementtree.ElementTree as etree
|
||||
except ImportError:
|
||||
etree = False
|
||||
|
||||
#: Dictionary of content decoders.
|
||||
content_decoders = {
|
||||
# No decoding applied.
|
||||
'identity': lambda content: content,
|
||||
# Decode Response file object compressed with deflate.
|
||||
'deflate': lambda content: zlib.decompress(content),
|
||||
# Decode Response file object compressed with gzip.
|
||||
'gzip': lambda content: zlib.decompress(content, 16+zlib.MAX_WBITS),
|
||||
# Decode Response file object compressed with bz2.
|
||||
# Not a standard Content-Encoding value, but..
|
||||
'bzip2': lambda content: bz2.decompress(content),
|
||||
}
|
||||
|
||||
# Decode Response file object compressed with compress.
|
||||
content_decoders['compress'] = content_decoders['deflate']
|
||||
|
||||
def decode_unicode(r):
|
||||
"""Encode a :py:class:`requests.models.Response` file object in unicode."""
|
||||
content_type, params = parse_header(r.headers['content-type'])
|
||||
charset = params.get('charset', '').strip("'\"")
|
||||
r._content = unicode(r.content, charset) if charset else unicode(r.content)
|
||||
return r
|
||||
|
||||
def decode_encoding(r):
|
||||
"""
|
||||
Decode a :py:class:`requests.models.Response` content using
|
||||
Contetn-Encoding header.
|
||||
"""
|
||||
# Apply decoding only if the header is set.
|
||||
encoding = r.headers['content-encoding']
|
||||
if encoding:
|
||||
r._content = content_decoders[encoding](r.content)
|
||||
return r
|
||||
|
||||
if json:
|
||||
def json_content(r):
|
||||
"""
|
||||
Turns :py:class:`requests.models.Response` content into a dumped
|
||||
JSON structure.
|
||||
"""
|
||||
r._content = json.dumps(r.content)
|
||||
return r
|
||||
|
||||
if etree:
|
||||
def etree_content(r):
|
||||
"""
|
||||
Turns :py:class:`requests.models.Response` content into an
|
||||
ElementTree structure.
|
||||
"""
|
||||
r._content = etree.fromstring(r.content)
|
||||
return r
|
||||
Reference in New Issue
Block a user