Issue 2415: Tolerate unicode strings when using intern()
authorpankrat <pankrat@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sun, 17 May 2009 10:22:30 +0000 (10:22 +0000)
committerpankrat <pankrat@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Sun, 17 May 2009 10:22:30 +0000 (10:22 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@4199 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/engine/SCons/Node/FS.py
src/engine/SCons/Scanner/__init__.py
src/engine/SCons/Util.py
src/engine/SCons/UtilTests.py

index bd8314b6c0a6811cdc9c46f363d5d13d21f85696..c34cfed7c8691046f2fffcb3c1acc88958fb31ce 100644 (file)
@@ -588,22 +588,22 @@ class Base(SCons.Node.Node):
 
         # Filenames and paths are probably reused and are intern'ed to
         # save some memory.
-        self.name = intern(name)
-        self.suffix = intern(SCons.Util.splitext(name)[1])
+        self.name = SCons.Util.silent_intern(name)
+        self.suffix = SCons.Util.silent_intern(SCons.Util.splitext(name)[1])
         self.fs = fs
 
         assert directory, "A directory must be provided"
 
-        self.abspath = intern(directory.entry_abspath(name))
-        self.labspath = intern(directory.entry_labspath(name))
+        self.abspath = SCons.Util.silent_intern(directory.entry_abspath(name))
+        self.labspath = SCons.Util.silent_intern(directory.entry_labspath(name))
         if directory.path == '.':
-            self.path = intern(name)
+            self.path = SCons.Util.silent_intern(name)
         else:
-            self.path = intern(directory.entry_path(name))
+            self.path = SCons.Util.silent_intern(directory.entry_path(name))
         if directory.tpath == '.':
-            self.tpath = intern(name)
+            self.tpath = SCons.Util.silent_intern(name)
         else:
-            self.tpath = intern(directory.entry_tpath(name))
+            self.tpath = SCons.Util.silent_intern(directory.entry_tpath(name))
         self.path_elements = directory.path_elements + [self]
 
         self.dir = directory
index d0c7d3c5a69114f90266da6ac53632b5df39ab6b..cbf829c6d5b05fea23a5dd8794cb03e63da0be96 100644 (file)
@@ -358,10 +358,7 @@ class Classic(Current):
             includes = self.find_include_names (node)
             # Intern the names of the include files. Saves some memory
             # if the same header is included many times.
-            try:
-                node.includes = map(intern, includes)
-            except TypeError:
-                node.includes = includes
+            node.includes = map(SCons.Util.silent_intern, includes)
 
         # This is a hand-coded DSU (decorate-sort-undecorate, or
         # Schwartzian transform) pattern.  The sort key is the raw name
@@ -405,12 +402,7 @@ class ClassicCPP(Classic):
 
         n = SCons.Node.FS.find_file(include[1], paths)
 
-        i = include[1]
-        try:
-            i = intern(i)
-        except TypeError:
-            # Probably a unicode object; just don't worry about intern().
-            pass
+        i = SCons.Util.silent_intern(include[1])
         return n, i
 
     def sort_key(self, include):
index ac949a07db0970ae2bbae8383735d316ba7be153..ebdd1cd0101149abfe80a65b0ab76d704479ab5e 100644 (file)
@@ -1569,6 +1569,27 @@ def MD5collect(signatures):
 
 
 
+# Wrap the intern() function so it doesn't throw exceptions if ineligible
+# arguments are passed. The intern() function was moved into the sys module in
+# Python 3.
+try:
+    intern
+except NameError:
+    from sys import intern
+
+def silent_intern(x):
+    """
+    Perform intern() on the passed argument and return the result.
+    If the input is ineligible (e.g. a unicode string) the original argument is
+    returned and no exception is thrown.
+    """
+    try:
+        return intern(x)
+    except TypeError:
+        return x
+
+
+
 # From Dinu C. Gherman,
 # Python Cookbook, second edition, recipe 6.17, p. 277.
 # Also:
index ee2c89834a0c79e8bca44c81dbaba49b74faa6dc..7d417d3efa6ddb58b832be60dc2c216290c7a82c 100644 (file)
@@ -695,6 +695,14 @@ bling
             'bling\n',
         ], lines
 
+    def test_intern(self):
+        s1 = silent_intern("spam")
+        s2 = silent_intern(u"unicode spam")
+        s3 = silent_intern(42)
+        s4 = silent_intern("spam")
+        assert id(s1) == id(s4)
+
+
 class MD5TestCase(unittest.TestCase):
 
     def test_collect(self):