From 0d7d394d98ec72dc34496bce0d7824806a79f35d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 13 Aug 2022 16:20:49 -0700 Subject: Add ValidateOption() API which validates that all command line options are either SCons specified or specifie by AddOption calls. It will error out if there are any unknown options. Resolves Issue #4187 --- CHANGES.txt | 5 +++ RELEASE.txt | 4 +- SCons/Script/Main.py | 11 +++++ SCons/Script/Main.xml | 20 +++++++++ SCons/Script/SConscript.py | 1 + SCons/Script/__init__.py | 1 + SCons/__init__.py | 8 ++-- doc/generated/examples/caching_ex-random_1.xml | 6 +-- doc/generated/examples/troubleshoot_explain1_3.xml | 2 +- doc/generated/functions.gen | 18 ++++++++ doc/generated/functions.mod | 4 ++ test/ValidateOptions.py | 51 ++++++++++++++++++++++ test/fixture/SConstruct-check-valid-options | 9 ++++ 13 files changed, 131 insertions(+), 9 deletions(-) create mode 100644 test/ValidateOptions.py create mode 100644 test/fixture/SConstruct-check-valid-options diff --git a/CHANGES.txt b/CHANGES.txt index ee49590..31407fb 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -9,6 +9,11 @@ NOTE: 4.3.0 now requires Python 3.6.0 and above. Python 3.5.x is no longer suppo RELEASE VERSION/DATE TO BE FILLED IN LATER + From William Deegan: + - Added ValidateOptions() which will check that all command line options are in either + those specified by SCons itself, or by AddOption() in SConstruct/SConscript. It should + not be called until all AddOption() calls are completed. Resolves Issue #4187 + From Dan Mezhiborsky: - Add newline to end of compilation db (compile_commands.json). diff --git a/RELEASE.txt b/RELEASE.txt index 711b6f2..3eff8ad 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -16,7 +16,9 @@ Here is a summary of the changes since 4.4.0: NEW FUNCTIONALITY ----------------- -- List new features (presumably why a checkpoint is being released) +- Added ValidateOptions() which will check that all command line options are in either + those specified by SCons itself, or by AddOption() in SConstruct/SConscript. It should + not be called until all AddOption() calls are completed. Resolves Issue #4187 DEPRECATED FUNCTIONALITY ------------------------ diff --git a/SCons/Script/Main.py b/SCons/Script/Main.py index ab2dc0e..850ca71 100644 --- a/SCons/Script/Main.py +++ b/SCons/Script/Main.py @@ -492,6 +492,16 @@ def GetOption(name): def SetOption(name, value): return OptionsParser.values.set_option(name, value) +def ValidateOptions(): + """ + If you call this after you set all your command line options with AddOption(), + it will verify that all command line options are valid. + So if you added an option --xyz and you call SCons with --xyy you can cause + SCons to issue an error message and exit by calling this function. + """ + OptionsParser.preserve_unknown_options = False + OptionsParser.parse_args(OptionsParser.largs, OptionsParser.values) + def PrintHelp(file=None): OptionsParser.print_help(file=file) @@ -1364,6 +1374,7 @@ def _exec_main(parser, values): else: _main(parser) + def main(): global OptionsParser global exit_status diff --git a/SCons/Script/Main.xml b/SCons/Script/Main.xml index f4f4705..746c1dc 100644 --- a/SCons/Script/Main.xml +++ b/SCons/Script/Main.xml @@ -740,6 +740,7 @@ Multiple targets can be passed in to a single call to + (name, value) @@ -943,6 +944,25 @@ Example: SetOption('max_drift', 0) + + + + + + Check that all the options provided by the user on the command line are either defined by SCons itself + or + defined by &f-link-AddOption;. + + + If there are any command line options not defined. + Calling this function will cause SCons to issue an error message and then exit with and error exit + status. + + + This function should only be called after the last &f-link-AddOption; call in your &SConscript; logic. + + + diff --git a/SCons/Script/SConscript.py b/SCons/Script/SConscript.py index 6188151..548ef44 100644 --- a/SCons/Script/SConscript.py +++ b/SCons/Script/SConscript.py @@ -528,6 +528,7 @@ class SConsEnvironment(SCons.Environment.Base): name = self.subst(name) return SCons.Script.Main.GetOption(name) + def Help(self, text, append=False): text = self.subst(text, raw=1) SCons.Script.HelpFunction(text, append=append) diff --git a/SCons/Script/__init__.py b/SCons/Script/__init__.py index 40be95e..aed31a5 100644 --- a/SCons/Script/__init__.py +++ b/SCons/Script/__init__.py @@ -107,6 +107,7 @@ AddOption = Main.AddOption PrintHelp = Main.PrintHelp GetOption = Main.GetOption SetOption = Main.SetOption +ValidateOptions = Main.ValidateOptions Progress = Main.Progress GetBuildFailures = Main.GetBuildFailures diff --git a/SCons/__init__.py b/SCons/__init__.py index 189bec3..dc8a9c0 100644 --- a/SCons/__init__.py +++ b/SCons/__init__.py @@ -1,9 +1,9 @@ -__version__="4.4.0" +__version__="4.4.1" __copyright__="Copyright (c) 2001 - 2022 The SCons Foundation" __developer__="bdbaddog" -__date__="Sat, 30 Jul 2022 14:11:34 -0700" +__date__="Sat, 13 Aug 2022 15:38:28 -0700" __buildsys__="M1Dog2021" -__revision__="fc8d0ec215ee6cba8bc158ad40c099be0b598297" -__build__="fc8d0ec215ee6cba8bc158ad40c099be0b598297" +__revision__="c7deb78684a518c59ed05c40bef266e9d27a9957" +__build__="c7deb78684a518c59ed05c40bef266e9d27a9957" # make sure compatibility is always in place import SCons.compat # noqa \ No newline at end of file diff --git a/doc/generated/examples/caching_ex-random_1.xml b/doc/generated/examples/caching_ex-random_1.xml index b8bd1bf..b54cc37 100644 --- a/doc/generated/examples/caching_ex-random_1.xml +++ b/doc/generated/examples/caching_ex-random_1.xml @@ -1,8 +1,8 @@ % scons -Q -cc -o f4.o -c f4.c -cc -o f2.o -c f2.c -cc -o f3.o -c f3.c cc -o f1.o -c f1.c +cc -o f3.o -c f3.c +cc -o f2.o -c f2.c cc -o f5.o -c f5.c +cc -o f4.o -c f4.c cc -o prog f1.o f2.o f3.o f4.o f5.o diff --git a/doc/generated/examples/troubleshoot_explain1_3.xml b/doc/generated/examples/troubleshoot_explain1_3.xml index e658d89..7a02fd5 100644 --- a/doc/generated/examples/troubleshoot_explain1_3.xml +++ b/doc/generated/examples/troubleshoot_explain1_3.xml @@ -2,5 +2,5 @@ cp file.in file.oout scons: warning: Cannot find target file.out after building -File "/Users/bdbaddog/devel/scons/git/as_scons/scripts/scons.py", line 97, in <module> +File "/Users/bdbaddog/devel/scons/git/scons-bugfixes-4/scripts/scons.py", line 97, in <module> diff --git a/doc/generated/functions.gen b/doc/generated/functions.gen index c135173..3c3413d 100644 --- a/doc/generated/functions.gen +++ b/doc/generated/functions.gen @@ -4384,6 +4384,24 @@ the tool object, previously it did not return + + ValidateOptions() + env.ValidateOptions() + + Check that all the options provided by the user on the command line are either defined by SCons itself + or + defined by &f-link-AddOption;. + + + If there are any command line options not defined. + Calling this function will cause SCons to issue an error message and then exit with and error exit + status. + + + This function should only be called after the last &f-link-AddOption; call in your &SConscript; logic. + + + Value(value, [built_value], [name]) env.Value(value, [built_value], [name]) diff --git a/doc/generated/functions.mod b/doc/generated/functions.mod index 9701bf3..34424a5 100644 --- a/doc/generated/functions.mod +++ b/doc/generated/functions.mod @@ -84,6 +84,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. subst"> Tag"> Tool"> +ValidateOptions"> Value"> VariantDir"> WhereIs"> @@ -164,6 +165,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. env.subst"> env.Tag"> env.Tool"> +env.ValidateOptions"> env.Value"> env.VariantDir"> env.WhereIs"> @@ -250,6 +252,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. subst"> Tag"> Tool"> +ValidateOptions"> Value"> VariantDir"> WhereIs"> @@ -330,6 +333,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. env.subst"> env.Tag"> env.Tool"> +env.ValidateOptions"> env.Value"> env.VariantDir"> env.WhereIs"> diff --git a/test/ValidateOptions.py b/test/ValidateOptions.py new file mode 100644 index 0000000..09609ef --- /dev/null +++ b/test/ValidateOptions.py @@ -0,0 +1,51 @@ +# MIT License +# +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Test ValidateOptions() command. +""" + +import TestSCons + +test = TestSCons.TestSCons() +test.file_fixture('fixture/SConstruct-check-valid-options', 'SConstruct') + +# Should see "This is in SConstruct" +test.run() +test.must_contain_single_instance_of(test.stdout(), ["This is in SConstruct"]) + +test.run(arguments="--testing=abc") +test.must_contain_single_instance_of(test.stdout(), ["This is in SConstruct"]) + +# Should not see "This is in SConstruct" +test.run(arguments="--garbage=xyz", status=2, stderr=".*SCons Error: no such option: --garbage.*", match=TestSCons.match_re_dotall) +test.fail_test(("This is in SConstruct" in test.stdout()), message='"This is in SConstruct" should not be output. This means ValidateOptions() did not error out before this was printed') + + + + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/fixture/SConstruct-check-valid-options b/test/fixture/SConstruct-check-valid-options new file mode 100644 index 0000000..0e2930d --- /dev/null +++ b/test/fixture/SConstruct-check-valid-options @@ -0,0 +1,9 @@ + +AddOption( + '--testing', + help='Test arg', +) + +ValidateOptions() + +print("This is in SConstruct") \ No newline at end of file -- cgit v0.12 From f14796556e3b26c63422f62b2848b4be70088cb6 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 14 Aug 2022 17:01:46 -0700 Subject: address comments by mwichmann --- SCons/Script/Main.xml | 4 ++-- test/ValidateOptions.py | 17 ++++++++++------- test/fixture/SConstruct-check-valid-options | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/SCons/Script/Main.xml b/SCons/Script/Main.xml index 746c1dc..70b9d18 100644 --- a/SCons/Script/Main.xml +++ b/SCons/Script/Main.xml @@ -950,13 +950,13 @@ SetOption('max_drift', 0) - Check that all the options provided by the user on the command line are either defined by SCons itself + Check that all the options specified on the command line are either defined by SCons itself or defined by &f-link-AddOption;. If there are any command line options not defined. - Calling this function will cause SCons to issue an error message and then exit with and error exit + Calling this function will cause SCons to issue an error message and then exit with an error exit status. diff --git a/test/ValidateOptions.py b/test/ValidateOptions.py index 09609ef..65e216b 100644 --- a/test/ValidateOptions.py +++ b/test/ValidateOptions.py @@ -30,19 +30,22 @@ import TestSCons test = TestSCons.TestSCons() test.file_fixture('fixture/SConstruct-check-valid-options', 'SConstruct') -# Should see "This is in SConstruct" +# Should see "This is in SConstruct" because all options specified (none) are valid and +# so ValidatedOptions() won't exit before it's printed. test.run() test.must_contain_single_instance_of(test.stdout(), ["This is in SConstruct"]) +# Should see "This is in SConstruct" because all options specified (--testing=abc) are valid and +# so ValidatedOptions() won't exit before it's printed. test.run(arguments="--testing=abc") test.must_contain_single_instance_of(test.stdout(), ["This is in SConstruct"]) -# Should not see "This is in SConstruct" -test.run(arguments="--garbage=xyz", status=2, stderr=".*SCons Error: no such option: --garbage.*", match=TestSCons.match_re_dotall) -test.fail_test(("This is in SConstruct" in test.stdout()), message='"This is in SConstruct" should not be output. This means ValidateOptions() did not error out before this was printed') - - - +# Should not see "This is in SConstruct" because the option specified (--garbage=xyz) is invalid and +# so ValidatedOptions() will exit before it's printed. +test.run(arguments="--garbage=xyz", status=2, stderr=".*SCons Error: no such option: --garbage.*", + match=TestSCons.match_re_dotall) +test.fail_test(("This is in SConstruct" in test.stdout()), + message='"This is in SConstruct" should not be output. This means ValidateOptions() did not error out before this was printed') # Local Variables: # tab-width:4 diff --git a/test/fixture/SConstruct-check-valid-options b/test/fixture/SConstruct-check-valid-options index 0e2930d..47f253c 100644 --- a/test/fixture/SConstruct-check-valid-options +++ b/test/fixture/SConstruct-check-valid-options @@ -6,4 +6,4 @@ AddOption( ValidateOptions() -print("This is in SConstruct") \ No newline at end of file +print("This is in SConstruct") -- cgit v0.12 From 7951e61b4eba59309624211a98a6a0e30e54740c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 14 Aug 2022 17:21:19 -0700 Subject: updates based on mwichmann's comments on the PR --- doc/generated/examples/caching_ex-random_1.xml | 6 +++--- doc/generated/functions.gen | 4 ++-- test/ValidateOptions.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/generated/examples/caching_ex-random_1.xml b/doc/generated/examples/caching_ex-random_1.xml index b54cc37..14432f1 100644 --- a/doc/generated/examples/caching_ex-random_1.xml +++ b/doc/generated/examples/caching_ex-random_1.xml @@ -1,8 +1,8 @@ % scons -Q -cc -o f1.o -c f1.c +cc -o f4.o -c f4.c +cc -o f5.o -c f5.c cc -o f3.o -c f3.c +cc -o f1.o -c f1.c cc -o f2.o -c f2.c -cc -o f5.o -c f5.c -cc -o f4.o -c f4.c cc -o prog f1.o f2.o f3.o f4.o f5.o diff --git a/doc/generated/functions.gen b/doc/generated/functions.gen index 3c3413d..03afa05 100644 --- a/doc/generated/functions.gen +++ b/doc/generated/functions.gen @@ -4388,13 +4388,13 @@ the tool object, previously it did not return ValidateOptions() env.ValidateOptions() - Check that all the options provided by the user on the command line are either defined by SCons itself + Check that all the options specified on the command line are either defined by SCons itself or defined by &f-link-AddOption;. If there are any command line options not defined. - Calling this function will cause SCons to issue an error message and then exit with and error exit + Calling this function will cause SCons to issue an error message and then exit with an error exit status. diff --git a/test/ValidateOptions.py b/test/ValidateOptions.py index 65e216b..e35ed15 100644 --- a/test/ValidateOptions.py +++ b/test/ValidateOptions.py @@ -22,7 +22,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -Test ValidateOptions() command. +Test ValidateOptions(). """ import TestSCons -- cgit v0.12 From 18745cfc5e75df8028682183097202f926e22134 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 14 Aug 2022 18:02:18 -0700 Subject: add language with instructions what to do if options added by tools are being flagged as undefined. Per mwichmann's feedback --- SCons/Script/Main.xml | 11 ++++++++--- doc/generated/functions.gen | 10 +++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/SCons/Script/Main.xml b/SCons/Script/Main.xml index 70b9d18..e6eb499 100644 --- a/SCons/Script/Main.xml +++ b/SCons/Script/Main.xml @@ -947,12 +947,12 @@ SetOption('max_drift', 0) + Check that all the options specified on the command line are either defined by SCons itself - or - defined by &f-link-AddOption;. + or defined by &f-link-AddOption;. If there are any command line options not defined. @@ -960,7 +960,12 @@ SetOption('max_drift', 0) status. - This function should only be called after the last &f-link-AddOption; call in your &SConscript; logic. + This function should only be called after the last &f-link-AddOption; call in your &SConscript; + logic. + + + Be aware that some tools call &f-link-AddOption;, if you are getting error messages for arguments + that they add, you will need to ensure that you load those tools before you call &f-ValidateOptions;. diff --git a/doc/generated/functions.gen b/doc/generated/functions.gen index 03afa05..fd6c44b 100644 --- a/doc/generated/functions.gen +++ b/doc/generated/functions.gen @@ -4389,8 +4389,7 @@ the tool object, previously it did not return env.ValidateOptions() Check that all the options specified on the command line are either defined by SCons itself - or - defined by &f-link-AddOption;. + or defined by &f-link-AddOption;. If there are any command line options not defined. @@ -4398,7 +4397,12 @@ the tool object, previously it did not return status. - This function should only be called after the last &f-link-AddOption; call in your &SConscript; logic. + This function should only be called after the last &f-link-AddOption; call in your &SConscript; + logic. + + + Be aware that some tools call &f-link-AddOption;, if you are getting error messages for arguments + that they add, you will need to ensure that you load those tools before you call &f-ValidateOptions;. -- cgit v0.12 From 0a482919aa521a45abab2fb77f7474151a9f4b82 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 15 Aug 2022 15:56:39 -0700 Subject: Added throw_exception parameter to ValidateOptions() which allows you to select either have ValidateOptions() issue error message and exit,or throw an exception and then you can handle it your own way. per dmoody's sugguestion --- SCons/Script/Main.py | 5 ++++- SCons/Script/Main.xml | 21 +++++++++++++++++ SCons/Script/SConsOptions.py | 31 ++++++++++++++++++++++---- SCons/__init__.py | 6 ++--- bin/update_doc_files.sh | 5 +++++ doc/generated/examples/caching_ex-random_1.xml | 6 ++--- doc/generated/functions.gen | 20 +++++++++++++++-- test/ValidateOptions.py | 14 ++++++++++++ test/fixture/SConstruct-check-valid-options | 14 +++++++++++- 9 files changed, 108 insertions(+), 14 deletions(-) create mode 100755 bin/update_doc_files.sh diff --git a/SCons/Script/Main.py b/SCons/Script/Main.py index 850ca71..3516e90 100644 --- a/SCons/Script/Main.py +++ b/SCons/Script/Main.py @@ -492,13 +492,16 @@ def GetOption(name): def SetOption(name, value): return OptionsParser.values.set_option(name, value) -def ValidateOptions(): + +def ValidateOptions(throw_exception=False): """ If you call this after you set all your command line options with AddOption(), it will verify that all command line options are valid. So if you added an option --xyz and you call SCons with --xyy you can cause SCons to issue an error message and exit by calling this function. """ + + OptionsParser.raise_exception_on_error = throw_exception OptionsParser.preserve_unknown_options = False OptionsParser.parse_args(OptionsParser.largs, OptionsParser.values) diff --git a/SCons/Script/Main.xml b/SCons/Script/Main.xml index e6eb499..ace1799 100644 --- a/SCons/Script/Main.xml +++ b/SCons/Script/Main.xml @@ -949,12 +949,21 @@ SetOption('max_drift', 0) + + ([throw_exception=False]) + + Check that all the options specified on the command line are either defined by SCons itself or defined by &f-link-AddOption;. + If throw_exception is True, &f-ValidateOptions; will raise a + SConsBadOptionError + exception instead of printing an error message and exiting with an error status. + + If there are any command line options not defined. Calling this function will cause SCons to issue an error message and then exit with an error exit status. @@ -967,6 +976,18 @@ SetOption('max_drift', 0) Be aware that some tools call &f-link-AddOption;, if you are getting error messages for arguments that they add, you will need to ensure that you load those tools before you call &f-ValidateOptions;. + + + Example: + + + +except SConsBadOptionError as e: + print("Parser is SConsOptionParser:%s" % (isinstance(e.parser, SConsOptionParser))) + print("Message is :%s" % e.opt_str) + Exit(3) + + diff --git a/SCons/Script/SConsOptions.py b/SCons/Script/SConsOptions.py index 0dff6be..aab8c7e 100644 --- a/SCons/Script/SConsOptions.py +++ b/SCons/Script/SConsOptions.py @@ -289,14 +289,37 @@ class SConsOptionGroup(optparse.OptionGroup): return result +class SConsBadOptionError(optparse.BadOptionError): + """ + Instance attributes: + opt_str : str + The offending option specified on command line which is not recognized + parser : OptionParser + the active argument parser + """ + + def __init__(self, opt_str, parser=None): + self.opt_str = opt_str + self.parser = parser + + def __str__(self): + return _("no such option: %s") % self.opt_str + + class SConsOptionParser(optparse.OptionParser): preserve_unknown_options = False + raise_exception_on_error = False def error(self, msg): - # overridden OptionValueError exception handler - self.print_usage(sys.stderr) - sys.stderr.write("SCons Error: %s\n" % msg) - sys.exit(2) + """ + overridden OptionValueError exception handler + """ + if self.raise_exception_on_error: + raise SConsBadOptionError(msg, self) + else: + self.print_usage(sys.stderr) + sys.stderr.write("SCons Error: %s\n" % msg) + sys.exit(2) def _process_long_opt(self, rargs, values): """ SCons-specific processing of long options. diff --git a/SCons/__init__.py b/SCons/__init__.py index dc8a9c0..de64c52 100644 --- a/SCons/__init__.py +++ b/SCons/__init__.py @@ -1,9 +1,9 @@ __version__="4.4.1" __copyright__="Copyright (c) 2001 - 2022 The SCons Foundation" __developer__="bdbaddog" -__date__="Sat, 13 Aug 2022 15:38:28 -0700" +__date__="Mon, 15 Aug 2022 11:59:33 -0700" __buildsys__="M1Dog2021" -__revision__="c7deb78684a518c59ed05c40bef266e9d27a9957" -__build__="c7deb78684a518c59ed05c40bef266e9d27a9957" +__revision__="18745cfc5e75df8028682183097202f926e22134" +__build__="18745cfc5e75df8028682183097202f926e22134" # make sure compatibility is always in place import SCons.compat # noqa \ No newline at end of file diff --git a/bin/update_doc_files.sh b/bin/update_doc_files.sh new file mode 100755 index 0000000..5e5cbe6 --- /dev/null +++ b/bin/update_doc_files.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +python bin/docs-update-generated.py +python bin/docs-validate.py +python bin/docs-create-example-outputs.py diff --git a/doc/generated/examples/caching_ex-random_1.xml b/doc/generated/examples/caching_ex-random_1.xml index 14432f1..a2de9bd 100644 --- a/doc/generated/examples/caching_ex-random_1.xml +++ b/doc/generated/examples/caching_ex-random_1.xml @@ -1,8 +1,8 @@ % scons -Q -cc -o f4.o -c f4.c +cc -o f2.o -c f2.c cc -o f5.o -c f5.c -cc -o f3.o -c f3.c cc -o f1.o -c f1.c -cc -o f2.o -c f2.c +cc -o f3.o -c f3.c +cc -o f4.o -c f4.c cc -o prog f1.o f2.o f3.o f4.o f5.o diff --git a/doc/generated/functions.gen b/doc/generated/functions.gen index fd6c44b..6deda59 100644 --- a/doc/generated/functions.gen +++ b/doc/generated/functions.gen @@ -4385,13 +4385,17 @@ the tool object, previously it did not return - ValidateOptions() - env.ValidateOptions() + ValidateOptions([throw_exception=False]) Check that all the options specified on the command line are either defined by SCons itself or defined by &f-link-AddOption;. + If throw_exception is True, &f-ValidateOptions; will raise a + SConsBadOptionError + exception instead of printing an error message and exiting with an error status. + + If there are any command line options not defined. Calling this function will cause SCons to issue an error message and then exit with an error exit status. @@ -4404,6 +4408,18 @@ the tool object, previously it did not return Be aware that some tools call &f-link-AddOption;, if you are getting error messages for arguments that they add, you will need to ensure that you load those tools before you call &f-ValidateOptions;. + + + Example: + + + +except SConsBadOptionError as e: + print("Parser is SConsOptionParser:%s" % (isinstance(e.parser, SConsOptionParser))) + print("Message is :%s" % e.opt_str) + Exit(3) + + diff --git a/test/ValidateOptions.py b/test/ValidateOptions.py index e35ed15..9b53c09 100644 --- a/test/ValidateOptions.py +++ b/test/ValidateOptions.py @@ -47,6 +47,20 @@ test.run(arguments="--garbage=xyz", status=2, stderr=".*SCons Error: no such opt test.fail_test(("This is in SConstruct" in test.stdout()), message='"This is in SConstruct" should not be output. This means ValidateOptions() did not error out before this was printed') +# Now we'll test having ValidateOptions raise a SConsBadOptionError exception +test.run(arguments="--garbage=xyz raise=1", status=2, + stderr=".*SConsBadOptionError: no such option: no such option: --garbage.*", + match=TestSCons.match_re_dotall) +test.fail_test(("This is in SConstruct" in test.stdout()), + message='"This is in SConstruct" should not be output. This means ValidateOptions() did not error out before this was printed') + +# Now we'll test having ValidateOptions raise a SConsBadOptionError exception and catching that exception +test.run(arguments="--garbage=xyz raise=2", status=3, + stdout=".*Parser is SConsOptionParser:True.*Message is .no such option. --garbage.*", + match=TestSCons.match_re_dotall) +test.fail_test(("This is in SConstruct" in test.stdout()), + message='"This is in SConstruct" should not be output. This means ValidateOptions() did not error out before this was printed') + # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/test/fixture/SConstruct-check-valid-options b/test/fixture/SConstruct-check-valid-options index 47f253c..2c935a2 100644 --- a/test/fixture/SConstruct-check-valid-options +++ b/test/fixture/SConstruct-check-valid-options @@ -1,9 +1,21 @@ +import sys +from SCons.Script.SConsOptions import SConsOptionParser, SConsBadOptionError AddOption( '--testing', help='Test arg', ) -ValidateOptions() +if ARGUMENTS.get('raise', 0) == '1': + ValidateOptions(throw_exception=True) +elif ARGUMENTS.get('raise', 0) == '2': + try: + ValidateOptions(throw_exception=True) + except SConsBadOptionError as e: + print("Parser is SConsOptionParser:%s" % (isinstance(e.parser, SConsOptionParser))) + print("Message is :%s" % e.opt_str) + Exit(3) +else: + ValidateOptions() print("This is in SConstruct") -- cgit v0.12 From d4ed957cb6562938a434d268f062238647f9f9fb Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 15 Aug 2022 21:13:04 -0700 Subject: Address doc and docstring feedback from mwichmann --- SCons/Script/Main.py | 10 +++++++++- SCons/Script/Main.xml | 16 ++++++++++------ 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/SCons/Script/Main.py b/SCons/Script/Main.py index 3516e90..442ee56 100644 --- a/SCons/Script/Main.py +++ b/SCons/Script/Main.py @@ -494,11 +494,19 @@ def SetOption(name, value): def ValidateOptions(throw_exception=False): - """ + """Validate options passed to SCons on the command line. + If you call this after you set all your command line options with AddOption(), it will verify that all command line options are valid. So if you added an option --xyz and you call SCons with --xyy you can cause SCons to issue an error message and exit by calling this function. + + args: + throw_exception (bool): Should this function raise an error if there's an + invalid option, or issue a message and exit with error status. + + Raises: + SConsBadOptionError """ OptionsParser.raise_exception_on_error = throw_exception diff --git a/SCons/Script/Main.xml b/SCons/Script/Main.xml index ace1799..efec64f 100644 --- a/SCons/Script/Main.xml +++ b/SCons/Script/Main.xml @@ -956,12 +956,7 @@ SetOption('max_drift', 0) Check that all the options specified on the command line are either defined by SCons itself - or defined by &f-link-AddOption;. - - - If throw_exception is True, &f-ValidateOptions; will raise a - SConsBadOptionError - exception instead of printing an error message and exiting with an error status. + or defined by calls to &f-link-AddOption;. If there are any command line options not defined. @@ -969,6 +964,13 @@ SetOption('max_drift', 0) status. + If optional throw_exception is True, &f-ValidateOptions; will raise a + SConsBadOptionError + exception instead of printing an error message and exiting with an error status. Then the calling + &SConscript; logic can catch that exception and handle invalid options itself. + + + This function should only be called after the last &f-link-AddOption; call in your &SConscript; logic. @@ -982,6 +984,8 @@ SetOption('max_drift', 0) +try: + ValidateOptions(throw_exception=True) except SConsBadOptionError as e: print("Parser is SConsOptionParser:%s" % (isinstance(e.parser, SConsOptionParser))) print("Message is :%s" % e.opt_str) -- cgit v0.12 From 764fb465a45f10adec4d4b904abd78ce731a0f8a Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 16 Aug 2022 21:51:31 -0700 Subject: rework the docs --- SCons/Script/Main.xml | 41 +++++++++++++++--------- doc/generated/examples/caching_ex-random_1.xml | 6 ++-- doc/generated/functions.gen | 43 ++++++++++++++++++-------- 3 files changed, 60 insertions(+), 30 deletions(-) diff --git a/SCons/Script/Main.xml b/SCons/Script/Main.xml index efec64f..ec09d35 100644 --- a/SCons/Script/Main.xml +++ b/SCons/Script/Main.xml @@ -959,18 +959,6 @@ SetOption('max_drift', 0) or defined by calls to &f-link-AddOption;. - If there are any command line options not defined. - Calling this function will cause SCons to issue an error message and then exit with an error exit - status. - - - If optional throw_exception is True, &f-ValidateOptions; will raise a - SConsBadOptionError - exception instead of printing an error message and exiting with an error status. Then the calling - &SConscript; logic can catch that exception and handle invalid options itself. - - - This function should only be called after the last &f-link-AddOption; call in your &SConscript; logic. @@ -978,19 +966,44 @@ SetOption('max_drift', 0) Be aware that some tools call &f-link-AddOption;, if you are getting error messages for arguments that they add, you will need to ensure that you load those tools before you call &f-ValidateOptions;. + + If there are any command line options not defined, calling this function will cause SCons to issue an + error message and then exit with an error exit + status. + If the optional throw_exception is True, &f-ValidateOptions; will raise a + SConsBadOptionError + exception. This would allow the calling + &SConscript; logic can catch that exception and handle invalid options itself. + Example: - + try: ValidateOptions(throw_exception=True) except SConsBadOptionError as e: print("Parser is SConsOptionParser:%s" % (isinstance(e.parser, SConsOptionParser))) print("Message is :%s" % e.opt_str) Exit(3) - + + + + This function is useful to force SCons to fail fast before you execute any expensive logic later in your + build logic. + For example if you specify build options via any flags, a simple typo could yield the incorrect build + option throughout your entire build. + + +scons --compilers=mingw (the correct flag is --compiler) + + + Could cause SCons to run configure steps with the incorrect compiler. Costing developer time trying to + track down why the configure logic failed with a compiler which should work. + + + diff --git a/doc/generated/examples/caching_ex-random_1.xml b/doc/generated/examples/caching_ex-random_1.xml index a2de9bd..2e3b879 100644 --- a/doc/generated/examples/caching_ex-random_1.xml +++ b/doc/generated/examples/caching_ex-random_1.xml @@ -1,8 +1,8 @@ % scons -Q -cc -o f2.o -c f2.c -cc -o f5.o -c f5.c -cc -o f1.o -c f1.c cc -o f3.o -c f3.c cc -o f4.o -c f4.c +cc -o f1.o -c f1.c +cc -o f2.o -c f2.c +cc -o f5.o -c f5.c cc -o prog f1.o f2.o f3.o f4.o f5.o diff --git a/doc/generated/functions.gen b/doc/generated/functions.gen index 6deda59..1c580f5 100644 --- a/doc/generated/functions.gen +++ b/doc/generated/functions.gen @@ -4388,17 +4388,7 @@ the tool object, previously it did not return ValidateOptions([throw_exception=False]) Check that all the options specified on the command line are either defined by SCons itself - or defined by &f-link-AddOption;. - - - If throw_exception is True, &f-ValidateOptions; will raise a - SConsBadOptionError - exception instead of printing an error message and exiting with an error status. - - - If there are any command line options not defined. - Calling this function will cause SCons to issue an error message and then exit with an error exit - status. + or defined by calls to &f-link-AddOption;. This function should only be called after the last &f-link-AddOption; call in your &SConscript; @@ -4408,17 +4398,44 @@ the tool object, previously it did not return Be aware that some tools call &f-link-AddOption;, if you are getting error messages for arguments that they add, you will need to ensure that you load those tools before you call &f-ValidateOptions;. + + If there are any command line options not defined, calling this function will cause SCons to issue an + error message and then exit with an error exit + status. + If the optional throw_exception is True, &f-ValidateOptions; will raise a + SConsBadOptionError + exception. This would allow the calling + &SConscript; logic can catch that exception and handle invalid options itself. + Example: - + +try: + ValidateOptions(throw_exception=True) except SConsBadOptionError as e: print("Parser is SConsOptionParser:%s" % (isinstance(e.parser, SConsOptionParser))) print("Message is :%s" % e.opt_str) Exit(3) - + + + + This function is useful to force SCons to fail fast before you execute any expensive logic later in your + build logic. + For example if you specify build options via any flags, a simple typo could yield the incorrect build + option throughout your entire build. + + +scons --compilers=mingw (the correct flag is --compiler) + + + Could cause SCons to run configure steps with the incorrect compiler. Costing developer time trying to + track down why the configure logic failed with a compiler which should work. + + + -- cgit v0.12 From 6f94c86e5ef250ef76474221fca17e24e12e14f9 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 17 Aug 2022 11:17:12 -0700 Subject: doc and docstring updates --- SCons/Script/Main.py | 11 +++++------ SCons/Script/Main.xml | 2 +- SCons/Script/SConsOptions.py | 11 +++++------ 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/SCons/Script/Main.py b/SCons/Script/Main.py index 442ee56..1b06a64 100644 --- a/SCons/Script/Main.py +++ b/SCons/Script/Main.py @@ -493,7 +493,7 @@ def SetOption(name, value): return OptionsParser.values.set_option(name, value) -def ValidateOptions(throw_exception=False): +def ValidateOptions(throw_exception=False) -> None: """Validate options passed to SCons on the command line. If you call this after you set all your command line options with AddOption(), @@ -501,12 +501,11 @@ def ValidateOptions(throw_exception=False): So if you added an option --xyz and you call SCons with --xyy you can cause SCons to issue an error message and exit by calling this function. - args: - throw_exception (bool): Should this function raise an error if there's an - invalid option, or issue a message and exit with error status. + :param bool throw_exception: (Optional) Should this function raise an error if there's an invalid option on the command line, or issue a message and exit with error status. - Raises: - SConsBadOptionError + :raises SConsBadOptionError: If throw_exception is True and there are invalid options on command line. + + .. versionadded:: 4.4.1 """ OptionsParser.raise_exception_on_error = throw_exception diff --git a/SCons/Script/Main.xml b/SCons/Script/Main.xml index ec09d35..cd4cc1a 100644 --- a/SCons/Script/Main.xml +++ b/SCons/Script/Main.xml @@ -988,7 +988,7 @@ except SConsBadOptionError as e: print("Message is :%s" % e.opt_str) Exit(3) - + This function is useful to force SCons to fail fast before you execute any expensive logic later in your build logic. diff --git a/SCons/Script/SConsOptions.py b/SCons/Script/SConsOptions.py index aab8c7e..f3b4708 100644 --- a/SCons/Script/SConsOptions.py +++ b/SCons/Script/SConsOptions.py @@ -290,12 +290,11 @@ class SConsOptionGroup(optparse.OptionGroup): class SConsBadOptionError(optparse.BadOptionError): - """ - Instance attributes: - opt_str : str - The offending option specified on command line which is not recognized - parser : OptionParser - the active argument parser + """Exception used to indicate that invalid command line options were specified + + :ivar str opt_str: The offending option specified on command line which is not recognized + :ivar OptionParser parser: The active argument parser + """ def __init__(self, opt_str, parser=None): -- cgit v0.12