This file is indexed.

/usr/lib/python2.7/dist-packages/praw/multiprocess.py is in python-praw 3.3.0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
"""Provides a request server to be used with the multiprocess handler."""

from __future__ import print_function, unicode_literals

import socket
import sys
from optparse import OptionParser
from praw import __version__
from praw.handlers import DefaultHandler
from requests import Session
from six.moves import cPickle, socketserver  # pylint: disable=F0401
from threading import Lock


class ThreadingTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    # pylint: disable=R0903,W0232

    """A TCP server that creates new threads per connection."""

    allow_reuse_address = True

    @staticmethod
    def handle_error(_, client_addr):
        """Mute tracebacks of common errors."""
        exc_type, exc_value, _ = sys.exc_info()
        if exc_type is socket.error and exc_value[0] == 32:
            pass
        elif exc_type is cPickle.UnpicklingError:
            sys.stderr.write('Invalid connection from {0}\n'
                             .format(client_addr[0]))
        else:
            raise


class RequestHandler(socketserver.StreamRequestHandler):
    # pylint: disable=W0232

    """A class that handles incoming requests.

    Requests to the same domain are cached and rate-limited.

    """

    ca_lock = Lock()  # lock around cache and timeouts
    cache = {}  # caches requests
    http = Session()  # used to make requests
    last_call = {}  # Stores a two-item list: [lock, previous_call_time]
    rl_lock = Lock()  # lock used for adding items to last_call
    timeouts = {}  # store the time items in cache were entered

    do_evict = DefaultHandler.evict  # Add in the evict method

    @staticmethod
    def cache_hit_callback(key):
        """Output when a cache hit occurs."""
        print('HIT {0} {1}'.format('POST' if key[1][1] else 'GET', key[0]))

    @DefaultHandler.with_cache
    @DefaultHandler.rate_limit
    def do_request(self, request, proxies, timeout, **_):
        """Dispatch the actual request and return the result."""
        print('{0} {1}'.format(request.method, request.url))
        response = self.http.send(request, proxies=proxies, timeout=timeout,
                                  allow_redirects=False)
        response.raw = None  # Make pickleable
        return response

    def handle(self):
        """Parse the RPC, make the call, and pickle up the return value."""
        data = cPickle.load(self.rfile)  # pylint: disable=E1101
        method = data.pop('method')
        try:
            retval = getattr(self, 'do_{0}'.format(method))(**data)
        except Exception as retval:  # pylint: disable=W0703
            # All exceptions should be passed to the client
            pass
        cPickle.dump(retval, self.wfile,  # pylint: disable=E1101
                     cPickle.HIGHEST_PROTOCOL)


def run():
    """The entry point from the praw-multiprocess utility."""
    parser = OptionParser(version='%prog {0}'.format(__version__))
    parser.add_option('-a', '--addr', default='localhost',
                      help=('The address or host to listen on. Specify -a '
                            '0.0.0.0 to listen on all addresses. '
                            'Default: localhost'))
    parser.add_option('-p', '--port', type='int', default='10101',
                      help=('The port to listen for requests on. '
                            'Default: 10101'))
    options, _ = parser.parse_args()
    try:
        server = ThreadingTCPServer((options.addr, options.port),
                                    RequestHandler)
    except (socket.error, socket.gaierror) as exc:  # Handle bind errors
        print(exc)
        sys.exit(1)
    print('Listening on {0} port {1}'.format(options.addr, options.port))
    try:
        server.serve_forever()  # pylint: disable=E1101
    except KeyboardInterrupt:
        server.socket.close()  # pylint: disable=E1101
        RequestHandler.http.close()
        print('Goodbye!')