1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
"""
Various richly-typed exceptions, that also help us deal with string formatting
in python where it's easier.
By putting the formatting in `__str__`, we also avoid paying the cost for
users who silence the exceptions.
"""
from numpy.core.overrides import set_module
def _unpack_tuple(tup):
if len(tup) == 1:
return tup[0]
else:
return tup
def _display_as_base(cls):
"""
A decorator that makes an exception class look like its base.
We use this to hide subclasses that are implementation details - the user
should catch the base type, which is what the traceback will show them.
Classes decorated with this decorator are subject to removal without a
deprecation warning.
"""
assert issubclass(cls, Exception)
cls.__name__ = cls.__base__.__name__
cls.__qualname__ = cls.__base__.__qualname__
set_module(cls.__base__.__module__)(cls)
return cls
class UFuncTypeError(TypeError):
""" Base class for all ufunc exceptions """
def __init__(self, ufunc):
self.ufunc = ufunc
@_display_as_base
class _UFuncBinaryResolutionError(UFuncTypeError):
""" Thrown when a binary resolution fails """
def __init__(self, ufunc, dtypes):
super().__init__(ufunc)
self.dtypes = tuple(dtypes)
assert len(self.dtypes) == 2
def __str__(self):
return (
"ufunc {!r} cannot use operands with types {!r} and {!r}"
).format(
self.ufunc.__name__, *self.dtypes
)
@_display_as_base
class _UFuncNoLoopError(UFuncTypeError):
""" Thrown when a ufunc loop cannot be found """
def __init__(self, ufunc, dtypes):
super().__init__(ufunc)
self.dtypes = tuple(dtypes)
def __str__(self):
return (
"ufunc {!r} did not contain a loop with signature matching types "
"{!r} -> {!r}"
).format(
self.ufunc.__name__,
_unpack_tuple(self.dtypes[:self.ufunc.nin]),
_unpack_tuple(self.dtypes[self.ufunc.nin:])
)
@_display_as_base
class _UFuncCastingError(UFuncTypeError):
def __init__(self, ufunc, casting, from_, to):
super().__init__(ufunc)
self.casting = casting
self.from_ = from_
self.to = to
@_display_as_base
class _UFuncInputCastingError(_UFuncCastingError):
""" Thrown when a ufunc input cannot be casted """
def __init__(self, ufunc, casting, from_, to, i):
super().__init__(ufunc, casting, from_, to)
self.in_i = i
def __str__(self):
# only show the number if more than one input exists
i_str = "{} ".format(self.in_i) if self.ufunc.nin != 1 else ""
return (
"Cannot cast ufunc {!r} input {}from {!r} to {!r} with casting "
"rule {!r}"
).format(
self.ufunc.__name__, i_str, self.from_, self.to, self.casting
)
@_display_as_base
class _UFuncOutputCastingError(_UFuncCastingError):
""" Thrown when a ufunc output cannot be casted """
def __init__(self, ufunc, casting, from_, to, i):
super().__init__(ufunc, casting, from_, to)
self.out_i = i
def __str__(self):
# only show the number if more than one output exists
i_str = "{} ".format(self.out_i) if self.ufunc.nout != 1 else ""
return (
"Cannot cast ufunc {!r} output {}from {!r} to {!r} with casting "
"rule {!r}"
).format(
self.ufunc.__name__, i_str, self.from_, self.to, self.casting
)
# Exception used in shares_memory()
@set_module('numpy')
class TooHardError(RuntimeError):
pass
@set_module('numpy')
class AxisError(ValueError, IndexError):
""" Axis supplied was invalid. """
def __init__(self, axis, ndim=None, msg_prefix=None):
# single-argument form just delegates to base class
if ndim is None and msg_prefix is None:
msg = axis
# do the string formatting here, to save work in the C code
else:
msg = ("axis {} is out of bounds for array of dimension {}"
.format(axis, ndim))
if msg_prefix is not None:
msg = "{}: {}".format(msg_prefix, msg)
super(AxisError, self).__init__(msg)
@_display_as_base
class _ArrayMemoryError(MemoryError):
""" Thrown when an array cannot be allocated"""
def __init__(self, shape, dtype):
self.shape = shape
self.dtype = dtype
def __str__(self):
return "Unable to allocate array with shape {} and data type {}".format(self.shape, self.dtype)
|