summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavidjn <dnic12345@gmail.com>2017-05-07 16:26:17 -0700
committerEric Wieser <wieser.eric@gmail.com>2017-05-08 00:26:17 +0100
commitd7d1b2a7297a680164e216f96905047ca1a2051f (patch)
tree2dce0b0aa44710aae147c711e6077b1209910380
parentbc5dae97c92232e9778fac062437f6f2224282f1 (diff)
downloadpython-numpy-d7d1b2a7297a680164e216f96905047ca1a2051f.tar.gz
python-numpy-d7d1b2a7297a680164e216f96905047ca1a2051f.tar.bz2
python-numpy-d7d1b2a7297a680164e216f96905047ca1a2051f.zip
BUG: Move ctypes ImportError catching to appropriate place (#8898)
This fixes a regression in 3c1a13dea6a7e189675977ad65ea230ce4816061, restoring the behaviour intended by eee00f8f7e15592a048c8b841aef9ea81faa0fda. This also extends the support on ctype-less systems for `arr.ctypes.shape` and `arr.ctypes.strides`. The dummy_ctype object is a naive fake used when ctypes is not importable. It does not intend to fake any ctypes behavior, but provides a duck-typed interface so that method calls do not fail. The get_shape and get_strides refactors take advantage of other instance methods and reduce code duplication.
-rw-r--r--numpy/core/_internal.py47
-rw-r--r--numpy/core/tests/test_multiarray.py22
2 files changed, 52 insertions, 17 deletions
diff --git a/numpy/core/_internal.py b/numpy/core/_internal.py
index 01741cd1a..d8d9168ac 100644
--- a/numpy/core/_internal.py
+++ b/numpy/core/_internal.py
@@ -11,7 +11,10 @@ import sys
from numpy.compat import basestring
from .multiarray import dtype, array, ndarray
-import ctypes
+try:
+ import ctypes
+except ImportError:
+ ctypes = None
from .numerictypes import object_
if (sys.byteorder == 'little'):
@@ -194,19 +197,33 @@ def _commastring(astr):
return result
+class dummy_ctype(object):
+ def __init__(self, cls):
+ self._cls = cls
+ def __mul__(self, other):
+ return self
+ def __call__(self, *other):
+ return self._cls(other)
+ def __eq__(self, other):
+ return self._cls == other._cls
+
def _getintp_ctype():
val = _getintp_ctype.cache
if val is not None:
return val
- char = dtype('p').char
- if (char == 'i'):
- val = ctypes.c_int
- elif char == 'l':
- val = ctypes.c_long
- elif char == 'q':
- val = ctypes.c_longlong
+ if ctypes is None:
+ import numpy as np
+ val = dummy_ctype(np.intp)
else:
- val = ctypes.c_long
+ char = dtype('p').char
+ if (char == 'i'):
+ val = ctypes.c_int
+ elif char == 'l':
+ val = ctypes.c_long
+ elif char == 'q':
+ val = ctypes.c_longlong
+ else:
+ val = ctypes.c_long
_getintp_ctype.cache = val
return val
_getintp_ctype.cache = None
@@ -222,9 +239,9 @@ class _missing_ctypes(object):
class _ctypes(object):
def __init__(self, array, ptr=None):
- try:
+ if ctypes:
self._ctypes = ctypes
- except ImportError:
+ else:
self._ctypes = _missing_ctypes()
self._arr = array
self._data = ptr
@@ -250,14 +267,10 @@ class _ctypes(object):
return self._data
def get_shape(self):
- if self._zerod:
- return None
- return (_getintp_ctype()*self._arr.ndim)(*self._arr.shape)
+ return self.shape_as(_getintp_ctype())
def get_strides(self):
- if self._zerod:
- return None
- return (_getintp_ctype()*self._arr.ndim)(*self._arr.strides)
+ return self.strides_as(_getintp_ctype())
def get_as_parameter(self):
return self._ctypes.c_void_p(self._data)
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index 4dc82eb1d..8ab8c0ca7 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -6742,6 +6742,28 @@ class TestUnicodeArrayNonzero(TestCase):
a[0] = ' \0 \0'
self.assertTrue(a)
+
+class TestCTypes(TestCase):
+
+ def test_ctypes_is_available(self):
+ test_arr = np.array([[1, 2, 3], [4, 5, 6]])
+
+ self.assertEqual(ctypes, test_arr.ctypes._ctypes)
+ assert_equal(tuple(test_arr.ctypes.shape), (2, 3))
+
+ def test_ctypes_is_not_available(self):
+ from numpy.core import _internal
+ _internal.ctypes = None
+ try:
+ test_arr = np.array([[1, 2, 3], [4, 5, 6]])
+
+ self.assertIsInstance(
+ test_arr.ctypes._ctypes, _internal._missing_ctypes)
+ assert_equal(tuple(test_arr.ctypes.shape), (2, 3))
+ finally:
+ _internal.ctypes = ctypes
+
+
def test_orderconverter_with_nonASCII_unicode_ordering():
# gh-7475
a = np.arange(5)