summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_warnings.py
blob: f6c933962fae05837c44eccfdda968300a9e183f (plain)
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
import warnings
import os
import unittest
from test import test_support

import warning_tests

# The warnings module isn't easily tested, because it relies on module
# globals to store configuration information.  setUp() and tearDown()
# preserve the current settings to avoid bashing them while running tests.

# To capture the warning messages, a replacement for showwarning() is
# used to save warning information in a global variable.

class WarningMessage:
    "Holds results of latest showwarning() call"
    pass

def showwarning(message, category, filename, lineno, file=None):
    msg.message = str(message)
    msg.category = category.__name__
    msg.filename = os.path.basename(filename)
    msg.lineno = lineno

class CatchWarningTest(unittest.TestCase):
    # base class used for catching warnings issued by the
    # warning framework (this is reused by test_structmembers.py)

    def setUp(self):
        global msg
        msg = WarningMessage()
        self._filters = warnings.filters[:]
        self._showwarning = warnings.showwarning
        warnings.showwarning = showwarning
        self.ignored = [w[2].__name__ for w in self._filters
            if w[0]=='ignore' and w[1] is None and w[3] is None]

    def tearDown(self):
        warnings.filters = self._filters[:]
        warnings.showwarning = self._showwarning

class TestModule(CatchWarningTest):

    def test_warn_default_category(self):
        for i in range(4):
            text = 'multi %d' %i    # Different text on each call
            warnings.warn(text)
            self.assertEqual(msg.message, text)
            self.assertEqual(msg.category, 'UserWarning')

    def test_warn_specific_category(self):
        text = 'None'
        for category in [DeprecationWarning, FutureWarning,
                    PendingDeprecationWarning, RuntimeWarning,
                    SyntaxWarning, UserWarning, Warning]:
            if category.__name__ in self.ignored:
                text = 'filtered out' + category.__name__
                warnings.warn(text, category)
                self.assertNotEqual(msg.message, text)
            else:
                text = 'unfiltered %s' % category.__name__
                warnings.warn(text, category)
                self.assertEqual(msg.message, text)
                self.assertEqual(msg.category, category.__name__)

    def test_filtering(self):

        warnings.filterwarnings("error", "", Warning, "", 0)
        self.assertRaises(UserWarning, warnings.warn, 'convert to error')

        warnings.resetwarnings()
        text = 'handle normally'
        warnings.warn(text)
        self.assertEqual(msg.message, text)
        self.assertEqual(msg.category, 'UserWarning')

        warnings.filterwarnings("ignore", "", Warning, "", 0)
        text = 'filtered out'
        warnings.warn(text)
        self.assertNotEqual(msg.message, text)

        warnings.resetwarnings()
        warnings.filterwarnings("error", "hex*", Warning, "", 0)
        self.assertRaises(UserWarning, warnings.warn, 'hex/oct')
        text = 'nonmatching text'
        warnings.warn(text)
        self.assertEqual(msg.message, text)
        self.assertEqual(msg.category, 'UserWarning')

    def test_options(self):
        # Uses the private _setoption() function to test the parsing
        # of command-line warning arguments
        self.assertRaises(warnings._OptionError,
                          warnings._setoption, '1:2:3:4:5:6')
        self.assertRaises(warnings._OptionError,
                          warnings._setoption, 'bogus::Warning')
        self.assertRaises(warnings._OptionError,
                          warnings._setoption, 'ignore:2::4:-5')
        warnings._setoption('error::Warning::0')
        self.assertRaises(UserWarning, warnings.warn, 'convert to error')

    def test_filename(self):
        warning_tests.inner("spam1")
        self.assertEqual(msg.filename, "warning_tests.py")
        warning_tests.outer("spam2")
        self.assertEqual(msg.filename, "warning_tests.py")

    def test_stacklevel(self):
        # Test stacklevel argument
        # make sure all messages are different, so the warning won't be skipped
        warning_tests.inner("spam3", stacklevel=1)
        self.assertEqual(msg.filename, "warning_tests.py")
        warning_tests.outer("spam4", stacklevel=1)
        self.assertEqual(msg.filename, "warning_tests.py")

        warning_tests.inner("spam5", stacklevel=2)
        self.assertEqual(msg.filename, "test_warnings.py")
        warning_tests.outer("spam6", stacklevel=2)
        self.assertEqual(msg.filename, "warning_tests.py")

        warning_tests.inner("spam7", stacklevel=9999)
        self.assertEqual(msg.filename, "sys")


def test_main(verbose=None):
    # Obscure hack so that this test passes after reloads or repeated calls
    # to test_main (regrtest -R).
    if '__warningregistry__' in globals():
        del globals()['__warningregistry__']
    test_support.run_unittest(TestModule)

if __name__ == "__main__":
    test_main(verbose=True)