Change how Node/__init__.py imports Executor, remove unnecessary has_builder() calls...
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Fri, 21 Jan 2005 17:01:49 +0000 (17:01 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Fri, 21 Jan 2005 17:01:49 +0000 (17:01 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@1218 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/engine/SCons/Builder.py
src/engine/SCons/BuilderTests.py
src/engine/SCons/Environment.py
src/engine/SCons/Node/NodeTests.py
src/engine/SCons/Node/__init__.py

index 9ac01fab7cd6d0845859f0dc0ce8347214a67e19..584becad5c3a191f1df4a640e80bef988d27a2eb 100644 (file)
@@ -341,6 +341,7 @@ def _init_nodes(builder, env, overrides, executor_kw, tlist, slist):
         t.env_set(env)
         t.add_source(slist)
         t.set_executor(executor)
+        t.set_explicit(builder.is_explicit)
 
 class EmitterProxy:
     """This is a callable class that can act as a
index 0d9c2ec96cfd250fae03ddad5e48284472dab971..8d60d335836f9d75385812d2ff33a893ac4817a9 100644 (file)
@@ -143,6 +143,7 @@ class MyNode_without_target_from_source:
         self.name = name
         self.sources = []
         self.builder = None
+        self.is_explicit = None
         self.side_effect = 0
     def __str__(self):
         return self.name
@@ -150,8 +151,10 @@ class MyNode_without_target_from_source:
         self.builder = builder
     def has_builder(self):
         return not self.builder is None
+    def set_explicit(self, is_explicit):
+        self.is_explicit = is_explicit
     def has_explicit_builder(self):
-        return not self.builder is None and self.builder.is_explicit
+        return self.is_explicit
     def env_set(self, env, safe=0):
         self.env = env
     def add_source(self, source):
index fdd9b4054f7a8e02e2675aa6bf04d4a6be6648c0..419e4e1cb1478fd0e30df0794dd72d63c83481a8 100644 (file)
@@ -1126,11 +1126,13 @@ class Base(SubstitutionEnvironment):
                 result.extend(bld(self, t, source))
             return result
 
-        action = SCons.Action.Action(action)
         nkw = self.subst_kw(kw)
-        nkw['source_factory'] = self.fs.Entry
-        nkw['multi'] = 1
-        nkw['action'] = action
+        nkw.update({
+            'action'            : SCons.Action.Action(action),
+            'source_factory'    : self.fs.Entry,
+            'multi'             : 1,
+            'is_explicit'       : None,
+        })
         bld = apply(SCons.Builder.Builder, (), nkw)
 
         # Apply the Builder separately to each target so that the Aliases
index f80196354a2e631a85dc1025116133f33ea6324f..7d737bec581acb2051dbca67d6a2bd7aa8123efc 100644 (file)
@@ -416,9 +416,9 @@ class NodeTestCase(unittest.TestCase):
         """
         n1 = SCons.Node.Node()
         assert not n1.has_explicit_builder()
-        n1.builder_set(Builder(is_explicit=1))
+        n1.set_explicit(1)
         assert n1.has_explicit_builder()
-        n1.builder_set(Builder(is_explicit=None))
+        n1.set_explicit(None)
         assert not n1.has_explicit_builder()
 
     def test_get_builder(self):
index c20d65716193c025a99bbdb904c2a664a3f99970..06cb5bfe17efa7709f4c2a1ff9d7b7d8b2b2df58 100644 (file)
@@ -51,6 +51,7 @@ import string
 import UserList
 
 from SCons.Debug import logInstanceCreation
+import SCons.Executor
 import SCons.SConsign
 import SCons.Util
 
@@ -165,17 +166,39 @@ class Node:
         except AttributeError:
             if not create:
                 raise
-            import SCons.Executor
-            act = self.builder.action
-            if self.pre_actions:
-                act = self.pre_actions + act
-            if self.post_actions:
-                act = act + self.post_actions
-            executor = SCons.Executor.Executor(act,
-                                               self.env or self.builder.env,
-                                               [self.builder.overrides],
-                                               [self],
-                                               self.sources)
+            try:
+                act = self.builder.action
+            except AttributeError:
+                # If there's no builder or action, then return a created
+                # null Executor with a null build Environment that
+                # does nothing when the rest of the methods call it.
+                # We're keeping this here for now because this module is
+                # the only one using it, and because this whole thing
+                # may go away in the next step of refactoring this to
+                # disassociate Builders from Nodes entirely.
+                class NullExecutor:
+                    def get_build_env(self):
+                        class NullEnvironment:
+                            def get_scanner(self, key):
+                                return None
+                        return NullEnvironment()
+                    def get_build_scanner_path(self):
+                        return None
+                    def __call__(self, *args, **kw):
+                        pass
+                    def cleanup(self):
+                        pass
+                executor = NullExecutor()
+            else:
+                if self.pre_actions:
+                    act = self.pre_actions + act
+                if self.post_actions:
+                    act = act + self.post_actions
+                executor = SCons.Executor.Executor(act,
+                                                   self.env or self.builder.env,
+                                                   [self.builder.overrides],
+                                                   [self],
+                                                   self.sources)
             self.executor = executor
         return executor
 
@@ -204,8 +227,6 @@ class Node:
         so only do thread safe stuff here. Do thread unsafe stuff in
         built().
         """
-        if not self.has_builder():
-            return
         def errfunc(stat, node=self):
             raise SCons.Errors.BuildError(node=node, errstr="Error %d" % stat)
         executor = self.get_executor()
@@ -303,7 +324,6 @@ class Node:
         and __nonzero__ attributes on instances of our Builder Proxy
         class(es), generating a bazillion extra calls and slowing
         things down immensely.
-        __cacheable__
         """
         try:
             b = self.builder
@@ -314,6 +334,9 @@ class Node:
             b = self.builder
         return not b is None
 
+    def set_explicit(self, is_explicit):
+        self.is_explicit = is_explicit
+
     def has_explicit_builder(self):
         """Return whether this Node has an explicit builder
 
@@ -321,7 +344,11 @@ class Node:
         non-explicit, so that it can be overridden by an explicit
         builder that the user supplies (the canonical example being
         directories)."""
-        return self.has_builder() and self.builder.is_explicit
+        try:
+            return self.is_explicit
+        except AttributeError:
+            self.is_explicit = None
+            return self.is_explicit
 
     def get_builder(self, default_builder=None):
         """Return the set builder, or a specified default value"""
@@ -426,28 +453,15 @@ class Node:
         This function may be called very often; it attempts to cache
         the scanner found to improve performance.
         """
-        # Called from scan() for each child (node) of this node
-        # (self).  The scan() may be called multiple times, so this
-        # gets called a multiple of those times; caching results is
-        # good.  Index results based on the id of the child; can
-        # ignore build_env parameter for the index because it's passed
-        # as an optimization of an already-determined value, not as a
-        # changing parameter.
-
-        if not self.has_builder():
-            return None
-        
         scanner = None
         try:
             scanner = self.builder.source_scanner
         except AttributeError:
             pass
-
-        # Not cached, so go look up a scanner from env['SCANNERS']
-        # based on the node's scanner key (usually the file
-        # extension).
-        
         if not scanner:
+            # The builder didn't have an explicit scanner, so go look up
+            # a scanner from env['SCANNERS'] based on the node's scanner
+            # key (usually the file extension).
             scanner = self.get_build_env().get_scanner(node.scanner_key())
         if scanner:
             scanner = scanner.select(node)