Skip to content

Commit

Permalink
Merge pull request #10151 from eric-wieser/integer-type-__name__
Browse files Browse the repository at this point in the history
BUG: Numpy scalar types sometimes have the same name
  • Loading branch information
mattip committed Sep 12, 2019
2 parents 842079e + fa09f5e commit 2f81858
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 7 deletions.
9 changes: 9 additions & 0 deletions doc/release/upcoming_changes/10151.improvement.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Different C numeric types of the same size have unique names
------------------------------------------------------------
On any given platform, two of ``np.intc``, ``np.int_``, and ``np.longlong``
would previously appear indistinguishable through their ``repr``, despite
having different properties when wrapped into ``dtype``s.
A similar problem existed for the unsigned counterparts to these types, and on
some plaforms for ``np.double`` and ``np.longdouble``

These types now always print with a unique ``__name__``.
30 changes: 30 additions & 0 deletions numpy/core/src/multiarray/scalartypes.c.src
Original file line number Diff line number Diff line change
Expand Up @@ -4492,6 +4492,36 @@ initialize_numeric_types(void)

PyArrayIter_Type.tp_iter = PyObject_SelfIter;
PyArrayMapIter_Type.tp_iter = PyObject_SelfIter;

/*
* Give types different names when they are the same size (gh-9799).
* `np.intX` always refers to the first int of that size in the sequence
* `['LONG', 'LONGLONG', 'INT', 'SHORT', 'BYTE']`.
*/
#if (NPY_SIZEOF_BYTE == NPY_SIZEOF_SHORT)
PyByteArrType_Type.tp_name = "numpy.byte";
PyUByteArrType_Type.tp_name = "numpy.ubyte";
#endif
#if (NPY_SIZEOF_SHORT == NPY_SIZEOF_INT)
PyShortArrType_Type.tp_name = "numpy.short";
PyUShortArrType_Type.tp_name = "numpy.ushort";
#endif
#if (NPY_SIZEOF_INT == NPY_SIZEOF_LONG)
PyIntArrType_Type.tp_name = "numpy.intc";
PyUIntArrType_Type.tp_name = "numpy.uintc";
#endif
#if (NPY_SIZEOF_LONGLONG == NPY_SIZEOF_LONG)
PyLongLongArrType_Type.tp_name = "numpy.longlong";
PyULongLongArrType_Type.tp_name = "numpy.ulonglong";
#endif

/*
Do the same for longdouble
*/
#if (NPY_SIZEOF_LONGDOUBLE == NPY_SIZEOF_DOUBLE)
PyLongDoubleArrType_Type.tp_name = "numpy.longdouble";
PyCLongDoubleArrType_Type.tp_name = "numpy.clongdouble";
#endif
}

typedef struct {
Expand Down
7 changes: 0 additions & 7 deletions numpy/core/tests/test_dtype.py
Original file line number Diff line number Diff line change
Expand Up @@ -963,13 +963,6 @@ def test_descr_has_trailing_void(self):
new_dtype = np.dtype(dtype.descr)
assert_equal(new_dtype.itemsize, 16)

@pytest.mark.parametrize('t', np.typeDict.values())
def test_name_builtin(self, t):
name = t.__name__
if name.endswith('_'):
name = name[:-1]
assert_equal(np.dtype(t).name, name)

def test_name_dtype_subclass(self):
# Ticket #4357
class user_def_subcls(np.void):
Expand Down
29 changes: 29 additions & 0 deletions numpy/core/tests/test_numerictypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,3 +498,32 @@ def test_platform_dependent_aliases(self):
assert_('int64' in np.int_.__doc__)
elif np.int64 is np.longlong:
assert_('int64' in np.longlong.__doc__)


class TestScalarTypeNames:
# gh-9799

numeric_types = [
np.byte, np.short, np.intc, np.int_, np.longlong,
np.ubyte, np.ushort, np.uintc, np.uint, np.ulonglong,
np.half, np.single, np.double, np.longdouble,
np.csingle, np.cdouble, np.clongdouble,
]

def test_names_are_unique(self):
# none of the above may be aliases for each other
assert len(set(self.numeric_types)) == len(self.numeric_types)

# names must be unique
names = [t.__name__ for t in self.numeric_types]
assert len(set(names)) == len(names)

@pytest.mark.parametrize('t', numeric_types)
def test_names_reflect_attributes(self, t):
""" Test that names correspond to where the type is under ``np.`` """
assert getattr(np, t.__name__) is t

@pytest.mark.parametrize('t', numeric_types)
def test_names_are_undersood_by_dtype(self, t):
""" Test the dtype constructor maps names back to the type """
assert np.dtype(t.__name__).type is t

0 comments on commit 2f81858

Please sign in to comment.