blob: bab007fd34b0b44686e674e064c5c0f55df4ff36 [file] [log] [blame]
Guido van Rossum2a862c62000-12-15 21:59:53 +00001"""Python part of the warnings subsystem."""
2
Mark Hammonda43fd0c2003-02-19 00:33:33 +00003# Note: function level imports should *not* be used
4# in this module as it may cause import lock deadlock.
5# See bug 683658.
Guido van Rossum2a862c62000-12-15 21:59:53 +00006import sys, re, types
Mark Hammonda43fd0c2003-02-19 00:33:33 +00007import linecache
Guido van Rossum2a862c62000-12-15 21:59:53 +00008
Skip Montanaro40fc1602001-03-01 04:27:19 +00009__all__ = ["warn", "showwarning", "formatwarning", "filterwarnings",
10 "resetwarnings"]
11
Guido van Rossum2a862c62000-12-15 21:59:53 +000012defaultaction = "default"
13filters = []
14onceregistry = {}
15
16def warn(message, category=None, stacklevel=1):
17 """Issue a warning, or maybe ignore it or raise an exception."""
Walter Dörwaldb25c2b02002-03-21 10:38:40 +000018 # Check if message is already a Warning object
19 if isinstance(message, Warning):
Tim Peters863ac442002-04-16 01:38:40 +000020 category = message.__class__
Guido van Rossum2a862c62000-12-15 21:59:53 +000021 # Check category argument
22 if category is None:
23 category = UserWarning
24 assert issubclass(category, Warning)
25 # Get context information
26 try:
27 caller = sys._getframe(stacklevel)
28 except ValueError:
29 globals = sys.__dict__
30 lineno = 1
31 else:
32 globals = caller.f_globals
33 lineno = caller.f_lineno
Raymond Hettinger54f02222002-06-01 14:18:47 +000034 if '__name__' in globals:
Guido van Rossum8031bbe2001-08-31 17:46:35 +000035 module = globals['__name__']
36 else:
37 module = "<string>"
Guido van Rossum2a862c62000-12-15 21:59:53 +000038 filename = globals.get('__file__')
39 if filename:
40 fnl = filename.lower()
41 if fnl.endswith(".pyc") or fnl.endswith(".pyo"):
42 filename = filename[:-1]
43 else:
44 if module == "__main__":
45 filename = sys.argv[0]
46 if not filename:
47 filename = module
Guido van Rossum2a862c62000-12-15 21:59:53 +000048 registry = globals.setdefault("__warningregistry__", {})
Guido van Rossum9e263182001-02-28 21:43:40 +000049 warn_explicit(message, category, filename, lineno, module, registry)
50
51def warn_explicit(message, category, filename, lineno,
52 module=None, registry=None):
53 if module is None:
54 module = filename
55 if module[-3:].lower() == ".py":
56 module = module[:-3] # XXX What about leading pathname?
57 if registry is None:
58 registry = {}
Walter Dörwaldb25c2b02002-03-21 10:38:40 +000059 if isinstance(message, Warning):
Tim Peters863ac442002-04-16 01:38:40 +000060 text = str(message)
61 category = message.__class__
Walter Dörwaldb25c2b02002-03-21 10:38:40 +000062 else:
Tim Peters863ac442002-04-16 01:38:40 +000063 text = message
64 message = category(message)
Walter Dörwaldb25c2b02002-03-21 10:38:40 +000065 key = (text, category, lineno)
Guido van Rossum3756fa32001-02-28 22:26:36 +000066 # Quick test for common case
Guido van Rossum2a862c62000-12-15 21:59:53 +000067 if registry.get(key):
68 return
69 # Search the filters
70 for item in filters:
71 action, msg, cat, mod, ln = item
Walter Dörwaldb25c2b02002-03-21 10:38:40 +000072 if (msg.match(text) and
Guido van Rossum2a862c62000-12-15 21:59:53 +000073 issubclass(category, cat) and
74 mod.match(module) and
75 (ln == 0 or lineno == ln)):
76 break
77 else:
78 action = defaultaction
79 # Early exit actions
80 if action == "ignore":
81 registry[key] = 1
82 return
83 if action == "error":
Walter Dörwaldb25c2b02002-03-21 10:38:40 +000084 raise message
Guido van Rossum2a862c62000-12-15 21:59:53 +000085 # Other actions
86 if action == "once":
87 registry[key] = 1
Walter Dörwaldb25c2b02002-03-21 10:38:40 +000088 oncekey = (text, category)
Guido van Rossum2a862c62000-12-15 21:59:53 +000089 if onceregistry.get(oncekey):
90 return
91 onceregistry[oncekey] = 1
92 elif action == "always":
93 pass
94 elif action == "module":
95 registry[key] = 1
Walter Dörwaldb25c2b02002-03-21 10:38:40 +000096 altkey = (text, category, 0)
Guido van Rossum2a862c62000-12-15 21:59:53 +000097 if registry.get(altkey):
98 return
99 registry[altkey] = 1
100 elif action == "default":
101 registry[key] = 1
102 else:
103 # Unrecognized actions are errors
104 raise RuntimeError(
105 "Unrecognized action (%s) in warnings.filters:\n %s" %
106 (`action`, str(item)))
107 # Print message and context
108 showwarning(message, category, filename, lineno)
109
110def showwarning(message, category, filename, lineno, file=None):
111 """Hook to write a warning to a file; replace if you like."""
112 if file is None:
113 file = sys.stderr
Mark Hammond51a0ae32002-09-11 13:22:35 +0000114 try:
115 file.write(formatwarning(message, category, filename, lineno))
116 except IOError:
117 pass # the file (probably stderr) is invalid - this warning gets lost.
Guido van Rossum2a862c62000-12-15 21:59:53 +0000118
119def formatwarning(message, category, filename, lineno):
Guido van Rossum9464a7d2001-01-14 14:08:40 +0000120 """Function to format a warning the standard way."""
Guido van Rossum2a862c62000-12-15 21:59:53 +0000121 s = "%s:%s: %s: %s\n" % (filename, lineno, category.__name__, message)
122 line = linecache.getline(filename, lineno).strip()
123 if line:
124 s = s + " " + line + "\n"
125 return s
126
Guido van Rossum9464a7d2001-01-14 14:08:40 +0000127def filterwarnings(action, message="", category=Warning, module="", lineno=0,
128 append=0):
Guido van Rossum2a862c62000-12-15 21:59:53 +0000129 """Insert an entry into the list of warnings filters (at the front).
130
131 Use assertions to check that all arguments have the right type."""
132 assert action in ("error", "ignore", "always", "default", "module",
133 "once"), "invalid action: %s" % `action`
Martin v. Löwisff9284bc22002-10-14 21:06:02 +0000134 assert isinstance(message, basestring), "message must be a string"
Guido van Rossum2a862c62000-12-15 21:59:53 +0000135 assert isinstance(category, types.ClassType), "category must be a class"
136 assert issubclass(category, Warning), "category must be a Warning subclass"
Martin v. Löwisff9284bc22002-10-14 21:06:02 +0000137 assert isinstance(module, basestring), "module must be a string"
Walter Dörwald65230a22002-06-03 15:58:32 +0000138 assert isinstance(lineno, int) and lineno >= 0, \
Guido van Rossum2a862c62000-12-15 21:59:53 +0000139 "lineno must be an int >= 0"
Guido van Rossum9464a7d2001-01-14 14:08:40 +0000140 item = (action, re.compile(message, re.I), category,
141 re.compile(module), lineno)
142 if append:
143 filters.append(item)
144 else:
145 filters.insert(0, item)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000146
147def resetwarnings():
Tim Petersd0cc4f02002-04-16 01:51:25 +0000148 """Clear the list of warning filters, so that no filters are active."""
Guido van Rossum2a862c62000-12-15 21:59:53 +0000149 filters[:] = []
150
151class _OptionError(Exception):
152 """Exception used by option processing helpers."""
153 pass
154
155# Helper to process -W options passed via sys.warnoptions
156def _processoptions(args):
157 for arg in args:
158 try:
159 _setoption(arg)
160 except _OptionError, msg:
161 print >>sys.stderr, "Invalid -W option ignored:", msg
162
163# Helper for _processoptions()
164def _setoption(arg):
Tim Peterse1190062001-01-15 03:34:38 +0000165 parts = arg.split(':')
166 if len(parts) > 5:
167 raise _OptionError("too many fields (max 5): %s" % `arg`)
168 while len(parts) < 5:
169 parts.append('')
170 action, message, category, module, lineno = [s.strip()
171 for s in parts]
172 action = _getaction(action)
173 message = re.escape(message)
174 category = _getcategory(category)
175 module = re.escape(module)
176 if module:
177 module = module + '$'
178 if lineno:
179 try:
180 lineno = int(lineno)
181 if lineno < 0:
182 raise ValueError
183 except (ValueError, OverflowError):
184 raise _OptionError("invalid lineno %s" % `lineno`)
185 else:
186 lineno = 0
187 filterwarnings(action, message, category, module, lineno)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000188
189# Helper for _setoption()
190def _getaction(action):
191 if not action:
192 return "default"
193 if action == "all": return "always" # Alias
194 for a in ['default', 'always', 'ignore', 'module', 'once', 'error']:
195 if a.startswith(action):
196 return a
197 raise _OptionError("invalid action: %s" % `action`)
198
199# Helper for _setoption()
200def _getcategory(category):
201 if not category:
202 return Warning
203 if re.match("^[a-zA-Z0-9_]+$", category):
204 try:
205 cat = eval(category)
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000206 except NameError:
207 raise _OptionError("unknown warning category: %s" % `category`)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000208 else:
209 i = category.rfind(".")
210 module = category[:i]
211 klass = category[i+1:]
Guido van Rossumd1db30b2000-12-19 03:04:50 +0000212 try:
213 m = __import__(module, None, None, [klass])
214 except ImportError:
215 raise _OptionError("invalid module name: %s" % `module`)
216 try:
217 cat = getattr(m, klass)
218 except AttributeError:
219 raise _OptionError("unknown warning category: %s" % `category`)
Guido van Rossum2a862c62000-12-15 21:59:53 +0000220 if (not isinstance(cat, types.ClassType) or
221 not issubclass(cat, Warning)):
222 raise _OptionError("invalid warning category: %s" % `category`)
223 return cat
224
225# Self-test
226def _test():
227 import getopt
228 testoptions = []
229 try:
230 opts, args = getopt.getopt(sys.argv[1:], "W:")
231 except getopt.error, msg:
232 print >>sys.stderr, msg
233 return
234 for o, a in opts:
235 testoptions.append(a)
236 try:
237 _processoptions(testoptions)
238 except _OptionError, msg:
239 print >>sys.stderr, msg
240 return
241 for item in filters: print item
242 hello = "hello world"
243 warn(hello); warn(hello); warn(hello); warn(hello)
244 warn(hello, UserWarning)
245 warn(hello, DeprecationWarning)
246 for i in range(3):
247 warn(hello)
248 filterwarnings("error", "", Warning, "", 0)
249 try:
250 warn(hello)
251 except Exception, msg:
252 print "Caught", msg.__class__.__name__ + ":", msg
253 else:
254 print "No exception"
255 resetwarnings()
256 try:
257 filterwarnings("booh", "", Warning, "", 0)
258 except Exception, msg:
259 print "Caught", msg.__class__.__name__ + ":", msg
260 else:
261 print "No exception"
262
263# Module initialization
264if __name__ == "__main__":
265 import __main__
266 sys.modules['warnings'] = __main__
267 _test()
268else:
269 _processoptions(sys.warnoptions)
Guido van Rossumacc21d82001-08-23 03:07:42 +0000270 filterwarnings("ignore", category=OverflowWarning, append=1)
Neal Norwitzd68f5172002-05-29 15:54:55 +0000271 filterwarnings("ignore", category=PendingDeprecationWarning, append=1)