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
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-09 06:12 +0000
1"""
2Functions for changing global ufunc configuration
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
12from .._utils import set_module
13from .umath import _make_extobj, _get_extobj_dict, _extobj_contextvar
15__all__ = [
16 "seterr", "geterr", "setbufsize", "getbufsize", "seterrcall", "geterrcall",
17 "errstate", '_no_nep50_warning'
18]
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.
26 Note that operations on integer scalar types (such as `int16`) are
27 handled like floating point, and are affected by these settings.
29 Parameters
30 ----------
31 all : {'ignore', 'warn', 'raise', 'call', 'print', 'log'}, optional
32 Set treatment for all types of floating-point errors at once:
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`.
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.
52 Returns
53 -------
54 old_settings : dict
55 Dictionary containing the old settings.
57 See also
58 --------
59 seterrcall : Set a callback function for the 'call' mode.
60 geterr, geterrcall, errstate
62 Notes
63 -----
64 The floating-point exceptions are defined in the IEEE 754 standard [1]_:
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.
73 .. [1] https://en.wikipedia.org/wiki/IEEE_754
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
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'}
96 """
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)
103 extobj = _make_extobj(
104 all=all, divide=divide, over=over, under=under, invalid=invalid)
105 _extobj_contextvar.set(extobj)
106 return old
109@set_module('numpy')
110def geterr():
111 """
112 Get the current way of handling floating-point errors.
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.
122 See Also
123 --------
124 geterrcall, seterr, seterrcall
126 Notes
127 -----
128 For complete documentation of the types of floating-point exceptions and
129 treatment options, see `seterr`.
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
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
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
156@set_module('numpy')
157def setbufsize(size):
158 """
159 Set the size of the buffer used in ufuncs.
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.
165 Parameters
166 ----------
167 size : int
168 Size of buffer.
170 """
171 old = _get_extobj_dict()["bufsize"]
172 extobj = _make_extobj(bufsize=size)
173 _extobj_contextvar.set(extobj)
174 return old
177@set_module('numpy')
178def getbufsize():
179 """
180 Return the size of the buffer used in ufuncs.
182 Returns
183 -------
184 getbufsize : int
185 Size of ufunc buffer in bytes.
187 """
188 return _get_extobj_dict()["bufsize"]
191@set_module('numpy')
192def seterrcall(func):
193 """
194 Set the floating-point error callback function or log object.
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.
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.
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).
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"::
216 [0 0 0 0 divide over under invalid]
218 In other words, ``flags = divide + 2*over + 4*under + 8*invalid``.
220 If an object is provided, its write method should take one argument,
221 a string.
223 Returns
224 -------
225 h : callable, log instance or None
226 The old error handler.
228 See Also
229 --------
230 seterr, geterr, geterrcall
232 Examples
233 --------
234 Callback upon error:
236 >>> def err_handler(type, flag):
237 ... print("Floating point error (%s), with flag %s" % (type, flag))
238 ...
240 >>> orig_handler = np.seterrcall(err_handler)
241 >>> orig_err = np.seterr(all='call')
243 >>> np.array([1, 2, 3]) / 0.0
244 Floating point error (divide by zero), with flag 1
245 array([inf, inf, inf])
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'}
252 Log error message:
254 >>> class Log:
255 ... def write(self, msg):
256 ... print("LOG: %s" % msg)
257 ...
259 >>> log = Log()
260 >>> saved_handler = np.seterrcall(log)
261 >>> save_err = np.seterr(all='log')
263 >>> np.array([1, 2, 3]) / 0.0
264 LOG: Warning: divide by zero encountered in divide
265 array([inf, inf, inf])
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'}
272 """
273 old = _get_extobj_dict()["call"]
274 extobj = _make_extobj(call=func)
275 _extobj_contextvar.set(extobj)
276 return old
279@set_module('numpy')
280def geterrcall():
281 """
282 Return the current callback function used on floating-point errors.
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`.
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.
296 See Also
297 --------
298 seterrcall, seterr, geterr
300 Notes
301 -----
302 For complete documentation of the types of floating-point exceptions and
303 treatment options, see `seterr`.
305 Examples
306 --------
307 >>> np.geterrcall() # we did not yet set a handler, returns None
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])
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
323 """
324 return _get_extobj_dict()["call"]
327class _unspecified:
328 pass
331_Unspecified = _unspecified()
334@set_module('numpy')
335class errstate:
336 """
337 errstate(**kwargs)
339 Context manager for floating-point error handling.
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.
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.
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``.
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'}.
363 See Also
364 --------
365 seterr, geterr, seterrcall, geterrcall
367 Notes
368 -----
369 For complete documentation of the types of floating-point exceptions and
370 treatment options, see `seterr`.
372 Examples
373 --------
374 >>> olderr = np.seterr(all='ignore') # Set error handling to known state.
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])
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
390 Outside the context the error handling behavior has not changed:
392 >>> np.geterr()
393 {'divide': 'ignore', 'over': 'ignore', 'under': 'ignore', 'invalid': 'ignore'}
394 >>> olderr = np.seterr(**olderr) # restore original state
396 """
397 __slots__ = (
398 "_call", "_all", "_divide", "_over", "_under", "_invalid", "_token")
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
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)
424 self._token = _extobj_contextvar.set(extobj)
426 def __exit__(self, *exc_info):
427 _extobj_contextvar.reset(self._token)
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)
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)
453 return inner
456NO_NEP50_WARNING = contextvars.ContextVar("_no_nep50_warning", default=False)
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).
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)