summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjbrockmendel <jbrockmendel@gmail.com>2020-05-21 15:54:30 -0700
committerjbrockmendel <jbrockmendel@gmail.com>2020-05-21 15:54:30 -0700
commit0d7909bfb350bf33c86f40636e3b8717e5c41f7e (patch)
tree35436234d1fc92427be4fbb20496cf96532a85c1
parent690a0ab4c65bb828b73526ad9064d7495fdbd6b6 (diff)
downloadnumpy-0d7909bfb350bf33c86f40636e3b8717e5c41f7e.tar.gz
First stab at tests, try on the CI
-rw-r--r--numpy/__init__.pxd6
-rw-r--r--numpy/core/tests/examples/checks.pyx26
-rw-r--r--numpy/core/tests/examples/setup.py26
-rw-r--r--numpy/core/tests/test_cython.py114
4 files changed, 169 insertions, 3 deletions
diff --git a/numpy/__init__.pxd b/numpy/__init__.pxd
index c265cdedb..338da3d7e 100644
--- a/numpy/__init__.pxd
+++ b/numpy/__init__.pxd
@@ -26,7 +26,7 @@ cimport libc.stdio as stdio
cdef extern from "Python.h":
ctypedef int Py_intptr_t
- bint PyObject_TypeCheck(object obj, PyTypeObject* type) nogil
+ bint PyObject_TypeCheck(object obj, PyTypeObject* type)
cdef extern from "numpy/arrayobject.h":
ctypedef Py_intptr_t npy_intp
@@ -1018,7 +1018,7 @@ cdef extern from *:
"""
-cdef inline bint is_timedelta64_object(object obj) nogil:
+cdef inline bint is_timedelta64_object(object obj):
"""
Cython equivalent of `isinstance(obj, np.timedelta64)`
@@ -1033,7 +1033,7 @@ cdef inline bint is_timedelta64_object(object obj) nogil:
return PyObject_TypeCheck(obj, &PyTimedeltaArrType_Type)
-cdef inline bint is_datetime64_object(object obj) nogil:
+cdef inline bint is_datetime64_object(object obj):
"""
Cython equivalent of `isinstance(obj, np.datetime64)`
diff --git a/numpy/core/tests/examples/checks.pyx b/numpy/core/tests/examples/checks.pyx
new file mode 100644
index 000000000..ecf0ad3fa
--- /dev/null
+++ b/numpy/core/tests/examples/checks.pyx
@@ -0,0 +1,26 @@
+"""
+Functions in this module give python-space wrappers for cython functions
+exposed in numpy/__init__.pxd, so they can be tested in test_cython.py
+"""
+cimport numpy as cnp
+cnp.import_array()
+
+
+def is_td64(obj):
+ return cnp.is_timedelta64_object(obj)
+
+
+def is_dt64(obj):
+ return cnp.is_datetime64_object(obj)
+
+
+def get_dt64_value(obj):
+ return cnp.get_datetime64_value(obj)
+
+
+def get_td64_value(obj):
+ return cnp.get_timedelta64_value(obj)
+
+
+def get_dt64_unit(obj):
+ return cnp.get_datetime64_unit(obj)
diff --git a/numpy/core/tests/examples/setup.py b/numpy/core/tests/examples/setup.py
new file mode 100644
index 000000000..9860bf5f7
--- /dev/null
+++ b/numpy/core/tests/examples/setup.py
@@ -0,0 +1,26 @@
+"""
+Provide python-space access to the functions exposed in numpy/__init__.pxd
+for testing.
+"""
+
+import numpy as np
+from distutils.core import setup
+from Cython.Build import cythonize
+from setuptools.extension import Extension
+import os
+
+here = os.path.dirname(__file__)
+macros = [("NPY_NO_DEPRECATED_API", 0)]
+
+checks = Extension(
+ "checks",
+ sources=[os.path.join(here, "checks.pyx")],
+ include_dirs=[np.get_include()],
+ define_macros=macros,
+)
+
+extensions = [checks]
+
+setup(
+ ext_modules=cythonize(extensions)
+)
diff --git a/numpy/core/tests/test_cython.py b/numpy/core/tests/test_cython.py
new file mode 100644
index 000000000..bb173e439
--- /dev/null
+++ b/numpy/core/tests/test_cython.py
@@ -0,0 +1,114 @@
+
+import os
+import shutil
+import subprocess
+import sys
+import pytest
+
+import numpy as np
+
+# This import is copied from random.tests.test_extending
+try:
+ import cython
+ from Cython.Compiler.Version import version as cython_version
+except ImportError:
+ cython = None
+else:
+ from distutils.version import LooseVersion
+ # Cython 0.29.14 is required for Python 3.8 and there are
+ # other fixes in the 0.29 series that are needed even for earlier
+ # Python versions.
+ # Note: keep in sync with the one in pyproject.toml
+ required_version = LooseVersion("0.29.14")
+ if LooseVersion(cython_version) < required_version:
+ # too old or wrong cython, skip the test
+ cython = None
+
+pytestmark = pytest.mark.skipif(cython is None, reason="requires cython")
+
+
+@pytest.fixture
+def install_temp(request, tmp_path):
+ # Based in part on test_cython from random.tests.test_extending
+
+ here = os.path.dirname(__file__)
+ ext_dir = os.path.join(here, "examples")
+
+ #assert False
+ tmp_path = tmp_path._str#str(tmp_path)
+ cytest = os.path.join(tmp_path, "cytest")
+
+ shutil.copytree(ext_dir, cytest)
+ # build the examples and "install" them into a temporary directory
+
+ build_dir = os.path.join(tmp_path, "examples")
+ subprocess.check_call([sys.executable, "setup.py", "build", "install",
+ "--prefix", os.path.join(tmp_path, "installdir"),
+ "--single-version-externally-managed",
+ "--record", os.path.join(tmp_path, "tmp_install_log.txt"),
+ ],
+ cwd=cytest,
+ )
+ sys.path.append(cytest)
+
+
+def test_is_timedelta64_object(install_temp):
+ import checks
+
+ assert checks.is_td64(np.timedelta64(1234))
+ assert checks.is_td64(np.timedelta64(1234, "ns"))
+ assert checks.is_td64(np.timedelta64("NaT", "ns"))
+
+ assert not checks.is_td64(1)
+ assert not checks.is_td64(None)
+ assert not checks.is_td64("foo")
+ assert not checks.is_td64(np.datetime64("now"))
+
+
+def test_is_datetime64_object(install_temp):
+ import checks
+
+ assert checks.is_dt64(np.datetime64(1234))
+ assert checks.is_dt64(np.datetime64(1234, "ns"))
+ assert checks.is_dt64(np.datetime64("NaT", "ns"))
+
+ assert not checks.is_dt64(1)
+ assert not checks.is_dt64(None)
+ assert not checks.is_dt64("foo")
+ assert not checks.is_dt64(np.timedelta64(1234))
+
+
+def test_get_datetime64_value(install_temp):
+ import checks
+
+ dt64 = np.datetime64("2016-01-01", "ns")
+
+ result = checks.get_dt64_value(dt64)
+ expected = dt64.view("i8")
+
+ assert result == expected
+
+
+def test_get_timedelta64_value(install_temp):
+ import checks
+
+ td64 = np.timedelta(12345, "h")
+
+ result = checks.get_td64_value(dt64)
+ expected = td64.view("i8")
+
+ assert result == expected
+
+
+def test_get_datetime64_unit(install_temp):
+ import checks
+
+ dt64 = np.datetime64("2016-01-01", "ns")
+ result = checks.get_dt64_unit(dt64)
+ expected = 11
+ assert result == expected
+
+ td64 = np.timedelta(12345, "h")
+ result = checks.get_dt64_unit(dt64)
+ expected = 5
+ assert result == expected