[Python-checkins] cpython (merge default -> default): merge

barry.warsaw python-checkins at python.org
Tue Jul 31 22:10:35 CEST 2012


http://hg.python.org/cpython/rev/8c0745ffbef5
changeset:   78358:8c0745ffbef5
parent:      78357:1cf1df6f62f5
parent:      78349:28c935ded243
user:        Barry Warsaw <barry at python.org>
date:        Tue Jul 31 16:03:25 2012 -0400
summary:
  merge

files:
  Doc/distutils/uploading.rst   |     6 +-
  Doc/howto/ipaddress.rst       |     8 +-
  Doc/library/faulthandler.rst  |     2 +-
  Doc/library/functions.rst     |     3 +
  Doc/library/ipaddress.rst     |   248 +-
  Lib/idlelib/PyShell.py        |     4 +-
  Lib/importlib/_bootstrap.py   |    65 +-
  Lib/test/test_faulthandler.py |    15 +
  Lib/test/test_import.py       |    18 +-
  Misc/NEWS                     |     7 +
  Python/bltinmodule.c          |     5 +-
  Python/import.c               |    28 +-
  Python/importlib.h            |  7034 ++++++++++----------
  Python/pythonrun.c            |     8 +-
  14 files changed, 3749 insertions(+), 3702 deletions(-)


diff --git a/Doc/distutils/uploading.rst b/Doc/distutils/uploading.rst
--- a/Doc/distutils/uploading.rst
+++ b/Doc/distutils/uploading.rst
@@ -74,5 +74,7 @@
 
 :mod:`docutils` will display a warning if there's something wrong with your
 syntax.  Because PyPI applies additional checks (e.g. by passing ``--no-raw``
-to ``rst2html.py`` in the command above), running the command above without
-warnings is not sufficient for PyPI to convert the content successfully.
+to ``rst2html.py`` in the command above), being able to run the command above
+without warnings does not guarantee that PyPI will convert the content
+successfully.
+
diff --git a/Doc/howto/ipaddress.rst b/Doc/howto/ipaddress.rst
--- a/Doc/howto/ipaddress.rst
+++ b/Doc/howto/ipaddress.rst
@@ -19,7 +19,7 @@
 Creating Address/Network/Interface objects
 ==========================================
 
-Since :mod:`ipaddress` is a module for inspecting and manipulating IP address,
+Since :mod:`ipaddress` is a module for inspecting and manipulating IP addresses,
 the first thing you'll want to do is create some objects.  You can use
 :mod:`ipaddress` to create objects from strings and integers.
 
@@ -183,10 +183,10 @@
    >>> net6.numhosts
    4294967296
 
-Iterating through the 'usable' addresses on a network::
+Iterating through the "usable" addresses on a network::
 
    >>> net4 = ipaddress.ip_network('192.0.2.0/24')
-   >>> for x in net4.iterhosts():
+   >>> for x in net4.hosts():
           print(x)
    192.0.2.1
    192.0.2.2
@@ -294,7 +294,7 @@
 When creating address/network/interface objects using the version-agnostic
 factory functions, any errors will be reported as :exc:`ValueError` with
 a generic error message that simply says the passed in value was not
-recognised as an object of that type. The lack of a specific error is
+recognized as an object of that type. The lack of a specific error is
 because it's necessary to know whether the value is *supposed* to be IPv4
 or IPv6 in order to provide more detail on why it has been rejected.
 
diff --git a/Doc/library/faulthandler.rst b/Doc/library/faulthandler.rst
--- a/Doc/library/faulthandler.rst
+++ b/Doc/library/faulthandler.rst
@@ -23,7 +23,7 @@
 
 * Only ASCII is supported. The ``backslashreplace`` error handler is used on
   encoding.
-* Each string is limited to 100 characters.
+* Each string is limited to 500 characters.
 * Only the filename, the function name and the line number are
   displayed. (no source code)
 * It is limited to 100 frames and 100 threads.
diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -1506,6 +1506,9 @@
    If you simply want to import a module (potentially within a package) by name,
    use :func:`importlib.import_module`.
 
+   .. versionchanged:: 3.3
+      Negative values for *level* are no longer supported.
+
 
 .. rubric:: Footnotes
 
diff --git a/Doc/library/ipaddress.rst b/Doc/library/ipaddress.rst
--- a/Doc/library/ipaddress.rst
+++ b/Doc/library/ipaddress.rst
@@ -22,19 +22,18 @@
 IP address or network definition.
 
 
-Defining IP Addresses and Interfaces
-------------------------------------
+Convenience factory functions
+-----------------------------
 
-The :mod:`ipaddress` module provides factory functions to define IP addresses
-and networks:
+The :mod:`ipaddress` module provides factory functions to conveniently create
+IP addresses, networks and interfaces:
 
 .. function:: ip_address(address)
 
    Return an :class:`IPv4Address` or :class:`IPv6Address` object depending on
-   the IP address passed as argument.  *address* is a string or integer
-   representing the IP address.  Either IPv4 or IPv6 addresses may be supplied;
-   integers less than 2**32 will be considered to be IPv4 by default.  A
-   :exc:`ValueError` is raised if the *address* passed is neither an IPv4 nor
+   the IP address passed as argument.  Either IPv4 or IPv6 addresses may be
+   supplied; integers less than 2**32 will be considered to be IPv4 by default.
+   A :exc:`ValueError` is raised if *address* does not represent a valid IPv4 or
    IPv6 address.
 
    >>> ipaddress.ip_address('192.168.0.1')
@@ -50,8 +49,8 @@
    representing the IP network.  Either IPv4 or IPv6 networks may be supplied;
    integers less than 2**32 will be considered to be IPv4 by default.  *strict*
    is passed to :class:`IPv4Network` or :class:`IPv6Network` constructor.  A
-   :exc:`ValueError` is raised if the string passed isn't either an IPv4 or IPv6
-   address, or if the network has host bits set.
+   :exc:`ValueError` is raised if *address* does not represent a valid IPv4 or
+   IPv6 address, or if the network has host bits set.
 
    >>> ipaddress.ip_network('192.168.0.0/28')
    IPv4Network('192.168.0.0/28')
@@ -62,45 +61,174 @@
    Return an :class:`IPv4Interface` or :class:`IPv6Interface` object depending
    on the IP address passed as argument.  *address* is a string or integer
    representing the IP address.  Either IPv4 or IPv6 addresses may be supplied;
-   integers less than 2**32 will be considered to be IPv4 by default..  A
-   :exc:`ValueError` is raised if the *address* passed isn't either an IPv4 or
+   integers less than 2**32 will be considered to be IPv4 by default.  A
+   :exc:`ValueError` is raised if *address* does not represent a valid IPv4 or
    IPv6 address.
 
 
-Representing IP Addresses and Networks
---------------------------------------
+Address objects
+---------------
 
-The module defines the following and classes to represent IP addresses
-and networks:
-
-.. todo: list the properties and methods
+The :class:`IPv4Address` and :class:`IPv6Address` objects share a lot of common
+attributes.  Some attributes that are only meaningful for IPv6 addresses are
+also implemented by :class:`IPv4Address` objects, in order to make it easier to
+write code that handles both IP versions correctly.  To avoid duplication, all
+common attributes will only be documented for :class:`IPv4Address`.
 
 .. class:: IPv4Address(address)
 
-   Construct an IPv4 address.  *address* is a string or integer representing the
-   IP address.  An :exc:`AddressValueError` is raised if *address* is not a
-   valid IPv4 address.
+   Construct an IPv4 address.  An :exc:`AddressValueError` is raised if
+   *address* is not a valid IPv4 address.
+
+   The following constitutes a valid IPv4 address:
+
+   1. A string in decimal-dot notation, consisting of four decimal integers in
+      the inclusive range 0-255, separated by dots (e.g. ``192.168.0.1``). Each
+      integer represents an octet (byte) in the address, big-endian.
+   2. An integer that fits into 32 bits.
+   3. An integer packed into a :class:`bytes` object of length 4, big-endian.
 
    >>> ipaddress.IPv4Address('192.168.0.1')
    IPv4Address('192.168.0.1')
    >>> ipaddress.IPv4Address('192.0.2.1') == ipaddress.IPv4Address(3221225985)
    True
 
+   .. attribute:: exploded
 
-.. class:: IPv4Interface(address)
+   The longhand version of the address as a string. Note: the
+   exploded/compressed distinction is meaningful only for IPv6 addresses.
+   For IPv4 addresses it is the same.
 
-   Construct an IPv4 interface.  *address* is a string or integer representing
-   the IP interface.  An :exc:`AddressValueError` is raised if *address* is not
-   a valid IPv4 address.
+   .. attribute:: compressed
 
-   The network address for the interface is determined by calling
-   ``IPv4Network(address, strict=False)``.
+   The shorthand version of the address as a string.
 
-   >>> ipaddress.IPv4Interface('192.168.0.0/24')
-   IPv4Interface('192.168.0.0/24')
-   >>> ipaddress.IPv4Interface('192.168.0.0/24').network
-   IPv4Network('192.168.0.0/24')
+   .. attribute:: packed
 
+   The binary representation of this address - a :class:`bytes` object.
+
+   .. attribute:: version
+
+   A numeric version number.
+
+   .. attribute:: max_prefixlen
+
+   Maximal length of the prefix (in bits).  The prefix defines the number of
+   leading bits in an address that are compared to determine whether or not an
+   address is part of a network.
+
+   .. attribute:: is_multicast
+
+   ``True`` if the address is reserved for multicast use.  See :RFC:`3171` (for
+   IPv4) or :RFC:`2373` (for IPv6).
+
+   .. attribute:: is_private
+
+   ``True`` if the address is allocated for private networks.  See :RFC:`1918`
+   (for IPv4) or :RFC:`4193` (for IPv6).
+
+   .. attribute:: is_unspecified
+
+   ``True`` if the address is unspecified.  See :RFC:`5375` (for IPv4) or
+   :RFC:`2373` (for IPv6).
+
+   .. attribute:: is_reserved
+
+   ``True`` if the address is otherwise IETF reserved.
+
+   .. attribute:: is_loopback
+
+   ``True`` if this is a loopback address.  See :RFC:`3330` (for IPv4) or
+   :RFC:`2373` (for IPv6).
+
+   .. attribute:: is_link_local
+
+   ``True`` if the address is reserved for link-local.  See :RFC:`3927`.
+
+.. class:: IPv6Address(address)
+
+   Construct an IPv6 address.  An :exc:`AddressValueError` is raised if
+   *address* is not a valid IPv6 address.
+
+   The following constitutes a valid IPv6 address:
+
+   1. A string consisting of eight groups of four hexadecimal digits, each
+      group representing 16 bits.  The groups are separated by colons.
+      This describes an *exploded* (longhand) notation.  The string can
+      also be *compressed* (shorthand notation) by various means.  See
+      :RFC:`4291` for details.  For example,
+      ``"0000:0000:0000:0000:0000:0abc:0007:0def"`` can be compressed to
+      ``"::abc:7:def"``.
+   2. An integer that fits into 128 bits.
+   3. An integer packed into a :class:`bytes` object of length 16, big-endian.
+
+   >>> ipaddress.IPv6Address('2001:db8::1000')
+   IPv6Address('2001:db8::1000')
+
+   All the attributes exposed by :class:`IPv4Address` are supported.  In
+   addition, the following attributs are exposed only by :class:`IPv6Address`.
+
+   .. attribute:: is_site_local
+
+   ``True`` if the address is reserved for site-local.  Note that the site-local
+   address space has been deprecated by :RFC:`3879`.  Use
+   :attr:`~IPv4Address.is_private` to test if this address is in the space of
+   unique local addresses as defined by :RFC:`4193`.
+
+   .. attribute:: ipv4_mapped
+
+   If this address represents a IPv4 mapped address, return the IPv4 mapped
+   address.  Otherwise return ``None``.
+
+   .. attribute:: teredo
+
+   If this address appears to be a teredo address (starts with ``2001::/32``),
+   return a tuple of embedded teredo IPs ``(server, client)`` pairs.  Otherwise
+   return ``None``.
+
+   .. attribute:: sixtofour
+
+   If this address appears to contain a 6to4 embedded address, return the
+   embedded IPv4 address.  Otherwise return ``None``.
+
+
+Operators
+^^^^^^^^^
+
+Address objects support some operators.  Unless stated otherwise, operators can
+only be applied between compatible objects (i.e. IPv4 with IPv4, IPv6 with
+IPv6).
+
+Logical operators
+"""""""""""""""""
+
+Address objects can be compared with the usual set of logical operators.  Some
+examples::
+
+   >>> IPv4Address('127.0.0.2') > IPv4Address('127.0.0.1')
+   True
+   >>> IPv4Address('127.0.0.2') == IPv4Address('127.0.0.1')
+   False
+   >>> IPv4Address('127.0.0.2') != IPv4Address('127.0.0.1')
+   True
+
+Arithmetic operators
+""""""""""""""""""""
+
+Integers can be added to or subtracted from address objects.  Some examples::
+
+   >>> IPv4Address('127.0.0.2') + 3
+   IPv4Address('127.0.0.5')
+   >>> IPv4Address('127.0.0.2') - 3
+   IPv4Address('126.255.255.255')
+   >>> IPv4Address('255.255.255.255') + 1
+   Traceback (most recent call last):
+     File "<stdin>", line 1, in <module>
+   ipaddress.AddressValueError: 4294967296 (>= 2**32) is not permitted as an IPv4 address
+
+
+Network objects
+---------------
 
 .. class:: IPv4Network(address, strict=True)
 
@@ -121,31 +249,6 @@
    IPv4Network('192.0.2.0/27')
 
 
-.. class:: IPv6Address(address)
-
-   Construct an IPv6 address.  *address* is a string or integer representing the
-   IP address.  An :exc:`AddressValueError` is raised if *address* is not a
-   valid IPv6 address.
-
-   >>> ipaddress.IPv6Address('2001:db8::1000')
-   IPv6Address('2001:db8::1000')
-
-
-.. class:: IPv6Interface(address)
-
-   Construct an IPv6 interface.  *address* is a string or integer representing
-   the IP interface.  An :exc:`AddressValueError` is raised if *address* is not
-   a valid IPv6 address.
-
-   The network address for the interface is determined by calling
-   ``IPv6Network(address, strict=False)``.
-
-   >>> ipaddress.IPv6Interface('2001:db8::1000/96')
-   IPv6Interface('2001:db8::1000/96')
-   >>> ipaddress.IPv6Interface('2001:db8::1000/96').network
-   IPv6Network('2001:db8::/96')
-
-
 .. class:: IPv6Network(address, strict=True)
 
    Construct an IPv6 network.  *address* is a string or integer representing the
@@ -165,6 +268,39 @@
    IPv6Network('2001:db8::/96')
 
 
+Interface objects
+-----------------
+
+.. class:: IPv4Interface(address)
+
+   Construct an IPv4 interface.  *address* is a string or integer representing
+   the IP interface.  An :exc:`AddressValueError` is raised if *address* is not
+   a valid IPv4 address.
+
+   The network address for the interface is determined by calling
+   ``IPv4Network(address, strict=False)``.
+
+   >>> ipaddress.IPv4Interface('192.168.0.0/24')
+   IPv4Interface('192.168.0.0/24')
+   >>> ipaddress.IPv4Interface('192.168.0.0/24').network
+   IPv4Network('192.168.0.0/24')
+
+
+.. class:: IPv6Interface(address)
+
+   Construct an IPv6 interface.  *address* is a string or integer representing
+   the IP interface.  An :exc:`AddressValueError` is raised if *address* is not
+   a valid IPv6 address.
+
+   The network address for the interface is determined by calling
+   ``IPv6Network(address, strict=False)``.
+
+   >>> ipaddress.IPv6Interface('2001:db8::1000/96')
+   IPv6Interface('2001:db8::1000/96')
+   >>> ipaddress.IPv6Interface('2001:db8::1000/96').network
+   IPv6Network('2001:db8::/96')
+
+
 Other Module Level Functions
 ----------------------------
 
diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py
--- a/Lib/idlelib/PyShell.py
+++ b/Lib/idlelib/PyShell.py
@@ -248,8 +248,8 @@
     def ranges_to_linenumbers(self, ranges):
         lines = []
         for index in range(0, len(ranges), 2):
-            lineno = int(float(ranges[index]))
-            end = int(float(ranges[index+1]))
+            lineno = int(float(ranges[index].string))
+            end = int(float(ranges[index+1].string))
             while lineno < end:
                 lines.append(lineno)
                 lineno += 1
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py
--- a/Lib/importlib/_bootstrap.py
+++ b/Lib/importlib/_bootstrap.py
@@ -297,8 +297,20 @@
     else:
         lock.release()
 
+# Frame stripping magic ###############################################
 
-# Finder/loader utility code ##################################################
+def _call_with_frames_removed(f, *args, **kwds):
+    """remove_importlib_frames in import.c will always remove sequences
+    of importlib frames that end with a call to this function
+
+    Use it instead of a normal call in places where including the importlib
+    frames introduces unwanted noise into the traceback (e.g. when executing
+    module code)
+    """
+    return f(*args, **kwds)
+
+
+# Finder/loader utility code ###############################################
 
 """Magic word to reject .pyc files generated by other Python versions.
 It should change for each incompatible change to the bytecode.
@@ -629,20 +641,13 @@
         """Load a built-in module."""
         is_reload = fullname in sys.modules
         try:
-            return cls._exec_module(fullname)
+            return _call_with_frames_removed(_imp.init_builtin, fullname)
         except:
             if not is_reload and fullname in sys.modules:
                 del sys.modules[fullname]
             raise
 
     @classmethod
-    def _exec_module(cls, fullname):
-        """Helper for load_module, allowing to isolate easily (when
-        looking at a traceback) whether an error comes from executing
-        an imported module's code."""
-        return _imp.init_builtin(fullname)
-
-    @classmethod
     @_requires_builtin
     def get_code(cls, fullname):
         """Return None as built-in modules do not have code objects."""
@@ -687,7 +692,7 @@
         """Load a frozen module."""
         is_reload = fullname in sys.modules
         try:
-            m = cls._exec_module(fullname)
+            m = _call_with_frames_removed(_imp.init_frozen, fullname)
             # Let our own module_repr() method produce a suitable repr.
             del m.__file__
             return m
@@ -714,13 +719,6 @@
         """Return if the frozen module is a package."""
         return _imp.is_frozen_package(fullname)
 
-    @classmethod
-    def _exec_module(cls, fullname):
-        """Helper for load_module, allowing to isolate easily (when
-        looking at a traceback) whether an error comes from executing
-        an imported module's code."""
-        return _imp.init_frozen(fullname)
-
 
 class WindowsRegistryImporter:
 
@@ -850,15 +848,9 @@
         else:
             module.__package__ = module.__package__.rpartition('.')[0]
         module.__loader__ = self
-        self._exec_module(code_object, module.__dict__)
+        _call_with_frames_removed(exec, code_object, module.__dict__)
         return module
 
-    def _exec_module(self, code_object, module_dict):
-        """Helper for _load_module, allowing to isolate easily (when
-        looking at a traceback) whether an error comes from executing
-        an imported module's code."""
-        exec(code_object, module_dict)
-
 
 class SourceLoader(_LoaderBasics):
 
@@ -956,8 +948,9 @@
                             raise ImportError(msg.format(bytecode_path),
                                               name=fullname, path=bytecode_path)
         source_bytes = self.get_data(source_path)
-        code_object = compile(source_bytes, source_path, 'exec',
-                                dont_inherit=True)
+        code_object = _call_with_frames_removed(compile,
+                          source_bytes, source_path, 'exec',
+                          dont_inherit=True)
         _verbose_message('code object from {}', source_path)
         if (not sys.dont_write_bytecode and bytecode_path is not None and
             source_mtime is not None):
@@ -1093,7 +1086,8 @@
         """Load an extension module."""
         is_reload = fullname in sys.modules
         try:
-            module = self._exec_module(fullname, self.path)
+            module = _call_with_frames_removed(_imp.load_dynamic,
+                                               fullname, self.path)
             _verbose_message('extension module loaded from {!r}', self.path)
             return module
         except:
@@ -1113,12 +1107,6 @@
         """Return None as extension modules have no source code."""
         return None
 
-    def _exec_module(self, fullname, path):
-        """Helper for load_module, allowing to isolate easily (when
-        looking at a traceback) whether an error comes from executing
-        an imported module's code."""
-        return _imp.load_dynamic(fullname, path)
-
 
 class _NamespacePath:
     """Represents a namespace package's path.  It uses the module name
@@ -1472,7 +1460,7 @@
     parent = name.rpartition('.')[0]
     if parent:
         if parent not in sys.modules:
-            _recursive_import(import_, parent)
+            _call_with_frames_removed(import_, parent)
         # Crazy side-effects!
         if name in sys.modules:
             return sys.modules[name]
@@ -1550,13 +1538,6 @@
     _lock_unlock_module(name)
     return module
 
-def _recursive_import(import_, name):
-    """Common exit point for recursive calls to the import machinery
-
-    This simplifies the process of stripping importlib from tracebacks
-    """
-    return import_(name)
-
 def _handle_fromlist(module, fromlist, import_):
     """Figure out what __import__ should return.
 
@@ -1575,7 +1556,7 @@
                 fromlist.extend(module.__all__)
         for x in fromlist:
             if not hasattr(module, x):
-                _recursive_import(import_,
+                _call_with_frames_removed(import_,
                                   '{}.{}'.format(module.__name__, x))
     return module
 
diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py
--- a/Lib/test/test_faulthandler.py
+++ b/Lib/test/test_faulthandler.py
@@ -7,6 +7,7 @@
 import subprocess
 import sys
 from test import support, script_helper
+from test.script_helper import assert_python_ok
 import tempfile
 import unittest
 
@@ -256,6 +257,20 @@
         finally:
             sys.stderr = orig_stderr
 
+    def test_disabled_by_default(self):
+        # By default, the module should be disabled
+        code = "import faulthandler; print(faulthandler.is_enabled())"
+        rc, stdout, stderr = assert_python_ok("-c", code)
+        stdout = (stdout + stderr).strip()
+        self.assertEqual(stdout, b"False")
+
+    def test_sys_xoptions(self):
+        # Test python -X faulthandler
+        code = "import faulthandler; print(faulthandler.is_enabled())"
+        rc, stdout, stderr = assert_python_ok("-X", "faulthandler", "-c", code)
+        stdout = (stdout + stderr).strip()
+        self.assertEqual(stdout, b"True")
+
     def check_dump_traceback(self, filename):
         """
         Explicitly call dump_traceback() function and check its output.
diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py
--- a/Lib/test/test_import.py
+++ b/Lib/test/test_import.py
@@ -785,11 +785,13 @@
         sys.path[:] = self.old_path
         rmtree(TESTFN)
 
-    def create_module(self, mod, contents):
-        with open(os.path.join(TESTFN, mod + ".py"), "w") as f:
+    def create_module(self, mod, contents, ext=".py"):
+        fname = os.path.join(TESTFN, mod + ext)
+        with open(fname, "w") as f:
             f.write(contents)
         self.addCleanup(unload, mod)
         importlib.invalidate_caches()
+        return fname
 
     def assert_traceback(self, tb, files):
         deduped_files = []
@@ -857,16 +859,14 @@
 
     def _setup_broken_package(self, parent, child):
         pkg_name = "_parent_foo"
-        def cleanup():
-            rmtree(pkg_name)
-            unload(pkg_name)
-        os.mkdir(pkg_name)
-        self.addCleanup(cleanup)
+        self.addCleanup(unload, pkg_name)
+        pkg_path = os.path.join(TESTFN, pkg_name)
+        os.mkdir(pkg_path)
         # Touch the __init__.py
-        init_path = os.path.join(pkg_name, '__init__.py')
+        init_path = os.path.join(pkg_path, '__init__.py')
         with open(init_path, 'w') as f:
             f.write(parent)
-        bar_path = os.path.join(pkg_name, 'bar.py')
+        bar_path = os.path.join(pkg_path, 'bar.py')
         with open(bar_path, 'w') as f:
             f.write(child)
         importlib.invalidate_caches()
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,10 @@
 Core and Builtins
 -----------------
 
+- Issue #15508: Fix the docstring for __import__ to have the proper default
+  value of 0 for 'level' and to not mention negative levels since they are
+  not supported.
+
 - Issue #15425: Eliminated traceback noise from more situations involving
   importlib
 
@@ -342,6 +346,9 @@
 Library
 -------
 
+- Issue #9803: Don't close IDLE on saving if breakpoint is open.
+  Patch by Roger Serwy.
+
 - Issue #12288: Consider '0' and '0.0' as valid initialvalue
   for tkinter SimpleDialog.
 
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -195,7 +195,7 @@
 }
 
 PyDoc_STRVAR(import_doc,
-"__import__(name, globals={}, locals={}, fromlist=[], level=-1) -> module\n\
+"__import__(name, globals={}, locals={}, fromlist=[], level=0) -> module\n\
 \n\
 Import a module. Because this function is meant for use by the Python\n\
 interpreter and not for general use it is better to use\n\
@@ -208,8 +208,7 @@
 When importing a module from a package, note that __import__('A.B', ...)\n\
 returns package A when fromlist is empty, but its submodule B when\n\
 fromlist is not empty.  Level is used to determine whether to perform \n\
-absolute or relative imports.  -1 is the original strategy of attempting\n\
-both absolute and relative imports, 0 is absolute, a positive number\n\
+absolute or relative imports. 0 is absolute while a positive number\n\
 is the number of parent directories to search relative to the current module.");
 
 
diff --git a/Python/import.c b/Python/import.c
--- a/Python/import.c
+++ b/Python/import.c
@@ -1153,9 +1153,7 @@
 remove_importlib_frames(void)
 {
     const char *importlib_filename = "<frozen importlib._bootstrap>";
-    const char *exec_funcname = "_exec_module";
-    const char *get_code_funcname = "get_code";
-    const char *recursive_import = "_recursive_import";
+    const char *remove_frames = "_call_with_frames_removed";
     int always_trim = 0;
     int trim_get_code = 0;
     int in_importlib = 0;
@@ -1163,18 +1161,8 @@
     PyObject **prev_link, **outer_link = NULL;
 
     /* Synopsis: if it's an ImportError, we trim all importlib chunks
-       from the traceback.  If it's a SyntaxError, we trim any chunks that
-       end with a call to "get_code", We always trim chunks
-       which end with a call to "_exec_module". */
-
-    /* Thanks to issue 15425, we also strip any chunk ending with
-     * _recursive_import. This is used when making a recursive call to the
-     * full import machinery which means the inner stack gets stripped early
-     * and the normal heuristics won't fire properly for outer frames. A
-     * more elegant mechanism would be nice, as this one can misfire if
-     * builtins.__import__ has been replaced with a custom implementation.
-     * However, the current approach at least gets the job done.
-     */
+       from the traceback. We always trim chunks
+       which end with a call to "_call_with_frames_removed". */
 
     PyErr_Fetch(&exception, &value, &base_tb);
     if (!exception || Py_VerboseFlag)
@@ -1207,14 +1195,8 @@
 
         if (in_importlib &&
             (always_trim ||
-             (PyUnicode_CompareWithASCIIString(code->co_name,
-                                              exec_funcname) == 0) ||
-             (PyUnicode_CompareWithASCIIString(code->co_name,
-                                              recursive_import) == 0) ||
-             (trim_get_code &&
-              PyUnicode_CompareWithASCIIString(code->co_name,
-                                              get_code_funcname) == 0)
-           )) {
+             PyUnicode_CompareWithASCIIString(code->co_name,
+                                              remove_frames) == 0)) {
             PyObject *tmp = *outer_link;
             *outer_link = next;
             Py_XINCREF(next);
diff --git a/Python/importlib.h b/Python/importlib.h
--- a/Python/importlib.h
+++ b/Python/importlib.h
[stripped]
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -356,10 +356,6 @@
 
     _PyImportHooks_Init();
 
-    /* initialize the faulthandler module */
-    if (_PyFaulthandler_Init())
-        Py_FatalError("Py_Initialize: can't initialize faulthandler");
-
     /* Initialize _warnings. */
     _PyWarnings_Init();
 
@@ -368,6 +364,10 @@
 
     import_init(interp, sysmod);
 
+    /* initialize the faulthandler module */
+    if (_PyFaulthandler_Init())
+        Py_FatalError("Py_Initialize: can't initialize faulthandler");
+
     _PyTime_Init();
 
     if (initfsencoding(interp) < 0)

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list