8000 BUG: Move ctypes ImportError catching to appropriate place (#8898) · numpy/numpy@d7d1b2a · GitHub
[go: up one dir, main page]

Skip to content

Commit d7d1b2a

Browse files
davidjneric-wieser
authored andcommitted
BUG: Move ctypes ImportError catching to appropriate place (#8898)
This fixes a regression in 3c1a13d, restoring the behaviour intended by eee00f8. 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.
1 parent bc5dae9 commit d7d1b2a

File tree

2 files changed

+52
-17
lines changed

2 files changed

+52
-17
lines changed

numpy/core/_internal.py

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111

1212
from numpy.compat import basestring
1313
from .multiarray import dtype, array, ndarray
14-
import ctypes
14+
try:
15+
import ctypes
16+
except ImportError:
17+
ctypes = None
1518
from .numerictypes import object_
1619

1720
if (sys.byteorder == 'little'):
@@ -194,19 +197,33 @@ def _commastring(astr):
194197

195198
return result
196199

200+
class dummy_ctype(object):
201+
def __init__(self, cls):
202+
self._cls = cls
203+
def __mul__(self, other):
204+
return self
205+
def __call__(self, *other):
206+
return self._cls(other)
207+
def __eq__(self, other):
208+
return self._cls == other._cls
209+
197210
def _getintp_ctype():
198211
val = _getintp_ctype.cache
199212
if val is not None:
200213
return val
201-
char = dtype('p').char
202-
if (char == 'i'):
203-
val = ctypes.c_int
204-
elif char == 'l':
205-
val = ctypes.c_long
206-
elif char == 'q':
207-
val = ctypes.c_longlong
214+
if ctypes is None:
215+
import numpy as np
216+
val = dummy_ctype(np.intp)
208217
else:
209-
val = ctypes.c_long
218+
char = dtype('p').char
219+
if (char == 'i'):
220+
val = ctypes.c_int
221+
elif char == 'l':
222+
val = ctypes.c_long
223+
elif char == 'q':
224+
val = ctypes.c_longlong
225+
else:
226+
val = ctypes.c_long
210227
_getintp_ctype.cache = val
211228
return val
212229
_getintp_ctype.cache = None
@@ -222,9 +239,9 @@ def c_void_p(self, num):
222239

223240
class _ctypes(object):
224241
def __init__(self, array, ptr=None):
225-
try:
242+
if ctypes:
226243
self._ctypes = ctypes
227-
except ImportError:
244+
else:
228245
self._ctypes = _missing_ctypes()
229246
self._arr = array
230247
self._data = ptr
@@ -250,14 +267,10 @@ def get_data(self):
250267
return self._data
251268

252269
def get_shape(self):
253-
if self._zerod:
254-
return None
255-
return (_getintp_ctype()*self._arr.ndim)(*self._arr.shape)
270+
return self.shape_as(_getintp_ctype())
256271

257272
def get_strides(self):
258-
if self._zerod:
259-
return None
260-
return (_getintp_ctype()*self._arr.ndim)(*self._arr.strides)
273+
return self.strides_as(_getintp_ctype())
261274

262275
def get_as_parameter(self):
263276
return self._ctypes.c_void_p(self._data)

numpy/core/tests/test_multiarray.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6742,6 +6742,28 @@ def test_null_inside_ustring_array_is_truthy(self):
67426742
a[0] = ' \0 \0'
67436743
self.assertTrue(a)
67446744

6745+
6746+
class TestCTypes(TestCase):
6747+
6748+
def test_ctypes_is_available(self):
6749+
test_arr = np.array([[1, 2, 3], [4, 5, 6]])
6750+
6751+
self.assertEqual(ctypes, test_arr.ctypes._ctypes)
6752+
assert_equal(tuple(test_arr.ctypes.shape), (2, 3))
6753+
6754+
def test_ctypes_is_not_available(self):
6755+
from numpy.core import _internal
6756+
_internal.ctypes = None
6757+
try:
6758+
test_arr = np.array([[1, 2, 3], [4, 5, 6]])
6759+
6760+
self.assertIsInstance(
6761+
test_arr.ctypes._ctypes, _internal._missing_ctypes)
6762+
assert_equal(tuple(test_arr.ctypes.shape), (2, 3))
6763+
finally:
6764+
_internal.ctypes = ctypes
6765+
6766+
67456767
def test_orderconverter_with_nonASCII_unicode_ordering():
67466768
# gh-7475
67476769
a = np.arange(5)

0 commit comments

Comments
 (0)
0