Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/numpy/_core/_ufunc_config.py: 56%

81 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-09 06:12 +0000

1""" 

2Functions for changing global ufunc configuration 

3 

4This provides helpers which wrap `_get_extobj_dict` and `_make_extobj`, and 

5`_extobj_contextvar` from umath. 

6""" 

7import collections.abc 

8import contextlib 

9import contextvars 

10import functools 

11 

12from .._utils import set_module 

13from .umath import _make_extobj, _get_extobj_dict, _extobj_contextvar 

14 

15__all__ = [ 

16 "seterr", "geterr", "setbufsize", "getbufsize", "seterrcall", "geterrcall", 

17 "errstate", '_no_nep50_warning' 

18] 

19 

20 

21@set_module('numpy') 

22def seterr(all=None, divide=None, over=None, under=None, invalid=None): 

23 """ 

24 Set how floating-point errors are handled. 

25 

26 Note that operations on integer scalar types (such as `int16`) are 

27 handled like floating point, and are affected by these settings. 

28 

29 Parameters 

30 ---------- 

31 all : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional 

32 Set treatment for all types of floating-point errors at once: 

33 

34 - ignore: Take no action when the exception occurs. 

35 - warn: Print a :exc:`RuntimeWarning` (via the Python `warnings` 

36 module). 

37 - raise: Raise a :exc:`FloatingPointError`. 

38 - call: Call a function specified using the `seterrcall` function. 

39 - print: Print a warning directly to ``stdout``. 

40 - log: Record error in a Log object specified by `seterrcall`. 

41 

42 The default is not to change the current behavior. 

43 divide : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional 

44 Treatment for division by zero. 

45 over : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional 

46 Treatment for floating-point overflow. 

47 under : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional 

48 Treatment for floating-point underflow. 

49 invalid : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional 

50 Treatment for invalid floating-point operation. 

51 

52 Returns 

53 ------- 

54 old_settings : dict 

55 Dictionary containing the old settings. 

56 

57 See also 

58 -------- 

59 seterrcall : Set a callback function for the 'call' mode. 

60 geterr, geterrcall, errstate 

61 

62 Notes 

63 ----- 

64 The floating-point exceptions are defined in the IEEE 754 standard [1]_: 

65 

66 - Division by zero: infinite result obtained from finite numbers. 

67 - Overflow: result too large to be expressed. 

68 - Underflow: result so close to zero that some precision 

69 was lost. 

70 - Invalid operation: result is not an expressible number, typically 

71 indicates that a NaN was produced. 

72 

73 .. [1] https://en.wikipedia.org/wiki/IEEE_754 

74 

75 Examples 

76 -------- 

77 >>> orig_settings = np.seterr(all='ignore') # seterr to known value 

78 >>> np.int16(32000) * np.int16(3) 

79 30464 

80 >>> np.seterr(over='raise') 

81 {'divide': 'ignore', 'over': 'ignore', 'under': 'ignore', 'invalid': 'ignore'} 

82 >>> old_settings = np.seterr(all='warn', over='raise') 

83 >>> np.int16(32000) * np.int16(3) 

84 Traceback (most recent call last): 

85 File "<stdin>", line 1, in <module> 

86 FloatingPointError: overflow encountered in scalar multiply 

87 

88 >>> old_settings = np.seterr(all='print') 

89 >>> np.geterr() 

90 {'divide': 'print', 'over': 'print', 'under': 'print', 'invalid': 'print'} 

91 >>> np.int16(32000) * np.int16(3) 

92 30464 

93 >>> np.seterr(**orig_settings) # restore original 

94 {'divide': 'print', 'over': 'print', 'under': 'print', 'invalid': 'print'} 

95 

96 """ 

97 

98 old = _get_extobj_dict() 

99 # The errstate doesn't include call and bufsize, so pop them: 

100 old.pop("call", None) 

101 old.pop("bufsize", None) 

102 

103 extobj = _make_extobj( 

104 all=all, divide=divide, over=over, under=under, invalid=invalid) 

105 _extobj_contextvar.set(extobj) 

106 return old 

107 

108 

109@set_module('numpy') 

110def geterr(): 

111 """ 

112 Get the current way of handling floating-point errors. 

113 

114 Returns 

115 ------- 

116 res : dict 

117 A dictionary with keys "divide", "over", "under", and "invalid", 

118 whose values are from the strings "ignore", "print", "log", "warn", 

119 "raise", and "call". The keys represent possible floating-point 

120 exceptions, and the values define how these exceptions are handled. 

121 

122 See Also 

123 -------- 

124 geterrcall, seterr, seterrcall 

125 

126 Notes 

127 ----- 

128 For complete documentation of the types of floating-point exceptions and 

129 treatment options, see `seterr`. 

130 

131 Examples 

132 -------- 

133 >>> np.geterr() 

134 {'divide': 'warn', 'over': 'warn', 'under': 'ignore', 'invalid': 'warn'} 

135 >>> np.arange(3.) / np.arange(3.) # doctest: +SKIP 

136 array([nan, 1., 1.]) 

137 RuntimeWarning: invalid value encountered in divide 

138 

139 >>> oldsettings = np.seterr(all='warn', invalid='raise') 

140 >>> np.geterr() 

141 {'divide': 'warn', 'over': 'warn', 'under': 'warn', 'invalid': 'raise'} 

142 >>> np.arange(3.) / np.arange(3.) 

143 Traceback (most recent call last): 

144 ... 

145 FloatingPointError: invalid value encountered in divide 

146 >>> oldsettings = np.seterr(**oldsettings) # restore original 

147 

148 """ 

149 res = _get_extobj_dict() 

150 # The "geterr" doesn't include call and bufsize,: 

151 res.pop("call", None) 

152 res.pop("bufsize", None) 

153 return res 

154 

155 

156@set_module('numpy') 

157def setbufsize(size): 

158 """ 

159 Set the size of the buffer used in ufuncs. 

160 

161 .. versionchanged:: 2.0 

162 The scope of setting the buffer is tied to the `numpy.errstate` 

163 context. Exiting a ``with errstate():`` will also restore the bufsize. 

164 

165 Parameters 

166 ---------- 

167 size : int 

168 Size of buffer. 

169 

170 """ 

171 old = _get_extobj_dict()["bufsize"] 

172 extobj = _make_extobj(bufsize=size) 

173 _extobj_contextvar.set(extobj) 

174 return old 

175 

176 

177@set_module('numpy') 

178def getbufsize(): 

179 """ 

180 Return the size of the buffer used in ufuncs. 

181 

182 Returns 

183 ------- 

184 getbufsize : int 

185 Size of ufunc buffer in bytes. 

186 

187 """ 

188 return _get_extobj_dict()["bufsize"] 

189 

190 

191@set_module('numpy') 

192def seterrcall(func): 

193 """ 

194 Set the floating-point error callback function or log object. 

195 

196 There are two ways to capture floating-point error messages. The first 

197 is to set the error-handler to 'call', using `seterr`. Then, set 

198 the function to call using this function. 

199 

200 The second is to set the error-handler to 'log', using `seterr`. 

201 Floating-point errors then trigger a call to the 'write' method of 

202 the provided object. 

203 

204 Parameters 

205 ---------- 

206 func : callable f(err, flag) or object with write method 

207 Function to call upon floating-point errors ('call'-mode) or 

208 object whose 'write' method is used to log such message ('log'-mode). 

209 

210 The call function takes two arguments. The first is a string describing 

211 the type of error (such as "divide by zero", "overflow", "underflow", 

212 or "invalid value"), and the second is the status flag. The flag is a 

213 byte, whose four least-significant bits indicate the type of error, one 

214 of "divide", "over", "under", "invalid":: 

215 

216 [0 0 0 0 divide over under invalid] 

217 

218 In other words, ``flags = divide + 2*over + 4*under + 8*invalid``. 

219 

220 If an object is provided, its write method should take one argument, 

221 a string. 

222 

223 Returns 

224 ------- 

225 h : callable, log instance or None 

226 The old error handler. 

227 

228 See Also 

229 -------- 

230 seterr, geterr, geterrcall 

231 

232 Examples 

233 -------- 

234 Callback upon error: 

235 

236 >>> def err_handler(type, flag): 

237 ... print("Floating point error (%s), with flag %s" % (type, flag)) 

238 ... 

239 

240 >>> orig_handler = np.seterrcall(err_handler) 

241 >>> orig_err = np.seterr(all='call') 

242 

243 >>> np.array([1, 2, 3]) / 0.0 

244 Floating point error (divide by zero), with flag 1 

245 array([inf, inf, inf]) 

246 

247 >>> np.seterrcall(orig_handler) 

248 <function err_handler at 0x...> 

249 >>> np.seterr(**orig_err) 

250 {'divide': 'call', 'over': 'call', 'under': 'call', 'invalid': 'call'} 

251 

252 Log error message: 

253 

254 >>> class Log: 

255 ... def write(self, msg): 

256 ... print("LOG: %s" % msg) 

257 ... 

258 

259 >>> log = Log() 

260 >>> saved_handler = np.seterrcall(log) 

261 >>> save_err = np.seterr(all='log') 

262 

263 >>> np.array([1, 2, 3]) / 0.0 

264 LOG: Warning: divide by zero encountered in divide 

265 array([inf, inf, inf]) 

266 

267 >>> np.seterrcall(orig_handler) 

268 <numpy.Log object at 0x...> 

269 >>> np.seterr(**orig_err) 

270 {'divide': 'log', 'over': 'log', 'under': 'log', 'invalid': 'log'} 

271 

272 """ 

273 old = _get_extobj_dict()["call"] 

274 extobj = _make_extobj(call=func) 

275 _extobj_contextvar.set(extobj) 

276 return old 

277 

278 

279@set_module('numpy') 

280def geterrcall(): 

281 """ 

282 Return the current callback function used on floating-point errors. 

283 

284 When the error handling for a floating-point error (one of "divide", 

285 "over", "under", or "invalid") is set to 'call' or 'log', the function 

286 that is called or the log instance that is written to is returned by 

287 `geterrcall`. This function or log instance has been set with 

288 `seterrcall`. 

289 

290 Returns 

291 ------- 

292 errobj : callable, log instance or None 

293 The current error handler. If no handler was set through `seterrcall`, 

294 ``None`` is returned. 

295 

296 See Also 

297 -------- 

298 seterrcall, seterr, geterr 

299 

300 Notes 

301 ----- 

302 For complete documentation of the types of floating-point exceptions and 

303 treatment options, see `seterr`. 

304 

305 Examples 

306 -------- 

307 >>> np.geterrcall() # we did not yet set a handler, returns None 

308 

309 >>> orig_settings = np.seterr(all='call') 

310 >>> def err_handler(type, flag): 

311 ... print("Floating point error (%s), with flag %s" % (type, flag)) 

312 >>> old_handler = np.seterrcall(err_handler) 

313 >>> np.array([1, 2, 3]) / 0.0 

314 Floating point error (divide by zero), with flag 1 

315 array([inf, inf, inf]) 

316 

317 >>> cur_handler = np.geterrcall() 

318 >>> cur_handler is err_handler 

319 True 

320 >>> old_settings = np.seterr(**orig_settings) # restore original 

321 >>> old_handler = np.seterrcall(None) # restore original 

322 

323 """ 

324 return _get_extobj_dict()["call"] 

325 

326 

327class _unspecified: 

328 pass 

329 

330 

331_Unspecified = _unspecified() 

332 

333 

334@set_module('numpy') 

335class errstate: 

336 """ 

337 errstate(**kwargs) 

338 

339 Context manager for floating-point error handling. 

340 

341 Using an instance of `errstate` as a context manager allows statements in 

342 that context to execute with a known error handling behavior. Upon entering 

343 the context the error handling is set with `seterr` and `seterrcall`, and 

344 upon exiting it is reset to what it was before. 

345 

346 .. versionchanged:: 1.17.0 

347 `errstate` is also usable as a function decorator, saving 

348 a level of indentation if an entire function is wrapped. 

349 

350 .. versionchanged:: 2.0 

351 `errstate` is now fully thread and asyncio safe, but may not be 

352 entered more than once. 

353 It is not safe to decorate async functions using ``errstate``. 

354 

355 Parameters 

356 ---------- 

357 kwargs : {divide, over, under, invalid} 

358 Keyword arguments. The valid keywords are the possible floating-point 

359 exceptions. Each keyword should have a string value that defines the 

360 treatment for the particular error. Possible values are 

361 {'ignore', 'warn', 'raise', 'call', 'print', 'log'}. 

362 

363 See Also 

364 -------- 

365 seterr, geterr, seterrcall, geterrcall 

366 

367 Notes 

368 ----- 

369 For complete documentation of the types of floating-point exceptions and 

370 treatment options, see `seterr`. 

371 

372 Examples 

373 -------- 

374 >>> olderr = np.seterr(all='ignore') # Set error handling to known state. 

375 

376 >>> np.arange(3) / 0. 

377 array([nan, inf, inf]) 

378 >>> with np.errstate(divide='ignore'): 

379 ... np.arange(3) / 0. 

380 array([nan, inf, inf]) 

381 

382 >>> np.sqrt(-1) 

383 np.float64(nan) 

384 >>> with np.errstate(invalid='raise'): 

385 ... np.sqrt(-1) 

386 Traceback (most recent call last): 

387 File "<stdin>", line 2, in <module> 

388 FloatingPointError: invalid value encountered in sqrt 

389 

390 Outside the context the error handling behavior has not changed: 

391 

392 >>> np.geterr() 

393 {'divide': 'ignore', 'over': 'ignore', 'under': 'ignore', 'invalid': 'ignore'} 

394 >>> olderr = np.seterr(**olderr) # restore original state 

395 

396 """ 

397 __slots__ = ( 

398 "_call", "_all", "_divide", "_over", "_under", "_invalid", "_token") 

399 

400 def __init__(self, *, call=_Unspecified, 

401 all=None, divide=None, over=None, under=None, invalid=None): 

402 self._token = None 

403 self._call = call 

404 self._all = all 

405 self._divide = divide 

406 self._over = over 

407 self._under = under 

408 self._invalid = invalid 

409 

410 def __enter__(self): 

411 # Note that __call__ duplicates much of this logic 

412 if self._token is not None: 

413 raise TypeError("Cannot enter `np.errstate` twice.") 

414 if self._call is _Unspecified: 

415 extobj = _make_extobj( 

416 all=self._all, divide=self._divide, over=self._over, 

417 under=self._under, invalid=self._invalid) 

418 else: 

419 extobj = _make_extobj( 

420 call=self._call, 

421 all=self._all, divide=self._divide, over=self._over, 

422 under=self._under, invalid=self._invalid) 

423 

424 self._token = _extobj_contextvar.set(extobj) 

425 

426 def __exit__(self, *exc_info): 

427 _extobj_contextvar.reset(self._token) 

428 

429 def __call__(self, func): 

430 # We need to customize `__call__` compared to `ContextDecorator` 

431 # because we must store the token per-thread so cannot store it on 

432 # the instance (we could create a new instance for this). 

433 # This duplicates the code from `__enter__`. 

434 @functools.wraps(func) 

435 def inner(*args, **kwargs): 

436 if self._call is _Unspecified: 

437 extobj = _make_extobj( 

438 all=self._all, divide=self._divide, over=self._over, 

439 under=self._under, invalid=self._invalid) 

440 else: 

441 extobj = _make_extobj( 

442 call=self._call, 

443 all=self._all, divide=self._divide, over=self._over, 

444 under=self._under, invalid=self._invalid) 

445 

446 _token = _extobj_contextvar.set(extobj) 

447 try: 

448 # Call the original, decorated, function: 

449 return func(*args, **kwargs) 

450 finally: 

451 _extobj_contextvar.reset(_token) 

452 

453 return inner 

454 

455 

456NO_NEP50_WARNING = contextvars.ContextVar("_no_nep50_warning", default=False) 

457 

458@set_module('numpy') 

459@contextlib.contextmanager 

460def _no_nep50_warning(): 

461 """ 

462 Context manager to disable NEP 50 warnings. This context manager is 

463 only relevant if the NEP 50 warnings are enabled globally (which is not 

464 thread/context safe). 

465 

466 This warning context manager itself is fully safe, however. 

467 """ 

468 token = NO_NEP50_WARNING.set(True) 

469 try: 

470 yield 

471 finally: 

472 NO_NEP50_WARNING.reset(token)