Author: Benjamin Peterson <benja...@python.org>
Branch: py3k
Changeset: r53484:794e8ba95264
Date: 2012-03-13 15:40 -0500
http://bitbucket.org/pypy/pypy/changeset/794e8ba95264/

Log:    give __file__ python3 semantics and add __cached__

diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -852,11 +852,17 @@
     pycode = ec.compiler.compile(source, pathname, 'exec', 0)
     return pycode
 
-def exec_code_module(space, w_mod, code_w):
+def exec_code_module(space, w_mod, code_w, pathname, cpathname):
     w_dict = space.getattr(w_mod, space.wrap('__dict__'))
     space.call_method(w_dict, 'setdefault',
                       space.wrap('__builtins__'),
                       space.wrap(space.builtin))
+    if pathname is not None:
+        w_pathname = get_sourcefile(space, pathname)
+    if w_pathname is None:
+        w_pathname = code_w.w_filename
+    space.setitem(w_dict, space.wrap("__file__"), w_pathname)
+    space.setitem(w_dict, space.wrap("__cached__"), space.wrap(cpathname))
     code_w.exec_code(space, w_dict, w_dict)
 
 def rightmost_sep(filename):
@@ -895,28 +901,44 @@
 
     right = rightmost_sep(pathname)
     if right < 0:
-        raise ValueError()
+        return None
     left = rightmost_sep(pathname[:right]) + 1
     assert left >= 0
     if pathname[left:right] != '__pycache__':
-        raise ValueError()
+        return None
 
     # Now verify that the path component to the right of the last
     # slash has two dots in it.
     rightpart = pathname[right + 1:]
     dot0 = rightpart.find('.') + 1
     if dot0 <= 0:
-        raise ValueError
+        return None
     dot1 = rightpart[dot0:].find('.') + 1
     if dot1 <= 0:
-        raise ValueError
+        return None
     # Too many dots?
     if rightpart[dot0 + dot1:].find('.') >= 0:
-        raise ValueError
+        return None
 
     result = pathname[:left] + rightpart[:dot0] + 'py'
     return result
 
+def get_sourcefile(space, filename):
+    l = len(filename)
+    if l < 5 or filename[-4:-1].lower() != ".py":
+        return space.wrap(filename)
+    py = make_source_pathname(filename)
+    if py is None:
+        py = filename[:-1]
+    try:
+        st = os.stat(py)
+    except OSError:
+        pass
+    else:
+        if stat.S_ISREG(st.st_mode):
+            return space.wrap(py)
+    return space.wrap(filename)
+
 @jit.dont_look_inside
 def load_source_module(space, w_modulename, w_mod, pathname, source,
                        write_pyc=True):
@@ -944,7 +966,7 @@
             code_w = read_compiled_module(space, cpathname, stream.readall())
         finally:
             stream.close()
-        space.setattr(w_mod, w('__file__'), w(cpathname))
+        pathname = cpathname
     else:
         code_w = parse_source_module(space, pathname, source)
 
@@ -953,7 +975,7 @@
                 write_compiled_module(space, code_w, cpathname, mode, mtime)
 
     update_code_filenames(space, code_w, pathname)
-    exec_code_module(space, w_mod, code_w)
+    exec_code_module(space, w_mod, code_w, pathname, cpathname)
 
     return w_mod
 
@@ -1048,7 +1070,7 @@
                               "Bad magic number in %s", cpathname)
     #print "loading pyc file:", cpathname
     code_w = read_compiled_module(space, cpathname, source)
-    exec_code_module(space, w_mod, code_w)
+    exec_code_module(space, w_mod, code_w, cpathname, cpathname)
 
     return w_mod
 
diff --git a/pypy/module/imp/interp_imp.py b/pypy/module/imp/interp_imp.py
--- a/pypy/module/imp/interp_imp.py
+++ b/pypy/module/imp/interp_imp.py
@@ -222,9 +222,8 @@
     The .pyc/.pyo file does not need to exist; this simply returns the path to
     the .py file calculated to correspond to the .pyc/.pyo file.  If path
     does not conform to PEP 3147 format, ValueError will be raised."""
-    try:
-        sourcename = importing.make_source_pathname(pathname)
-    except ValueError:
+    sourcename = importing.make_source_pathname(pathname)
+    if sourcename is None:
         raise operationerrfmt(space.w_ValueError,
                               "Not a PEP 3147 pyc path: %s", pathname)
     return space.wrap(sourcename)
diff --git a/pypy/module/imp/test/test_import.py 
b/pypy/module/imp/test/test_import.py
--- a/pypy/module/imp/test/test_import.py
+++ b/pypy/module/imp/test/test_import.py
@@ -163,6 +163,13 @@
     def w_exec_(self, cmd, ns):
         exec(cmd, ns)
 
+    def test_file_and_cached(self):
+        import compiled.x
+        assert "__pycache__" not in compiled.x.__file__
+        assert compiled.x.__file__.endswith(".py")
+        assert "__pycache__" in compiled.x.__cached__
+        assert compiled.x.__cached__.endswith(".pyc")
+
     def test_set_sys_modules_during_import(self):
         from evil_pkg import evil
         assert evil.a == 42
@@ -373,6 +380,7 @@
             import readonly.x    # cannot write x.pyc, but should not crash
         finally:
             os.chmod(p, 0o775)
+        assert "__pycache__" in readonly.x.__cached__
 
     def test__import__empty_string(self):
         raises(ValueError, __import__, "")
@@ -1217,17 +1225,14 @@
 
     def test_import_possibly_from_pyc(self):
         from compiled import x
-        if self.usepycfiles:
-            assert x.__file__.endswith('.pyc')
-        else:
-            assert x.__file__.endswith('.py')
+        assert x.__file__.endswith('.py')
         try:
             from compiled import lone
         except ImportError:
             assert not self.lonepycfiles, "should have found 'lone.pyc'"
         else:
             assert self.lonepycfiles, "should not have found 'lone.pyc'"
-            assert lone.__file__.endswith('.pyc')
+            assert lone.__cached__.endswith('.pyc')
 
 class AppTestNoLonePycFile(AppTestNoPycFile):
     spaceconfig = {
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to