diff --git a/setup.py b/setup.py index e0ff636..5a54e19 100644 --- a/setup.py +++ b/setup.py @@ -2,14 +2,26 @@ from setuptools import setup, Extension, find_packages import sys -import numpy as np - long_description = '' if 'upload' in sys.argv: with open('README.rst') as f: long_description = f.read() +if 'sdist' in sys.argv: + ext_modules = [] +else: + import numpy as np + ext_modules = [ + Extension( + 'warp_prism._warp_prism', + ['warp_prism/_warp_prism.c'], + include_dirs=[np.get_include()], + extra_compile_args=['-std=c99', '-Wall', '-Wextra'], + ), + ] + + classifiers = [ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', @@ -33,14 +45,7 @@ license='Apache 2.0', classifiers=classifiers, url='https://github.com/quantopian/warp_prism', - ext_modules=[ - Extension( - 'warp_prism._warp_prism', - ['warp_prism/_warp_prism.c'], - include_dirs=[np.get_include()], - extra_compile_args=['-std=c99', '-Wall', '-Wextra'], - ), - ], + ext_modules=ext_modules, install_requires=[ 'datashape', 'numpy', diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..6186f69 --- /dev/null +++ b/tox.ini @@ -0,0 +1,22 @@ +[tox] +envlist=py27,py35 +skip_missing_interpreters=true + +[pep8] +max-line-length = 80 + +[testenv] +deps = numpy +commands= + pip install .[dev] + py.test {posargs} + +# # cd to .tox/env/tmp before running tests. This ensures that we test in a +# # context where the source checkout is **not** on sys.path, which means that we +# # test against the sdist created by `pip` rather than the git checkout. +# changedir={envtmpdir} + +[pytest] +addopts = --flake8 --pyargs +flake8-max-line-length = 80 +python_classes = *Test* diff --git a/warp_prism/__init__.py b/warp_prism/__init__.py index 7a560a5..92570a2 100644 --- a/warp_prism/__init__.py +++ b/warp_prism/__init__.py @@ -104,7 +104,7 @@ def _getbind(selectable, bind): return sa.create_engine(bind) -def to_arrays(query, *, bind=None): +def to_arrays(query, bind=None): """Run the query returning a the results as np.ndarrays. Parameters @@ -131,7 +131,7 @@ def to_arrays(query, *, bind=None): stmt = _CopyToBinary(query, bind) with bind.connect() as conn: conn.connection.cursor().copy_expert(literal_compile(stmt), buf) - out = _raw_to_arrays(buf.getbuffer(), types) + out = _raw_to_arrays(buf.getvalue(), types) column_names = query.c.keys() return {column_names[n]: v for n, v in enumerate(out)} @@ -151,7 +151,7 @@ def to_arrays(query, *, bind=None): _default_null_values_for_type = null_values -def to_dataframe(query, *, bind=None, null_values=None): +def to_dataframe(query, bind=None, null_values=None): """Run the query returning a the results as a pd.DataFrame. Parameters diff --git a/warp_prism/_warp_prism.c b/warp_prism/_warp_prism.c index 070e770..798e6fb 100644 --- a/warp_prism/_warp_prism.c +++ b/warp_prism/_warp_prism.c @@ -6,6 +6,9 @@ #include "Python.h" #include "numpy/arrayobject.h" +#define COMPILING_IN_PY2 (PY_VERSION_HEX <= 0x03000000) +#define MODULE_NAME "warp_prism._warp_prism" + const char* const signature = "PGCOPY\n\377\r\n\0"; const size_t signature_len = 11; @@ -822,9 +825,10 @@ PyMethodDef methods[] = { {NULL}, }; +#if !COMPILING_IN_PY2 static struct PyModuleDef _warp_prism_module = { PyModuleDef_HEAD_INIT, - "warp_prism._warp_prism", + MODULE_NAME, "", -1, methods, @@ -833,8 +837,17 @@ static struct PyModuleDef _warp_prism_module = { NULL, NULL }; +#endif /* !COMPILING_IN_PY2*/ -PyMODINIT_FUNC PyInit__warp_prism(void) { +PyMODINIT_FUNC +#if COMPILING_IN_PY2 +#define ERROR_RETURN +init_warp_prism(void) +#else +#define ERROR_RETURN NULL +PyInit__warp_prism(void) +#endif /* COMPILING_IN_PY2*/ +{ PyObject* m; PyObject* typeid_map; PyObject* signature_ob; @@ -843,7 +856,7 @@ PyMODINIT_FUNC PyInit__warp_prism(void) { import_array(); if (!(typeid_map = PyDict_New())) { - return NULL; + return ERROR_RETURN; } for (size_t n = 0; n < max_typeid; ++n) { @@ -854,21 +867,21 @@ PyMODINIT_FUNC PyInit__warp_prism(void) { if (!(dtype_name_ob = PyUnicode_FromString(typeids[n]->dtype_name))) { Py_DECREF(typeid_map); - return NULL; + return ERROR_RETURN; } if (!PyArray_DescrConverter(dtype_name_ob, (PyArray_Descr**) &typeids[n]->dtype)) { Py_DECREF(dtype_name_ob); Py_DECREF(typeid_map); - return NULL; + return ERROR_RETURN; } if (!(n_ob = PyLong_FromLong(n))) { Py_DECREF(dtype_name_ob); Py_DECREF(typeid_map); - return NULL; + return ERROR_RETURN; } err = PyDict_SetItem(typeid_map, dtype_name_ob, n_ob); @@ -876,31 +889,37 @@ PyMODINIT_FUNC PyInit__warp_prism(void) { Py_DECREF(n_ob); if (err) { Py_DECREF(typeid_map); - return NULL; + return ERROR_RETURN; } } +#if COMPILING_IN_PY2 + if (!(m = Py_InitModule(MODULE_NAME, methods))) { +#else if (!(m = PyModule_Create(&_warp_prism_module))) { +#endif /* COMPILING_IN_PY2 */ Py_DECREF(typeid_map); - return NULL; + return ERROR_RETURN; } if (PyModule_AddObject(m, "typeid_map", typeid_map)) { Py_DECREF(typeid_map); Py_DECREF(m); - return NULL; + return ERROR_RETURN; } if (!(signature_ob = PyBytes_FromStringAndSize(signature, signature_len))) { Py_DECREF(m); - return NULL; + return ERROR_RETURN; } if (PyModule_AddObject(m, "postgres_signature", signature_ob)) { Py_DECREF(signature_ob); Py_DECREF(m); - return NULL; + return ERROR_RETURN; } +#if !COMPILING_IN_PY2 return m; +#endif /* !COMPILING_IN_PY2 */ } diff --git a/warp_prism/tests/test_warp_prism.py b/warp_prism/tests/test_warp_prism.py index f5b2a0a..df81ea7 100644 --- a/warp_prism/tests/test_warp_prism.py +++ b/warp_prism/tests/test_warp_prism.py @@ -111,7 +111,6 @@ def check_roundtrip_null_values(table_uri, sqltype, null_values, mask, - *, astype=False): """Check the data roundtrip through postgres using warp_prism to read the data @@ -170,7 +169,6 @@ def check_roundtrip_null(table_uri, sqltype, null, mask, - *, astype=False): """Check the data roundtrip through postgres using warp_prism to read the data @@ -427,7 +425,7 @@ def test_missing_flags(): def test_missing_extension_length(): - input_data = postgres_signature + (0).to_bytes(4, 'big') + input_data = postgres_signature + b'\x00\x00\x00\x00' with pytest.raises(ValueError) as e: raw_to_arrays(input_data, ()) @@ -438,7 +436,7 @@ def test_missing_extension_length(): def test_missing_end_marker(): - input_data = postgres_signature + (0).to_bytes(4, 'big') + input_data = postgres_signature + b'\x00\x00\x00\x00' with pytest.raises(ValueError) as e: raw_to_arrays(input_data, ())