summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Wieser <wieser.eric@gmail.com>2018-09-11 21:14:57 -0700
committerEric Wieser <wieser.eric@gmail.com>2018-09-11 21:56:10 -0700
commit5cba7ca56aa83ce222b40dbfbb12f696d1a4ab75 (patch)
treebb5f2d2d4bff60146777414b5c9506937800f1a7
parent371cc4d604a58d01cc4f1057c8741620a7edca6f (diff)
downloadnumpy-5cba7ca56aa83ce222b40dbfbb12f696d1a4ab75.tar.gz
MAINT: Move np.dtype.name.__get__ to python
This shares a lot of code with part of `dtype.__repr__`, and it's helpful to get it all in one place. This fixes possible but unlikely segfaults if `PyUString_ConcatAndDel` fails.
-rw-r--r--numpy/core/_dtype.py33
-rw-r--r--numpy/core/src/multiarray/descriptor.c73
2 files changed, 40 insertions, 66 deletions
diff --git a/numpy/core/_dtype.py b/numpy/core/_dtype.py
index ca2c1eaff..7c79c6f5a 100644
--- a/numpy/core/_dtype.py
+++ b/numpy/core/_dtype.py
@@ -161,8 +161,14 @@ def _byte_order_str(dtype):
def _datetime_metadata_str(dtype):
- # This is a hack since the data is not exposed to python in any other way
- return dtype.name[dtype.name.rfind('['):]
+ # TODO: this duplicates the C append_metastr_to_string
+ unit, count = np.datetime_data(dtype)
+ if unit == 'generic':
+ return ''
+ elif count == 1:
+ return '[{}]'.format(unit)
+ else:
+ return '[{}{}]'.format(count, unit)
def _struct_dict_str(dtype, includealignedflag):
@@ -292,3 +298,26 @@ def _struct_repr(dtype):
return s
+def _name_get(dtype):
+ # provides dtype.name.__get__
+
+ if dtype.isbuiltin == 2:
+ # user dtypes don't promise to do anything special
+ return dtype.type.__name__
+
+ # Builtin classes are documented as returning a "bit name"
+ name = dtype.type.__name__
+
+ # handle bool_, str_, etc
+ if name[-1] == '_':
+ name = name[:-1]
+
+ # append bit counts to str, unicode, and void
+ if np.issubdtype(dtype, np.flexible) and not _isunsized(dtype):
+ name += "{}".format(dtype.itemsize * 8)
+
+ # append metadata to datetimes
+ elif dtype.type in (np.datetime64, np.timedelta64):
+ name += _datetime_metadata_str(dtype)
+
+ return name
diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c
index 8c8c0b61c..439980877 100644
--- a/numpy/core/src/multiarray/descriptor.c
+++ b/numpy/core/src/multiarray/descriptor.c
@@ -1859,72 +1859,17 @@ arraydescr_protocol_typestr_get(PyArray_Descr *self)
}
static PyObject *
-arraydescr_typename_get(PyArray_Descr *self)
+arraydescr_name_get(PyArray_Descr *self)
{
- static const char np_prefix[] = "numpy.";
- const int np_prefix_len = sizeof(np_prefix) - 1;
- PyTypeObject *typeobj = self->typeobj;
+ /* let python handle this */
+ PyObject *_numpy_dtype;
PyObject *res;
- char *s;
- int len;
- int prefix_len;
- int suffix_len;
-
- if (PyTypeNum_ISUSERDEF(self->type_num)) {
- s = strrchr(typeobj->tp_name, '.');
- if (s == NULL) {
- res = PyUString_FromString(typeobj->tp_name);
- }
- else {
- res = PyUString_FromStringAndSize(s + 1, strlen(s) - 1);
- }
- return res;
- }
- else {
- /*
- * NumPy type or subclass
- *
- * res is derived from typeobj->tp_name with the following rules:
- * - if starts with "numpy.", that prefix is removed
- * - if ends with "_", that suffix is removed
- */
- len = strlen(typeobj->tp_name);
-
- if (! strncmp(typeobj->tp_name, np_prefix, np_prefix_len)) {
- prefix_len = np_prefix_len;
- }
- else {
- prefix_len = 0;
- }
-
- if (typeobj->tp_name[len - 1] == '_') {
- suffix_len = 1;
- }
- else {
- suffix_len = 0;
- }
-
- len -= prefix_len;
- len -= suffix_len;
- res = PyUString_FromStringAndSize(typeobj->tp_name+prefix_len, len);
- }
- if (PyTypeNum_ISFLEXIBLE(self->type_num) && !PyDataType_ISUNSIZED(self)) {
- PyObject *p;
- p = PyUString_FromFormat("%d", self->elsize * 8);
- PyUString_ConcatAndDel(&res, p);
- }
- if (PyDataType_ISDATETIME(self)) {
- PyArray_DatetimeMetaData *meta;
-
- meta = get_datetime_metadata_from_dtype(self);
- if (meta == NULL) {
- Py_DECREF(res);
- return NULL;
- }
-
- res = append_metastr_to_string(meta, 0, res);
+ _numpy_dtype = PyImport_ImportModule("numpy.core._dtype");
+ if (_numpy_dtype == NULL) {
+ return NULL;
}
-
+ res = PyObject_CallMethod(_numpy_dtype, "_name_get", "O", self);
+ Py_DECREF(_numpy_dtype);
return res;
}
@@ -2218,7 +2163,7 @@ static PyGetSetDef arraydescr_getsets[] = {
(getter)arraydescr_protocol_typestr_get,
NULL, NULL, NULL},
{"name",
- (getter)arraydescr_typename_get,
+ (getter)arraydescr_name_get,
NULL, NULL, NULL},
{"base",
(getter)arraydescr_base_get,