Skip to content

Commit

Permalink
Merge branch 'main' into dictwatch
Browse files Browse the repository at this point in the history
* main:
  pythonGH-88050: fix race in closing subprocess pipe in asyncio  (python#97951)
  pythongh-93738: Disallow pre-v3 syntax in the C domain (python#97962)
  pythongh-95986: Fix the example using match keyword (python#95989)
  pythongh-97897: Prevent os.mkfifo and os.mknod segfaults with macOS 13 SDK (pythonGH-97944)
  pythongh-94808: Cover `PyUnicode_Count` in CAPI (python#96929)
  pythongh-94808: Cover `PyObject_PyBytes` case with custom `__bytes__` method (python#96610)
  pythongh-95691: Doc BufferedWriter and BufferedReader (python#95703)
  pythonGH-88968: Add notes about socket ownership transfers (python#97936)
  pythongh-96865: [Enum] fix Flag to use CONFORM boundary (pythonGH-97528)
  • Loading branch information
carljm committed Oct 6, 2022
2 parents 7dcf9b0 + e2e6b95 commit 7938d6f
Show file tree
Hide file tree
Showing 21 changed files with 230 additions and 45 deletions.
25 changes: 0 additions & 25 deletions Doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,28 +239,3 @@
# Relative filename of the data files
refcount_file = 'data/refcounts.dat'
stable_abi_file = 'data/stable_abi.dat'

# Sphinx 2 and Sphinx 3 compatibility
# -----------------------------------

# bpo-40204: Allow Sphinx 2 syntax in the C domain
c_allow_pre_v3 = True

# bpo-40204: Disable warnings on Sphinx 2 syntax of the C domain since the
# documentation is built with -W (warnings treated as errors).
c_warn_on_allowed_pre_v3 = False

# Fix '!' not working with C domain when pre_v3 is enabled
import sphinx

if sphinx.version_info[:2] < (5, 3):
from sphinx.domains.c import CXRefRole

original_run = CXRefRole.run

def new_run(self):
if self.disabled:
return super(CXRefRole, self).run()
return original_run(self)

CXRefRole.run = new_run
6 changes: 3 additions & 3 deletions Doc/extending/newtypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ a special case, for which the new value passed to the handler is ``NULL``.
Python supports two pairs of attribute handlers; a type that supports attributes
only needs to implement the functions for one pair. The difference is that one
pair takes the name of the attribute as a :c:expr:`char\*`, while the other
accepts a :c:type:`PyObject\*`. Each type can use whichever pair makes more
accepts a :c:expr:`PyObject*`. Each type can use whichever pair makes more
sense for the implementation's convenience. ::

getattrfunc tp_getattr; /* char * version */
Expand All @@ -219,7 +219,7 @@ sense for the implementation's convenience. ::

If accessing attributes of an object is always a simple operation (this will be
explained shortly), there are generic implementations which can be used to
provide the :c:type:`PyObject\*` version of the attribute management functions.
provide the :c:expr:`PyObject*` version of the attribute management functions.
The actual need for type-specific attribute handlers almost completely
disappeared starting with Python 2.2, though there are many examples which have
not been updated to use some of the new generic mechanism that is available.
Expand Down Expand Up @@ -341,7 +341,7 @@ Type-specific Attribute Management

For simplicity, only the :c:expr:`char\*` version will be demonstrated here; the
type of the name parameter is the only difference between the :c:expr:`char\*`
and :c:type:`PyObject\*` flavors of the interface. This example effectively does
and :c:expr:`PyObject*` flavors of the interface. This example effectively does
the same thing as the generic example above, but does not use the generic
support added in Python 2.2. It explains how the handler functions are
called, so that if you do need to extend their functionality, you'll understand
Expand Down
2 changes: 1 addition & 1 deletion Doc/extending/newtypes_tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The Basics
==========

The :term:`CPython` runtime sees all Python objects as variables of type
:c:type:`PyObject\*`, which serves as a "base type" for all Python objects.
:c:expr:`PyObject*`, which serves as a "base type" for all Python objects.
The :c:type:`PyObject` structure itself only contains the object's
:term:`reference count` and a pointer to the object's "type object".
This is where the action is; the type object determines which (C) functions
Expand Down
2 changes: 1 addition & 1 deletion Doc/howto/isolating-extensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ that subclass, which may be defined in different module than yours.
pass
For a method to get its "defining class", it must use the
:c:data:`METH_METHOD | METH_FASTCALL | METH_KEYWORDS`
:data:`METH_METHOD | METH_FASTCALL | METH_KEYWORDS`
:c:type:`calling convention <PyMethodDef>`
and the corresponding :c:type:`PyCMethod` signature::

Expand Down
24 changes: 24 additions & 0 deletions Doc/library/asyncio-eventloop.rst
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,12 @@ Opening network connections
*happy_eyeballs_delay*, *interleave*
and *local_addr* should be specified.

.. note::

The *sock* argument transfers ownership of the socket to the
transport created. To close the socket, call the transport's
:meth:`~asyncio.BaseTransport.close` method.

* *local_addr*, if given, is a ``(local_host, local_port)`` tuple used
to bind the socket locally. The *local_host* and *local_port*
are looked up using ``getaddrinfo()``, similarly to *host* and *port*.
Expand Down Expand Up @@ -577,6 +583,12 @@ Opening network connections
transport. If specified, *local_addr* and *remote_addr* should be omitted
(must be :const:`None`).

.. note::

The *sock* argument transfers ownership of the socket to the
transport created. To close the socket, call the transport's
:meth:`~asyncio.BaseTransport.close` method.

See :ref:`UDP echo client protocol <asyncio-udp-echo-client-protocol>` and
:ref:`UDP echo server protocol <asyncio-udp-echo-server-protocol>` examples.

Expand Down Expand Up @@ -688,6 +700,12 @@ Creating network servers
* *sock* can optionally be specified in order to use a preexisting
socket object. If specified, *host* and *port* must not be specified.

.. note::

The *sock* argument transfers ownership of the socket to the
server created. To close the socket, call the server's
:meth:`~asyncio.Server.close` method.

* *backlog* is the maximum number of queued connections passed to
:meth:`~socket.socket.listen` (defaults to 100).

Expand Down Expand Up @@ -789,6 +807,12 @@ Creating network servers
* *sock* is a preexisting socket object returned from
:meth:`socket.accept <socket.socket.accept>`.

.. note::

The *sock* argument transfers ownership of the socket to the
transport created. To close the socket, call the transport's
:meth:`~asyncio.BaseTransport.close` method.

* *ssl* can be set to an :class:`~ssl.SSLContext` to enable SSL over
the accepted connections.

Expand Down
24 changes: 24 additions & 0 deletions Doc/library/asyncio-stream.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ and work with streams:
The rest of the arguments are passed directly to
:meth:`loop.create_connection`.

.. note::

The *sock* argument transfers ownership of the socket to the
:class:`StreamWriter` created. To close the socket, call its
:meth:`~asyncio.StreamWriter.close` method.

.. versionchanged:: 3.7
Added the *ssl_handshake_timeout* parameter.

Expand Down Expand Up @@ -103,6 +109,12 @@ and work with streams:
The rest of the arguments are passed directly to
:meth:`loop.create_server`.

.. note::

The *sock* argument transfers ownership of the socket to the
server created. To close the socket, call the server's
:meth:`~asyncio.Server.close` method.

.. versionchanged:: 3.7
Added the *ssl_handshake_timeout* and *start_serving* parameters.

Expand All @@ -123,6 +135,12 @@ and work with streams:

See also the documentation of :meth:`loop.create_unix_connection`.

.. note::

The *sock* argument transfers ownership of the socket to the
:class:`StreamWriter` created. To close the socket, call its
:meth:`~asyncio.StreamWriter.close` method.

.. availability:: Unix.

.. versionchanged:: 3.7
Expand All @@ -143,6 +161,12 @@ and work with streams:

See also the documentation of :meth:`loop.create_unix_server`.

.. note::

The *sock* argument transfers ownership of the socket to the
server created. To close the socket, call the server's
:meth:`~asyncio.Server.close` method.

.. availability:: Unix.

.. versionchanged:: 3.7
Expand Down
2 changes: 1 addition & 1 deletion Doc/library/io.rst
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ to provide an interface to files in the machine's file system.
The :class:`BufferedIOBase` ABC extends :class:`IOBase`. It deals with
buffering on a raw binary stream (:class:`RawIOBase`). Its subclasses,
:class:`BufferedWriter`, :class:`BufferedReader`, and :class:`BufferedRWPair`
buffer raw binary streams that are readable, writable, and both readable and writable,
buffer raw binary streams that are writable, readable, and both readable and writable,
respectively. :class:`BufferedRandom` provides a buffered interface to seekable streams.
Another :class:`BufferedIOBase` subclass, :class:`BytesIO`, is a stream of
in-memory bytes.
Expand Down
5 changes: 4 additions & 1 deletion Doc/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ sphinx==4.5.0

blurb

sphinx-lint<1
# sphinx-lint 0.6.2 yields many default role errors due to the new regular
# expression used for default role detection, so we don't use the version
# until the errors are fixed.
sphinx-lint<1,!=0.6.2

# The theme used by the documentation is stored separately, so we need
# to install that as well.
Expand Down
2 changes: 1 addition & 1 deletion Doc/whatsnew/2.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1102,7 +1102,7 @@ code, none of the changes described here will affect you very much.
* A different argument parsing function, :c:func:`PyArg_UnpackTuple`, has been
added that's simpler and presumably faster. Instead of specifying a format
string, the caller simply gives the minimum and maximum number of arguments
expected, and a set of pointers to :c:type:`PyObject\*` variables that will be
expected, and a set of pointers to :c:expr:`PyObject*` variables that will be
filled in with argument values.

* Two new flags :const:`METH_NOARGS` and :const:`METH_O` are available in method
Expand Down
2 changes: 1 addition & 1 deletion Doc/whatsnew/2.5.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1725,7 +1725,7 @@ attribute of the function object to change this::
``ctypes.pythonapi`` object. This object does *not* release the global
interpreter lock before calling a function, because the lock must be held when
calling into the interpreter's code. There's a :class:`py_object()` type
constructor that will create a :c:type:`PyObject \*` pointer. A simple usage::
constructor that will create a :c:expr:`PyObject *` pointer. A simple usage::

import ctypes

Expand Down
1 change: 1 addition & 0 deletions Doc/whatsnew/3.10.rst
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,7 @@ Several other key features:
GREEN = 1
BLUE = 2
color = Color.GREEN
match color:
case Color.RED:
print("I see red!")
Expand Down
4 changes: 3 additions & 1 deletion Lib/asyncio/base_subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,9 @@ def _process_exited(self, returncode):
self._proc.returncode = returncode
self._call(self._protocol.process_exited)
for p in self._pipes.values():
p.pipe.close()
if p is not None:
p.pipe.close()

self._try_finish()

async def _wait(self):
Expand Down
2 changes: 1 addition & 1 deletion Lib/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -1269,7 +1269,7 @@ class FlagBoundary(StrEnum):
STRICT, CONFORM, EJECT, KEEP = FlagBoundary


class Flag(Enum, boundary=STRICT):
class Flag(Enum, boundary=CONFORM):
"""
Support for flags
"""
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -2927,7 +2927,7 @@ def test_bool(self):
self.assertEqual(bool(f.value), bool(f))

def test_boundary(self):
self.assertIs(enum.Flag._boundary_, STRICT)
self.assertIs(enum.Flag._boundary_, CONFORM)
class Iron(Flag, boundary=STRICT):
ONE = 1
TWO = 2
Expand Down
16 changes: 16 additions & 0 deletions Lib/test/test_long.py
Original file line number Diff line number Diff line change
Expand Up @@ -1518,6 +1518,22 @@ def __init__(self, value):
self.assertEqual(i, 1)
self.assertEqual(getattr(i, 'foo', 'none'), 'bar')

class ValidBytes:
def __bytes__(self):
return b'\x01'
class InvalidBytes:
def __bytes__(self):
return 'abc'
class MissingBytes: ...
class RaisingBytes:
def __bytes__(self):
1 / 0

self.assertEqual(int.from_bytes(ValidBytes()), 1)
self.assertRaises(TypeError, int.from_bytes, InvalidBytes())
self.assertRaises(TypeError, int.from_bytes, MissingBytes())
self.assertRaises(ZeroDivisionError, int.from_bytes, RaisingBytes())

@support.cpython_only
def test_from_bytes_small(self):
# bpo-46361
Expand Down
22 changes: 22 additions & 0 deletions Lib/test/test_posix.py
Original file line number Diff line number Diff line change
Expand Up @@ -2090,6 +2090,28 @@ def test_mkdir(self):
with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
os.mkdir("dir", dir_fd=0)

def test_mkfifo(self):
self._verify_available("HAVE_MKFIFOAT")
if self.mac_ver >= (13, 0):
self.assertIn("HAVE_MKFIFOAT", posix._have_functions)

else:
self.assertNotIn("HAVE_MKFIFOAT", posix._have_functions)

with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
os.mkfifo("path", dir_fd=0)

def test_mknod(self):
self._verify_available("HAVE_MKNODAT")
if self.mac_ver >= (13, 0):
self.assertIn("HAVE_MKNODAT", posix._have_functions)

else:
self.assertNotIn("HAVE_MKNODAT", posix._have_functions)

with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
os.mknod("path", dir_fd=0)

def test_rename_replace(self):
self._verify_available("HAVE_RENAMEAT")
if self.mac_ver >= (10, 10):
Expand Down
38 changes: 38 additions & 0 deletions Lib/test/test_unicode.py
Original file line number Diff line number Diff line change
Expand Up @@ -2945,6 +2945,44 @@ def test_asutf8andsize(self):
self.assertEqual(unicode_asutf8andsize(nonbmp), (b'\xf4\x8f\xbf\xbf', 4))
self.assertRaises(UnicodeEncodeError, unicode_asutf8andsize, 'a\ud800b\udfffc')

# Test PyUnicode_Count()
@support.cpython_only
@unittest.skipIf(_testcapi is None, 'need _testcapi module')
def test_count(self):
from _testcapi import unicode_count

st = 'abcabd'
self.assertEqual(unicode_count(st, 'a', 0, len(st)), 2)
self.assertEqual(unicode_count(st, 'ab', 0, len(st)), 2)
self.assertEqual(unicode_count(st, 'abc', 0, len(st)), 1)
self.assertEqual(unicode_count(st, 'а', 0, len(st)), 0) # cyrillic "a"
# start < end
self.assertEqual(unicode_count(st, 'a', 3, len(st)), 1)
self.assertEqual(unicode_count(st, 'a', 4, len(st)), 0)
self.assertEqual(unicode_count(st, 'a', 0, sys.maxsize), 2)
# start >= end
self.assertEqual(unicode_count(st, 'abc', 0, 0), 0)
self.assertEqual(unicode_count(st, 'a', 3, 2), 0)
self.assertEqual(unicode_count(st, 'a', sys.maxsize, 5), 0)
# negative
self.assertEqual(unicode_count(st, 'ab', -len(st), -1), 2)
self.assertEqual(unicode_count(st, 'a', -len(st), -3), 1)
# wrong args
self.assertRaises(TypeError, unicode_count, 'a', 'a')
self.assertRaises(TypeError, unicode_count, 'a', 'a', 1)
self.assertRaises(TypeError, unicode_count, 1, 'a', 0, 1)
self.assertRaises(TypeError, unicode_count, 'a', 1, 0, 1)
# empty string
self.assertEqual(unicode_count('abc', '', 0, 3), 4)
self.assertEqual(unicode_count('abc', '', 1, 3), 3)
self.assertEqual(unicode_count('', '', 0, 1), 1)
self.assertEqual(unicode_count('', 'a', 0, 1), 0)
# different unicode kinds
for uni in "\xa1", "\u8000\u8080", "\ud800\udc02", "\U0001f100\U0001f1f1":
for ch in uni:
self.assertEqual(unicode_count(uni, ch, 0, len(uni)), 1)
self.assertEqual(unicode_count(st, ch, 0, len(st)), 0)

# Test PyUnicode_FindChar()
@support.cpython_only
@unittest.skipIf(_testcapi is None, 'need _testcapi module')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
fix Flag to use boundary CONFORM

This restores previous Flag behavior of allowing flags with non-sequential values to be combined; e.g.

class Skip(Flag):
TWO = 2
EIGHT = 8

Skip.TWO | Skip.EIGHT -> <Skip.TWO|EIGHT: 10>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
The macOS 13 SDK includes support for the ``mkfifoat`` and ``mknodat`` system calls.
Using the ``dir_fd`` option with either :func:`os.mkfifo` or :func:`os.mknod` could result in a
segfault if cpython is built with the macOS 13 SDK but run on an earlier
version of macOS. Prevent this by adding runtime support for detection of
these system calls ("weaklinking") as is done for other newer syscalls on
macOS.
Loading

0 comments on commit 7938d6f

Please sign in to comment.