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