[Python-checkins] r53280 - 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
Fri Jan 5 22:59:40 CET 2007
Author: brett.cannon
Date: Fri Jan 5 22:59:39 2007
New Revision: 53280
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:
Tighten up API to just what needs to be publicly exposed by adding underscores
to various functions and methods.
Modified: sandbox/trunk/import_in_py/importer.py
==============================================================================
--- sandbox/trunk/import_in_py/importer.py (original)
+++ sandbox/trunk/import_in_py/importer.py Fri Jan 5 22:59:39 2007
@@ -1,7 +1,5 @@
"""Re-implementation of import machinery in Python source code.
-XXX See http://docs.google.com/View?docid=dg7fctr4_4d8tdbq on current status.
-
====================
References on import
====================
@@ -30,38 +28,39 @@
AttributeError.
+ Possible fix
- Implement optional interface for loaders.
+ - Do not have new loaders set __loader__.
+ * Might happen because of security issues.
* warnings and stack level.
+ Affected tests
- test___all__
- test_imageop
+ 'warnings' assumes that the import code does not show up in the call
stack.
- + Because import now in Python, import does show up in the call stack.
- + Trick of specifying that going back two levels will cause the warning
- to be raised in the caller for an import statement no longer holds true.
+ + Because import now implemented in Python, import does show up in the
+ call stack.
+ + Trick of specifying going back in the call stack two levels so warning
+ shows up in the caller will cause the warning no longer holds true.
+ Possible fixes
- Special module deprecation function.
- - Code in warnings.warn to handle import case.
+ - Code in warnings.warn to handle special import case.
- Flag on warnings.warn that warning is for an import and ignore stack
level argument.
* Could also infer from type of warning.
* test_pkg
+ Old-style test that compares output.
+ Setting of __loader__ leads to different output.
-* PEP 235 not implemented.
"""
from __future__ import with_statement
+# Built-in modules.
import imp
import sys
import marshal
-# XXX Following imports will eventually need to be removed since they are not
-# built-in modules.
+# Not built-in.
import errno
import os
import contextlib
-import py_compile
import warnings
@@ -76,7 +75,7 @@
_set__import__ was called previously)."""
__builtins__['__import__'] = original__import__
-def w_long(x):
+def _w_long(x):
"""Convert a 32-bit integer to little-endian.
XXX Temporary until marshal's long functions are exposed.
@@ -89,7 +88,7 @@
bytes.append((x >> 24) & 0xFF)
return ''.join(chr(x) for x in bytes)
-def r_long(bytes):
+def _r_long(bytes):
"""Convert 4 bytes in little-endian to an integer.
XXX Temporary until marshal's long function are exposed.
@@ -101,7 +100,7 @@
x |= ord(bytes[3]) << 24
return x
-def case_ok(directory, file_name):
+def _case_ok(directory, file_name):
"""Verify that file_name (as found in 'directory') has the proper case.
The path is assumed to already exist.
@@ -114,8 +113,6 @@
"""
if sys.platform not in ('win32', 'mac', 'riscos', 'darwin', 'cygwin',
'os2emx') or os.environ.get('PYTHONCASEOK'):
- # Platform is case-sensitive so existence check already handle
- # case-sensitivity.
return True
directory_contents = os.listdir(directory)
if file_name in directory_contents:
@@ -124,7 +121,7 @@
return False
-class BuiltinFrozenBaseImporter(object):
+class _BuiltinFrozenBaseImporter(object):
"""Base class for meta_path importers for built-in and frozen modules.
@@ -164,7 +161,7 @@
return mod
-class BuiltinImporter(BuiltinFrozenBaseImporter):
+class BuiltinImporter(_BuiltinFrozenBaseImporter):
"""sys.meta_path class for importing built-in modules.
@@ -177,7 +174,7 @@
_load = imp.init_builtin
-class FrozenImporter(BuiltinFrozenBaseImporter):
+class FrozenImporter(_BuiltinFrozenBaseImporter):
"""sys.meta_path class for importing frozen modules."""
@@ -248,17 +245,17 @@
init_filename = '__init__' + file_ext
package_init = os.path.join(package_directory, init_filename)
if (os.path.isfile(package_init) and
- case_ok(self.path_entry, tail_module) and
- case_ok(package_directory, init_filename)):
+ _case_ok(self.path_entry, tail_module) and
+ _case_ok(package_directory, init_filename)):
return self.loader(package_init, handler, package_directory)
file_name = tail_module + file_ext
file_path = os.path.join(self.path_entry, file_name)
if (os.path.isfile(file_path) and
- case_ok(self.path_entry, file_name)):
+ _case_ok(self.path_entry, file_name)):
return self.loader(file_path, handler)
else:
if (os.path.isdir(package_directory) and
- case_ok(self.path_entry, tail_module)):
+ _case_ok(self.path_entry, tail_module)):
warnings.warn("Not importing directory %s: missing __init__.py"
% package_directory,
ImportWarning)
@@ -367,7 +364,7 @@
def parse_pyc(self, data):
"""Split data into magic number, timestamp, and bytecode."""
- return data[:4], r_long(data[4:8]), data[8:]
+ return data[:4], _r_long(data[4:8]), data[8:]
def check_magic(self, magic):
"""Check whether the magic number is valid or not."""
@@ -389,7 +386,7 @@
def create_pyc(self, bytecode, timestamp):
"""Create data for a .pyc file."""
data = imp.get_magic()
- data += w_long(timestamp)
+ data += _w_long(timestamp)
data += marshal.dumps(bytecode)
return data
@@ -551,7 +548,7 @@
handlers = ExtensionFileHandler(), PyPycHandler()
self.default_path_hook = FileSystemFactory(*handlers)
- def search_meta_path(self, name, path=None):
+ def _search_meta_path(self, name, path=None):
"""Check the importers on sys.meta_path for a loader along with the
extended meta path sequence stored within this instance.
@@ -566,7 +563,7 @@
else:
raise ImportError("No module named %s" % name)
- def sys_path_importer(self, path_entry):
+ def _sys_path_importer(self, path_entry):
"""Return the importer for the specified path.
If None is stored in sys.path_importer_cache then use the default path
@@ -608,7 +605,7 @@
sys.path_importer_cache[path_entry] = None
raise ImportError("no importer found for %s" % path_entry)
- def search_std_path(self, name, path=None):
+ def _search_std_path(self, name, path=None):
"""Check sys.path or 'path' (depending if 'path' is set) for the
named module and return its loader."""
if path:
@@ -617,7 +614,7 @@
search_paths = sys.path
for entry in search_paths:
try:
- importer = self.sys_path_importer(entry)
+ importer = self._sys_path_importer(entry)
except ImportError:
continue
loader = importer.find_module(name)
@@ -626,7 +623,7 @@
else:
raise ImportError("No module found named %s" % name)
- def import_module(self, name, path=None):
+ def _import_module(self, name, path=None):
"""Import the specified module with no handling of parent modules.
If None is set for a value in sys.modules (to signify that a relative
@@ -641,16 +638,16 @@
return value
try:
# Attempt to find a loader on sys.meta_path.
- loader = self.search_meta_path(name, path)
+ loader = self._search_meta_path(name, path)
except ImportError:
# sys.meta_path search failed. Attempt to find a loader on
# sys.path. If this fails then module cannot be found.
- loader = self.search_std_path(name, path)
+ loader = self._search_std_path(name, path)
# A loader was found. It is the loader's responsibility to have put an
# entry in sys.modules.
return loader.load_module(name)
- def import_full_module(self, name):
+ def _import_full_module(self, name):
"""Import a module along with its parent modules and set into
sys.modules."""
# Import the module (importing its parent modules first).
@@ -671,12 +668,12 @@
path_list = parent_module.__path__
except AttributeError:
pass
- module = self.import_module(current_name, path_list)
+ module = self._import_module(current_name, path_list)
if parent_module:
setattr(parent_module, name_part, module)
parent_module = module
- def classic_resolve_name(self, name, caller_name, caller_is_package):
+ def _classic_resolve_name(self, name, caller_name, caller_is_package):
"""Return the absolute name of the module specified in 'name' as based
on the name of the caller and whether it is a package."""
if caller_is_package:
@@ -689,7 +686,7 @@
base_name = caller_name.rsplit('.', 1)[0]
return base_name + '.' + name
- def resolve_name(self, name, caller_name, caller_is_package, level):
+ def _resolve_name(self, name, caller_name, caller_is_package, level):
"""Return the absolute name of the module specified by 'name' based on
where the module is being imported and the requested change in dotted
name level.
@@ -711,7 +708,7 @@
else:
return base_name
- def return_module(self, absolute_name, relative_name, fromlist):
+ def _return_module(self, absolute_name, relative_name, fromlist):
"""Return the proper module based on what module was requested (and its
absolute module name), who is
requesting it, and whether any speicific attributes were specified.
@@ -755,10 +752,10 @@
if item == '*':
continue
if not hasattr(module, item):
- resolved_name = self.resolve_name(item, module.__name__,
+ resolved_name = self._resolve_name(item, module.__name__,
True, 1)
try:
- self.import_full_module(resolved_name)
+ self._import_full_module(resolved_name)
except ImportError:
pass
return module
@@ -808,30 +805,30 @@
# Handle the classic style of import: relative first, then
# absolute.
if level == -1:
- relative_name = self.classic_resolve_name(name, caller_name,
+ relative_name = self._classic_resolve_name(name, caller_name,
is_pkg)
imported_name = relative_name
try:
# Try a relative import.
- self.import_full_module(imported_name)
+ self._import_full_module(imported_name)
except ImportError:
# If the relative import fails (or is redirected), try an
# absolute import.
imported_name = name
- self.import_full_module(imported_name)
+ self._import_full_module(imported_name)
# Redirection entry for resolved relative name to instead
# redirect to the absolute import.
sys.modules[relative_name] = None
# If using absolute imports with a relative path, only attempt with
# the fully-resolved module name.
else:
- imported_name = self.resolve_name(name, caller_name, is_pkg,
+ imported_name = self._resolve_name(name, caller_name, is_pkg,
level)
# This call will also handle setting the attribute on the
# package.
- self.import_full_module(imported_name)
+ self._import_full_module(imported_name)
else:
imported_name = name
- self.import_full_module(name)
+ self._import_full_module(name)
relative_name = '' if imported_name == name else name
- return self.return_module(imported_name, relative_name, fromlist)
+ return self._return_module(imported_name, relative_name, fromlist)
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 Fri Jan 5 22:59:39 2007
@@ -2,8 +2,7 @@
import marshal
import imp
from test import test_support
-# XXX for w_long and r_long
-from importer import w_long, r_long
+from importer import _w_long
def log_call(method):
"""Log method calls to self.log."""
@@ -94,9 +93,9 @@
magic = imp.get_magic()
pyc = magic[:3] + chr(ord(magic[3]) - 1)
if good_timestamp:
- pyc += w_long(self.modification_time)
+ pyc += _w_long(self.modification_time)
else:
- pyc += w_long(self.modification_time - 1)
+ pyc += _w_long(self.modification_time - 1)
# Needed for read_data on .pyc path.
if good_bytecode:
self.pyc = pyc + bytecode
@@ -198,7 +197,7 @@
assert path[1] == self.pyc_ext, "%s != %s" % (path[1], self.pyc_ext)
assert binary
assert data[:4] == imp.get_magic()
- assert w_long(self.modification_time) == data[4:8]
+ assert _w_long(self.modification_time) == data[4:8]
module = MockModule(self.module_name)
code = marshal.loads(data[8:])
exec code in module.__dict__
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 Fri Jan 5 22:59:39 2007
@@ -653,7 +653,7 @@
data = self.handler.create_pyc(bytecode, timestamp)
self.failUnlessEqual(imp.get_magic(), data[:4])
# XXX Using importer module's marshal long function.
- self.failUnlessEqual(timestamp, importer.r_long(data[4:8]))
+ self.failUnlessEqual(timestamp, importer._r_long(data[4:8]))
self.failUnlessEqual(marshal.dumps(bytecode), data[8:])
@@ -865,7 +865,7 @@
# Importing from within a package's __init__ file should lead to a
# resolved import name of the package name tacked on to the name of the
# module being imported.
- resolved_name = self.importer.classic_resolve_name(self.child_name,
+ resolved_name = self.importer._classic_resolve_name(self.child_name,
self.parent_name,
True)
self.failUnlessEqual(resolved_name, self.full_child_name)
@@ -875,7 +875,7 @@
# module name being removed and replaced with the name of what is to be
# imported.
calling_from = self.parent_name + '.' + '<calling from>'
- resolved_name = self.importer.classic_resolve_name(self.child_name,
+ resolved_name = self.importer._classic_resolve_name(self.child_name,
calling_from,
False)
self.failUnlessEqual(resolved_name, self.full_child_name)
@@ -884,7 +884,7 @@
# Trying to import a single level within a package within it's __init__
# module should stay within the package.
# ``from .child_name import ...`` in a package.
- resolved_name = self.importer.resolve_name(self.child_name,
+ resolved_name = self.importer._resolve_name(self.child_name,
self.parent_name, True, 1)
self.failUnlessEqual(resolved_name, self.full_child_name)
@@ -893,7 +893,7 @@
# within the same directory as the module requesting the import.
# ``from .child_name import ...`` in a package module.
calling_from = self.parent_name + '.' + '<calling from>'
- resolved_name = self.importer.resolve_name(self.child_name,
+ resolved_name = self.importer._resolve_name(self.child_name,
calling_from, False, 1)
self.failUnlessEqual(resolved_name, self.full_child_name)
@@ -902,7 +902,7 @@
depth = 10
name_extension = (str(x) for x in xrange(10))
calling_from = self.parent_name + '.' + '.'.join(name_extension)
- resolved_name = self.importer.resolve_name(self.child_name,
+ resolved_name = self.importer._resolve_name(self.child_name,
calling_from, False, depth)
self.failUnlessEqual(resolved_name, self.full_child_name)
@@ -910,7 +910,7 @@
# Attempting to go too high out of a package in its __init__ file
# should raise ImportError.
# ``from ..child_name import ...`` in a top-level package.
- self.failUnlessRaises(ImportError, self.importer.resolve_name,
+ self.failUnlessRaises(ImportError, self.importer._resolve_name,
self.child_name, self.parent_name, True, 2)
def test_attempt_to_escape_out_of_package_module(self):
@@ -918,25 +918,25 @@
# ImportError.
# ``from ..child_name import ...`` in a top-level package module.
calling_from = self.parent_name + '.' + '<calling from>'
- self.failUnlessRaises(ImportError, self.importer.resolve_name,
+ self.failUnlessRaises(ImportError, self.importer._resolve_name,
self.child_name, calling_from, False, 2)
def test_relative_import_in_top_level(self):
# Attempting a relative import in a top-level location should raise
# ImportError.
# ``from .child_name import ...`` outside of a package.
- self.failUnlessRaises(ImportError, self.importer.resolve_name,
+ self.failUnlessRaises(ImportError, self.importer._resolve_name,
self.child_name, self.parent_name, False, 1)
def test_relative_import_in_package_init(self):
# ``from . import ...`` in a package.
- resolved_name = self.importer.resolve_name('', self.parent_name, True,
+ resolved_name = self.importer._resolve_name('', self.parent_name, True,
1)
self.failUnlessEqual(resolved_name, self.parent_name)
def test_relative_import_in_package_module(self):
# ``from . import ...`` in a package module.
- resolved_name = self.importer.resolve_name('', self.full_child_name,
+ resolved_name = self.importer._resolve_name('', self.full_child_name,
False, 1)
self.failUnlessEqual(resolved_name, self.parent_name)
@@ -973,7 +973,7 @@
succeed = mock_importer.SucceedImporter()
sys.meta_path.append(succeed)
# Import the package with a fromlist of the module.
- module = self.importer.return_module(pkg_name, '',
+ module = self.importer._return_module(pkg_name, '',
fromlist=[module_name])
self.failUnless(hasattr(module, module_name))
fromlist_module = getattr(module, module_name)
@@ -986,7 +986,7 @@
pkg_module = mock_importer.MockModule(pkg_name, pkg_list=['some path'])
sys.modules[pkg_name] = pkg_module
nonexistent_attr = 'asdfsdfd'
- module = self.importer.return_module(pkg_name, '',
+ module = self.importer._return_module(pkg_name, '',
fromlist=[nonexistent_attr])
self.failUnless(not hasattr(module, nonexistent_attr))
@@ -1036,7 +1036,7 @@
# An empty fromlist means that the root module is returned.
sys.modules[self.parent_name] = self.parent_module
sys.modules[self.full_child_name] = self.child_module
- module = self.importer.return_module(self.full_child_name, '', [])
+ module = self.importer._return_module(self.full_child_name, '', [])
self.failUnless(module is self.parent_module)
def test_nonempty_fromlist(self):
@@ -1045,7 +1045,7 @@
sys.modules[self.full_child_name] = self.child_module
test_attr_name = 'test_attr'
setattr(self.child_module, test_attr_name, None)
- module = self.importer.return_module(self.full_child_name, '',
+ module = self.importer._return_module(self.full_child_name, '',
[test_attr_name])
self.failUnless(module is self.child_module)
@@ -1054,7 +1054,7 @@
# then the module specified in the relative name is returned.
sys.modules[self.full_child_name] = self.child_module
sys.modules[self.parent_name] = self.parent_module
- module = self.importer.return_module(self.full_child_name,
+ module = self.importer._return_module(self.full_child_name,
self.child_name, [])
self.failUnless(module is self.child_module)
@@ -1066,7 +1066,7 @@
extra_depth = '.baz'
absolute_name = self.full_child_name + extra_depth
relative_name = self.child_name + extra_depth
- module = self.importer.return_module(absolute_name, relative_name, [])
+ module = self.importer._return_module(absolute_name, relative_name, [])
self.failUnless(module is self.child_module)
@@ -1082,14 +1082,14 @@
def test_sys_module_return(self):
# A module found in sys.modules should be returned immediately.
sys.modules[self.parent_name] = self.parent_module
- module = self.importer.import_module(self.parent_name)
+ module = self.importer._import_module(self.parent_name)
self.failUnless(module is self.parent_module)
def test_sys_module_None(self):
# If sys.modules contains None for a module name, then raise ImportError.
module_name = '<module>'
sys.modules[module_name] = None
- self.failUnlessRaises(ImportError, self.importer.import_module,
+ self.failUnlessRaises(ImportError, self.importer._import_module,
module_name)
def test_parent_missing(self):
@@ -1150,13 +1150,13 @@
# Test search method of sys.meta_path.
# Should raise ImportError on error.
self.clear_sys_modules('sys')
- self.failUnlessRaises(ImportError, self.importer.search_meta_path,
+ self.failUnlessRaises(ImportError, self.importer._search_meta_path,
'sys')
# Verify call order.
meta_path = (mock_importer.PassImporter(),
mock_importer.SucceedImporter())
sys.meta_path = meta_path
- loader = self.importer.search_meta_path('sys')
+ loader = self.importer._search_meta_path('sys')
for entry in meta_path:
self.failUnlessEqual(entry.find_request, ('sys', None))
self.failUnless(loader is meta_path[-1])
@@ -1169,7 +1169,7 @@
sys.meta_path = [pass_importer]
succeed_importer = mock_importer.SucceedImporter()
importer_ = importer.Import(extended_meta_path=(succeed_importer,))
- module = importer_.import_module('sys')
+ module = importer_._import_module('sys')
for meta_importer in (pass_importer, succeed_importer):
self.failUnlessEqual(meta_importer.find_request, ('sys', None))
self.failUnless(module in succeed_importer.loaded_modules)
@@ -1207,7 +1207,7 @@
sys.meta_path = []
sys.path = ['<succeed>']
sys.path_importer_cache['<succeed>'] = None
- module = importer_.import_module(module_name)
+ module = importer_._import_module(module_name)
self.failUnlessEqual(succeed_importer.find_request,
(module_name, None))
self.failUnless(module in succeed_importer.loaded_modules)
@@ -1221,7 +1221,7 @@
pass_importer = mock_importer.PassImporter.set_on_sys_path()
succeed_importer = mock_importer.SucceedImporter.set_on_sys_path()
sys_path = (pass_importer, succeed_importer)
- module = importer_.import_module(module_name)
+ module = importer_._import_module(module_name)
for entry in sys_path:
self.failUnlessEqual(entry.find_request, (module_name, None))
self.failUnless(module in succeed_importer.loaded_modules)
@@ -1233,7 +1233,7 @@
self.clear_sys_modules(module_name)
sys.path = []
succeed_importer = mock_importer.SucceedImporter.set_on_sys_path()
- loader = self.importer.search_std_path(module_name)
+ loader = self.importer._search_std_path(module_name)
self.failUnless(loader is succeed_importer)
def test_importer_cache_from_path_hooks(self):
@@ -1247,7 +1247,7 @@
sys.path = [path_entry]
sys.path_importer_cache.clear()
sys.path_hooks = [succeed_importer]
- loader = self.importer.search_std_path(module_name)
+ loader = self.importer._search_std_path(module_name)
self.failUnless(loader is succeed_importer)
self.failUnless(sys.path_importer_cache[path_entry] is
succeed_importer)
@@ -1261,7 +1261,7 @@
sys.path = [path_entry]
sys.path_hooks = []
sys.path_importer_cache.clear()
- self.failUnlessRaises(ImportError, self.importer.search_std_path,
+ self.failUnlessRaises(ImportError, self.importer._search_std_path,
module_name)
self.failUnless(sys.path_importer_cache[path_entry] is None)
@@ -1272,7 +1272,7 @@
sys.path_hooks.append(succeed_importer)
search_paths = ['test path']
module_name = '<pkg>.<dummy>'
- loader = self.importer.search_std_path(module_name, search_paths)
+ loader = self.importer._search_std_path(module_name, search_paths)
self.failUnless(loader is succeed_importer)
self.failUnless(search_paths[0] in succeed_importer.path_entries)
self.failUnlessEqual(succeed_importer.find_request,
@@ -1281,7 +1281,7 @@
self.clear_sys_modules(module_name)
del sys.path_importer_cache[search_paths[0]]
succeed_importer.path_entries = []
- self.importer.import_module(module_name, search_paths)
+ self.importer._import_module(module_name, search_paths)
self.failUnless(search_paths[0] in succeed_importer.path_entries)
@@ -1404,8 +1404,8 @@
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])
+ # 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)
More information about the Python-checkins
mailing list