From 39d50eb2332228e827b56638877862f4c709a6bf Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Thu, 2 May 2002 13:40:38 +0000 Subject: Add a Split() function (like argmunge()) in anticipation of removing the automatic white-space splitting from Builders in 0.08. --- doc/man/scons.1 | 94 ++++++++++++++++++++++++++++------- src/CHANGES.txt | 4 ++ src/RELEASE.txt | 32 ++++++++++++ src/engine/SCons/Builder.py | 3 ++ src/engine/SCons/Node/__init__.py | 6 +++ src/engine/SCons/Script/SConscript.py | 1 + src/engine/SCons/Util.py | 12 +++-- src/engine/SCons/UtilTests.py | 8 +-- test/Split.py | 54 ++++++++++++++++++++ 9 files changed, 189 insertions(+), 25 deletions(-) create mode 100644 test/Split.py diff --git a/doc/man/scons.1 b/doc/man/scons.1 index 3fcfc80..a716147 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -33,7 +33,7 @@ .RE .fi .. -.TH SCONS 1 "April 2002" +.TH SCONS 1 "May 2002" .SH NAME scons \- a software construction tool .SH SYNOPSIS @@ -630,16 +630,33 @@ env = Environment() Build rules are specified by calling builder methods on a construction environment. The arguments to the builder methods are target (a list of -target files) and source (a list of source files). If a string is given +target files) and source (a list of source files). +If a string is given for target or source, then .B scons -interprets it as a space delimited list -of files. The following are examples of calling a builder: +.I currently +interprets it as a space-delimited list of files. +NOTE: Splitting a string into a list of files this +way will be +.I removed +as of the next version of SCons. +If you currently use space-delimited file lists, +you must change them by next release. +See the discussion of the Split() function +for more information. + +The following are examples of calling a builder: + +.ES +# The recommended ways to call a builder +# with multiple source input files: +env.Program('bar', ['bar.c', 'foo.c']) +env.Program('bar', Split('bar.c foo.c')) -.ES +# Space-delimited lists. +# The following will NOT work in version 0.08 of SCons! env.Program(target = 'bar', source = 'bar.c foo.c') env.Program('bar', 'bar.c foo.c') -env.Program('bar', ['bar.c', 'foo.c']) .EE .B scons @@ -1465,9 +1482,15 @@ is usually safe, and is always more efficient than .RI Default( targets ) This specifies a list of default targets. Default targets will be built by .B scons -if no explicit targets are given on the command line. Multiple targets can -be specified either as a space delimited string of target file names or as -separate arguments. +if no explicit targets are given on the command line. +Multiple targets should be specified as +separate arguments to the +.BR Default () +method. +In this version of SCons (0.07), +.BR Default () +will also accept a space-delimited string of target file names; +this functionality will be removed in the next version of SCons (0.08). Target names with white space may be be enclosed in an array to prevent the string from being split into separate file names. @@ -1497,12 +1520,13 @@ to export a list of variables from the current configuration file to all other configuration files. The exported variables are kept in a global collection, so subsequent exports will over-write previous exports that have the same name. -Multiple variable names can be passed to +Multiple variable names should be passed to .BR Export () -in a space delimited string or as seperate arguments. Example: +as separate arguments. Examples: .ES Export("env") +Export("env", "variable") .EE .TP @@ -1536,12 +1560,15 @@ argument to .BR SConscript (). Variables exported by .BR SConscript () -have precedence. Multiple variable names can be passed to +have precedence. +Multiple variable names should be passed to .BR Import () -in a space delimited string or as seperate arguments. Example: +as separate arguments. +Examples: .ES Import("env") +Import("env", "variable") .EE .TP @@ -1552,12 +1579,13 @@ what variable(s) to use as the return value(s) of the current configuration file. These variables will be returned to the "calling" configuration file as the return value(s) of .BR SConscript (). -Multiple variable names can be passed to +Multiple variable names should be passed to .BR Return () -in a space delimited string or as seperate arguments. Example: +as a list. Example: .ES Return("foo") +Return(["foo", "bar"]) .EE .TP @@ -1569,8 +1597,7 @@ to execute as a configuration file. The optional .I exports argument provides a list of variable names to export to -.IR script ". " exports -can also be a space delimited string of variables names. +.IR script ". " .I script must use the .BR Import () @@ -1631,6 +1658,39 @@ is a dictionary of the environment variables in which the command should be executed. .TP +.RI Split( arg ) +Returns a list of file names or other objects. +If arg is a string, +it will be split on strings of white-space characters +within the string, +making it easier to write long lists of file names. +If arg is already a list, +the list will be returned untouched. +If arg is any other type of object, +it will be returned as a list +containing just the object. + +.ES +files = Split("f1.c f2.c f3.c") +files = Split(""" + f4.c + f5.c + f6.c +""") +.EE +.IP +NOTE: Currently, all builders perform this white-space split +automatically on their target and source file arguments. +As of the next version of SCons, +Builder objects will no longer perform this split. +If you use white-space separated strings of file names, +you will need to convert them to lists +by the next release of SCons by hand, +or by using the Split() function provided here, +or by using a similar function such as the +string.split() function in the Python library. + +.TP .RI WhereIs( program ", [" path ", [" pathext ]]) Searches for the specified executable diff --git a/src/CHANGES.txt b/src/CHANGES.txt index f152670..caaaf3e 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -109,6 +109,10 @@ RELEASE 0.07 - Thu, 25 Apr 2002 06:24:50 -0500 A -X option indicates it's an executable, not a script to feed to the Python interpreter. + - Add a Split() function (identical to SCons.Util.argmunge()) for use + in the next release, when Builders will no longer automatically split + strings on white space. + From Steve Leblanc: - Add the SConscriptChdir() method. diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 1d0a5a9..803869a 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -67,6 +67,38 @@ RELEASE 0.07 - Thu, 25 Apr 2002 06:24:50 -0500 open(str(target), 'w').write(open(str(source), 'r').read()) return 0 + Please not the following UPCOMING very important change: + + - As of the next SCons release (0.08), Builder objects will no longer + automatically split target and source file strings on white space. + SCons will interpret the string arguments for the target or source + files as the complete name of the file, even if the name contains + white space. + + Consequently, any builder calls that you have defined which supply + multiple file names in a single string, such as: + + env.Program(target = 'foo', source = 'f1.c f2.c') + + These calls will need to be changed by next release. You may + either split up the string into an array of individual file name + strings by hand: + + env.Program(target = 'foo', source = ['f1.c', 'f2.c']) + + Or you may use the newly-provided Split() function to turn a + string of white-space separated file names into an array: + + env.Program(target = 'foo', source = Split('f1.c f2.c')) + + The Split() function preserves the functionality that the builder + objects currently invoke internally: if the argument is a string, + it will be split on white space; if the argument is already a list, + the list will be returned. + + (You may, of course, also use the string.split() function from + the standard Python library to convert your strings.) + Owing to an extensive test suite, the SCons team believes that this release is of sufficient quality that you can use it for real work, despite the "alpha" label. diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index 05330e4..a28a31d 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -218,6 +218,9 @@ class BuilderBase: """ def adjustixes(files, pre, suf): ret = [] + # FOR RELEASE 0.08: + #if not SCons.Util.is_List(files): + # files = [files] files = SCons.Util.argmunge(files) for f in files: diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 68e4c73..68a55f8 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -398,6 +398,9 @@ arg2nodes_lookups = [] def arg2nodes(arg, node_factory=None): + # FOR RELEASE 0.08: + #"""This function converts a string or list into a list of Node + #instances.""" """This function converts a string or list into a list of Node instances. It follows the rules outlined in the SCons design document by accepting any of the following inputs: @@ -408,6 +411,9 @@ def arg2nodes(arg, node_factory=None): in the list are not split at spaces. In all cases, the function returns a list of Node instances.""" + # FOR RELEASE 0.08: + #if not SCons.Util.is_List(arg): + # arg = [arg] narg = SCons.Util.argmunge(arg) nodes = [] diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py index a6f293d..79e2a60 100644 --- a/src/engine/SCons/Script/SConscript.py +++ b/src/engine/SCons/Script/SConscript.py @@ -263,5 +263,6 @@ def BuildDefaultGlobals(): globals['SConscript'] = SConscript globals['SConscriptChdir'] = SConscriptChdir globals['SetCommandHandler'] = SCons.Action.SetCommandHandler + globals['Split'] = SCons.Util.Split globals['WhereIs'] = SCons.Util.WhereIs return globals diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 08edde7..7912abb 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -297,12 +297,16 @@ def to_String(s): return str(s) def argmunge(arg): - """This function converts a string or list into a list of strings or Nodes. - It follows the rules outlined in the SCons design document by accepting - any of the following inputs: + return Split(arg) + +def Split(arg): + """This function converts a string or list into a list of strings + or Nodes. This makes things easier for users by allowing files to + be specified as a white-space separated list to be split. + The input rules are: - A single string containing names separated by spaces. These will be split apart at the spaces. - - A single None instance + - A single Node instance - A list containing either strings or Node instances. Any strings in the list are not split at spaces. In all cases, the function returns a list of Nodes and strings.""" diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index 34dba99..4f3195f 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -240,10 +240,10 @@ class UtilTestCase(unittest.TestCase): if hasattr(types, 'UnicodeType'): exec "assert not is_List(u'')" - def test_argmunge(self): - assert argmunge("foo bar") == ["foo", "bar"] - assert argmunge(["foo", "bar"]) == ["foo", "bar"] - assert argmunge("foo") == ["foo"] + def test_Split(self): + assert Split("foo bar") == ["foo", "bar"] + assert Split(["foo", "bar"]) == ["foo", "bar"] + assert Split("foo") == ["foo"] def test_is_String(self): assert is_String("") diff --git a/test/Split.py b/test/Split.py new file mode 100644 index 0000000..ee1a435 --- /dev/null +++ b/test/Split.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# +# Copyright (c) 2001, 2002 Steven Knight +# +# 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__" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +print Split('aaa') +print Split('bbb ccc') +print Split(['ddd', 'eee']) +SConscript('SConscript') +""") + +test.write('SConscript', """ +print Split('fff') +print Split('ggg hhh') +print Split(['iii', 'jjj']) +""") + +expect = """['aaa'] +['bbb', 'ccc'] +['ddd', 'eee'] +['fff'] +['ggg', 'hhh'] +['iii', 'jjj'] +""" + +test.run(stdout = expect) + +test.pass_test() -- cgit v0.12