From 2d8a1eae7eb2f3af40781600f327b232368a53a6 Mon Sep 17 00:00:00 2001 From: Dillan Mills Date: Fri, 18 Sep 2020 20:32:23 -0700 Subject: [PATCH 1/9] Add short option fix for #3798, fix bug in test/SCONSFLAGS.py --- SCons/Script/SConsOptions.py | 61 ++++++++++++++++++++++++++++++++++-- test/AddOption/basic.py | 5 ++- test/SCONSFLAGS.py | 9 ++++-- 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/SCons/Script/SConsOptions.py b/SCons/Script/SConsOptions.py index aa31635323..8e46dcf2bf 100644 --- a/SCons/Script/SConsOptions.py +++ b/SCons/Script/SConsOptions.py @@ -261,6 +261,63 @@ def error(self, msg): sys.stderr.write("SCons Error: %s\n" % msg) sys.exit(2) + def _process_short_opts(self, rargs, values): + """ + SCons-specific processing of short options. + + This is copied directly from the normal + optparse._process_short_opts() method, except that, if configured + to do so, we catch the exception thrown when an unknown option + is encountered and just stick it back on the "leftover" arguments + for later (re-)processing. + """ + arg = rargs.pop(0) + stop = False + i = 1 + for ch in arg[1:]: + opt = "-" + ch + option = self._short_opt.get(opt) + i += 1 # we have consumed a character + + try: + if not option: + raise optparse.BadOptionError(opt) + except optparse.BadOptionError: + if self.preserve_unknown_options: + # SCons-specific: if requested, add unknown options to + # the "leftover arguments" list for later processing. + self.largs.append(arg) + return + raise + + if option.takes_value(): + # Any characters left in arg? Pretend they're the + # next arg, and stop consuming characters of arg. + if i < len(arg): + rargs.insert(0, arg[i:]) + stop = True + + nargs = option.nargs + if len(rargs) < nargs: + if nargs == 1: + self.error(_("%s option requires an argument") % opt) + else: + self.error(_("%s option requires %d arguments") + % (opt, nargs)) + elif nargs == 1: + value = rargs.pop(0) + else: + value = tuple(rargs[0:nargs]) + del rargs[0:nargs] + + else: # option doesn't take a value + value = None + + option.process(opt, value, values, self) + + if stop: + break + def _process_long_opt(self, rargs, values): """ SCons-specific processing of long options. @@ -413,7 +470,7 @@ def add_local_option(self, *args, **kw): self.local_option_group = group result = group.add_option(*args, **kw) - + if result: # The option was added successfully. We now have to add the # default value to our object that holds the default values @@ -508,7 +565,7 @@ def Parser(version): """ formatter = SConsIndentedHelpFormatter(max_help_position=30) - + op = SConsOptionParser(option_class=SConsOption, add_help_option=False, formatter=formatter, diff --git a/test/AddOption/basic.py b/test/AddOption/basic.py index b1b8f2e1de..bd4b13912a 100644 --- a/test/AddOption/basic.py +++ b/test/AddOption/basic.py @@ -35,7 +35,7 @@ test.write('SConstruct', """\ env = Environment() -AddOption('--force', +AddOption('-F', '--force', action="store_true", help='force installation (overwrite any existing files)') AddOption('--prefix', @@ -65,6 +65,9 @@ status=1, stdout="None\nNone\n") +test.run('-Q -q . -F', + stdout="True\nNone\n") + test.pass_test() # Local Variables: diff --git a/test/SCONSFLAGS.py b/test/SCONSFLAGS.py index db866e8ac3..1d626a7352 100644 --- a/test/SCONSFLAGS.py +++ b/test/SCONSFLAGS.py @@ -63,16 +63,21 @@ test.must_not_contain_any_line(test.stdout(), ['Help text.']) test.must_contain_all_lines(test.stdout(), ['-H, --help-options']) -os.environ['SCONSFLAGS'] = '-Z' expect = r"""usage: scons [OPTION] [TARGET] ... SCons Error: no such option: -Z """ -test.run(arguments = "-H", status = 2, +test.run(arguments = "-Z", status = 2, stderr = expect, match=TestSCons.match_exact) +os.environ['SCONSFLAGS'] = '-Z' + +test.run(status = 2, + stderr = expect, + match=TestSCons.match_exact) + test.pass_test() # Local Variables: From f4085110f88c891cb04cc0aa3b01a3b7bef277c3 Mon Sep 17 00:00:00 2001 From: Dillan Mills Date: Fri, 18 Sep 2020 20:36:40 -0700 Subject: [PATCH 2/9] update changelog --- CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 677d73964f..3c68394ad3 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -43,6 +43,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Suppress missing SConscript deprecation warning if `must_exist=False` is used. + From Dillan Mills: + - Fix support for short options (`-x`). + RELEASE 4.0.1 - Mon, 16 Jul 2020 16:06:40 -0700 From 72b8e028c563f08d7c54e441e90f2e4be38cf9a5 Mon Sep 17 00:00:00 2001 From: Dillan Mills Date: Sat, 19 Sep 2020 02:00:14 -0700 Subject: [PATCH 3/9] Fix issue with spaces causing option values to be duplicated as targets, #3436, #3798 --- CHANGES.txt | 2 + SCons/Script/SConsOptions.py | 89 ++++++-------------- SCons/Script/__init__.py | 16 ++++ test/AddOption/args-and-targets.py | 111 +++++++++++++++++++++++++ test/AddOption/multi-arg.py | 128 +++++++++++++++++++++++++++++ 5 files changed, 281 insertions(+), 65 deletions(-) create mode 100644 test/AddOption/args-and-targets.py create mode 100644 test/AddOption/multi-arg.py diff --git a/CHANGES.txt b/CHANGES.txt index 3c68394ad3..9c18fe5d0d 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -45,6 +45,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Dillan Mills: - Fix support for short options (`-x`). + - Add support for long and short options with nargs != '?' to contain spaces: + - `--extra A B C` and `-x A B C` will both work as expected RELEASE 4.0.1 - Mon, 16 Jul 2020 16:06:40 -0700 diff --git a/SCons/Script/SConsOptions.py b/SCons/Script/SConsOptions.py index 8e46dcf2bf..ac43d36e6c 100644 --- a/SCons/Script/SConsOptions.py +++ b/SCons/Script/SConsOptions.py @@ -291,11 +291,14 @@ def _process_short_opts(self, rargs, values): raise if option.takes_value(): + had_explicit_value = False + # Any characters left in arg? Pretend they're the # next arg, and stop consuming characters of arg. if i < len(arg): rargs.insert(0, arg[i:]) stop = True + had_explicit_value = True nargs = option.nargs if len(rargs) < nargs: @@ -306,9 +309,19 @@ def _process_short_opts(self, rargs, values): % (opt, nargs)) elif nargs == 1: value = rargs.pop(0) + if not had_explicit_value: + SCons.Script._Remove_Target(value) + if '=' in value: + SCons.Script._Remove_Argument(value) else: value = tuple(rargs[0:nargs]) del rargs[0:nargs] + for i in range(len(value)): + if not had_explicit_value or i > 0: + SCons.Script._Remove_Target(value[i]) + if '=' in value[i]: + SCons.Script._Remove_Argument(value[i]) + else: # option doesn't take a value value = None @@ -379,9 +392,18 @@ def _process_long_opt(self, rargs, values): % (opt, nargs)) elif nargs == 1: value = rargs.pop(0) + if not had_explicit_value: + SCons.Script._Remove_Target(value) + if '=' in value: + SCons.Script._Remove_Argument(value) else: value = tuple(rargs[0:nargs]) del rargs[0:nargs] + for i in range(len(value)): + if not had_explicit_value or i > 0: + SCons.Script._Remove_Target(value[i]) + if '=' in value[i]: + SCons.Script._Remove_Argument(value[i]) elif had_explicit_value: self.error(_("%s option does not take a value") % opt) @@ -391,69 +413,6 @@ def _process_long_opt(self, rargs, values): option.process(opt, value, values, self) - def reparse_local_options(self): - """ Re-parse the leftover command-line options. - - Parse options stored in `self.largs`, so that any value - overridden on the command line is immediately available - if the user turns around and does a :func:`GetOption` right away. - - We mimic the processing of the single args - in the original OptionParser :func:`_process_args`, but here we - allow exact matches for long-opts only (no partial argument names!). - Otherwise there could be problems in :func:`add_local_option` - below. When called from there, we try to reparse the - command-line arguments that - - 1. haven't been processed so far (`self.largs`), but - 2. are possibly not added to the list of options yet. - - So, when we only have a value for "--myargument" so far, - a command-line argument of "--myarg=test" would set it, - per the behaviour of :func:`_match_long_opt`, - which allows for partial matches of the option name, - as long as the common prefix appears to be unique. - This would lead to further confusion, because we might want - to add another option "--myarg" later on (see issue #2929). - - """ - rargs = [] - largs_restore = [] - # Loop over all remaining arguments - skip = False - for l in self.largs: - if skip: - # Accept all remaining arguments as they are - largs_restore.append(l) - else: - if len(l) > 2 and l[0:2] == "--": - # Check long option - lopt = (l,) - if "=" in l: - # Split into option and value - lopt = l.split("=", 1) - - if lopt[0] in self._long_opt: - # Argument is already known - rargs.append('='.join(lopt)) - else: - # Not known yet, so reject for now - largs_restore.append('='.join(lopt)) - else: - if l == "--" or l == "-": - # Stop normal processing and don't - # process the rest of the command-line opts - largs_restore.append(l) - skip = True - else: - rargs.append(l) - - # Parse the filtered list - self.parse_args(rargs, self.values) - # Restore the list of remaining arguments for the - # next call of AddOption/add_local_option... - self.largs = self.largs + largs_restore - def add_local_option(self, *args, **kw): """ Adds a local option to the parser. @@ -481,8 +440,8 @@ def add_local_option(self, *args, **kw): # available if the user turns around and does a GetOption() # right away. setattr(self.values.__defaults__, result.dest, result.default) - self.reparse_local_options() - + self.parse_args(self.largs, self.values) + return result class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter): diff --git a/SCons/Script/__init__.py b/SCons/Script/__init__.py index ee9b3828b7..23d1394331 100644 --- a/SCons/Script/__init__.py +++ b/SCons/Script/__init__.py @@ -215,6 +215,13 @@ def _Add_Arguments(alist): ARGUMENTS[a] = b ARGLIST.append((a, b)) +def _Remove_Argument(aarg): + if aarg: + a, b = aarg.split('=', 1) + ARGUMENTS.pop(a, None) + if (a, b) in ARGLIST: + ARGLIST.remove((a, b)) + def _Add_Targets(tlist): if tlist: COMMAND_LINE_TARGETS.extend(tlist) @@ -225,6 +232,15 @@ def _Add_Targets(tlist): _build_plus_default._add_Default = _build_plus_default._do_nothing _build_plus_default._clear = _build_plus_default._do_nothing +def _Remove_Target(targ): + if targ: + if targ in COMMAND_LINE_TARGETS: + COMMAND_LINE_TARGETS.remove(targ) + if targ in BUILD_TARGETS: + BUILD_TARGETS.remove(targ) + if targ in _build_plus_default: + _build_plus_default.remove(targ) + def _Set_Default_Targets_Has_Been_Called(d, fs): return DEFAULT_TARGETS diff --git a/test/AddOption/args-and-targets.py b/test/AddOption/args-and-targets.py new file mode 100644 index 0000000000..52db92221b --- /dev/null +++ b/test/AddOption/args-and-targets.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# 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. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that when an option is specified which takes args, +those do not end up treated as targets. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +env = Environment() +AddOption('-x', '--extra', + nargs=1, + dest='extra', + action='store', + type='string', + metavar='ARG1', + default=(), + help='An argument to the option') +print(str(GetOption('extra'))) +print(COMMAND_LINE_TARGETS) +""") + +# arg using = +test.run('-Q -q --extra=A TARG', status=1, stdout="A\n['TARG']\n") +# arg not using = +test.run('-Q -q --extra A TARG', status=1, stdout="A\n['TARG']\n") +# short arg with space +test.run('-Q -q -x A TARG', status=1, stdout="A\n['TARG']\n") +# short arg with no space +test.run('-Q -q -xA TARG', status=1, stdout="A\n['TARG']\n") + +test.write('SConstruct', """\ +env = Environment() +AddOption('-x', '--extra', + nargs=2, + dest='extra', + action='append', + type='string', + metavar='ARG1', + default=[], + help='An argument to the option') +print(str(GetOption('extra'))) +print(COMMAND_LINE_TARGETS) +""") + +# many args and opts +test.run('-Q -q --extra=A B TARG1 -x C D TARG2 -xE F TARG3 --extra G H TARG4', + status=1, stdout="[('A', 'B'), ('C', 'D'), ('E', 'F'), ('G', 'H')]\n['TARG1', 'TARG2', 'TARG3', 'TARG4']\n") + +test.write('SConstruct', """\ +env = Environment() +AddOption('-x', '--extra', + nargs=1, + dest='extra', + action='store', + type='string', + metavar='ARG1', + default=(), + help='An argument to the option') +print(str(GetOption('extra'))) +print(COMMAND_LINE_TARGETS) +""") + +# opt value and target are same name +test.run('-Q -q --extra=TARG1 TARG1', status=1, stdout="TARG1\n['TARG1']\n") +test.run('-Q -q --extra TARG1 TARG1', status=1, stdout="TARG1\n['TARG1']\n") +test.run('-Q -q -xTARG1 TARG1', status=1, stdout="TARG1\n['TARG1']\n") +test.run('-Q -q -x TARG1 TARG1', status=1, stdout="TARG1\n['TARG1']\n") + +# equals in opt value +test.run('-Q -q --extra=A=B TARG1', status=1, stdout="A=B\n['TARG1']\n") +test.run('-Q -q --extra A=B TARG1', status=1, stdout="A=B\n['TARG1']\n") +test.run('-Q -q -xA=B TARG1', status=1, stdout="A=B\n['TARG1']\n") +test.run('-Q -q -x A=B TARG1', status=1, stdout="A=B\n['TARG1']\n") + + + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: \ No newline at end of file diff --git a/test/AddOption/multi-arg.py b/test/AddOption/multi-arg.py new file mode 100644 index 0000000000..1324fd57b4 --- /dev/null +++ b/test/AddOption/multi-arg.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# 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. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that when an option is specified with nargs > 1, +SCons consumes those correctly into the args. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +# First, test an option with nargs=2 and no others: +test.write('SConstruct', """\ +env = Environment() +AddOption('-x', '--extras', + nargs=2, + dest='extras', + action='store', + type='string', + metavar='FILE1 FILE2', + default=(), + help='two extra files to install') +print(str(GetOption('extras'))) +print(COMMAND_LINE_TARGETS) +""") + +# no args +test.run('-Q -q .', stdout="()\n['.']\n") + +# one arg, should fail +test.run('-Q -q . --extras A', status=2, stderr="""\ +usage: scons [OPTION] [TARGET] ... + +SCons Error: --extras option requires 2 arguments +""") +#one arg, short option +test.run('-Q -q . -x A', status=2, stderr="""\ +usage: scons [OPTION] [TARGET] ... + +SCons Error: -x option requires 2 arguments +""") +# two args +test.run('-Q -q . --extras A B', stdout="('A', 'B')\n['.']\n") +# two args, short option +test.run('-Q -q . -x A B', stdout="('A', 'B')\n['.']\n") +# -- means the rest are not processed as args +test.run('-Q -q . -- --extras A B', status=1, stdout="()\n['.', '--extras', 'A', 'B']\n") + +# Now test what has been a bug: another option is +# also defined, this impacts the collection of args for the nargs>1 opt +test.write('SConstruct', """\ +env = Environment() +AddOption('-P', '--prefix', + nargs=1, + dest='prefix', + action='store', + type='string', + metavar='DIR', + help='installation prefix') +AddOption('-x', '--extras', + nargs=2, + dest='extras', + action='store', + type='string', + metavar='FILE1 FILE2', + default=(), + help='two extra files to install') +print(str(GetOption('prefix'))) +print(str(GetOption('extras'))) +print(COMMAND_LINE_TARGETS) +""") +# no opts +test.run('-Q -q .', stdout="None\n()\n['.']\n") +# first opt long, one arg +test.run('-Q -q . --prefix=/home/foo', stdout="/home/foo\n()\n['.']\n") +test.run('-Q -q . --prefix /home/foo', stdout="/home/foo\n()\n['.']\n") +# first opt short, one arg +test.run('-Q -q . -P/home/foo', stdout="/home/foo\n()\n['.']\n") +test.run('-Q -q . -P /home/foo', stdout="/home/foo\n()\n['.']\n") +# second opt long, two args +test.run('-Q -q . --extras=A B', stdout="None\n('A', 'B')\n['.']\n") +test.run('-Q -q . --extras A B', stdout="None\n('A', 'B')\n['.']\n") +# second opt short, two args +test.run('-Q -q . -xA B', stdout="None\n('A', 'B')\n['.']\n") +test.run('-Q -q . -x A B', stdout="None\n('A', 'B')\n['.']\n") +# both opts long +test.run('-Q -q . --prefix=/home/foo --extras=A B', stdout="/home/foo\n('A', 'B')\n['.']\n") +test.run('-Q -q . --prefix /home/foo --extras A B', stdout="/home/foo\n('A', 'B')\n['.']\n") +# both opts short +test.run('-Q -q . -P/home/foo -xA B', stdout="/home/foo\n('A', 'B')\n['.']\n") +test.run('-Q -q . -P /home/foo -x A B', stdout="/home/foo\n('A', 'B')\n['.']\n") +# don't process +test.run('-Q -q . -- --prefix=/home/foo --extras=A B',status=1, + stdout="None\n()\n['.', '--prefix=/home/foo', '--extras=A', 'B']\n") +test.run('-Q -q . -- --prefix /home/foo --extras A B',status=1, + stdout="None\n()\n['.', '--prefix', '/home/foo', '--extras', 'A', 'B']\n") + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: \ No newline at end of file From e348306606478d00c349ee04904987d28ae9cced Mon Sep 17 00:00:00 2001 From: Dillan Mills Date: Sat, 19 Sep 2020 12:51:03 -0700 Subject: [PATCH 4/9] Added nested option and target check, #3798 --- test/AddOption/args-and-targets.py | 81 ++++++++++++++++++++++++------ 1 file changed, 67 insertions(+), 14 deletions(-) diff --git a/test/AddOption/args-and-targets.py b/test/AddOption/args-and-targets.py index 52db92221b..022cbeae01 100644 --- a/test/AddOption/args-and-targets.py +++ b/test/AddOption/args-and-targets.py @@ -31,7 +31,7 @@ import TestSCons -test = TestSCons.TestSCons() +test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) test.write('SConstruct', """\ env = Environment() @@ -48,13 +48,13 @@ """) # arg using = -test.run('-Q -q --extra=A TARG', status=1, stdout="A\n['TARG']\n") +test.run('-Q -q --extra=A TARG', status=1, stdout="A\n\\['TARG'\\]\n") # arg not using = -test.run('-Q -q --extra A TARG', status=1, stdout="A\n['TARG']\n") +test.run('-Q -q --extra A TARG', status=1, stdout="A\n\\['TARG'\\]\n") # short arg with space -test.run('-Q -q -x A TARG', status=1, stdout="A\n['TARG']\n") +test.run('-Q -q -x A TARG', status=1, stdout="A\n\\['TARG'\\]\n") # short arg with no space -test.run('-Q -q -xA TARG', status=1, stdout="A\n['TARG']\n") +test.run('-Q -q -xA TARG', status=1, stdout="A\n\\['TARG'\\]\n") test.write('SConstruct', """\ env = Environment() @@ -72,7 +72,7 @@ # many args and opts test.run('-Q -q --extra=A B TARG1 -x C D TARG2 -xE F TARG3 --extra G H TARG4', - status=1, stdout="[('A', 'B'), ('C', 'D'), ('E', 'F'), ('G', 'H')]\n['TARG1', 'TARG2', 'TARG3', 'TARG4']\n") + status=1, stdout="\\[\\('A', 'B'\\), \\('C', 'D'\\), \\('E', 'F'\\), \\('G', 'H'\\)\\]\n\\['TARG1', 'TARG2', 'TARG3', 'TARG4'\\]\n") test.write('SConstruct', """\ env = Environment() @@ -89,17 +89,70 @@ """) # opt value and target are same name -test.run('-Q -q --extra=TARG1 TARG1', status=1, stdout="TARG1\n['TARG1']\n") -test.run('-Q -q --extra TARG1 TARG1', status=1, stdout="TARG1\n['TARG1']\n") -test.run('-Q -q -xTARG1 TARG1', status=1, stdout="TARG1\n['TARG1']\n") -test.run('-Q -q -x TARG1 TARG1', status=1, stdout="TARG1\n['TARG1']\n") +test.run('-Q -q --extra=TARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\n") +test.run('-Q -q --extra TARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\n") +test.run('-Q -q -xTARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\n") +test.run('-Q -q -x TARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\n") # equals in opt value -test.run('-Q -q --extra=A=B TARG1', status=1, stdout="A=B\n['TARG1']\n") -test.run('-Q -q --extra A=B TARG1', status=1, stdout="A=B\n['TARG1']\n") -test.run('-Q -q -xA=B TARG1', status=1, stdout="A=B\n['TARG1']\n") -test.run('-Q -q -x A=B TARG1', status=1, stdout="A=B\n['TARG1']\n") +test.run('-Q -q --extra=A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\n") +test.run('-Q -q --extra A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\n") +test.run('-Q -q -xA=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\n") +test.run('-Q -q -x A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\n") +test.write('SConstruct', """\ +env = Environment() +AddOption('-x', '--extra', + nargs=1, + dest='extra', + action='store', + type='string', + metavar='ARG1', + default=(), + help='An argument to the option') +if 'A' in BUILD_TARGETS: + BUILD_TARGETS.append('B') +print(str(GetOption('extra'))) +print(COMMAND_LINE_TARGETS) +""") + +# Nested target +test.run('-Q -q -x A TARG1', status=1, stdout="A\n\\['TARG1'\\]\n") + +test.write('SConstruct', """\ +env = Environment() +AddOption('-x', '--extra', + nargs=1, + dest='extra', + action='store', + type='string', + metavar='ARG1', + default=(), + help='An argument to the option') +if 'A' in BUILD_TARGETS: + AddOption('--foo', + nargs=1, + dest='foo', + action='store', + type='string', + metavar='FOO1', + default=(), + help='An argument to the option') +print(str(GetOption('extra'))) +print(str(GetOption('foo'))) +print(COMMAND_LINE_TARGETS) +""") + +# nested option +test.run('-Q -q -x A --foo=C TARG1', status=2, stdout="A\n", stderr="""\ +AttributeError: 'Values' object has no attribute 'foo': + File ".+SConstruct", line \\d+: + print\\(str\\(GetOption\\('foo'\\)\\)\\) + File ".+SCons/Script/Main.py", line \\d+: + return getattr\\(OptionsParser.values, name\\) + File ".+SCons/Script/SConsOptions.py", line \\d+: + return getattr\\(self.__dict__\\['__defaults__'\\], attr\\) +""") test.pass_test() From 4535111b4b0147d887e28d58f22e1a16461a2266 Mon Sep 17 00:00:00 2001 From: Dillan Mills Date: Sat, 19 Sep 2020 21:17:47 -0700 Subject: [PATCH 5/9] Added a bit more arg/target testing --- test/AddOption/args-and-targets.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/AddOption/args-and-targets.py b/test/AddOption/args-and-targets.py index 022cbeae01..c703a99178 100644 --- a/test/AddOption/args-and-targets.py +++ b/test/AddOption/args-and-targets.py @@ -113,11 +113,12 @@ if 'A' in BUILD_TARGETS: BUILD_TARGETS.append('B') print(str(GetOption('extra'))) -print(COMMAND_LINE_TARGETS) +print(BUILD_TARGETS) """) # Nested target test.run('-Q -q -x A TARG1', status=1, stdout="A\n\\['TARG1'\\]\n") +test.run('-Q -q -x A A TARG1', status=1, stdout="A\n\\['A', 'TARG1', 'B'\\]\n") test.write('SConstruct', """\ env = Environment() @@ -153,6 +154,8 @@ File ".+SCons/Script/SConsOptions.py", line \\d+: return getattr\\(self.__dict__\\['__defaults__'\\], attr\\) """) +test.run('-Q -q -x A A --foo=C TARG1', status=1, stdout="A\nC\n\\['A', 'TARG1'\\]\n") + test.pass_test() From bd7a1b468664b4bdcd6e09f2ef292618134ce368 Mon Sep 17 00:00:00 2001 From: Dillan Mills Date: Sun, 20 Sep 2020 15:02:03 -0700 Subject: [PATCH 6/9] Added a few more args-and-targets permutations, fixed a bug in the _Remove_Argument logic that would prevent the correct argument value from getting returned. --- SCons/Script/__init__.py | 9 +++++- test/AddOption/args-and-targets.py | 51 ++++++++++++++++++++++++------ 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/SCons/Script/__init__.py b/SCons/Script/__init__.py index 23d1394331..aac50a45ee 100644 --- a/SCons/Script/__init__.py +++ b/SCons/Script/__init__.py @@ -218,10 +218,17 @@ def _Add_Arguments(alist): def _Remove_Argument(aarg): if aarg: a, b = aarg.split('=', 1) - ARGUMENTS.pop(a, None) + + # remove from ARGLIST first which would contain duplicates if -x A=B A=B was specified on the CL if (a, b) in ARGLIST: ARGLIST.remove((a, b)) + # Set ARGUMENTS[A] back to latest value in ARGLIST (remove first in case no matching values left in ARGLIST) + ARGUMENTS.pop(a, None) + for item in ARGLIST: + if item[0] == a: + ARGUMENTS[a] = item[1] + def _Add_Targets(tlist): if tlist: COMMAND_LINE_TARGETS.extend(tlist) diff --git a/test/AddOption/args-and-targets.py b/test/AddOption/args-and-targets.py index c703a99178..e075a44687 100644 --- a/test/AddOption/args-and-targets.py +++ b/test/AddOption/args-and-targets.py @@ -86,19 +86,50 @@ help='An argument to the option') print(str(GetOption('extra'))) print(COMMAND_LINE_TARGETS) +print(ARGUMENTS.get('A', None)) """) # opt value and target are same name -test.run('-Q -q --extra=TARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\n") -test.run('-Q -q --extra TARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\n") -test.run('-Q -q -xTARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\n") -test.run('-Q -q -x TARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\n") +test.run('-Q -q --extra=TARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") +test.run('-Q -q --extra TARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") +test.run('-Q -q -xTARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") +test.run('-Q -q -x TARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") + +# target first +test.run('-Q -q TARG1 --extra=TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") +test.run('-Q -q TARG1 --extra TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") +test.run('-Q -q TARG1 -xTARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") +test.run('-Q -q TARG1 -x TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") # equals in opt value -test.run('-Q -q --extra=A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\n") -test.run('-Q -q --extra A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\n") -test.run('-Q -q -xA=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\n") -test.run('-Q -q -x A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\n") +test.run('-Q -q --extra=A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nNone\n") +test.run('-Q -q --extra A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nNone\n") +test.run('-Q -q -xA=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nNone\n") +test.run('-Q -q -x A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nNone\n") + +# equals in opt value and a different argument +test.run('-Q -q --extra=A=B A=C TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") +test.run('-Q -q --extra A=B A=C TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") +test.run('-Q -q -xA=B A=C TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") +test.run('-Q -q -x A=B A=C TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") + +# different argument first +test.run('-Q -q A=C --extra=A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") +test.run('-Q -q A=C --extra A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") +test.run('-Q -q A=C -xA=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") +test.run('-Q -q A=C -x A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") + +# equals in opt value and the same as an argument +test.run('-Q -q --extra=A=B A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") +test.run('-Q -q --extra A=B A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") +test.run('-Q -q -xA=B A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") +test.run('-Q -q -x A=B A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") + +# same argument first +test.run('-Q -q A=B --extra=A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") +test.run('-Q -q A=B --extra A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") +test.run('-Q -q A=B -xA=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") +test.run('-Q -q A=B -x A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") test.write('SConstruct', """\ env = Environment() @@ -119,6 +150,7 @@ # Nested target test.run('-Q -q -x A TARG1', status=1, stdout="A\n\\['TARG1'\\]\n") test.run('-Q -q -x A A TARG1', status=1, stdout="A\n\\['A', 'TARG1', 'B'\\]\n") +test.run('-Q -q A -x A TARG1', status=1, stdout="A\n\\['A', 'TARG1', 'B'\\]\n") test.write('SConstruct', """\ env = Environment() @@ -155,6 +187,7 @@ return getattr\\(self.__dict__\\['__defaults__'\\], attr\\) """) test.run('-Q -q -x A A --foo=C TARG1', status=1, stdout="A\nC\n\\['A', 'TARG1'\\]\n") +test.run('-Q -q A -x A --foo=C TARG1', status=1, stdout="A\nC\n\\['A', 'TARG1'\\]\n") @@ -164,4 +197,4 @@ # tab-width:4 # indent-tabs-mode:nil # End: -# vim: set expandtab tabstop=4 shiftwidth=4: \ No newline at end of file +# vim: set expandtab tabstop=4 shiftwidth=4: From 07cf82a266d464eae150ed65dc4071ad1e0d6b85 Mon Sep 17 00:00:00 2001 From: Dillan Mills Date: Sun, 20 Sep 2020 15:03:44 -0700 Subject: [PATCH 7/9] updated comment --- SCons/Script/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SCons/Script/__init__.py b/SCons/Script/__init__.py index aac50a45ee..02c34e0419 100644 --- a/SCons/Script/__init__.py +++ b/SCons/Script/__init__.py @@ -223,8 +223,9 @@ def _Remove_Argument(aarg): if (a, b) in ARGLIST: ARGLIST.remove((a, b)) - # Set ARGUMENTS[A] back to latest value in ARGLIST (remove first in case no matching values left in ARGLIST) + # Remove first in case no matching values left in ARGLIST ARGUMENTS.pop(a, None) + # Set ARGUMENTS[A] back to latest value in ARGLIST (assuming order matches CL order) for item in ARGLIST: if item[0] == a: ARGUMENTS[a] = item[1] From aea1a889a839ad659bf806172ee38cb57754533f Mon Sep 17 00:00:00 2001 From: Dillan Mills Date: Sun, 20 Sep 2020 17:01:11 -0700 Subject: [PATCH 8/9] Added fail cases --- test/AddOption/args-and-targets.py | 63 ++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/test/AddOption/args-and-targets.py b/test/AddOption/args-and-targets.py index e075a44687..245417e163 100644 --- a/test/AddOption/args-and-targets.py +++ b/test/AddOption/args-and-targets.py @@ -190,6 +190,69 @@ test.run('-Q -q A -x A --foo=C TARG1', status=1, stdout="A\nC\n\\['A', 'TARG1'\\]\n") +############################################ +################ Fail Case ################# +############################################ + +test.write('SConstruct', """\ +env = Environment() +if 'A' in BUILD_TARGETS: + BUILD_TARGETS.append('B') +AddOption('-x', '--extra', + nargs=1, + dest='extra', + action='store', + type='string', + metavar='ARG1', + default=(), + help='An argument to the option') +print(str(GetOption('extra'))) +print(BUILD_TARGETS) +""") + +# Nested target +test.run('-Q -q -x A TARG1', status=1, stdout="A\n\\['TARG1'\\]\n") +test.run('-Q -q -x A A TARG1', status=1, stdout="A\n\\['A', 'TARG1', 'B'\\]\n") +test.run('-Q -q A -x A TARG1', status=1, stdout="A\n\\['A', 'TARG1', 'B'\\]\n") + +test.write('SConstruct', """\ +env = Environment() +if 'A' in BUILD_TARGETS: + AddOption('--foo', + nargs=1, + dest='foo', + action='store', + type='string', + metavar='FOO1', + default=(), + help='An argument to the option') +AddOption('-x', '--extra', + nargs=1, + dest='extra', + action='store', + type='string', + metavar='ARG1', + default=(), + help='An argument to the option') +print(str(GetOption('extra'))) +print(str(GetOption('foo'))) +print(COMMAND_LINE_TARGETS) +""") + +# nested option +test.run('-Q -q -x A --foo=C TARG1', status=2, stdout="A\n", stderr="""\ +AttributeError: 'Values' object has no attribute 'foo': + File ".+SConstruct", line \\d+: + print\\(str\\(GetOption\\('foo'\\)\\)\\) + File ".+SCons/Script/Main.py", line \\d+: + return getattr\\(OptionsParser.values, name\\) + File ".+SCons/Script/SConsOptions.py", line \\d+: + return getattr\\(self.__dict__\\['__defaults__'\\], attr\\) +""") +test.run('-Q -q -x A A --foo=C TARG1', status=1, stdout="A\nC\n\\['A', 'TARG1'\\]\n") +test.run('-Q -q A -x A --foo=C TARG1', status=1, stdout="A\nC\n\\['A', 'TARG1'\\]\n") + + test.pass_test() From 642a7baf1a0e6dbadad24ae04943f11760cd760d Mon Sep 17 00:00:00 2001 From: Dillan Mills Date: Sun, 20 Sep 2020 17:26:27 -0700 Subject: [PATCH 9/9] Added a test case that still fails --- test/AddOption/args-and-targets.py | 280 ++++++++++++++--------------- 1 file changed, 140 insertions(+), 140 deletions(-) diff --git a/test/AddOption/args-and-targets.py b/test/AddOption/args-and-targets.py index 245417e163..1187934fb9 100644 --- a/test/AddOption/args-and-targets.py +++ b/test/AddOption/args-and-targets.py @@ -33,161 +33,161 @@ test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) -test.write('SConstruct', """\ -env = Environment() -AddOption('-x', '--extra', - nargs=1, - dest='extra', - action='store', - type='string', - metavar='ARG1', - default=(), - help='An argument to the option') -print(str(GetOption('extra'))) -print(COMMAND_LINE_TARGETS) -""") +# test.write('SConstruct', """\ +# env = Environment() +# AddOption('-x', '--extra', +# nargs=1, +# dest='extra', +# action='store', +# type='string', +# metavar='ARG1', +# default=(), +# help='An argument to the option') +# print(str(GetOption('extra'))) +# print(COMMAND_LINE_TARGETS) +# """) -# arg using = -test.run('-Q -q --extra=A TARG', status=1, stdout="A\n\\['TARG'\\]\n") -# arg not using = -test.run('-Q -q --extra A TARG', status=1, stdout="A\n\\['TARG'\\]\n") -# short arg with space -test.run('-Q -q -x A TARG', status=1, stdout="A\n\\['TARG'\\]\n") -# short arg with no space -test.run('-Q -q -xA TARG', status=1, stdout="A\n\\['TARG'\\]\n") +# # arg using = +# test.run('-Q -q --extra=A TARG', status=1, stdout="A\n\\['TARG'\\]\n") +# # arg not using = +# test.run('-Q -q --extra A TARG', status=1, stdout="A\n\\['TARG'\\]\n") +# # short arg with space +# test.run('-Q -q -x A TARG', status=1, stdout="A\n\\['TARG'\\]\n") +# # short arg with no space +# test.run('-Q -q -xA TARG', status=1, stdout="A\n\\['TARG'\\]\n") -test.write('SConstruct', """\ -env = Environment() -AddOption('-x', '--extra', - nargs=2, - dest='extra', - action='append', - type='string', - metavar='ARG1', - default=[], - help='An argument to the option') -print(str(GetOption('extra'))) -print(COMMAND_LINE_TARGETS) -""") +# test.write('SConstruct', """\ +# env = Environment() +# AddOption('-x', '--extra', +# nargs=2, +# dest='extra', +# action='append', +# type='string', +# metavar='ARG1', +# default=[], +# help='An argument to the option') +# print(str(GetOption('extra'))) +# print(COMMAND_LINE_TARGETS) +# """) -# many args and opts -test.run('-Q -q --extra=A B TARG1 -x C D TARG2 -xE F TARG3 --extra G H TARG4', - status=1, stdout="\\[\\('A', 'B'\\), \\('C', 'D'\\), \\('E', 'F'\\), \\('G', 'H'\\)\\]\n\\['TARG1', 'TARG2', 'TARG3', 'TARG4'\\]\n") +# # many args and opts +# test.run('-Q -q --extra=A B TARG1 -x C D TARG2 -xE F TARG3 --extra G H TARG4', +# status=1, stdout="\\[\\('A', 'B'\\), \\('C', 'D'\\), \\('E', 'F'\\), \\('G', 'H'\\)\\]\n\\['TARG1', 'TARG2', 'TARG3', 'TARG4'\\]\n") -test.write('SConstruct', """\ -env = Environment() -AddOption('-x', '--extra', - nargs=1, - dest='extra', - action='store', - type='string', - metavar='ARG1', - default=(), - help='An argument to the option') -print(str(GetOption('extra'))) -print(COMMAND_LINE_TARGETS) -print(ARGUMENTS.get('A', None)) -""") +# test.write('SConstruct', """\ +# env = Environment() +# AddOption('-x', '--extra', +# nargs=1, +# dest='extra', +# action='store', +# type='string', +# metavar='ARG1', +# default=(), +# help='An argument to the option') +# print(str(GetOption('extra'))) +# print(COMMAND_LINE_TARGETS) +# print(ARGUMENTS.get('A', None)) +# """) -# opt value and target are same name -test.run('-Q -q --extra=TARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") -test.run('-Q -q --extra TARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") -test.run('-Q -q -xTARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") -test.run('-Q -q -x TARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") +# # opt value and target are same name +# test.run('-Q -q --extra=TARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") +# test.run('-Q -q --extra TARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") +# test.run('-Q -q -xTARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") +# test.run('-Q -q -x TARG1 TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") -# target first -test.run('-Q -q TARG1 --extra=TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") -test.run('-Q -q TARG1 --extra TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") -test.run('-Q -q TARG1 -xTARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") -test.run('-Q -q TARG1 -x TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") +# # target first +# test.run('-Q -q TARG1 --extra=TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") +# test.run('-Q -q TARG1 --extra TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") +# test.run('-Q -q TARG1 -xTARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") +# test.run('-Q -q TARG1 -x TARG1', status=1, stdout="TARG1\n\\['TARG1'\\]\nNone\n") -# equals in opt value -test.run('-Q -q --extra=A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nNone\n") -test.run('-Q -q --extra A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nNone\n") -test.run('-Q -q -xA=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nNone\n") -test.run('-Q -q -x A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nNone\n") +# # equals in opt value +# test.run('-Q -q --extra=A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nNone\n") +# test.run('-Q -q --extra A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nNone\n") +# test.run('-Q -q -xA=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nNone\n") +# test.run('-Q -q -x A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nNone\n") -# equals in opt value and a different argument -test.run('-Q -q --extra=A=B A=C TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") -test.run('-Q -q --extra A=B A=C TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") -test.run('-Q -q -xA=B A=C TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") -test.run('-Q -q -x A=B A=C TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") +# # equals in opt value and a different argument +# test.run('-Q -q --extra=A=B A=C TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") +# test.run('-Q -q --extra A=B A=C TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") +# test.run('-Q -q -xA=B A=C TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") +# test.run('-Q -q -x A=B A=C TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") -# different argument first -test.run('-Q -q A=C --extra=A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") -test.run('-Q -q A=C --extra A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") -test.run('-Q -q A=C -xA=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") -test.run('-Q -q A=C -x A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") +# # different argument first +# test.run('-Q -q A=C --extra=A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") +# test.run('-Q -q A=C --extra A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") +# test.run('-Q -q A=C -xA=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") +# test.run('-Q -q A=C -x A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nC\n") -# equals in opt value and the same as an argument -test.run('-Q -q --extra=A=B A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") -test.run('-Q -q --extra A=B A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") -test.run('-Q -q -xA=B A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") -test.run('-Q -q -x A=B A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") +# # equals in opt value and the same as an argument +# test.run('-Q -q --extra=A=B A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") +# test.run('-Q -q --extra A=B A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") +# test.run('-Q -q -xA=B A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") +# test.run('-Q -q -x A=B A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") -# same argument first -test.run('-Q -q A=B --extra=A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") -test.run('-Q -q A=B --extra A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") -test.run('-Q -q A=B -xA=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") -test.run('-Q -q A=B -x A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") +# # same argument first +# test.run('-Q -q A=B --extra=A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") +# test.run('-Q -q A=B --extra A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") +# test.run('-Q -q A=B -xA=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") +# test.run('-Q -q A=B -x A=B TARG1', status=1, stdout="A=B\n\\['TARG1'\\]\nB\n") -test.write('SConstruct', """\ -env = Environment() -AddOption('-x', '--extra', - nargs=1, - dest='extra', - action='store', - type='string', - metavar='ARG1', - default=(), - help='An argument to the option') -if 'A' in BUILD_TARGETS: - BUILD_TARGETS.append('B') -print(str(GetOption('extra'))) -print(BUILD_TARGETS) -""") +# test.write('SConstruct', """\ +# env = Environment() +# AddOption('-x', '--extra', +# nargs=1, +# dest='extra', +# action='store', +# type='string', +# metavar='ARG1', +# default=(), +# help='An argument to the option') +# if 'A' in BUILD_TARGETS: +# BUILD_TARGETS.append('B') +# print(str(GetOption('extra'))) +# print(BUILD_TARGETS) +# """) -# Nested target -test.run('-Q -q -x A TARG1', status=1, stdout="A\n\\['TARG1'\\]\n") -test.run('-Q -q -x A A TARG1', status=1, stdout="A\n\\['A', 'TARG1', 'B'\\]\n") -test.run('-Q -q A -x A TARG1', status=1, stdout="A\n\\['A', 'TARG1', 'B'\\]\n") +# # Nested target +# test.run('-Q -q -x A TARG1', status=1, stdout="A\n\\['TARG1'\\]\n") +# test.run('-Q -q -x A A TARG1', status=1, stdout="A\n\\['A', 'TARG1', 'B'\\]\n") +# test.run('-Q -q A -x A TARG1', status=1, stdout="A\n\\['A', 'TARG1', 'B'\\]\n") -test.write('SConstruct', """\ -env = Environment() -AddOption('-x', '--extra', - nargs=1, - dest='extra', - action='store', - type='string', - metavar='ARG1', - default=(), - help='An argument to the option') -if 'A' in BUILD_TARGETS: - AddOption('--foo', - nargs=1, - dest='foo', - action='store', - type='string', - metavar='FOO1', - default=(), - help='An argument to the option') -print(str(GetOption('extra'))) -print(str(GetOption('foo'))) -print(COMMAND_LINE_TARGETS) -""") +# test.write('SConstruct', """\ +# env = Environment() +# AddOption('-x', '--extra', +# nargs=1, +# dest='extra', +# action='store', +# type='string', +# metavar='ARG1', +# default=(), +# help='An argument to the option') +# if 'A' in BUILD_TARGETS: +# AddOption('--foo', +# nargs=1, +# dest='foo', +# action='store', +# type='string', +# metavar='FOO1', +# default=(), +# help='An argument to the option') +# print(str(GetOption('extra'))) +# print(str(GetOption('foo'))) +# print(COMMAND_LINE_TARGETS) +# """) -# nested option -test.run('-Q -q -x A --foo=C TARG1', status=2, stdout="A\n", stderr="""\ -AttributeError: 'Values' object has no attribute 'foo': - File ".+SConstruct", line \\d+: - print\\(str\\(GetOption\\('foo'\\)\\)\\) - File ".+SCons/Script/Main.py", line \\d+: - return getattr\\(OptionsParser.values, name\\) - File ".+SCons/Script/SConsOptions.py", line \\d+: - return getattr\\(self.__dict__\\['__defaults__'\\], attr\\) -""") -test.run('-Q -q -x A A --foo=C TARG1', status=1, stdout="A\nC\n\\['A', 'TARG1'\\]\n") -test.run('-Q -q A -x A --foo=C TARG1', status=1, stdout="A\nC\n\\['A', 'TARG1'\\]\n") +# # nested option +# test.run('-Q -q -x A --foo=C TARG1', status=2, stdout="A\n", stderr="""\ +# AttributeError: 'Values' object has no attribute 'foo': +# File ".+SConstruct", line \\d+: +# print\\(str\\(GetOption\\('foo'\\)\\)\\) +# File ".+SCons/Script/Main.py", line \\d+: +# return getattr\\(OptionsParser.values, name\\) +# File ".+SCons/Script/SConsOptions.py", line \\d+: +# return getattr\\(self.__dict__\\['__defaults__'\\], attr\\) +# """) +# test.run('-Q -q -x A A --foo=C TARG1', status=1, stdout="A\nC\n\\['A', 'TARG1'\\]\n") +# test.run('-Q -q A -x A --foo=C TARG1', status=1, stdout="A\nC\n\\['A', 'TARG1'\\]\n") ############################################