ยปCore Development>Code coverage>Lib/warnings.py

Python code coverage for Lib/warnings.py

#countcontent
1n/a"""Python part of the warnings subsystem."""
2n/a
3n/aimport sys
4n/a
5n/a
6n/a__all__ = ["warn", "warn_explicit", "showwarning",
7n/a "formatwarning", "filterwarnings", "simplefilter",
8n/a "resetwarnings", "catch_warnings"]
9n/a
10n/adef showwarning(message, category, filename, lineno, file=None, line=None):
11n/a """Hook to write a warning to a file; replace if you like."""
12n/a msg = WarningMessage(message, category, filename, lineno, file, line)
13n/a _showwarnmsg_impl(msg)
14n/a
15n/adef formatwarning(message, category, filename, lineno, line=None):
16n/a """Function to format a warning the standard way."""
17n/a msg = WarningMessage(message, category, filename, lineno, None, line)
18n/a return _formatwarnmsg_impl(msg)
19n/a
20n/adef _showwarnmsg_impl(msg):
21n/a file = msg.file
22n/a if file is None:
23n/a file = sys.stderr
24n/a if file is None:
25n/a # sys.stderr is None when run with pythonw.exe:
26n/a # warnings get lost
27n/a return
28n/a text = _formatwarnmsg(msg)
29n/a try:
30n/a file.write(text)
31n/a except OSError:
32n/a # the file (probably stderr) is invalid - this warning gets lost.
33n/a pass
34n/a
35n/adef _formatwarnmsg_impl(msg):
36n/a s = ("%s:%s: %s: %s\n"
37n/a % (msg.filename, msg.lineno, msg.category.__name__,
38n/a msg.message))
39n/a
40n/a if msg.line is None:
41n/a try:
42n/a import linecache
43n/a line = linecache.getline(msg.filename, msg.lineno)
44n/a except Exception:
45n/a # When a warning is logged during Python shutdown, linecache
46n/a # and the import machinery don't work anymore
47n/a line = None
48n/a linecache = None
49n/a else:
50n/a line = msg.line
51n/a if line:
52n/a line = line.strip()
53n/a s += " %s\n" % line
54n/a
55n/a if msg.source is not None:
56n/a try:
57n/a import tracemalloc
58n/a tb = tracemalloc.get_object_traceback(msg.source)
59n/a except Exception:
60n/a # When a warning is logged during Python shutdown, tracemalloc
61n/a # and the import machinery don't work anymore
62n/a tb = None
63n/a
64n/a if tb is not None:
65n/a s += 'Object allocated at (most recent call first):\n'
66n/a for frame in tb:
67n/a s += (' File "%s", lineno %s\n'
68n/a % (frame.filename, frame.lineno))
69n/a
70n/a try:
71n/a if linecache is not None:
72n/a line = linecache.getline(frame.filename, frame.lineno)
73n/a else:
74n/a line = None
75n/a except Exception:
76n/a line = None
77n/a if line:
78n/a line = line.strip()
79n/a s += ' %s\n' % line
80n/a return s
81n/a
82n/a# Keep a reference to check if the function was replaced
83n/a_showwarning_orig = showwarning
84n/a
85n/adef _showwarnmsg(msg):
86n/a """Hook to write a warning to a file; replace if you like."""
87n/a try:
88n/a sw = showwarning
89n/a except NameError:
90n/a pass
91n/a else:
92n/a if sw is not _showwarning_orig:
93n/a # warnings.showwarning() was replaced
94n/a if not callable(sw):
95n/a raise TypeError("warnings.showwarning() must be set to a "
96n/a "function or method")
97n/a
98n/a sw(msg.message, msg.category, msg.filename, msg.lineno,
99n/a msg.file, msg.line)
100n/a return
101n/a _showwarnmsg_impl(msg)
102n/a
103n/a# Keep a reference to check if the function was replaced
104n/a_formatwarning_orig = formatwarning
105n/a
106n/adef _formatwarnmsg(msg):
107n/a """Function to format a warning the standard way."""
108n/a try:
109n/a fw = formatwarning
110n/a except NameError:
111n/a pass
112n/a else:
113n/a if fw is not _formatwarning_orig:
114n/a # warnings.formatwarning() was replaced
115n/a return fw(msg.message, msg.category,
116n/a msg.filename, msg.lineno, line=msg.line)
117n/a return _formatwarnmsg_impl(msg)
118n/a
119n/adef filterwarnings(action, message="", category=Warning, module="", lineno=0,
120n/a append=False):
121n/a """Insert an entry into the list of warnings filters (at the front).
122n/a
123n/a 'action' -- one of "error", "ignore", "always", "default", "module",
124n/a or "once"
125n/a 'message' -- a regex that the warning message must match
126n/a 'category' -- a class that the warning must be a subclass of
127n/a 'module' -- a regex that the module name must match
128n/a 'lineno' -- an integer line number, 0 matches all warnings
129n/a 'append' -- if true, append to the list of filters
130n/a """
131n/a import re
132n/a assert action in ("error", "ignore", "always", "default", "module",
133n/a "once"), "invalid action: %r" % (action,)
134n/a assert isinstance(message, str), "message must be a string"
135n/a assert isinstance(category, type), "category must be a class"
136n/a assert issubclass(category, Warning), "category must be a Warning subclass"
137n/a assert isinstance(module, str), "module must be a string"
138n/a assert isinstance(lineno, int) and lineno >= 0, \
139n/a "lineno must be an int >= 0"
140n/a _add_filter(action, re.compile(message, re.I), category,
141n/a re.compile(module), lineno, append=append)
142n/a
143n/adef simplefilter(action, category=Warning, lineno=0, append=False):
144n/a """Insert a simple entry into the list of warnings filters (at the front).
145n/a
146n/a A simple filter matches all modules and messages.
147n/a 'action' -- one of "error", "ignore", "always", "default", "module",
148n/a or "once"
149n/a 'category' -- a class that the warning must be a subclass of
150n/a 'lineno' -- an integer line number, 0 matches all warnings
151n/a 'append' -- if true, append to the list of filters
152n/a """
153n/a assert action in ("error", "ignore", "always", "default", "module",
154n/a "once"), "invalid action: %r" % (action,)
155n/a assert isinstance(lineno, int) and lineno >= 0, \
156n/a "lineno must be an int >= 0"
157n/a _add_filter(action, None, category, None, lineno, append=append)
158n/a
159n/adef _add_filter(*item, append):
160n/a # Remove possible duplicate filters, so new one will be placed
161n/a # in correct place. If append=True and duplicate exists, do nothing.
162n/a if not append:
163n/a try:
164n/a filters.remove(item)
165n/a except ValueError:
166n/a pass
167n/a filters.insert(0, item)
168n/a else:
169n/a if item not in filters:
170n/a filters.append(item)
171n/a _filters_mutated()
172n/a
173n/adef resetwarnings():
174n/a """Clear the list of warning filters, so that no filters are active."""
175n/a filters[:] = []
176n/a _filters_mutated()
177n/a
178n/aclass _OptionError(Exception):
179n/a """Exception used by option processing helpers."""
180n/a pass
181n/a
182n/a# Helper to process -W options passed via sys.warnoptions
183n/adef _processoptions(args):
184n/a for arg in args:
185n/a try:
186n/a _setoption(arg)
187n/a except _OptionError as msg:
188n/a print("Invalid -W option ignored:", msg, file=sys.stderr)
189n/a
190n/a# Helper for _processoptions()
191n/adef _setoption(arg):
192n/a import re
193n/a parts = arg.split(':')
194n/a if len(parts) > 5:
195n/a raise _OptionError("too many fields (max 5): %r" % (arg,))
196n/a while len(parts) < 5:
197n/a parts.append('')
198n/a action, message, category, module, lineno = [s.strip()
199n/a for s in parts]
200n/a action = _getaction(action)
201n/a message = re.escape(message)
202n/a category = _getcategory(category)
203n/a module = re.escape(module)
204n/a if module:
205n/a module = module + '$'
206n/a if lineno:
207n/a try:
208n/a lineno = int(lineno)
209n/a if lineno < 0:
210n/a raise ValueError
211n/a except (ValueError, OverflowError):
212n/a raise _OptionError("invalid lineno %r" % (lineno,))
213n/a else:
214n/a lineno = 0
215n/a filterwarnings(action, message, category, module, lineno)
216n/a
217n/a# Helper for _setoption()
218n/adef _getaction(action):
219n/a if not action:
220n/a return "default"
221n/a if action == "all": return "always" # Alias
222n/a for a in ('default', 'always', 'ignore', 'module', 'once', 'error'):
223n/a if a.startswith(action):
224n/a return a
225n/a raise _OptionError("invalid action: %r" % (action,))
226n/a
227n/a# Helper for _setoption()
228n/adef _getcategory(category):
229n/a import re
230n/a if not category:
231n/a return Warning
232n/a if re.match("^[a-zA-Z0-9_]+$", category):
233n/a try:
234n/a cat = eval(category)
235n/a except NameError:
236n/a raise _OptionError("unknown warning category: %r" % (category,))
237n/a else:
238n/a i = category.rfind(".")
239n/a module = category[:i]
240n/a klass = category[i+1:]
241n/a try:
242n/a m = __import__(module, None, None, [klass])
243n/a except ImportError:
244n/a raise _OptionError("invalid module name: %r" % (module,))
245n/a try:
246n/a cat = getattr(m, klass)
247n/a except AttributeError:
248n/a raise _OptionError("unknown warning category: %r" % (category,))
249n/a if not issubclass(cat, Warning):
250n/a raise _OptionError("invalid warning category: %r" % (category,))
251n/a return cat
252n/a
253n/a
254n/adef _is_internal_frame(frame):
255n/a """Signal whether the frame is an internal CPython implementation detail."""
256n/a filename = frame.f_code.co_filename
257n/a return 'importlib' in filename and '_bootstrap' in filename
258n/a
259n/a
260n/adef _next_external_frame(frame):
261n/a """Find the next frame that doesn't involve CPython internals."""
262n/a frame = frame.f_back
263n/a while frame is not None and _is_internal_frame(frame):
264n/a frame = frame.f_back
265n/a return frame
266n/a
267n/a
268n/a# Code typically replaced by _warnings
269n/adef warn(message, category=None, stacklevel=1, source=None):
270n/a """Issue a warning, or maybe ignore it or raise an exception."""
271n/a # Check if message is already a Warning object
272n/a if isinstance(message, Warning):
273n/a category = message.__class__
274n/a # Check category argument
275n/a if category is None:
276n/a category = UserWarning
277n/a if not (isinstance(category, type) and issubclass(category, Warning)):
278n/a raise TypeError("category must be a Warning subclass, "
279n/a "not '{:s}'".format(type(category).__name__))
280n/a # Get context information
281n/a try:
282n/a if stacklevel <= 1 or _is_internal_frame(sys._getframe(1)):
283n/a # If frame is too small to care or if the warning originated in
284n/a # internal code, then do not try to hide any frames.
285n/a frame = sys._getframe(stacklevel)
286n/a else:
287n/a frame = sys._getframe(1)
288n/a # Look for one frame less since the above line starts us off.
289n/a for x in range(stacklevel-1):
290n/a frame = _next_external_frame(frame)
291n/a if frame is None:
292n/a raise ValueError
293n/a except ValueError:
294n/a globals = sys.__dict__
295n/a lineno = 1
296n/a else:
297n/a globals = frame.f_globals
298n/a lineno = frame.f_lineno
299n/a if '__name__' in globals:
300n/a module = globals['__name__']
301n/a else:
302n/a module = "<string>"
303n/a filename = globals.get('__file__')
304n/a if filename:
305n/a fnl = filename.lower()
306n/a if fnl.endswith(".pyc"):
307n/a filename = filename[:-1]
308n/a else:
309n/a if module == "__main__":
310n/a try:
311n/a filename = sys.argv[0]
312n/a except AttributeError:
313n/a # embedded interpreters don't have sys.argv, see bug #839151
314n/a filename = '__main__'
315n/a if not filename:
316n/a filename = module
317n/a registry = globals.setdefault("__warningregistry__", {})
318n/a warn_explicit(message, category, filename, lineno, module, registry,
319n/a globals, source)
320n/a
321n/adef warn_explicit(message, category, filename, lineno,
322n/a module=None, registry=None, module_globals=None,
323n/a source=None):
324n/a lineno = int(lineno)
325n/a if module is None:
326n/a module = filename or "<unknown>"
327n/a if module[-3:].lower() == ".py":
328n/a module = module[:-3] # XXX What about leading pathname?
329n/a if registry is None:
330n/a registry = {}
331n/a if registry.get('version', 0) != _filters_version:
332n/a registry.clear()
333n/a registry['version'] = _filters_version
334n/a if isinstance(message, Warning):
335n/a text = str(message)
336n/a category = message.__class__
337n/a else:
338n/a text = message
339n/a message = category(message)
340n/a key = (text, category, lineno)
341n/a # Quick test for common case
342n/a if registry.get(key):
343n/a return
344n/a # Search the filters
345n/a for item in filters:
346n/a action, msg, cat, mod, ln = item
347n/a if ((msg is None or msg.match(text)) and
348n/a issubclass(category, cat) and
349n/a (mod is None or mod.match(module)) and
350n/a (ln == 0 or lineno == ln)):
351n/a break
352n/a else:
353n/a action = defaultaction
354n/a # Early exit actions
355n/a if action == "ignore":
356n/a registry[key] = 1
357n/a return
358n/a
359n/a # Prime the linecache for formatting, in case the
360n/a # "file" is actually in a zipfile or something.
361n/a import linecache
362n/a linecache.getlines(filename, module_globals)
363n/a
364n/a if action == "error":
365n/a raise message
366n/a # Other actions
367n/a if action == "once":
368n/a registry[key] = 1
369n/a oncekey = (text, category)
370n/a if onceregistry.get(oncekey):
371n/a return
372n/a onceregistry[oncekey] = 1
373n/a elif action == "always":
374n/a pass
375n/a elif action == "module":
376n/a registry[key] = 1
377n/a altkey = (text, category, 0)
378n/a if registry.get(altkey):
379n/a return
380n/a registry[altkey] = 1
381n/a elif action == "default":
382n/a registry[key] = 1
383n/a else:
384n/a # Unrecognized actions are errors
385n/a raise RuntimeError(
386n/a "Unrecognized action (%r) in warnings.filters:\n %s" %
387n/a (action, item))
388n/a # Print message and context
389n/a msg = WarningMessage(message, category, filename, lineno, source)
390n/a _showwarnmsg(msg)
391n/a
392n/a
393n/aclass WarningMessage(object):
394n/a
395n/a _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
396n/a "line", "source")
397n/a
398n/a def __init__(self, message, category, filename, lineno, file=None,
399n/a line=None, source=None):
400n/a local_values = locals()
401n/a for attr in self._WARNING_DETAILS:
402n/a setattr(self, attr, local_values[attr])
403n/a self._category_name = category.__name__ if category else None
404n/a
405n/a def __str__(self):
406n/a return ("{message : %r, category : %r, filename : %r, lineno : %s, "
407n/a "line : %r}" % (self.message, self._category_name,
408n/a self.filename, self.lineno, self.line))
409n/a
410n/a
411n/aclass catch_warnings(object):
412n/a
413n/a """A context manager that copies and restores the warnings filter upon
414n/a exiting the context.
415n/a
416n/a The 'record' argument specifies whether warnings should be captured by a
417n/a custom implementation of warnings.showwarning() and be appended to a list
418n/a returned by the context manager. Otherwise None is returned by the context
419n/a manager. The objects appended to the list are arguments whose attributes
420n/a mirror the arguments to showwarning().
421n/a
422n/a The 'module' argument is to specify an alternative module to the module
423n/a named 'warnings' and imported under that name. This argument is only useful
424n/a when testing the warnings module itself.
425n/a
426n/a """
427n/a
428n/a def __init__(self, *, record=False, module=None):
429n/a """Specify whether to record warnings and if an alternative module
430n/a should be used other than sys.modules['warnings'].
431n/a
432n/a For compatibility with Python 3.0, please consider all arguments to be
433n/a keyword-only.
434n/a
435n/a """
436n/a self._record = record
437n/a self._module = sys.modules['warnings'] if module is None else module
438n/a self._entered = False
439n/a
440n/a def __repr__(self):
441n/a args = []
442n/a if self._record:
443n/a args.append("record=True")
444n/a if self._module is not sys.modules['warnings']:
445n/a args.append("module=%r" % self._module)
446n/a name = type(self).__name__
447n/a return "%s(%s)" % (name, ", ".join(args))
448n/a
449n/a def __enter__(self):
450n/a if self._entered:
451n/a raise RuntimeError("Cannot enter %r twice" % self)
452n/a self._entered = True
453n/a self._filters = self._module.filters
454n/a self._module.filters = self._filters[:]
455n/a self._module._filters_mutated()
456n/a self._showwarning = self._module.showwarning
457n/a self._showwarnmsg_impl = self._module._showwarnmsg_impl
458n/a if self._record:
459n/a log = []
460n/a self._module._showwarnmsg_impl = log.append
461n/a # Reset showwarning() to the default implementation to make sure
462n/a # that _showwarnmsg() calls _showwarnmsg_impl()
463n/a self._module.showwarning = self._module._showwarning_orig
464n/a return log
465n/a else:
466n/a return None
467n/a
468n/a def __exit__(self, *exc_info):
469n/a if not self._entered:
470n/a raise RuntimeError("Cannot exit %r without entering first" % self)
471n/a self._module.filters = self._filters
472n/a self._module._filters_mutated()
473n/a self._module.showwarning = self._showwarning
474n/a self._module._showwarnmsg_impl = self._showwarnmsg_impl
475n/a
476n/a
477n/a# filters contains a sequence of filter 5-tuples
478n/a# The components of the 5-tuple are:
479n/a# - an action: error, ignore, always, default, module, or once
480n/a# - a compiled regex that must match the warning message
481n/a# - a class representing the warning category
482n/a# - a compiled regex that must match the module that is being warned
483n/a# - a line number for the line being warning, or 0 to mean any line
484n/a# If either if the compiled regexs are None, match anything.
485n/a_warnings_defaults = False
486n/atry:
487n/a from _warnings import (filters, _defaultaction, _onceregistry,
488n/a warn, warn_explicit, _filters_mutated)
489n/a defaultaction = _defaultaction
490n/a onceregistry = _onceregistry
491n/a _warnings_defaults = True
492n/aexcept ImportError:
493n/a filters = []
494n/a defaultaction = "default"
495n/a onceregistry = {}
496n/a
497n/a _filters_version = 1
498n/a
499n/a def _filters_mutated():
500n/a global _filters_version
501n/a _filters_version += 1
502n/a
503n/a
504n/a# Module initialization
505n/a_processoptions(sys.warnoptions)
506n/aif not _warnings_defaults:
507n/a silence = [ImportWarning, PendingDeprecationWarning]
508n/a silence.append(DeprecationWarning)
509n/a for cls in silence:
510n/a simplefilter("ignore", category=cls)
511n/a bytes_warning = sys.flags.bytes_warning
512n/a if bytes_warning > 1:
513n/a bytes_action = "error"
514n/a elif bytes_warning:
515n/a bytes_action = "default"
516n/a else:
517n/a bytes_action = "ignore"
518n/a simplefilter(bytes_action, category=BytesWarning, append=1)
519n/a # resource usage warnings are enabled by default in pydebug mode
520n/a if hasattr(sys, 'gettotalrefcount'):
521n/a resource_action = "always"
522n/a else:
523n/a resource_action = "ignore"
524n/a simplefilter(resource_action, category=ResourceWarning, append=1)
525n/a
526n/adel _warnings_defaults