diff --git a/.travis.yml b/.travis.yml index 3aa6228b..dea98552 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,15 +7,17 @@ env: - TOX_ENV=py27 CASS_VER=20 - TOX_ENV=py27 CASS_VER=21 - TOX_ENV=py27 CASS_VER=21 CYTHON_DEP=cython - - TOX_ENV=pypy CASS_VER=21 - TOX_ENV=py33 CASS_VER=21 - TOX_ENV=py33 CASS_VER=21 CYTHON_DEP=cython - TOX_ENV=py34 CASS_VER=21 - TOX_ENV=py34 CASS_VER=21 CYTHON_DEP=cython + - TOX_ENV=pypy CASS_VER=21 + - TOX_ENV=pypy3 CASS_VER=21 before_install: - sudo apt-get update -y - sudo apt-get install -y build-essential python-dev + - sudo apt-get install -y pypy-dev - sudo apt-get install -y libev4 libev-dev - sudo echo "deb http://www.apache.org/dist/cassandra/debian ${CASS_VER}x main" | sudo tee -a /etc/apt/sources.list - sudo echo "deb-src http://www.apache.org/dist/cassandra/debian ${CASS_VER}x main" | sudo tee -a /etc/apt/sources.list diff --git a/cassandra/murmur3.c b/cassandra/murmur3.c index 657c01f6..dc98b491 100644 --- a/cassandra/murmur3.c +++ b/cassandra/murmur3.c @@ -20,6 +20,13 @@ typedef int Py_ssize_t; #define PY_SSIZE_T_MIN INT_MIN #endif +#ifdef PYPY_VERSION +#define COMPILING_IN_PYPY 1 +#define COMPILING_IN_CPYTHON 0 +#else +#define COMPILING_IN_PYPY 0 +#define COMPILING_IN_CPYTHON 1 +#endif //----------------------------------------------------------------------------- // Platform-specific functions and macros @@ -179,7 +186,8 @@ struct module_state { PyObject *error; }; -#if PY_MAJOR_VERSION >= 3 +// pypy3 doesn't have GetState yet. +#if COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3 #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) #else #define GETSTATE(m) (&_state) diff --git a/setup.py b/setup.py index 5d4b6cad..37899c2e 100644 --- a/setup.py +++ b/setup.py @@ -235,6 +235,7 @@ def run_setup(extensions): **kw) is_windows = os.name == 'nt' + if is_windows: build_extensions.error_message = """ =============================================================================== @@ -267,7 +268,7 @@ if "--no-cython" not in sys.argv: [Extension('cassandra.%s' % m, ['cassandra/%s.py' % m], extra_compile_args=compile_args) for m in cython_candidates], exclude_failures=True)) except ImportError: - print("Cython is not installed. Not compiling core driver files as extensions (optional).") + sys.stderr.write("Cython is not installed. Not compiling core driver files as extensions (optional).") if "--no-extensions" in sys.argv: extensions = [] @@ -289,15 +290,25 @@ The optional C extensions are not supported on big-endian systems. =============================================================================== """ +pypy_unsupported_msg = \ +""" +================================================================================= +Some optional C extensions are not supported in PyPy. Only murmur3 will be built. +================================================================================= +""" + if extensions: - if (sys.platform.startswith("java") - or sys.platform == "cli" - or "PyPy" in sys.version): + if "PyPy" in sys.version: + sys.stderr.write(pypy_unsupported_msg) + extensions = [ext for ext in extensions if ext is murmur3_ext] + + if (sys.platform.startswith("java") or sys.platform == "cli"): sys.stderr.write(platform_unsupported_msg) - extensions = () + extensions = [] elif sys.byteorder == "big": sys.stderr.write(arch_unsupported_msg) - extensions = () + extensions = [] + while True: # try to build as many of the extensions as we can diff --git a/tests/unit/io/test_twistedreactor.py b/tests/unit/io/test_twistedreactor.py index 148a5e15..5c6bb2d0 100644 --- a/tests/unit/io/test_twistedreactor.py +++ b/tests/unit/io/test_twistedreactor.py @@ -199,17 +199,17 @@ class TestTwistedConnection(unittest.TestCase): Verify that handle_read() processes incomplete messages properly. """ self.obj_ut.process_msg = Mock() - self.assertEqual(self.obj_ut._iobuf.getvalue(), '') # buf starts empty + self.assertEqual(self.obj_ut._iobuf.getvalue(), b'') # buf starts empty # incomplete header - self.obj_ut._iobuf.write('\x84\x00\x00\x00\x00') + self.obj_ut._iobuf.write(b'\x84\x00\x00\x00\x00') self.obj_ut.handle_read() - self.assertEqual(self.obj_ut._iobuf.getvalue(), '\x84\x00\x00\x00\x00') + self.assertEqual(self.obj_ut._iobuf.getvalue(), b'\x84\x00\x00\x00\x00') # full header, but incomplete body - self.obj_ut._iobuf.write('\x00\x00\x00\x15') + self.obj_ut._iobuf.write(b'\x00\x00\x00\x15') self.obj_ut.handle_read() self.assertEqual(self.obj_ut._iobuf.getvalue(), - '\x84\x00\x00\x00\x00\x00\x00\x00\x15') + b'\x84\x00\x00\x00\x00\x00\x00\x00\x15') self.assertEqual(self.obj_ut._current_frame.end_pos, 30) # verify we never attempted to process the incomplete message @@ -220,14 +220,14 @@ class TestTwistedConnection(unittest.TestCase): Verify that handle_read() processes complete messages properly. """ self.obj_ut.process_msg = Mock() - self.assertEqual(self.obj_ut._iobuf.getvalue(), '') # buf starts empty + self.assertEqual(self.obj_ut._iobuf.getvalue(), b'') # buf starts empty # write a complete message, plus 'NEXT' (to simulate next message) # assumes protocol v3+ as default Connection.protocol_version - body = 'this is the drum roll' - extra = 'NEXT' + body = b'this is the drum roll' + extra = b'NEXT' self.obj_ut._iobuf.write( - '\x84\x01\x00\x02\x03\x00\x00\x00\x15' + body + extra) + b'\x84\x01\x00\x02\x03\x00\x00\x00\x15' + body + extra) self.obj_ut.handle_read() self.assertEqual(self.obj_ut._iobuf.getvalue(), extra) self.obj_ut.process_msg.assert_called_with( diff --git a/tox.ini b/tox.ini index 0f97b241..11d9f259 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py{26,27,33,34},pypy +envlist = py{26,27,33,34},pypy,pypy3 [base] deps = nose @@ -25,5 +25,10 @@ commands = nosetests --verbosity=2 --no-path-adjustment {toxinidir}/tests/unit/ [testenv:pypy] deps = {[base]deps} commands = nosetests --verbosity=2 {toxinidir}/tests/unit/ + +[testenv:pypy3] +deps = {[base]deps} +commands = nosetests --verbosity=2 {toxinidir}/tests/unit/ + # cqlengine/test_timestamp.py uses sure, which fails in pypy presently # could remove sure usage