From 93c44157bab8ba5fc4dfe7c4d890489b4fd02ff1 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Thu, 13 Oct 2011 20:11:05 -0400 Subject: [PATCH] initial import of urllib3 branch async --- requests/async.py | 102 +++++++++++++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 28 deletions(-) diff --git a/requests/async.py b/requests/async.py index ab04084f..9517064d 100644 --- a/requests/async.py +++ b/requests/async.py @@ -1,41 +1,87 @@ # -*- coding: utf-8 -*- """ - requests.async - ~~~~~~~~~~~~~~ +requests.async +~~~~~~~~~~~~~~ - This module implements the main Requests system, after monkey-patching - the urllib2 module with eventlet or gevent.. - - :copyright: (c) 2011 by Kenneth Reitz. - :license: ISC, see LICENSE for more details. +This module contains an asynchronous replica of ``requests.api``, powered +by gevent. All API methods return a ``Request`` instance (as opposed to +``Response``). A list of requests can be sent with ``map()``. """ - -from __future__ import absolute_import - -import urllib -import urllib2 - -from urllib2 import HTTPError - - try: - import eventlet - eventlet.monkey_patch() + import gevent + from gevent import monkey as curious_george except ImportError: - pass + raise RuntimeError('Gevent is required for requests.async.') -if not 'eventlet' in locals(): - try: - from gevent import monkey - monkey.patch_all() - except ImportError: - pass +# Monkey-patch. +curious_george.patch_all(thread=False) + +from . import api +from .hooks import dispatch_hook +from .packages.urllib3.poolmanager import PoolManager + + +__all__ = ( + 'map', + 'get', 'head', 'post', 'put', 'patch', 'delete', 'request' +) + + +def _patched(f): + """Patches a given API function to not send.""" + + def wrapped(*args, **kwargs): + return f(*args, _return_request=True, **kwargs) + + return wrapped + + +def _send(r, pools=None): + """Sends a given Request object.""" + + if pools: + r._pools = pools + + r.send() + + # Post-request hook. + r = dispatch_hook('post_request', r.hooks, r) + + # Response manipulation hook. + r.response = dispatch_hook('response', r.hooks, r.response) + + return r.response + + +# Patched requests.api functions. +get = _patched(api.get) +head = _patched(api.head) +post = _patched(api.post) +put = _patched(api.put) +patch = _patched(api.patch) +delete = _patched(api.delete) +request = _patched(api.request) + + +def map(requests, keep_alive=False): + """Concurrently converts a list of Requests to Responses. + + :param requests: a collection of Request objects. + :param keep_alive: If True, HTTP Keep-Alive will be used. + """ + + if keep_alive: + pools = PoolManager(num_pools=len(requests), maxsize=1) + else: + pools = None + + jobs = [gevent.spawn(_send, r, pools=pools) for r in requests] + gevent.joinall(jobs) + + return [r.response for r in requests] -if not 'eventlet' in locals(): - raise ImportError('No Async adaptations of urllib2 found!') -from .core import *