From f7c0bd312df6ac105173969c8b57ee4b8bd9c664 Mon Sep 17 00:00:00 2001 From: John Anderson Date: Thu, 25 Jun 2015 10:59:57 -0700 Subject: [PATCH 1/6] Enable C extensions on pypy and add pypy3 support Conflicts: tox.ini --- cassandra/murmur3.c | 10 +++++++++- setup.py | 4 ++-- tox.ini | 11 +++++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) 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 54527d1a..bf124262 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 = """ =============================================================================== @@ -291,8 +292,7 @@ The optional C extensions are not supported on big-endian systems. if extensions: if (sys.platform.startswith("java") - or sys.platform == "cli" - or "PyPy" in sys.version): + or sys.platform == "cli"): sys.stderr.write(platform_unsupported_msg) extensions = () elif sys.byteorder == "big": diff --git a/tox.ini b/tox.ini index 433e2540..b1f99087 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 @@ -20,6 +20,13 @@ commands = nosetests --verbosity=2 --no-path-adjustment {toxinidir}/tests/unit/ [testenv:pypy] deps = {[base]deps} -commands = nosetests --verbosity=2 {toxinidir}/tests/unit/ +commands = {envpython} setup.py build_ext --inplace + nosetests --verbosity=2 tests/unit/ + +[testenv:pypy3] +deps = {[base]deps} +commands = {envpython} setup.py build_ext --inplace + nosetests --verbosity=2 tests/unit/ + # cqlengine/test_timestamp.py uses sure, which fails in pypy presently # could remove sure usage From e08fefc9822d7d8594262e2735fa79e80d6b59f7 Mon Sep 17 00:00:00 2001 From: Adam Holmberg Date: Wed, 15 Jul 2015 14:48:43 -0500 Subject: [PATCH 2/6] Make tests.unit.io.test_twistedreactor work in Python3 --- tests/unit/io/test_twistedreactor.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/unit/io/test_twistedreactor.py b/tests/unit/io/test_twistedreactor.py index d2142b09..90634609 100644 --- a/tests/unit/io/test_twistedreactor.py +++ b/tests/unit/io/test_twistedreactor.py @@ -153,17 +153,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 @@ -174,14 +174,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( From cf7e6683d3c036b70e17de9fa187ec8e01bf7e6e Mon Sep 17 00:00:00 2001 From: Adam Holmberg Date: Wed, 15 Jul 2015 15:15:08 -0500 Subject: [PATCH 3/6] Whitelist murmur3 extension for PyPy runtime --- setup.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index bf124262..d89a5ca5 100644 --- a/setup.py +++ b/setup.py @@ -268,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 = [] @@ -290,14 +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"): + 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 From 5391a206343deb129db34a252348f56f8c45a451 Mon Sep 17 00:00:00 2001 From: Adam Holmberg Date: Fri, 10 Jul 2015 09:52:48 -0500 Subject: [PATCH 4/6] Limit mock dependency to version 1.0.1 1.1.0 dropped Python 2.6 support, and at least one call assert function currently used by tests. --- setup.py | 2 +- test-requirements.txt | 2 +- tox.ini | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index d89a5ca5..37899c2e 100644 --- a/setup.py +++ b/setup.py @@ -216,7 +216,7 @@ def run_setup(extensions): keywords='cassandra,cql,orm', include_package_data=True, install_requires=dependencies, - tests_require=['nose', 'mock', 'PyYAML', 'pytz', 'sure'], + tests_require=['nose', 'mock<=1.0.1', 'PyYAML', 'pytz', 'sure'], classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', diff --git a/test-requirements.txt b/test-requirements.txt index a90f1ad5..cc7b3c2b 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -2,7 +2,7 @@ blist scales nose -mock +mock<=1.0.1 ccm>=2.0 unittest2 PyYAML diff --git a/tox.ini b/tox.ini index b1f99087..d1ffc545 100644 --- a/tox.ini +++ b/tox.ini @@ -3,7 +3,7 @@ envlist = py{26,27,33,34},pypy,pypy3 [base] deps = nose - mock + mock<=1.0.1 PyYAML six From be47fce1c13a2c574a07bdef5dcead2d966acac7 Mon Sep 17 00:00:00 2001 From: Adam Holmberg Date: Wed, 15 Jul 2015 15:29:23 -0500 Subject: [PATCH 5/6] Make tox pypy commands use absolute path to unit tests follows from new setdir --- tox.ini | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tox.ini b/tox.ini index d1ffc545..5b5832af 100644 --- a/tox.ini +++ b/tox.ini @@ -20,13 +20,11 @@ commands = nosetests --verbosity=2 --no-path-adjustment {toxinidir}/tests/unit/ [testenv:pypy] deps = {[base]deps} -commands = {envpython} setup.py build_ext --inplace - nosetests --verbosity=2 tests/unit/ +commands = nosetests --verbosity=2 {toxinidir}/tests/unit/ [testenv:pypy3] deps = {[base]deps} -commands = {envpython} setup.py build_ext --inplace - nosetests --verbosity=2 tests/unit/ +commands = nosetests --verbosity=2 {toxinidir}/tests/unit/ # cqlengine/test_timestamp.py uses sure, which fails in pypy presently # could remove sure usage From d5b7f9264295dd16345e09e843f2ca1fdb4428b5 Mon Sep 17 00:00:00 2001 From: Adam Holmberg Date: Thu, 16 Jul 2015 11:16:17 -0500 Subject: [PATCH 6/6] Add pypy3 config to .travis.yml --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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