Add a PathOptions.PathAccept validator. (Kevin Quick)
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Mon, 3 Jan 2005 15:29:43 +0000 (15:29 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Mon, 3 Jan 2005 15:29:43 +0000 (15:29 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@1201 fdb21ef1-2011-0410-befe-b5e4ea1792b1

doc/scons.mod
doc/user/command-line.in
doc/user/command-line.sgml
src/CHANGES.txt
src/engine/SCons/Options/PathOption.py
src/engine/SCons/Options/PathOptionTests.py
test/Options/PathOption.py

index 58a6576aa2de6b831419e65ed5f7ef5b69c914cb..897262dcd08c161b4cdfafe8725ba40698ef58e5 100644 (file)
 <!ENTITY Options "<function>Options</function>">
 <!ENTITY PackageOption "<function>PackageOption</function>">
 <!ENTITY PathOption "<function>PathOption</function>">
+<!ENTITY PathOption_PathAccept "<function>PathOption.PathAccept</function>">
+<!ENTITY PathOption_PathExists "<function>PathOption.PathExists</function>">
+<!ENTITY PathOption_PathIsDir "<function>PathOption.PathIsDir</function>">
+<!ENTITY PathOption_PathIsDirCreate "<function>PathOption.PathIsDirCreate</function>">
+<!ENTITY PathOption_PathIsFile "<function>PathOption.PathIsFile</function>">
 <!ENTITY Precious "<function>Precious</function>">
 <!ENTITY Prepend "<function>Prepend</function>">
 <!ENTITY Replace "<function>Replace</function>">
index 9d69b2194f8116c1c58464ea8b28d93809777976..f23755f36fa9d9acdd3a4f1f4d7d3ee0743c8212 100644 (file)
         <command>scons -Q CONFIG=__ROOT__/usr/local/etc/other_config foo.o</command>
       </scons_output>
 
+      <para>
+
+      By default, &PathOption; checks to make sure
+      that the specified path exists and generates an error if it
+      doesn't:
+
+      </para>
+
+      <scons_output example="PathOption">
+        <command>scons -Q CONFIG=__ROOT__/does/not/exist foo.o</command>
+      </scons_output>
+
+      <para>
+
+      &PathOption; provides a number of methods
+      that you can use to change this behavior.
+      If you want to ensure that any specified paths are,
+      in fact, files and not directories,
+      use the &PathOption_PathIsFile; method:
+
+      </para>
+
+      <scons_example name="PathIsFile">
+        <file name="SConstruct" printme="1">
+           opts = Options('custom.py')
+           opts.Add(PathOption('CONFIG',
+                               'Path to configuration file',
+                               '__ROOT__/etc/my_config',
+                               PathOption.PathIsFile))
+           env = Environment(options = opts,
+                             CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'})
+           env.Program('foo.c')
+        </file>
+        <file name="foo.c">
+        foo.c
+        </file>
+        <file name="__ROOT__/etc/my_config">
+        /opt/location
+        </file>
+      </scons_example>
+
+      <para>
+
+      Conversely, to ensure that any specified paths are
+      directories and not files,
+      use the &PathOption_PathIsDir; method:
+
+      </para>
+
+      <scons_example name="PathIsDir">
+        <file name="SConstruct" printme="1">
+           opts = Options('custom.py')
+           opts.Add(PathOption('DBDIR',
+                               'Path to database directory',
+                               '__ROOT__/var/my_dbdir',
+                               PathOption.PathIsDir))
+           env = Environment(options = opts,
+                             CPPDEFINES={'DBDIR' : '"$DBDIR"'})
+           env.Program('foo.c')
+        </file>
+        <file name="foo.c">
+        foo.c
+        </file>
+        <file name="__ROOT__/var/my_dbdir">
+        /opt/location
+        </file>
+      </scons_example>
+
+      <para>
+
+      If you want to make sure that any specified paths
+      are directories,
+      and you would like the directory created
+      if it doesn't already exist,
+      use the &PathOption_PathIsDirCreate; method:
+
+      </para>
+
+      <scons_example name="PathIsDirCreate">
+        <file name="SConstruct" printme="1">
+           opts = Options('custom.py')
+           opts.Add(PathOption('DBDIR',
+                               'Path to database directory',
+                               '__ROOT__/var/my_dbdir',
+                               PathOption.PathIsDirCreate))
+           env = Environment(options = opts,
+                             CPPDEFINES={'DBDIR' : '"$DBDIR"'})
+           env.Program('foo.c')
+        </file>
+        <file name="foo.c">
+        foo.c
+        </file>
+        <file name="__ROOT__/var/my_dbdir">
+        /opt/location
+        </file>
+      </scons_example>
+
+      <para>
+
+      Lastly, if you don't care whether the path exists,
+      is a file, or a directory,
+      use the &PathOption_PathAccept; method
+      to accept any path that the user supplies:
+
+      </para>
+
+      <scons_example name="PathAccept">
+        <file name="SConstruct" printme="1">
+           opts = Options('custom.py')
+           opts.Add(PathOption('OUTPUT',
+                               'Path to output file or directory',
+                               None,
+                               PathOption.PathAccept))
+           env = Environment(options = opts,
+                             CPPDEFINES={'OUTPUT' : '"$OUTPUT"'})
+           env.Program('foo.c')
+        </file>
+        <file name="foo.c">
+        foo.c
+        </file>
+      </scons_example>
+
     </section>
 
     <section>
index c488f7f1942d9cda77e43f0d157d8f3f98e50346..70658e000c55ec13ed2bf09bf40b64968f31a510 100644 (file)
         scons: `foo.o' is up to date.
       </screen>
 
+      <para>
+
+      By default, &PathOption; checks to make sure
+      that the specified path exists and generates an error if it
+      doesn't:
+
+      </para>
+
+      <screen>
+        % <userinput>scons -Q CONFIG=/does/not/exist foo.o</userinput>
+        
+        scons: *** Path for option CONFIG does not exist: /does/not/exist
+        File "SConstruct", line 6, in ?
+      </screen>
+
+      <para>
+
+      &PathOption; provides a number of methods
+      that you can use to change this behavior.
+      If you want to ensure that any specified paths are,
+      in fact, files and not directories,
+      use the &PathOption_PathIsFile; method:
+
+      </para>
+
+      <programlisting>
+           opts = Options('custom.py')
+           opts.Add(PathOption('CONFIG',
+                               'Path to configuration file',
+                               '/etc/my_config',
+                               PathOption.PathIsFile))
+           env = Environment(options = opts,
+                             CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'})
+           env.Program('foo.c')
+      </programlisting>
+
+      <para>
+
+      Conversely, to ensure that any specified paths are
+      directories and not files,
+      use the &PathOption_PathIsDir; method:
+
+      </para>
+
+      <programlisting>
+           opts = Options('custom.py')
+           opts.Add(PathOption('DBDIR',
+                               'Path to database directory',
+                               '/var/my_dbdir',
+                               PathOption.PathIsDir))
+           env = Environment(options = opts,
+                             CPPDEFINES={'DBDIR' : '"$DBDIR"'})
+           env.Program('foo.c')
+      </programlisting>
+
+      <para>
+
+      If you want to make sure that any specified paths
+      are directories,
+      and you would like the directory created
+      if it doesn't already exist,
+      use the &PathOption_PathIsDirCreate; method:
+
+      </para>
+
+      <programlisting>
+           opts = Options('custom.py')
+           opts.Add(PathOption('DBDIR',
+                               'Path to database directory',
+                               '/var/my_dbdir',
+                               PathOption.PathIsDirCreate))
+           env = Environment(options = opts,
+                             CPPDEFINES={'DBDIR' : '"$DBDIR"'})
+           env.Program('foo.c')
+      </programlisting>
+
+      <para>
+
+      Lastly, if you don't care whether the path exists,
+      is a file, or a directory,
+      use the &PathOption_PathAccept; method
+      to accept any path that the user supplies:
+
+      </para>
+
+      <programlisting>
+           opts = Options('custom.py')
+           opts.Add(PathOption('OUTPUT',
+                               'Path to output file or directory',
+                               None,
+                               PathOption.PathAccept))
+           env = Environment(options = opts,
+                             CPPDEFINES={'OUTPUT' : '"$OUTPUT"'})
+           env.Program('foo.c')
+      </programlisting>
+
     </section>
 
     <section>
index 20842b43639db33737cc44e776eaf10157fe9605..523ace9216daeaaa478e66a0b0e3633ca990f307 100644 (file)
@@ -357,6 +357,9 @@ RELEASE 0.97 - XXX
     which cleans up a lot of special-case code in various methods and
     caches additional values to speed up most configurations.
 
+  - Add a PathAccept validator to the list of new canned PathOption
+    validators.
+
   From Levi Stephen:
 
   - Allow $JARCHDIR to be expanded to other construction variables.
index f407864918f5fa5a8912dddf856f5f0d359ebe83..683ede05c30dd3289abd64fdcc2e34e8dfa96869 100644 (file)
@@ -1,29 +1,44 @@
-"""engine.SCons.Options.PathOption
+"""SCons.Options.PathOption
 
-This file defines an option type for SCons implementing 'package
-activation'.
+This file defines an option type for SCons implementing path settings.
 
-To be used whenever a 'package' may be enabled/disabled and the
-package path may be specified.
+To be used whenever a a user-specified path override should be allowed.
+
+Arguments to PathOption are:
+  option-name  = name of this option on the command line (e.g. "prefix")
+  option-help  = help string for option
+  option-dflt  = default value for this option
+  validator    = [optional] validator for option value.  Predefined
+                 validators are:
+
+                     PathAccept -- accepts any path setting; no validation
+                     PathIsDir  -- path must be an existing directory
+                     PathIsDirCreate -- path must be a dir; will create
+                     PathIsFile -- path must be a file
+                     PathExists -- path must exist (any type) [default]
+
+                 The validator is a function that is called and which
+                 should return True or False to indicate if the path
+                 is valid.  The arguments to the validator function
+                 are: (key, val, env).  The key is the name of the
+                 option, the val is the path specified for the option,
+                 and the env is the env to which the Otions have been
+                 added.
 
 Usage example:
 
   Examples:
-      x11=no   (disables X11 support)
-      x11=yes  (will search for the package installation dir)
-      x11=/usr/local/X11 (will check this path for existance)
-
-  To replace autoconf's --with-xxx=yyy 
+      prefix=/usr/local
 
   opts = Options()
 
   opts = Options()
   opts.Add(PathOption('qtdir',
                       'where the root of Qt is installed',
-                      qtdir))
+                      qtdir, PathIsDir))
   opts.Add(PathOption('qt_includes',
                       'where the Qt includes are installed',
-                      '$qtdir/includes'))
+                      '$qtdir/includes', PathIsDirCreate))
   opts.Add(PathOption('qt_libraries',
                       'where the Qt library is installed',
                       '$qtdir/lib'))
@@ -62,6 +77,10 @@ import SCons.Errors
 
 class _PathOptionClass:
 
+    def PathAccept(self, key, val, env):
+        """Accepts any path, no checking done."""
+        pass
+    
     def PathIsDir(self, key, val, env):
         """Validator to check if Path is a directory."""
         if not os.path.isdir(val):
@@ -102,8 +121,8 @@ class _PathOptionClass:
         are returned with the correct converter and validator appended. The
         result is usable for input to opts.Add() .
 
-        A 'package list' option may either be 'all', 'none' or a list of
-        package names (seperated by space).
+        The 'default' option specifies the default path to use if the
+        user does not specify an override with this option.
 
         validator is a validator, see this file for examples
         """
index 9749ee7fab017653267246b5009e1fa9c6aaa321..22e79ae8d161967a034b92804d34af116c40b9c3 100644 (file)
@@ -159,6 +159,28 @@ class PathOptionTestCase(unittest.TestCase):
         except:
             raise "did not catch expected UserError"
 
+    def test_PathAccept(self):
+        """Test the PathAccept validator"""
+        opts = SCons.Options.Options()
+        opts.Add(SCons.Options.PathOption('test',
+                                          'test option help',
+                                          '/default/path',
+                                          SCons.Options.PathOption.PathAccept))
+
+        test = TestCmd.TestCmd(workdir='')
+        test.subdir('dir')
+        test.write('file', "file\n")
+
+        o = opts.options[0]
+
+        o.validator('X', test.workpath('file'), {})
+
+        d = test.workpath('d')
+        o.validator('X', d, {})
+
+        dne = test.workpath('does_not_exist')
+        o.validator('X', dne, {})
+
     def test_validator(self):
         """Test the PathOption validator argument"""
         opts = SCons.Options.Options()
index 4366730c5226e8a7ba229aed73ae96eca5249cd1..55f95c53c138bf0b80e001579bc08ff0ca556d97 100644 (file)
@@ -116,6 +116,39 @@ non_existing_file = test.workpath('non_existing_file')
 
 
 
+test.write('SConstruct', """\
+opts = Options(args=ARGUMENTS)
+opts.AddOptions(
+    PathOption('X', 'X variable', r'%s', validator=PathOption.PathAccept),
+    )
+
+env = Environment(options=opts)
+
+print env['X']
+
+Default(env.Alias('dummy', None))
+""" % default_subdir)
+
+test.run()
+check([default_subdir])
+
+test.run(arguments='"X=%s"' % existing_file)
+check([existing_file])
+
+test.run(arguments='"X=%s"' % non_existing_file)
+check([non_existing_file])
+
+test.run(arguments='"X=%s"' % existing_subdir)
+check([existing_subdir])
+
+test.run(arguments='"X=%s"' % non_existing_subdir)
+check([non_existing_subdir])
+
+test.must_not_exist(non_existing_file)
+test.must_not_exist(non_existing_subdir)
+
+
+
 test.write('SConstruct', """\
 opts = Options(args=ARGUMENTS)
 opts.AddOptions(