]> granicus.if.org Git - python/commitdiff
Merge fix for #15230 from 3.2
authorNick Coghlan <ncoghlan@gmail.com>
Sat, 14 Jul 2012 14:07:43 +0000 (00:07 +1000)
committerNick Coghlan <ncoghlan@gmail.com>
Sat, 14 Jul 2012 14:07:43 +0000 (00:07 +1000)
1  2 
Lib/runpy.py
Lib/test/test_runpy.py
Misc/NEWS

diff --cc Lib/runpy.py
index 71c175fe653b1c96fa44b3895bdebefcd07b45a8,7cb4668a01cf5e347c8850ae79ce42d4d99cc9df..8ca325b0a3f95ff975fb5b139f9fb7c7cb8e89a4
@@@ -233,8 -243,9 +234,9 @@@ def run_path(path_name, init_globals=No
      """
      if run_name is None:
          run_name = "<run_path>"
+     pkg_name = run_name.rpartition(".")[0]
      importer = _get_importer(path_name)
 -    if isinstance(importer, imp.NullImporter):
 +    if isinstance(importer, (type(None), imp.NullImporter)):
          # Not a valid sys.path entry, so run the code directly
          # execfile() doesn't help as we want to allow compiled files
          code = _get_code_from_file(path_name)
index de44df07baf9bdee888ddddd01b7f818a677417b,85eb76fa79fc0e8ab3594012ecf853f3084da5fb..c39e281d93835cef128ad131a0ca9adbc0bf4c84
@@@ -156,63 -217,84 +219,88 @@@ class RunModuleTestCase(unittest.TestCa
                  try:
                      os.rmdir(fullname)
                  except OSError as ex:
-                     if verbose: print(ex) # Persist with cleaning up
+                     if verbose > 1: print(ex) # Persist with cleaning up
          try:
              os.rmdir(top)
-             if verbose: print("  Removed package tree")
+             if verbose > 1: print("  Removed package tree")
          except OSError as ex:
-             if verbose: print(ex) # Persist with cleaning up
+             if verbose > 1: print(ex) # Persist with cleaning up
+     def _fix_ns_for_legacy_pyc(self, ns, alter_sys):
+         char_to_add = "c" if __debug__ else "o"
+         ns["__file__"] += char_to_add
+         if alter_sys:
+             ns["run_argv0"] += char_to_add
  
-     def _check_module(self, depth):
+     def _check_module(self, depth, alter_sys=False):
          pkg_dir, mod_fname, mod_name = (
-                self._make_pkg("x=1\n", depth))
+                self._make_pkg(example_source, depth))
          forget(mod_name)
+         expected_ns = example_namespace.copy()
+         expected_ns.update({
+             "__name__": mod_name,
+             "__file__": mod_fname,
+             "__package__": mod_name.rpartition(".")[0],
+         })
+         if alter_sys:
+             expected_ns.update({
+                 "run_argv0": mod_fname,
+                 "run_name_in_sys_modules": True,
+                 "module_in_sys_modules": True,
+             })
+         def create_ns(init_globals):
+             return run_module(mod_name, init_globals, alter_sys=alter_sys)
          try:
-             if verbose: print("Running from source:", mod_name)
-             d1 = run_module(mod_name) # Read from source
-             self.assertIn("x", d1)
-             self.assertEqual(d1["x"], 1)
-             del d1 # Ensure __loader__ entry doesn't keep file open
+             if verbose > 1: print("Running from source:", mod_name)
+             self.check_code_execution(create_ns, expected_ns)
 +            importlib.invalidate_caches()
              __import__(mod_name)
              os.remove(mod_fname)
              make_legacy_pyc(mod_fname)
              unload(mod_name)  # In case loader caches paths
-             if verbose: print("Running from compiled:", mod_name)
 +            importlib.invalidate_caches()
-             d2 = run_module(mod_name) # Read from bytecode
-             self.assertIn("x", d2)
-             self.assertEqual(d2["x"], 1)
-             del d2 # Ensure __loader__ entry doesn't keep file open
+             if verbose > 1: print("Running from compiled:", mod_name)
+             self._fix_ns_for_legacy_pyc(expected_ns, alter_sys)
+             self.check_code_execution(create_ns, expected_ns)
          finally:
              self._del_pkg(pkg_dir, depth, mod_name)
-         if verbose: print("Module executed successfully")
+         if verbose > 1: print("Module executed successfully")
  
-     def _check_package(self, depth):
+     def _check_package(self, depth, alter_sys=False):
          pkg_dir, mod_fname, mod_name = (
-                self._make_pkg("x=1\n", depth, "__main__"))
-         pkg_name, _, _ = mod_name.rpartition(".")
+                self._make_pkg(example_source, depth, "__main__"))
+         pkg_name = mod_name.rpartition(".")[0]
          forget(mod_name)
+         expected_ns = example_namespace.copy()
+         expected_ns.update({
+             "__name__": mod_name,
+             "__file__": mod_fname,
+             "__package__": pkg_name,
+         })
+         if alter_sys:
+             expected_ns.update({
+                 "run_argv0": mod_fname,
+                 "run_name_in_sys_modules": True,
+                 "module_in_sys_modules": True,
+             })
+         def create_ns(init_globals):
+             return run_module(pkg_name, init_globals, alter_sys=alter_sys)
          try:
-             if verbose: print("Running from source:", pkg_name)
-             d1 = run_module(pkg_name) # Read from source
-             self.assertIn("x", d1)
-             self.assertTrue(d1["x"] == 1)
-             del d1 # Ensure __loader__ entry doesn't keep file open
+             if verbose > 1: print("Running from source:", pkg_name)
+             self.check_code_execution(create_ns, expected_ns)
 +            importlib.invalidate_caches()
              __import__(mod_name)
              os.remove(mod_fname)
              make_legacy_pyc(mod_fname)
              unload(mod_name)  # In case loader caches paths
-             if verbose: print("Running from compiled:", pkg_name)
+             if verbose > 1: print("Running from compiled:", pkg_name)
 +            importlib.invalidate_caches()
-             d2 = run_module(pkg_name) # Read from bytecode
-             self.assertIn("x", d2)
-             self.assertTrue(d2["x"] == 1)
-             del d2 # Ensure __loader__ entry doesn't keep file open
+             self._fix_ns_for_legacy_pyc(expected_ns, alter_sys)
+             self.check_code_execution(create_ns, expected_ns)
          finally:
              self._del_pkg(pkg_dir, depth, pkg_name)
-         if verbose: print("Package executed successfully")
+         if verbose > 1: print("Package executed successfully")
  
      def _add_relative_modules(self, base_dir, source, depth):
          if depth <= 1:
              module_dir = os.path.join(module_dir, pkg_name)
          # Add sibling module
          sibling_fname = os.path.join(module_dir, "sibling.py")
 -        sibling_file = open(sibling_fname, "w")
 -        sibling_file.close()
 +        create_empty_file(sibling_fname)
-         if verbose: print("  Added sibling module:", sibling_fname)
+         if verbose > 1: print("  Added sibling module:", sibling_fname)
          # Add nephew module
          uncle_dir = os.path.join(parent_dir, "uncle")
          self._add_pkg_dir(uncle_dir)
-         if verbose: print("  Added uncle package:", uncle_dir)
+         if verbose > 1: print("  Added uncle package:", uncle_dir)
          cousin_dir = os.path.join(uncle_dir, "cousin")
          self._add_pkg_dir(cousin_dir)
-         if verbose: print("  Added cousin package:", cousin_dir)
+         if verbose > 1: print("  Added cousin package:", cousin_dir)
          nephew_fname = os.path.join(cousin_dir, "nephew.py")
 -        nephew_file = open(nephew_fname, "w")
 -        nephew_file.close()
 +        create_empty_file(nephew_fname)
-         if verbose: print("  Added nephew module:", nephew_fname)
+         if verbose > 1: print("  Added nephew module:", nephew_fname)
  
      def _check_relative_imports(self, depth, run_name=None):
          contents = r"""\
@@@ -260,11 -347,10 +352,11 @@@ from ..uncle.cousin import nephe
              os.remove(mod_fname)
              make_legacy_pyc(mod_fname)
              unload(mod_name)  # In case the loader caches paths
-             if verbose: print("Running from compiled:", mod_name)
+             if verbose > 1: print("Running from compiled:", mod_name)
 +            importlib.invalidate_caches()
              d2 = run_module(mod_name, run_name=run_name) # Read from bytecode
-             self.assertIn("__package__", d2)
-             self.assertTrue(d2["__package__"] == pkg_name)
+             self.assertEqual(d2["__name__"], expected_name)
+             self.assertEqual(d2["__package__"], pkg_name)
              self.assertIn("sibling", d2)
              self.assertIn("nephew", d2)
              del d2 # Ensure __loader__ entry doesn't keep file open
diff --cc Misc/NEWS
index 89b1147fcd11cba989ca2bcbb16c0b1d082a63e9,1b2f4f41eb65e071a5fe7875cd7409b303b3b86c..5bdf2df3823523c6880df1d46ffe51e7aaa2cc61
+++ b/Misc/NEWS
@@@ -28,146 -16,6 +28,151 @@@ Core and Builtin
  - Issue #15033: Fix the exit status bug when modules invoked using -m swith,
    return the proper failure return value (1). Patch contributed by Jeff Knupp.
  
 +- Issue #15229: An OSError subclass whose __init__ doesn't call back
 +  OSError.__init__ could produce incomplete instances, leading to crashes
 +  when calling str() on them.
 +
 +Library
 +-------
 +
++- Issue #15230: runpy.run_path now correctly sets __package__ as described
++  in the documentation
++
 +- Issue #15315: Support VS 2010 in distutils cygwincompiler.
 +
 +- Issue #15294: Fix a regression in pkgutil.extend_path()'s handling of
 +  nested namespace packages.
 +
 +- Issue #15056: imp.cache_from_source() and source_from_cache() raise
 +  NotImplementedError when sys.implementation.cache_tag is set to None.
 +
 +- Issue #15256: Grammatical mistake in exception raised by imp.find_module().
 +
 +- Issue #5931: wsgiref environ variable SERVER_SOFTWARE will specify an
 +  implementation specific term like Cpython, Jython instead of generic "Python"
 +
 +- Issue #13248: Remove obsolete argument "max_buffer_size" of BufferedWriter
 +  and BufferedRWPair, from the io module.
 +
 +- Issue #13248: Remove obsolete argument "version" of argparse.ArgumentParser.
 +
 +- Issue #14814: implement more consistent ordering and sorting behaviour
 +  for ipaddress objects
 +
 +- Issue #14814: ipaddress network objects correctly return NotImplemented
 +  when compared to arbitrary objects instead of raising TypeError
 +
 +- Issue #14990: Correctly fail with SyntaxError on invalid encoding
 +  declaration.
 +
 +- Issue #14814: ipaddress now provides more informative error messages when
 +  constructing instances directly (changes permitted during beta due to
 +  provisional API status)
 +
 +- Issue #15247: FileIO now raises an error when given a file descriptor
 +  pointing to a directory.
 +
 +- Issue #15261: Stop os.stat(fd) crashing on Windows when fd not open.
 +
 +- Issue #15166: Implement imp.get_tag() using sys.implementation.cache_tag.
 +
 +- Issue #15210: Catch KeyError when imprortlib.__init__ can't find
 +  _frozen_importlib in sys.modules, not ImportError.
 +
 +- Issue #15030: importlib.abc.PyPycLoader now supports the new source size
 +  header field in .pyc files.
 +
 +- Issue #5346: Preserve permissions of mbox, MMDF and Babyl mailbox
 +  files on flush().
 +
 +- Issue #10571: Fix the "--sign" option of distutils' upload command.
 +  Patch by Jakub Wilk.
 +
 +- Issue #9559: If messages were only added, a new file is no longer
 +  created and renamed over the old file when flush() is called on an
 +  mbox, MMDF or Babyl mailbox.
 +
 +- Issue 10924: Fixed mksalt() to use a RNG that is suitable for cryptographic
 +  purpose.
 +
 +C API
 +-----
 +
 +- Issues #15169, #14599: Strip out the C implementation of
 +  imp.source_from_cache() used by PyImport_ExecCodeModuleWithPathnames() and
 +  used the Python code instead. Leads to PyImport_ExecCodeModuleObject() to not
 +  try to infer the source path from the bytecode path as
 +  PyImport_ExecCodeModuleWithPathnames() does.
 +
 +Extension Modules
 +-----------------
 +
 +- Issue #15194: Update libffi to the 3.0.11 release.
 +
 +Tools/Demos
 +-----------
 +
 +- Issue #12605: The gdb hooks for debugging CPython (within Tools/gdb) have
 +  been enhanced to show information on more C frames relevant to CPython within
 +  the "py-bt" and "py-bt-full" commands:
 +    * C frames that are waiting on the GIL
 +    * C frames that are garbage-collecting
 +    * C frames that are due to the invocation of a PyCFunction
 +
 +Documentation
 +-------------
 +
 +- Issue #15053: Copy Python 3.3 import lock change notice to all relevant
 +  functions in imp instead of just at the top of the relevant section.
 +
 +- Issue #15288: Link to the term "loader" in notes in pkgutil about how things
 +  won't work as expected in Python 3.3 and mark the requisite functions as
 +  "changed" since they will no longer work with modules directly imported by
 +  import itself.
 +
 +- Issue #13557: Clarify effect of giving two different namespaces to exec or
 +  execfile().
 +
 +Tests
 +-----
 +
++- Issue #15230: Adopted a more systematic approach in the runpy tests
++
 +- Issue #15300: Ensure the temporary test working directories are in the same
 +  parent folder when running tests in multiprocess mode from a Python build.
 +  Patch by Chris Jerdonek.
 +
 +- Issue #15284: Skip {send,recv}msg tests in test_socket when IPv6 is not
 +  enabled. Patch by Brian Brazil.
 +
 +- Issue #15277: Fix a resource leak in support.py when IPv6 is disabled.
 +  Patch by Brian Brazil.
 +
 +Build
 +-----
 +
 +- Issue #14330: For cross builds, don't use host python, use host search paths
 +  for host compiler.
 +
 +- Issue #15235: Allow Berkley DB versions up to 5.3 to build the dbm module.
 +
 +- Issue #15268: Search curses.h in /usr/include/ncursesw.
 +
 +
 +What's New in Python 3.3.0 Beta 1?
 +==================================
 +
 +*Release date: 27-Jun-2012*
 +
 +Core and Builtins
 +-----------------
 +
 +- Fix a (most likely) very rare memory leak when calling main() and not being
 +  able to decode a command-line argument.
 +
 +- Issue #14815: Use Py_ssize_t instead of long for the object hash, to
 +  preserve all 64 bits of hash on Win64.
 +
  - Issue #12268: File readline, readlines and read() or readall() methods
    no longer lose data when an underlying read system call is interrupted.
    IOError is no longer raised due to a read system call returning EINTR