summaryrefslogtreecommitdiff
path: root/numpy/f2py/tests/test_array_from_pyobj.py
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/f2py/tests/test_array_from_pyobj.py')
-rw-r--r--numpy/f2py/tests/test_array_from_pyobj.py81
1 files changed, 70 insertions, 11 deletions
diff --git a/numpy/f2py/tests/test_array_from_pyobj.py b/numpy/f2py/tests/test_array_from_pyobj.py
index 5a084bc3e..2b8c8defc 100644
--- a/numpy/f2py/tests/test_array_from_pyobj.py
+++ b/numpy/f2py/tests/test_array_from_pyobj.py
@@ -6,11 +6,18 @@ import pytest
import numpy as np
-from numpy.core.multiarray import typeinfo
+from numpy.testing import assert_, assert_equal
+from numpy.core.multiarray import typeinfo as _typeinfo
from . import util
wrap = None
+# Extend core typeinfo with CHARACTER to test dtype('c')
+_ti = _typeinfo['STRING']
+typeinfo = dict(
+ CHARACTER=type(_ti)(('c', _ti.num, 8, _ti.alignment, _ti.type)),
+ **_typeinfo)
+
def setup_module():
"""
@@ -56,6 +63,7 @@ def flags2names(flags):
"NOTSWAPPED",
"WRITEABLE",
"WRITEBACKIFCOPY",
+ "UPDATEIFCOPY",
"BEHAVED",
"BEHAVED_RO",
"CARRAY",
@@ -116,6 +124,9 @@ _type_names = [
"FLOAT",
"DOUBLE",
"CFLOAT",
+ "STRING1",
+ "STRING5",
+ "CHARACTER",
]
_cast_dict = {"BOOL": ["BOOL"]}
@@ -139,6 +150,10 @@ _cast_dict["DOUBLE"] = _cast_dict["INT"] + ["UINT", "FLOAT", "DOUBLE"]
_cast_dict["CFLOAT"] = _cast_dict["FLOAT"] + ["CFLOAT"]
+_cast_dict['STRING1'] = ['STRING1']
+_cast_dict['STRING5'] = ['STRING5']
+_cast_dict['CHARACTER'] = ['CHARACTER']
+
# 32 bit system malloc typically does not provide the alignment required by
# 16 byte long double types this means the inout intent cannot be satisfied
# and several tests fail as the alignment flag can be randomly true or fals
@@ -184,14 +199,33 @@ class Type:
def _init(self, name):
self.NAME = name.upper()
- info = typeinfo[self.NAME]
- self.type_num = getattr(wrap, "NPY_" + self.NAME)
+
+ if self.NAME == 'CHARACTER':
+ info = typeinfo[self.NAME]
+ self.type_num = getattr(wrap, 'NPY_STRING')
+ self.elsize = 1
+ self.dtype = np.dtype('c')
+ elif self.NAME.startswith('STRING'):
+ info = typeinfo[self.NAME[:6]]
+ self.type_num = getattr(wrap, 'NPY_STRING')
+ self.elsize = int(self.NAME[6:] or 0)
+ self.dtype = np.dtype(f'S{self.elsize}')
+ else:
+ info = typeinfo[self.NAME]
+ self.type_num = getattr(wrap, 'NPY_' + self.NAME)
+ self.elsize = info.bits // 8
+ self.dtype = np.dtype(info.type)
+
assert self.type_num == info.num
- self.dtype = np.dtype(info.type)
self.type = info.type
- self.elsize = info.bits / 8
self.dtypechar = info.char
+ def __repr__(self):
+ return (f"Type({self.NAME})|type_num={self.type_num},"
+ f" dtype={self.dtype},"
+ f" type={self.type}, elsize={self.elsize},"
+ f" dtypechar={self.dtypechar}")
+
def cast_types(self):
return [self.__class__(_m) for _m in _cast_dict[self.NAME]]
@@ -226,6 +260,11 @@ class Type:
class Array:
+
+ def __repr__(self):
+ return (f'Array({self.type}, {self.dims}, {self.intent},'
+ f' {self.obj})|arr={self.arr}')
+
def __init__(self, typ, dims, intent, obj):
self.type = typ
self.dims = dims
@@ -234,7 +273,9 @@ class Array:
self.obj = obj
# arr.dtypechar may be different from typ.dtypechar
- self.arr = wrap.call(typ.type_num, dims, intent.flags, obj)
+ self.arr = wrap.call(typ.type_num,
+ typ.elsize,
+ dims, intent.flags, obj)
assert isinstance(self.arr, np.ndarray)
@@ -289,7 +330,9 @@ class Array:
self.arr.tobytes(),
self.pyarr.tobytes(),
)) # strides
- assert self.arr_attr[5][-2:] == self.pyarr_attr[5][-2:] # descr
+ assert self.arr_attr[5][-2:] == self.pyarr_attr[5][-2:], repr((
+ self.arr_attr[5], self.pyarr_attr[5]
+ )) # descr
assert self.arr_attr[6] == self.pyarr_attr[6], repr((
self.arr_attr[6],
self.pyarr_attr[6],
@@ -338,8 +381,6 @@ class TestIntent:
class TestSharedMemory:
- num2seq = [1, 2]
- num23seq = [[1, 2, 3], [4, 5, 6]]
@pytest.fixture(autouse=True, scope="class", params=_type_names)
def setup_type(self, request):
@@ -347,6 +388,21 @@ class TestSharedMemory:
request.cls.array = lambda self, dims, intent, obj: Array(
Type(request.param), dims, intent, obj)
+ @property
+ def num2seq(self):
+ if self.type.NAME.startswith('STRING'):
+ elsize = self.type.elsize
+ return ['1' * elsize, '2' * elsize]
+ return [1, 2]
+
+ @property
+ def num23seq(self):
+ if self.type.NAME.startswith('STRING'):
+ elsize = self.type.elsize
+ return [['1' * elsize, '2' * elsize, '3' * elsize],
+ ['4' * elsize, '5' * elsize, '6' * elsize]]
+ return [[1, 2, 3], [4, 5, 6]]
+
def test_in_from_2seq(self):
a = self.array([2], intent.in_, self.num2seq)
assert not a.has_shared_memory()
@@ -367,9 +423,9 @@ class TestSharedMemory:
"""Test if intent(in) array can be passed without copies"""
seq = getattr(self, "num" + inp)
obj = np.array(seq, dtype=self.type.dtype, order=order)
- obj.setflags(write=(write == "w"))
+ obj.setflags(write=(write == 'w'))
a = self.array(obj.shape,
- ((order == "C" and intent.in_.c) or intent.in_), obj)
+ ((order == 'C' and intent.in_.c) or intent.in_), obj)
assert a.has_shared_memory()
def test_inout_2seq(self):
@@ -496,6 +552,9 @@ class TestSharedMemory:
def test_in_cache_from_2casttype_failure(self):
for t in self.type.all_types():
+ if t.NAME == 'STRING':
+ # string elsize is 0, so skipping the test
+ continue
if t.elsize >= self.type.elsize:
continue
obj = np.array(self.num2seq, dtype=t.dtype)