Skip to content

Commit 7b75616

Browse files
Merge branch 'main' into argparse-single-dash-long-option-dest
2 parents d80974d + e90061f commit 7b75616

17 files changed

+199
-25
lines changed

Doc/c-api/datetime.rst

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,42 @@ DateTime Objects
88
Various date and time objects are supplied by the :mod:`datetime` module.
99
Before using any of these functions, the header file :file:`datetime.h` must be
1010
included in your source (note that this is not included by :file:`Python.h`),
11-
and the macro :c:macro:`!PyDateTime_IMPORT` must be invoked, usually as part of
11+
and the macro :c:macro:`PyDateTime_IMPORT` must be invoked, usually as part of
1212
the module initialisation function. The macro puts a pointer to a C structure
13-
into a static variable, :c:data:`!PyDateTimeAPI`, that is used by the following
13+
into a static variable, :c:data:`PyDateTimeAPI`, that is used by the following
1414
macros.
1515

16+
.. c:macro:: PyDateTime_IMPORT()
17+
18+
Import the datetime C API.
19+
20+
On success, populate the :c:var:`PyDateTimeAPI` pointer.
21+
On failure, set :c:var:`PyDateTimeAPI` to ``NULL`` and set an exception.
22+
The caller must check if an error occurred via :c:func:`PyErr_Occurred`:
23+
24+
.. code-block::
25+
26+
PyDateTime_IMPORT;
27+
if (PyErr_Occurred()) { /* cleanup */ }
28+
29+
.. warning::
30+
31+
This is not compatible with subinterpreters.
32+
33+
.. c:type:: PyDateTime_CAPI
34+
35+
Structure containing the fields for the datetime C API.
36+
37+
The fields of this structure are private and subject to change.
38+
39+
Do not use this directly; prefer ``PyDateTime_*`` APIs instead.
40+
41+
.. c:var:: PyDateTime_CAPI *PyDateTimeAPI
42+
43+
Dynamically allocated object containing the datetime C API.
44+
45+
This variable is only available once :c:macro:`PyDateTime_IMPORT` succeeds.
46+
1647
.. c:type:: PyDateTime_Date
1748
1849
This subtype of :c:type:`PyObject` represents a Python date object.
@@ -325,3 +356,16 @@ Macros for the convenience of modules implementing the DB API:
325356
326357
Create and return a new :class:`datetime.date` object given an argument
327358
tuple suitable for passing to :meth:`datetime.date.fromtimestamp`.
359+
360+
361+
Internal data
362+
-------------
363+
364+
The following symbols are exposed by the C API but should be considered
365+
internal-only.
366+
367+
.. c:macro:: PyDateTime_CAPSULE_NAME
368+
369+
Name of the datetime capsule to pass to :c:func:`PyCapsule_Import`.
370+
371+
Internal usage only. Use :c:macro:`PyDateTime_IMPORT` instead.

Doc/c-api/gen.rst

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,41 @@ than explicitly calling :c:func:`PyGen_New` or :c:func:`PyGen_NewWithQualName`.
4444
with ``__name__`` and ``__qualname__`` set to *name* and *qualname*.
4545
A reference to *frame* is stolen by this function. The *frame* argument
4646
must not be ``NULL``.
47+
48+
.. c:function:: PyCodeObject* PyGen_GetCode(PyGenObject *gen)
49+
50+
Return a new :term:`strong reference` to the code object wrapped by *gen*.
51+
This function always succeeds.
52+
53+
54+
Asynchronous Generator Objects
55+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
56+
57+
.. seealso::
58+
:pep:`525`
59+
60+
.. c:var:: PyTypeObject PyAsyncGen_Type
61+
62+
The type object corresponding to asynchronous generator objects. This is
63+
available as :class:`types.AsyncGeneratorType` in the Python layer.
64+
65+
.. versionadded:: 3.6
66+
67+
.. c:function:: PyObject *PyAsyncGen_New(PyFrameObject *frame, PyObject *name, PyObject *qualname)
68+
69+
Create a new asynchronous generator wrapping *frame*, with ``__name__`` and
70+
``__qualname__`` set to *name* and *qualname*. *frame* is stolen by this
71+
function and must not be ``NULL``.
72+
73+
On success, this function returns a :term:`strong reference` to the
74+
new asynchronous generator. On failure, this function returns ``NULL``
75+
with an exception set.
76+
77+
.. versionadded:: 3.6
78+
79+
.. c:function:: int PyAsyncGen_CheckExact(PyObject *op)
80+
81+
Return true if *op* is an asynchronous generator object, false otherwise.
82+
This function always succeeds.
83+
84+
.. versionadded:: 3.6

Doc/c-api/init.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1891,6 +1891,25 @@ pointer and a void pointer argument.
18911891
This function now always schedules *func* to be run in the main
18921892
interpreter.
18931893
1894+
1895+
.. c:function:: int Py_MakePendingCalls(void)
1896+
1897+
Execute all pending calls. This is usually executed automatically by the
1898+
interpreter.
1899+
1900+
This function returns ``0`` on success, and returns ``-1`` with an exception
1901+
set on failure.
1902+
1903+
If this is not called in the main thread of the main
1904+
interpreter, this function does nothing and returns ``0``.
1905+
The caller must hold an :term:`attached thread state`.
1906+
1907+
.. versionadded:: 3.1
1908+
1909+
.. versionchanged:: 3.12
1910+
This function only runs pending calls in the main interpreter.
1911+
1912+
18941913
.. _profiling:
18951914
18961915
Profiling and Tracing

Include/internal/pycore_global_objects_fini_generated.h

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_global_strings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,7 @@ struct _Py_global_strings {
793793
STRUCT_FOR_ID(symmetric_difference_update)
794794
STRUCT_FOR_ID(tabsize)
795795
STRUCT_FOR_ID(tag)
796+
STRUCT_FOR_ID(take_bytes)
796797
STRUCT_FOR_ID(target)
797798
STRUCT_FOR_ID(target_is_directory)
798799
STRUCT_FOR_ID(task)

Include/internal/pycore_runtime_init_generated.h

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_unicodeobject_generated.h

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_bytes.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,6 +1524,32 @@ def test_take_bytes(self):
15241524
self.assertRaises(BufferError, ba.take_bytes)
15251525
self.assertEqual(ba.take_bytes(), b'abc')
15261526

1527+
@support.cpython_only # tests an implementation detail
1528+
def test_take_bytes_optimization(self):
1529+
# Validate optimization around taking lots of little chunks out of a
1530+
# much bigger buffer. Save work by only copying a little rather than
1531+
# moving a lot.
1532+
ba = bytearray(b'abcdef' + b'0' * 1000)
1533+
start_alloc = ba.__alloc__()
1534+
1535+
# Take two bytes at a time, checking alloc doesn't change.
1536+
self.assertEqual(ba.take_bytes(2), b'ab')
1537+
self.assertEqual(ba.__alloc__(), start_alloc)
1538+
self.assertEqual(len(ba), 4 + 1000)
1539+
self.assertEqual(ba.take_bytes(2), b'cd')
1540+
self.assertEqual(ba.__alloc__(), start_alloc)
1541+
self.assertEqual(len(ba), 2 + 1000)
1542+
self.assertEqual(ba.take_bytes(2), b'ef')
1543+
self.assertEqual(ba.__alloc__(), start_alloc)
1544+
self.assertEqual(len(ba), 0 + 1000)
1545+
self.assertEqual(ba.__alloc__(), start_alloc)
1546+
1547+
# Take over half, alloc shrinks to exact size.
1548+
self.assertEqual(ba.take_bytes(501), b'0' * 501)
1549+
self.assertEqual(len(ba), 499)
1550+
bytes_header_size = sys.getsizeof(b'')
1551+
self.assertEqual(ba.__alloc__(), 499 + bytes_header_size)
1552+
15271553
def test_setitem(self):
15281554
def setitem_as_mapping(b, i, val):
15291555
b[i] = val

Lib/test/test_copy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ def __eq__(self, other):
672672
def test_reduce_5tuple(self):
673673
class C(dict):
674674
def __reduce__(self):
675-
return (C, (), self.__dict__, None, self.items())
675+
return (C, (), self.__dict__, None, iter(self.items()))
676676
def __eq__(self, other):
677677
return (dict(self) == dict(other) and
678678
self.__dict__ == other.__dict__)

Lib/test/test_io/test_general.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,25 @@ def readinto(self, b):
609609
with self.assertRaises(ValueError):
610610
Misbehaved(bad_size).read()
611611

612+
def test_RawIOBase_read_gh60107(self):
613+
# gh-60107: Ensure a "Raw I/O" which keeps a reference to the
614+
# mutable memory doesn't allow making a mutable bytes.
615+
class RawIOKeepsReference(self.MockRawIOWithoutRead):
616+
def __init__(self, *args, **kwargs):
617+
self.buf = None
618+
super().__init__(*args, **kwargs)
619+
620+
def readinto(self, buf):
621+
# buf is the bytearray so keeping a reference to it doesn't keep
622+
# the memory alive; a memoryview does.
623+
self.buf = memoryview(buf)
624+
buf[0:4] = self._read_stack.pop()
625+
return 3
626+
627+
with self.assertRaises(BufferError):
628+
rawio = RawIOKeepsReference([b"1234"])
629+
rawio.read(4)
630+
612631
def test_types_have_dict(self):
613632
test = (
614633
self.IOBase(),

0 commit comments

Comments
 (0)