summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorNick Coghlan <ncoghlan@gmail.com>2007-12-03 12:55:17 (GMT)
committerNick Coghlan <ncoghlan@gmail.com>2007-12-03 12:55:17 (GMT)
commitef01d822aaea11ae25f78cb0be32865a5df07620 (patch)
tree0fbbaa653cb033490019809a9eb8b3c3ac942c74 /Lib
parentf19b95112669db32556c157c04f064d319c11f09 (diff)
downloadcpython-ef01d822aaea11ae25f78cb0be32865a5df07620.zip
cpython-ef01d822aaea11ae25f78cb0be32865a5df07620.tar.gz
cpython-ef01d822aaea11ae25f78cb0be32865a5df07620.tar.bz2
Implement PEP 366
Diffstat (limited to 'Lib')
-rwxr-xr-xLib/runpy.py20
-rw-r--r--Lib/test/test_cmd_line_script.py94
-rw-r--r--Lib/test/test_pkg.py24
-rw-r--r--Lib/test/test_runpy.py33
4 files changed, 118 insertions, 53 deletions
diff --git a/Lib/runpy.py b/Lib/runpy.py
index 4e8d563..673b1a8 100755
--- a/Lib/runpy.py
+++ b/Lib/runpy.py
@@ -23,19 +23,20 @@ __all__ = [
def _run_code(code, run_globals, init_globals=None,
mod_name=None, mod_fname=None,
- mod_loader=None):
+ mod_loader=None, pkg_name=None):
"""Helper for _run_module_code"""
if init_globals is not None:
run_globals.update(init_globals)
run_globals.update(__name__ = mod_name,
__file__ = mod_fname,
- __loader__ = mod_loader)
+ __loader__ = mod_loader,
+ __package__ = pkg_name)
exec code in run_globals
return run_globals
def _run_module_code(code, init_globals=None,
mod_name=None, mod_fname=None,
- mod_loader=None):
+ mod_loader=None, pkg_name=None):
"""Helper for run_module"""
# Set up the top level namespace dictionary
temp_module = imp.new_module(mod_name)
@@ -49,7 +50,8 @@ def _run_module_code(code, init_globals=None,
sys.modules[mod_name] = temp_module
try:
_run_code(code, mod_globals, init_globals,
- mod_name, mod_fname, mod_loader)
+ mod_name, mod_fname,
+ mod_loader, pkg_name)
finally:
sys.argv[0] = saved_argv0
if restore_module:
@@ -95,11 +97,12 @@ def _run_module_as_main(mod_name, set_argv0=True):
__loader__
"""
loader, code, fname = _get_module_details(mod_name)
+ pkg_name = mod_name.rpartition('.')[0]
main_globals = sys.modules["__main__"].__dict__
if set_argv0:
sys.argv[0] = fname
return _run_code(code, main_globals, None,
- "__main__", fname, loader)
+ "__main__", fname, loader, pkg_name)
def run_module(mod_name, init_globals=None,
run_name=None, alter_sys=False):
@@ -110,13 +113,14 @@ def run_module(mod_name, init_globals=None,
loader, code, fname = _get_module_details(mod_name)
if run_name is None:
run_name = mod_name
+ pkg_name = mod_name.rpartition('.')[0]
if alter_sys:
return _run_module_code(code, init_globals, run_name,
- fname, loader)
+ fname, loader, pkg_name)
else:
# Leave the sys module alone
- return _run_code(code, {}, init_globals,
- run_name, fname, loader)
+ return _run_code(code, {}, init_globals, run_name,
+ fname, loader, pkg_name)
if __name__ == "__main__":
diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py
index 3a8e8f1..9d78356 100644
--- a/Lib/test/test_cmd_line_script.py
+++ b/Lib/test/test_cmd_line_script.py
@@ -35,15 +35,15 @@ def temp_dir():
finally:
shutil.rmtree(dirname)
-test_source = ("""\
+test_source = """\
# Script may be run with optimisation enabled, so don't rely on assert
# statements being executed
def assertEqual(lhs, rhs):
if lhs != rhs:
- raise AssertionError("%r != %r" % (lhs, rhs))
+ raise AssertionError('%r != %r' % (lhs, rhs))
def assertIdentical(lhs, rhs):
if lhs is not rhs:
- raise AssertionError("%r is not %r" % (lhs, rhs))
+ raise AssertionError('%r is not %r' % (lhs, rhs))
# Check basic code execution
result = ['Top level assignment']
def f():
@@ -53,17 +53,18 @@ assertEqual(result, ['Top level assignment', 'Lower level reference'])
# Check population of magic variables
assertEqual(__name__, '__main__')
print '__file__==%r' % __file__
+print '__package__==%r' % __package__
# Check the sys module
import sys
assertIdentical(globals(), sys.modules[__name__].__dict__)
print 'sys.argv[0]==%r' % sys.argv[0]
-""")
+"""
-def _make_test_script(script_dir, script_basename):
- script_filename = script_basename+os.extsep+"py"
+def _make_test_script(script_dir, script_basename, source=test_source):
+ script_filename = script_basename+os.extsep+'py'
script_name = os.path.join(script_dir, script_filename)
- script_file = open(script_name, "w")
- script_file.write(test_source)
+ script_file = open(script_name, 'w')
+ script_file.write(source)
script_file.close()
return script_name
@@ -76,71 +77,108 @@ def _compile_test_script(script_name):
return compiled_name
def _make_test_zip(zip_dir, zip_basename, script_name):
- zip_filename = zip_basename+os.extsep+"zip"
+ zip_filename = zip_basename+os.extsep+'zip'
zip_name = os.path.join(zip_dir, zip_filename)
zip_file = zipfile.ZipFile(zip_name, 'w')
zip_file.write(script_name, os.path.basename(script_name))
zip_file.close()
# if verbose:
# zip_file = zipfile.ZipFile(zip_name, 'r')
- # print "Contents of %r:" % zip_name
+ # print 'Contents of %r:' % zip_name
# zip_file.printdir()
# zip_file.close()
return zip_name
+def _make_test_pkg(pkg_dir):
+ os.mkdir(pkg_dir)
+ _make_test_script(pkg_dir, '__init__', '')
+
+# There's no easy way to pass the script directory in to get
+# -m to work (avoiding that is the whole point of making
+# directories and zipfiles executable!)
+# So we fake it for testing purposes with a custom launch script
+launch_source = """\
+import sys, os.path, runpy
+sys.path[0:0] = os.path.dirname(__file__)
+runpy._run_module_as_main(%r)
+"""
+
+def _make_launch_script(script_dir, script_basename, module_name):
+ return _make_test_script(script_dir, script_basename,
+ launch_source % module_name)
+
class CmdLineTest(unittest.TestCase):
- def _check_script(self, script_name, expected_file, expected_argv0):
- exit_code, data = _run_python(script_name)
+ def _check_script(self, script_name, expected_file,
+ expected_argv0, expected_package,
+ *cmd_line_switches):
+ run_args = cmd_line_switches + (script_name,)
+ exit_code, data = _run_python(*run_args)
if verbose:
- print "Output from test script %r:" % script_name
+ print 'Output from test script %r:' % script_name
print data
self.assertEqual(exit_code, 0)
printed_file = '__file__==%r' % expected_file
printed_argv0 = 'sys.argv[0]==%r' % expected_argv0
+ printed_package = '__package__==%r' % expected_package
+ if verbose:
+ print 'Expected output:'
+ print printed_file
+ print printed_package
+ print printed_argv0
self.assert_(printed_file in data)
+ self.assert_(printed_package in data)
self.assert_(printed_argv0 in data)
def test_basic_script(self):
with temp_dir() as script_dir:
- script_name = _make_test_script(script_dir, "script")
- self._check_script(script_name, script_name, script_name)
+ script_name = _make_test_script(script_dir, 'script')
+ self._check_script(script_name, script_name, script_name, None)
def test_script_compiled(self):
with temp_dir() as script_dir:
- script_name = _make_test_script(script_dir, "script")
+ script_name = _make_test_script(script_dir, 'script')
compiled_name = _compile_test_script(script_name)
os.remove(script_name)
- self._check_script(compiled_name, compiled_name, compiled_name)
+ self._check_script(compiled_name, compiled_name, compiled_name, None)
def test_directory(self):
with temp_dir() as script_dir:
- script_name = _make_test_script(script_dir, "__main__")
- self._check_script(script_dir, script_name, script_dir)
+ script_name = _make_test_script(script_dir, '__main__')
+ self._check_script(script_dir, script_name, script_dir, '')
def test_directory_compiled(self):
with temp_dir() as script_dir:
- script_name = _make_test_script(script_dir, "__main__")
+ script_name = _make_test_script(script_dir, '__main__')
compiled_name = _compile_test_script(script_name)
os.remove(script_name)
- self._check_script(script_dir, compiled_name, script_dir)
+ self._check_script(script_dir, compiled_name, script_dir, '')
def test_zipfile(self):
with temp_dir() as script_dir:
- script_name = _make_test_script(script_dir, "__main__")
- zip_name = _make_test_zip(script_dir, "test_zip", script_name)
- self._check_script(zip_name, None, zip_name)
+ script_name = _make_test_script(script_dir, '__main__')
+ zip_name = _make_test_zip(script_dir, 'test_zip', script_name)
+ self._check_script(zip_name, None, zip_name, '')
def test_zipfile_compiled(self):
with temp_dir() as script_dir:
- script_name = _make_test_script(script_dir, "__main__")
+ script_name = _make_test_script(script_dir, '__main__')
compiled_name = _compile_test_script(script_name)
- zip_name = _make_test_zip(script_dir, "test_zip", compiled_name)
- self._check_script(zip_name, None, zip_name)
+ zip_name = _make_test_zip(script_dir, 'test_zip', compiled_name)
+ self._check_script(zip_name, None, zip_name, '')
+
+ def test_module_in_package(self):
+ with temp_dir() as script_dir:
+ pkg_dir = os.path.join(script_dir, 'test_pkg')
+ _make_test_pkg(pkg_dir)
+ script_name = _make_test_script(pkg_dir, 'script')
+ launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.script')
+ self._check_script(launch_name, script_name,
+ script_name, 'test_pkg')
def test_main():
test.test_support.run_unittest(CmdLineTest)
test.test_support.reap_children()
-if __name__ == "__main__":
+if __name__ == '__main__':
test_main()
diff --git a/Lib/test/test_pkg.py b/Lib/test/test_pkg.py
index 7a4c01b..28f9943 100644
--- a/Lib/test/test_pkg.py
+++ b/Lib/test/test_pkg.py
@@ -188,11 +188,13 @@ class Test(unittest.TestCase):
import t5
self.assertEqual(fixdir(dir(t5)),
['__doc__', '__file__', '__name__',
- '__path__', 'foo', 'string', 't5'])
+ '__package__', '__path__', 'foo', 'string', 't5'])
self.assertEqual(fixdir(dir(t5.foo)),
- ['__doc__', '__file__', '__name__', 'string'])
+ ['__doc__', '__file__', '__name__', '__package__',
+ 'string'])
self.assertEqual(fixdir(dir(t5.string)),
- ['__doc__', '__file__', '__name__', 'spam'])
+ ['__doc__', '__file__', '__name__','__package__',
+ 'spam'])
def test_6(self):
hier = [
@@ -208,14 +210,14 @@ class Test(unittest.TestCase):
import t6
self.assertEqual(fixdir(dir(t6)),
['__all__', '__doc__', '__file__',
- '__name__', '__path__'])
+ '__name__', '__package__', '__path__'])
s = """
import t6
from t6 import *
self.assertEqual(fixdir(dir(t6)),
['__all__', '__doc__', '__file__',
- '__name__', '__path__', 'eggs',
- 'ham', 'spam'])
+ '__name__', '__package__', '__path__',
+ 'eggs', 'ham', 'spam'])
self.assertEqual(dir(), ['eggs', 'ham', 'self', 'spam', 't6'])
"""
self.run_code(s)
@@ -241,17 +243,19 @@ class Test(unittest.TestCase):
t7, sub, subsub = None, None, None
import t7 as tas
self.assertEqual(fixdir(dir(tas)),
- ['__doc__', '__file__', '__name__', '__path__'])
+ ['__doc__', '__file__', '__name__',
+ '__package__', '__path__'])
self.failIf(t7)
from t7 import sub as subpar
self.assertEqual(fixdir(dir(subpar)),
- ['__doc__', '__file__', '__name__', '__path__'])
+ ['__doc__', '__file__', '__name__',
+ '__package__', '__path__'])
self.failIf(t7)
self.failIf(sub)
from t7.sub import subsub as subsubsub
self.assertEqual(fixdir(dir(subsubsub)),
- ['__doc__', '__file__', '__name__', '__path__',
- 'spam'])
+ ['__doc__', '__file__', '__name__',
+ '__package__', '__path__', 'spam'])
self.failIf(t7)
self.failIf(sub)
self.failIf(subsub)
diff --git a/Lib/test/test_runpy.py b/Lib/test/test_runpy.py
index dfefee9..165cb63 100644
--- a/Lib/test/test_runpy.py
+++ b/Lib/test/test_runpy.py
@@ -5,7 +5,12 @@ import os.path
import sys
import tempfile
from test.test_support import verbose, run_unittest, forget
-from runpy import _run_code, _run_module_code, _run_module_as_main, run_module
+from runpy import _run_code, _run_module_code, run_module
+
+# Note: This module can't safely test _run_module_as_main as it
+# runs its tests in the current process, which would mess with the
+# real __main__ module (usually test.regrtest)
+# See test_cmd_line_script for a test that executes that code path
# Set up the test code and expected results
@@ -36,6 +41,7 @@ class RunModuleCodeTest(unittest.TestCase):
self.failUnless(d["__name__"] is None)
self.failUnless(d["__file__"] is None)
self.failUnless(d["__loader__"] is None)
+ self.failUnless(d["__package__"] is None)
self.failUnless(d["run_argv0"] is saved_argv0)
self.failUnless("run_name" not in d)
self.failUnless(sys.argv[0] is saved_argv0)
@@ -45,13 +51,15 @@ class RunModuleCodeTest(unittest.TestCase):
name = "<Nonsense>"
file = "Some other nonsense"
loader = "Now you're just being silly"
+ package = '' # Treat as a top level module
d1 = dict(initial=initial)
saved_argv0 = sys.argv[0]
d2 = _run_module_code(self.test_source,
d1,
name,
file,
- loader)
+ loader,
+ package)
self.failUnless("result" not in d1)
self.failUnless(d2["initial"] is initial)
self.failUnless(d2["result"] == self.expected_result)
@@ -62,6 +70,7 @@ class RunModuleCodeTest(unittest.TestCase):
self.failUnless(d2["__file__"] is file)
self.failUnless(d2["run_argv0"] is file)
self.failUnless(d2["__loader__"] is loader)
+ self.failUnless(d2["__package__"] is package)
self.failUnless(sys.argv[0] is saved_argv0)
self.failUnless(name not in sys.modules)
@@ -164,7 +173,7 @@ class RunModuleTest(unittest.TestCase):
self._del_pkg(pkg_dir, depth, mod_name)
if verbose: print "Module executed successfully"
- def _add_relative_modules(self, base_dir, depth):
+ def _add_relative_modules(self, base_dir, source, depth):
if depth <= 1:
raise ValueError("Relative module test needs depth > 1")
pkg_name = "__runpy_pkg__"
@@ -190,7 +199,7 @@ class RunModuleTest(unittest.TestCase):
if verbose: print " Added nephew module:", nephew_fname
def _check_relative_imports(self, depth, run_name=None):
- contents = """\
+ contents = r"""\
from __future__ import absolute_import
from . import sibling
from ..uncle.cousin import nephew
@@ -198,16 +207,21 @@ from ..uncle.cousin import nephew
pkg_dir, mod_fname, mod_name = (
self._make_pkg(contents, depth))
try:
- self._add_relative_modules(pkg_dir, depth)
+ self._add_relative_modules(pkg_dir, contents, depth)
+ pkg_name = mod_name.rpartition('.')[0]
if verbose: print "Running from source:", mod_name
- d1 = run_module(mod_name) # Read from source
+ d1 = run_module(mod_name, run_name=run_name) # Read from source
+ self.failUnless("__package__" in d1)
+ self.failUnless(d1["__package__"] == pkg_name)
self.failUnless("sibling" in d1)
self.failUnless("nephew" in d1)
del d1 # Ensure __loader__ entry doesn't keep file open
__import__(mod_name)
os.remove(mod_fname)
if verbose: print "Running from compiled:", mod_name
- d2 = run_module(mod_name) # Read from bytecode
+ d2 = run_module(mod_name, run_name=run_name) # Read from bytecode
+ self.failUnless("__package__" in d2)
+ self.failUnless(d2["__package__"] == pkg_name)
self.failUnless("sibling" in d2)
self.failUnless("nephew" in d2)
del d2 # Ensure __loader__ entry doesn't keep file open
@@ -225,6 +239,11 @@ from ..uncle.cousin import nephew
if verbose: print "Testing relative imports at depth:", depth
self._check_relative_imports(depth)
+ def test_main_relative_import(self):
+ for depth in range(2, 5):
+ if verbose: print "Testing main relative imports at depth:", depth
+ self._check_relative_imports(depth, "__main__")
+
def test_main():
run_unittest(RunModuleCodeTest)