Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
5380589
Add test for explicit `cls` argument bypassing default JSON decoder (…
GovernmentPlates Jul 19, 2026
84897d2
gh-153903: Use `@ctypes.util.wrap_dll_function()` with pythonapi (#15…
vstinner Jul 19, 2026
ee50ed3
gh-104533: Use `@ctypes.util.struct` decorator (#154031)
vstinner Jul 19, 2026
104c397
gh-154055: Gate optional curses functions absent on old SVr4 curses (…
serhiy-storchaka Jul 19, 2026
b8ec956
urllib: Add tests for HTTP errors to complete coverage (#154102)
AjobK Jul 19, 2026
1530b38
gh-151949: Fix Sphinx reference warnings in `Doc/library/lzma.rst` (G…
fedonman Jul 19, 2026
ee1e48e
improve json test coverage (GH-154123)
dslavicek Jul 19, 2026
ec1057e
gh-152433: Windows: ``_uuid`` module: improve UWP compatibility (#152…
thexai Jul 19, 2026
1604043
gh-153932: protect read of en_index during enumerate.reduce (GH-154118)
lelynn Jul 19, 2026
69d44f8
gh-153906: Show 'Data' in code formatting (#154132)
hugovk Jul 19, 2026
8d11eb0
gh-154144: Fix false positive from the stdbool.h guard in _testcapimo…
serhiy-storchaka Jul 19, 2026
249d5e0
gh-153903: Use `@ctypes.util.wrap_dll_function()` (#154122)
vstinner Jul 19, 2026
eb44708
gh-139806: Mention pickle error changes in What's New in 3.14 (GH-154…
serhiy-storchaka Jul 19, 2026
5625b18
gh-62534: Document that three-argument type() does not call __prepare…
soreavis Jul 19, 2026
f252132
gh-119710: fix asyncio Process.wait() to finish on process exit and n…
tapetersen Jul 19, 2026
da5713c
gh-104533: Fix ctypes test_pointer_proto_missing_argtypes_error() (#1…
vstinner Jul 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Doc/library/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2179,6 +2179,11 @@ are always available. They are listed here in alphabetical order.
in the same way that keywords in a class
definition (besides *metaclass*) would.

Unlike a :keyword:`class` statement, the three argument form does not
call the metaclass ``__prepare__`` method (see :ref:`prepare`). Use
:func:`types.new_class` to dynamically create a class using the
appropriate metaclass.

See also :ref:`class-customization`.

.. versionchanged:: 3.6
Expand Down
131 changes: 105 additions & 26 deletions Doc/library/lzma.rst
Original file line number Diff line number Diff line change
Expand Up @@ -152,35 +152,14 @@ Compressing and decompressing data in memory
:func:`compress`.

The *format* argument specifies what container format should be used.
Possible values are:

* :const:`FORMAT_XZ`: The ``.xz`` container format.
This is the default format.

* :const:`FORMAT_ALONE`: The legacy ``.lzma`` container format.
This format is more limited than ``.xz`` -- it does not support integrity
checks or multiple filters.

* :const:`FORMAT_RAW`: A raw data stream, not using any container format.
This format specifier does not support integrity checks, and requires that
you always specify a custom filter chain (for both compression and
decompression). Additionally, data compressed in this manner cannot be
decompressed using :const:`FORMAT_AUTO` (see :class:`LZMADecompressor`).
Possible values are :const:`FORMAT_XZ` (the default),
:const:`FORMAT_ALONE` and :const:`FORMAT_RAW`.

The *check* argument specifies the type of integrity check to include in the
compressed data. This check is used when decompressing, to ensure that the
data has not been corrupted. Possible values are:

* :const:`CHECK_NONE`: No integrity check.
This is the default (and the only acceptable value) for
:const:`FORMAT_ALONE` and :const:`FORMAT_RAW`.

* :const:`CHECK_CRC32`: 32-bit Cyclic Redundancy Check.

* :const:`CHECK_CRC64`: 64-bit Cyclic Redundancy Check.
This is the default for :const:`FORMAT_XZ`.

* :const:`CHECK_SHA256`: 256-bit Secure Hash Algorithm.
data has not been corrupted. Possible values are :const:`CHECK_NONE`,
:const:`CHECK_CRC32`, :const:`CHECK_CRC64` (the default for
:const:`FORMAT_XZ`) and :const:`CHECK_SHA256`.

If the specified check is not supported, an :class:`LZMAError` is raised.

Expand Down Expand Up @@ -412,6 +391,106 @@ These filters support one option, ``start_offset``. This specifies the address
that should be mapped to the beginning of the input data. The default is 0.


Constants
---------

The following module-level constants are provided for use as the *format*,
*check*, *preset* and *filters* arguments of the classes and functions above.

Container formats:

.. data:: FORMAT_XZ

The ``.xz`` container format.

.. data:: FORMAT_ALONE

The legacy ``.lzma`` container format. This format is more limited than
``.xz`` -- it does not support integrity checks or multiple filters.

.. data:: FORMAT_RAW

A raw data stream, not using any container format. This format specifier
does not support integrity checks, and requires that you always specify a
custom filter chain (for both compression and decompression). Additionally,
data compressed in this manner cannot be decompressed using
:const:`FORMAT_AUTO`.

.. data:: FORMAT_AUTO

Used for decompression only. The container format is detected
automatically, so that both ``.xz`` and ``.lzma`` files can be decompressed.

Integrity checks:

.. data:: CHECK_NONE

No integrity check. This is the default (and the only acceptable value) for
:const:`FORMAT_ALONE` and :const:`FORMAT_RAW`.

.. data:: CHECK_CRC32

A 32-bit Cyclic Redundancy Check.

.. data:: CHECK_CRC64

A 64-bit Cyclic Redundancy Check. This is the default for
:const:`FORMAT_XZ`.

.. data:: CHECK_SHA256

A 256-bit Secure Hash Algorithm.

.. data:: CHECK_UNKNOWN

The integrity check used by a stream could not yet be determined. This may
be the value of the :attr:`LZMADecompressor.check` attribute until enough of
the input has been decoded.

.. data:: CHECK_ID_MAX

The largest supported integrity-check ID.

Compression presets:

.. data:: PRESET_DEFAULT

The default compression preset, equivalent to preset level ``6``.

.. data:: PRESET_EXTREME

A flag that may be bitwise OR-ed with a preset level (``0`` to ``9``) to
select a slower but more thorough variant of that preset.

Filter IDs and options:

.. data:: FILTER_LZMA1
FILTER_LZMA2

The LZMA1 and LZMA2 compression filters. :const:`FILTER_LZMA1` is for use
with :const:`FORMAT_ALONE`, while :const:`FILTER_LZMA2` is for use with
:const:`FORMAT_XZ` and :const:`FORMAT_RAW`.

.. data:: FILTER_DELTA

The delta filter.

.. data:: MODE_FAST
MODE_NORMAL

Compression modes that may be used as the ``mode`` option of a filter
specifier (see :ref:`filter-chain-specs`).

.. data:: MF_HC3
MF_HC4
MF_BT2
MF_BT3
MF_BT4

Match finders that may be used as the ``mf`` option of a filter specifier
(see :ref:`filter-chain-specs`).


Examples
--------

Expand Down
1 change: 0 additions & 1 deletion Doc/tools/.nitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ Doc/library/email.parser.rst
Doc/library/importlib.rst
Doc/library/logging.config.rst
Doc/library/logging.handlers.rst
Doc/library/lzma.rst
Doc/library/mmap.rst
Doc/library/multiprocessing.rst
Doc/library/optparse.rst
Expand Down
10 changes: 10 additions & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3312,6 +3312,16 @@ Changes in the Python API
This temporary change affects other threads.
(Contributed by Serhiy Storchaka in :gh:`69998`.)

* :func:`pickle.dump` and :func:`pickle.dumps` now raise
:exc:`~pickle.PicklingError` for some failures that previously raised
:exc:`AttributeError`, :exc:`ImportError`, :exc:`ValueError`,
:exc:`UnicodeEncodeError` or :exc:`!PicklingError`,
depending on the implementation
(for example, pickling a local object, or an object whose module cannot be imported).
The original exception is chained to the :exc:`!PicklingError`.
Code that caught these exceptions should also catch :exc:`!PicklingError`.
(Contributed by Serhiy Storchaka in :gh:`122311`.)

* :class:`types.UnionType` is now an alias for :class:`typing.Union`,
causing changes in some behaviors.
See :ref:`above <whatsnew314-typing-union>` for more details.
Expand Down
9 changes: 9 additions & 0 deletions Include/py_curses.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@
# define PDC_NCMOUSE
#endif

/* On Solaris/illumos, the SVr4 <curses.h> does "typedef char bool;", which
clashes with C's bool from <stdbool.h>. Define _BOOL to suppress it, and
include <stdbool.h> for the bool the header then needs. ncurses ignores
_BOOL. */
#if defined(__sun) && !defined(_BOOL)
# include <stdbool.h>
# define _BOOL
#endif

#if defined(HAVE_NCURSESW_NCURSES_H)
# include <ncursesw/ncurses.h>
#elif defined(HAVE_NCURSESW_CURSES_H)
Expand Down
25 changes: 9 additions & 16 deletions Lib/asyncio/base_subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ def __init__(self, loop, protocol, args, shell,
self._pending_calls = collections.deque()
self._pipes = {}
self._finished = False
self._pipes_connected = False

if stdin == subprocess.PIPE:
self._pipes[0] = None
Expand Down Expand Up @@ -214,7 +213,6 @@ async def _connect_pipes(self, waiter):
else:
if waiter is not None and not waiter.cancelled():
waiter.set_result(None)
self._pipes_connected = True

def _call(self, cb, *data):
if self._pending_calls is not None:
Expand All @@ -235,6 +233,7 @@ def _process_exited(self, returncode):
if self._loop.get_debug():
logger.info('%r exited with return code %r', self, returncode)
self._returncode = returncode

if self._proc.returncode is None:
# asyncio uses a child watcher: copy the status into the Popen
# object. On Python 3.6, it is required to avoid a ResourceWarning.
Expand All @@ -243,6 +242,13 @@ def _process_exited(self, returncode):

self._try_finish()

# gh-119710: Wake up futures waiting for wait() as soon as the process
# exits.
for waiter in self._exit_waiters:
if not waiter.done():
waiter.set_result(returncode)
self._exit_waiters = None

async def _wait(self):
"""Wait until the process exit and return the process return code.

Expand All @@ -258,15 +264,7 @@ def _try_finish(self):
assert not self._finished
if self._returncode is None:
return
if not self._pipes_connected:
# self._pipes_connected can be False if not all pipes were connected
# because either the process failed to start or the self._connect_pipes task
# got cancelled. In this broken state we consider all pipes disconnected and
# to avoid hanging forever in self._wait as otherwise _exit_waiters
# would never be woken up, we wake them up here.
for waiter in self._exit_waiters:
if not waiter.done():
waiter.set_result(self._returncode)

if all(p is not None and p.disconnected
for p in self._pipes.values()):
self._finished = True
Expand All @@ -276,11 +274,6 @@ def _call_connection_lost(self, exc):
try:
self._protocol.connection_lost(exc)
finally:
# wake up futures waiting for wait()
for waiter in self._exit_waiters:
if not waiter.done():
waiter.set_result(self._returncode)
self._exit_waiters = None
self._loop = None
self._proc = None
self._protocol = None
Expand Down
12 changes: 8 additions & 4 deletions Lib/platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,21 +543,25 @@ def android_ver(release="", api_level=0, manufacturer="", model="", device="",
is_emulator=False):
if sys.platform == "android":
try:
from ctypes import CDLL, c_char_p, create_string_buffer
from ctypes import CDLL, c_int, c_char_p, create_string_buffer
from ctypes.util import wrap_dll_function
except ImportError:
pass
else:
# An NDK developer confirmed that this is an officially-supported
# API (https://stackoverflow.com/a/28416743). Use `getattr` to avoid
# private name mangling.
system_property_get = getattr(CDLL("libc.so"), "__system_property_get")
system_property_get.argtypes = (c_char_p, c_char_p)
libc = CDLL("libc.so")

@wrap_dll_function(libc)
def __system_property_get(name: c_char_p, value: c_char_p) -> c_int:
pass

def getprop(name, default):
# https://android.googlesource.com/platform/bionic/+/refs/tags/android-5.0.0_r1/libc/include/sys/system_properties.h#39
PROP_VALUE_MAX = 92
buffer = create_string_buffer(PROP_VALUE_MAX)
length = system_property_get(name.encode("UTF-8"), buffer)
length = __system_property_get(name.encode("UTF-8"), buffer)
if length == 0:
# This API doesn’t distinguish between an empty property and
# a missing one.
Expand Down
5 changes: 3 additions & 2 deletions Lib/pydoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -881,9 +881,10 @@ def docmodule(self, object, name=None, mod=None, *ignored):
if data:
contents = []
for key, value in data:
contents.append(self.document(value, key))
contents.append(
f'<dl class="doc"><dt>{self.document(value, key)}</dt></dl>')
result = result + self.bigsection(
'Data', 'data', '<br>\n'.join(contents))
'Data', 'data', '\n'.join(contents))
if hasattr(object, '__author__'):
contents = self.markup(str(object.__author__), self.preformat)
result = result + self.bigsection('Author', 'author', contents)
Expand Down
16 changes: 8 additions & 8 deletions Lib/test/_test_multiprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,10 @@ def wait_for_handle(handle, timeout):
#

try:
from ctypes import Structure, c_int, c_double, c_longlong
from ctypes.util import struct as ctypes_struct
from ctypes import c_int, c_double, c_longlong
except ImportError:
Structure = object
def ctypes_struct(cls): return cls
c_int = c_double = c_longlong = None


Expand Down Expand Up @@ -4390,12 +4391,11 @@ def test_free_from_gc(self):
#
#

class _Foo(Structure):
_fields_ = [
('x', c_int),
('y', c_double),
('z', c_longlong,)
]
@ctypes_struct
class _Foo:
x: c_int
y: c_double
z: c_longlong

class _TestSharedCTypes(BaseTestCase):

Expand Down
1 change: 1 addition & 0 deletions Lib/test/libregrtest/tsan.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
'test_ctypes',
'test_concurrent_futures',
'test_enum',
'test_enumerate',
'test_functools',
'test_httpservers',
'test_imaplib',
Expand Down
17 changes: 8 additions & 9 deletions Lib/test/pythoninfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -995,7 +995,7 @@ def collect_windows(info_add):
# windows.RtlAreLongPathsEnabled: RtlAreLongPathsEnabled()
# windows.is_admin: IsUserAnAdmin()
try:
import ctypes
import ctypes.util
if not hasattr(ctypes, 'WinDLL'):
raise ImportError
except ImportError:
Expand All @@ -1004,20 +1004,19 @@ def collect_windows(info_add):
ntdll = ctypes.WinDLL('ntdll')
BOOLEAN = ctypes.c_ubyte
try:
RtlAreLongPathsEnabled = ntdll.RtlAreLongPathsEnabled
@ctypes.util.wrap_dll_function(ntdll)
def RtlAreLongPathsEnabled() -> BOOLEAN:
pass
except AttributeError:
res = '<function not available>'
else:
RtlAreLongPathsEnabled.restype = BOOLEAN
RtlAreLongPathsEnabled.argtypes = ()
res = bool(RtlAreLongPathsEnabled())
info_add('windows.RtlAreLongPathsEnabled', res)

shell32 = ctypes.windll.shell32
IsUserAnAdmin = shell32.IsUserAnAdmin
IsUserAnAdmin.restype = BOOLEAN
IsUserAnAdmin.argtypes = ()
info_add('windows.is_admin', IsUserAnAdmin())
@ctypes.util.wrap_dll_function(ctypes.windll.shell32)
def IsUserAnAdmin() -> BOOLEAN:
pass
info_add('windows.is_admin', bool(IsUserAnAdmin()))

try:
import _winapi
Expand Down
Loading
Loading