797ff41b6d7eb998c9e6b7081864f9b095d87702
[scons.git] / src / engine / SCons / Warnings.py
1 #
2 # __COPYRIGHT__
3 #
4 # Permission is hereby granted, free of charge, to any person obtaining
5 # a copy of this software and associated documentation files (the
6 # "Software"), to deal in the Software without restriction, including
7 # without limitation the rights to use, copy, modify, merge, publish,
8 # distribute, sublicense, and/or sell copies of the Software, and to
9 # permit persons to whom the Software is furnished to do so, subject to
10 # the following conditions:
11 #
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
14 #
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
16 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 #
23
24 """SCons.Warnings
25
26 This file implements the warnings framework for SCons.
27
28 """
29
30 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
31
32 import string
33 import sys
34
35 import SCons.Errors
36
37 class Warning(SCons.Errors.UserError):
38     pass
39
40 class MandatoryWarning(Warning):
41     pass
42
43
44
45 class FutureDeprecatedWarning(Warning):
46     pass
47
48 class DeprecatedWarning(Warning):
49     pass
50
51 class MandatoryDeprecatedWarning(MandatoryWarning):
52     pass
53
54
55
56 # NOTE:  If you add a new warning class, add it to the man page, too!
57
58 class CacheWriteErrorWarning(Warning):
59     pass
60
61 class CorruptSConsignWarning(Warning):
62     pass
63
64 class DependencyWarning(Warning):
65     pass
66
67 class DeprecatedCopyWarning(DeprecatedWarning):
68     pass
69
70 class DeprecatedOptionsWarning(DeprecatedWarning):
71     pass
72
73 class DeprecatedSourceSignaturesWarning(DeprecatedWarning):
74     pass
75
76 class DeprecatedTargetSignaturesWarning(DeprecatedWarning):
77     pass
78
79 class DuplicateEnvironmentWarning(Warning):
80     pass
81
82 class FutureReservedVariableWarning(Warning):
83     pass
84
85 class LinkWarning(Warning):
86     pass
87
88 class MisleadingKeywordsWarning(Warning):
89     pass
90
91 class MissingSConscriptWarning(Warning):
92     pass
93
94 class NoMD5ModuleWarning(Warning):
95     pass
96
97 class NoMetaclassSupportWarning(Warning):
98     pass
99
100 class NoObjectCountWarning(Warning):
101     pass
102
103 class NoParallelSupportWarning(Warning):
104     pass
105
106 class PythonVersionWarning(DeprecatedWarning):
107     pass
108
109 class ReservedVariableWarning(Warning):
110     pass
111
112 class StackSizeWarning(Warning):
113     pass
114
115 class TaskmasterNeedsExecuteWarning(FutureDeprecatedWarning):
116     pass
117
118 class VisualCMissingWarning(Warning):
119     pass
120
121 # Used when MSVC_VERSION and MSVS_VERSION do not point to the
122 # same version (MSVS_VERSION is deprecated)
123 class VisualVersionMismatch(Warning):
124     pass
125
126 class VisualStudioMissingWarning(Warning):
127     pass
128
129 class FortranCxxMixWarning(LinkWarning):
130     pass
131
132 _warningAsException = 0
133
134 # The below is a list of 2-tuples.  The first element is a class object.
135 # The second element is true if that class is enabled, false if it is disabled.
136 _enabled = []
137
138 _warningOut = None
139
140 def suppressWarningClass(clazz):
141     """Suppresses all warnings that are of type clazz or
142     derived from clazz."""
143     _enabled.insert(0, (clazz, 0))
144
145 def enableWarningClass(clazz):
146     """Suppresses all warnings that are of type clazz or
147     derived from clazz."""
148     _enabled.insert(0, (clazz, 1))
149
150 def warningAsException(flag=1):
151     """Turn warnings into exceptions.  Returns the old value of the flag."""
152     global _warningAsException
153     old = _warningAsException
154     _warningAsException = flag
155     return old
156
157 def warn(clazz, *args):
158     global _enabled, _warningAsException, _warningOut
159
160     warning = clazz(args)
161     for clazz, flag in _enabled:
162         if isinstance(warning, clazz):
163             if flag:
164                 if _warningAsException:
165                     raise warning
166
167                 if _warningOut:
168                     _warningOut(warning)
169             break
170
171 def process_warn_strings(arguments):
172     """Process string specifications of enabling/disabling warnings,
173     as passed to the --warn option or the SetOption('warn') function.
174     
175
176     An argument to this option should be of the form <warning-class>
177     or no-<warning-class>.  The warning class is munged in order
178     to get an actual class name from the classes above, which we
179     need to pass to the {enable,disable}WarningClass() functions.
180     The supplied <warning-class> is split on hyphens, each element
181     is capitalized, then smushed back together.  Then the string
182     "Warning" is appended to get the class name.
183
184     For example, 'deprecated' will enable the DeprecatedWarning
185     class.  'no-dependency' will disable the .DependencyWarning
186     class.
187
188     As a special case, --warn=all and --warn=no-all will enable or
189     disable (respectively) the base Warning class of all warnings.
190
191     """
192
193     def _capitalize(s):
194         if s[:5] == "scons":
195             return "SCons" + s[5:]
196         else:
197             return string.capitalize(s)
198
199     for arg in arguments:
200
201         elems = string.split(string.lower(arg), '-')
202         enable = 1
203         if elems[0] == 'no':
204             enable = 0
205             del elems[0]
206
207         if len(elems) == 1 and elems[0] == 'all':
208             class_name = "Warning"
209         else:
210             class_name = string.join(map(_capitalize, elems), '') + "Warning"
211         try:
212             clazz = globals()[class_name]
213         except KeyError:
214             sys.stderr.write("No warning type: '%s'\n" % arg)
215         else:
216             if enable:
217                 enableWarningClass(clazz)
218             elif issubclass(clazz, MandatoryDeprecatedWarning):
219                 fmt = "Can not disable mandataory warning: '%s'\n"
220                 sys.stderr.write(fmt % arg)
221             else:
222                 suppressWarningClass(clazz)
223
224 # Local Variables:
225 # tab-width:4
226 # indent-tabs-mode:nil
227 # End:
228 # vim: set expandtab tabstop=4 shiftwidth=4: