merge
This commit is contained in:
commit
9a5af1288d
|
@ -74,5 +74,7 @@ check the ``long_description`` from the command line::
|
|||
|
||||
: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.
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ An Introduction to the ipaddress module
|
|||
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 @@ Finding out how many individual addresses are in a network::
|
|||
>>> 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 @@ Getting more detail when instance creation fails
|
|||
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.
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ tracebacks:
|
|||
|
||||
* 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.
|
||||
|
|
|
@ -1506,6 +1506,9 @@ are always available. They are listed here in alphabetical order.
|
|||
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
|
||||
|
||||
|
|
|
@ -22,19 +22,18 @@ subnet, as well as checking whether or not a string represents a valid
|
|||
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 @@ and networks:
|
|||
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 @@ and networks:
|
|||
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 @@ and networks:
|
|||
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 @@ and networks:
|
|||
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
|
||||
----------------------------
|
||||
|
||||
|
|
|
@ -248,8 +248,8 @@ class PyShellEditorWindow(EditorWindow):
|
|||
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
|
||||
|
|
|
@ -297,8 +297,20 @@ def _lock_unlock_module(name):
|
|||
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,19 +641,12 @@ class BuiltinImporter:
|
|||
"""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):
|
||||
|
@ -687,7 +692,7 @@ class FrozenImporter:
|
|||
"""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 @@ class FrozenImporter:
|
|||
"""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 @@ class _LoaderBasics:
|
|||
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 @@ class SourceLoader(_LoaderBasics):
|
|||
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 @@ class ExtensionFileLoader:
|
|||
"""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 @@ class ExtensionFileLoader:
|
|||
"""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 @@ def _find_and_load_unlocked(name, import_):
|
|||
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 @@ def _gcd_import(name, package=None, level=0):
|
|||
_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 @@ def _handle_fromlist(module, fromlist, import_):
|
|||
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
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import signal
|
|||
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 @@ faulthandler._read_null()
|
|||
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.
|
||||
|
|
|
@ -785,11 +785,13 @@ class ImportTracebackTests(unittest.TestCase):
|
|||
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 @@ class ImportTracebackTests(unittest.TestCase):
|
|||
|
||||
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()
|
||||
|
|
|
@ -10,6 +10,10 @@ What's New in Python 3.3.0 Beta 2?
|
|||
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 @@ Core and Builtins
|
|||
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.
|
||||
|
||||
|
|
|
@ -195,7 +195,7 @@ builtin___import__(PyObject *self, PyObject *args, PyObject *kwds)
|
|||
}
|
||||
|
||||
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 @@ empty list to emulate ``import name''.\n\
|
|||
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.");
|
||||
|
||||
|
||||
|
|
|
@ -1153,9 +1153,7 @@ static void
|
|||
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 @@ remove_importlib_frames(void)
|
|||
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 @@ remove_importlib_frames(void)
|
|||
|
||||
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);
|
||||
|
|
7020
Python/importlib.h
7020
Python/importlib.h
File diff suppressed because it is too large
Load Diff
|
@ -356,10 +356,6 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib)
|
|||
|
||||
_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 @@ _Py_InitializeEx_Private(int install_sigs, int install_importlib)
|
|||
|
||||
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)
|
||||
|
|
Loading…
Reference in New Issue