diff --git a/eventlet/__init__.py b/eventlet/__init__.py index cc00d4e..254a46f 100644 --- a/eventlet/__init__.py +++ b/eventlet/__init__.py @@ -1,24 +1,21 @@ -"""\ -@file __init__.py -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" - -version_info = (0, 8, 10) +version_info = (0, 8, 11) __version__ = '%s.%s.%s' % version_info diff --git a/eventlet/api.py b/eventlet/api.py index 3dfdb9e..cfdacb8 100644 --- a/eventlet/api.py +++ b/eventlet/api.py @@ -1,27 +1,24 @@ -"""\ -@file api.py -@author Bob Ippolito - -Copyright (c) 2005-2006, Bob Ippolito -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# @author Bob Ippolito +# +# Copyright (c) 2005-2006, Bob Ippolito +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import sys import socket diff --git a/eventlet/backdoor.py b/eventlet/backdoor.py index 9e0aa2e..2683c65 100644 --- a/eventlet/backdoor.py +++ b/eventlet/backdoor.py @@ -1,29 +1,26 @@ -"""\ -@file backdoor.py -@author Bob Ippolito - -Copyright (c) 2005-2006, Bob Ippolito -Copyright (c) 2007, Linden Research, Inc. -Copyright (c) 2008, Donovan Preston - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# @author Bob Ippolito +# +# Copyright (c) 2005-2006, Bob Ippolito +# Copyright (c) 2007, Linden Research, Inc. +# Copyright (c) 2008, Donovan Preston +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import socket import sys diff --git a/eventlet/channel.py b/eventlet/channel.py index 3c52824..80146e5 100644 --- a/eventlet/channel.py +++ b/eventlet/channel.py @@ -12,4 +12,5 @@ class channel(coros.queue): def balance(self): return self.sem.balance - +import warnings +warnings.warn("channel is deprecated; use coros.queue(0) which behaves the same", DeprecationWarning, stacklevel=2) diff --git a/eventlet/coros.py b/eventlet/coros.py index a41d449..e44b3b6 100644 --- a/eventlet/coros.py +++ b/eventlet/coros.py @@ -1,26 +1,23 @@ -"""\ -@file coros.py -@author Donovan Preston - -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# @author Donovan Preston +# +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import collections import time @@ -196,13 +193,11 @@ class event(object): >>> api.sleep(0) received stuff """ - # why is waiter not used? if waiter in self._waiters: del self._waiters[waiter] # XXX This does not check that waiter still waits when throw actually happens # XXX and therefore is broken (see how send() deals with this) - api.get_hub().schedule_call( - 0, waiter.throw, Cancelled()) + api.get_hub().schedule_call(0, waiter.throw, Cancelled()) def send(self, result=None, exc=None): """Makes arrangements for the waiters to be woken with the @@ -458,29 +453,8 @@ def execute(func, *args, **kw): def CoroutinePool(*args, **kwargs): - from eventlet.pools import CoroutinePool - return CoroutinePool(*args, **kwargs) - - -class pipe(object): - """ Implementation of pipe using events. Not tested! Not used, either.""" - def __init__(self): - self._event = event() - self._buffer = '' - - def send(self, txt): - self._buffer += txt - evt, self._event = self._event, event() - evt.send() - - def recv(self, num=16384): - if not self._buffer: - self._event.wait() - if num >= len(self._buffer): - buf, self._buffer = self._buffer, '' - else: - buf, self._buffer = self._buffer[:num], self._buffer[num:] - return buf + from eventlet.pool import Pool + return Pool(*args, **kwargs) class queue(object): diff --git a/eventlet/db_pool.py b/eventlet/db_pool.py index 30880a7..337d338 100644 --- a/eventlet/db_pool.py +++ b/eventlet/db_pool.py @@ -1,28 +1,26 @@ -"""\ -@file db_pool.py -@brief A pool of nonblocking database connections. - -Copyright (c) 2007, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - +# @brief A pool of nonblocking database connections. +# +# Copyright (c) 2007, Linden Research, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +""" The db_pool module is useful for managing database connections. It provides three primary benefits: cooperative yielding during database operations, concurrency limiting to a database host, and connection reuse. db_pool is intended to be db-agnostic, compatible with any DB-API 2.0 database module; however it has currently only been tested and used with MySQLdb. == ConnectionPool == @@ -79,11 +77,11 @@ The constructor arguments: >>> dc = DatabaseConnector(MySQLdb, {'db.internal.example.com': {'user':'internal', 'passwd':'s33kr1t'}, - 'localhost': + 'localhost': {'user':'root', 'passwd':''}) - + If the credentials contain a host named 'default', then the value for 'default' is used whenever trying to connect to a host that has no explicit entry in the database. This is useful if there is some pool of hosts that share arguments. - + * conn_pool : The connection pool class to use. Defaults to db_pool.ConnectionPool. The rest of the arguments to the DatabaseConnector constructor are passed on to the ConnectionPool. @@ -92,7 +90,6 @@ NOTE: The DatabaseConnector is a bit unfinished, it only suits a subset of use c """ from collections import deque -import os import sys import time @@ -106,28 +103,28 @@ class ConnectTimeout(Exception): class BaseConnectionPool(Pool): - def __init__(self, db_module, - min_size = 0, max_size = 4, + def __init__(self, db_module, + min_size = 0, max_size = 4, max_idle = 10, max_age = 30, connect_timeout = 5, *args, **kwargs): """ Constructs a pool with at least *min_size* connections and at most *max_size* connections. Uses *db_module* to construct new connections. - + The *max_idle* parameter determines how long pooled connections can - remain idle, in seconds. After *max_idle* seconds have elapsed - without the connection being used, the pool closes the connection. - + remain idle, in seconds. After *max_idle* seconds have elapsed + without the connection being used, the pool closes the connection. + *max_age* is how long any particular connection is allowed to live. Connections that have been open for longer than *max_age* seconds are - closed, regardless of idle time. If *max_age* is 0, all connections are + closed, regardless of idle time. If *max_age* is 0, all connections are closed on return to the pool, reducing it to a concurrency limiter. - - *connect_timeout* is the duration in seconds that the pool will wait + + *connect_timeout* is the duration in seconds that the pool will wait before timing out on connect() to the database. If triggered, the timeout will raise a ConnectTimeout from get(). - + The remainder of the arguments are used as parameters to the *db_module*'s connection constructor. """ @@ -139,33 +136,33 @@ class BaseConnectionPool(Pool): self.max_age = max_age self.connect_timeout = connect_timeout self._expiration_timer = None - super(BaseConnectionPool, self).__init__(min_size=min_size, + super(BaseConnectionPool, self).__init__(min_size=min_size, max_size=max_size, order_as_stack=True) - + def _schedule_expiration(self): - """ Sets up a timer that will call _expire_old_connections when the + """ Sets up a timer that will call _expire_old_connections when the oldest connection currently in the free pool is ready to expire. This is the earliest possible time that a connection could expire, thus, the - timer will be running as infrequently as possible without missing a + timer will be running as infrequently as possible without missing a possible expiration. - - If this function is called when a timer is already scheduled, it does + + If this function is called when a timer is already scheduled, it does nothing. - + If max_age or max_idle is 0, _schedule_expiration likewise does nothing. """ if self.max_age is 0 or self.max_idle is 0: # expiration is unnecessary because all connections will be expired # on put return - - if ( self._expiration_timer is not None + + if ( self._expiration_timer is not None and not getattr(self._expiration_timer, 'called', False) and not getattr(self._expiration_timer, 'cancelled', False) ): # the next timer is already scheduled - return - + return + try: now = time.time() self._expire_old_connections(now) @@ -174,23 +171,23 @@ class BaseConnectionPool(Pool): idle_delay = (self.free_items[-1][0] - now) + self.max_idle oldest = min([t[1] for t in self.free_items]) age_delay = (oldest - now) + self.max_age - + next_delay = min(idle_delay, age_delay) except IndexError, ValueError: # no free items, unschedule ourselves self._expiration_timer = None return - + if next_delay > 0: # set up a continuous self-calling loop self._expiration_timer = api.call_after(next_delay, self._schedule_expiration) - + def _expire_old_connections(self, now): """ Iterates through the open connections contained in the pool, closing ones that have remained idle for longer than max_idle seconds, or have been in existence for longer than max_age seconds. - + *now* is the current time, as returned by time.time(). """ original_count = len(self.free_items) @@ -207,8 +204,8 @@ class BaseConnectionPool(Pool): if not self._is_expired(now, last_used, created_at)] self.free_items.clear() self.free_items.extend(new_free) - - # adjust the current size counter to account for expired + + # adjust the current size counter to account for expired # connections self.current_size -= original_count - len(self.free_items) @@ -220,7 +217,7 @@ class BaseConnectionPool(Pool): or now - created_at > self.max_age ): return True return False - + def _unwrap_connection(self, conn): """ If the connection was wrapped by a subclass of BaseConnectionWrapper and is still functional (as determined @@ -253,7 +250,7 @@ class BaseConnectionPool(Pool): def get(self): conn = super(BaseConnectionPool, self).get() - + # None is a flag value that means that put got called with # something it couldn't use if conn is None: @@ -273,7 +270,7 @@ class BaseConnectionPool(Pool): _last_used, created_at, conn = conn else: created_at = time.time() - + # wrap the connection so the consumer can call close() safely wrapped = PooledConnectionWrapper(conn, self) # annotating the wrapper so that when it gets put in the pool @@ -285,7 +282,7 @@ class BaseConnectionPool(Pool): created_at = getattr(conn, '_db_pool_created_at', 0) now = time.time() conn = self._unwrap_connection(conn) - + if self._is_expired(now, now, created_at): self._safe_close(conn, quiet=False) conn = None @@ -317,7 +314,7 @@ class BaseConnectionPool(Pool): self._schedule_expiration() def clear(self): - """ Close all connections that this pool still holds a reference to, + """ Close all connections that this pool still holds a reference to, and removes all references to them. """ if self._expiration_timer: @@ -325,10 +322,10 @@ class BaseConnectionPool(Pool): free_items, self.free_items = self.free_items, deque() for _last_used, _created_at, conn in free_items: self._safe_close(conn, quiet=True) - + def __del__(self): self.clear() - + class SaranwrappedConnectionPool(BaseConnectionPool): """A pool which gives out saranwrapped database connections. @@ -346,9 +343,9 @@ class SaranwrappedConnectionPool(BaseConnectionPool): return saranwrap.wrap(db_module).connect(*args, **kw) finally: timeout.cancel() - + connect = classmethod(connect) - + class TpooledConnectionPool(BaseConnectionPool): """A pool which gives out tpool.Proxy-based database connections. @@ -422,16 +419,12 @@ class GenericConnectionWrapper(object): def set_sql_mode(self, sql_mode): return self._base.set_sql_mode(sql_mode) def show_warnings(self): return self._base.show_warnings() def warning_count(self): return self._base.warning_count() - def literal(self, o): return self._base.literal(o) def ping(self,*args, **kwargs): return self._base.ping(*args, **kwargs) def query(self,*args, **kwargs): return self._base.query(*args, **kwargs) def rollback(self,*args, **kwargs): return self._base.rollback(*args, **kwargs) def select_db(self,*args, **kwargs): return self._base.select_db(*args, **kwargs) def set_server_option(self,*args, **kwargs): return self._base.set_server_option(*args, **kwargs) - 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 server_capabilities(self,*args, **kwargs): return self._base.server_capabilities(*args, **kwargs) - def show_warnings(self): return self._base.show_warnings() 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) @@ -439,7 +432,6 @@ class GenericConnectionWrapper(object): 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) def use_result(self,*args, **kwargs): return self._base.use_result(*args, **kwargs) - def warning_count(self): return self._base.warning_count() class PooledConnectionWrapper(GenericConnectionWrapper): @@ -470,7 +462,7 @@ class PooledConnectionWrapper(GenericConnectionWrapper): if self and self._pool: self._pool.put(self) self._destroy() - + def __del__(self): self.close() @@ -479,7 +471,7 @@ class DatabaseConnector(object): """\ @brief This is an object which will maintain a collection of database connection pools on a per-host basis.""" - def __init__(self, module, credentials, + def __init__(self, module, credentials, conn_pool=None, *args, **kwargs): """\ @brief constructor diff --git a/eventlet/exc.py b/eventlet/exc.py index 93673c0..3626f48 100644 --- a/eventlet/exc.py +++ b/eventlet/exc.py @@ -1,28 +1,26 @@ -"""\ -@file exc.py -@brief Takes an exception object and returns a dictionary suitable for use debugging the exception later. +# Copyright (c) 2005-2009, Donovan Preston +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. -Copyright (c) 2005-2009, Donovan Preston - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. """ - +Takes an exception object and returns a dictionary suitable for use debugging the exception later. +""" import linecache import re @@ -39,7 +37,7 @@ def format_exc(exc=None): frames = [] while exc_tb is not None: f = exc_tb.tb_frame - + frames.append(( f.f_code.co_name, f.f_code.co_filename, diff --git a/eventlet/greenio.py b/eventlet/greenio.py index 6baa94f..8598647 100644 --- a/eventlet/greenio.py +++ b/eventlet/greenio.py @@ -1,26 +1,22 @@ -"""\ -@file greenio.py - -Copyright (c) 2005-2006, Bob Ippolito -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# Copyright (c) 2005-2006, Bob Ippolito +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. from eventlet.api import trampoline, get_hub from eventlet import util @@ -293,7 +289,9 @@ class GreenSocket(object): def dup(self, *args, **kw): sock = self.fd.dup(*args, **kw) set_nonblocking(sock) - return type(self)(sock) + newsock = type(self)(sock) + newsock.settimeout(self.timeout) + return newsock def fileno(self, *args, **kw): fn = self.fileno = self.fd.fileno @@ -352,7 +350,6 @@ class GreenSocket(object): return self.fd.sendto(*args) def setblocking(self, flag): - self.fd.setblocking(flag) if flag: self.act_non_blocking = False self.timeout = None diff --git a/eventlet/greenlib.py b/eventlet/greenlib.py index 5f21783..c1babb6 100644 --- a/eventlet/greenlib.py +++ b/eventlet/greenlib.py @@ -1,7 +1,4 @@ """\ -@file greenlib.py -@author Bob Ippolito - Copyright (c) 2005-2006, Bob Ippolito Copyright (c) 2007, Linden Research, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -22,11 +19,13 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ +from eventlet.api import Greenlet + +class SwitchingToDeadGreenlet(Exception): + pass + def switch(other=None, value=None, exc=None): - """ - Switch to another greenlet, passing value or exception - """ - self = greenlet.getcurrent() + self = Greenlet.getcurrent() if other is None: other = self.parent if other is None: @@ -37,3 +36,6 @@ def switch(other=None, value=None, exc=None): return other.throw(exc) else: return other.switch(value) + +import warnings +warnings.warn("greenlib is deprecated; use greenlet methods directly", DeprecationWarning, stacklevel=2) diff --git a/eventlet/httpc.py b/eventlet/httpc.py index 125a29c..57c9333 100644 --- a/eventlet/httpc.py +++ b/eventlet/httpc.py @@ -1,30 +1,26 @@ -"""\ -@file httpc.py -@author Donovan Preston - -Copyright (c) 2005-2006, Donovan Preston -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# @author Donovan Preston +# +# Copyright (c) 2005-2006, Donovan Preston +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import copy -import datetime from eventlet.green import httplib import os.path import os diff --git a/eventlet/httpd.py b/eventlet/httpd.py index 0111c4c..f7833b7 100644 --- a/eventlet/httpd.py +++ b/eventlet/httpd.py @@ -1,27 +1,24 @@ -"""\ -@file httpd.py -@author Donovan Preston - -Copyright (c) 2005-2006, Donovan Preston -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# @author Donovan Preston +# +# Copyright (c) 2005-2006, Donovan Preston +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import cgi import errno @@ -29,7 +26,6 @@ import socket import sys import time import urllib -import socket import traceback import BaseHTTPServer diff --git a/eventlet/httpdate.py b/eventlet/httpdate.py index e1f81f3..d530667 100644 --- a/eventlet/httpdate.py +++ b/eventlet/httpdate.py @@ -1,39 +1,3 @@ -"""\ -@file httpdate.py -@author Donovan Preston - -Copyright (c) 2006-2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" - -import time - -__all__ = ['format_date_time'] - -# Weekday and month names for HTTP date/time formatting; always English! -_weekdayname = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] -_monthname = [None, # Dummy so we can use 1-based month numbers - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] - -def format_date_time(timestamp): - year, month, day, hh, mm, ss, wd, y, z = time.gmtime(timestamp) - return "%s, %02d %3s %4d %02d:%02d:%02d GMT" % ( - _weekdayname[wd], day, _monthname[month], year, hh, mm, ss - ) +from wsgi import format_date_time +import warnings +warnings.warn("httpdate module is deprecated; its contents is moved to wsgi.py", DeprecationWarning, stacklevel=2) diff --git a/eventlet/hubs/hub.py b/eventlet/hubs/hub.py index 74b1427..211e55b 100644 --- a/eventlet/hubs/hub.py +++ b/eventlet/hubs/hub.py @@ -1,25 +1,21 @@ -"""\ -@file hub.py - -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import bisect import sys diff --git a/eventlet/hubs/libev.py b/eventlet/hubs/libev.py index 8964778..54af53f 100644 --- a/eventlet/hubs/libev.py +++ b/eventlet/hubs/libev.py @@ -1,38 +1,28 @@ -"""\ -@file libev.py +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" - -import bisect import signal import sys -import socket -import errno -import traceback import time from eventlet.hubs import hub -from eventlet.support import greenlets as greenlet - # XXX for debugging only #raise ImportError() @@ -81,7 +71,7 @@ class Hub(hub.BaseHub): def signal_received(self, signal): # can't do more than set this flag here because the pyevent callback - # mechanism swallows exceptions raised here, so we have to raise in + # mechanism swallows exceptions raised here, so we have to raise in # the 'main' greenlet (in wait()) to kill the program self.interrupted = True self._evloop.unloop() @@ -107,7 +97,7 @@ class Hub(hub.BaseHub): # raise any signals that deserve raising if self.interrupted: self.interrupted = False - raise KeyboardInterrupt() + raise KeyboardInterrupt() def add_timer(self, timer): # store the pyevent timer object so that we can cancel later diff --git a/eventlet/hubs/libevent.py b/eventlet/hubs/libevent.py index 2184649..bab7f90 100644 --- a/eventlet/hubs/libevent.py +++ b/eventlet/hubs/libevent.py @@ -1,38 +1,28 @@ -"""\ -@file libevent.py +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" - -import bisect import signal import sys -import socket -import errno -import traceback import time -from eventlet.timer import Timer from eventlet.hubs import hub -from eventlet.support import greenlets as greenlet # XXX for debugging only #raise ImportError() diff --git a/eventlet/hubs/nginx.py b/eventlet/hubs/nginx.py deleted file mode 100644 index 3553d42..0000000 --- a/eventlet/hubs/nginx.py +++ /dev/null @@ -1,168 +0,0 @@ -"""\ -@file nginx.py -@author Donovan Preston - -Copyright (c) 2008, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" - - - -from os.path import abspath, dirname -import sys -import traceback - -sys.stdout = sys.stderr -mydir = dirname(dirname(dirname(abspath(__file__)))) -if mydir not in sys.path: - sys.path.append(mydir) - - -from eventlet import api -from eventlet import httpc -from eventlet.hubs import hub - - -def hello_world(env, start_response): - result = httpc.get('http://www.google.com/') - start_response('200 OK', [('Content-type', 'text/plain')]) - return [result] - - -def wrap_application(master, env, start_response): - try: - real_application = api.named(env['eventlet_nginx_wsgi_app']) - except: - real_application = hello_world - result = real_application(env, start_response) - master.switch((result, None)) - return None, None - - -class StartResponse(object): - def __call__(self, *args): - self.args = args - - -pythonpath_already_set = False - - - - -WSGI_POLLIN = 0x01 -WSGI_POLLOUT = 0x04 - -import traceback -class Hub(hub.BaseHub): - def __init__(self, *args, **kw): - hub.BaseHub.__init__(self, *args, **kw) - self._connection_wrappers = {} - - def add_descriptor(self, fileno, read=None, write=None, exc=None): - print "ADD DESCRIPTOR", fileno, read, write, exc - traceback.print_stack() - - result = super(Hub, self).add_descriptor(fileno, read, write, exc) - flag = 0 - if read: - flag |= WSGI_POLLIN - if write: - flag |= WSGI_POLLOUT - conn = self.connection_wrapper(fileno) - self._connection_wrappers[fileno] = conn - print "POLL REGISTER", flag - self.poll_register(conn, flag) - return result - - def remove_descriptor(self, fileno): - super(Hub, self).remove_descriptor(fileno) - - try: - self.poll_unregister(self._connection_wrappers[fileno]) - except RuntimeError: - pass - - def wait(self, seconds=0): - to_call = getattr(self, 'to_call', None) - print "WAIT", self, to_call - if to_call: - print "CALL TOCALL" - result = to_call[0](to_call[1]) - del self.to_call - return result - self.current_application.switch(self.poll(int(seconds*1000))) - - def application(self, env, start_response): - print "ENV",env - self.poll_register = env['ngx.poll_register'] - self.poll_unregister = env['ngx.poll_unregister'] - self.poll = env['ngx.poll'] - self.connection_wrapper = env['ngx.connection_wrapper'] - self.current_application = api.getcurrent() - - slave = api.greenlet.greenlet(wrap_application) - response = StartResponse() - result = slave.switch( - api.getcurrent(), env, response) - - while True: - self.current_application = api.getcurrent() - print "RESULT", result, callable(result[0]) - if result and callable(result[0]): - print "YIELDING!" - yield '' - print "AFTER YIELD!" - conn, flags = result[0]() - fileno = conn.fileno() - if flags & WSGI_POLLIN: - self.readers[fileno](fileno) - elif flags & WSGI_POLLOUT: - self.writers[fileno](fileno) - print "POLL STATE", conn, flags, dir(conn) - else: - start_response(*response.args) - if isinstance(result, tuple): - for x in result[0]: - yield x - else: - for x in result: - yield x - return - result = self.switch() - #if not isinstance(result, tuple): - # result = (result, None) ## TODO Fix greenlib's return values - - -def application(env, start_response): - hub = api.get_hub() - - if not isinstance(hub, Hub): - api.use_hub(sys.modules[Hub.__module__]) - hub = api.get_hub() - - global pythonpath_already_set - if not pythonpath_already_set: - pythonpath = env.get('eventlet_python_path', '').split(':') - for seg in pythonpath: - if seg not in sys.path: - sys.path.append(seg) - - return hub.application(env, start_response) - diff --git a/eventlet/hubs/poll.py b/eventlet/hubs/poll.py index a6ec709..f37bd03 100644 --- a/eventlet/hubs/poll.py +++ b/eventlet/hubs/poll.py @@ -1,33 +1,28 @@ -"""\ -@file poll.py -@author Bob Ippolito - -Copyright (c) 2005-2006, Bob Ippolito -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# @author Bob Ippolito +# +# Copyright (c) 2005-2006, Bob Ippolito +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import sys import select -import socket import errno -import traceback from time import sleep import time @@ -60,7 +55,7 @@ class Hub(hub.BaseHub): mask |= WRITE_MASK return mask - + def remove_descriptor(self, fileno): super(Hub, self).remove_descriptor(fileno) try: diff --git a/eventlet/hubs/selects.py b/eventlet/hubs/selects.py index 06e2b36..a695722 100644 --- a/eventlet/hubs/selects.py +++ b/eventlet/hubs/selects.py @@ -1,26 +1,22 @@ -"""\ -@file select.py - -Copyright (c) 2005-2006, Bob Ippolito -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# Copyright (c) 2005-2006, Bob Ippolito +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import sys import select @@ -29,7 +25,6 @@ import time from eventlet.hubs import hub -from eventlet.support import greenlets as greenlet class Hub(hub.BaseHub): def wait(self, seconds=None): diff --git a/eventlet/jsonhttp.py b/eventlet/jsonhttp.py index 2fc0e54..3fed3ad 100644 --- a/eventlet/jsonhttp.py +++ b/eventlet/jsonhttp.py @@ -1,26 +1,23 @@ -"""\ -@file jsonhttp.py -@author Donovan Preston - -Copyright (c) 2006-2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# @author Donovan Preston +# +# Copyright (c) 2006-2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. from eventlet import httpc diff --git a/eventlet/logutil.py b/eventlet/logutil.py index 0885042..5ac169b 100644 --- a/eventlet/logutil.py +++ b/eventlet/logutil.py @@ -1,26 +1,23 @@ -"""\ -@file logutil.py -@author Donovan Preston - -Copyright (c) 2006-2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# @author Donovan Preston +# +# Copyright (c) 2006-2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import syslog import logging diff --git a/eventlet/oldchannel.py b/eventlet/oldchannel.py index 963088f..d1a626d 100644 --- a/eventlet/oldchannel.py +++ b/eventlet/oldchannel.py @@ -1,27 +1,24 @@ -"""\ -@file channel.py -@author Bob Ippolito - -Copyright (c) 2005-2006, Bob Ippolito -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# @author Bob Ippolito +# +# Copyright (c) 2005-2006, Bob Ippolito +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import collections @@ -100,3 +97,6 @@ class channel(object): def send_exception(self, exc): return self._send_tasklet(None, exc) + +import warnings +warnings.warn("channel is deprecated; use coros.queue(0) which behaves the same", DeprecationWarning, stacklevel=2) diff --git a/eventlet/pool.py b/eventlet/pool.py index 0436d8b..bffa391 100644 --- a/eventlet/pool.py +++ b/eventlet/pool.py @@ -15,6 +15,10 @@ class Pool(object): else: self.results = None + @property + def current_size(self): + return len(self.procs) + def free(self): return self.sem.counter @@ -50,7 +54,7 @@ class Pool(object): execute_async = execute def _execute(self, evt, func, args, kw): - p = self.execute(func, args, kw) + p = self.execute(func, *args, **kw) p.link(evt) return p diff --git a/eventlet/pools.py b/eventlet/pools.py index 18ee6f3..66cdbca 100644 --- a/eventlet/pools.py +++ b/eventlet/pools.py @@ -1,32 +1,27 @@ -"""\ -@file pools.py -@author Donovan Preston, Aaron Brashears - -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# @author Donovan Preston, Aaron Brashears +# +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import collections -import traceback from eventlet import api -from eventlet import channel from eventlet import coros class FanFailed(RuntimeError): @@ -76,7 +71,7 @@ class Pool(object): self.max_size = max_size self.order_as_stack = order_as_stack self.current_size = 0 - self.channel = channel.channel() + self.channel = coros.queue(0) self.free_items = collections.deque() for x in xrange(min_size): self.current_size += 1 @@ -91,7 +86,7 @@ class Pool(object): created = self.create() self.current_size += 1 return created - return self.channel.receive() + return self.channel.wait() def put(self, item): """Put an item back into the pool, when done @@ -100,7 +95,7 @@ class Pool(object): self.current_size -= 1 return - if self.channel.balance < 0: + if self.channel.sem.balance < 0: self.channel.send(item) else: if self.order_as_stack: @@ -121,8 +116,8 @@ class Pool(object): def waiting(self): """Return the number of routines waiting for a pool item. """ - if self.channel.balance < 0: - return -self.channel.balance + if self.channel.sem.balance < 0: + return -self.channel.sem.balance return 0 def create(self): @@ -212,458 +207,6 @@ class ExceptionWrapper(object): def __init__(self, e): self.e = e - -class CoroutinePool(Pool): - """ Like a thread pool, but with coroutines. - - Coroutine pools are useful for splitting up tasks or globally controlling - concurrency. You don't retrieve the coroutines directly with get() -- - instead use the execute() and execute_async() methods to run code. - - >>> from eventlet import coros, api - >>> p = coros.CoroutinePool(max_size=2) - >>> def foo(a): - ... print "foo", a - ... - >>> evt = p.execute(foo, 1) - >>> evt.wait() - foo 1 - - Once the pool is exhausted, calling an execute forces a yield. - - >>> p.execute_async(foo, 2) - >>> p.execute_async(foo, 3) - >>> p.free() - 0 - >>> p.execute_async(foo, 4) - foo 2 - foo 3 - - >>> api.sleep(0) - foo 4 - """ - - def __init__(self, min_size=0, max_size=4, track_events=False): - self._greenlets = set() - if track_events: - self._tracked_events = [] - self._next_event = None - else: - self._tracked_events = None - self.requested = coros.metaphore() - super(CoroutinePool, self).__init__(min_size, max_size) - -## This doesn't yet pass its own doctest -- but I'm not even sure it's a -## wonderful idea. -## def __del__(self): -## """Experimental: try to prevent the calling script from exiting until -## all coroutines in this pool have run to completion. - -## >>> from eventlet import coros -## >>> pool = coros.CoroutinePool() -## >>> def saw(x): print "I saw %s!" -## ... -## >>> pool.launch_all(saw, "GHI") -## >>> del pool -## I saw G! -## I saw H! -## I saw I! -## """ -## self.wait_all() - - def _main_loop(self, sender): - """ Private, infinite loop run by a pooled coroutine. """ - try: - # not really a loop anymore because we want the greenlet - # to die so all its timers get canceled - if True: - recvd = sender.wait() - # Delete the sender's result here because the very - # first event through the loop is referenced by - # spawn_startup, and therefore is not itself deleted. - # This means that we have to free up its argument - # because otherwise said argument persists in memory - # forever. This is generally only a problem in unit - # tests. - sender._result = coros.NOT_USED - - (evt, func, args, kw) = recvd - self._safe_apply(evt, func, args, kw) - # Likewise, delete these variables or else they will - # be referenced by this frame until replaced by the - # next recvd, which may or may not be a long time from - # now. - del evt, func, args, kw, recvd - finally: - self.put(self.create()) - - def _safe_apply(self, evt, func, args, kw): - """ Private method that runs the function, catches exceptions, and - passes back the return value in the event.""" - try: - result = func(*args, **kw) - if evt is not None: - evt.send(result) - if self._tracked_events is not None: - if self._next_event is None: - self._tracked_events.append(result) - else: - - ne = self._next_event - self._next_event = None - ne.send(result) - except api.GreenletExit, e: - # we're printing this out to see if it ever happens - # in practice - print "GreenletExit raised in coroutine pool", e - if evt is not None: - evt.send(e) # sent as a return value, not an exception - except KeyboardInterrupt: - raise # allow program to exit - except Exception, e: - traceback.print_exc() - if evt is not None: - evt.send(exc=e) - if self._tracked_events is not None: - if self._next_event is None: - self._tracked_events.append(ExceptionWrapper(e)) - else: - ne = self._next_event - self._next_event = None - ne.send(exc=e) - - def _execute(self, evt, func, args, kw): - """ Private implementation of the execute methods. - """ - # if reentering an empty pool, don't try to wait on a coroutine freeing - # itself -- instead, just execute in the current coroutine - if self.free() == 0 and api.getcurrent() in self._greenlets: - self._safe_apply(evt, func, args, kw) - else: - sender = self.get() - sender.send((evt, func, args, kw)) - - def create(self): - """Private implementation of eventlet.pools.Pool - interface. Creates an event and spawns the - _main_loop coroutine, passing the event. - The event is used to send a callable into the - new coroutine, to be executed. - """ - sender = coros.event() - self._greenlets.add(api.spawn(self._main_loop, sender)) - return sender - - def get(self): - """Override of eventlet.pools.Pool interface""" - # Track the number of requested CoroutinePool coroutines - self.requested.inc() - # forward call to base class - return super(CoroutinePool, self).get() - - def put(self, item): - """Override of eventlet.pools.Pool interface""" - # forward call to base class - super(CoroutinePool, self).put(item) - # Track the number of outstanding CoroutinePool coroutines - self.requested.dec() - - def execute(self, func, *args, **kw): - """Execute func in one of the coroutines maintained - by the pool, when one is free. - - Immediately returns an eventlet.coros.event object which - func's result will be sent to when it is available. - - >>> from eventlet import coros - >>> p = coros.CoroutinePool() - >>> evt = p.execute(lambda a: ('foo', a), 1) - >>> evt.wait() - ('foo', 1) - """ - receiver = coros.event() - self._execute(receiver, func, args, kw) - return receiver - - def execute_async(self, func, *args, **kw): - """Execute func in one of the coroutines maintained - by the pool, when one is free. - - No return value is provided. - >>> from eventlet import coros, api - >>> p = coros.CoroutinePool() - >>> def foo(a): - ... print "foo", a - ... - >>> p.execute_async(foo, 1) - >>> api.sleep(0) - foo 1 - """ - self._execute(None, func, args, kw) - - def wait(self): - """Wait for the next execute in the pool to complete, - and return the result. - - You must pass track_events=True to the CoroutinePool constructor - in order to use this method. - """ - assert self._tracked_events is not None, ( - "Must pass track_events=True to the constructor to use CoroutinePool.wait()") - if self._next_event is not None: - return self._next_event.wait() - - if not self._tracked_events: - self._next_event = coros.event() - return self._next_event.wait() - - result = self._tracked_events.pop(0) - if isinstance(result, ExceptionWrapper): - raise result.e - - if not self._tracked_events: - self._next_event = coros.event() - return result - - def killall(self): - for g in self._greenlets: - api.kill(g) - - def wait_all(self): - """Wait until all coroutines started either by execute() or - execute_async() have completed. If you kept the event objects returned - by execute(), you can then call their individual wait() methods to - retrieve results with no further actual waiting. - - >>> from eventlet import coros - >>> pool = coros.CoroutinePool() - >>> pool.wait_all() - >>> def hi(name): - ... print "Hello, %s!" % name - ... return name - ... - >>> evt = pool.execute(hi, "world") - >>> pool.execute_async(hi, "darkness, my old friend") - >>> pool.wait_all() - Hello, world! - Hello, darkness, my old friend! - >>> evt.wait() - 'world' - >>> pool.wait_all() - """ - self.requested.wait() - - def launch_all(self, function, iterable): - """For each tuple (sequence) in iterable, launch function(*tuple) in - its own coroutine -- like itertools.starmap(), but in parallel. - Discard values returned by function(). You should call wait_all() to - wait for all coroutines, newly-launched plus any previously-submitted - execute() or execute_async() calls, to complete. - - >>> from eventlet import coros - >>> pool = coros.CoroutinePool() - >>> def saw(x): - ... print "I saw %s!" % x - ... - >>> pool.launch_all(saw, "ABC") - >>> pool.wait_all() - I saw A! - I saw B! - I saw C! - """ - for tup in iterable: - self.execute_async(function, *tup) - - def process_all(self, function, iterable): - """For each tuple (sequence) in iterable, launch function(*tuple) in - its own coroutine -- like itertools.starmap(), but in parallel. - Discard values returned by function(). Don't return until all - coroutines, newly-launched plus any previously-submitted execute() or - execute_async() calls, have completed. - - >>> from eventlet import coros - >>> pool = coros.CoroutinePool() - >>> def saw(x): print "I saw %s!" % x - ... - >>> pool.process_all(saw, "DEF") - I saw D! - I saw E! - I saw F! - """ - self.launch_all(function, iterable) - self.wait_all() - - def generate_results(self, function, iterable, qsize=None): - """For each tuple (sequence) in iterable, launch function(*tuple) in - its own coroutine -- like itertools.starmap(), but in parallel. - Yield each of the values returned by function(), in the order they're - completed rather than the order the coroutines were launched. - - Iteration stops when we've yielded results for each arguments tuple in - iterable. Unlike wait_all() and process_all(), this function does not - wait for any previously-submitted execute() or execute_async() calls. - - Results are temporarily buffered in a queue. If you pass qsize=, this - value is used to limit the max size of the queue: an attempt to buffer - too many results will suspend the completed CoroutinePool coroutine - until the requesting coroutine (the caller of generate_results()) has - retrieved one or more results by calling this generator-iterator's - next(). - - If any coroutine raises an uncaught exception, that exception will - propagate to the requesting coroutine via the corresponding next() call. - - What I particularly want these tests to illustrate is that using this - generator function: - - for result in generate_results(function, iterable): - # ... do something with result ... - - executes coroutines at least as aggressively as the classic eventlet - idiom: - - events = [pool.execute(function, *args) for args in iterable] - for event in events: - result = event.wait() - # ... do something with result ... - - even without a distinct event object for every arg tuple in iterable, - and despite the funny flow control from interleaving launches of new - coroutines with yields of completed coroutines' results. - - (The use case that makes this function preferable to the classic idiom - above is when the iterable, which may itself be a generator, produces - millions of items.) - - >>> from eventlet import coros - >>> import string - >>> pool = coros.CoroutinePool(max_size=5) - >>> pausers = [coros.event() for x in xrange(2)] - >>> def longtask(evt, desc): - ... print "%s woke up with %s" % (desc, evt.wait()) - ... - >>> pool.launch_all(longtask, zip(pausers, "AB")) - >>> def quicktask(desc): - ... print "returning %s" % desc - ... return desc - ... - - (Instead of using a for loop, step through generate_results() - items individually to illustrate timing) - - >>> step = iter(pool.generate_results(quicktask, string.ascii_lowercase)) - >>> print step.next() - returning a - returning b - returning c - a - >>> print step.next() - b - >>> print step.next() - c - >>> print step.next() - returning d - returning e - returning f - d - >>> pausers[0].send("A") - >>> print step.next() - e - >>> print step.next() - f - >>> print step.next() - A woke up with A - returning g - returning h - returning i - g - >>> print "".join([step.next() for x in xrange(3)]) - returning j - returning k - returning l - returning m - hij - >>> pausers[1].send("B") - >>> print "".join([step.next() for x in xrange(4)]) - B woke up with B - returning n - returning o - returning p - returning q - klmn - """ - # Get an iterator because of our funny nested loop below. Wrap the - # iterable in enumerate() so we count items that come through. - tuples = iter(enumerate(iterable)) - # If the iterable is empty, this whole function is a no-op, and we can - # save ourselves some grief by just quitting out. In particular, once - # we enter the outer loop below, we're going to wait on the queue -- - # but if we launched no coroutines with that queue as the destination, - # we could end up waiting a very long time. - try: - index, args = tuples.next() - except StopIteration: - return - # From this point forward, 'args' is the current arguments tuple and - # 'index+1' counts how many such tuples we've seen. - # This implementation relies on the fact that _execute() accepts an - # event-like object, and -- unless it's None -- the completed - # coroutine calls send(result). We slyly pass a queue rather than an - # event -- the same queue instance for all coroutines. This is why our - # queue interface intentionally resembles the event interface. - q = coros.queue(max_size=qsize) - # How many results have we yielded so far? - finished = 0 - # This first loop is only until we've launched all the coroutines. Its - # complexity is because if iterable contains more args tuples than the - # size of our pool, attempting to _execute() the (poolsize+1)th - # coroutine would suspend until something completes and send()s its - # result to our queue. But to keep down queue overhead and to maximize - # responsiveness to our caller, we'd rather suspend on reading the - # queue. So we stuff the pool as full as we can, then wait for - # something to finish, then stuff more coroutines into the pool. - try: - while True: - # Before each yield, start as many new coroutines as we can fit. - # (The self.free() test isn't 100% accurate: if we happen to be - # executing in one of the pool's coroutines, we could _execute() - # without waiting even if self.free() reports 0. See _execute().) - # The point is that we don't want to wait in the _execute() call, - # we want to wait in the q.wait() call. - # IMPORTANT: at start, and whenever we've caught up with all - # coroutines we've launched so far, we MUST iterate this inner - # loop at least once, regardless of self.free() -- otherwise the - # q.wait() call below will deadlock! - # Recall that index is the index of the NEXT args tuple that we - # haven't yet launched. Therefore it counts how many args tuples - # we've launched so far. - while self.free() > 0 or finished == index: - # Just like the implementation of execute_async(), save that - # we're passing our queue instead of None as the "event" to - # which to send() the result. - self._execute(q, function, args, {}) - # We've consumed that args tuple, advance to next. - index, args = tuples.next() - # Okay, we've filled up the pool again, yield a result -- which - # will probably wait for a coroutine to complete. Although we do - # have q.ready(), so we could iterate without waiting, we avoid - # that because every yield could involve considerable real time. - # We don't know how long it takes to return from yield, so every - # time we do, take the opportunity to stuff more requests into the - # pool before yielding again. - yield q.wait() - # Be sure to count results so we know when to stop! - finished += 1 - except StopIteration: - pass - # Here we've exhausted the input iterable. index+1 is the total number - # of coroutines we've launched. We probably haven't yielded that many - # results yet. Wait for the rest of the results, yielding them as they - # arrive. - while finished < index + 1: - yield q.wait() - finished += 1 - if __name__=='__main__': import doctest doctest.testmod() diff --git a/eventlet/proc.py b/eventlet/proc.py index add269c..56be74f 100644 --- a/eventlet/proc.py +++ b/eventlet/proc.py @@ -683,6 +683,9 @@ class RunningProcSet(object): for p in self.args[0]: p.link(lambda p: self.procs.discard(p)) + def __len__(self): + return len(self.procs) + def __contains__(self, item): if isinstance(item, api.Greenlet): # special case for "api.getcurrent() in running_proc_set" to work diff --git a/eventlet/processes.py b/eventlet/processes.py index d2fea8a..48041cb 100644 --- a/eventlet/processes.py +++ b/eventlet/processes.py @@ -1,36 +1,30 @@ -"""\ -@file processes.py - -Copyright (c) 2006-2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# Copyright (c) 2006-2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import errno import os import popen2 import signal -import sys from eventlet import coros from eventlet import pools from eventlet import greenio -from eventlet import util class DeadProcess(RuntimeError): diff --git a/eventlet/saranwrap.py b/eventlet/saranwrap.py index 8af56f3..77fe64b 100644 --- a/eventlet/saranwrap.py +++ b/eventlet/saranwrap.py @@ -1,29 +1,28 @@ -"""\ -@file saranwrap.py +# Copyright (c) 2007, Linden Research, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +""" @author Phoenix @date 2007-07-13 -@brief A simple, pickle based rpc mechanism which reflects python -objects and callables. - -Copyright (c) 2007, Linden Research, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +@brief A simple, pickle based rpc mechanism which reflects python objects and +callables. This file provides classes and exceptions used for simple python level remote procedure calls. This is achieved by intercepting the basic @@ -91,12 +90,6 @@ import os import struct import sys -try: - set = set - frozenset = frozenset -except NameError: - from sets import Set as set, ImmutableSet as frozenset - from eventlet.processes import Process, DeadProcess from eventlet import api, pools @@ -282,7 +275,7 @@ class ChildProcess(object): retval = _read_response(_id, attribute, self._in, self) finally: self._lock.put(t) - + return retval def __del__(self): @@ -330,7 +323,7 @@ not supported, so you have to know what has been exported. _dead_list.remove(dead_object) except KeyError: pass - + # Pass all public attributes across to find out if it is # callable or a simple attribute. request = Request('getattr', {'id':my_id, 'attribute':attribute}) @@ -339,7 +332,7 @@ not supported, so you have to know what has been exported. def __setattr__(self, attribute, value): #_prnt("Proxy::__setattr__: %s" % attribute) if _is_local(attribute): - # It must be local to this actual object, so we have to apply + # It must be local to this actual object, so we have to apply # it to the dict in a roundabout way attribute = _unmunge_attr_name(attribute) super(Proxy, self).__getattribute__('__dict__')[attribute]=value @@ -377,7 +370,7 @@ not need to deal with this class directly.""" my_id = self.__local_dict['_id'] request = Request('getitem', {'id':my_id, 'key':key}) return my_cp.make_request(request, attribute=key) - + def __setitem__(self, key, value): my_cp = self.__local_dict['_cp'] my_id = self.__local_dict['_id'] @@ -429,7 +422,7 @@ not need to deal with this class directly.""" # since the remote object is being serialized whole anyway, # there's no semantic difference between copy and deepcopy __copy__ = __deepcopy__ - + def proxied_type(self): """ Returns the type of the object in the child process. @@ -439,7 +432,7 @@ def proxied_type(self): 'real' type value.""" if type(self) is not ObjectProxy: return type(self) - + my_cp = self.__local_dict['_cp'] my_id = self.__local_dict['_id'] request = Request('type', {'id':my_id}) @@ -506,7 +499,7 @@ when the id is None.""" else: raise e #_log('getattr: %s' % str(response)) - + def handle_setattr(self, obj, req): try: return setattr(obj, req['attribute'], req['value']) @@ -541,7 +534,7 @@ when the id is None.""" fn = obj[req['name']] else: raise e - + return fn(*req['args'],**req['kwargs']) def handle_del(self, obj, req): diff --git a/eventlet/support/pylib.py b/eventlet/support/pylib.py index bc135ba..b9c2fa5 100644 --- a/eventlet/support/pylib.py +++ b/eventlet/support/pylib.py @@ -1,36 +1,30 @@ -"""\ -@file support.pylib.py -@author Donovan Preston - -Copyright (c) 2005-2006, Donovan Preston -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" - +# @author Donovan Preston +# +# Copyright (c) 2005-2006, Donovan Preston +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. from py.magic import greenlet - import sys import types - def emulate(): module = types.ModuleType('greenlet') sys.modules['greenlet'] = module @@ -38,5 +32,3 @@ def emulate(): module.getcurrent = greenlet.getcurrent module.GreenletExit = greenlet.GreenletExit - - diff --git a/eventlet/support/stacklesspypys.py b/eventlet/support/stacklesspypys.py index 9403d21..1f79257 100644 --- a/eventlet/support/stacklesspypys.py +++ b/eventlet/support/stacklesspypys.py @@ -1,35 +1,29 @@ -"""\ -@file stacklesspypysupport.py -@author Donovan Preston - -Copyright (c) 2008, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" - +# @author Donovan Preston +# +# Copyright (c) 2008, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. from stackless import greenlet - import sys import types - def emulate(): module = types.ModuleType('greenlet') sys.modules['greenlet'] = module @@ -37,8 +31,3 @@ def emulate(): module.getcurrent = greenlet.getcurrent module.GreenletExit = greenlet.GreenletExit - - - - - diff --git a/eventlet/support/stacklesss.py b/eventlet/support/stacklesss.py index 5220cb6..b0b5486 100644 --- a/eventlet/support/stacklesss.py +++ b/eventlet/support/stacklesss.py @@ -1,41 +1,34 @@ -"""\ -@file __init__.py -@brief Support for using stackless python. Broken and riddled with -print statements at the moment. Please fix it! +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. +""" +Support for using stackless python. Broken and riddled with print statements +at the moment. Please fix it! """ import sys import types import stackless -import traceback - caller = None - - coro_args = {} - - tasklet_to_greenlet = {} diff --git a/eventlet/support/twisteds.py b/eventlet/support/twisteds.py deleted file mode 100644 index cd6fdb3..0000000 --- a/eventlet/support/twisteds.py +++ /dev/null @@ -1,142 +0,0 @@ -"""\ -@file support.twisted.py -@author Donovan Preston - -Copyright (c) 2005-2006, Donovan Preston -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" - -import sys -import traceback - -from eventlet import api -from eventlet import timer - -from twisted.internet import posixbase -from twisted.internet.interfaces import IReactorFDSet - -try: - from zope.interface import implements - _working = True -except ImportError: - _working = False - def implements(*args, **kw): - pass - - -class TwistedTimer(object): - def __init__(self, timer): - self.timer = timer - - def cancel(self): - self.timer.cancel() - - def getTime(self): - return self.timer.scheduled_time - - def delay(self, seconds): - hub = api.get_hub() - new_time = hub.clock() - self.timer_scheduled_time + seconds - self.timer.cancel() - cb, args, kw = self.timer.tpl - self.timer = hub.schedule_call(new_time, cb, *args, **kw) - - def reset(self, new_time): - self.timer.cancel() - cb, args, kw = self.timer.tpl - self.timer = api.get_hub().schedule_call(new_time, cb, *args, **kw) - - def active(self): - return not self.timer.called - - -class EventletReactor(posixbase.PosixReactorBase): - implements(IReactorFDSet) - - def __init__(self, *args, **kw): - self._readers = {} - self._writers = {} - posixbase.PosixReactorBase.__init__(self, *args, **kw) - - def callLater(self, func, *args, **kw): - return TwistedTimer(api.call_after(func, *args, **kw)) - - def run(self): - self.running = True - self._stopper = api.call_after(sys.maxint / 1000.0, lambda: None) - ## schedule a call way in the future, and cancel it in stop? - api.get_hub().run() - - def stop(self): - self._stopper.cancel() - posixbase.PosixReactorBase.stop(self) - api.get_hub().remove_descriptor(self._readers.keys()[0]) - api.get_hub().abort() - - def addReader(self, reader): - print "NEW READER", reader.fileno() - fileno = reader.fileno() - self._readers[fileno] = reader - api.get_hub().add_descriptor(fileno, read=self._got_read) - - def _got_read(self, fileno): - print "got read on", fileno, self._readers[fileno] - api.get_hub().add_descriptor(fileno, read=self._got_read) - self._readers[fileno].doRead() - - def addWriter(self, writer): - print "NEW WRITER", writer.fileno() - fileno = writer.fileno() - self._writers[fileno] = writer - api.get_hub().add_descriptor(fileno, write=self._got_write) - - def _got_write(self, fileno): - print "got write on", fileno, self._writers[fileno] - api.get_hub().add_descriptor(fileno, write=self._got_write) - self._writers[fileno].doWrite() - - def removeReader(self, reader): - print "removing reader", reader.fileno() - fileno = reader.fileno() - if fileno in self._readers: - self._readers.pop(fileno) - api.get_hub().remove_descriptor(fileno) - - def removeWriter(self, writer): - print "removing writer", writer.fileno() - fileno = writer.fileno() - if fileno in self._writers: - self._writers.pop(fileno) - api.get_hub().remove_descriptor(fileno) - - def removeAll(self): - return self._removeAll(self._readers.values(), self._writers.values()) - - -def install(): - if not _working: - raise RuntimeError, "Can't use support.twisted because zope.interface is not installed." - reactor = EventletReactor() - from twisted.internet.main import installReactor - installReactor(reactor) - - -__all__ = ['install'] - diff --git a/eventlet/timer.py b/eventlet/timer.py index 99f11da..8b71cd3 100644 --- a/eventlet/timer.py +++ b/eventlet/timer.py @@ -1,27 +1,25 @@ -"""\ -@file timer.py -@author Bob Ippolito +# @author Bob Ippolito +# +# Copyright (c) 2005-2006, Bob Ippolito +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. -Copyright (c) 2005-2006, Bob Ippolito -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" from eventlet.api import get_hub, getcurrent """ If true, captures a stack trace for each timer when constructed. This is @@ -95,7 +93,7 @@ class Timer(object): pass class LocalTimer(Timer): - + def __init__(self, *args, **kwargs): self.greenlet = getcurrent() Timer.__init__(self, *args, **kwargs) diff --git a/eventlet/tpool.py b/eventlet/tpool.py index 867e2e5..5acf365 100644 --- a/eventlet/tpool.py +++ b/eventlet/tpool.py @@ -1,21 +1,17 @@ -"""\ -@file tpool.py - -Copyright (c) 2007, Linden Research, Inc. -Copyright (c) 2007, IBM Corp. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" +# Copyright (c) 2007, Linden Research, Inc. +# Copyright (c) 2007, IBM Corp. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. import os import threading @@ -75,7 +71,7 @@ def tworker(): except SYS_EXCS: raise except Exception,exn: - import sys, traceback + import sys (a,b,tb) = sys.exc_info() rv = (exn,a,b,tb) _rspq.put((e,rv)) @@ -86,7 +82,7 @@ def tworker(): def erecv(e): rv = e.wait() if isinstance(rv,tuple) and len(rv) == 4 and isinstance(rv[0],Exception): - import sys, traceback + import traceback (e,a,b,tb) = rv if not QUIET: traceback.print_exception(Exception,e,tb) diff --git a/eventlet/util.py b/eventlet/util.py index f83c286..694ffe1 100644 --- a/eventlet/util.py +++ b/eventlet/util.py @@ -1,32 +1,28 @@ -"""\ -@file util.py -@author Bob Ippolito - -Copyright (c) 2005-2006, Bob Ippolito -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# @author Bob Ippolito +# +# Copyright (c) 2005-2006, Bob Ippolito +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import os import select import socket -import sys import errno try: @@ -81,7 +77,7 @@ except AttributeError: def wrap_ssl(sock, certificate=None, private_key=None): from OpenSSL import SSL - from eventlet import greenio, util + from eventlet import greenio context = SSL.Context(SSL.SSLv23_METHOD) if certificate is not None: context.use_certificate_file(certificate) @@ -174,7 +170,7 @@ def wrap_pipes_with_coroutine_pipes(): return pid, evt.wait() return 0, 0 elif options: - return __original_waitpid__(pid, result) + return __original_waitpid__(pid, options) return pid, evt.wait() os.fdopen = new_fdopen os.read = new_read @@ -238,7 +234,7 @@ def wrap_threading_local_with_coro_local(): class local(object): def __init__(self): self.__dict__['__objs'] = {} - + def __getattr__(self, attr, g=get_ident): try: return self.__dict__['__objs'][g()][attr] @@ -246,10 +242,10 @@ def wrap_threading_local_with_coro_local(): raise AttributeError( "No variable %s defined for the thread %s" % (attr, g())) - + def __setattr__(self, attr, value, g=get_ident): self.__dict__['__objs'].setdefault(g(), {})[attr] = value - + def __delattr__(self, attr, g=get_ident): try: del self.__dict__['__objs'][g()][attr] diff --git a/eventlet/wsgi.py b/eventlet/wsgi.py index 85b6b33..45b4bc3 100644 --- a/eventlet/wsgi.py +++ b/eventlet/wsgi.py @@ -1,27 +1,24 @@ -"""\ -@file wsgi.py -@author Bob Ippolito - -Copyright (c) 2005-2006, Bob Ippolito -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# @author Bob Ippolito +# +# Copyright (c) 2005-2006, Bob Ippolito +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import errno import os @@ -124,7 +121,7 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler): if e[0] != errno.EBADF: raise self.raw_requestline = '' - + if not self.raw_requestline: self.close_connection = 1 return @@ -254,7 +251,7 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler): start_response("500 Internal Server Error", [('Content-type', 'text/plain')]) write(exc) return - + if towrite: write(''.join(towrite)) if not headers_sent: @@ -346,7 +343,7 @@ class Server(BaseHTTPServer.HTTPServer): self.log = sys.stderr self.app = app self.environ = environ - self.max_http_version = max_http_version + self.max_http_version = max_http_version self.protocol = protocol self.pid = os.getpid() if minimum_chunk_size is not None: diff --git a/greentest/api_test.py b/greentest/api_test.py index 561bab0..59bbccc 100644 --- a/greentest/api_test.py +++ b/greentest/api_test.py @@ -1,38 +1,32 @@ -"""\ -@file api_test.py -@author Donovan Preston - -Copyright (c) 2006-2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# @author Donovan Preston +# +# Copyright (c) 2006-2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import os -import socket +import os.path from eventlet import api from eventlet import greenio from greentest import tests from eventlet import util -import os.path -import socket - def check_hub(): # Clear through the descriptor queue @@ -50,10 +44,10 @@ def check_hub(): class TestApi(tests.TestCase): mode = 'static' - + certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt') private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key') - + def test_tcp_listener(self): socket = api.tcp_listener(('0.0.0.0', 0)) assert socket.getsockname()[0] == '0.0.0.0' @@ -86,27 +80,27 @@ class TestApi(tests.TestCase): check_hub() def test_connect_ssl(self): - def accept_once(listenfd): - try: + def accept_once(listenfd): + try: conn, addr = listenfd.accept() fl = conn.makeGreenFile('w') fl.write('hello\r\n') fl.close() - conn.close() - finally: - listenfd.close() - - server = api.ssl_listener(('0.0.0.0', 0), - self.certificate_file, - self.private_key_file) - api.spawn(accept_once, server) - - client = util.wrap_ssl( + conn.close() + finally: + listenfd.close() + + server = api.ssl_listener(('0.0.0.0', 0), + self.certificate_file, + self.private_key_file) + api.spawn(accept_once, server) + + client = util.wrap_ssl( api.connect_tcp(('127.0.0.1', server.getsockname()[1]))) client = client.makeGreenFile() - assert client.readline() == 'hello\r\n' - assert client.read() == '' + assert client.readline() == 'hello\r\n' + assert client.read() == '' client.close() def test_server(self): diff --git a/greentest/coros_test.py b/greentest/coros_test.py index 4f52344..e83510b 100644 --- a/greentest/coros_test.py +++ b/greentest/coros_test.py @@ -1,32 +1,27 @@ -"""\ -@file coros_test.py -@author Donovan Preston, Ryan Williams +# @author Donovan Preston, Ryan Williams +# +# Copyright (c) 2000-2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. -Copyright (c) 2000-2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" from greentest import tests -from eventlet import timer from eventlet import coros, api -import sys - class TestEvent(tests.TestCase): mode = 'static' def setUp(self): @@ -114,121 +109,6 @@ class TestEvent(tests.TestCase): self.assertRaises(api.TimeoutError, evt.wait) -class TestCoroutinePool(tests.TestCase): - mode = 'static' - def setUp(self): - # raise an exception if we're waiting forever - self._cancel_timeout = api.exc_after(1, api.TimeoutError) - - def tearDown(self): - self._cancel_timeout.cancel() - - def test_execute_async(self): - done = coros.event() - def some_work(): - done.send() - pool = coros.CoroutinePool(0, 2) - pool.execute_async(some_work) - done.wait() - - def test_execute(self): - value = 'return value' - def some_work(): - return value - pool = coros.CoroutinePool(0, 2) - worker = pool.execute(some_work) - self.assertEqual(value, worker.wait()) - - def test_multiple_coros(self): - evt = coros.event() - results = [] - def producer(): - results.append('prod') - evt.send() - - def consumer(): - results.append('cons1') - evt.wait() - results.append('cons2') - - pool = coros.CoroutinePool(0, 2) - done = pool.execute(consumer) - pool.execute_async(producer) - done.wait() - self.assertEquals(['cons1', 'prod', 'cons2'], results) - -# since CoroutinePool does not kill the greenlet, the following does not work -# def test_timer_cancel(self): -# def some_work(): -# t = timer.LocalTimer(5, lambda: None) -# t.schedule() -# return t -# pool = coros.CoroutinePool(0, 2) -# worker = pool.execute(some_work) -# t = worker.wait() -# api.sleep(0) -# self.assertEquals(t.cancelled, True) - - def test_reentrant(self): - pool = coros.CoroutinePool(0,1) - def reenter(): - waiter = pool.execute(lambda a: a, 'reenter') - self.assertEqual('reenter', waiter.wait()) - - outer_waiter = pool.execute(reenter) - outer_waiter.wait() - - evt = coros.event() - def reenter_async(): - pool.execute_async(lambda a: a, 'reenter') - evt.send('done') - - pool.execute_async(reenter_async) - evt.wait() - - def test_horrible_main_loop_death(self): - # testing the case that causes the run_forever - # method to exit unwantedly - pool = coros.CoroutinePool(min_size=1, max_size=1) - def crash(*args, **kw): - raise RuntimeError("Whoa") - class FakeFile(object): - write = crash - - # we're going to do this by causing the traceback.print_exc in - # safe_apply to raise an exception and thus exit _main_loop - normal_err = sys.stderr - try: - sys.stderr = FakeFile() - waiter = pool.execute(crash) - self.assertRaises(RuntimeError, waiter.wait) - # the pool should have something free at this point since the - # waiter returned - self.assertEqual(pool.free(), 1) - # shouldn't block when trying to get - t = api.exc_after(0.1, api.TimeoutError) - self.assert_(pool.get()) - t.cancel() - finally: - sys.stderr = normal_err - - def test_track_events(self): - pool = coros.CoroutinePool(track_events=True) - for x in range(6): - pool.execute(lambda n: n, x) - for y in range(6): - print "wait", y - pool.wait() - - def test_track_slow_event(self): - pool = coros.CoroutinePool(track_events=True) - def slow(): - api.sleep(0.1) - return 'ok' - pool.execute(slow) - self.assertEquals(pool.wait(), 'ok') - - class IncrActor(coros.Actor): def received(self, evt): self.value = getattr(self, 'value', 0) + 1 @@ -340,9 +220,11 @@ class TestActor(tests.TestCase): self.assertEqual(total[0], 2) # both coroutines should have been used self.assertEqual(self.actor._pool.current_size, 2) + api.sleep(0) self.assertEqual(self.actor._pool.free(), 1) evt.wait() self.assertEqual(total[0], 3) + api.sleep(0) self.assertEqual(self.actor._pool.free(), 2) diff --git a/greentest/db_pool_test.py b/greentest/db_pool_test.py index a073c6d..1ddee51 100644 --- a/greentest/db_pool_test.py +++ b/greentest/db_pool_test.py @@ -22,8 +22,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -import os.path - from eventlet import api, coros from greentest import tests from eventlet import db_pool diff --git a/greentest/greenio_test.py b/greentest/greenio_test.py index e769008..c454f7e 100644 --- a/greentest/greenio_test.py +++ b/greentest/greenio_test.py @@ -1,28 +1,24 @@ -"""\ -@file greenio_test.py - -Copyright (c) 2006-2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# Copyright (c) 2006-2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. from greentest import tests -from eventlet import api, greenio, util +from eventlet import api import socket # TODO try and reuse unit tests from within Python itself diff --git a/greentest/httpc_test.py b/greentest/httpc_test.py index 95110e4..5424730 100644 --- a/greentest/httpc_test.py +++ b/greentest/httpc_test.py @@ -1,33 +1,28 @@ -"""\ -@file httpc_test.py -@author Bryan O'Sullivan - -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# @author Bryan O'Sullivan +# +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import cgi from eventlet import api from eventlet import httpc -from eventlet import processes -from eventlet import util from eventlet import wsgi import time diff --git a/greentest/httpd_test.py b/greentest/httpd_test.py index e6af7c5..b51debe 100644 --- a/greentest/httpd_test.py +++ b/greentest/httpd_test.py @@ -1,27 +1,23 @@ -"""\ -@file httpd_test.py -@author Donovan Preston - -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" - +# @author Donovan Preston +# +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. from eventlet import api from eventlet import httpd @@ -33,8 +29,6 @@ try: except ImportError: from StringIO import StringIO -from eventlet import greenio - util.wrap_socket_with_coroutine_socket() @@ -106,7 +100,7 @@ class TestHttpd(tests.TestCase): def test_001_server(self): sock = api.connect_tcp( ('127.0.0.1', 12346)) - + fd = sock.makeGreenFile() fd.write('GET / HTTP/1.0\r\nHost: localhost\r\n\r\n') result = fd.read() @@ -118,7 +112,7 @@ class TestHttpd(tests.TestCase): def test_002_keepalive(self): sock = api.connect_tcp( ('127.0.0.1', 12346)) - + fd = sock.makeGreenFile() fd.write('GET / HTTP/1.1\r\nHost: localhost\r\n\r\n') read_http(sock) @@ -130,7 +124,7 @@ class TestHttpd(tests.TestCase): # This should go in greenio_test sock = api.connect_tcp( ('127.0.0.1', 12346)) - + fd = sock.makeGreenFile() fd.write('GET / HTTP/1.1\r\nHost: localhost\r\n\r\n') cancel = api.exc_after(1, RuntimeError) @@ -172,7 +166,7 @@ class TestHttpd(tests.TestCase): status = result.split(' ')[1] self.assertEqual(status, '414') fd.close() - + def test_007_get_arg(self): # define a new handler that does a get_arg as well as a read_body def new_handle_request(req): @@ -180,28 +174,28 @@ class TestHttpd(tests.TestCase): body = req.read_body() req.write('a is %s, body is %s' % (a, body)) self.site.handle_request = new_handle_request - + sock = api.connect_tcp( ('127.0.0.1', 12346)) request = '\r\n'.join(( - 'POST /%s HTTP/1.0', - 'Host: localhost', - 'Content-Length: 3', + 'POST /%s HTTP/1.0', + 'Host: localhost', + 'Content-Length: 3', '', 'a=a')) fd = sock.makeGreenFile() fd.write(request) - + # send some junk after the actual request fd.write('01234567890123456789') reqline, headers, body = read_http(sock) self.assertEqual(body, 'a is a, body is a=a') fd.close() - + def test_008_correctresponse(self): sock = api.connect_tcp( ('127.0.0.1', 12346)) - + fd = sock.makeGreenFile() fd.write('GET / HTTP/1.1\r\nHost: localhost\r\n\r\n') response_line_200,_,_ = read_http(sock) diff --git a/greentest/parse_results.py b/greentest/parse_results.py index 29319dc..89e7017 100755 --- a/greentest/parse_results.py +++ b/greentest/parse_results.py @@ -93,7 +93,6 @@ def main(db): 'parsed_command_record.id=command_record.id)') for row in c.execute(SQL).fetchall(): id, command, stdout, exitcode = row - stdout = stdout.encode() try: testname, hub = parse_stdout(stdout) if unittest_delim in stdout: diff --git a/greentest/pools_test.py b/greentest/pools_test.py index d81c8d1..b28b9e4 100644 --- a/greentest/pools_test.py +++ b/greentest/pools_test.py @@ -1,35 +1,29 @@ -"""\ -@file test_pools.py -@author Donovan Preston, Aaron Brashears - -Copyright (c) 2006-2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" - -import sys +# @author Donovan Preston, Aaron Brashears +# +# Copyright (c) 2006-2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. from eventlet import api from eventlet import channel from eventlet import coros from eventlet import pools from greentest import tests -from eventlet import timer class IntPool(pools.Pool): def create(self): @@ -240,190 +234,6 @@ class TestFan(tests.TestCase): self.assertRaises(pools.SomeFailed, self.pool.fan, my_failing_callable, range(4)) -class TestCoroutinePool(tests.TestCase): - mode = 'static' - def setUp(self): - # raise an exception if we're waiting forever - self._cancel_timeout = api.exc_after(1, TestTookTooLong()) - - def tearDown(self): - self._cancel_timeout.cancel() - - def test_execute_async(self): - done = coros.event() - def some_work(): - done.send() - pool = pools.CoroutinePool(0, 2) - pool.execute_async(some_work) - done.wait() - - def test_execute(self): - value = 'return value' - def some_work(): - return value - pool = pools.CoroutinePool(0, 2) - worker = pool.execute(some_work) - self.assertEqual(value, worker.wait()) - - def test_multiple_coros(self): - evt = coros.event() - results = [] - def producer(): - results.append('prod') - evt.send() - - def consumer(): - results.append('cons1') - evt.wait() - results.append('cons2') - - pool = pools.CoroutinePool(0, 2) - done = pool.execute(consumer) - pool.execute_async(producer) - done.wait() - self.assertEquals(['cons1', 'prod', 'cons2'], results) - - def test_timer_cancel(self): - timer_fired = [] - def fire_timer(): - timer_fired.append(True) - def some_work(): - api.get_hub().schedule_call_local(0, fire_timer) - pool = pools.CoroutinePool(0, 2) - worker = pool.execute(some_work) - worker.wait() - api.sleep(0) - self.assertEquals(timer_fired, []) - - def test_reentrant(self): - pool = pools.CoroutinePool(0,1) - def reenter(): - waiter = pool.execute(lambda a: a, 'reenter') - self.assertEqual('reenter', waiter.wait()) - - outer_waiter = pool.execute(reenter) - outer_waiter.wait() - - evt = coros.event() - def reenter_async(): - pool.execute_async(lambda a: a, 'reenter') - evt.send('done') - - pool.execute_async(reenter_async) - evt.wait() - - def test_horrible_main_loop_death(self): - # testing the case that causes the run_forever - # method to exit unwantedly - pool = pools.CoroutinePool(min_size=1, max_size=1) - def crash(*args, **kw): - raise RuntimeError("Whoa") - class FakeFile(object): - write = crash - - # we're going to do this by causing the traceback.print_exc in - # safe_apply to raise an exception and thus exit _main_loop - normal_err = sys.stderr - try: - sys.stderr = FakeFile() - waiter = pool.execute(crash) - self.assertRaises(RuntimeError, waiter.wait) - # the pool should have something free at this point since the - # waiter returned - self.assertEqual(pool.free(), 1) - # shouldn't block when trying to get - t = api.exc_after(0.1, api.TimeoutError) - self.assert_(pool.get()) - t.cancel() - finally: - sys.stderr = normal_err - - def test_track_events(self): - pool = pools.CoroutinePool(track_events=True) - for x in range(6): - pool.execute(lambda n: n, x) - for y in range(6): - pool.wait() - - def test_track_slow_event(self): - pool = pools.CoroutinePool(track_events=True) - def slow(): - api.sleep(0.1) - return 'ok' - pool.execute(slow) - self.assertEquals(pool.wait(), 'ok') - - def test_channel_smash(self): - # The premise is that the coroutine in the pool exhibits an - # interest in receiving data from the channel, but then times - # out and gets recycled, so it ceases to care about what gets - # sent over the channel. The pool should be able to tell the - # channel about the sudden change of heart, or else, when we - # eventually do send something into the channel it will catch - # the coroutine pool's coroutine in an awkward place, losing - # the data that we're sending. - from eventlet import pools - pool = pools.CoroutinePool(min_size=1, max_size=1) - tp = pools.TokenPool(max_size=1) - token = tp.get() # empty pool - def do_receive(tp): - api.exc_after(0, RuntimeError()) - try: - t = tp.get() - self.fail("Shouldn't have recieved anything from the pool") - except RuntimeError: - return 'timed out' - - # the execute makes the pool expect that coroutine, but then - # immediately cuts bait - e1 = pool.execute(do_receive, tp) - self.assertEquals(e1.wait(), 'timed out') - - # the pool can get some random item back - def send_wakeup(tp): - tp.put('wakeup') - api.spawn(send_wakeup, tp) - - # now we ask the pool to run something else, which should not - # be affected by the previous send at all - def resume(): - return 'resumed' - e2 = pool.execute(resume) - self.assertEquals(e2.wait(), 'resumed') - - # we should be able to get out the thing we put in there, too - self.assertEquals(tp.get(), 'wakeup') - - def test_channel_death(self): - # In here, we have a coroutine trying to receive data from a - # channel, but timing out immediately and dying. The channel - # should be smart enough to not try to send data to a dead - # coroutine, because if it tries to, it'll lose the data. - from eventlet import pools - tp = pools.TokenPool(max_size=1) - token = tp.get() - e1 = coros.event() - def do_receive(evt, tp): - api.exc_after(0, RuntimeError()) - try: - t = tp.get() - evt.send(t) - except RuntimeError: - evt.send('timed out') - - # the execute gets the pool to add a waiter, but then kills - # itself off - api.spawn(do_receive, e1, tp) - self.assertEquals(e1.wait(), 'timed out') - - def send_wakeup(tp): - tp.put('wakeup') - api.spawn(send_wakeup, tp) - - # should be able to retrieve the message - self.assertEquals(tp.get(), 'wakeup') - - if __name__ == '__main__': tests.main() diff --git a/greentest/processes_test.py b/greentest/processes_test.py index b5eee6a..6ac4fee 100644 --- a/greentest/processes_test.py +++ b/greentest/processes_test.py @@ -1,30 +1,27 @@ -"""\ -@file processes_test.py -@author Donovan Preston, Aaron Brashears +# @author Donovan Preston, Aaron Brashears +# +# Copyright (c) 2006-2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. -Copyright (c) 2006-2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" import sys from greentest import tests -from eventlet import api from eventlet import processes class TestEchoPool(tests.TestCase): diff --git a/greentest/record_results.py b/greentest/record_results.py index de39394..c92b67e 100755 --- a/greentest/record_results.py +++ b/greentest/record_results.py @@ -26,6 +26,7 @@ Usage: %prog program [args] """ import sys import os +import codecs try: import sqlite3 except ImportError: @@ -63,7 +64,7 @@ def main(): print arg returncode = os.system(arg)>>8 print arg, 'finished with code', returncode - stdout = file(output_name).read() + stdout = codecs.open(output_name, mode='r', encoding='utf-8', errors='replace').read().replace('\x00', '?') if not debug: if returncode==1: pass diff --git a/greentest/runall.py b/greentest/runall.py index f26eb0d..7d4db31 100755 --- a/greentest/runall.py +++ b/greentest/runall.py @@ -37,7 +37,7 @@ COMMAND = sys.executable + ' ./record_results.py ' + sys.executable + ' ./with_t PARSE_PERIOD = 10 # the following aren't in the default list unless --all option present -NOT_HUBS = set(['nginx']) +NOT_HUBS = set() NOT_REACTORS = set(['wxreactor', 'glib2reactor', 'gtk2reactor']) NOT_TESTS = set() diff --git a/greentest/test__pool.py b/greentest/test__pool.py index b9be4ae..38354c7 100644 --- a/greentest/test__pool.py +++ b/greentest/test__pool.py @@ -1,4 +1,3 @@ -import sys from eventlet import pool, coros, api from greentest import LimitedTestCase from unittest import main diff --git a/greentest/test__twistedutil_protocol.py b/greentest/test__twistedutil_protocol.py index dad7441..3da5aec 100644 --- a/greentest/test__twistedutil_protocol.py +++ b/greentest/test__twistedutil_protocol.py @@ -20,7 +20,7 @@ # THE SOFTWARE. from twisted.internet import reactor -from greentest import exit_unless_twisted, LimitedTestCase +from greentest import exit_unless_twisted exit_unless_twisted() import unittest @@ -188,53 +188,6 @@ class TestGreenTransport_bufsize1(TestGreenTransport): # self.assertEqual('', self.conn.recv()) # -# class TestHalfClose_TCP(LimitedTestCase): -# -# def _test_server(self, conn): -# conn.write('hello') -# conn.loseWriteConnection() -# self.assertRaises(pr.ConnectionDone, conn.write, 'hey') -# data = conn.read() -# self.assertEqual('bye', data) -# conn.loseConnection() -# self.assertRaises(ConnectionDone, conn._wait) -# self.check.append('server') -# -# def setUp(self): -# LimitedTestCase.setUp(self) -# self.factory = pr.SpawnFactory(self._test_server) -# self.port = reactor.listenTCP(0, self.factory) -# self.conn = pr.GreenClientCreator(reactor).connectTCP('localhost', self.port.getHost().port) -# self.port.stopListening() -# self.check = [] -# -# def test(self): -# conn = self.conn -# data = conn.read() -# self.assertEqual('hello', data) -# conn.write('bye') -# conn.loseWriteConnection() -# self.assertRaises(pr.ConnectionDone, conn.write, 'hoy') -# self.factory.waitall() -# self.assertRaises(ConnectionDone, conn._wait) -# assert self.check == ['server'] -# -# class TestHalfClose_TLS(TestHalfClose_TCP): -# -# def setUp(self): -# LimitedTestCase.setUp(self) -# from gnutls.crypto import X509PrivateKey, X509Certificate -# from gnutls.interfaces.twisted import X509Credentials -# cert = X509Certificate(open('gnutls_valid.crt').read()) -# key = X509PrivateKey(open('gnutls_valid.key').read()) -# server_credentials = X509Credentials(cert, key) -# self.factory = pr.SpawnFactory(self._test_server) -# self.port = reactor.listenTLS(0, self.factory, server_credentials) -# self.conn = pr.GreenClientCreator(reactor).connectTLS('localhost', self.port.getHost().port, X509Credentials()) -# self.port.stopListening() -# self.check = [] -# - if socket is not None: class TestUnbufferedTransport_socketserver(TestUnbufferedTransport): @@ -275,7 +228,6 @@ try: import gnutls.interfaces.twisted except ImportError: del TestTLSError - del TestHalfClose_TLS if __name__=='__main__': unittest.main() diff --git a/greentest/tests.py b/greentest/tests.py index 41968c2..19d93d9 100644 --- a/greentest/tests.py +++ b/greentest/tests.py @@ -1,27 +1,24 @@ -"""\ -@file tests.py -@author Donovan Preston -@brief Indirection layer for tests in case we want to fix unittest. - -Copyright (c) 2006-2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# @author Donovan Preston +# @brief Indirection layer for tests in case we want to fix unittest. +# +# Copyright (c) 2006-2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import errno import os @@ -44,24 +41,24 @@ def find_command(command): if os.access(p, os.X_OK): return p raise IOError(errno.ENOENT, 'Command not found: %r' % command) - + def run_all_tests(test_files = doc_test_files): - """ Runs all the unit tests, returning immediately after the + """ Runs all the unit tests, returning immediately after the first failed test. - + Returns true if the tests all succeeded. This method is really much longer than it ought to be. """ eventlet_dir = os.path.realpath(os.path.dirname(__file__)) if eventlet_dir not in sys.path: sys.path.append(eventlet_dir) - + # add all _test files as a policy import glob - test_files += [os.path.splitext(os.path.basename(x))[0] + test_files += [os.path.splitext(os.path.basename(x))[0] for x in glob.glob(os.path.join(eventlet_dir, "*_test.py"))] test_files.sort() - + for test_file in test_files: print "-=", test_file, "=-" try: @@ -69,21 +66,21 @@ def run_all_tests(test_files = doc_test_files): except ImportError: print "Unable to import %s, skipping" % test_file continue - + if test_file.endswith('_test'): # gawd, unittest, why you make it so difficult to just run some tests! suite = unittest.findTestCases(test_module) result = unittest.TextTestRunner().run(suite) if not result.wasSuccessful(): return False - else: + else: failures, tests = doctest.testmod(test_module) if failures: return False else: print "OK" - + return True - + if __name__ == '__main__': run_all_tests() diff --git a/greentest/timer_test.py b/greentest/timer_test.py index ecebe2a..75ddd0e 100644 --- a/greentest/timer_test.py +++ b/greentest/timer_test.py @@ -1,26 +1,23 @@ -"""\ -@file timer_test.py -@author Donovan Preston - -Copyright (c) 2006-2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" +# @author Donovan Preston +# +# Copyright (c) 2006-2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import unittest diff --git a/greentest/tpool_test.py b/greentest/tpool_test.py index a7641a7..7848242 100644 --- a/greentest/tpool_test.py +++ b/greentest/tpool_test.py @@ -1,27 +1,22 @@ -"""\ -@file tpool_test.py +# Copyright (c) 2007, Linden Research, Inc. +# Copyright (c) 2007, IBM Corp. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. -Copyright (c) 2007, Linden Research, Inc. -Copyright (c) 2007, IBM Corp. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -""" - -import os, socket, time, threading +import time from eventlet import coros, api, tpool from greentest import tests -from eventlet.tpool import erpc from sys import stdout import random diff --git a/greentest/wsgi_test.py b/greentest/wsgi_test.py index f896c93..998d23d 100644 --- a/greentest/wsgi_test.py +++ b/greentest/wsgi_test.py @@ -1,26 +1,24 @@ -"""\ -@file wsgi_test.py -@author Donovan Preston +# @author Donovan Preston +# +# Copyright (c) 2007, Linden Research, Inc. +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. -Copyright (c) 2007, Linden Research, Inc. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -""" import cgi import os @@ -28,7 +26,6 @@ import os from eventlet import api from eventlet import wsgi from eventlet import processes -from eventlet import util try: from cStringIO import StringIO @@ -43,7 +40,7 @@ def hello_world(env, start_response): if env['PATH_INFO'] == 'notexist': start_response('404 Not Found', [('Content-type', 'text/plain')]) return ["not found"] - + start_response('200 OK', [('Content-type', 'text/plain')]) return ["hello world"] @@ -123,7 +120,7 @@ class TestHttpd(tests.TestCase): def test_001_server(self): sock = api.connect_tcp( ('127.0.0.1', 12346)) - + fd = sock.makeGreenFile() fd.write('GET / HTTP/1.0\r\nHost: localhost\r\n\r\n') result = fd.read() @@ -135,7 +132,7 @@ class TestHttpd(tests.TestCase): def test_002_keepalive(self): sock = api.connect_tcp( ('127.0.0.1', 12346)) - + fd = sock.makeGreenFile() fd.write('GET / HTTP/1.1\r\nHost: localhost\r\n\r\n') read_http(sock) @@ -147,7 +144,7 @@ class TestHttpd(tests.TestCase): # This should go in greenio_test sock = api.connect_tcp( ('127.0.0.1', 12346)) - + fd = sock.makeGreenFile() fd.write('GET / HTTP/1.1\r\nHost: localhost\r\n\r\n') cancel = api.exc_after(1, RuntimeError) @@ -189,7 +186,7 @@ class TestHttpd(tests.TestCase): status = result.split(' ')[1] self.assertEqual(status, '414') fd.close() - + def test_007_get_arg(self): # define a new handler that does a get_arg as well as a read_body def new_app(env, start_response): @@ -201,24 +198,24 @@ class TestHttpd(tests.TestCase): sock = api.connect_tcp( ('127.0.0.1', 12346)) request = '\r\n'.join(( - 'POST / HTTP/1.0', - 'Host: localhost', - 'Content-Length: 3', + 'POST / HTTP/1.0', + 'Host: localhost', + 'Content-Length: 3', '', 'a=a')) fd = sock.makeGreenFile() fd.write(request) - + # send some junk after the actual request fd.write('01234567890123456789') reqline, headers, body = read_http(sock) self.assertEqual(body, 'a is a, body is a=a') fd.close() - + def test_008_correctresponse(self): sock = api.connect_tcp( ('127.0.0.1', 12346)) - + fd = sock.makeGreenFile() fd.write('GET / HTTP/1.1\r\nHost: localhost\r\n\r\n') response_line_200,_,_ = read_http(sock) @@ -233,7 +230,7 @@ class TestHttpd(tests.TestCase): self.site.application = chunked_app sock = api.connect_tcp( ('127.0.0.1', 12346)) - + fd = sock.makeGreenFile() fd.write('GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n') self.assert_('Transfer-Encoding: chunked' in fd.read()) @@ -242,7 +239,7 @@ class TestHttpd(tests.TestCase): self.site.application = chunked_app sock = api.connect_tcp( ('127.0.0.1', 12346)) - + fd = sock.makeGreenFile() fd.write('GET / HTTP/1.0\r\nHost: localhost\r\nConnection: close\r\n\r\n') self.assert_('Transfer-Encoding: chunked' not in fd.read()) @@ -251,7 +248,7 @@ class TestHttpd(tests.TestCase): self.site.application = big_chunks sock = api.connect_tcp( ('127.0.0.1', 12346)) - + fd = sock.makeGreenFile() fd.write('GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n') headers = fd.readuntil('\r\n\r\n') @@ -273,9 +270,9 @@ class TestHttpd(tests.TestCase): certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt') private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key') - + sock = api.ssl_listener(('', 4201), certificate_file, private_key_file) - + api.spawn(wsgi.server, sock, wsgi_app) result = httpc.post("https://localhost:4201/foo", "abc") @@ -295,6 +292,20 @@ class TestHttpd(tests.TestCase): res = httpc.get("https://localhost:4202/foo") self.assertEquals(res, '') + def test_013_empty_return(self): + from eventlet import httpc + def wsgi_app(environ, start_response): + start_response("200 OK", []) + return [""] + + certificate_file = os.path.join(os.path.dirname(__file__), 'test_server.crt') + private_key_file = os.path.join(os.path.dirname(__file__), 'test_server.key') + sock = api.ssl_listener(('', 4202), certificate_file, private_key_file) + api.spawn(wsgi.server, sock, wsgi_app) + + res = httpc.get("https://localhost:4202/foo") + self.assertEquals(res, '') + if __name__ == '__main__': tests.main()