Skip to content

Commit 55af4ba

Browse files
committed
Merge branch 'origin/main' into pythongh-127266-type-slots-ts
2 parents c404ed4 + 4b4b9fb commit 55af4ba

39 files changed

+880
-174
lines changed

Doc/library/fcntl.rst

+46-29
Original file line numberDiff line numberDiff line change
@@ -82,65 +82,82 @@ descriptor.
8282
The module defines the following functions:
8383

8484

85-
.. function:: fcntl(fd, cmd, arg=0)
85+
.. function:: fcntl(fd, cmd, arg=0, /)
8686

8787
Perform the operation *cmd* on file descriptor *fd* (file objects providing
8888
a :meth:`~io.IOBase.fileno` method are accepted as well). The values used
8989
for *cmd* are operating system dependent, and are available as constants
9090
in the :mod:`fcntl` module, using the same names as used in the relevant C
91-
header files. The argument *arg* can either be an integer value, or a
92-
:class:`bytes` object. With an integer value, the return value of this
93-
function is the integer return value of the C :c:func:`fcntl` call. When
94-
the argument is bytes it represents a binary structure, e.g. created by
95-
:func:`struct.pack`. The binary data is copied to a buffer whose address is
91+
header files. The argument *arg* can either be an integer value, a
92+
:class:`bytes` object, or a string.
93+
The type and size of *arg* must match the type and size of
94+
the argument of the operation as specified in the relevant C documentation.
95+
96+
When *arg* is an integer, the function returns the integer
97+
return value of the C :c:func:`fcntl` call.
98+
99+
When the argument is bytes, it represents a binary structure,
100+
for example, created by :func:`struct.pack`.
101+
A string value is encoded to binary using the UTF-8 encoding.
102+
The binary data is copied to a buffer whose address is
96103
passed to the C :c:func:`fcntl` call. The return value after a successful
97104
call is the contents of the buffer, converted to a :class:`bytes` object.
98105
The length of the returned object will be the same as the length of the
99-
*arg* argument. This is limited to 1024 bytes. If the information returned
100-
in the buffer by the operating system is larger than 1024 bytes, this is
101-
most likely to result in a segmentation violation or a more subtle data
102-
corruption.
106+
*arg* argument. This is limited to 1024 bytes.
103107

104108
If the :c:func:`fcntl` call fails, an :exc:`OSError` is raised.
105109

110+
.. note::
111+
If the type or the size of *arg* does not match the type or size
112+
of the argument of the operation (for example, if an integer is
113+
passed when a pointer is expected, or the information returned in
114+
the buffer by the operating system is larger than 1024 bytes),
115+
this is most likely to result in a segmentation violation or
116+
a more subtle data corruption.
117+
106118
.. audit-event:: fcntl.fcntl fd,cmd,arg fcntl.fcntl
107119

108120

109-
.. function:: ioctl(fd, request, arg=0, mutate_flag=True)
121+
.. function:: ioctl(fd, request, arg=0, mutate_flag=True, /)
110122

111123
This function is identical to the :func:`~fcntl.fcntl` function, except
112124
that the argument handling is even more complicated.
113125

114-
The *request* parameter is limited to values that can fit in 32-bits.
126+
The *request* parameter is limited to values that can fit in 32-bits
127+
or 64-bits, depending on the platform.
115128
Additional constants of interest for use as the *request* argument can be
116129
found in the :mod:`termios` module, under the same names as used in
117130
the relevant C header files.
118131

119-
The parameter *arg* can be one of an integer, an object supporting the
120-
read-only buffer interface (like :class:`bytes`) or an object supporting
121-
the read-write buffer interface (like :class:`bytearray`).
132+
The parameter *arg* can be an integer, a :term:`bytes-like object`,
133+
or a string.
134+
The type and size of *arg* must match the type and size of
135+
the argument of the operation as specified in the relevant C documentation.
122136

123-
In all but the last case, behaviour is as for the :func:`~fcntl.fcntl`
137+
If *arg* does not support the read-write buffer interface or
138+
the *mutate_flag* is false, behavior is as for the :func:`~fcntl.fcntl`
124139
function.
125140

126-
If a mutable buffer is passed, then the behaviour is determined by the value of
127-
the *mutate_flag* parameter.
128-
129-
If it is false, the buffer's mutability is ignored and behaviour is as for a
130-
read-only buffer, except that the 1024 byte limit mentioned above is avoided --
131-
so long as the buffer you pass is at least as long as what the operating system
132-
wants to put there, things should work.
133-
134-
If *mutate_flag* is true (the default), then the buffer is (in effect) passed
135-
to the underlying :func:`ioctl` system call, the latter's return code is
141+
If *arg* supports the read-write buffer interface (like :class:`bytearray`)
142+
and *mutate_flag* is true (the default), then the buffer is (in effect) passed
143+
to the underlying :c:func:`!ioctl` system call, the latter's return code is
136144
passed back to the calling Python, and the buffer's new contents reflect the
137-
action of the :func:`ioctl`. This is a slight simplification, because if the
145+
action of the :c:func:`ioctl`. This is a slight simplification, because if the
138146
supplied buffer is less than 1024 bytes long it is first copied into a static
139147
buffer 1024 bytes long which is then passed to :func:`ioctl` and copied back
140148
into the supplied buffer.
141149

142150
If the :c:func:`ioctl` call fails, an :exc:`OSError` exception is raised.
143151

152+
.. note::
153+
If the type or size of *arg* does not match the type or size
154+
of the operation's argument (for example, if an integer is
155+
passed when a pointer is expected, or the information returned in
156+
the buffer by the operating system is larger than 1024 bytes,
157+
or the size of the mutable bytes-like object is too small),
158+
this is most likely to result in a segmentation violation or
159+
a more subtle data corruption.
160+
144161
An example::
145162

146163
>>> import array, fcntl, struct, termios, os
@@ -157,7 +174,7 @@ The module defines the following functions:
157174
.. audit-event:: fcntl.ioctl fd,request,arg fcntl.ioctl
158175

159176

160-
.. function:: flock(fd, operation)
177+
.. function:: flock(fd, operation, /)
161178

162179
Perform the lock operation *operation* on file descriptor *fd* (file objects providing
163180
a :meth:`~io.IOBase.fileno` method are accepted as well). See the Unix manual
@@ -169,7 +186,7 @@ The module defines the following functions:
169186
.. audit-event:: fcntl.flock fd,operation fcntl.flock
170187

171188

172-
.. function:: lockf(fd, cmd, len=0, start=0, whence=0)
189+
.. function:: lockf(fd, cmd, len=0, start=0, whence=0, /)
173190

174191
This is essentially a wrapper around the :func:`~fcntl.fcntl` locking calls.
175192
*fd* is the file descriptor (file objects providing a :meth:`~io.IOBase.fileno`

Doc/library/multiprocessing.rst

+19
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,25 @@ The :mod:`multiprocessing` package mostly replicates the API of the
670670

671671
.. versionadded:: 3.3
672672

673+
.. method:: interrupt()
674+
675+
Terminate the process. Works on POSIX using the :py:const:`~signal.SIGINT` signal.
676+
Behavior on Windows is undefined.
677+
678+
By default, this terminates the child process by raising :exc:`KeyboardInterrupt`.
679+
This behavior can be altered by setting the respective signal handler in the child
680+
process :func:`signal.signal` for :py:const:`~signal.SIGINT`.
681+
682+
Note: if the child process catches and discards :exc:`KeyboardInterrupt`, the
683+
process will not be terminated.
684+
685+
Note: the default behavior will also set :attr:`exitcode` to ``1`` as if an
686+
uncaught exception was raised in the child process. To have a different
687+
:attr:`exitcode` you may simply catch :exc:`KeyboardInterrupt` and call
688+
``exit(your_code)``.
689+
690+
.. versionadded:: next
691+
673692
.. method:: terminate()
674693

675694
Terminate the process. On POSIX this is done using the :py:const:`~signal.SIGTERM` signal;

Doc/library/struct.rst

+3-3
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,9 @@ C11 standard) is supported, the following format characters are available:
273273
+--------+--------------------------+--------------------+----------------+------------+
274274
| Format | C Type | Python type | Standard size | Notes |
275275
+========+==========================+====================+================+============+
276-
| ``E`` | :c:expr:`float complex` | complex | 8 | \(10) |
276+
| ``F`` | :c:expr:`float complex` | complex | 8 | \(10) |
277277
+--------+--------------------------+--------------------+----------------+------------+
278-
| ``C`` | :c:expr:`double complex` | complex | 16 | \(10) |
278+
| ``D`` | :c:expr:`double complex` | complex | 16 | \(10) |
279279
+--------+--------------------------+--------------------+----------------+------------+
280280

281281
.. versionchanged:: 3.3
@@ -285,7 +285,7 @@ C11 standard) is supported, the following format characters are available:
285285
Added support for the ``'e'`` format.
286286

287287
.. versionchanged:: 3.14
288-
Added support for the ``'E'`` and ``'C'`` formats.
288+
Added support for the ``'F'`` and ``'D'`` formats.
289289

290290

291291
Notes:

Doc/whatsnew/3.14.rst

+48-1
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,49 @@ is unchanged.
264264
Improved error messages
265265
-----------------------
266266

267+
* The interpreter now provides helpful suggestions when it detects typos in Python
268+
keywords. When a word that closely resembles a Python keyword is encountered,
269+
the interpreter will suggest the correct keyword in the error message. This
270+
feature helps programmers quickly identify and fix common typing mistakes. For
271+
example:
272+
273+
.. code-block:: python
274+
275+
>>> whille True:
276+
... pass
277+
Traceback (most recent call last):
278+
File "<stdin>", line 1
279+
whille True:
280+
^^^^^^
281+
SyntaxError: invalid syntax. Did you mean 'while'?
282+
283+
>>> asynch def fetch_data():
284+
... pass
285+
Traceback (most recent call last):
286+
File "<stdin>", line 1
287+
asynch def fetch_data():
288+
^^^^^^
289+
SyntaxError: invalid syntax. Did you mean 'async'?
290+
291+
>>> async def foo():
292+
... awaid fetch_data()
293+
Traceback (most recent call last):
294+
File "<stdin>", line 2
295+
awaid fetch_data()
296+
^^^^^
297+
SyntaxError: invalid syntax. Did you mean 'await'?
298+
299+
>>> raisee ValueError("Error")
300+
Traceback (most recent call last):
301+
File "<stdin>", line 1
302+
raisee ValueError("Error")
303+
^^^^^^
304+
SyntaxError: invalid syntax. Did you mean 'raise'?
305+
306+
While the feature focuses on the most common cases, some variations of
307+
misspellings may still result in regular syntax errors.
308+
(Contributed by Pablo Galindo in :gh:`132449`.)
309+
267310
* When unpacking assignment fails due to incorrect number of variables, the
268311
error message prints the received number of values in more cases than before.
269312
(Contributed by Tushar Sadhwani in :gh:`122239`.)
@@ -972,6 +1015,10 @@ multiprocessing
9721015
The :func:`set` in :func:`multiprocessing.Manager` method is now available.
9731016
(Contributed by Mingyu Park in :gh:`129949`.)
9741017

1018+
* Add :func:`multiprocessing.Process.interrupt` which terminates the child
1019+
process by sending :py:const:`~signal.SIGINT`. This enables "finally" clauses
1020+
and printing stack trace for the terminated process.
1021+
(Contributed by Artem Pulkin in :gh:`131913`.)
9751022

9761023
operator
9771024
--------
@@ -1126,7 +1173,7 @@ struct
11261173
------
11271174

11281175
* Support the :c:expr:`float complex` and :c:expr:`double complex` C types in
1129-
the :mod:`struct` module (formatting characters ``'E'`` and ``'C'``,
1176+
the :mod:`struct` module (formatting characters ``'F'`` and ``'D'``,
11301177
respectively) if the compiler has C11 complex arithmetic.
11311178
(Contributed by Sergey B Kirpichev in :gh:`121249`.)
11321179

Lib/ctypes/__init__.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,13 @@ class c_longdouble(_SimpleCData):
209209

210210
try:
211211
class c_double_complex(_SimpleCData):
212-
_type_ = "C"
212+
_type_ = "D"
213213
_check_size(c_double_complex)
214214
class c_float_complex(_SimpleCData):
215-
_type_ = "E"
215+
_type_ = "F"
216216
_check_size(c_float_complex)
217217
class c_longdouble_complex(_SimpleCData):
218-
_type_ = "F"
218+
_type_ = "G"
219219
except AttributeError:
220220
pass
221221

Lib/multiprocessing/popen_fork.py

+3
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ def _send_signal(self, sig):
5454
if self.wait(timeout=0.1) is None:
5555
raise
5656

57+
def interrupt(self):
58+
self._send_signal(signal.SIGINT)
59+
5760
def terminate(self):
5861
self._send_signal(signal.SIGTERM)
5962

Lib/multiprocessing/process.py

+7
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,13 @@ def start(self):
125125
del self._target, self._args, self._kwargs
126126
_children.add(self)
127127

128+
def interrupt(self):
129+
'''
130+
Terminate process; sends SIGINT signal
131+
'''
132+
self._check_closed()
133+
self._popen.interrupt()
134+
128135
def terminate(self):
129136
'''
130137
Terminate process; sends SIGTERM signal or uses TerminateProcess()

Lib/test/_test_multiprocessing.py

+22-2
Original file line numberDiff line numberDiff line change
@@ -512,15 +512,20 @@ def _test_process_mainthread_native_id(cls, q):
512512
def _sleep_some(cls):
513513
time.sleep(100)
514514

515+
@classmethod
516+
def _sleep_no_int_handler(cls):
517+
signal.signal(signal.SIGINT, signal.SIG_DFL)
518+
cls._sleep_some()
519+
515520
@classmethod
516521
def _test_sleep(cls, delay):
517522
time.sleep(delay)
518523

519-
def _kill_process(self, meth):
524+
def _kill_process(self, meth, target=None):
520525
if self.TYPE == 'threads':
521526
self.skipTest('test not appropriate for {}'.format(self.TYPE))
522527

523-
p = self.Process(target=self._sleep_some)
528+
p = self.Process(target=target or self._sleep_some)
524529
p.daemon = True
525530
p.start()
526531

@@ -567,6 +572,19 @@ def handler(*args):
567572

568573
return p.exitcode
569574

575+
@unittest.skipIf(os.name == 'nt', "POSIX only")
576+
def test_interrupt(self):
577+
exitcode = self._kill_process(multiprocessing.Process.interrupt)
578+
self.assertEqual(exitcode, 1)
579+
# exit code 1 is hard-coded for uncaught exceptions
580+
# (KeyboardInterrupt in this case)
581+
# in multiprocessing.BaseProcess._bootstrap
582+
583+
@unittest.skipIf(os.name == 'nt', "POSIX only")
584+
def test_interrupt_no_handler(self):
585+
exitcode = self._kill_process(multiprocessing.Process.interrupt, target=self._sleep_no_int_handler)
586+
self.assertEqual(exitcode, -signal.SIGINT)
587+
570588
def test_terminate(self):
571589
exitcode = self._kill_process(multiprocessing.Process.terminate)
572590
self.assertEqual(exitcode, -signal.SIGTERM)
@@ -1498,6 +1516,7 @@ def _test_lock_locked_2processes(cls, lock, event, res):
14981516
res.value = lock.locked()
14991517
event.set()
15001518

1519+
@unittest.skipUnless(HAS_SHAREDCTYPES, 'needs sharedctypes')
15011520
def test_lock_locked_2processes(self):
15021521
if self.TYPE != 'processes':
15031522
self.skipTest('test not appropriate for {}'.format(self.TYPE))
@@ -1582,6 +1601,7 @@ def test_rlock(self):
15821601
self.assertFalse(lock.locked())
15831602
self.assertRaises((AssertionError, RuntimeError), lock.release)
15841603

1604+
@unittest.skipUnless(HAS_SHAREDCTYPES, 'needs sharedctypes')
15851605
def test_rlock_locked_2processes(self):
15861606
if self.TYPE != 'processes':
15871607
self.skipTest('test not appropriate for {}'.format(self.TYPE))

Lib/test/support/os_helper.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ def fd_count():
657657
"""
658658
if sys.platform.startswith(('linux', 'android', 'freebsd', 'emscripten')):
659659
fd_path = "/proc/self/fd"
660-
elif sys.platform == "darwin":
660+
elif support.is_apple:
661661
fd_path = "/dev/fd"
662662
else:
663663
fd_path = None

Lib/test/test_capi/test_abstract.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,8 @@ def test_mapping_haskey(self):
460460
self.assertFalse(haskey({}, []))
461461
self.assertEqual(cm.unraisable.exc_type, TypeError)
462462
self.assertEqual(str(cm.unraisable.exc_value),
463-
"unhashable type: 'list'")
463+
"cannot use 'list' as a dict key "
464+
"(unhashable type: 'list')")
464465

465466
with support.catch_unraisable_exception() as cm:
466467
self.assertFalse(haskey([], 1))

Lib/test/test_ctypes/test_c_simple_type_meta.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,11 @@ def test_bad_type_message(self):
160160
class F(metaclass=PyCSimpleType):
161161
_type_ = "\0"
162162
message = str(cm.exception)
163-
expected_type_chars = list('cbBhHiIlLdCEFfuzZqQPXOv?g')
163+
expected_type_chars = list('cbBhHiIlLdDFGfuzZqQPXOv?g')
164164
if not hasattr(ctypes, 'c_float_complex'):
165-
expected_type_chars.remove('C')
166-
expected_type_chars.remove('E')
167165
expected_type_chars.remove('F')
166+
expected_type_chars.remove('D')
167+
expected_type_chars.remove('G')
168168
if not MS_WINDOWS:
169169
expected_type_chars.remove('X')
170170
self.assertIn("'" + ''.join(expected_type_chars) + "'", message)

0 commit comments

Comments
 (0)