Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit f307cec

Browse filesBrowse files
authored
Merge pull request #9505 from eric-wieser/fix-issubdtype
BUG: issubdtype is inconsistent on types and dtypes
2 parents d653986 + 091b8c3 commit f307cec
Copy full SHA for f307cec

File tree

Expand file treeCollapse file tree

12 files changed

+97
-22
lines changed
Filter options
Expand file treeCollapse file tree

12 files changed

+97
-22
lines changed

‎doc/release/1.14.0-notes.rst

Copy file name to clipboardExpand all lines: doc/release/1.14.0-notes.rst
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,17 @@ Deprecations
2525
Future Changes
2626
==============
2727

28+
``np.issubdtype`` will stop downcasting dtype-like arguments
29+
------------------------------------------------------------
30+
It would be expected that ``issubdtype(np.float32, 'float64')`` and
31+
``issubdtype(np.float32, np.float64)`` mean the same thing - however, there
32+
was an undocumented special case that translated the former into
33+
``issubdtype(np.float32, np.floating)``, giving the surprising result of True.
34+
35+
This translation now gives a warning explaining what translation is occuring.
36+
In future, the translation will be disabled, and the first example will be made
37+
equivalent to the second.
38+
2839

2940
Build System Changes
3041
====================

‎numpy/core/function_base.py

Copy file name to clipboardExpand all lines: numpy/core/function_base.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ def geomspace(start, stop, num=50, endpoint=True, dtype=None):
339339
# complex and another is negative and log would produce NaN otherwise
340340
start = start + (stop - stop)
341341
stop = stop + (start - start)
342-
if _nx.issubdtype(dtype, complex):
342+
if _nx.issubdtype(dtype, _nx.complexfloating):
343343
start = start + 0j
344344
stop = stop + 0j
345345

‎numpy/core/numeric.py

Copy file name to clipboardExpand all lines: numpy/core/numeric.py
+1-2Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -436,8 +436,7 @@ def count_nonzero(a, axis=None):
436436
if issubdtype(a.dtype, np.number):
437437
return (a != 0).sum(axis=axis, dtype=np.intp)
438438

439-
if (issubdtype(a.dtype, np.string_) or
440-
issubdtype(a.dtype, np.unicode_)):
439+
if issubdtype(a.dtype, np.character):
441440
nullstr = a.dtype.type('')
442441
return (a != nullstr).sum(axis=axis, dtype=np.intp)
443442

‎numpy/core/numerictypes.py

Copy file name to clipboardExpand all lines: numpy/core/numerictypes.py
+36-9Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
import types as _types
8686
import sys
8787
import numbers
88+
import warnings
8889

8990
from numpy.compat import bytes, long
9091
from numpy.core.multiarray import (
@@ -739,20 +740,46 @@ def issubdtype(arg1, arg2):
739740
740741
Examples
741742
--------
742-
>>> np.issubdtype('S1', str)
743+
>>> np.issubdtype('S1', np.string_)
743744
True
744745
>>> np.issubdtype(np.float64, np.float32)
745746
False
746747
747748
"""
748-
if issubclass_(arg2, generic):
749-
return issubclass(dtype(arg1).type, arg2)
750-
mro = dtype(arg2).type.mro()
751-
if len(mro) > 1:
752-
val = mro[1]
753-
else:
754-
val = mro[0]
755-
return issubclass(dtype(arg1).type, val)
749+
if not issubclass_(arg1, generic):
750+
arg1 = dtype(arg1).type
751+
if not issubclass_(arg2, generic):
752+
arg2_orig = arg2
753+
arg2 = dtype(arg2).type
754+
if not isinstance(arg2_orig, dtype):
755+
# weird deprecated behaviour, that tried to infer np.floating from
756+
# float, and similar less obvious things, such as np.generic from
757+
# basestring
758+
mro = arg2.mro()
759+
arg2 = mro[1] if len(mro) > 1 else mro[0]
760+
761+
def type_repr(x):
762+
""" Helper to produce clear error messages """
763+
if not isinstance(x, type):
764+
return repr(x)
765+
elif issubclass(x, generic):
766+
return "np.{}".format(x.__name__)
767+
else:
768+
return x.__name__
769+
770+
# 1.14, 2017-08-01
771+
warnings.warn(
772+
"Conversion of the second argument of issubdtype from `{raw}` "
773+
"to `{abstract}` is deprecated. In future, it will be treated "
774+
"as `{concrete} == np.dtype({raw}).type`.".format(
775+
raw=type_repr(arg2_orig),
776+
abstract=type_repr(arg2),
777+
concrete=type_repr(dtype(arg2_orig).type)
778+
),
779+
FutureWarning, stacklevel=2
780+
)
781+
782+
return issubclass(arg1, arg2)
756783

757784

758785
# This dictionary allows look up based on any alias for an array data-type

‎numpy/core/tests/test_numerictypes.py

Copy file name to clipboardExpand all lines: numpy/core/tests/test_numerictypes.py
+32Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import division, absolute_import, print_function
22

33
import sys
4+
import itertools
45

56
import numpy as np
67
from numpy.testing import (
@@ -377,5 +378,36 @@ def test_return(self):
377378
res = self.ary[['f0', 'f2']].tolist()
378379
assert_(res == [(1, 3), (5, 7)])
379380

381+
382+
class TestIsSubDType(object):
383+
# scalar types can be promoted into dtypes
384+
wrappers = [np.dtype, lambda x: x]
385+
386+
def test_both_abstract(self):
387+
assert_(np.issubdtype(np.floating, np.inexact))
388+
assert_(not np.issubdtype(np.inexact, np.floating))
389+
390+
def test_same(self):
391+
for cls in (np.float32, np.int32):
392+
for w1, w2 in itertools.product(self.wrappers, repeat=2):
393+
assert_(np.issubdtype(w1(cls), w2(cls)))
394+
395+
def test_subclass(self):
396+
# note we cannot promote floating to a dtype, as it would turn into a
397+
# concrete type
398+
for w in self.wrappers:
399+
assert_(np.issubdtype(w(np.float32), np.floating))
400+
assert_(np.issubdtype(w(np.float64), np.floating))
401+
402+
def test_subclass_backwards(self):
403+
for w in self.wrappers:
404+
assert_(not np.issubdtype(np.floating, w(np.float32)))
405+
assert_(not np.issubdtype(np.floating, w(np.float64)))
406+
407+
def test_sibling_class(self):
408+
for w1, w2 in itertools.product(self.wrappers, repeat=2):
409+
assert_(not np.issubdtype(w1(np.float32), w2(np.float64)))
410+
assert_(not np.issubdtype(w1(np.float64), w2(np.float32)))
411+
380412
if __name__ == "__main__":
381413
run_module_suite()

‎numpy/doc/basics.py

Copy file name to clipboardExpand all lines: numpy/doc/basics.py
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,10 @@
114114
>>> d
115115
dtype('int32')
116116
117-
>>> np.issubdtype(d, int)
117+
>>> np.issubdtype(d, np.integer)
118118
True
119119
120-
>>> np.issubdtype(d, float)
120+
>>> np.issubdtype(d, np.floating)
121121
False
122122
123123

‎numpy/lib/_iotools.py

Copy file name to clipboardExpand all lines: numpy/lib/_iotools.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ class StringConverter(object):
527527
_mapper.append((nx.int64, int, -1))
528528

529529
_mapper.extend([(nx.floating, float, nx.nan),
530-
(complex, _bytes_to_complex, nx.nan + 0j),
530+
(nx.complexfloating, _bytes_to_complex, nx.nan + 0j),
531531
(nx.longdouble, nx.longdouble, nx.nan),
532532
(nx.string_, bytes, b'???')])
533533

‎numpy/lib/tests/test_function_base.py

Copy file name to clipboardExpand all lines: numpy/lib/tests/test_function_base.py
+4-4Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1711,16 +1711,16 @@ def test_type(self):
17111711
# Check the type of the returned histogram
17121712
a = np.arange(10) + .5
17131713
h, b = histogram(a)
1714-
assert_(np.issubdtype(h.dtype, int))
1714+
assert_(np.issubdtype(h.dtype, np.integer))
17151715

17161716
h, b = histogram(a, normed=True)
1717-
assert_(np.issubdtype(h.dtype, float))
1717+
assert_(np.issubdtype(h.dtype, np.floating))
17181718

17191719
h, b = histogram(a, weights=np.ones(10, int))
1720-
assert_(np.issubdtype(h.dtype, int))
1720+
assert_(np.issubdtype(h.dtype, np.integer))
17211721

17221722
h, b = histogram(a, weights=np.ones(10, float))
1723-
assert_(np.issubdtype(h.dtype, float))
1723+
assert_(np.issubdtype(h.dtype, np.floating))
17241724

17251725
def test_f32_rounding(self):
17261726
# gh-4799, check that the rounding of the edges works with float32

‎numpy/lib/tests/test_index_tricks.py

Copy file name to clipboardExpand all lines: numpy/lib/tests/test_index_tricks.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ def test_shape_and_dtype(self):
243243
for k, (a, sz) in enumerate(zip(arrays, sizes)):
244244
assert_equal(a.shape[k], sz)
245245
assert_(all(sh == 1 for j, sh in enumerate(a.shape) if j != k))
246-
assert_(np.issubdtype(a.dtype, int))
246+
assert_(np.issubdtype(a.dtype, np.integer))
247247

248248
def test_bool(self):
249249
bool_a = [True, False, True, True]

‎numpy/lib/tests/test_type_check.py

Copy file name to clipboardExpand all lines: numpy/lib/tests/test_type_check.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ class TestArrayConversion(object):
420420
def test_asfarray(self):
421421
a = asfarray(np.array([1, 2, 3]))
422422
assert_equal(a.__class__, np.ndarray)
423-
assert_(np.issubdtype(a.dtype, float))
423+
assert_(np.issubdtype(a.dtype, np.floating))
424424

425425
if __name__ == "__main__":
426426
run_module_suite()

‎numpy/matrixlib/defmatrix.py

Copy file name to clipboardExpand all lines: numpy/matrixlib/defmatrix.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ def matrix_power(M, n):
137137
M = asanyarray(M)
138138
if M.ndim != 2 or M.shape[0] != M.shape[1]:
139139
raise ValueError("input must be a square array")
140-
if not issubdtype(type(n), int):
140+
if not issubdtype(type(n), N.integer):
141141
raise TypeError("exponent must be an integer")
142142

143143
from numpy.linalg import inv

‎numpy/matrixlib/tests/test_defmatrix.py

Copy file name to clipboardExpand all lines: numpy/matrixlib/tests/test_defmatrix.py
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,12 @@ def test_pow(self):
249249
assert_array_almost_equal(m4, np.dot(m2, m2))
250250
assert_array_almost_equal(np.dot(mi, m), np.eye(2))
251251

252+
def test_scalar_type_pow(self):
253+
m = matrix([[1, 2], [3, 4]])
254+
for scalar_t in [np.int8, np.uint8]:
255+
two = scalar_t(2)
256+
assert_array_almost_equal(m ** 2, m ** two)
257+
252258
def test_notimplemented(self):
253259
'''Check that 'not implemented' operations produce a failure.'''
254260
A = matrix([[1., 2.],

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.