Add Python Value Nodes. (Chad Austin)
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Thu, 1 May 2003 12:19:09 +0000 (12:19 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Thu, 1 May 2003 12:19:09 +0000 (12:19 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@667 fdb21ef1-2011-0410-befe-b5e4ea1792b1

bin/files
doc/man/scons.1
src/CHANGES.txt
src/engine/MANIFEST.in
src/engine/SCons/Node/Python.py [new file with mode: 0644]
src/engine/SCons/Node/PythonTests.py [new file with mode: 0644]
src/engine/SCons/Script/SConscript.py
test/Value.py [new file with mode: 0644]

index ccb608952226f55ac2aedfdd1fd605d89adaf9d2..3af157283cda5385433fba7405b128f71d4f2feb 100644 (file)
--- a/bin/files
+++ b/bin/files
@@ -6,6 +6,7 @@
 ./SCons/Job.py
 ./SCons/Node/Alias.py
 ./SCons/Node/FS.py
+./SCons/Node/Python.py
 ./SCons/Node/__init__.py
 ./SCons/Options.py
 ./SCons/Platform/__init__.py
index c96c8b805a94f80b056ca0a86df068022fc63e6f..14a2e501892b76de1c971d5a58fcac8c4c9699f2 100644 (file)
@@ -4063,6 +4063,27 @@ tools keyword of the Environment() method.
 env = Environment(tools = [ Tool('msvc') ])
 .EE
 
+.TP
+.RI Value( value )
+Returns a Node object representing the specified Python value.  Value
+nodes can be used as dependencies of targets.  If the result of
+calling
+.BR str( value )
+changes between SCons runs, any targets depending on
+.BR Value( value )
+will be rebuilt.
+
+.ES
+def create(target, source, env):
+    f = open(str(target[0]), 'wb')
+    f.write('prefix=' + source[0].get_contents())
+    
+prefix = ARGUMENTS.get('prefix', '/usr/local')
+env = Environment()
+env['BUILDERS']['Config'] = Builder(action = create)
+env.Config(target = 'package-config', source = Value(prefix))
+.EE
+
 .TP
 .RI WhereIs( program ", [" path  ", [" pathext ]])
 
index f6bdee0f7ec9135a21f06d82be0f25f57a5dae17..196c28d672b303d097a0f9cdbad82b057e8e672d 100644 (file)
@@ -28,6 +28,8 @@ RELEASE 0.14 - XXX
 
   - Portability fixes for a lot of tests.
 
+  - Add a Value Node class for dependencies on in-core Python values.
+
   From Allen Bierbaum:
 
   - Pass an Environment to the Options validator method, and
index ca713ff879cfc0763ef92462e220fb765eb57e3f..c028989eb4de583243cec538bc1ed6d8667f3218 100644 (file)
@@ -9,6 +9,7 @@ SCons/exitfuncs.py
 SCons/Node/__init__.py
 SCons/Node/Alias.py
 SCons/Node/FS.py
+SCons/Node/Python.py
 SCons/Optik/__init__.py
 SCons/Optik/errors.py
 SCons/Optik/option.py
diff --git a/src/engine/SCons/Node/Python.py b/src/engine/SCons/Node/Python.py
new file mode 100644 (file)
index 0000000..9348b83
--- /dev/null
@@ -0,0 +1,76 @@
+"""scons.Node.Python
+
+Python nodes.
+
+"""
+
+#
+# __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__"
+
+import SCons.Node
+
+class Value(SCons.Node.Node):
+    """A class for Python variables, typically passed on the command line 
+    or generated by a script, but not from a file or some other source.
+    """
+    def __init__(self, value):
+        SCons.Node.Node.__init__(self)
+        self.value = value
+
+    def __str__(self):
+        return repr(self.value)
+
+    def build(self):
+        """A "builder" for Values."""
+        pass
+
+    def current(self, calc):
+        """If all of our children were up-to-date, then this
+        Value was up-to-date, too."""
+        # Allow the children to calculate their signatures.
+        calc.bsig(self)
+        state = 0
+        for kid in self.children(None):
+            s = kid.get_state()
+            if s and (not state or s > state):
+                state = s
+        if state == 0 or state == SCons.Node.up_to_date:
+            return 1
+        else:
+            return 0
+
+    def is_under(self, dir):
+        # Make Value nodes get built regardless of 
+        # what directory scons was run from. Value nodes
+        # are outside the filesystem:
+        return 1
+
+    def get_contents(self):
+        """The contents of a Value are the concatenation
+        of all the contents of its sources with the node's value itself."""
+        contents = str(self.value)
+        for kid in self.children(None):
+            contents = contents + kid.get_contents()
+        return contents
diff --git a/src/engine/SCons/Node/PythonTests.py b/src/engine/SCons/Node/PythonTests.py
new file mode 100644 (file)
index 0000000..0befa25
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# __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__"
+
+import sys
+import unittest
+
+import SCons.Errors
+import SCons.Node.Python
+
+class ValueTestCase(unittest.TestCase):
+
+    def test_Value(self):
+        """Test creating a Value() object
+        """
+        v1 = SCons.Node.Python.Value('a')
+        assert v1.value == 'a', v1.value
+
+        value2 = 'a'
+        v2 = SCons.Node.Python.Value(value2)
+        assert v2.value == value2, v2.value
+        assert v2.value is value2, v2.value
+
+        assert not v1 is v2
+        assert v1.value == v2.value
+
+
+if __name__ == "__main__":
+    suite = unittest.makeSuite(ValueTestCase, 'test_')
+    if not unittest.TextTestRunner().run(suite).wasSuccessful():
+        sys.exit(1)
index 6b28b928b9e1149e2100ad5b2d66fe8ef443b79c..af8cc79ea45cc2ab58776b2f6d396cdee56fb0ea 100644 (file)
@@ -37,6 +37,7 @@ import SCons.Environment
 import SCons.Errors
 import SCons.Node
 import SCons.Node.FS
+import SCons.Node.Python
 import SCons.Platform
 import SCons.SConf
 import SCons.Script
@@ -561,5 +562,6 @@ def BuildDefaultGlobals():
     globals['StaticObject']      = SCons.Defaults.StaticObject
     globals['TargetSignatures']  = TargetSignatures
     globals['Tool']              = SCons.Tool.Tool
+    globals['Value']             = SCons.Node.Python.Value
     globals['WhereIs']           = SCons.Util.WhereIs
     return globals
diff --git a/test/Value.py b/test/Value.py
new file mode 100644 (file)
index 0000000..f3df6fe
--- /dev/null
@@ -0,0 +1,103 @@
+#!/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__"
+
+import os
+import re
+import string
+import sys
+import TestSCons
+import TestCmd
+
+test = TestSCons.TestSCons(match=TestCmd.match_re)
+
+test.write('SConstruct', """
+class Custom:
+    def __init__(self, value):  self.value = value
+    def __str__(self):          return "C=" + str(self.value)
+
+P = ARGUMENTS.get('prefix', '/usr/local')
+L = len(P)
+C = Custom(P)
+
+def create(target, source, env):
+    open(str(target[0]), 'wb').write(source[0].get_contents())
+
+env = Environment()
+env['BUILDERS']['B'] = Builder(action = create)
+env.B('f1.out', Value(P))
+env.B('f2.out', Value(L))
+env.B('f3.out', Value(C))
+""")
+
+
+test.run()
+out1 = """create("f1.out", "'/usr/local'")"""
+out2 = """create("f2.out", "10")"""
+out3 = """create\\("f3.out", "<.*.Custom instance at """
+test.fail_test(string.find(test.stdout(), out1) == -1)
+test.fail_test(string.find(test.stdout(), out2) == -1)
+test.fail_test(re.search(out3, test.stdout()) == None)
+
+test.fail_test(not os.path.exists(test.workpath('f1.out')))
+test.fail_test(open(test.workpath('f1.out'), 'rb').read() != '/usr/local')
+test.fail_test(not os.path.exists(test.workpath('f2.out')))
+test.fail_test(open(test.workpath('f2.out'), 'rb').read() != '10')
+test.fail_test(not os.path.exists(test.workpath('f3.out')))
+test.fail_test(open(test.workpath('f3.out'), 'rb').read() != 'C=/usr/local')
+
+test.up_to_date(arguments = ".")
+
+test.run(arguments = 'prefix=/usr')
+out4 = """create("f1.out", "'/usr'")"""
+out5 = """create("f2.out", "4")"""
+out6 = """create\\("f3.out", "<.*.Custom instance at """
+test.fail_test(string.find(test.stdout(), out4) == -1)
+test.fail_test(string.find(test.stdout(), out5) == -1)
+test.fail_test(re.search(out6, test.stdout()) == None)
+
+test.fail_test(not os.path.exists(test.workpath('f1.out')))
+test.fail_test(open(test.workpath('f1.out'), 'rb').read() != '/usr')
+test.fail_test(not os.path.exists(test.workpath('f2.out')))
+test.fail_test(open(test.workpath('f2.out'), 'rb').read() != '4')
+test.fail_test(not os.path.exists(test.workpath('f3.out')))
+test.fail_test(open(test.workpath('f3.out'), 'rb').read() != 'C=/usr')
+
+test.unlink('f3.out')
+
+test.run(arguments = 'prefix=/var')
+out4 = """create("f1.out", "'/var'")"""
+test.fail_test(string.find(test.stdout(), out4) == -1)
+test.fail_test(string.find(test.stdout(), out5) != -1)
+test.fail_test(re.search(out6, test.stdout()) == None)
+
+test.fail_test(not os.path.exists(test.workpath('f1.out')))
+test.fail_test(open(test.workpath('f1.out'), 'rb').read() != '/var')
+test.fail_test(not os.path.exists(test.workpath('f2.out')))
+test.fail_test(open(test.workpath('f2.out'), 'rb').read() != '4')
+test.fail_test(not os.path.exists(test.workpath('f3.out')))
+test.fail_test(open(test.workpath('f3.out'), 'rb').read() != 'C=/var')
+
+test.pass_test()