Commit 715a7071 authored by Denis Bilenko's avatar Denis Bilenko

Experimental/WIP PyPy support #248

Some tests fail, consult known_failures.py for the list.

stdlib's signal module is not supported. Depends on https://bitbucket.org/cffi/cffi/issue/152/handling-errors-from-signal-handlers-in

On PyPy, sys.exc_info is shared between greenlets apparently https://bugs.pypy.org/issue1743.

based on gevent-on-pypy/pypycore@f04a41c written by Ralf Schmitt and Lucas Clemente Vella with patches from hasenj and Armin Rigo
parent d5c907bf
......@@ -3,9 +3,12 @@ python:
- "2.6"
- "2.7"
- "3.3"
- "pypy"
matrix:
allow_failures:
- python: "3.3"
script: make travis
script:
- if [[ $TRAVIS_PYTHON_VERSION == 'pypy' ]]; then PYTHON=pypy make travis_pypy; fi
- if [[ $TRAVIS_PYTHON_VERSION != 'pypy' ]]; then PYTHON=python$TRAVIS_PYTHON_VERSION make travis_cpython; fi
notifications:
email: false
......@@ -4,13 +4,13 @@
PYTHON ?= python${TRAVIS_PYTHON_VERSION}
CYTHON ?= cython
all: gevent/gevent.core.c gevent/gevent.ares.c gevent/gevent._semaphore.c gevent/gevent._util.c
all: gevent/gevent.corecext.c gevent/gevent.ares.c gevent/gevent._semaphore.c gevent/gevent._util.c
gevent/gevent.core.c: gevent/core.ppyx gevent/libev.pxd
$(PYTHON) util/cythonpp.py -o gevent.core.c gevent/core.ppyx
echo >> gevent.core.c
echo '#include "callbacks.c"' >> gevent.core.c
mv gevent.core.* gevent/
gevent/gevent.corecext.c: gevent/core.ppyx gevent/libev.pxd
$(PYTHON) util/cythonpp.py -o gevent.corecext.c gevent/core.ppyx
echo >> gevent.corecext.c
echo '#include "callbacks.c"' >> gevent.corecext.c
mv gevent.corecext.* gevent/
gevent/gevent.ares.c: gevent/ares.pyx gevent/*.pxd
$(CYTHON) -o gevent.ares.c gevent/ares.pyx
......@@ -26,6 +26,7 @@ gevent/gevent._util.c: gevent/_util.pyx
clean:
rm -f gevent.core.c gevent.core.h core.pyx gevent/gevent.core.c gevent/gevent.core.h gevent/core.pyx
rm -f gevent.corecext.c gevent.corecext.h gevent/gevent.corecext.c gevent/gevent.corecext.h
rm -f gevent.ares.c gevent.ares.h gevent/gevent.ares.c gevent/gevent.ares.h
rm -f gevent._semaphore.c gevent._semaphore.h gevent/gevent._semaphore.c gevent/gevent._semaphore.h
rm -f gevent._util.c gevent._util.h gevent/gevent._util.c gevent/gevent._util.h
......@@ -57,7 +58,14 @@ travistest:
cd greentest && GEVENT_RESOLVER=ares GEVENTARES_SERVERS=8.8.8.8 ${PYTHON} testrunner.py --config ../known_failures.py --ignore tests_that_dont_use_resolver.txt
cd greentest && GEVENT_FILE=thread ${PYTHON} testrunner.py --config ../known_failures.py `grep -l subprocess test_*.py`
travis:
travis_pypy:
# no need to repeat linters here
which ${PYTHON}
${PYTHON} --version
${PYTHON} setup.py install
NWORKERS=1 cd greentest && ${PYTHON} testrunner.py --config ../known_failures.py
travis_cpython:
make whitespace
pip install -q pep8
......
......@@ -32,7 +32,7 @@ __all__ = ['get_hub',
'reinit']
from gevent.hub import get_hub, iwait, wait
from gevent.hub import get_hub, iwait, wait, PYPY
from gevent.greenlet import Greenlet, joinall, killall
spawn = Greenlet.spawn
spawn_later = Greenlet.spawn_later
......
......@@ -2,6 +2,7 @@
import time
from gevent import _socketcommon
from gevent.hub import PYPY
for key in _socketcommon.__dict__:
if key.startswith('__'):
......@@ -36,6 +37,15 @@ class _closedsocket(object):
raise error(EBADF, 'Bad file descriptor')
# All _delegate_methods must also be initialized here.
send = recv = recv_into = sendto = recvfrom = recvfrom_into = _dummy
if PYPY:
def _drop(self):
pass
def _reuse(self):
pass
__getattr__ = _dummy
......@@ -57,6 +67,8 @@ class socket(object):
else:
self._sock = _sock
self.timeout = _socket.getdefaulttimeout()
if PYPY:
self._sock._reuse()
self._sock.setblocking(0)
fileno = self._sock.fileno()
self.hub = get_hub()
......@@ -133,13 +145,19 @@ class socket(object):
raise
sys.exc_clear()
self._wait(self._read_event)
return socket(_sock=client_socket), address
sockobj = socket(_sock=client_socket)
if PYPY:
client_socket._drop()
return sockobj, address
def close(self, _closedsocket=_closedsocket, cancel_wait_ex=cancel_wait_ex):
# This function should not reference any globals. See Python issue #808164.
self.hub.cancel_wait(self._read_event, cancel_wait_ex)
self.hub.cancel_wait(self._write_event, cancel_wait_ex)
s = self._sock
self._sock = _closedsocket()
if PYPY:
s._drop()
@property
def closed(self):
......@@ -196,7 +214,10 @@ class socket(object):
# socket (hence creating a new instance)
# 2) The resulting fileobject must keep the timeout in order
# to be compatible with the stdlib's socket.makefile.
return _fileobject(type(self)(_sock=self), mode, bufsize)
fobj = _fileobject(type(self)(_sock=self._sock), mode, bufsize)
if PYPY:
self._sock._drop()
return fobj
def recv(self, *args):
sock = self._sock # keeping the reference so that fd is not closed during waiting
......@@ -340,20 +361,38 @@ class socket(object):
exec(_s % (_m, _m, _m, _m))
del _m, _s
if PYPY:
def _reuse(self):
self._sock._reuse()
def _drop(self):
self._sock._drop()
SocketType = socket
if hasattr(_socket, 'socketpair'):
def socketpair(*args):
one, two = _socket.socketpair(*args)
return socket(_sock=one), socket(_sock=two)
result = socket(_sock=one), socket(_sock=two)
if PYPY:
one._drop()
two._drop()
return result
else:
__implements__.remove('socketpair')
if hasattr(_socket, 'fromfd'):
def fromfd(*args):
return socket(_sock=_socket.fromfd(*args))
s = _socket.fromfd(*args)
result = socket(_sock=s)
if PYPY:
s._drop()
return result
else:
__implements__.remove('fromfd')
......
......@@ -18,8 +18,8 @@ except AttributeError:
import sys
import errno
from gevent.socket import socket, _fileobject, timeout_default
from gevent.socket import error as socket_error
from gevent.hub import string_types
from gevent.socket import error as socket_error, EWOULDBLOCK
from gevent.hub import string_types, PYPY
__implements__ = ['SSLSocket',
......@@ -65,6 +65,9 @@ class SSLSocket(socket):
ciphers=None):
socket.__init__(self, _sock=sock)
if PYPY:
sock._drop()
if certfile and not keyfile:
keyfile = certfile
# see if it's connected
......@@ -289,6 +292,17 @@ class SSLSocket(socket):
else:
self._makefile_refs -= 1
if PYPY:
def _reuse(self):
self._makefile_refs += 1
def _drop(self):
if self._makefile_refs < 1:
self.close()
else:
self._makefile_refs -= 1
def do_handshake(self):
"""Perform a TLS/SSL handshake."""
while True:
......@@ -331,24 +345,36 @@ class SSLSocket(socket):
"""Accepts a new connection from a remote client, and returns
a tuple containing that new connection wrapped with a server-side
SSL channel, and the address of the remote client."""
newsock, addr = socket.accept(self)
return (SSLSocket(newsock._sock,
keyfile=self.keyfile,
certfile=self.certfile,
server_side=True,
cert_reqs=self.cert_reqs,
ssl_version=self.ssl_version,
ca_certs=self.ca_certs,
do_handshake_on_connect=self.do_handshake_on_connect,
suppress_ragged_eofs=self.suppress_ragged_eofs,
ciphers=self.ciphers),
addr)
sock = self._sock
while True:
try:
client_socket, address = sock.accept()
break
except socket_error as ex:
if ex.args[0] != EWOULDBLOCK or self.timeout == 0.0:
raise
sys.exc_clear()
self._wait(self._read_event)
sslobj = SSLSocket(client_socket,
keyfile=self.keyfile,
certfile=self.certfile,
server_side=True,
cert_reqs=self.cert_reqs,
ssl_version=self.ssl_version,
ca_certs=self.ca_certs,
do_handshake_on_connect=self.do_handshake_on_connect,
suppress_ragged_eofs=self.suppress_ragged_eofs,
ciphers=self.ciphers)
return sslobj, address
def makefile(self, mode='r', bufsize=-1):
"""Make and return a file-like object that
works with the SSL connection. Just use the code
from the socket module."""
self._makefile_refs += 1
if not PYPY:
self._makefile_refs += 1
# close=True so as to decrement the reference count when done with
# the file-like object.
return _fileobject(self, mode, bufsize, close=True)
......
......@@ -126,10 +126,17 @@ class BaseServer(object):
def do_handle(self, *args):
spawn = self._spawn
if spawn is None:
self._handle(*args)
else:
spawn(self._handle, *args)
try:
if spawn is None:
self._handle(*args)
else:
spawn(self._handle, *args)
except:
self.do_close(*args)
raise
def do_close(self, *args):
pass
def _do_read(self):
for _ in xrange(self.max_accept):
......
from gevent.hub import PYPY
if PYPY:
from gevent import corecffi as _core
else:
from gevent import corecext as _core
for item in dir(_core):
if item.startswith('__'):
continue
globals()[item] = getattr(_core, item)
__all__ = _core.__all__
from __future__ import absolute_import
import sys
import os
import traceback
import signal as signalmodule
__all__ = ['get_version',
'get_header_version',
'supported_backends',
'recommended_backends',
'embeddable_backends',
'time',
'loop']
def st_nlink_type():
if sys.platform == "darwin":
return "short"
return "long long"
from cffi import FFI
ffi = FFI()
ffi.cdef("""
#define EV_MINPRI ...
#define EV_MAXPRI ...
#define EV_VERSION_MAJOR ...
#define EV_VERSION_MINOR ...
#define EV_UNDEF ...
#define EV_NONE ...
#define EV_READ ...
#define EV_WRITE ...
#define EV__IOFDSET ...
#define EV_TIMER ...
#define EV_PERIODIC ...
#define EV_SIGNAL ...
#define EV_CHILD ...
#define EV_STAT ...
#define EV_IDLE ...
#define EV_PREPARE ...
#define EV_CHECK ...
#define EV_EMBED ...
#define EV_FORK ...
#define EV_CLEANUP ...
#define EV_ASYNC ...
#define EV_CUSTOM ...
#define EV_ERROR ...
#define EVFLAG_AUTO ...
#define EVFLAG_NOENV ...
#define EVFLAG_FORKCHECK ...
#define EVFLAG_NOINOTIFY ...
#define EVFLAG_SIGNALFD ...
#define EVFLAG_NOSIGMASK ...
#define EVBACKEND_SELECT ...
#define EVBACKEND_POLL ...
#define EVBACKEND_EPOLL ...
#define EVBACKEND_KQUEUE ...
#define EVBACKEND_DEVPOLL ...
#define EVBACKEND_PORT ...
/* #define EVBACKEND_IOCP ... */
#define EVBACKEND_ALL ...
#define EVBACKEND_MASK ...
#define EVRUN_NOWAIT ...
#define EVRUN_ONCE ...
#define EVBREAK_CANCEL ...
#define EVBREAK_ONE ...
#define EVBREAK_ALL ...
struct ev_loop {
int backend_fd;
int activecnt;
...;
};
struct ev_io {
int fd;
int events;
...;
};
struct ev_timer {
double at;
...;
};
struct ev_signal {...;};
struct ev_idle {...;};
struct ev_prepare {...;};
struct ev_check {...;};
struct ev_fork {...;};
struct ev_async {...;};
struct ev_child {
int pid;
int rpid;
int rstatus;
...;
};
struct stat {
""" + st_nlink_type() + """ st_nlink;
...;
};
struct ev_stat {
struct stat attr;
struct stat prev;
double interval;
...;
};
typedef double ev_tstamp;
int ev_version_major();
int ev_version_minor();
unsigned int ev_supported_backends (void);
unsigned int ev_recommended_backends (void);
unsigned int ev_embeddable_backends (void);
ev_tstamp ev_time (void);
void ev_set_syserr_cb(void *);
int ev_priority(void*);
void ev_set_priority(void*, int);
int ev_is_pending(void*);
int ev_is_active(void*);
void ev_io_init(struct ev_io*, void* callback, int fd, int events);
void ev_io_start(struct ev_loop*, struct ev_io*);
void ev_io_stop(struct ev_loop*, struct ev_io*);
void ev_feed_event(struct ev_loop*, void*, int);
void ev_timer_init(struct ev_timer*, void (*callback)(struct ev_loop *_loop, struct ev_timer *w, int revents), double, double);
void ev_timer_start(struct ev_loop*, struct ev_timer*);
void ev_timer_stop(struct ev_loop*, struct ev_timer*);
void ev_timer_again(struct ev_loop*, struct ev_timer*);
void ev_signal_init(struct ev_signal*, void* callback, int);
void ev_signal_start(struct ev_loop*, struct ev_signal*);
void ev_signal_stop(struct ev_loop*, struct ev_signal*);
void ev_idle_init(struct ev_idle*, void* callback);
void ev_idle_start(struct ev_loop*, struct ev_idle*);
void ev_idle_stop(struct ev_loop*, struct ev_idle*);
void ev_prepare_init(struct ev_prepare*, void* callback);
void ev_prepare_start(struct ev_loop*, struct ev_prepare*);
void ev_prepare_stop(struct ev_loop*, struct ev_prepare*);
void ev_check_init(struct ev_check*, void* callback);
void ev_check_start(struct ev_loop*, struct ev_check*);
void ev_check_stop(struct ev_loop*, struct ev_check*);
void ev_fork_init(struct ev_fork*, void* callback);
void ev_fork_start(struct ev_loop*, struct ev_fork*);
void ev_fork_stop(struct ev_loop*, struct ev_fork*);
void ev_async_init(struct ev_async*, void* callback);
void ev_async_start(struct ev_loop*, struct ev_async*);
void ev_async_stop(struct ev_loop*, struct ev_async*);
void ev_async_send(struct ev_loop*, struct ev_async*);
int ev_async_pending(struct ev_async*);
void ev_child_init(struct ev_child*, void* callback, int, int);
void ev_child_start(struct ev_loop*, struct ev_child*);
void ev_child_stop(struct ev_loop*, struct ev_child*);
void ev_stat_init(struct ev_stat*, void* callback, char*, double);
void ev_stat_start(struct ev_loop*, struct ev_stat*);
void ev_stat_stop(struct ev_loop*, struct ev_stat*);
struct ev_loop *ev_default_loop (unsigned int flags);
struct ev_loop* ev_loop_new(unsigned int flags);
void ev_loop_destroy(struct ev_loop*);
void ev_loop_fork(struct ev_loop*);
int ev_is_default_loop (struct ev_loop *);
unsigned int ev_iteration(struct ev_loop*);
unsigned int ev_depth(struct ev_loop*);
unsigned int ev_backend(struct ev_loop*);
void ev_verify(struct ev_loop*);
void ev_run(struct ev_loop*, int flags);
ev_tstamp ev_now (struct ev_loop *);
void ev_now_update (struct ev_loop *); /* update event loop time */
void ev_ref(struct ev_loop*);
void ev_unref(struct ev_loop*);
void ev_break(struct ev_loop*, int);
unsigned int ev_pending_count(struct ev_loop*);
struct ev_loop* gevent_ev_default_loop(unsigned int flags);
void gevent_install_sigchld_handler();
void (*gevent_noop)(struct ev_loop *_loop, struct ev_timer *w, int revents);
void ev_sleep (ev_tstamp delay); /* sleep for a while */
""")
thisdir = os.path.dirname(os.path.realpath(__file__))
include_dirs = [thisdir, os.path.join(thisdir, 'libev')]
libev = C = ffi.verify(""" // passed to the real C compiler
#define LIBEV_EMBED 1
#include "libev.h"
static void
_gevent_noop(struct ev_loop *_loop, struct ev_timer *w, int revents) { }
void (*gevent_noop)(struct ev_loop *, struct ev_timer *, int) = &_gevent_noop;
""", include_dirs=include_dirs)
del thisdir, include_dirs
libev.vfd_open = libev.vfd_get = lambda fd: fd
libev.vfd_free = lambda fd: None
UNDEF = libev.EV_UNDEF
NONE = libev.EV_NONE
READ = libev.EV_READ
WRITE = libev.EV_WRITE
TIMER = libev.EV_TIMER
PERIODIC = libev.EV_PERIODIC
SIGNAL = libev.EV_SIGNAL
CHILD = libev.EV_CHILD
STAT = libev.EV_STAT
IDLE = libev.EV_IDLE
PREPARE = libev.EV_PREPARE
CHECK = libev.EV_CHECK
EMBED = libev.EV_EMBED
FORK = libev.EV_FORK
CLEANUP = libev.EV_CLEANUP
ASYNC = libev.EV_ASYNC
CUSTOM = libev.EV_CUSTOM
ERROR = libev.EV_ERROR
READWRITE = libev.EV_READ | libev.EV_WRITE
MINPRI = libev.EV_MINPRI
MAXPRI = libev.EV_MAXPRI
BACKEND_PORT = libev.EVBACKEND_PORT
BACKEND_KQUEUE = libev.EVBACKEND_KQUEUE
BACKEND_EPOLL = libev.EVBACKEND_EPOLL
BACKEND_POLL = libev.EVBACKEND_POLL
BACKEND_SELECT = libev.EVBACKEND_SELECT
FORKCHECK = libev.EVFLAG_FORKCHECK
NOINOTIFY = libev.EVFLAG_NOINOTIFY
SIGNALFD = libev.EVFLAG_SIGNALFD
NOSIGMASK = libev.EVFLAG_NOSIGMASK
class _EVENTSType(object):
def __repr__(self):
return 'gevent.core.EVENTS'
EVENTS = GEVENT_CORE_EVENTS = _EVENTSType()
def get_version():
return 'libev-%d.%02d' % (C.ev_version_major(), C.ev_version_minor())
def get_header_version():
return 'libev-%d.%02d' % (C.EV_VERSION_MAJOR, C.EV_VERSION_MINOR)
_flags = [(C.EVBACKEND_PORT, 'port'),
(C.EVBACKEND_KQUEUE, 'kqueue'),
(C.EVBACKEND_EPOLL, 'epoll'),
(C.EVBACKEND_POLL, 'poll'),
(C.EVBACKEND_SELECT, 'select'),
(C.EVFLAG_NOENV, 'noenv'),
(C.EVFLAG_FORKCHECK, 'forkcheck'),
(C.EVFLAG_SIGNALFD, 'signalfd'),
(C.EVFLAG_NOSIGMASK, 'nosigmask')]
_flags_str2int = dict((string, flag) for (flag, string) in _flags)
_events = [(libev.EV_READ, 'READ'),
(libev.EV_WRITE, 'WRITE'),
(libev.EV__IOFDSET, '_IOFDSET'),
(libev.EV_PERIODIC, 'PERIODIC'),
(libev.EV_SIGNAL, 'SIGNAL'),
(libev.EV_CHILD, 'CHILD'),
(libev.EV_STAT, 'STAT'),
(libev.EV_IDLE, 'IDLE'),
(libev.EV_PREPARE, 'PREPARE'),
(libev.EV_CHECK, 'CHECK'),
(libev.EV_EMBED, 'EMBED'),
(libev.EV_FORK, 'FORK'),
(libev.EV_CLEANUP, 'CLEANUP'),
(libev.EV_ASYNC, 'ASYNC'),
(libev.EV_CUSTOM, 'CUSTOM'),
(libev.EV_ERROR, 'ERROR')]
def _flags_to_list(flags):
result = []
for code, value in _flags:
if flags & code:
result.append(value)
flags &= ~code
if not flags:
break
if flags:
result.append(flags)
return result
if sys.version_info[0] >= 3:
basestring = (bytes, str)
integer_types = int,
else:
import __builtin__
basestring = __builtin__.basestring
integer_types = (int, __builtin__.long)
def _flags_to_int(flags):
# Note, that order does not matter, libev has its own predefined order
if not flags:
return 0
if isinstance(flags, integer_types):
return flags
result = 0
try:
if isinstance(flags, basestring):
flags = flags.split(',')
for value in flags:
value = value.strip().lower()
if value:
result |= _flags_str2int[value]
except KeyError as ex:
raise ValueError('Invalid backend or flag: %s\nPossible values: %s' % (ex, ', '.join(sorted(_flags_str2int.keys()))))
return result
def _str_hex(flag):
if isinstance(flag, integer_types):
return hex(flag)
return str(flag)
def _check_flags(flags):
as_list = []
flags &= libev.EVBACKEND_MASK
if not flags:
return
if not (flags & libev.EVBACKEND_ALL):
raise ValueError('Invalid value for backend: 0x%x' % flags)
if not (flags & libev.ev_supported_backends()):
as_list = [_str_hex(x) for x in _flags_to_list(flags)]
raise ValueError('Unsupported backend: %s' % '|'.join(as_list))
def _events_to_str(events):
result = []
for (flag, string) in _events:
c_flag = flag
if events & c_flag:
result.append(string)
events = events & (~c_flag)
if not events:
break
if events:
result.append(hex(events))
return '|'.join(result)
def supported_backends():
return _flags_to_list(libev.ev_supported_backends())
def recommended_backends():
return _flags_to_list(libev.ev_recommended_backends())
def embeddable_backends():
return _flags_to_list(libev.ev_embeddable_backends())
def time():
return C.ev_time()
_default_loop_destroyed = False
class loop(object):
error_handler = None
def __init__(self, flags=None, default=None):
self._in_callback = False
self._callbacks = []
self._check = ffi.new("struct ev_check *")
self._check_callback_ffi = ffi.callback("void(*)(struct ev_loop *, void*, int)", self._check_callback)
libev.ev_check_init(self._check, self._check_callback_ffi)
self._prepare = ffi.new("struct ev_prepare *")
self._prepare_callback_ffi = ffi.callback("void(*)(struct ev_loop *, void*, int)", self._run_callbacks)
libev.ev_prepare_init(self._prepare, self._prepare_callback_ffi)
self._timer0 = ffi.new("struct ev_timer *")
libev.ev_timer_init(self._timer0, libev.gevent_noop, 0.0, 0.0)
c_flags = _flags_to_int(flags)
_check_flags(c_flags)
c_flags |= libev.EVFLAG_NOENV
if default is None:
default = True
if _default_loop_destroyed:
default = False
if default:
self._ptr = libev.gevent_ev_default_loop(c_flags)
if not self._ptr:
raise SystemError("ev_default_loop(%s) failed" % (c_flags, ))
else:
self._ptr = libev.ev_loop_new(c_flags)
if not self._ptr:
raise SystemError("ev_loop_new(%s) failed" % (c_flags, ))
if default or globals()["__SYSERR_CALLBACK"] is None:
set_syserr_cb(self._handle_syserr)
libev.ev_prepare_start(self._ptr, self._prepare)
self.unref()
libev.ev_check_start(self._ptr, self._check)
self.unref()
if default:
signalmodule.signal(2, self.int_handler)
self.ate_keyboard_interrupt = False
self.keyboard_interrupt_allowed = True
self._keepaliveset = set()
def _check_callback(self, *args):
if self.ate_keyboard_interrupt:
self.handle_error(self, KeyboardInterrupt, KeyboardInterrupt(), None)
self.ate_keyboard_interrupt = False
def int_handler(self, *args):
if self.keyboard_interrupt_allowed:
raise KeyboardInterrupt
self.ate_keyboard_interrupt = True
def _wrap_cb(self, cb):
def wrapper(*args):
try:
self.keyboard_interrupt_allowed = True
return cb(*args)
except:
self.handle_error((cb, args), *sys.exc_info())
finally:
self.keyboard_interrupt_allowed = False
return wrapper
def _run_callbacks(self, evloop, _, revents):
count = 1000
libev.ev_timer_stop(self._ptr, self._timer0)
while self._callbacks and count > 0:
callbacks = self._callbacks
self._callbacks = []
for cb in callbacks:
self.unref()
callback = cb.callback
args = cb.args
if callback is None or args is None:
continue
cb.callback = None
try:
self.keyboard_interrupt_allowed = True
callback(*args)
except:
self.handle_error(cb, *sys.exc_info())
finally:
self.keyboard_interrupt_allowed = False
# Note, this must be reset here, because cb.args is used as a flag in callback class,
cb.args = None
count -= 1
if self._callbacks:
libev.ev_timer_start(self._ptr, self._timer0)
def _stop_aux_watchers(self):
if libev.ev_is_active(self._prepare):
self.ref()
libev.ev_prepare_stop(self._ptr, self._prepare)
if libev.ev_is_active(self._check):
self.ref()
libev.ev_check_stop(self._ptr, self._check)
def destroy(self):
global _default_loop_destroyed
if self._ptr:
self._stop_aux_watchers()
if globals()["__SYSERR_CALLBACK"] == self._handle_syserr:
set_syserr_cb(None)
if libev.ev_is_default_loop(self._ptr):
_default_loop_destroyed = True
libev.ev_loop_destroy(self._ptr)
self._ptr = ffi.NULL
# XXX restore default_int_signal handler
@property
def ptr(self):
return self._ptr
@property
def WatcherType(self):
return watcher
@property
def MAXPRI(self):
return libev.EV_MAXPRI
@property
def MINPRI(self):
return libev.EV_MINPRI
def _handle_syserr(self, message, errno):
try:
errno = os.strerror(errno)
except:
traceback.print_exc()
try:
message = '%s: %s' % (message, errno)
except:
traceback.print_exc()
self.handle_error(None, SystemError, SystemError(message), None)
def handle_error(self, context, type, value, tb):
handle_error = None
error_handler = self.error_handler
if error_handler is not None:
# we do want to do getattr every time so that setting Hub.handle_error property just works
handle_error = getattr(error_handler, 'handle_error', error_handler)
handle_error(context, type, value, tb)
else:
self._default_handle_error(context, type, value, tb)
def _default_handle_error(self, context, type, value, tb):
# note: Hub sets its own error handler so this is not used by gevent
# this is here to make core.loop usable without the rest of gevent
traceback.print_exception(type, value, tb)
libev.ev_break(self._ptr, libev.EVBREAK_ONE)
def run(self, nowait=False, once=False):
flags = 0
if nowait:
flags |= libev.EVRUN_NOWAIT
if once:
flags |= libev.EVRUN_ONCE
self.keyboard_interrupt_allowed = False
libev.ev_run(self._ptr, flags)
self.keyboard_interrupt_allowed = True
def reinit(self):
libev.ev_loop_fork(self._ptr)
def ref(self):
libev.ev_ref(self._ptr)
def unref(self):
libev.ev_unref(self._ptr)
def break_(self, how=libev.EVBREAK_ONE):
libev.ev_break(self._ptr, how)
def verify(self):
libev.ev_verify(self._ptr)
def now(self):
return libev.ev_now(self._ptr)
def update(self):
libev.ev_now_update(self._ptr)
def __repr__(self):
return '<%s at 0x%x %s>' % (self.__class__.__name__, id(self), self._format())
@property
def default(self):
return True if libev.ev_is_default_loop(self._ptr) else False
@property
def iteration(self):
return libev.ev_iteration(self._ptr)
@property
def depth(self):
return libev.ev_depth(self._ptr)
@property
def backend_int(self):
return libev.ev_backend(self._ptr)
@property
def backend(self):
backend = libev.ev_backend(self._ptr)
for key, value in _flags:
if key == backend:
return value
return backend
@property
def pendingcnt(self):
return libev.ev_pending_count(self._ptr)
def io(self, fd, events, ref=True, priority=None):
return io(self, fd, events, ref, priority)
def timer(self, after, repeat=0.0, ref=True, priority=None):
return timer(self, after, repeat, ref, priority)
def signal(self, signum, ref=True, priority=None):
return signal(self, signum, ref, priority)
def idle(self, ref=True, priority=None):
return idle(self, ref, priority)
def prepare(self, ref=True, priority=None):
return prepare(self, ref, priority)
def check(self, ref=True, priority=None):
return check(self, ref, priority)
def fork(self, ref=True, priority=None):
return fork(self, ref, priority)
def async(self, ref=True, priority=None):
return async(self, ref, priority)
if sys.platform != "win32":
def child(self, pid, trace=0, ref=True):
return child(self, pid, trace, ref)
def install_sigchld(self):
libev.gevent_install_sigchld_handler()
def callback(self, priority=None):
return callback(self, priority)
def run_callback(self, func, *args):
cb = callback(func, args)
self._callbacks.append(cb)
self.ref()
return cb
def _format(self):
if not self._ptr:
return 'destroyed'
msg = self.backend
if self.default:
msg += ' default'
msg += ' pending=%s' % self.pendingcnt
msg += self._format_details()
return msg
def _format_details(self):
msg = ''
fileno = self.fileno()
try:
activecnt = self.activecnt
except AttributeError:
activecnt = None
if activecnt is not None:
msg += ' ref=' + repr(activecnt)
if fileno is not None:
msg += ' fileno=' + repr(fileno)
#if sigfd is not None and sigfd != -1:
# msg += ' sigfd=' + repr(sigfd)
return msg
def fileno(self):
if self._ptr:
fd = self._ptr.backend_fd
if fd >= 0:
return fd
@property
def activecnt(self):
if not self._ptr:
raise ValueError('operation on destroyed loop')
return self._ptr.activecnt
class callback(object):
def __init__(self, callback, args):
self.callback = callback
self.args = args
def stop(self):
self.callback = None
self.args = None
# Note, that __nonzero__ and pending are different
# nonzero is used in contexts where we need to know whether to schedule another callback,
# so it's true if it's pending or currently running
# 'pending' has the same meaning as libev watchers: it is cleared before entering callback
def __nonzero__(self):
# it's nonzero if it's pending or currently executing
return self.args is not None
@property
def pending(self):
return self.callback is not None
def _format(self):
return ''
class watcher(object):
def __init__(self, _loop, ref=True, priority=None, args=tuple()):
self.loop = _loop
if ref:
self._flags = 0
else:
self._flags = 4
self.args = None
self._callback = None
self._watcher = ffi.new(self._watcher_ffi_type)
self._cb = ffi.callback(self._watcher_ffi_cb, _loop._wrap_cb(self._run_callback))
if priority is not None:
libev.ev_set_priority(self._watcher, priority)
self._watcher_init(self._watcher, self._cb, *args)
# this is not needed, since we keep alive the watcher while it's started
#def __del__(self):
# self._watcher_stop(self.loop._ptr, self._watcher)
def __repr__(self):
format = self._format()
result = "<%s at 0x%x%s" % (self.__class__.__name__, id(self), format)
if self.pending:
result += " pending"
if self.callback is not None:
result += " callback=%r" % (self.callback, )
if self.args is not None:
result += " args=%r" % (self.args, )
if self.callback is None and self.args is None:
result += " stopped"
return result + ">"
def _format(self):
return ''
def _run_callback(self, loop, c_watcher, revents):
try:
self.callback(*self.args)
except:
try:
self.loop.handle_error(self, *sys.exc_info())
finally:
if revents & (libev.EV_READ | libev.EV_WRITE):
# /* io watcher: not stopping it may cause the failing callback to be called repeatedly */
try:
self.stop()
except:
self.loop.handle_error(self, *sys.exc_info())
return
# callbacks' self.active differs from ev_is_active(...) at
# this point. don't use it!
if not libev.ev_is_active(c_watcher):
self.stop()
def _libev_unref(self):
if self._flags & 6 == 4:
self.loop.unref()
self._flags |= 2
def _get_ref(self):
return False if self._flags & 4 else True
def _set_ref(self, value):
if value:
if not self._flags & 4:
return # ref is already True
if self._flags & 2: # ev_unref was called, undo
self.loop.ref()
self._flags &= ~6 # do not want unref, no outstanding unref
else:
if self._flags & 4:
return # ref is already False
self._flags |= 4
if not self._flags & 2 and libev.ev_is_active(self._watcher):
self.loop.unref()
self._flags |= 2
ref = property(_get_ref, _set_ref)
def _get_callback(self):
return self._callback
def _set_callback(self, callback):
if not callable(callback) and callback is not None:
raise TypeError("Expected callable, not %r" % (callback, ))
self._callback = callback
callback = property(_get_callback, _set_callback)
def start(self, callback, *args):
if callback is None:
raise TypeError('callback must be callable, not None')
self.callback = callback
self.args = args
self._libev_unref()
self._watcher_start(self.loop._ptr, self._watcher)
self.loop._keepaliveset.add(self)
def stop(self):
if self._flags & 2:
self.loop.ref()
self._flags &= ~2
self._watcher_stop(self.loop._ptr, self._watcher)
self.loop._keepaliveset.discard(self)
self._callback = None
self.args = None
def _get_priority(self):
return libev.ev_priority(self._watcher)
def _set_priority(self, priority):
if libev.ev_is_active(self._watcher):
raise AttributeError("Cannot set priority of an active watcher")
libev.ev_set_priority(self._watcher, priority)
priority = property(_get_priority, _set_priority)
def feed(self, revents, callback, *args):
self.callback = callback
self.args = args
if self._flags & 6 == 4:
self.loop.unref()
self._flags |= 2
libev.ev_feed_event(self.loop._ptr, self._watcher, revents)
if not self._flags & 1:
# Py_INCREF(<PyObjectPtr>self)
self._flags |= 1
@property
def active(self):
return True if libev.ev_is_active(self._watcher) else False
@property
def pending(self):
return True if libev.ev_is_pending(self._watcher) else False
class io(watcher):
_watcher_start = libev.ev_io_start
_watcher_stop = libev.ev_io_stop
_watcher_init = libev.ev_io_init
_watcher_type = 'ev_io'
_watcher_ffi_type = "struct %s *" % _watcher_type
_watcher_ffi_cb = "void(*)(struct ev_loop *, struct %s *, int)" % _watcher_type
def __init__(self, loop, fd, events, ref=True, priority=None):
if fd < 0:
raise ValueError('fd must be non-negative: %r' % fd)
if events & ~(libev.EV__IOFDSET | libev.EV_READ | libev.EV_WRITE):
raise ValueError('illegal event mask: %r' % events)
watcher.__init__(self, loop, ref=ref, priority=priority, args=(fd, events))
def _get_fd(self):
return libev.vfd_get(self._watcher.fd)
def _set_fd(self, fd):
if libev.ev_is_active(self._watcher):
raise AttributeError("'io' watcher attribute 'fd' is read-only while watcher is active")
vfd = libev.vfd_open(fd)
libev.vfd_free(self._watcher.fd)
libev.ev_io_init(self._watcher, self._cb, vfd, self._watcher.events)
fd = property(_get_fd, _set_fd)
def _get_events(self):
return libev.vfd_get(self._watcher.fd)
def _set_events(self, events):
if libev.ev_is_active(self._watcher):
raise AttributeError("'io' watcher attribute 'events' is read-only while watcher is active")
libev.ev_io_init(self._watcher, self._cb, self._watcher.fd, events)
events = property(_get_events, _set_events)
@property
def events_str(self):
return _events_to_str(self._watcher.events)
def _format(self):
return ' fd=%s events=%s' % (self.fd, self.events_str)
class timer(watcher):
_watcher_start = libev.ev_timer_start
_watcher_stop = libev.ev_timer_stop
_watcher_init = libev.ev_timer_init
_watcher_type = 'ev_timer'
_watcher_ffi_type = "struct %s *" % _watcher_type
_watcher_ffi_cb = "void(*)(struct ev_loop *, struct %s *, int)" % _watcher_type
def __init__(self, loop, after=0.0, repeat=0.0, ref=True, priority=None):
if repeat < 0.0:
raise ValueError("repeat must be positive or zero: %r" % repeat)
watcher.__init__(self, loop, ref=ref, priority=priority, args=(after, repeat))
def start(self, callback, *args, **kw):
if callback is None:
raise TypeError('callback must be callable, not None')
update = kw.get("update", True)
self.callback = callback
self.args = args
self._libev_unref() # LIBEV_UNREF
if update:
libev.ev_now_update(self.loop._ptr)
libev.ev_timer_start(self.loop._ptr, self._watcher)
self.loop._keepaliveset.add(self)
@property
def at(self):
return self._watcher.at
def again(self, callback, *args, **kw):
update = kw.get("update", True)
self.callback = callback
self.args = args
self._libev_unref()
if update:
libev.ev_now_update(self.loop._ptr)
libev.ev_timer_again(self.loop._ptr, self._watcher)
class signal(watcher):
_watcher_start = libev.ev_signal_start
_watcher_stop = libev.ev_signal_stop
_watcher_init = libev.ev_signal_init
_watcher_type = 'ev_signal'
_watcher_ffi_type = "struct %s *" % _watcher_type
_watcher_ffi_cb = "void(*)(struct ev_loop *, struct %s *, int)" % _watcher_type
def __init__(self, loop, signalnum, ref=True, priority=None):
if signalnum < 1 or signalnum >= signalmodule.NSIG:
raise ValueError('illegal signal number: %r' % signalnum)
# still possible to crash on one of libev's asserts:
# 1) "libev: ev_signal_start called with illegal signal number"
# EV_NSIG might be different from signal.NSIG on some platforms
# 2) "libev: a signal must not be attached to two different loops"
# we probably could check that in LIBEV_EMBED mode, but not in general
watcher.__init__(self, loop, ref=ref, priority=priority, args=(signalnum, ))
class idle(watcher):
_watcher_start = libev.ev_idle_start
_watcher_stop = libev.ev_idle_stop
_watcher_init = libev.ev_idle_init
_watcher_type = 'ev_idle'
_watcher_ffi_type = "struct %s *" % _watcher_type
_watcher_ffi_cb = "void(*)(struct ev_loop *, struct %s *, int)" % _watcher_type
class prepare(watcher):
_watcher_start = libev.ev_prepare_start
_watcher_stop = libev.ev_prepare_stop
_watcher_init = libev.ev_prepare_init
_watcher_type = 'ev_prepare'
_watcher_ffi_type = "struct %s *" % _watcher_type
_watcher_ffi_cb = "void(*)(struct ev_loop *, struct %s *, int)" % _watcher_type
class check(watcher):
_watcher_start = libev.ev_check_start
_watcher_stop = libev.ev_check_stop
_watcher_init = libev.ev_check_init
_watcher_type = 'ev_check'
_watcher_ffi_type = "struct %s *" % _watcher_type
_watcher_ffi_cb = "void(*)(struct ev_loop *, struct %s *, int)" % _watcher_type
class fork(watcher):
_watcher_start = libev.ev_fork_start
_watcher_stop = libev.ev_fork_stop
_watcher_init = libev.ev_fork_init
_watcher_type = 'ev_fork'
_watcher_ffi_type = "struct %s *" % _watcher_type
_watcher_ffi_cb = "void(*)(struct ev_loop *, struct %s *, int)" % _watcher_type
class async(watcher):
_watcher_start = libev.ev_async_start
_watcher_stop = libev.ev_async_stop
_watcher_init = libev.ev_async_init
_watcher_type = 'ev_async'
_watcher_ffi_type = "struct %s *" % _watcher_type
_watcher_ffi_cb = "void(*)(struct ev_loop *, struct %s *, int)" % _watcher_type
def send(self):
libev.ev_async_send(self.loop._ptr, self._watcher)
@property
def pending(self):
return True if libev.ev_async_pending(self._watcher) else False
class child(watcher):
_watcher_start = libev.ev_child_start
_watcher_stop = libev.ev_child_stop
_watcher_init = libev.ev_child_init
_watcher_type = 'ev_child'
_watcher_ffi_type = "struct %s *" % _watcher_type
_watcher_ffi_cb = "void(*)(struct ev_loop *, struct %s *, int)" % _watcher_type
def __init__(self, loop, pid, trace=0, ref=True):
if not loop.default:
raise TypeError('child watchers are only available on the default loop')
loop.install_sigchld()
watcher.__init__(self, loop, ref=ref, args=(pid, trace))
def _format(self):
return ' pid=%r rstatus=%r' % (self.pid, self.rstatus)
@property
def pid(self):
return self._watcher.pid
@property
def rpid(self, ):
return self._watcher.rpid
@rpid.setter
def rpid(self, value):
self._watcher.rpid = value
@property
def rstatus(self):
return self._watcher.rstatus
@rstatus.setter
def rstatus(self, value):
self._watcher.rstatus = value
def _syserr_cb(msg):
try:
msg = ffi.string(msg)
__SYSERR_CALLBACK(msg, ffi.errno)
except:
set_syserr_cb(None)
raise # let cffi print the traceback
_syserr_cb._cb = ffi.callback("void(*)(char *msg)", _syserr_cb)
def set_syserr_cb(callback):
global __SYSERR_CALLBACK
if callback is None:
libev.ev_set_syserr_cb(ffi.NULL)
__SYSERR_CALLBACK = None
elif callable(callback):
libev.ev_set_syserr_cb(_syserr_cb._cb)
__SYSERR_CALLBACK = callback
else:
raise TypeError('Expected callable or None, got %r' % (callback, ))
__SYSERR_CALLBACK = None
LIBEV_EMBED = True
......@@ -150,10 +150,11 @@ class AsyncResult(object):
>>> import gevent
>>> result = AsyncResult()
>>> gevent.spawn(lambda : 1/0).link(result)
>>> result.get()
Traceback (most recent call last):
...
ZeroDivisionError: integer division or modulo by zero
>>> try:
... result.get()
... except ZeroDivisionError:
... print 'ZeroDivisionError'
ZeroDivisionError
"""
def __init__(self):
self._links = deque()
......
......@@ -8,6 +8,9 @@ from gevent.os import _read, _write, ignored_errors
from gevent.lock import Semaphore, DummySemaphore
PYPY = hasattr(sys, 'pypy_version_info')
try:
from fcntl import fcntl
except ImportError:
......@@ -64,6 +67,7 @@ else:
io = self.hub.loop.io
self._read_event = io(fileno, 1)
self._write_event = io(fileno, 2)
self._refcount = 1
def __repr__(self):
if self._fileno is None:
......@@ -86,7 +90,18 @@ else:
self._fileno = None
return x
def _reuse(self):
self._refcount += 1
def _drop(self):
self._refcount -= 1
if self._refcount <= 0:
self._realclose()
def close(self):
self._drop()
def _realclose(self):
self.hub.cancel_wait(self._read_event, cancel_wait_ex)
self.hub.cancel_wait(self._write_event, cancel_wait_ex)
fileno = self._fileno
......@@ -161,6 +176,8 @@ else:
self._fobj = fobj
self._closed = False
_fileobject.__init__(self, sock, mode=mode, bufsize=bufsize, close=close)
if PYPY:
sock._drop()
def __repr__(self):
if self._sock is None:
......@@ -184,6 +201,8 @@ else:
finally:
if self._fobj is not None or not self._close:
sock.detach()
else:
sock._drop()
self._sock = None
self._fobj = None
......
# Copyright (c) 2009-2012 Denis Bilenko. See LICENSE for details.
import sys
from gevent.hub import greenlet, getcurrent, get_hub, GreenletExit, Waiter, PY3, iwait, wait
from gevent.hub import greenlet, getcurrent, get_hub, GreenletExit, Waiter, PY3, iwait, wait, PYPY
from gevent.timeout import Timeout
from collections import deque
......@@ -11,6 +11,11 @@ __all__ = ['Greenlet',
'killall']
if PYPY:
import _continuation
_continulet = _continuation.continulet
class SpawnedLink(object):
"""A wrapper around link that calls it in another greenlet.
......@@ -96,6 +101,14 @@ class Greenlet(greenlet):
def __nonzero__(self):
return self._start_event is not None and self._exception is _NONE
if PYPY:
# oops - pypy's .dead relies on __nonzero__ which we overriden above
@property
def dead(self):
return self._greenlet__started and not (self._greenlet__main or _continulet.is_pending(self))
@property
def started(self):
# DEPRECATED
......
......@@ -28,6 +28,7 @@ __all__ = ['getcurrent',
PY3 = sys.version_info[0] >= 3
PYPY = hasattr(sys, 'pypy_version_info')
if PY3:
......
......@@ -128,7 +128,7 @@ affects what we see:
"""
from weakref import WeakKeyDictionary
from copy import copy
from gevent.hub import getcurrent
from gevent.hub import getcurrent, PYPY
from gevent.lock import RLock
__all__ = ["local"]
......@@ -144,8 +144,9 @@ class _localbase(object):
dicts = WeakKeyDictionary()
object.__setattr__(self, '_local__dicts', dicts)
if (args or kw) and (cls.__init__ is object.__init__):
raise TypeError("Initialization arguments are not supported")
if args or kw:
if (PYPY and cls.__init__ == object.__init__) or (not PYPY and cls.__init__ is object.__init__):
raise TypeError("Initialization arguments are not supported")
# We need to create the greenlet dict in anticipation of
# __init__ being called, to make sure we don't call it again ourselves.
......
......@@ -4,6 +4,7 @@ import sys
import _socket
from gevent.baseserver import BaseServer
from gevent.socket import EWOULDBLOCK, socket
from gevent.hub import PYPY
__all__ = ['StreamServer', 'DatagramServer']
......@@ -95,7 +96,13 @@ class StreamServer(BaseServer):
if err.args[0] == EWOULDBLOCK:
return
raise
return socket(_sock=client_socket), address
sockobj = socket(_sock=client_socket)
if PYPY:
client_socket._drop()
return sockobj, address
def do_close(self, socket, *args):
socket.close()
def wrap_socket_and_handle(self, client_socket, address):
# used in case of ssl sockets
......
......@@ -32,3 +32,6 @@ class _DummyThread(_DummyThread_):
rawlink = getattr(g, 'rawlink', None)
if rawlink is not None:
rawlink(_cleanup)
def _Thread__stop(self):
pass
......@@ -32,7 +32,9 @@ from gevent.hub import _get_hub
from functools import wraps
import contextlib
import gc
import six
PYPY = hasattr(sys, 'pypy_version_info')
VERBOSE = sys.argv.count('-v') > 1
if '--debug-greentest' in sys.argv:
......@@ -42,6 +44,7 @@ else:
DEBUG = False
gettotalrefcount = getattr(sys, 'gettotalrefcount', None)
OPTIONAL_MODULES = ['resolver_ares']
def wrap_switch_count_check(method):
......@@ -369,7 +372,9 @@ class ExpectedException(Exception):
"""An exception whose traceback should be ignored"""
def walk_modules(basedir=None, modpath=None, include_so=False):
def walk_modules(basedir=None, modpath=None, include_so=False, recursive=False):
if PYPY:
include_so = False
if basedir is None:
basedir = os.path.dirname(gevent.__file__)
if modpath is None:
......@@ -380,6 +385,8 @@ def walk_modules(basedir=None, modpath=None, include_so=False):
for fn in sorted(os.listdir(basedir)):
path = os.path.join(basedir, fn)
if os.path.isdir(path):
if not recursive:
continue
pkg_init = os.path.join(path, '__init__.py')
if os.path.exists(pkg_init):
yield pkg_init, modpath + fn
......@@ -390,8 +397,14 @@ def walk_modules(basedir=None, modpath=None, include_so=False):
x = fn[:-3]
if x.endswith('_d'):
x = x[:-2]
if x not in ['__init__', 'core', 'ares', '_util', '_semaphore']:
yield path, modpath + x
if x in ['__init__', 'core', 'ares', '_util', '_semaphore', 'corecffi']:
continue
if x in OPTIONAL_MODULES:
try:
six.exec_("import %s" % x, {})
except ImportError:
continue
yield path, modpath + x
elif include_so and fn.endswith('.so'):
if fn.endswith('_d.so'):
yield path, modpath + fn[:-5]
......@@ -433,3 +446,14 @@ def get_number_open_files():
if os.path.exists('/proc/'):
fd_directory = '/proc/%d/fd' % os.getpid()
return len(os.listdir(fd_directory))
if PYPY:
def getrefcount(*args):
pass
else:
def getrefcount(*args):
return sys.getrefcount(*args)
......@@ -8,6 +8,8 @@ import atexit
TIMEOUT = 60
directory = '%s.%s' % sys.version_info[:2]
if hasattr(sys, 'pypy_version_info'):
directory += 'pypy'
version = '%s.%s.%s' % sys.version_info[:3]
......
......@@ -23,6 +23,7 @@ import sys
import greentest
import weakref
import time
import gc
from gevent import sleep, Timeout
DELAY = 0.04
......@@ -104,6 +105,7 @@ class Test(greentest.TestCase):
with Timeout(DELAY * 2, err):
sleep(DELAY)
del err
gc.collect()
assert not err_ref(), repr(err_ref())
def test_nested_timeout(self):
......
......@@ -30,21 +30,28 @@ class Test(greentest.TestCase):
pass
# test that args can be changed later
io.args = (1, 2, 3)
# test that only tuple and None are accepted by 'args' attribute
try:
io.args = 5
raise AssertionError('"io.args = 5" must raise TypeError')
except TypeError:
pass
self.assertEqual(io.args, (1, 2, 3))
try:
io.args = [4, 5]
raise AssertionError('"io.args = [4, 5]" must raise TypeError')
except TypeError:
pass
if greentest.PYPY:
pass # on PYPY .args is just a normal property
else:
# test that only tuple and None are accepted by 'args' attribute
try:
io.args = 5
raise AssertionError('"io.args = 5" must raise TypeError')
except TypeError:
pass
self.assertEqual(io.args, (1, 2, 3))
try:
io.args = [4, 5]
raise AssertionError('"io.args = [4, 5]" must raise TypeError')
except TypeError:
pass
self.assertEqual(io.args, (1, 2, 3))
# None also works, means empty tuple
io.args = None
if greentest.PYPY:
io.args = ()
else:
# None also works, means empty tuple
# XXX why?
io.args = None
start = core.time()
loop.run()
took = core.time() - start
......
import os
import sys
import greentest
import gevent
from gevent.fileobject import FileObject, FileObjectThread
PYPY = hasattr(sys, 'pypy_version_info')
class Test(greentest.TestCase):
def _test_del(self, **kwargs):
......@@ -11,7 +15,10 @@ class Test(greentest.TestCase):
s = FileObject(w, 'wb')
s.write('x')
s.flush()
del s
if PYPY:
s.close()
else:
del s
try:
os.close(w)
except OSError:
......@@ -33,7 +40,10 @@ class Test(greentest.TestCase):
s = FileObject(w, 'wb', close=False)
s.write('x')
s.flush()
del s
if PYPY:
s.close()
else:
del s
os.close(w)
self.assertEqual(FileObject(r).read(), 'x')
......@@ -67,7 +77,10 @@ else:
r, w = os.pipe()
s = SocketAdapter(w)
s.sendall('x')
del s
if PYPY:
s.close()
else:
del s
try:
os.close(w)
except OSError:
......
......@@ -20,6 +20,10 @@
from greentest import TestCase, main, tcp_listener
import gevent
from gevent import socket
import sys
PYPY = hasattr(sys, 'pypy_version_info')
class TestGreenIo(TestCase):
......@@ -76,6 +80,8 @@ class TestGreenIo(TestCase):
server_greenlet.kill()
def test_del_closes_socket(self):
if PYPY:
return
timer = gevent.Timeout.start_new(0.5)
def accept_once(listener):
......
import os
from gevent import monkey; monkey.patch_all()
import re
import socket
import ssl
import threading
import unittest
dirname = os.path.dirname(os.path.abspath(__file__))
certfile = os.path.join(dirname, '2.7/keycert.pem')
pid = os.getpid()
tmpname = '/tmp/test__makefile_ref.lsof.%s' % pid
lsof_command = 'lsof -p %s > %s' % (pid, tmpname)
def get_open_files():
if os.system(lsof_command):
raise OSError('lsof failed')
with open(tmpname) as fobj:
data = fobj.read().strip()
results = {}
for line in data.split('\n'):
line = line.strip()
if not line:
continue
split = re.split(r'\s+', line)
command, pid, user, fd = split[:4]
if fd[:-1].isdigit() and not fd[-1].isdigit():
fd = int(fd[:-1])
if fd in results:
params = (fd, line, split, results.get(fd), data)
raise AssertionError('error when parsing lsof output: duplicate fd=%r\nline=%r\nsplit=%r\nprevious=%r\ndata:\n%s' % params)
results[fd] = line
if not results:
raise AssertionError('failed to parse lsof:\n%s' % (data, ))
results['data'] = data
return results
class Test(unittest.TestCase):
def assert_raises_EBADF(self, func):
try:
result = func()
except socket.error as ex:
if ex.errno == 9:
return
raise
raise AssertionError('NOT RAISED EBADF: %r() returned %r' % (func, result))
def assert_fd_open(self, fileno):
assert isinstance(fileno, int)
open_files = get_open_files()
if fileno not in open_files:
raise AssertionError('%r is not open:\n%s' % (fileno, open_files['data']))
def assert_fd_closed(self, fileno):
assert isinstance(fileno, int), repr(fileno)
assert fileno > 0, fileno
open_files = get_open_files()
if fileno in open_files:
raise AssertionError('%r is not closed:\n%s' % (fileno, open_files['data']))
def assert_open(self, sock, *rest):
if isinstance(sock, int):
self.assert_fd_open(sock)
else:
fileno = sock.fileno()
assert isinstance(fileno, int), fileno
sockname = sock.getsockname()
assert isinstance(sockname, tuple), sockname
self.assert_fd_open(fileno)
if rest:
self.assert_open(rest[0], *rest[1:])
def assert_closed(self, sock, *rest):
if isinstance(sock, int):
self.assert_fd_closed(sock)
else:
self.assert_raises_EBADF(sock.fileno)
self.assert_raises_EBADF(sock.getsockname)
self.assert_raises_EBADF(sock.accept)
if rest:
self.assert_closed(rest[0], *rest[1:])
class TestSocket(Test):
def test_simple_close(self):
s = socket.socket()
fileno = s.fileno()
s.bind(('127.0.0.1', 0))
self.assert_open(s, fileno)
s.close()
self.assert_closed(s, fileno)
def test_makefile1(self):
s = socket.socket()
fileno = s.fileno()
s.bind(('127.0.0.1', 0))
self.assert_open(s, fileno)
f = s.makefile()
self.assert_open(s, fileno)
s.close()
# this closes socket wrapper object but not the file descriptor
self.assert_closed(s)
self.assert_open(fileno)
f.close()
self.assert_closed(s)
self.assert_closed(fileno)
def test_makefile2(self):
s = socket.socket()
fileno = s.fileno()
s.bind(('127.0.0.1', 0))
self.assert_open(s)
self.assert_open(s, fileno)
f = s.makefile()
self.assert_open(s)
self.assert_open(s, fileno)
f.close()
# closing fileobject does not close the socket
self.assert_open(s, fileno)
s.close()
self.assert_closed(s, fileno)
def test_server_simple(self):
listener = socket.socket()
listener.bind(('127.0.0.1', 0))
port = listener.getsockname()[1]
listener.listen(1)
connector = socket.socket()
def connect():
connector.connect(('127.0.0.1', port))
t = threading.Thread(target=connect)
t.start()
try:
client_socket, _addr = listener.accept()
fileno = client_socket.fileno()
self.assert_open(client_socket, fileno)
client_socket.close()
self.assert_closed(client_socket)
finally:
t.join()
listener.close()
def test_server_makefile1(self):
listener = socket.socket()
listener.bind(('127.0.0.1', 0))
port = listener.getsockname()[1]
listener.listen(1)
connector = socket.socket()
def connect():
connector.connect(('127.0.0.1', port))
t = threading.Thread(target=connect)
t.start()
try:
client_socket, _addr = listener.accept()
fileno = client_socket.fileno()
f = client_socket.makefile()
self.assert_open(client_socket, fileno)
client_socket.close()
self.assert_closed(client_socket)
self.assert_open(fileno)
f.close()
self.assert_closed(client_socket, fileno)
finally:
t.join()
listener.close()
def test_server_makefile2(self):
listener = socket.socket()
listener.bind(('127.0.0.1', 0))
port = listener.getsockname()[1]
listener.listen(1)
connector = socket.socket()
def connect():
connector.connect(('127.0.0.1', port))
t = threading.Thread(target=connect)
t.start()
try:
client_socket, _addr = listener.accept()
fileno = client_socket.fileno()
f = client_socket.makefile()
self.assert_open(client_socket, fileno)
# closing fileobject does not close the socket
f.close()
self.assert_open(client_socket, fileno)
client_socket.close()
self.assert_closed(client_socket, fileno)
finally:
t.join()
listener.close()
class TestSSL(Test):
def test_simple_close(self):
s = socket.socket()
fileno = s.fileno()
s.bind(('127.0.0.1', 0))
self.assert_open(s, fileno)
s = ssl.wrap_socket(s)
fileno = s.fileno()
self.assert_open(s, fileno)
s.close()
self.assert_closed(s, fileno)
def test_makefile1(self):
s = socket.socket()
fileno = s.fileno()
s.bind(('127.0.0.1', 0))
self.assert_open(s, fileno)
s = ssl.wrap_socket(s)
fileno = s.fileno()
self.assert_open(s, fileno)
f = s.makefile()
self.assert_open(s, fileno)
s.close()
self.assert_open(s, fileno)
f.close()
self.assert_closed(s, fileno)
def test_makefile2(self):
s = socket.socket()
fileno = s.fileno()
s.bind(('127.0.0.1', 0))
self.assert_open(s, fileno)
s = ssl.wrap_socket(s)
fileno = s.fileno()
self.assert_open(s, fileno)
f = s.makefile()
self.assert_open(s, fileno)
f.close()
# closing fileobject does not close the socket
self.assert_open(s, fileno)
s.close()
self.assert_closed(s, fileno)
def test_server_simple(self):
listener = socket.socket()
listener.bind(('127.0.0.1', 0))
port = listener.getsockname()[1]
listener.listen(1)
connector = socket.socket()
def connect():
connector.connect(('127.0.0.1', port))
ssl.wrap_socket(connector)
t = threading.Thread(target=connect)
t.start()
try:
client_socket, _addr = listener.accept()
client_socket = ssl.wrap_socket(client_socket, keyfile=certfile, certfile=certfile, server_side=True)
fileno = client_socket.fileno()
self.assert_open(client_socket, fileno)
client_socket.close()
self.assert_closed(client_socket, fileno)
finally:
t.join()
listener.close()
def test_server_makefile1(self):
listener = socket.socket()
listener.bind(('127.0.0.1', 0))
port = listener.getsockname()[1]
listener.listen(1)
connector = socket.socket()
def connect():
connector.connect(('127.0.0.1', port))
ssl.wrap_socket(connector)
t = threading.Thread(target=connect)
t.start()
try:
client_socket, _addr = listener.accept()
client_socket = ssl.wrap_socket(client_socket, keyfile=certfile, certfile=certfile, server_side=True)
fileno = client_socket.fileno()
self.assert_open(client_socket, fileno)
f = client_socket.makefile()
self.assert_open(client_socket, fileno)
client_socket.close()
self.assert_open(client_socket, fileno)
f.close()
self.assert_closed(client_socket, fileno)
finally:
t.join()
def test_server_makefile2(self):
listener = socket.socket()
listener.bind(('127.0.0.1', 0))
port = listener.getsockname()[1]
listener.listen(1)
connector = socket.socket()
def connect():
connector.connect(('127.0.0.1', port))
ssl.wrap_socket(connector)
t = threading.Thread(target=connect)
t.start()
try:
client_socket, _addr = listener.accept()
client_socket = ssl.wrap_socket(client_socket, keyfile=certfile, certfile=certfile, server_side=True)
fileno = client_socket.fileno()
self.assert_open(client_socket, fileno)
f = client_socket.makefile()
self.assert_open(client_socket, fileno)
# Closing fileobject does not close SSLObject
f.close()
self.assert_open(client_socket, fileno)
client_socket.close()
self.assert_closed(client_socket, fileno)
finally:
t.join()
listener.close()
def test_serverssl_makefile1(self):
listener = socket.socket()
fileno = listener.fileno()
listener.bind(('127.0.0.1', 0))
port = listener.getsockname()[1]
listener.listen(1)
listener = ssl.wrap_socket(listener, keyfile=certfile, certfile=certfile)
connector = socket.socket()
def connect():
connector.connect(('127.0.0.1', port))
ssl.wrap_socket(connector)
t = threading.Thread(target=connect)
t.start()
try:
client_socket, _addr = listener.accept()
fileno = client_socket.fileno()
self.assert_open(client_socket, fileno)
f = client_socket.makefile()
self.assert_open(client_socket, fileno)
client_socket.close()
self.assert_open(client_socket, fileno)
f.close()
self.assert_closed(client_socket, fileno)
finally:
t.join()
listener.close()
def test_serverssl_makefile2(self):
listener = socket.socket()
listener.bind(('127.0.0.1', 0))
port = listener.getsockname()[1]
listener.listen(1)
listener = ssl.wrap_socket(listener, keyfile=certfile, certfile=certfile)
connector = socket.socket()
def connect():
connector.connect(('127.0.0.1', port))
s = ssl.wrap_socket(connector)
s.sendall('test_serverssl_makefile2')
s.close()
connector.close()
t = threading.Thread(target=connect)
t.start()
try:
client_socket, _addr = listener.accept()
fileno = client_socket.fileno()
self.assert_open(client_socket, fileno)
f = client_socket.makefile()
self.assert_open(client_socket, fileno)
self.assertEqual(f.read(), 'test_serverssl_makefile2')
self.assertEqual(f.read(), '')
f.close()
self.assert_open(client_socket, fileno)
client_socket.close()
self.assert_closed(client_socket, fileno)
finally:
t.join()
listener.close()
if __name__ == '__main__':
unittest.main()
......@@ -77,6 +77,9 @@ class TestCoroutinePool(unittest.TestCase):
evt.wait()
def test_stderr_raising(self):
if greentest.PYPY:
# Does not work on PyPy
return
# testing that really egregious errors in the error handling code
# (that prints tracebacks to stderr) don't cause the pool to lose
# any members
......
......@@ -11,24 +11,27 @@ class SimpleStreamServer(StreamServer):
def handle(self, client_socket, address):
fd = client_socket.makefile()
request_line = fd.readline()
if not request_line:
return
try:
method, path, rest = request_line.split(' ', 3)
except Exception:
print('Failed to parse request line: %r' % (request_line, ))
raise
if path == '/ping':
client_socket.sendall('HTTP/1.0 200 OK\r\n\r\nPONG')
elif path in ['/long', '/short']:
client_socket.sendall('hello')
while True:
data = client_socket.recv(1)
if not data:
break
else:
client_socket.sendall('HTTP/1.0 404 WTF?\r\n\r\n')
request_line = fd.readline()
if not request_line:
return
try:
method, path, rest = request_line.split(' ', 3)
except Exception:
print('Failed to parse request line: %r' % (request_line, ))
raise
if path == '/ping':
client_socket.sendall('HTTP/1.0 200 OK\r\n\r\nPONG')
elif path in ['/long', '/short']:
client_socket.sendall('hello')
while True:
data = client_socket.recv(1)
if not data:
break
else:
client_socket.sendall('HTTP/1.0 404 WTF?\r\n\r\n')
finally:
fd.close()
class Settings:
......@@ -81,6 +84,7 @@ class TestCase(greentest.TestCase):
sock.connect((self.server.server_host, self.server.server_port))
fobj = sock.makefile(bufsize=bufsize)
fobj._sock.settimeout(timeout)
sock.close()
return fobj
def send_request(self, url='/', timeout=0.1, bufsize=1):
......
......@@ -150,6 +150,7 @@ class TestTCP(greentest.TestCase):
fd = conn.makefile(mode='w')
fd.write('hello\n')
fd.close()
conn.close() # for pypy
acceptor = Thread(target=accept_once)
client = self.create_connection()
......
from gevent import monkey; monkey.patch_all()
import socket
import unittest
class Test(unittest.TestCase):
def test(self):
msg = 'hello world'
x, y = socket.socketpair()
x.sendall(msg)
x.close()
read = y.makefile().read()
self.assertEqual(msg, read)
def test_fromfd(self):
msg = 'hello world'
x, y = socket.socketpair()
xx = socket.fromfd(x.fileno(), x.family, socket.SOCK_STREAM)
x.close()
yy = socket.fromfd(y.fileno(), y.family, socket.SOCK_STREAM)
y.close()
xx.sendall(msg)
xx.close()
read = yy.makefile().read()
self.assertEqual(msg, read)
if __name__ == '__main__':
unittest.main()
......@@ -6,6 +6,10 @@ import greentest
import gevent
from gevent import subprocess
import time
import gc
PYPY = hasattr(sys, 'pypy_version_info')
if subprocess.mswindows:
......@@ -19,6 +23,10 @@ python_universal_newlines = hasattr(sys.stdout, 'newlines')
class Test(greentest.TestCase):
def setUp(self):
gc.collect()
gc.collect()
def test_exit(self):
popen = subprocess.Popen([sys.executable, '-c', 'import sys; sys.exit(10)'])
self.assertEqual(popen.wait(), 10)
......@@ -42,6 +50,9 @@ class Test(greentest.TestCase):
stdout=subprocess.PIPE)
p.wait()
del p
if PYPY:
gc.collect()
gc.collect()
num_after = greentest.get_number_open_files()
self.assertEqual(num_before, num_after)
......
......@@ -6,6 +6,10 @@ import greentest
from gevent.threadpool import ThreadPool
import gevent
import six
import gc
PYPY = hasattr(sys, 'pypy_version_info')
class TestCase(greentest.TestCase):
......@@ -133,6 +137,22 @@ class TestPool(TestCase):
self.assertEqual(six.advance_iterator(it), i * i)
self.assertRaises(StopIteration, lambda: six.advance_iterator(it))
def test_imap_gc(self):
it = self.pool.imap(sqr, range(10))
for i in range(10):
self.assertEqual(six.advance_iterator(it), i * i)
gc.collect()
self.assertRaises(StopIteration, lambda: six.advance_iterator(it))
def test_imap_unordered_gc(self):
it = self.pool.imap_unordered(sqr, range(10))
result = []
for i in range(10):
result.append(six.advance_iterator(it))
gc.collect()
self.assertRaises(StopIteration, lambda: six.advance_iterator(it))
self.assertEqual(sorted(result), [x * x for x in range(10)])
def test_imap_random(self):
it = self.pool.imap(sqr_random_sleep, range(10))
self.assertEqual(list(it), list(map(sqr, range(10))))
......@@ -327,8 +347,11 @@ class TestRef(TestCase):
refs.append(weakref.ref(func))
del func, result
if PYPY:
gc.collect()
gc.collect()
for index, r in enumerate(refs):
assert r() is None, (index, r(), sys.getrefcount(r()), refs)
assert r() is None, (index, r(), greentest.getrefcount(r()), refs)
assert len(refs) == 4, refs
......
from __future__ import print_function
import sys
import gevent
from gevent.resolver_ares import Resolver
try:
from gevent.resolver_ares import Resolver
except ImportError as ex:
print(ex)
sys.exit(0)
from gevent import socket
print(gevent.__file__)
......
......@@ -374,7 +374,7 @@ class ThreadTests(unittest.TestCase):
finally:
sys.setcheckinterval(old_interval)
if sys.version_info[:2] > (2, 5):
if sys.version_info[:2] > (2, 5) and not hasattr(sys, 'pypy_version_info'):
def test_no_refcycle_through_target(self):
class RunSelfFunction(object):
def __init__(self, should_raise):
......
......@@ -44,8 +44,42 @@ if CPYTHON_DBG:
if PYPY:
# stat watchers are not implemented on pypy
FAILING_TESTS += ['test__core_stat.py']
FAILING_TESTS += [
# Not implemented:
# stat watchers are not implemented on pypy
'test__core_stat.py',
# ares not supported on PyPy yet
'test__ares_host_result.py',
# ---
# BUGS:
# https://bugs.pypy.org/issue1743
'test__real_greenlet.py',
'test__exc_info.py',
# in CPython we compile _semaphore.py with Cython to make its operation atomic
# how to do atomic operations on PyPy?
'test__threading_vs_settrace.py',
# check_sendall_interrupted and testInterruptedTimeout fail due to
# https://bitbucket.org/cffi/cffi/issue/152/handling-errors-from-signal-handlers-in
'test_socket.py',
# No idea!
'test_threading_2.py',
'test_threading.py',
'test__example_portforwarder.py',
'test__pywsgi.py',
'test__backdoor.py',
'test__refcount.py',
'test__server.py',
'test_subprocess.py', # test_executable_without_cwd
]
if __name__ == '__main__':
......
......@@ -9,9 +9,14 @@ import traceback
from os.path import join, abspath, basename, dirname
from glob import glob
PYPY = hasattr(sys, 'pypy_version_info')
try:
from setuptools import Extension, setup
except ImportError:
if PYPY:
# need setuptools for include_package_data to work
raise
from distutils.core import Extension, setup
from distutils.command.build_ext import build_ext
from distutils.command.sdist import sdist as _sdist
......@@ -19,9 +24,6 @@ from distutils.errors import CCompilerError, DistutilsExecError, DistutilsPlatfo
ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError, IOError)
# XXX make all env variables that setup.py parses start with GEVENTSETUP_
__version__ = re.search("__version__\s*=\s*'(.*)'", open('gevent/__init__.py').read(), re.M).group(1)
assert __version__
......@@ -52,8 +54,8 @@ CARES_EMBED = get_config_value('CARES_EMBED', 'EMBED', 'c-ares')
define_macros = []
libraries = []
libev_configure_command = ["/bin/sh", abspath('libev/configure'), '> configure-output.txt']
ares_configure_command = ["/bin/sh", abspath('c-ares/configure'), 'CONFIG_COMMANDS= CONFIG_FILES= > configure-output.txt']
libev_configure_command = ' '.join(["/bin/sh", abspath('libev/configure'), '> configure-output.txt'])
ares_configure_command = ' '.join(["/bin/sh", abspath('c-ares/configure'), 'CONFIG_COMMANDS= CONFIG_FILES= > configure-output.txt'])
if sys.platform == 'win32':
......@@ -70,7 +72,7 @@ def expand(*lst):
CORE = Extension(name='gevent.core',
sources=['gevent/gevent.core.c'],
sources=['gevent/gevent.corecext.c'],
include_dirs=['libev'] if LIBEV_EMBED else [],
libraries=libraries,
define_macros=define_macros,
......@@ -86,14 +88,6 @@ ARES = Extension(name='gevent.ares',
ARES.optional = True
ext_modules = [CORE,
ARES,
Extension(name="gevent._semaphore",
sources=["gevent/gevent._semaphore.c"]),
Extension(name="gevent._util",
sources=["gevent/gevent._util.c"])]
def make_universal_header(filename, *defines):
defines = [('#define %s ' % define, define) for define in defines]
lines = open(filename, 'r').read().split('\n')
......@@ -114,11 +108,15 @@ def make_universal_header(filename, *defines):
def _system(cmd):
cmd = ' '.join(cmd)
sys.stdout.write('Running %r in %s\n' % (cmd, os.getcwd()))
return os.system(cmd)
def system(cmd):
if _system(cmd):
sys.exit(1)
def configure_libev(bext, ext):
if sys.platform == "win32":
CORE.define_macros.append(('EV_STANDALONE', '1'))
......@@ -170,7 +168,6 @@ if LIBEV_EMBED:
CORE.define_macros += [('LIBEV_EMBED', '1'),
('EV_COMMON', ''), # we don't use void* data
# libev watchers that we don't use currently:
('EV_CHECK_ENABLE', '0'),
('EV_CLEANUP_ENABLE', '0'),
('EV_EMBED_ENABLE', '0'),
("EV_PERIODIC_ENABLE", '0')]
......@@ -204,8 +201,7 @@ def make(done=[]):
if os.path.exists('Makefile'):
if "PYTHON" not in os.environ:
os.environ["PYTHON"] = sys.executable
if os.system('make'):
sys.exit(1)
system('make')
done.append(1)
......@@ -227,7 +223,6 @@ class sdist(_sdist):
class my_build_ext(build_ext):
def gevent_prepare(self, ext):
make()
configure = getattr(ext, 'configure', None)
if configure:
configure(self, ext)
......@@ -241,6 +236,11 @@ class my_build_ext(build_ext):
raise BuildFailed
else:
raise
if not PYPY:
self.gevent_symlink(ext)
return result
def gevent_symlink(self, ext):
# hack: create a symlink from build/../core.so to gevent/core.so
# to prevent "ImportError: cannot import name core" failures
try:
......@@ -255,7 +255,6 @@ class my_build_ext(build_ext):
link(path_to_build_core_so, path_to_core_so)
except Exception:
traceback.print_exc()
return result
def link(source, dest):
......@@ -286,7 +285,32 @@ def read(name, *args):
return ''
def run_setup(ext_modules):
if PYPY:
sys.path.insert(0, '.')
# XXX ugly - need to find a better way
system('cp -r libev gevent/libev')
system('touch gevent/libev/__init__.py')
system('cd gevent/libev && ./configure > configure_output.txt')
from gevent import corecffi
ext_modules = [corecffi.ffi.verifier.get_extension()]
install_requires = []
include_package_data = True
run_make = False
else:
ext_modules = [CORE,
ARES,
Extension(name="gevent._semaphore",
sources=["gevent/gevent._semaphore.c"]),
Extension(name="gevent._util",
sources=["gevent/gevent._util.c"])]
install_requires = ['greenlet']
include_package_data = False
run_make = True
def run_setup(ext_modules, run_make):
if run_make:
make()
setup(
name='gevent',
version=__version__,
......@@ -296,9 +320,11 @@ def run_setup(ext_modules):
author_email='denis.bilenko@gmail.com',
url='http://www.gevent.org/',
packages=['gevent'],
include_package_data=include_package_data,
ext_modules=ext_modules,
cmdclass=dict(build_ext=my_build_ext, sdist=sdist),
install_requires=['greenlet'],
install_requires=install_requires,
zip_safe=False,
classifiers=[
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 2.6",
......@@ -314,11 +340,11 @@ def run_setup(ext_modules):
if __name__ == '__main__':
try:
run_setup(ext_modules)
run_setup(ext_modules, run_make=run_make)
except BuildFailed:
if ARES not in ext_modules:
raise
ext_modules.remove(ARES)
run_setup(ext_modules)
run_setup(ext_modules, run_make=run_make)
if ARES not in ext_modules:
sys.stderr.write('\nWARNING: The gevent.ares extension has been disabled.\n')
......@@ -24,6 +24,8 @@ gevent/wsgi.py:1: 'from gevent.pywsgi import *' used; unable to detect undefined
examples/webchat/urls.py:1: 'from django.conf.urls.defaults import *' used; unable to detect undefined names
greentest/test__queue.py:\d+: undefined name 'GenericGetTestCase'
greentest/test__server_pywsgi.py:
gevent/core.py:\d+: 'from gevent.corecffi import *' used; unable to detect undefined names
gevent/core.py:\d+: 'from gevent.corecext import *' used; unable to detect undefined names
'''
IGNORED = IGNORED.strip().replace(' *', ' \\*').split('\n')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment