Collect common type-checking logic in SCons.Util.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Tue, 8 Jan 2002 16:20:33 +0000 (16:20 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Tue, 8 Jan 2002 16:20:33 +0000 (16:20 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@193 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/CHANGES.txt
src/engine/SCons/Builder.py
src/engine/SCons/Environment.py
src/engine/SCons/Util.py
src/engine/SCons/UtilTests.py

index e83724c4dab4032091871aa1a6a54266af8c358e..31763f5ef0e1411f6a8285484f03c6a6f08cfca2 100644 (file)
@@ -37,6 +37,9 @@ RELEASE 0.03 -
     the user's environment variables to executed commands; how to
     build variants in multiple BuildDirs.
 
+  - Collect String, Dict, and List type-checking in common utility
+    routines so we can accept User{String,Dict,List}s all over.
+
   From Anthony Roach:
 
   - Add a "duplicate" keyword argument to BuildDir() that can be set
index f47e3a7f5a60f1ad596c6ef888733bd318597c8c..796af0ab91252bf91bccd726b9c7987087130f5f 100644 (file)
@@ -33,21 +33,13 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 import os
 import os.path
-import SCons.Node.FS
-from SCons.Util import PathList, scons_str2nodes, scons_subst, scons_subst_list, autogenerate
 import string
 import sys
 import types
-from UserList import UserList
-from UserDict import UserDict
 from Errors import UserError
 
-try:
-    from UserString import UserString
-except ImportError:
-    class UserString:
-        pass
-
+import SCons.Node.FS
+import SCons.Util
 
 exitvalmap = {
     2 : 127,
@@ -81,7 +73,7 @@ elif os.name == 'nt':
        if os.path.isabs(cmd):
            if not os.path.exists(cmd):
                exts = env['PATHEXT']
-               if type(exts) != type([]):
+               if not SCons.Util.is_List(exts):
                    exts = string.split(exts, os.pathsep)
                for e in exts:
                    f = cmd + e
@@ -89,10 +81,10 @@ elif os.name == 'nt':
                        return f
        else:
            path = env['PATH']
-           if type(path) != type([]):
+           if not SCons.Util.is_List(path):
                path = string.split(path, os.pathsep)
            exts = env['PATHEXT']
-           if type(exts) != type([]):
+           if not SCons.Util.is_List(exts):
                exts = string.split(exts, os.pathsep)
            pairs = []
            for dir in path:
@@ -122,8 +114,7 @@ elif os.name == 'nt':
 
 def Builder(**kw):
     """A factory for builder objects."""
-    if kw.has_key('action') and (type(kw['action']) is types.DictType or
-                                 isinstance(kw['action'], UserDict)):
+    if kw.has_key('action') and SCons.Util.is_Dict(kw['action']):
         return apply(CompositeBuilder, (), kw)
     elif kw.has_key('src_builder'):
         return apply(MultiStepBuilder, (), kw)
@@ -165,12 +156,12 @@ class BuilderBase:
         """
        def adjustixes(files, pre, suf):
            ret = []
-            if type(files) is types.StringType or isinstance(files, UserString):
+            if SCons.Util.is_String(files):
                 files = string.split(files)
-           if not type(files) is type([]):
+            if not SCons.Util.is_List(files):
                files = [files]
            for f in files:
-                if type(f) is types.StringType or isinstance(f, UserString):
+                if SCons.Util.is_String(f):
                    if pre and f[:len(pre)] != pre:
                         path, fn = os.path.split(os.path.normpath(f))
                         f = os.path.join(path, pre + fn)
@@ -180,15 +171,15 @@ class BuilderBase:
                ret.append(f)
            return ret
 
-       tlist = scons_str2nodes(adjustixes(target,
-                                           env.subst(self.prefix),
-                                           env.subst(self.suffix)),
-                                self.node_factory)
+        tlist = SCons.Util.scons_str2nodes(adjustixes(target,
+                                                      env.subst(self.prefix),
+                                                      env.subst(self.suffix)),
+                                           self.node_factory)
 
-        slist = scons_str2nodes(adjustixes(source,
-                                           None,
-                                           env.subst(self.src_suffix)),
-                                self.node_factory)
+        slist = SCons.Util.scons_str2nodes(adjustixes(source,
+                                                      None,
+                                                      env.subst(self.src_suffix)),
+                                           self.node_factory)
         return tlist, slist
 
     def _init_nodes(self, env, tlist, slist):
@@ -258,7 +249,7 @@ class MultiStepBuilder(BuilderBase):
         self.src_builder = src_builder
 
     def __call__(self, env, target = None, source = None):
-        slist = scons_str2nodes(source, self.node_factory)
+        slist = SCons.Util.scons_str2nodes(source, self.node_factory)
         final_sources = []
         src_suffix = env.subst(self.src_suffix)
         for snode in slist:
@@ -266,7 +257,7 @@ class MultiStepBuilder(BuilderBase):
             if not src_suffix or ext != src_suffix:
                 tgt = self.src_builder(env, target = [ path ],
                                      source=snode)
-                if not type(tgt) is types.ListType:
+                if not SCons.Util.is_List(tgt):
                     final_sources.append(tgt)
                 else:
                     final_sources.extend(tgt)
@@ -292,7 +283,7 @@ class CompositeBuilder(BuilderBase):
                         src_builder = []):
         BuilderBase.__init__(self, name=name, prefix=prefix,
                              suffix=suffix)
-        if src_builder and not type(src_builder) is types.ListType:
+        if src_builder and not SCons.Util.is_List(src_builder):
             src_builder = [src_builder]
         self.src_builder = src_builder
         self.builder_dict = {}
@@ -353,9 +344,9 @@ def Action(act):
     """A factory for action objects."""
     if callable(act):
        return FunctionAction(act)
-    elif type(act) == types.StringType or isinstance(act, UserString):
+    elif SCons.Util.is_String(act):
        return CommandAction(act)
-    elif type(act) == types.ListType or isinstance(act, UserList):
+    elif SCons.Util.is_List(act):
        return ListAction(act)
     else:
        return None
@@ -407,27 +398,27 @@ class ActionBase:
         if kw.has_key('target'):
             t = kw['target']
             del kw['target']
-            if not type(t) is types.ListType and not isinstance(t, UserList):
+            if not SCons.Util.is_List(t):
                 t = [t]
             try:
                 cwd = t[0].cwd
             except AttributeError:
                 pass
-            dict['TARGETS'] = PathList(map(os.path.normpath, map(str, t)))
+            dict['TARGETS'] = SCons.Util.PathList(map(os.path.normpath, map(str, t)))
             if dict['TARGETS']:
                 dict['TARGET'] = dict['TARGETS'][0]
 
         if kw.has_key('source'):
             s = kw['source']
             del kw['source']
-            if not type(s) is types.ListType:
+            if not SCons.Util.is_List(s):
                 s = [s]
-            dict['SOURCES'] = PathList(map(os.path.normpath, map(str, s)))
+            dict['SOURCES'] = SCons.Util.PathList(map(os.path.normpath, map(str, s)))
 
         dict.update(kw)
 
         # Autogenerate necessary construction variables.
-        autogenerate(dict, dir = cwd)
+        SCons.Util.autogenerate(dict, dir = cwd)
 
         return dict
 
@@ -437,8 +428,9 @@ class CommandAction(ActionBase):
         self.command = string
 
     def execute(self, **kw):
+        import SCons.Util
         dict = apply(self.subst_dict, (), kw)
-        cmd_list = scons_subst_list(self.command, dict, {})
+        cmd_list = SCons.Util.scons_subst_list(self.command, dict, {})
         for cmd_line in cmd_list:
             if len(cmd_line):
                 if print_actions:
@@ -465,7 +457,7 @@ class CommandAction(ActionBase):
         kw['target'] = ['__t1__', '__t2__']
         kw['source'] = ['__s1__', '__s2__']
         dict = apply(self.subst_dict, (), kw)
-        return scons_subst(self.command, dict, {})
+        return SCons.Util.scons_subst(self.command, dict, {})
 
 class FunctionAction(ActionBase):
     """Class for Python function actions."""
@@ -477,7 +469,7 @@ class FunctionAction(ActionBase):
        # XXX:  WHAT SHOULD WE PRINT HERE?
        if execute_actions:
             if kw.has_key('target'):
-                if type(kw['target']) is types.ListType:
+                if SCons.Util.is_List(kw['target']):
                     kw['target'] = map(str, kw['target'])
                 else:
                     kw['target'] = str(kw['target'])
index ad92dfd46be662ebff03f92e57fc2e1629b70175..6f773543a31ae73fefa94204018d9dbdaf0ed462 100644 (file)
@@ -39,7 +39,6 @@ import SCons.Util
 import SCons.Builder
 import SCons.Defaults
 from SCons.Errors import UserError
-from UserList import UserList
 import SCons.Node.FS
 import sys
 import shutil
@@ -73,11 +72,11 @@ def InstallAs():
 def our_deepcopy(x):
    """deepcopy lists and dictionaries, and just copy the reference 
    for everything else.""" 
-   if type(x) is type({}):
+   if SCons.Util.is_Dict(x):
        copy = {}
        for key in x.keys():
            copy[key] = our_deepcopy(x[key])
-   elif type(x) is type([]):
+   elif SCons.Util.is_List(x):
        copy = map(our_deepcopy, x)
    else:
        copy = x
@@ -130,10 +129,10 @@ class Environment:
        """
        self._dict.update(our_deepcopy(kw))
         if self._dict.has_key('BUILDERS') and \
-           type(self._dict['BUILDERS']) != type([]):
+           not SCons.Util.is_List(self._dict['BUILDERS']):
             self._dict['BUILDERS'] = [self._dict['BUILDERS']]
         if self._dict.has_key('SCANNERS') and \
-           type(self._dict['SCANNERS']) != type([]):
+           not SCons.Util.is_List(self._dict['SCANNERS']):
             self._dict['SCANNERS'] = [self._dict['SCANNERS']]
 
         class BuilderWrapper:
index a5174079e0a189402fbd9bdccbe6ae867886f251..e6ebd063064d8d53c821ae80689feef8fa3bd515 100644 (file)
@@ -30,14 +30,22 @@ Various utility functions go here.
 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
 
 
+import copy
 import os.path
-import types
-import string
 import re
-from UserList import UserList
-import SCons.Node.FS
-import copy
+import string
+import types
+import UserDict
+import UserList
+
+try:
+    from UserString import UserString
+except ImportError:
+    class UserString:
+        pass
+
 import SCons.Node
+import SCons.Node.FS
 
 def scons_str2nodes(arg, node_factory=SCons.Node.FS.default_fs.File):
     """This function converts a string or list into a list of Node instances.
@@ -51,14 +59,14 @@ def scons_str2nodes(arg, node_factory=SCons.Node.FS.default_fs.File):
     In all cases, the function returns a list of Node instances."""
 
     narg = arg
-    if type(arg) is types.StringType:
+    if is_String(arg):
        narg = string.split(arg)
-    elif type(arg) is not types.ListType:
+    elif not is_List(arg):
        narg = [arg]
 
     nodes = []
     for v in narg:
-       if type(v) is types.StringType:
+       if is_String(v):
            nodes.append(node_factory(v))
        # Do we enforce the following restriction?  Maybe, but it
        # also restricts what we can do for allowing people to
@@ -74,7 +82,7 @@ def scons_str2nodes(arg, node_factory=SCons.Node.FS.default_fs.File):
     return nodes
 
 
-class PathList(UserList):
+class PathList(UserList.UserList):
     """This class emulates the behavior of a list, but also implements
     the special "path dissection" attributes we can use to find
     suffixes, base names, etc. of the paths in the list.
@@ -91,7 +99,7 @@ class PathList(UserList):
     'bar foo'
     """
     def __init__(self, seq = []):
-        UserList.__init__(self, seq)
+        UserList.UserList.__init__(self, seq)
 
     def __getattr__(self, name):
         # This is how we implement the "special" attributes
@@ -157,7 +165,7 @@ class PathList(UserList):
         # We must do this to ensure that single items returned
         # by index access have the special attributes such as
         # suffix and basepath.
-        return self.__class__([ UserList.__getitem__(self, item), ])
+        return self.__class__([ UserList.UserList.__getitem__(self, item), ])
 
 _cv = re.compile(r'\$([_a-zA-Z]\w*|{[^}]*})')
 _space_sep = re.compile(r'[\t ]+(?![^{]*})')
@@ -189,8 +197,7 @@ def scons_subst_list(strSubst, locals, globals):
             e = eval(key, locals, globals)
             if not e:
                 s = ''
-            elif type(e) is types.ListType or \
-                 isinstance(e, UserList):
+            elif is_List(e):
                 s = string.join(map(str, e), '\0')
             else:
                 s = _space_sep.sub('\0', str(e))
@@ -282,7 +289,7 @@ class VarInterpolator:
 
     def prepareSrc(self, dict):
         src = dict[self.src]
-        if not type(src) is types.ListType and not isinstance(src, UserList):
+        if not is_List(src):
             src = [ src ]
 
         def prepare(x, dict=dict):
@@ -409,3 +416,12 @@ def render_tree(root, child_func, margin=[0], visited={}):
         margin.pop()
 
     return retval
+
+def is_Dict(e):
+    return type(e) is types.DictType or isinstance(e, UserDict.UserDict)
+
+def is_List(e):
+    return type(e) is types.ListType or isinstance(e, UserList.UserList)
+
+def is_String(e):
+    return type(e) is types.StringType or isinstance(e, UserString)
index 784c84d03d024e038e3798a8e97bed233fb3965e..5d7d52e339fbaf9e3df6abcac7ee945debfff79d 100644 (file)
@@ -243,6 +243,31 @@ class UtilTestCase(unittest.TestCase):
         actual = render_tree(foo, get_children)
         assert expect == actual, (expect, actual)
 
+    def test_is_Dict(self):
+        assert is_Dict({})
+        import UserDict
+        assert is_Dict(UserDict.UserDict())
+        assert not is_Dict([])
+        assert not is_Dict("")
+
+    def test_is_List(self):
+        assert is_List([])
+        import UserList
+        assert is_List(UserList.UserList())
+        assert not is_List({})
+        assert not is_List("")
+
+    def test_is_String(self):
+        assert is_String("")
+        try:
+            import UserString
+        except:
+            pass
+        else:
+            assert is_String(UserString.UserString())
+        assert not is_String({})
+        assert not is_String([])
+
 if __name__ == "__main__":
     suite = unittest.makeSuite(UtilTestCase, 'test_')
     if not unittest.TextTestRunner().run(suite).wasSuccessful():