From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001
From: "Matt A. Tobin" <mattatobin@localhost.localdomain>
Date: Fri, 2 Feb 2018 04:16:08 -0500
Subject: Add m-esr52 at 52.6.0

---
 python/pytest/_pytest/recwarn.py | 221 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 221 insertions(+)
 create mode 100644 python/pytest/_pytest/recwarn.py

(limited to 'python/pytest/_pytest/recwarn.py')

diff --git a/python/pytest/_pytest/recwarn.py b/python/pytest/_pytest/recwarn.py
new file mode 100644
index 000000000..a89474c03
--- /dev/null
+++ b/python/pytest/_pytest/recwarn.py
@@ -0,0 +1,221 @@
+""" recording warnings during test function execution. """
+
+import inspect
+
+import _pytest._code
+import py
+import sys
+import warnings
+import pytest
+
+
+@pytest.yield_fixture
+def recwarn(request):
+    """Return a WarningsRecorder instance that provides these methods:
+
+    * ``pop(category=None)``: return last warning matching the category.
+    * ``clear()``: clear list of warnings
+
+    See http://docs.python.org/library/warnings.html for information
+    on warning categories.
+    """
+    wrec = WarningsRecorder()
+    with wrec:
+        warnings.simplefilter('default')
+        yield wrec
+
+
+def pytest_namespace():
+    return {'deprecated_call': deprecated_call,
+            'warns': warns}
+
+
+def deprecated_call(func=None, *args, **kwargs):
+    """ assert that calling ``func(*args, **kwargs)`` triggers a
+    ``DeprecationWarning`` or ``PendingDeprecationWarning``.
+
+    This function can be used as a context manager::
+
+        >>> with deprecated_call():
+        ...    myobject.deprecated_method()
+
+    Note: we cannot use WarningsRecorder here because it is still subject
+    to the mechanism that prevents warnings of the same type from being
+    triggered twice for the same module. See #1190.
+    """
+    if not func:
+        return WarningsChecker(expected_warning=DeprecationWarning)
+
+    categories = []
+
+    def warn_explicit(message, category, *args, **kwargs):
+        categories.append(category)
+        old_warn_explicit(message, category, *args, **kwargs)
+
+    def warn(message, category=None, *args, **kwargs):
+        if isinstance(message, Warning):
+            categories.append(message.__class__)
+        else:
+            categories.append(category)
+        old_warn(message, category, *args, **kwargs)
+
+    old_warn = warnings.warn
+    old_warn_explicit = warnings.warn_explicit
+    warnings.warn_explicit = warn_explicit
+    warnings.warn = warn
+    try:
+        ret = func(*args, **kwargs)
+    finally:
+        warnings.warn_explicit = old_warn_explicit
+        warnings.warn = old_warn
+    deprecation_categories = (DeprecationWarning, PendingDeprecationWarning)
+    if not any(issubclass(c, deprecation_categories) for c in categories):
+        __tracebackhide__ = True
+        raise AssertionError("%r did not produce DeprecationWarning" % (func,))
+    return ret
+
+
+def warns(expected_warning, *args, **kwargs):
+    """Assert that code raises a particular class of warning.
+
+    Specifically, the input @expected_warning can be a warning class or
+    tuple of warning classes, and the code must return that warning
+    (if a single class) or one of those warnings (if a tuple).
+
+    This helper produces a list of ``warnings.WarningMessage`` objects,
+    one for each warning raised.
+
+    This function can be used as a context manager, or any of the other ways
+    ``pytest.raises`` can be used::
+
+        >>> with warns(RuntimeWarning):
+        ...    warnings.warn("my warning", RuntimeWarning)
+    """
+    wcheck = WarningsChecker(expected_warning)
+    if not args:
+        return wcheck
+    elif isinstance(args[0], str):
+        code, = args
+        assert isinstance(code, str)
+        frame = sys._getframe(1)
+        loc = frame.f_locals.copy()
+        loc.update(kwargs)
+
+        with wcheck:
+            code = _pytest._code.Source(code).compile()
+            py.builtin.exec_(code, frame.f_globals, loc)
+    else:
+        func = args[0]
+        with wcheck:
+            return func(*args[1:], **kwargs)
+
+
+class RecordedWarning(object):
+    def __init__(self, message, category, filename, lineno, file, line):
+        self.message = message
+        self.category = category
+        self.filename = filename
+        self.lineno = lineno
+        self.file = file
+        self.line = line
+
+
+class WarningsRecorder(object):
+    """A context manager to record raised warnings.
+
+    Adapted from `warnings.catch_warnings`.
+    """
+
+    def __init__(self, module=None):
+        self._module = sys.modules['warnings'] if module is None else module
+        self._entered = False
+        self._list = []
+
+    @property
+    def list(self):
+        """The list of recorded warnings."""
+        return self._list
+
+    def __getitem__(self, i):
+        """Get a recorded warning by index."""
+        return self._list[i]
+
+    def __iter__(self):
+        """Iterate through the recorded warnings."""
+        return iter(self._list)
+
+    def __len__(self):
+        """The number of recorded warnings."""
+        return len(self._list)
+
+    def pop(self, cls=Warning):
+        """Pop the first recorded warning, raise exception if not exists."""
+        for i, w in enumerate(self._list):
+            if issubclass(w.category, cls):
+                return self._list.pop(i)
+        __tracebackhide__ = True
+        raise AssertionError("%r not found in warning list" % cls)
+
+    def clear(self):
+        """Clear the list of recorded warnings."""
+        self._list[:] = []
+
+    def __enter__(self):
+        if self._entered:
+            __tracebackhide__ = True
+            raise RuntimeError("Cannot enter %r twice" % self)
+        self._entered = True
+        self._filters = self._module.filters
+        self._module.filters = self._filters[:]
+        self._showwarning = self._module.showwarning
+
+        def showwarning(message, category, filename, lineno,
+                        file=None, line=None):
+            self._list.append(RecordedWarning(
+                message, category, filename, lineno, file, line))
+
+            # still perform old showwarning functionality
+            self._showwarning(
+                message, category, filename, lineno, file=file, line=line)
+
+        self._module.showwarning = showwarning
+
+        # allow the same warning to be raised more than once
+
+        self._module.simplefilter('always')
+        return self
+
+    def __exit__(self, *exc_info):
+        if not self._entered:
+            __tracebackhide__ = True
+            raise RuntimeError("Cannot exit %r without entering first" % self)
+        self._module.filters = self._filters
+        self._module.showwarning = self._showwarning
+
+
+class WarningsChecker(WarningsRecorder):
+    def __init__(self, expected_warning=None, module=None):
+        super(WarningsChecker, self).__init__(module=module)
+
+        msg = ("exceptions must be old-style classes or "
+               "derived from Warning, not %s")
+        if isinstance(expected_warning, tuple):
+            for exc in expected_warning:
+                if not inspect.isclass(exc):
+                    raise TypeError(msg % type(exc))
+        elif inspect.isclass(expected_warning):
+            expected_warning = (expected_warning,)
+        elif expected_warning is not None:
+            raise TypeError(msg % type(expected_warning))
+
+        self.expected_warning = expected_warning
+
+    def __exit__(self, *exc_info):
+        super(WarningsChecker, self).__exit__(*exc_info)
+
+        # only check if we're not currently handling an exception
+        if all(a is None for a in exc_info):
+            if self.expected_warning is not None:
+                if not any(r.category in self.expected_warning for r in self):
+                    __tracebackhide__ = True
+                    pytest.fail("DID NOT WARN")
-- 
cgit v1.2.3