Fix Options.Update().
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Mon, 9 Jun 2003 10:14:17 +0000 (10:14 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Mon, 9 Jun 2003 10:14:17 +0000 (10:14 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@704 fdb21ef1-2011-0410-befe-b5e4ea1792b1

doc/man/scons.1
src/CHANGES.txt
src/engine/SCons/Options.py
src/engine/SCons/OptionsTests.py
src/engine/SCons/Script/SConscript.py
test/Options.py

index 32546ed9c553840b8ba51e319701055e4ddc2fce..054bbd127617565ef1426600cf82469db399b9d4 100644 (file)
@@ -3393,14 +3393,30 @@ command line or a text-based SConscript file through an Options
 object. To create an Options object, call the Options() function:
 
 .TP
-.RI Options([ files ])
+.RI Options([ files "], [" args ])
 This creates an Options object that will read construction variables from
-the file or list of filenames given in the  
+the file or list of filenames specified in
+.IR files .
+If no files are specified,
+or the
 .I files
-argument. If no files are given, then no files will be read. Example:
+argument is
+.BR None ,
+then no files will be read.
+The optional argument
+.I args
+is a dictionary of
+values that will override anything read from the specified files;
+it is primarily intended to be passed the
+.B ARGUMENTS
+dictionary that holds variables
+specified on the command line.
+Example:
 
 .ES
 opts = Options('custom.py')
+opts = Options('overrides.py', ARGUMENTS)
+opts = Options(None, {FOO:'expansion', BAR:7})
 .EE
 
 Options objects have the following methods:
@@ -3426,7 +3442,7 @@ opts.Add('CC', 'The C compiler')
 .EE
 
 .TP
-.RI Update( env )
+.RI Update( env ", [" args ])
 This updates a construction environment
 .I env
 with the customized construction variables. Normally this method is not
index dd976ef5dedd26a5e4fc78864464226e69ebf54e..b04942eae7407ec925d622bc2ca82e24f88a4d4c 100644 (file)
@@ -31,6 +31,9 @@ RELEASE 0.15 - XXX
   - Eliminate a dependency on the distutils.fancy_getopt module by
     copying and pasting its wrap_text() function directly.
 
+  - Make the Script.Options() subclass match the underlying base class
+    implementation.
+
   From Steve Leblanc:
 
   - Don't update the .sconsign files when run with -n.
index 9d315b84b6337d88accdc528966dc312c82306f7..953f1a44e6af1402df0329e79f3e2d449f10b2bb 100644 (file)
@@ -39,7 +39,7 @@ class Options:
     Holds all the options, updates the environment with the variables,
     and renders the help text.
     """
-    def __init__(self, files=None):
+    def __init__(self, files=None, args={}):
         """
         files - [optional] List of option configuration files to load
             (backward compatibility) If a single string is passed it is 
@@ -47,6 +47,7 @@ class Options:
         """
 
         self.options = []
+        self.args = args
         self.files = None
         if SCons.Util.is_String(files):
            self.files = [ files ]
@@ -83,12 +84,11 @@ class Options:
 
         self.options.append(option)
 
-    def Update(self, env, args):
+    def Update(self, env, args=None):
         """
         Update an environment with the option variables.
 
         env - the environment to update.
-        args - the dictionary to get the command line arguments from.
         """
 
         values = {}
@@ -105,12 +105,15 @@ class Options:
                  execfile(filename, values)
 
         # finally set the values specified on the command line
+        if args is None:
+            args = self.args
         values.update(args)
         
-        # Update the should save state
-        # This will mark options that have either been set on command line
-        # or in a loaded option file
-        # KeyError occurs when an option has default of None and has not been set
+        # Update should save state.
+        # This will mark options that have either been set on
+        # the command line or in a loaded option file.
+        # KeyError occurs when an option has default of None
+        # and has not been set.
         for option in self.options:
             try:
                 if values[option.key] != option.default:
@@ -177,7 +180,8 @@ class Options:
         """
         Generate the help text for the options.
 
-        env - an environment that is used to get the current values of the options.
+        env - an environment that is used to get the current values
+              of the options.
         """
 
         help_text = ""
@@ -196,4 +200,3 @@ class Options:
                 help_text = help_text + '    actual: None\n'
 
         return help_text
-
index 93705c0ee002108131c4fc28b85d5d8b9ebeef33..ce8bee7696302eec7ce0aa3cd70930954b6e04ab 100644 (file)
@@ -43,8 +43,8 @@ class Environment:
         return self.dict.has_key(key)
 
 
-def check(key,value, env):
-    assert value == 6 * 9,key
+def check(key, value, env):
+    assert value == 6 * 9, "key %s = %s" % (key, value)
     
 # Check saved option file by executing and comparing against
 # the expected dictionary
@@ -56,6 +56,7 @@ def checkSave(file, expected):
 
 class OptionsTestCase(unittest.TestCase):
     def test_Add(self):
+        """Test adding to an Options object"""
         opts = SCons.Options.Options()
 
         opts.Add('VAR')
@@ -91,7 +92,9 @@ class OptionsTestCase(unittest.TestCase):
         test_it('foo.bar')
 
     def test_Update(self):
+        """Test updating an Environment"""
 
+        # Test that a default value is validated correctly.
         test = TestSCons.TestSCons()
         file = test.workpath('custom.py')
         opts = SCons.Options.Options(file)
@@ -102,10 +105,16 @@ class OptionsTestCase(unittest.TestCase):
                  check,
                  lambda x: int(x) + 12)
 
+        env = Environment()
+        opts.Update(env)
+        assert env['ANSWER'] == 54
+
         env = Environment()
         opts.Update(env, {})
         assert env['ANSWER'] == 54
 
+        # Test that a bad value from the file is used and
+        # validation fails correctly.
         test = TestSCons.TestSCons()
         file = test.workpath('custom.py')
         test.write('custom.py', 'ANSWER=54')
@@ -118,11 +127,22 @@ class OptionsTestCase(unittest.TestCase):
                  lambda x: int(x) + 12)
 
         env = Environment()
+        exc_caught = None
+        try:
+            opts.Update(env)
+        except AssertionError:
+            exc_caught = 1
+        assert exc_caught, "did not catch expected assertion"
+
+        env = Environment()
+        exc_caught = None
         try:
             opts.Update(env, {})
         except AssertionError:
-            pass
+            exc_caught = 1
+        assert exc_caught, "did not catch expected assertion"
 
+        # Test that a good value from the file is used and validated.
         test = TestSCons.TestSCons()
         file = test.workpath('custom.py')
         test.write('custom.py', 'ANSWER=42')
@@ -130,22 +150,49 @@ class OptionsTestCase(unittest.TestCase):
         
         opts.Add('ANSWER',
                  'THE answer to THE question',
-                 "54",
+                 "10",
                  check,
                  lambda x: int(x) + 12)
 
+        env = Environment()
+        opts.Update(env)
+        assert env['ANSWER'] == 54
+
         env = Environment()
         opts.Update(env, {})
         assert env['ANSWER'] == 54
 
+        # Test that a bad value from an args dictionary passed to
+        # Update() is used and validation fails correctly.
         test = TestSCons.TestSCons()
         file = test.workpath('custom.py')
-        test.write('custom.py', 'ANSWER=54')
+        test.write('custom.py', 'ANSWER=10')
         opts = SCons.Options.Options(file)
         
         opts.Add('ANSWER',
                  'THE answer to THE question',
-                 "54",
+                 "12",
+                 check,
+                 lambda x: int(x) + 12)
+
+        env = Environment()
+        exc_caught = None
+        try:
+            opts.Update(env, {'ANSWER':'54'})
+        except AssertionError:
+            exc_caught = 1
+        assert exc_caught, "did not catch expected assertion"
+
+        # Test that a good value from an args dictionary
+        # passed to Update() is used and validated.
+        test = TestSCons.TestSCons()
+        file = test.workpath('custom.py')
+        test.write('custom.py', 'ANSWER=10')
+        opts = SCons.Options.Options(file)
+        
+        opts.Add('ANSWER',
+                 'THE answer to THE question',
+                 "12",
                  check,
                  lambda x: int(x) + 12)
 
@@ -153,8 +200,65 @@ class OptionsTestCase(unittest.TestCase):
         opts.Update(env, {'ANSWER':'42'})
         assert env['ANSWER'] == 54
 
+    def test_args(self):
+        """Test updating an Environment with arguments overridden"""
+
+        # Test that a bad (command-line) argument is used
+        # and the validation fails correctly.
+        test = TestSCons.TestSCons()
+        file = test.workpath('custom.py')
+        test.write('custom.py', 'ANSWER=42')
+        opts = SCons.Options.Options(file, {'ANSWER':54})
+        
+        opts.Add('ANSWER',
+                 'THE answer to THE question',
+                 "42",
+                 check,
+                 lambda x: int(x) + 12)
+
+        env = Environment()
+        exc_caught = None
+        try:
+            opts.Update(env)
+        except AssertionError:
+            exc_caught = 1
+        assert exc_caught, "did not catch expected assertion"
+
+        # Test that a good (command-line) argument is used and validated.
+        test = TestSCons.TestSCons()
+        file = test.workpath('custom.py')
+        test.write('custom.py', 'ANSWER=54')
+        opts = SCons.Options.Options(file, {'ANSWER':42})
+        
+        opts.Add('ANSWER',
+                 'THE answer to THE question',
+                 "54",
+                 check,
+                 lambda x: int(x) + 12)
+
+        env = Environment()
+        opts.Update(env)
+        assert env['ANSWER'] == 54
+
+        # Test that a (command-line) argument is overridden by a dictionary
+        # supplied to Update() and the dictionary value is validated correctly.
+        test = TestSCons.TestSCons()
+        file = test.workpath('custom.py')
+        test.write('custom.py', 'ANSWER=54')
+        opts = SCons.Options.Options(file, {'ANSWER':54})
+        
+        opts.Add('ANSWER',
+                 'THE answer to THE question',
+                 "54",
+                 check,
+                 lambda x: int(x) + 12)
+
+        env = Environment()
+        opts.Update(env, {'ANSWER':42})
+        assert env['ANSWER'] == 54
 
     def test_Save(self):
+        """Testing saving Options"""
 
         test = TestSCons.TestSCons()
         cache_file = test.workpath('cached.options')
index 1e14658d74bc94f7fd8de0f9eab1998974b9af06..0b3aa41aa615d33ab9ff791174e4396b5bb77854 100644 (file)
@@ -423,8 +423,8 @@ def SourceSignatures(type):
 
 
 class Options(SCons.Options.Options):
-    def Update(self, env):
-        return SCons.Options.Options.Update(self, env, arguments)
+    def __init__(self, files=None, args=arguments):
+        SCons.Options.Options.__init__(self, files, args)
 
 def CheckVersion(major,minor,version_string):
     """Return 0 if 'major' and 'minor' are greater than the version
index 7d850767110c3e2e42a44bd4ee79e97388d7a34a..b142db9926124d78cd95b6db9d87a272538fa0eb 100644 (file)
@@ -308,4 +308,12 @@ UNSPECIFIED: An option with no value
 Use scons -H for help about command-line options.
 """%cc)
 
+test.write('SConstruct', """
+import SCons.Options
+env1 = Environment(options = Options())
+env2 = Environment(options = SCons.Options.Options())
+""")
+
+test.run()
+
 test.pass_test()