File: sessions.py

package info (click to toggle)
python-txrequests 0.9.6-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 108 kB
  • sloc: python: 153; sh: 12; makefile: 2
file content (81 lines) | stat: -rw-r--r-- 2,705 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# -*- coding: utf-8 -*-
"""
txrequests
~~~~~~~~~~~~~~~~

This module provides a small add-on for the requests http library. It makes use
of twisted threadpool.

    from txrequests import Session

    session = Session()
    # request is run in the background
    d = session.get('http://httpbin.org/get')
    # ... do other stuff ...
    # wait for the request to complete, if it hasn't already
    @d.addCallback
    def print_res(response):
        print('response status: {0}'.format(response.status_code))
        print(response.content)

"""

from requests import Session as requestsSession
from twisted.internet import defer, reactor
from twisted.python.threadpool import ThreadPool


class Session(requestsSession):

    def __init__(self, pool=None, minthreads=1, maxthreads=4, **kwargs):
        """Creates a twisted aware Session

        Notes
        ~~~~~

        * If you provide both `pool` and `max_workers`, the latter is
          ignored and provided threadpool is used as is.
        """
        requestsSession.__init__(self, **kwargs)
        self.ownPool = False
        if pool is None:
            self.ownPool = True
            pool = ThreadPool(minthreads=minthreads, maxthreads=maxthreads)
            # unclosed ThreadPool leads to reactor hangs at shutdown
            # this is a problem in many situation, so better enforce pool stop here
            reactor.addSystemEventTrigger("after", "shutdown", lambda: pool.stop() if pool.started else None)
        self.pool = pool
        if self.ownPool:
            pool.start()

    def close(self):
        try:
            requestsSession.close(self)
        finally:
            if self.ownPool:
                self.pool.stop()

    def request(self, *args, **kwargs):
        """Maintains the existing api for Session.request.

        Used by all of the higher level methods, e.g. Session.get.

        The background_callback param allows you to do some processing on the
        response in the background, e.g. call resp.json() so that json parsing
        happens in the background thread.
        """
        def func(d):
            """Callbacks the deferred d upon request completion/error.
            """
            try:
                background_callback = kwargs.pop('background_callback', None)
                res = requestsSession.request(self, *args, **kwargs)
                if background_callback is not None:
                    res = background_callback(self, res)
                reactor.callFromThread(d.callback, res)
            except Exception as e:
                reactor.callFromThread(d.errback, e)

        d = defer.Deferred()
        self.pool.callInThread(func, d)
        return d