SF #737473: Show up-to-date source code in tracebacks always.
And add an optional argument 'filename' to linecache.checkcache()
to enable checking caches per-file.
diff --git a/Lib/linecache.py b/Lib/linecache.py
index 1b70c7c..2ccc6c6 100644
--- a/Lib/linecache.py
+++ b/Lib/linecache.py
@@ -40,11 +40,19 @@
         return updatecache(filename)
 
 
-def checkcache():
+def checkcache(filename=None):
     """Discard cache entries that are out of date.
     (This is not checked upon each call!)"""
 
-    for filename in cache.keys():
+    if filename is None:
+        filenames = cache.keys()
+    else:
+        if filename in cache:
+            filenames = [filename]
+        else:
+            return
+
+    for filename in filenames:
         size, mtime, lines, fullname = cache[filename]
         try:
             stat = os.stat(fullname)
diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py
index dc22c75..6812095 100644
--- a/Lib/test/test_traceback.py
+++ b/Lib/test/test_traceback.py
@@ -40,6 +40,47 @@
         self.assert_(len(err) == 3)
         self.assert_(err[1].strip() == "[x for x in x] = x")
 
+    def test_bug737473(self):
+        import sys, os, tempfile
+        savedpath = sys.path[:]
+        testdir = tempfile.mkdtemp()
+        try:
+            sys.path.insert(0, testdir)
+            testfile = os.path.join(testdir, 'test_bug737473.py')
+            print >> open(testfile, 'w'), """\
+def test():
+    raise ValueError"""
+
+            if hasattr(os, 'utime'):
+                os.utime(testfile, (0, 0))
+            else:
+                import time
+                time.sleep(3) # not to stay in same mtime.
+
+            if 'test_bug737473' in sys.modules:
+                del sys.modules['test_bug737473']
+            import test_bug737473
+
+            try:
+                test_bug737473.test()
+            except ValueError:
+                # this loads source code to linecache 
+                traceback.extract_tb(sys.exc_traceback)
+
+            print >> open(testfile, 'w'), """\
+def test():
+    raise NotImplementedError"""
+            reload(test_bug737473)
+            try:
+                test_bug737473.test()
+            except NotImplementedError:
+                src = traceback.extract_tb(sys.exc_traceback)[-1][-1]
+                self.failUnlessEqual(src, 'raise NotImplementedError')
+        finally:
+            sys.path[:] = savedpath
+            for f in os.listdir(testdir):
+                os.unlink(os.path.join(testdir, f))
+            os.rmdir(testdir)
 
 def test_main():
     run_unittest(TracebackCases)
diff --git a/Lib/traceback.py b/Lib/traceback.py
index cf78648..95cde2b 100644
--- a/Lib/traceback.py
+++ b/Lib/traceback.py
@@ -65,6 +65,7 @@
         name = co.co_name
         _print(file,
                '  File "%s", line %d, in %s' % (filename,lineno,name))
+        linecache.checkcache(filename)
         line = linecache.getline(filename, lineno)
         if line: _print(file, '    ' + line.strip())
         tb = tb.tb_next
@@ -96,6 +97,7 @@
         co = f.f_code
         filename = co.co_filename
         name = co.co_name
+        linecache.checkcache(filename)
         line = linecache.getline(filename, lineno)
         if line: line = line.strip()
         else: line = None
@@ -277,6 +279,7 @@
         co = f.f_code
         filename = co.co_filename
         name = co.co_name
+        linecache.checkcache(filename)
         line = linecache.getline(filename, lineno)
         if line: line = line.strip()
         else: line = None