summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Wieser <wieser.eric@gmail.com>2017-12-06 22:50:27 -0800
committerEric Wieser <wieser.eric@gmail.com>2017-12-06 22:56:31 -0800
commitd4d9e9589efb352b40d25422d9f9b9b01e189fba (patch)
treed07894d52d78a1ebe95736ef5887b1b8d76dd8a2
parent058abc1e0e1f75921599050a98f3991b1230cb1b (diff)
downloadnumpy-d4d9e9589efb352b40d25422d9f9b9b01e189fba.tar.gz
MAINT: Use a StructSequence in place of the typeinfo tuples
This makes the contents of `typeinfo` look liked namedtuples
-rw-r--r--numpy/core/numerictypes.py8
-rw-r--r--numpy/core/setup.py2
-rw-r--r--numpy/core/src/multiarray/arraytypes.c.src166
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c8
-rw-r--r--numpy/core/src/multiarray/typeinfo.c114
-rw-r--r--numpy/core/src/multiarray/typeinfo.h19
-rw-r--r--numpy/f2py/tests/test_array_from_pyobj.py2
7 files changed, 225 insertions, 94 deletions
diff --git a/numpy/core/numerictypes.py b/numpy/core/numerictypes.py
index b61f5e7bc..c24e2b544 100644
--- a/numpy/core/numerictypes.py
+++ b/numpy/core/numerictypes.py
@@ -286,7 +286,7 @@ def bitname(obj):
def _add_types():
for a in typeinfo.keys():
name = english_lower(a)
- if isinstance(typeinfo[a], tuple):
+ if not isinstance(typeinfo[a], type):
typeobj = typeinfo[a][-1]
# define C-name and insert typenum and typechar references also
@@ -302,7 +302,7 @@ _add_types()
def _add_aliases():
for a in typeinfo.keys():
name = english_lower(a)
- if not isinstance(typeinfo[a], tuple):
+ if isinstance(typeinfo[a], type):
continue
typeobj = typeinfo[a][-1]
# insert bit-width version for this class (if relevant)
@@ -429,7 +429,7 @@ _sctype2char_dict = {}
def _construct_char_code_lookup():
for name in typeinfo.keys():
tup = typeinfo[name]
- if isinstance(tup, tuple):
+ if not isinstance(tup, type):
if tup[0] not in ['p', 'P']:
_sctype2char_dict[tup[-1]] = tup[0]
_construct_char_code_lookup()
@@ -777,7 +777,7 @@ _maxvals = _typedict()
_minvals = _typedict()
def _construct_lookups():
for name, val in typeinfo.items():
- if not isinstance(val, tuple):
+ if isinstance(val, type):
continue
obj = val[-1]
nbytes[obj] = val[2] // 8
diff --git a/numpy/core/setup.py b/numpy/core/setup.py
index 371df5bec..37631f3c4 100644
--- a/numpy/core/setup.py
+++ b/numpy/core/setup.py
@@ -750,6 +750,7 @@ def configuration(parent_package='',top_path=None):
join('src', 'multiarray', 'sequence.h'),
join('src', 'multiarray', 'shape.h'),
join('src', 'multiarray', 'strfuncs.h'),
+ join('src', 'multiarray', 'typeinfo.h'),
join('src', 'multiarray', 'ucsnarrow.h'),
join('src', 'multiarray', 'usertypes.h'),
join('src', 'multiarray', 'vdot.h'),
@@ -827,6 +828,7 @@ def configuration(parent_package='',top_path=None):
join('src', 'multiarray', 'scalartypes.c.src'),
join('src', 'multiarray', 'strfuncs.c'),
join('src', 'multiarray', 'temp_elide.c'),
+ join('src', 'multiarray', 'typeinfo.c'),
join('src', 'multiarray', 'usertypes.c'),
join('src', 'multiarray', 'ucsnarrow.c'),
join('src', 'multiarray', 'vdot.c'),
diff --git a/numpy/core/src/multiarray/arraytypes.c.src b/numpy/core/src/multiarray/arraytypes.c.src
index d0370fe6b..e8aa19416 100644
--- a/numpy/core/src/multiarray/arraytypes.c.src
+++ b/numpy/core/src/multiarray/arraytypes.c.src
@@ -24,6 +24,7 @@
#include "_datetime.h"
#include "arrayobject.h"
#include "alloc.h"
+#include "typeinfo.h"
#ifdef NPY_HAVE_SSE2_INTRINSICS
#include <emmintrin.h>
#endif
@@ -4820,21 +4821,19 @@ set_typeinfo(PyObject *dict)
* #cn = i*7, N, i, l, i, N, i#
*/
- PyDict_SetItemString(infodict, "@name@",
-#if defined(NPY_PY3K)
- s = Py_BuildValue("Ciii@cx@@cn@O",
-#else
- s = Py_BuildValue("ciii@cx@@cn@O",
-#endif
- NPY_@name@LTR,
- NPY_@name@,
- NPY_BITSOF_@uname@,
- _ALIGN(@type@),
- @max@,
- @min@,
- (PyObject *) &Py@Name@ArrType_Type));
+ s = PyArray_typeinforanged(
+ NPY_@name@LTR, NPY_@name@, NPY_BITSOF_@uname@, _ALIGN(@type@),
+ Py_BuildValue("@cx@", @max@),
+ Py_BuildValue("@cn@", @min@),
+ &Py@Name@ArrType_Type
+ );
+ if (s == NULL) {
+ return -1;
+ }
+ PyDict_SetItemString(infodict, "@name@", s);
Py_DECREF(s);
+
/**end repeat**/
@@ -4848,91 +4847,80 @@ set_typeinfo(PyObject *dict)
* CFloat, CDouble, CLongDouble#
* #num = 1, 1, 1, 1, 2, 2, 2#
*/
-
- PyDict_SetItemString(infodict, "@name@",
-#if defined(NPY_PY3K)
- s = Py_BuildValue("CiiiO", NPY_@name@LTR,
-#else
- s = Py_BuildValue("ciiiO", NPY_@name@LTR,
-#endif
- NPY_@name@,
- NPY_BITSOF_@name@,
- @num@ * _ALIGN(@type@) > NPY_MAX_COPY_ALIGNMENT ?
- NPY_MAX_COPY_ALIGNMENT : @num@ * _ALIGN(@type@),
- (PyObject *) &Py@Name@ArrType_Type));
+ s = PyArray_typeinfo(
+ NPY_@name@LTR, NPY_@name@, NPY_BITSOF_@name@,
+ @num@ * _ALIGN(@type@) > NPY_MAX_COPY_ALIGNMENT ?
+ NPY_MAX_COPY_ALIGNMENT : @num@ * _ALIGN(@type@),
+ &Py@Name@ArrType_Type
+ );
+ if (s == NULL) {
+ return -1;
+ }
+ PyDict_SetItemString(infodict, "@name@", s);
Py_DECREF(s);
/**end repeat**/
- PyDict_SetItemString(infodict, "OBJECT",
-#if defined(NPY_PY3K)
- s = Py_BuildValue("CiiiO", NPY_OBJECTLTR,
-#else
- s = Py_BuildValue("ciiiO", NPY_OBJECTLTR,
-#endif
- NPY_OBJECT,
- sizeof(PyObject *) * CHAR_BIT,
- _ALIGN(PyObject *),
- (PyObject *) &PyObjectArrType_Type));
+ s = PyArray_typeinfo(
+ NPY_OBJECTLTR, NPY_OBJECT, sizeof(PyObject *) * CHAR_BIT,
+ _ALIGN(PyObject *),
+ &PyObjectArrType_Type
+ );
+ if (s == NULL) {
+ return -1;
+ }
+ PyDict_SetItemString(infodict, "OBJECT", s);
Py_DECREF(s);
- PyDict_SetItemString(infodict, "STRING",
-#if defined(NPY_PY3K)
- s = Py_BuildValue("CiiiO", NPY_STRINGLTR,
-#else
- s = Py_BuildValue("ciiiO", NPY_STRINGLTR,
-#endif
- NPY_STRING,
- 0,
- _ALIGN(char),
- (PyObject *) &PyStringArrType_Type));
+ s = PyArray_typeinfo(
+ NPY_STRINGLTR, NPY_STRING, 0, _ALIGN(char),
+ &PyStringArrType_Type
+ );
+ if (s == NULL) {
+ return -1;
+ }
+ PyDict_SetItemString(infodict, "STRING", s);
Py_DECREF(s);
- PyDict_SetItemString(infodict, "UNICODE",
-#if defined(NPY_PY3K)
- s = Py_BuildValue("CiiiO", NPY_UNICODELTR,
-#else
- s = Py_BuildValue("ciiiO", NPY_UNICODELTR,
-#endif
- NPY_UNICODE,
- 0,
- _ALIGN(npy_ucs4),
- (PyObject *) &PyUnicodeArrType_Type));
+ s = PyArray_typeinfo(
+ NPY_UNICODELTR, NPY_UNICODE, 0, _ALIGN(npy_ucs4),
+ &PyUnicodeArrType_Type
+ );
+ if (s == NULL) {
+ return -1;
+ }
+ PyDict_SetItemString(infodict, "UNICODE", s);
Py_DECREF(s);
- PyDict_SetItemString(infodict, "VOID",
-#if defined(NPY_PY3K)
- s = Py_BuildValue("CiiiO", NPY_VOIDLTR,
-#else
- s = Py_BuildValue("ciiiO", NPY_VOIDLTR,
-#endif
- NPY_VOID,
- 0,
- _ALIGN(char),
- (PyObject *) &PyVoidArrType_Type));
+ s = PyArray_typeinfo(
+ NPY_VOIDLTR, NPY_VOID, 0, _ALIGN(char),
+ &PyVoidArrType_Type
+ );
+ if (s == NULL) {
+ return -1;
+ }
+ PyDict_SetItemString(infodict, "VOID", s);
Py_DECREF(s);
- PyDict_SetItemString(infodict, "DATETIME",
-#if defined(NPY_PY3K)
- s = Py_BuildValue("CiiiNNO", NPY_DATETIMELTR,
-#else
- s = Py_BuildValue("ciiiNNO", NPY_DATETIMELTR,
-#endif
- NPY_DATETIME,
- NPY_BITSOF_DATETIME,
- _ALIGN(npy_datetime),
- MyPyLong_FromInt64(NPY_MAX_DATETIME),
- MyPyLong_FromInt64(NPY_MIN_DATETIME),
- (PyObject *) &PyDatetimeArrType_Type));
+ s = PyArray_typeinforanged(
+ NPY_DATETIMELTR, NPY_DATETIME, NPY_BITSOF_DATETIME,
+ _ALIGN(npy_datetime),
+ MyPyLong_FromInt64(NPY_MAX_DATETIME),
+ MyPyLong_FromInt64(NPY_MIN_DATETIME),
+ &PyDatetimeArrType_Type
+ );
+ if (s == NULL) {
+ return -1;
+ }
+ PyDict_SetItemString(infodict, "DATETIME", s);
Py_DECREF(s);
- PyDict_SetItemString(infodict, "TIMEDELTA",
-#if defined(NPY_PY3K)
- s = Py_BuildValue("CiiiNNO", NPY_TIMEDELTALTR,
-#else
- s = Py_BuildValue("ciiiNNO",NPY_TIMEDELTALTR,
-#endif
- NPY_TIMEDELTA,
- NPY_BITSOF_TIMEDELTA,
- _ALIGN(npy_timedelta),
- MyPyLong_FromInt64(NPY_MAX_TIMEDELTA),
- MyPyLong_FromInt64(NPY_MIN_TIMEDELTA),
- (PyObject *)&PyTimedeltaArrType_Type));
+ s = PyArray_typeinforanged(
+ NPY_TIMEDELTALTR, NPY_TIMEDELTA, NPY_BITSOF_TIMEDELTA,
+ _ALIGN(npy_timedelta),
+ MyPyLong_FromInt64(NPY_MAX_TIMEDELTA),
+ MyPyLong_FromInt64(NPY_MIN_TIMEDELTA),
+ &PyTimedeltaArrType_Type
+ );
+ if (s == NULL) {
+ return -1;
+ }
+ PyDict_SetItemString(infodict, "TIMEDELTA", s);
Py_DECREF(s);
#define SETTYPE(name) \
diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c
index 8e7352e4f..00ea958ef 100644
--- a/numpy/core/src/multiarray/multiarraymodule.c
+++ b/numpy/core/src/multiarray/multiarraymodule.c
@@ -62,6 +62,7 @@ NPY_NO_EXPORT int NPY_NUMUSERTYPES = 0;
#include "compiled_base.h"
#include "mem_overlap.h"
#include "alloc.h"
+#include "typeinfo.h"
#include "get_attr_string.h"
@@ -4879,6 +4880,13 @@ PyMODINIT_FUNC initmultiarray(void) {
(PyObject *)&NpyBusDayCalendar_Type);
set_flaginfo(d);
+ /* Create the typeinfo types */
+ typeinfo_init_structsequences();
+ PyDict_SetItemString(d,
+ "typeinfo", (PyObject *)&PyArray_typeinfoType);
+ PyDict_SetItemString(d,
+ "typeinforanged", (PyObject *)&PyArray_typeinforangedType);
+
if (!intern_strings()) {
goto err;
}
diff --git a/numpy/core/src/multiarray/typeinfo.c b/numpy/core/src/multiarray/typeinfo.c
new file mode 100644
index 000000000..565524ed4
--- /dev/null
+++ b/numpy/core/src/multiarray/typeinfo.c
@@ -0,0 +1,114 @@
+/*
+ * Provides namedtuples for numpy.core.multiarray.typeinfo
+ * Unfortunately, we need two different types to cover the cases where min/max
+ * do and do not appear in the tuple.
+ */
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
+
+/* In python 2, this is not exported from Python.h */
+#include <structseq.h>
+
+#define NPY_NO_DEPRECATED_API NPY_API_VERSION
+#define _MULTIARRAYMODULE
+#include "npy_pycompat.h"
+
+
+PyTypeObject PyArray_typeinfoType;
+PyTypeObject PyArray_typeinforangedType;
+
+static PyStructSequence_Field typeinfo_fields[] = {
+ {"char", "The character used to represent the type"},
+ {"num", "The numeric id assigned to the type"},
+ {"bits", "The number of bits in the type"},
+ {"alignment", "The alignment of the type in bytes"},
+ {"type", "The python type object this info is about"},
+ {NULL, NULL,}
+};
+
+static PyStructSequence_Field typeinforanged_fields[] = {
+ {"char", "The character used to represent the type"},
+ {"num", "The numeric id assigned to the type"},
+ {"bits", "The number of bits in the type"},
+ {"alignment", "The alignment of the type in bytes"},
+ {"max", "The maximum value of this type"},
+ {"min", "The minimum value of this type"},
+ {"type", "The python type object this info is about"},
+ {NULL, NULL,}
+};
+
+static PyStructSequence_Desc typeinfo_desc = {
+ /* name */ "numpy.core.multiarray.typeinfo",
+ /* doc */ "Information about a scalar numpy type",
+ /* fields */ typeinfo_fields,
+ /* n_in_sequence */ 5,
+};
+
+static PyStructSequence_Desc typeinforanged_desc = {
+ /* name */ "numpy.core.multiarray.typeinforanged",
+ /* doc */ "Information about a scalar numpy type with a range",
+ /* fields */ typeinforanged_fields,
+ /* n_in_sequence */ 7,
+};
+
+PyObject *
+PyArray_typeinfo(
+ char typechar, int typenum, int nbits, int align,
+ PyTypeObject *type_obj)
+{
+ PyObject *entry = PyStructSequence_New(&PyArray_typeinfoType);
+ if (entry == NULL)
+ return NULL;
+#if defined(NPY_PY3K)
+ PyStructSequence_SET_ITEM(entry, 0, Py_BuildValue("C", typechar));
+#else
+ PyStructSequence_SET_ITEM(entry, 0, Py_BuildValue("c", typechar));
+#endif
+ PyStructSequence_SET_ITEM(entry, 1, Py_BuildValue("i", typenum));
+ PyStructSequence_SET_ITEM(entry, 2, Py_BuildValue("i", nbits));
+ PyStructSequence_SET_ITEM(entry, 3, Py_BuildValue("i", align));
+ PyStructSequence_SET_ITEM(entry, 4, Py_BuildValue("O", (PyObject *) type_obj));
+
+ if (PyErr_Occurred()) {
+ Py_DECREF(entry);
+ return NULL;
+ }
+
+ return entry;
+}
+
+PyObject *
+PyArray_typeinforanged(
+ char typechar, int typenum, int nbits, int align,
+ PyObject *max, PyObject *min, PyTypeObject *type_obj)
+{
+ PyObject *entry = PyStructSequence_New(&PyArray_typeinforangedType);
+ if (entry == NULL)
+ return NULL;
+#if defined(NPY_PY3K)
+ PyStructSequence_SET_ITEM(entry, 0, Py_BuildValue("C", typechar));
+#else
+ PyStructSequence_SET_ITEM(entry, 0, Py_BuildValue("c", typechar));
+#endif
+ PyStructSequence_SET_ITEM(entry, 1, Py_BuildValue("i", typenum));
+ PyStructSequence_SET_ITEM(entry, 2, Py_BuildValue("i", nbits));
+ PyStructSequence_SET_ITEM(entry, 3, Py_BuildValue("i", align));
+ PyStructSequence_SET_ITEM(entry, 4, max);
+ PyStructSequence_SET_ITEM(entry, 5, min);
+ PyStructSequence_SET_ITEM(entry, 6, Py_BuildValue("O", (PyObject *) type_obj));
+
+ if (PyErr_Occurred()) {
+ Py_DECREF(entry);
+ return NULL;
+ }
+
+ return entry;
+}
+
+void typeinfo_init_structsequences(void)
+{
+ PyStructSequence_InitType(
+ &PyArray_typeinfoType, &typeinfo_desc);
+ PyStructSequence_InitType(
+ &PyArray_typeinforangedType, &typeinforanged_desc);
+}
diff --git a/numpy/core/src/multiarray/typeinfo.h b/numpy/core/src/multiarray/typeinfo.h
new file mode 100644
index 000000000..5899c2093
--- /dev/null
+++ b/numpy/core/src/multiarray/typeinfo.h
@@ -0,0 +1,19 @@
+#ifndef _NPY_PRIVATE_TYPEINFO_H_
+#define _NPY_PRIVATE_TYPEINFO_H_
+
+void typeinfo_init_structsequences(void);
+
+extern PyTypeObject PyArray_typeinfoType;
+extern PyTypeObject PyArray_typeinforangedType;
+
+PyObject *
+PyArray_typeinfo(
+ char typechar, int typenum, int nbits, int align,
+ PyTypeObject *type_obj);
+
+PyObject *
+PyArray_typeinforanged(
+ char typechar, int typenum, int nbits, int align,
+ PyObject *max, PyObject *min, PyTypeObject *type_obj);
+
+#endif
diff --git a/numpy/f2py/tests/test_array_from_pyobj.py b/numpy/f2py/tests/test_array_from_pyobj.py
index 776ec3471..2a6d8eef5 100644
--- a/numpy/f2py/tests/test_array_from_pyobj.py
+++ b/numpy/f2py/tests/test_array_from_pyobj.py
@@ -141,7 +141,7 @@ class Type(object):
dtype0 = name
name = None
for n, i in typeinfo.items():
- if isinstance(i, tuple) and dtype0.type is i[-1]:
+ if not isinstance(i, type) and dtype0.type is i.type:
name = n
break
obj = cls._type_cache.get(name.upper(), None)