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"""\
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
- 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