From d9977de30ed3a5636c799d37b6013a9f05bd4168 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Sun, 3 Jan 2010 22:09:53 -0800 Subject: [PATCH 1/5] Fix for rtyler's issue with psycopg2. Turns out violations of DB-API 2.0 are difficult to spot in various libraries. --- eventlet/db_pool.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/eventlet/db_pool.py b/eventlet/db_pool.py index 1b1f731..a1f57c1 100644 --- a/eventlet/db_pool.py +++ b/eventlet/db_pool.py @@ -297,14 +297,14 @@ class GenericConnectionWrapper(object): def character_set_name(self,*args, **kwargs): return self._base.character_set_name(*args, **kwargs) def close(self,*args, **kwargs): return self._base.close(*args, **kwargs) def commit(self,*args, **kwargs): return self._base.commit(*args, **kwargs) - def cursor(self, cursorclass=None, **kwargs): return self._base.cursor(cursorclass, **kwargs) + def cursor(self, *args, **kwargs): return self._base.cursor(*args, **kwargs) def dump_debug_info(self,*args, **kwargs): return self._base.dump_debug_info(*args, **kwargs) def errno(self,*args, **kwargs): return self._base.errno(*args, **kwargs) def error(self,*args, **kwargs): return self._base.error(*args, **kwargs) - def errorhandler(self, conn, curs, errcls, errval): return self._base.errorhandler(conn, curs, errcls, errval) - def literal(self, o): return self._base.literal(o) - def set_character_set(self, charset): return self._base.set_character_set(charset) - def set_sql_mode(self, sql_mode): return self._base.set_sql_mode(sql_mode) + def errorhandler(self, *args, **kwargs): return self._base.errorhandler(conn, curs, errcls, errval) + def literal(self, *args, **kwargs): return self._base.literal(*args, **kwargs) + def set_character_set(self, *args, **kwargs): return self._base.set_character_set(*args, **kwargs) + def set_sql_mode(self, *args, **kwargs): return self._base.set_sql_mode(*args, **kwargs) def show_warnings(self): return self._base.show_warnings() def warning_count(self): return self._base.warning_count() def ping(self,*args, **kwargs): return self._base.ping(*args, **kwargs) @@ -315,7 +315,7 @@ class GenericConnectionWrapper(object): def server_capabilities(self,*args, **kwargs): return self._base.server_capabilities(*args, **kwargs) def shutdown(self,*args, **kwargs): return self._base.shutdown(*args, **kwargs) def sqlstate(self,*args, **kwargs): return self._base.sqlstate(*args, **kwargs) - def stat(self,*args, **kwargs): return self._base.stat(*args, **kwargs) + def stat(self, *args, **kwargs): return self._base.stat(*args, **kwargs) def store_result(self,*args, **kwargs): return self._base.store_result(*args, **kwargs) def string_literal(self,*args, **kwargs): return self._base.string_literal(*args, **kwargs) def thread_id(self,*args, **kwargs): return self._base.thread_id(*args, **kwargs) From 2de670703fa61088b5a2960332d35e1e835d102c Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Sun, 3 Jan 2010 22:14:34 -0800 Subject: [PATCH 2/5] Oops. --- eventlet/db_pool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eventlet/db_pool.py b/eventlet/db_pool.py index a1f57c1..6be0a1c 100644 --- a/eventlet/db_pool.py +++ b/eventlet/db_pool.py @@ -301,7 +301,7 @@ class GenericConnectionWrapper(object): def dump_debug_info(self,*args, **kwargs): return self._base.dump_debug_info(*args, **kwargs) def errno(self,*args, **kwargs): return self._base.errno(*args, **kwargs) def error(self,*args, **kwargs): return self._base.error(*args, **kwargs) - def errorhandler(self, *args, **kwargs): return self._base.errorhandler(conn, curs, errcls, errval) + def errorhandler(self, *args, **kwargs): return self._base.errorhandler(*args, **kwargs) def literal(self, *args, **kwargs): return self._base.literal(*args, **kwargs) def set_character_set(self, *args, **kwargs): return self._base.set_character_set(*args, **kwargs) def set_sql_mode(self, *args, **kwargs): return self._base.set_sql_mode(*args, **kwargs) From bee6ec4bb923559f25b892aa968bd9d31bac34d2 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Mon, 4 Jan 2010 12:12:14 -0800 Subject: [PATCH 3/5] Embiggened docs link, renamed some things, added stats link, added bug reporting section. --- doc/real_index.html | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/doc/real_index.html b/doc/real_index.html index c4b98a5..f3b0bd7 100644 --- a/doc/real_index.html +++ b/doc/real_index.html @@ -22,9 +22,7 @@

Eventlet is a networking library written in Python. It achieves high scalability by using non-blocking io while at the same time retaining high programmer usability by using coroutines to make the non-blocking io operations appear blocking at the source code level.

-

Documentation

- -API Documentation +

API Documentation

Installation

@@ -47,10 +45,16 @@ easy_install eventlet

Development

-

"root" repository

+

trunk repository

We use Mercurial for our source control, hosted by BitBucket. It's easy to branch off the main repository and contribute patches, tests, and documentation back upstream.

+

Bugs

+ +

Bug Report Form

+ +

No registration is required. Please be sure to report bugs as effectively as possible, to ensure that we understand and act on them quickly.

+

Web Crawler ExampleΒΆ

This is a simple web “crawler” that fetches a bunch of urls using a coroutine pool. It has as much concurrency (i.e. pages being fetched simultaneously) as coroutines in the pool.

@@ -78,9 +82,13 @@ easy_install eventlet for waiter in waiters: waiter.wait()
+ +

Stats

+ +
@@ -92,6 +100,7 @@ easy_install eventlet From 5b5afd1859dd181c14d5dc1be6da1bc1039e52bd Mon Sep 17 00:00:00 2001 From: Mike Barton Date: Tue, 5 Jan 2010 01:27:01 +0000 Subject: [PATCH 4/5] 100-continue patch and reduce memory usage when big uploads aren't read --- eventlet/wsgi.py | 6 ++++-- tests/wsgi_test.py | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/eventlet/wsgi.py b/eventlet/wsgi.py index 9906e84..e7907f7 100644 --- a/eventlet/wsgi.py +++ b/eventlet/wsgi.py @@ -295,8 +295,10 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler): if hasattr(result, 'close'): result.close() if self.environ['eventlet.input'].position < self.environ.get('CONTENT_LENGTH', 0): - ## Read and discard body - self.environ['eventlet.input'].read() + ## Read and discard body if there was no pending 100-continue + if not self.environ['eventlet.input'].wfile: + while self.environ['eventlet.input'].read(MINIMUM_CHUNK_SIZE): + pass finish = time.time() self.server.log_message('%s - - [%s] "%s" %s %s %.6f' % ( diff --git a/tests/wsgi_test.py b/tests/wsgi_test.py index e72641c..615d64f 100644 --- a/tests/wsgi_test.py +++ b/tests/wsgi_test.py @@ -529,6 +529,30 @@ class TestHttpd(LimitedTestCase): self.assert_('400 Bad Request' in result) self.assert_('500' not in result) + def test_024_expect_100_continue(self): + def wsgi_app(environ, start_response): + if int(environ['CONTENT_LENGTH']) > 1024: + start_response('417 Expectation Failed', [('Content-Length', '7')]) + return ['failure'] + else: + text = environ['wsgi.input'].read() + start_response('200 OK', [('Content-Length', str(len(text)))]) + return [text] + self.site.application = wsgi_app + sock = api.connect_tcp(('localhost', self.port)) + fd = sock.makeGreenFile() + fd.write('PUT / HTTP/1.1\r\nHost: localhost\r\nContent-length: 1025\r\nExpect: 100-continue\r\n\r\n') + result = fd.readuntil('\r\n\r\n') + self.assert_(result.startswith('HTTP/1.1 417 Expectation Failed')) + self.assertEquals(fd.read(7), 'failure') + fd.write('PUT / HTTP/1.1\r\nHost: localhost\r\nContent-length: 7\r\nExpect: 100-continue\r\n\r\ntesting') + result = fd.readuntil('\r\n\r\n') + self.assert_(result.startswith('HTTP/1.1 100 Continue')) + result = fd.readuntil('\r\n\r\n') + self.assert_(result.startswith('HTTP/1.1 200 OK')) + self.assertEquals(fd.read(7), 'testing') + fd.close() + if __name__ == '__main__': main() From 5464cd0fb65b0cb630e6d1676fe7d0668d32a7fb Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Mon, 4 Jan 2010 20:33:43 -0800 Subject: [PATCH 5/5] Adding thanks for redbo's current and past contributions. :-) --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index efe4a6f..8a210e9 100644 --- a/AUTHORS +++ b/AUTHORS @@ -23,6 +23,7 @@ Linden Lab Contributors Thanks To --------- +* Michael Barton, 100-continue patch, content-length bugfixes for wsgi * gholt, wsgi patches for accepting a custom pool, and returning 400 if content-length is invalid * Luke Tucker, bug report regarding wsgi + webob * Chuck Thier, reporting a bug in processes.py