Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

""" 

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 

 

@property 

def _total_size(self): 

num_bytes = self.dtype.itemsize 

for dim in self.shape: 

num_bytes *= dim 

return num_bytes 

 

@staticmethod 

def _size_to_string(num_bytes): 

""" Convert a number of bytes into a binary size string """ 

 

# https://en.wikipedia.org/wiki/Binary_prefix 

LOG2_STEP = 10 

STEP = 1024 

units = ['bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB'] 

 

unit_i = max(num_bytes.bit_length() - 1, 1) // LOG2_STEP 

unit_val = 1 << (unit_i * LOG2_STEP) 

n_units = num_bytes / unit_val 

del unit_val 

 

# ensure we pick a unit that is correct after rounding 

if round(n_units) == STEP: 

unit_i += 1 

n_units /= STEP 

 

# deal with sizes so large that we don't have units for them 

if unit_i >= len(units): 

new_unit_i = len(units) - 1 

n_units *= 1 << ((unit_i - new_unit_i) * LOG2_STEP) 

unit_i = new_unit_i 

 

unit_name = units[unit_i] 

# format with a sensible number of digits 

if unit_i == 0: 

# no decimal point on bytes 

return '{:.0f} {}'.format(n_units, unit_name) 

elif round(n_units) < 1000: 

# 3 significant figures, if none are dropped to the left of the . 

return '{:#.3g} {}'.format(n_units, unit_name) 

else: 

# just give all the digits otherwise 

return '{:#.0f} {}'.format(n_units, unit_name) 

 

def __str__(self): 

size_str = self._size_to_string(self._total_size) 

return ( 

"Unable to allocate {} for an array with shape {} and data type {}" 

.format(size_str, self.shape, self.dtype) 

)