Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
number of tests, all because of the codecs/_multibytecodecs issue described
here (it's not a Py3K issue, just something Py3K discovers):
http://mail.python.org/pipermail/python-dev/2006-April/064051.html

Hye-Shik Chang promised to look for a fix, so no need to fix it here. The
tests that are expected to break are:

test_codecencodings_cn
test_codecencodings_hk
test_codecencodings_jp
test_codecencodings_kr
test_codecencodings_tw
test_codecs
test_multibytecodec

This merge fixes an actual test failure (test_weakref) in this branch,
though, so I believe merging is the right thing to do anyway.
diff --git a/Lib/linecache.py b/Lib/linecache.py
index 2ccc6c6..f49695a 100644
--- a/Lib/linecache.py
+++ b/Lib/linecache.py
@@ -10,8 +10,8 @@
 
 __all__ = ["getline", "clearcache", "checkcache"]
 
-def getline(filename, lineno):
-    lines = getlines(filename)
+def getline(filename, lineno, module_globals=None):
+    lines = getlines(filename, module_globals)
     if 1 <= lineno <= len(lines):
         return lines[lineno-1]
     else:
@@ -30,14 +30,14 @@
     cache = {}
 
 
-def getlines(filename):
+def getlines(filename, module_globals=None):
     """Get the lines for a file from the cache.
     Update the cache if it doesn't contain an entry for this file already."""
 
     if filename in cache:
         return cache[filename][2]
     else:
-        return updatecache(filename)
+        return updatecache(filename, module_globals)
 
 
 def checkcache(filename=None):
@@ -54,6 +54,8 @@
 
     for filename in filenames:
         size, mtime, lines, fullname = cache[filename]
+        if mtime is None:
+            continue   # no-op for files loaded via a __loader__
         try:
             stat = os.stat(fullname)
         except os.error:
@@ -63,7 +65,7 @@
             del cache[filename]
 
 
-def updatecache(filename):
+def updatecache(filename, module_globals=None):
     """Update a cache entry and return its list of lines.
     If something's wrong, print a message, discard the cache entry,
     and return an empty list."""
@@ -72,12 +74,34 @@
         del cache[filename]
     if not filename or filename[0] + filename[-1] == '<>':
         return []
+
     fullname = filename
     try:
         stat = os.stat(fullname)
     except os.error, msg:
-        # Try looking through the module search path.
         basename = os.path.split(filename)[1]
+
+        # Try for a __loader__, if available
+        if module_globals and '__loader__' in module_globals:
+            name = module_globals.get('__name__')
+            loader = module_globals['__loader__']
+            get_source = getattr(loader, 'get_source', None)
+
+            if name and get_source:
+                if basename.startswith(name.split('.')[-1]+'.'):
+                    try:
+                        data = get_source(name)
+                    except (ImportError, IOError):
+                        pass
+                    else:
+                        cache[filename] = (
+                            len(data), None,
+                            [line+'\n' for line in data.splitlines()], fullname
+                        )
+                        return cache[filename][2]
+
+        # Try looking through the module search path.
+
         for dirname in sys.path:
             # When using imputil, sys.path may contain things other than
             # strings; ignore them when it happens.