예제 #1
0
    def test_multiple_coros(self):
        evt = Event()
        results = []

        def producer():
            results.append('prod')
            evt.send()

        def consumer():
            results.append('cons1')
            evt.wait()
            results.append('cons2')

        pool = GreenPool(2)
        done = pool.spawn(consumer)
        pool.spawn_n(producer)
        done.wait()
        self.assertEquals(['cons1', 'prod', 'cons2'], results)
예제 #2
0
    def test_reentrant(self):
        pool = GreenPool(1)

        def reenter():
            waiter = pool.spawn(lambda a: a, 'reenter')
            self.assertEqual('reenter', waiter.wait())

        outer_waiter = pool.spawn(reenter)
        outer_waiter.wait()

        evt = Event()

        def reenter_async():
            pool.spawn_n(lambda a: a, 'reenter')
            evt.send('done')

        pool.spawn_n(reenter_async)
        self.assertEquals('done', evt.wait())
예제 #3
0
    def test_multiple_coros(self):
        evt = Event()
        results = []

        def producer():
            results.append("prod")
            evt.send()

        def consumer():
            results.append("cons1")
            evt.wait()
            results.append("cons2")

        pool = GreenPool(2)
        done = pool.spawn(consumer)
        pool.spawn_n(producer)
        done.wait()
        self.assertEquals(["cons1", "prod", "cons2"], results)
예제 #4
0
    def test_reentrant(self):
        pool = GreenPool(1)

        def reenter():
            waiter = pool.spawn(lambda a: a, "reenter")
            self.assertEqual("reenter", waiter.wait())

        outer_waiter = pool.spawn(reenter)
        outer_waiter.wait()

        evt = Event()

        def reenter_async():
            pool.spawn_n(lambda a: a, "reenter")
            evt.send("done")

        pool.spawn_n(reenter_async)
        self.assertEquals("done", evt.wait())
예제 #5
0
    def test_create_contention(self):
        creates = [0]

        def sleep_create():
            creates[0] += 1
            sleep()
            return "slept"

        p = pools.Pool(max_size=4, create=sleep_create)

        def do_get():
            x = p.get()
            self.assertEquals(x, "slept")
            p.put(x)

        gp = GreenPool()
        for i in xrange(100):
            gp.spawn_n(do_get)
        gp.waitall()
        self.assertEquals(creates[0], 4)
예제 #6
0
파일: test_pools.py 프로젝트: inercia/evy
    def test_create_contention (self):
        creates = [0]

        def sleep_create ():
            creates[0] += 1
            sleep()
            return "slept"

        p = pools.Pool(max_size = 4, create = sleep_create)

        def do_get ():
            x = p.get()
            self.assertEquals(x, "slept")
            p.put(x)

        gp = GreenPool()
        for i in xrange(100):
            gp.spawn_n(do_get)
        gp.waitall()
        self.assertEquals(creates[0], 4)
예제 #7
0
    def test_spawn_n_2(self):
        p = GreenPool(2)
        self.assertEqual(p.free(), 2)
        r = []

        def foo(a):
            r.append(a)

        gt = p.spawn(foo, 1)
        self.assertEqual(p.free(), 1)
        gt.wait()
        self.assertEqual(r, [1])
        sleep(0)
        self.assertEqual(p.free(), 2)

        #Once the pool is exhausted, spawning forces a yield.
        p.spawn_n(foo, 2)
        self.assertEqual(1, p.free())
        self.assertEqual(r, [1])

        p.spawn_n(foo, 3)
        self.assertEqual(0, p.free())
        self.assertEqual(r, [1])

        p.spawn_n(foo, 4)
        self.assertEqual(set(r), set([1, 2, 3]))
        sleep(0)
        self.assertEqual(set(r), set([1, 2, 3, 4]))
예제 #8
0
    def test_spawn_n_2(self):
        p = GreenPool(2)
        self.assertEqual(p.free(), 2)
        r = []

        def foo(a):
            r.append(a)

        gt = p.spawn(foo, 1)
        self.assertEqual(p.free(), 1)
        gt.wait()
        self.assertEqual(r, [1])
        sleep(0)
        self.assertEqual(p.free(), 2)

        # Once the pool is exhausted, spawning forces a yield.
        p.spawn_n(foo, 2)
        self.assertEqual(1, p.free())
        self.assertEqual(r, [1])

        p.spawn_n(foo, 3)
        self.assertEqual(0, p.free())
        self.assertEqual(r, [1])

        p.spawn_n(foo, 4)
        self.assertEqual(set(r), set([1, 2, 3]))
        sleep(0)
        self.assertEqual(set(r), set([1, 2, 3, 4]))
예제 #9
0
def server(sock,
           site,
           log=None,
           environ=None,
           max_size=None,
           max_http_version=DEFAULT_MAX_HTTP_VERSION,
           protocol=HttpProtocol,
           server_event=None,
           minimum_chunk_size=None,
           log_x_forwarded_for=True,
           custom_pool=None,
           keepalive=True,
           log_output=True,
           log_format=DEFAULT_LOG_FORMAT,
           url_length_limit=MAX_REQUEST_LINE,
           debug=True):
    """  Start up a wsgi server handling requests from the supplied server
    socket.  This function loops forever.  The *sock* object will be closed after server exits,
    but the underlying file descriptor will remain open, so if you have a dup() of *sock*,
    it will remain usable.

    :param sock: Server socket, must be already bound to a port and listening.
    :param site: WSGI application function.
    :param log: File-like object that logs should be written to.  If not specified, sys.stderr is used.
    :param environ: Additional parameters that go into the environ dictionary of every request.
    :param max_size: Maximum number of client connections opened at any time by this server.
    :param max_http_version: Set to "HTTP/1.0" to make the server pretend it only supports HTTP 1.0.  This can help with applications or clients that don't behave properly using HTTP 1.1.
    :param protocol: Protocol class.  Deprecated.
    :param server_event: Used to collect the Server object.  Deprecated.
    :param minimum_chunk_size: Minimum size in bytes for http chunks.  This  can be used to improve performance of applications which yield many small strings, though using it technically violates the WSGI spec.
    :param log_x_forwarded_for: If True (the default), logs the contents of the x-forwarded-for header in addition to the actual client ip address in the 'client_ip' field of the log line.
    :param custom_pool: A custom GreenPool instance which is used to spawn client green threads.  If this is supplied, max_size is ignored.
    :param keepalive: If set to False, disables keepalives on the server; all connections will be closed after serving one request.
    :param log_output: A Boolean indicating if the server will log data or not.
    :param log_format: A python format string that is used as the template to generate log lines.  The following values can be formatted into it: client_ip, date_time, request_line, status_code, body_length, wall_seconds.  The default is a good example of how to use it.
    :param url_length_limit: A maximum allowed length of the request url. If exceeded, 414 error is returned.
    :param debug: True if the server should send exception tracebacks to the clients on 500 errors.  If False, the server will respond with empty bodies.
    """
    serv = Server(sock,
                  sock.getsockname(),
                  site,
                  log,
                  environ=environ,
                  max_http_version=max_http_version,
                  protocol=protocol,
                  minimum_chunk_size=minimum_chunk_size,
                  log_x_forwarded_for=log_x_forwarded_for,
                  keepalive=keepalive,
                  log_output=log_output,
                  log_format=log_format,
                  url_length_limit=url_length_limit,
                  debug=debug)
    if server_event is not None:
        server_event.send(serv)
    if max_size is None:
        max_size = DEFAULT_MAX_SIMULTANEOUS_REQUESTS
    if custom_pool is not None:
        pool = custom_pool
    else:
        pool = GreenPool(max_size)
    try:
        host, port = sock.getsockname()[:2]
        port = ':%s' % (port, )
        if hasattr(sock, 'do_handshake'):
            scheme = 'https'
            if port == ':443':
                port = ''
        else:
            scheme = 'http'
            if port == ':80':
                port = ''

        serv.log.write("(%s) wsgi starting up on %s://%s%s/\n" %
                       (os.getpid(), scheme, host, port))
        while True:
            try:
                client_socket = sock.accept()
                try:
                    pool.spawn_n(serv.process_request, client_socket)
                except AttributeError:
                    warnings.warn("wsgi's pool should be an instance of "\
                                  "evy.greenpool.GreenPool, is %s. Please convert your"\
                                  " call site to use GreenPool instead" % type(pool),
                                  DeprecationWarning, stacklevel = 2)
                    pool.execute_async(serv.process_request, client_socket)
            except ACCEPT_EXCEPTIONS, e:
                if get_errno(e) not in ACCEPT_ERRNO:
                    raise
            except (KeyboardInterrupt, SystemExit):
                serv.log.write("wsgi exiting\n")
                break
예제 #10
0
파일: wsgi.py 프로젝트: inercia/evy
def server (sock, site,
            log = None,
            environ = None,
            max_size = None,
            max_http_version = DEFAULT_MAX_HTTP_VERSION,
            protocol = HttpProtocol,
            server_event = None,
            minimum_chunk_size = None,
            log_x_forwarded_for = True,
            custom_pool = None,
            keepalive = True,
            log_output = True,
            log_format = DEFAULT_LOG_FORMAT,
            url_length_limit = MAX_REQUEST_LINE,
            debug = True):
    """  Start up a wsgi server handling requests from the supplied server
    socket.  This function loops forever.  The *sock* object will be closed after server exits,
    but the underlying file descriptor will remain open, so if you have a dup() of *sock*,
    it will remain usable.

    :param sock: Server socket, must be already bound to a port and listening.
    :param site: WSGI application function.
    :param log: File-like object that logs should be written to.  If not specified, sys.stderr is used.
    :param environ: Additional parameters that go into the environ dictionary of every request.
    :param max_size: Maximum number of client connections opened at any time by this server.
    :param max_http_version: Set to "HTTP/1.0" to make the server pretend it only supports HTTP 1.0.  This can help with applications or clients that don't behave properly using HTTP 1.1.
    :param protocol: Protocol class.  Deprecated.
    :param server_event: Used to collect the Server object.  Deprecated.
    :param minimum_chunk_size: Minimum size in bytes for http chunks.  This  can be used to improve performance of applications which yield many small strings, though using it technically violates the WSGI spec.
    :param log_x_forwarded_for: If True (the default), logs the contents of the x-forwarded-for header in addition to the actual client ip address in the 'client_ip' field of the log line.
    :param custom_pool: A custom GreenPool instance which is used to spawn client green threads.  If this is supplied, max_size is ignored.
    :param keepalive: If set to False, disables keepalives on the server; all connections will be closed after serving one request.
    :param log_output: A Boolean indicating if the server will log data or not.
    :param log_format: A python format string that is used as the template to generate log lines.  The following values can be formatted into it: client_ip, date_time, request_line, status_code, body_length, wall_seconds.  The default is a good example of how to use it.
    :param url_length_limit: A maximum allowed length of the request url. If exceeded, 414 error is returned.
    :param debug: True if the server should send exception tracebacks to the clients on 500 errors.  If False, the server will respond with empty bodies.
    """
    serv = Server(sock, sock.getsockname(),
                  site, log,
                  environ = environ,
                  max_http_version = max_http_version,
                  protocol = protocol,
                  minimum_chunk_size = minimum_chunk_size,
                  log_x_forwarded_for = log_x_forwarded_for,
                  keepalive = keepalive,
                  log_output = log_output,
                  log_format = log_format,
                  url_length_limit = url_length_limit,
                  debug = debug)
    if server_event is not None:
        server_event.send(serv)
    if max_size is None:
        max_size = DEFAULT_MAX_SIMULTANEOUS_REQUESTS
    if custom_pool is not None:
        pool = custom_pool
    else:
        pool = GreenPool(max_size)
    try:
        host, port = sock.getsockname()[:2]
        port = ':%s' % (port, )
        if hasattr(sock, 'do_handshake'):
            scheme = 'https'
            if port == ':443':
                port = ''
        else:
            scheme = 'http'
            if port == ':80':
                port = ''

        serv.log.write("(%s) wsgi starting up on %s://%s%s/\n" % (
            os.getpid(), scheme, host, port))
        while True:
            try:
                client_socket = sock.accept()
                try:
                    pool.spawn_n(serv.process_request, client_socket)
                except AttributeError:
                    warnings.warn("wsgi's pool should be an instance of "\
                                  "evy.greenpool.GreenPool, is %s. Please convert your"\
                                  " call site to use GreenPool instead" % type(pool),
                                  DeprecationWarning, stacklevel = 2)
                    pool.execute_async(serv.process_request, client_socket)
            except ACCEPT_EXCEPTIONS, e:
                if get_errno(e) not in ACCEPT_ERRNO:
                    raise
            except (KeyboardInterrupt, SystemExit):
                serv.log.write("wsgi exiting\n")
                break