[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