diff options
author | davidjn <dnic12345@gmail.com> | 2017-05-07 16:26:17 -0700 |
---|---|---|
committer | Eric Wieser <wieser.eric@gmail.com> | 2017-05-08 00:26:17 +0100 |
commit | d7d1b2a7297a680164e216f96905047ca1a2051f (patch) | |
tree | 2dce0b0aa44710aae147c711e6077b1209910380 | |
parent | bc5dae97c92232e9778fac062437f6f2224282f1 (diff) | |
download | python-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.py | 47 | ||||
-rw-r--r-- | numpy/core/tests/test_multiarray.py | 22 |
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) |