summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Node
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2001-12-31 02:51:50 (GMT)
committerSteven Knight <knight@baldmt.com>2001-12-31 02:51:50 (GMT)
commit74bc0282241e4d35b225660fe783955629ed234a (patch)
treecf4b0175cee4670e6b366e7a4c2218dc3bce508f /src/engine/SCons/Node
parent19ece17e5e025b7b9278a846eea60c8d12be438a (diff)
downloadSCons-74bc0282241e4d35b225660fe783955629ed234a.zip
SCons-74bc0282241e4d35b225660fe783955629ed234a.tar.gz
SCons-74bc0282241e4d35b225660fe783955629ed234a.tar.bz2
General performance tweaks
Diffstat (limited to 'src/engine/SCons/Node')
-rw-r--r--src/engine/SCons/Node/FS.py89
-rw-r--r--src/engine/SCons/Node/FSTests.py53
2 files changed, 47 insertions, 95 deletions
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index 98b6b02..7e9a44b 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -52,6 +52,23 @@ except AttributeError:
st=os.stat(src)
os.chmod(dest, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
+class ParentOfRoot:
+ """
+ An instance of this class is used as the parent of the root of a
+ filesystem (POSIX) or drive (Win32). This isn't actually a node,
+ but it looks enough like one so that we don't have to have
+ special purpose code everywhere to deal with dir being None.
+ This class is an instance of the Null object pattern.
+ """
+ def __init__(self):
+ self.abspath = ""
+ self.duplicate = 1
+ self.path = ""
+ self.srcpath = ""
+
+ def is_under(self, dir):
+ return 0
+
class PathName:
"""This is a string like object with limited capabilities (i.e.,
cannot always be used interchangeably with strings). This class
@@ -145,16 +162,6 @@ class FS:
self.Top.path_ = os.path.join('.', '')
self._cwd = self.Top
- def __hash__(self):
- self.__setTopLevelDir()
- return hash(self.Top)
-
- def __cmp__(self, other):
- self.__setTopLevelDir()
- if isinstance(other, FS):
- other.__setTopLevelDir()
- return cmp(self.__dict__, other.__dict__)
-
def getcwd(self):
self.__setTopLevelDir()
return self._cwd
@@ -187,7 +194,7 @@ class FS:
# if not directory:
# raise OSError, 'No drive letter supplied for absolute path.'
# return directory.root()
- dir = Dir(tail)
+ dir = Dir(tail, ParentOfRoot())
dir.path = drive + dir.path
dir.path_ = drive + dir.path_
dir.abspath = drive + dir.abspath
@@ -298,7 +305,13 @@ class Entry(SCons.Node.Node):
"""A generic class for file system entries. This class if for
when we don't know yet whether the entry being looked up is a file
or a directory. Instances of this class can morph into either
- Dir or File objects by a later, more precise lookup."""
+ Dir or File objects by a later, more precise lookup.
+
+ Note: this class does not define __cmp__ and __hash__ for efficiency
+ reasons. SCons does a lot of comparing of Entry objects, and so that
+ operation must be as fast as possible, which means we want to use
+ Python's built-in object identity comparison.
+ """
def __init__(self, name, directory):
"""Initialize a generic file system Entry.
@@ -310,34 +323,35 @@ class Entry(SCons.Node.Node):
SCons.Node.Node.__init__(self)
self.name = name
- if directory:
- self.duplicate = directory.duplicate
- self.abspath = os.path.join(directory.abspath, name)
- if str(directory.path) == '.':
- self.path = name
- else:
- self.path = os.path.join(directory.path, name)
+
+ assert directory, "A directory must be provided"
+
+ self.duplicate = directory.duplicate
+ self.abspath = os.path.join(directory.abspath, name)
+
+ if str(directory.path) == '.':
+ self.path = name
else:
- self.abspath = self.path = name
- self.duplicate = 1
+ self.path = os.path.join(directory.path, name)
+
self.path_ = self.path
self.abspath_ = self.abspath
self.dir = directory
self.use_signature = 1
self.__doSrcpath(self.duplicate)
+ def get_dir(self):
+ return self.dir
+
def adjust_srcpath(self, duplicate):
self.__doSrcpath(duplicate)
def __doSrcpath(self, duplicate):
self.duplicate = duplicate
- if self.dir:
- if str(self.dir.srcpath) == '.':
- self.srcpath = self.name
- else:
- self.srcpath = os.path.join(self.dir.srcpath, self.name)
- else:
+ if str(self.dir.srcpath) == '.':
self.srcpath = self.name
+ else:
+ self.srcpath = os.path.join(self.dir.srcpath, self.name)
def __str__(self):
"""A FS node's string representation is its path name."""
@@ -346,18 +360,6 @@ class Entry(SCons.Node.Node):
else:
return self.srcpath
- def __cmp__(self, other):
- if type(self) != types.StringType and type(other) != types.StringType:
- try:
- if self.__class__ != other.__class__:
- return 1
- except:
- return 1
- return cmp(str(self), str(other))
-
- def __hash__(self):
- return hash(self.abspath_)
-
def exists(self):
return os.path.exists(str(self))
@@ -373,9 +375,8 @@ class Entry(SCons.Node.Node):
def is_under(self, dir):
if self is dir:
return 1
- if not self.dir:
- return 0
- return self.dir.is_under(dir)
+ else:
+ return self.dir.is_under(dir)
@@ -392,7 +393,7 @@ class Dir(Entry):
"""A class for directories in a file system.
"""
- def __init__(self, name, directory = None):
+ def __init__(self, name, directory):
Entry.__init__(self, name, directory)
self._morph()
@@ -564,7 +565,7 @@ class File(Entry):
if self.env:
for scn in self.scanners:
if not self.scanned.has_key(scn):
- deps = scn.scan(str(self), self.env)
+ deps = scn.scan(self, self.env)
self.add_implicit(deps,scn)
self.scanned[scn] = 1
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py
index 4801dae..c9d17a7 100644
--- a/src/engine/SCons/Node/FSTests.py
+++ b/src/engine/SCons/Node/FSTests.py
@@ -48,8 +48,8 @@ class Scanner:
global scanner_count
scanner_count = scanner_count + 1
self.hash = scanner_count
- def scan(self, filename, env):
- return [SCons.Node.FS.default_fs.File(filename)]
+ def scan(self, node, env):
+ return [node]
def __hash__(self):
return self.hash
@@ -393,56 +393,7 @@ class FSTestCase(unittest.TestCase):
f1.build()
assert f1.dir.exists()
- # Test comparison of FS objects
- fs1 = SCons.Node.FS.FS()
- fs2 = SCons.Node.FS.FS()
os.chdir('..')
- fs3 = SCons.Node.FS.FS()
- assert fs1 == fs2
- assert fs1 != fs3
-
- # Test comparison of Entry objects
- e1 = fs3.Entry('cmp/entry')
- e2 = fs3.Entry('cmp/../cmp/entry')
- e3 = fs3.Entry('entry')
- assert e1 == e2
- assert e1 != e3
- assert e1 == os.path.normpath("cmp/entry"), e1
- assert e1 != os.path.normpath("c/entry"), e1
-
- # Test comparison of Dir objects
- d1 = fs3.Dir('cmp/dir')
- d2 = fs3.Dir('cmp/../cmp/dir')
- d3 = fs3.Dir('dir')
- assert d1 == d2
- assert d1 != d3
- assert d1 == os.path.normpath("cmp/dir"), d1
- assert d1 != os.path.normpath("c/dir"), d1
-
- # Test comparison of File objects
- f1 = fs3.File('cmp/file')
- f2 = fs3.File('cmp/../cmp/file')
- f3 = fs3.File('file')
- assert f1 == f2
- assert f1 != f3
- assert f1 == os.path.normpath("cmp/file"), f1
- assert f1 != os.path.normpath("c/file"), f1
-
- # Test comparison of different type objects
- f1 = fs1.File('cmp/xxx')
- d2 = fs2.Dir('cmp/xxx')
- assert f1 != d2, "%s == %s" % (f1.__class__, d2.__class__)
-
- # Test hashing FS nodes
- f = fs1.File('hash/f')
- d = fs1.Dir('hash/d')
- e = fs1.Entry('hash/e')
- val = {}
- val[f] = 'f'
- val[d] = 'd'
- val[e] = 'e'
- for k, v in val.items():
- assert k == os.path.normpath("hash/" + v)
# Test getcwd()
fs = SCons.Node.FS.FS()