Merged revisions 2136-2200,2202-2290,2292-2301 via svnmerge from
[scons.git] / src / engine / SCons / Environment.py
index 8a7721e39406da9c63d0ec654d09bbd6d6954db4..012c36c39ca9f91f5c6149b43b085de603fd3a13 100644 (file)
@@ -67,6 +67,8 @@ _null = _Null
 CleanTargets = {}
 CalculatorArgs = {}
 
+semi_deepcopy = SCons.Util.semi_deepcopy
+
 # Pull UserError into the global name space for the benefit of
 # Environment().SourceSignatures(), which has some import statements
 # which seem to mess up its ability to reference SCons directly.
@@ -82,23 +84,6 @@ AliasBuilder = SCons.Builder.Builder(action = alias_builder,
                                      is_explicit = None,
                                      name='AliasBuilder')
 
-def our_deepcopy(x):
-   """deepcopy lists and dictionaries, and just copy the reference
-   for everything else."""
-   if SCons.Util.is_Dict(x):
-       copy = {}
-       for key in x.keys():
-           copy[key] = our_deepcopy(x[key])
-   elif SCons.Util.is_List(x):
-       copy = map(our_deepcopy, x)
-       try:
-           copy = x.__class__(copy)
-       except AttributeError:
-           pass
-   else:
-       copy = x
-   return copy
-
 def apply_tools(env, tools, toolpath):
     # Store the toolpath in the Environment.
     if toolpath is not None:
@@ -122,7 +107,7 @@ reserved_construction_var_names = \
     ['TARGET', 'TARGETS', 'SOURCE', 'SOURCES']
 
 def copy_non_reserved_keywords(dict):
-    result = our_deepcopy(dict)
+    result = semi_deepcopy(dict)
     for k in result.keys():
         if k in reserved_construction_var_names:
             SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning,
@@ -191,6 +176,9 @@ class BuilderDict(UserDict):
         self.env = env
         UserDict.__init__(self, dict)
 
+    def __semi_deepcopy__(self):
+        return self.__class__(self.data, self.env)
+
     def __setitem__(self, item, val):
         UserDict.__setitem__(self, item, val)
         try:
@@ -255,7 +243,7 @@ class SubstitutionEnvironment:
         """Initialization of an underlying SubstitutionEnvironment class.
         """
         if __debug__: logInstanceCreation(self, 'Environment.SubstitutionEnvironment')
-        self.fs = SCons.Node.FS.default_fs or SCons.Node.FS.FS()
+        self.fs = SCons.Node.FS.get_default_fs()
         self.ans = SCons.Node.Alias.default_ans
         self.lookup_list = SCons.Node.arg2nodes_lookups
         self._dict = kw.copy()
@@ -754,10 +742,10 @@ class Base(SubstitutionEnvironment):
         """
         if __debug__: logInstanceCreation(self, 'Environment.Base')
         self._memo = {}
-        self.fs = SCons.Node.FS.default_fs or SCons.Node.FS.FS()
+        self.fs = SCons.Node.FS.get_default_fs()
         self.ans = SCons.Node.Alias.default_ans
         self.lookup_list = SCons.Node.arg2nodes_lookups
-        self._dict = our_deepcopy(SCons.Defaults.ConstructionEnvironment)
+        self._dict = semi_deepcopy(SCons.Defaults.ConstructionEnvironment)
         self._init_special()
 
         self._dict['BUILDERS'] = BuilderDict(self._dict['BUILDERS'], self)
@@ -825,6 +813,14 @@ class Base(SubstitutionEnvironment):
             c = SCons.Defaults.DefaultEnvironment().get_calculator()
         return c
 
+    def get_CacheDir(self):
+        try:
+            return self._CacheDir
+        except AttributeError:
+            cd = SCons.Defaults.DefaultEnvironment()._CacheDir
+            self._CacheDir = cd
+            return cd
+
     def get_factory(self, factory, default='File'):
         """Return a factory function for creating Nodes for this
         construction environment.
@@ -980,7 +976,11 @@ class Base(SubstitutionEnvironment):
                         try:
                             update_dict(val)
                         except (AttributeError, TypeError, ValueError):
-                            orig[val] = None
+                            if SCons.Util.is_Dict(val):
+                                for k, v in val.items():
+                                    orig[k] = v
+                            else:
+                                orig[val] = None
         self.scanner_map_delete(kw)
 
     def AppendENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep):
@@ -1039,7 +1039,7 @@ class Base(SubstitutionEnvironment):
         objects in the original Environment.
         """
         clone = copy.copy(self)
-        clone._dict = our_deepcopy(self._dict)
+        clone._dict = semi_deepcopy(self._dict)
         try:
             cbd = clone._dict['BUILDERS']
             clone._dict['BUILDERS'] = BuilderDict(cbd, clone)
@@ -1235,7 +1235,11 @@ class Base(SubstitutionEnvironment):
                         try:
                             update_dict(val)
                         except (AttributeError, TypeError, ValueError):
-                            orig[val] = None
+                            if SCons.Util.is_Dict(val):
+                                for k, v in val.items():
+                                    orig[k] = v
+                            else:
+                                orig[val] = None
         self.scanner_map_delete(kw)
 
     def PrependENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep):
@@ -1290,13 +1294,13 @@ class Base(SubstitutionEnvironment):
         with new construction variables and/or values.
         """
         try:
-            kwbd = our_deepcopy(kw['BUILDERS'])
+            kwbd = semi_deepcopy(kw['BUILDERS'])
             del kw['BUILDERS']
             self.__setitem__('BUILDERS', kwbd)
         except KeyError:
             pass
         kw = copy_non_reserved_keywords(kw)
-        self._update(our_deepcopy(kw))
+        self._update(semi_deepcopy(kw))
         self.scanner_map_delete(kw)
 
     def ReplaceIxes(self, path, old_prefix, old_suffix, new_prefix, new_suffix):
@@ -1470,7 +1474,11 @@ class Base(SubstitutionEnvironment):
         return apply(SCons.Builder.Builder, [], nkw)
 
     def CacheDir(self, path):
-        self.fs.CacheDir(self.subst(path))
+        import SCons.CacheDir
+        if path is None:
+            self._CacheDir = SCons.CacheDir.Null()
+        else:
+            self._CacheDir = SCons.CacheDir.CacheDir(self.subst(path))
 
     def Clean(self, targets, files):
         global CleanTargets
@@ -1830,7 +1838,7 @@ class OverrideEnvironment(Base):
     # Overridden public construction environment methods.
     def Replace(self, **kw):
         kw = copy_non_reserved_keywords(kw)
-        self.__dict__['overrides'].update(our_deepcopy(kw))
+        self.__dict__['overrides'].update(semi_deepcopy(kw))
 
 # The entry point that will be used by the external world
 # to refer to a construction environment.  This allows the wrapper