[Python-checkins] r52761 - sandbox/trunk/import_in_py/importer.py sandbox/trunk/import_in_py/mock_importer.py sandbox/trunk/import_in_py/test_importer.py
brett.cannon
python-checkins at python.org
Thu Nov 16 01:20:04 CET 2006
Author: brett.cannon
Date: Thu Nov 16 01:20:03 2006
New Revision: 52761
Modified:
sandbox/trunk/import_in_py/importer.py
sandbox/trunk/import_in_py/mock_importer.py
sandbox/trunk/import_in_py/test_importer.py
Log:
Finish filling in tests that required ability to read/write longs in
little-endian and fixing code accordingly.
Modified: sandbox/trunk/import_in_py/importer.py
==============================================================================
--- sandbox/trunk/import_in_py/importer.py (original)
+++ sandbox/trunk/import_in_py/importer.py Thu Nov 16 01:20:03 2006
@@ -152,8 +152,9 @@
import imp
import sys
import marshal
-# XXX Following imports will eventually need to be removed since they involve
-# Python source.
+# XXX Following imports will eventually need to be removed since they are not
+# built-in modules.
+import errno
import os
import contextlib
import py_compile
@@ -366,22 +367,24 @@
return module
def mod_time(self, path):
- """Return the modification time for the specified path."""
- return os.stat(path).st_mtime
+ """Return the modification time for the specified path as an integer."""
+ return int(os.stat(path).st_mtime)
def split_path(self, path):
"""Split the specified path into a base path and the type of the
path."""
return os.path.splitext(path)
- def create_path(self, base_path, type_):
+ def create_path(self, base_path, type_, must_exist=False):
"""Create a new path based on a base path and requested path type.
- If the created path does not exist, return None.
+ If must_exist is True, the path must already exist.
"""
path = base_path + type_
- return path if os.path.exists(path) else None
+ if must_exist:
+ path = path if os.path.exists(path) else None
+ return path
def read_data(self, path, binary=False):
"""Open the path and return the data read from it in the specified
@@ -392,8 +395,14 @@
def write_data(self, data, path, binary=False):
"""Write data to a specified path as either binary or textual data."""
- with open(path, 'wb' if binary else 'w') as data_file:
- data_file.write(data)
+ try:
+ with open(path, 'wb' if binary else 'w') as data_file:
+ data_file.write(data)
+ except IOError, exc:
+ if exc.errno == errno.EACCES:
+ pass
+ else:
+ raise
class PyPycHandler(object):
@@ -464,11 +473,12 @@
Take in an opaque path object and split it into a base path and a
string representing the type of the path (which should be in the
'handles' attribute of the handler).
- * create_path(base_path, type_)
+ * create_path(base_path, type_, must_exist)
Create an opaque path object from a base path and the type of path
- that is desired.
+ that is desired. If must_exist is True the path must already
+ exist.
* mod_time(path)
- Return the last modification time for a path.
+ Return the last modification time for a path as an integer.
* read_data(path, binary)
Read the data from the specified path. 'binary' is a boolean that
flags whether the data should be read as binary data or text data.
@@ -478,7 +488,7 @@
"""
source_path = None
- source_timstamp = None
+ source_timestamp = None
bytecode_path = None
module = self.new_module(mod_name)
# __file__, __path__, and __loader__ *must* be set on the module before
@@ -499,7 +509,7 @@
magic, pyc_timestamp, bytecode = self.parse_pyc(pyc_data)
# Try to find corresponding source code.
for source_handle in self.source_handles:
- source_path = loader.create_path(base_path, source_handle)
+ source_path = loader.create_path(base_path, source_handle, True)
if source_path:
break
try:
@@ -529,14 +539,15 @@
code = self.code_from_source(source, source_path)
# See if there is a corresponding path to bytecode.
if not bytecode_path:
- for bytecode_handle in self.bytecode_handles:
+ if self.bytecode_handles:
+ bytecode_handle = self.bytecode_handles[0]
bytecode_path = loader.create_path(base_path,
- bytecode_handle)
- if bytecode_path:
- source_timestamp = loader.mod_time(source_path)
- break
+ bytecode_handle)
+ source_timestamp = loader.mod_time(source_path)
# If there is a possible path to bytecode, generate .pyc file.
if bytecode_path:
+ if not source_timestamp:
+ source_timestamp = loader.mod_time(source_path)
pyc = self.create_pyc(code, source_timestamp)
loader.write_data(pyc, bytecode_path, True)
exec code in module.__dict__
Modified: sandbox/trunk/import_in_py/mock_importer.py
==============================================================================
--- sandbox/trunk/import_in_py/mock_importer.py (original)
+++ sandbox/trunk/import_in_py/mock_importer.py Thu Nov 16 01:20:03 2006
@@ -2,6 +2,8 @@
import marshal
import imp
from test import test_support
+# XXX for w_long and r_long
+from importer import w_long, r_long
def log_call(method):
"""Log method calls to self.log."""
@@ -77,14 +79,14 @@
code_object = compile(self.source, "<mock loader>", 'exec')
bytecode = marshal.dumps(code_object)
if good_magic:
- pyc = str(imp.get_magic())
+ pyc = imp.get_magic()
else:
- pyc += str(imp.get_magic()-1)
+ magic = imp.get_magic()
+ pyc = magic[:3] + chr(ord(magic[3]) - 1)
if good_timestamp:
- pyc += str(1).zfill(4)
+ pyc += w_long(self.modification_time)
else:
- pyc += str(0).zfill(4)
- # XXX Not proper until can marshal longs.
+ pyc += w_long(self.modification_time - 1)
# Needed for read_data on .pyc path.
self.pyc = pyc + bytecode
self.log = []
@@ -141,13 +143,16 @@
return path
@log_call
- def create_path(self, base, type_):
+ def create_path(self, base, type_, must_exist=False):
"""Create a tuple from 'base' and type_."""
assert base == self.base_path
assert type_ in (self.py_ext, self.pyc_ext)
- if type_ not in (self.py_ext, self.pyc_ext):
- return None
+ if must_exist:
+ if type_ not in (self.py_ext, self.pyc_ext):
+ return None
+ else:
+ return (base, type_)
else:
return (base, type_)
@@ -179,10 +184,9 @@
assert self.pyc_ext
assert path[1] == self.pyc_ext, "%s != %s" % (path[1], self.pyc_ext)
assert binary
- # XXX Assert proper magic number
- # XXX Assert time stamp
- # XXX mock
- module = imp.new_module(self.module_name)
+ assert data[:4] == imp.get_magic()
+ assert w_long(self.modification_time) == data[4:8]
+ module = MockModule(self.module_name)
code = marshal.loads(data[8:])
exec code in module.__dict__
assert self._verify_module(module, False)
Modified: sandbox/trunk/import_in_py/test_importer.py
==============================================================================
--- sandbox/trunk/import_in_py/test_importer.py (original)
+++ sandbox/trunk/import_in_py/test_importer.py Thu Nov 16 01:20:03 2006
@@ -468,6 +468,7 @@
# Modification time for the passed-in path should match the file.
true_mod_time = os.stat(self.file_path).st_mtime
mod_time = self.loader.mod_time(self.file_path)
+ self.failUnless(isinstance(mod_time, (int, long)))
self.failUnlessEqual(mod_time, true_mod_time)
def test_split_path(self):
@@ -482,6 +483,9 @@
path = self.loader.create_path(*self.loader.split_path(
self.file_path))
self.failUnlessEqual(path, true_path)
+ self.failUnlessEqual(None, self.loader.create_path('sadfasdfd', 'aaa',
+ True))
+ self.failUnlessEqual('ab', self.loader.create_path('a', 'b'))
def test_read_data(self):
# Should be able to read a file.
@@ -588,29 +592,37 @@
# Bytecode should not be written.
self.failUnless("write_data" not in loader.log)
- def XXX_test_bad_magic_no_py(self):
+ def test_bad_magic_no_py(self):
# ImportError should be raised when a .pyc has a bad magic number and
# there is no corresponding .py file.
- pass
+ loader = mock_importer.MockPyPycLoader.setup(good_magic=False,
+ py_exists=False)
+ handler = loader._create_handler(importer.PyPycHandler)
+ self.failUnlessRaises(ImportError, loader._handle_pyc, handler)
- def test_bad_timestamp_no_py(self):
- # XXX Can't test until can unmarshal timestamp from pyc.
- pass
-
def test_bad_bytecode_no_py(self):
- # XXX
+ # XXX Will bad bytecode lead to an ImportError?
pass
def test_bad_magic_w_py(self):
- # XXX Can't test until can unmarhsal magic number from pyc.
- pass
+ # A .pyc file with a bad magic number should lead to the .py file being
+ # used to generate a new .pyc.
+ loader = mock_importer.MockPyPycLoader.setup(good_magic=False)
+ handler = loader._create_handler(importer.PyPycHandler)
+ module = loader._handle_pyc(handler)
+ loader._verify_module(module)
+ self.failUnless("write_data" in loader.log)
- def test_bad_magic_w_py(self):
- # XXX Can't test until can unmarshal timestamp from pyc.
- pass
+ def test_bad_timestamp_w_py(self):
+ # A .pyc file with a outdated timestamp should be regenerated.
+ loader = mock_importer.MockPyPycLoader.setup(good_timestamp=False)
+ handler = loader._create_handler(importer.PyPycHandler)
+ module = loader._handle_pyc(handler)
+ loader._verify_module(module)
+ self.failUnless("write_data" in loader.log)
def test_bad_bytecode_w_py(self):
- # XXX
+ # XXX Will the bytecode be recreated?
pass
def test_py_no_pyc(self):
@@ -1079,7 +1091,18 @@
# Importing a .py file should work and generate a .pyc file.
os.remove(self.pyc_path)
module = self.import_(self.module_name)
- # XXX Cannot fully test creation of bytecode files yet.
+ self.verify_module(module)
+ self.failUnless(os.path.exists(self.pyc_path))
+ with open(self.pyc_path, 'rb') as pyc_file:
+ data = pyc_file.read()
+ self.failUnlessEqual(data[:4], imp.get_magic())
+ py_mod = int(os.stat(self.py_path).st_mtime)
+ # XXX Using importer's r_long.
+ pyc_mod = importer.r_long(data[4:8])
+ self.failUnlessEqual(py_mod, pyc_mod)
+ code = marshal.loads(data[8:])
+ module = mock_importer.MockModule(self.module_name)
+ exec code in module.__dict__
self.verify_module(module)
def test_top_level_package(self):
More information about the Python-checkins
mailing list