1 """Python part of the warnings subsystem."""
5 __all__
= ["warn", "showwarning", "formatwarning", "filterwarnings",
8 defaultaction
= "default"
12 def warn(message
, category
=None, stacklevel
=1):
13 """Issue a warning, or maybe ignore it or raise an exception."""
14 # Check category argument
16 category
= UserWarning
17 assert issubclass(category
, Warning)
18 # Get context information
20 caller
= sys
._getframe
(stacklevel
)
22 globals = sys
.__dict
__
25 globals = caller
.f_globals
26 lineno
= caller
.f_lineno
27 module
= globals['__name__']
28 filename
= globals.get('__file__')
30 fnl
= filename
.lower()
31 if fnl
.endswith(".pyc") or fnl
.endswith(".pyo"):
32 filename
= filename
[:-1]
34 if module
== "__main__":
35 filename
= sys
.argv
[0]
38 registry
= globals.setdefault("__warningregistry__", {})
39 warn_explicit(message
, category
, filename
, lineno
, module
, registry
)
41 def warn_explicit(message
, category
, filename
, lineno
,
42 module
=None, registry
=None):
45 if module
[-3:].lower() == ".py":
46 module
= module
[:-3] # XXX What about leading pathname?
49 key
= (message
, category
, lineno
)
50 # Quick test for common case
55 action
, msg
, cat
, mod
, ln
= item
56 if (msg
.match(message
) and
57 issubclass(category
, cat
) and
59 (ln
== 0 or lineno
== ln
)):
62 action
= defaultaction
64 if action
== "ignore":
68 raise category(message
)
72 oncekey
= (message
, category
)
73 if onceregistry
.get(oncekey
):
75 onceregistry
[oncekey
] = 1
76 elif action
== "always":
78 elif action
== "module":
80 altkey
= (message
, category
, 0)
81 if registry
.get(altkey
):
84 elif action
== "default":
87 # Unrecognized actions are errors
89 "Unrecognized action (%s) in warnings.filters:\n %s" %
90 (`action`
, str(item
)))
91 # Print message and context
92 showwarning(message
, category
, filename
, lineno
)
94 def showwarning(message
, category
, filename
, lineno
, file=None):
95 """Hook to write a warning to a file; replace if you like."""
98 file.write(formatwarning(message
, category
, filename
, lineno
))
100 def formatwarning(message
, category
, filename
, lineno
):
101 """Function to format a warning the standard way."""
103 s
= "%s:%s: %s: %s\n" % (filename
, lineno
, category
.__name
__, message
)
104 line
= linecache
.getline(filename
, lineno
).strip()
106 s
= s
+ " " + line
+ "\n"
109 def filterwarnings(action
, message
="", category
=Warning, module
="", lineno
=0,
111 """Insert an entry into the list of warnings filters (at the front).
113 Use assertions to check that all arguments have the right type."""
114 assert action
in ("error", "ignore", "always", "default", "module",
115 "once"), "invalid action: %s" % `action`
116 assert isinstance(message
, types
.StringType
), "message must be a string"
117 assert isinstance(category
, types
.ClassType
), "category must be a class"
118 assert issubclass(category
, Warning), "category must be a Warning subclass"
119 assert type(module
) is types
.StringType
, "module must be a string"
120 assert type(lineno
) is types
.IntType
and lineno
>= 0, \
121 "lineno must be an int >= 0"
122 item
= (action
, re
.compile(message
, re
.I
), category
,
123 re
.compile(module
), lineno
)
127 filters
.insert(0, item
)
130 """Reset the list of warnings filters to its default state."""
133 class _OptionError(Exception):
134 """Exception used by option processing helpers."""
137 # Helper to process -W options passed via sys.warnoptions
138 def _processoptions(args
):
142 except _OptionError
, msg
:
143 print >>sys
.stderr
, "Invalid -W option ignored:", msg
145 # Helper for _processoptions()
147 parts
= arg
.split(':')
149 raise _OptionError("too many fields (max 5): %s" % `arg`
)
150 while len(parts
) < 5:
152 action
, message
, category
, module
, lineno
= [s
.strip()
154 action
= _getaction(action
)
155 message
= re
.escape(message
)
156 category
= _getcategory(category
)
157 module
= re
.escape(module
)
159 module
= module
+ '$'
165 except (ValueError, OverflowError):
166 raise _OptionError("invalid lineno %s" % `lineno`
)
169 filterwarnings(action
, message
, category
, module
, lineno
)
171 # Helper for _setoption()
172 def _getaction(action
):
175 if action
== "all": return "always" # Alias
176 for a
in ['default', 'always', 'ignore', 'module', 'once', 'error']:
177 if a
.startswith(action
):
179 raise _OptionError("invalid action: %s" % `action`
)
181 # Helper for _setoption()
182 def _getcategory(category
):
185 if re
.match("^[a-zA-Z0-9_]+$", category
):
189 raise _OptionError("unknown warning category: %s" % `category`
)
191 i
= category
.rfind(".")
192 module
= category
[:i
]
193 klass
= category
[i
+1:]
195 m
= __import__(module
, None, None, [klass
])
197 raise _OptionError("invalid module name: %s" % `module`
)
199 cat
= getattr(m
, klass
)
200 except AttributeError:
201 raise _OptionError("unknown warning category: %s" % `category`
)
202 if (not isinstance(cat
, types
.ClassType
) or
203 not issubclass(cat
, Warning)):
204 raise _OptionError("invalid warning category: %s" % `category`
)
212 opts
, args
= getopt
.getopt(sys
.argv
[1:], "W:")
213 except getopt
.error
, msg
:
214 print >>sys
.stderr
, msg
217 testoptions
.append(a
)
219 _processoptions(testoptions
)
220 except _OptionError
, msg
:
221 print >>sys
.stderr
, msg
223 for item
in filters
: print item
224 hello
= "hello world"
225 warn(hello
); warn(hello
); warn(hello
); warn(hello
)
226 warn(hello
, UserWarning)
227 warn(hello
, DeprecationWarning)
230 filterwarnings("error", "", Warning, "", 0)
233 except Exception, msg
:
234 print "Caught", msg
.__class
__.__name
__ + ":", msg
239 filterwarnings("booh", "", Warning, "", 0)
240 except Exception, msg
:
241 print "Caught", msg
.__class
__.__name
__ + ":", msg
245 # Module initialization
246 if __name__
== "__main__":
248 sys
.modules
['warnings'] = __main__
251 _processoptions(sys
.warnoptions
)