summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Deegan <bill@baddogconsulting.com>2021-03-28 19:44:15 (GMT)
committerGitHub <noreply@github.com>2021-03-28 19:44:15 (GMT)
commitb7477f0274bfad9ed8e8b98c328ab4263f6bfb62 (patch)
tree7cceb3e058a3acfe49881e8beb9889ca4c6acd8f
parent485749728ff769dbe9148bd3a946ad03e3e4ee64 (diff)
parenta256652f5b436d692ac0237d7f12a81a591fcb2a (diff)
downloadSCons-b7477f0274bfad9ed8e8b98c328ab4263f6bfb62.zip
SCons-b7477f0274bfad9ed8e8b98c328ab4263f6bfb62.tar.gz
SCons-b7477f0274bfad9ed8e8b98c328ab4263f6bfb62.tar.bz2
Merge pull request #3916 from mwichmann/issue2399
Add a __iadd__ method to CLVar to support inplace adds
-rwxr-xr-xCHANGES.txt2
-rw-r--r--SCons/Util.py30
-rw-r--r--SCons/UtilTests.py133
3 files changed, 101 insertions, 64 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index d400ceb..41ffe4e 100755
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -45,6 +45,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
- Remove long-deprecated construction variables PDFCOM, WIN32_INSERT_DEF,
WIN32DEFPREFIX, WIN32DEFSUFFIX, WIN32EXPPREFIX, WIN32EXPSUFFIX.
All have been replaced by other names since at least 1.0.
+ - Add a __iadd__ method to the CLVar class so that inplace adds
+ (+=) also work as expected (issue 2399)
- Remove local copy of CLVar in EnvironmentTests unittest file -
should be testing against the production version, and they
didn't really differ.
diff --git a/SCons/Util.py b/SCons/Util.py
index e614880..37107c9 100644
--- a/SCons/Util.py
+++ b/SCons/Util.py
@@ -1048,22 +1048,38 @@ def Split(arg):
else:
return [arg]
+
class CLVar(UserList):
"""A class for command-line construction variables.
- This is a list that uses Split() to split an initial string along
- white-space arguments, and similarly to split any strings that get
- added. This allows us to Do the Right Thing with Append() and
+ Forces the use of a list of strings, matching individual arguments
+ that will be issued on the command line. Like UserList,
+ but the argument passed to __init__ will be processed by the
+ Split function, which includes special handling for string types -
+ they will be split into a list of words, not coereced directly
+ to a list. The same happens if adding a string,
+ which allows us to Do the Right Thing with Append() and
Prepend() (as well as straight Python foo = env['VAR'] + 'arg1
arg2') regardless of whether a user adds a list or a string to a
command-line construction variable.
+
+ Side effect: spaces will be stripped from individual string
+ arguments. If you need spaces preserved, pass strings containing
+ spaces inside a list argument.
"""
- def __init__(self, seq = []):
- UserList.__init__(self, Split(seq))
+
+ def __init__(self, seq=[]):
+ super().__init__(Split(seq))
+
def __add__(self, other):
- return UserList.__add__(self, CLVar(other))
+ return super().__add__(CLVar(other))
+
def __radd__(self, other):
- return UserList.__radd__(self, CLVar(other))
+ return super().__radd__(CLVar(other))
+
+ def __iadd__(self, other):
+ return super().__iadd__(CLVar(other))
+
def __str__(self):
return ' '.join(self.data)
diff --git a/SCons/UtilTests.py b/SCons/UtilTests.py
index 817ad02..8e39a16 100644
--- a/SCons/UtilTests.py
+++ b/SCons/UtilTests.py
@@ -550,101 +550,120 @@ class UtilTestCase(unittest.TestCase):
def test_CLVar(self):
"""Test the command-line construction variable class"""
- f = SCons.Util.CLVar('a b')
- r = f + 'c d'
+ # input to CLVar is a string - should be split
+ f = SCons.Util.CLVar('aa bb')
+
+ r = f + 'cc dd'
assert isinstance(r, SCons.Util.CLVar), type(r)
- assert r.data == ['a', 'b', 'c', 'd'], r.data
- assert str(r) == 'a b c d', str(r)
+ assert r.data == ['aa', 'bb', 'cc', 'dd'], r.data
+ assert str(r) == 'aa bb cc dd', str(r)
- r = f + ' c d'
+ r = f + ' cc dd'
assert isinstance(r, SCons.Util.CLVar), type(r)
- assert r.data == ['a', 'b', 'c', 'd'], r.data
- assert str(r) == 'a b c d', str(r)
+ assert r.data == ['aa', 'bb', 'cc', 'dd'], r.data
+ assert str(r) == 'aa bb cc dd', str(r)
- r = f + ['c d']
+ r = f + ['cc dd']
assert isinstance(r, SCons.Util.CLVar), type(r)
- assert r.data == ['a', 'b', 'c d'], r.data
- assert str(r) == 'a b c d', str(r)
+ assert r.data == ['aa', 'bb', 'cc dd'], r.data
+ assert str(r) == 'aa bb cc dd', str(r)
- r = f + [' c d']
+ r = f + [' cc dd']
assert isinstance(r, SCons.Util.CLVar), type(r)
- assert r.data == ['a', 'b', ' c d'], r.data
- assert str(r) == 'a b c d', str(r)
+ assert r.data == ['aa', 'bb', ' cc dd'], r.data
+ assert str(r) == 'aa bb cc dd', str(r)
- r = f + ['c', 'd']
+ r = f + ['cc', 'dd']
assert isinstance(r, SCons.Util.CLVar), type(r)
- assert r.data == ['a', 'b', 'c', 'd'], r.data
- assert str(r) == 'a b c d', str(r)
+ assert r.data == ['aa', 'bb', 'cc', 'dd'], r.data
+ assert str(r) == 'aa bb cc dd', str(r)
- r = f + [' c', 'd']
+ r = f + [' cc', 'dd']
assert isinstance(r, SCons.Util.CLVar), type(r)
- assert r.data == ['a', 'b', ' c', 'd'], r.data
- assert str(r) == 'a b c d', str(r)
+ assert r.data == ['aa', 'bb', ' cc', 'dd'], r.data
+ assert str(r) == 'aa bb cc dd', str(r)
- f = SCons.Util.CLVar(['a b'])
+ # input to CLVar is a list of one string, should not be split
+ f = SCons.Util.CLVar(['aa bb'])
- r = f + 'c d'
+ r = f + 'cc dd'
assert isinstance(r, SCons.Util.CLVar), type(r)
- assert r.data == ['a b', 'c', 'd'], r.data
- assert str(r) == 'a b c d', str(r)
+ assert r.data == ['aa bb', 'cc', 'dd'], r.data
+ assert str(r) == 'aa bb cc dd', str(r)
- r = f + ' c d'
+ r = f + ' cc dd'
assert isinstance(r, SCons.Util.CLVar), type(r)
- assert r.data == ['a b', 'c', 'd'], r.data
- assert str(r) == 'a b c d', str(r)
+ assert r.data == ['aa bb', 'cc', 'dd'], r.data
+ assert str(r) == 'aa bb cc dd', str(r)
- r = f + ['c d']
+ r = f + ['cc dd']
assert isinstance(r, SCons.Util.CLVar), type(r)
- assert r.data == ['a b', 'c d'], r.data
- assert str(r) == 'a b c d', str(r)
+ assert r.data == ['aa bb', 'cc dd'], r.data
+ assert str(r) == 'aa bb cc dd', str(r)
- r = f + [' c d']
+ r = f + [' cc dd']
assert isinstance(r, SCons.Util.CLVar), type(r)
- assert r.data == ['a b', ' c d'], r.data
- assert str(r) == 'a b c d', str(r)
+ assert r.data == ['aa bb', ' cc dd'], r.data
+ assert str(r) == 'aa bb cc dd', str(r)
- r = f + ['c', 'd']
+ r = f + ['cc', 'dd']
assert isinstance(r, SCons.Util.CLVar), type(r)
- assert r.data == ['a b', 'c', 'd'], r.data
- assert str(r) == 'a b c d', str(r)
+ assert r.data == ['aa bb', 'cc', 'dd'], r.data
+ assert str(r) == 'aa bb cc dd', str(r)
- r = f + [' c', 'd']
+ r = f + [' cc', 'dd']
assert isinstance(r, SCons.Util.CLVar), type(r)
- assert r.data == ['a b', ' c', 'd'], r.data
- assert str(r) == 'a b c d', str(r)
+ assert r.data == ['aa bb', ' cc', 'dd'], r.data
+ assert str(r) == 'aa bb cc dd', str(r)
- f = SCons.Util.CLVar(['a', 'b'])
+ # input to CLVar is a list of strings
+ f = SCons.Util.CLVar(['aa', 'bb'])
- r = f + 'c d'
+ r = f + 'cc dd'
assert isinstance(r, SCons.Util.CLVar), type(r)
- assert r.data == ['a', 'b', 'c', 'd'], r.data
- assert str(r) == 'a b c d', str(r)
+ assert r.data == ['aa', 'bb', 'cc', 'dd'], r.data
+ assert str(r) == 'aa bb cc dd', str(r)
- r = f + ' c d'
+ r = f + ' cc dd'
assert isinstance(r, SCons.Util.CLVar), type(r)
- assert r.data == ['a', 'b', 'c', 'd'], r.data
- assert str(r) == 'a b c d', str(r)
+ assert r.data == ['aa', 'bb', 'cc', 'dd'], r.data
+ assert str(r) == 'aa bb cc dd', str(r)
- r = f + ['c d']
+ r = f + ['cc dd']
assert isinstance(r, SCons.Util.CLVar), type(r)
- assert r.data == ['a', 'b', 'c d'], r.data
- assert str(r) == 'a b c d', str(r)
+ assert r.data == ['aa', 'bb', 'cc dd'], r.data
+ assert str(r) == 'aa bb cc dd', str(r)
- r = f + [' c d']
+ r = f + [' cc dd']
assert isinstance(r, SCons.Util.CLVar), type(r)
- assert r.data == ['a', 'b', ' c d'], r.data
- assert str(r) == 'a b c d', str(r)
+ assert r.data == ['aa', 'bb', ' cc dd'], r.data
+ assert str(r) == 'aa bb cc dd', str(r)
- r = f + ['c', 'd']
+ r = f + ['cc', 'dd']
assert isinstance(r, SCons.Util.CLVar), type(r)
- assert r.data == ['a', 'b', 'c', 'd'], r.data
- assert str(r) == 'a b c d', str(r)
+ assert r.data == ['aa', 'bb', 'cc', 'dd'], r.data
+ assert str(r) == 'aa bb cc dd', str(r)
- r = f + [' c', 'd']
+ r = f + [' cc', 'dd']
assert isinstance(r, SCons.Util.CLVar), type(r)
- assert r.data == ['a', 'b', ' c', 'd'], r.data
- assert str(r) == 'a b c d', str(r)
+ assert r.data == ['aa', 'bb', ' cc', 'dd'], r.data
+ assert str(r) == 'aa bb cc dd', str(r)
+
+ # make sure inplace adding a string works as well (issue 2399)
+ # UserList would convert the string to a list of chars
+ f = SCons.Util.CLVar(['aa', 'bb'])
+ f += 'cc dd'
+ assert isinstance(f, SCons.Util.CLVar), type(f)
+ assert f.data == ['aa', 'bb', 'cc', 'dd'], f.data
+ assert str(f) == 'aa bb cc dd', str(f)
+
+ f = SCons.Util.CLVar(['aa', 'bb'])
+ f += ' cc dd'
+ assert isinstance(f, SCons.Util.CLVar), type(f)
+ assert f.data == ['aa', 'bb', 'cc', 'dd'], f.data
+ assert str(f) == 'aa bb cc dd', str(f)
+
def test_Selector(self):
"""Test the Selector class"""