Skip to content

Commit 88423e5

Browse files
authored
Merge branch 'main' into pep750-expression-default
2 parents d733d11 + 591abcc commit 88423e5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+326
-170
lines changed

Doc/howto/logging-cookbook.rst

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4140,6 +4140,42 @@ The script, when run, prints something like:
41404140
2025-07-02 13:54:47,234 DEBUG fool me ...
41414141
2025-07-02 13:54:47,234 DEBUG can't get fooled again
41424142
4143+
If, on the other hand, you are concerned about `log injection
4144+
<https://owasp.org/www-community/attacks/Log_Injection>`_, you can use a
4145+
formatter which escapes newlines, as per the following example:
4146+
4147+
.. code-block:: python
4148+
4149+
import logging
4150+
4151+
logger = logging.getLogger(__name__)
4152+
4153+
class EscapingFormatter(logging.Formatter):
4154+
def format(self, record):
4155+
s = super().format(record)
4156+
return s.replace('\n', r'\n')
4157+
4158+
if __name__ == '__main__':
4159+
h = logging.StreamHandler()
4160+
h.setFormatter(EscapingFormatter('%(asctime)s %(levelname)-9s %(message)s'))
4161+
logging.basicConfig(level=logging.DEBUG, handlers = [h])
4162+
logger.debug('Single line')
4163+
logger.debug('Multiple lines:\nfool me once ...')
4164+
logger.debug('Another single line')
4165+
logger.debug('Multiple lines:\n%s', 'fool me ...\ncan\'t get fooled again')
4166+
4167+
You can, of course, use whatever escaping scheme makes the most sense for you.
4168+
The script, when run, should produce output like this:
4169+
4170+
.. code-block:: text
4171+
4172+
2025-07-09 06:47:33,783 DEBUG Single line
4173+
2025-07-09 06:47:33,783 DEBUG Multiple lines:\nfool me once ...
4174+
2025-07-09 06:47:33,783 DEBUG Another single line
4175+
2025-07-09 06:47:33,783 DEBUG Multiple lines:\nfool me ...\ncan't get fooled again
4176+
4177+
Escaping behaviour can't be the stdlib default , as it would break backwards
4178+
compatibility.
41434179

41444180
.. patterns-to-avoid:
41454181

Doc/library/codecs.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,20 @@ wider range of codecs when working with binary files:
265265
:func:`iterencode`.
266266

267267

268+
.. function:: readbuffer_encode(buffer, errors=None, /)
269+
270+
Return a :class:`tuple` containing the raw bytes of *buffer*, a
271+
:ref:`buffer-compatible object <bufferobjects>` or :class:`str`
272+
(encoded to UTF-8 before processing), and their length in bytes.
273+
274+
The *errors* argument is ignored.
275+
276+
.. code-block:: pycon
277+
278+
>>> codecs.readbuffer_encode(b"Zito")
279+
(b'Zito', 4)
280+
281+
268282
The module also provides the following constants which are useful for reading
269283
and writing to platform dependent files:
270284

Doc/library/os.path.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -298,9 +298,10 @@ the :mod:`glob` module.)
298298
device than *path*, or whether :file:`{path}/..` and *path* point to the same
299299
i-node on the same device --- this should detect mount points for all Unix
300300
and POSIX variants. It is not able to reliably detect bind mounts on the
301-
same filesystem. On Windows, a drive letter root and a share UNC are
302-
always mount points, and for any other path ``GetVolumePathName`` is called
303-
to see if it is different from the input path.
301+
same filesystem. On Linux systems, it will always return ``True`` for btrfs
302+
subvolumes, even if they aren't mount points. On Windows, a drive letter root
303+
and a share UNC are always mount points, and for any other path
304+
``GetVolumePathName`` is called to see if it is different from the input path.
304305

305306
.. versionchanged:: 3.4
306307
Added support for detecting non-root mount points on Windows.

Doc/library/sqlite3.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2288,7 +2288,7 @@ This section shows recipes for common adapters and converters.
22882288

22892289
def adapt_datetime_iso(val):
22902290
"""Adapt datetime.datetime to timezone-naive ISO 8601 date."""
2291-
return val.isoformat()
2291+
return val.replace(tzinfo=None).isoformat()
22922292

22932293
def adapt_datetime_epoch(val):
22942294
"""Adapt datetime.datetime to Unix timestamp."""

Doc/library/unittest.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2563,7 +2563,7 @@ To add cleanup code that must be run even in the case of an exception, use
25632563
.. versionadded:: 3.8
25642564

25652565

2566-
.. classmethod:: enterModuleContext(cm)
2566+
.. function:: enterModuleContext(cm)
25672567

25682568
Enter the supplied :term:`context manager`. If successful, also
25692569
add its :meth:`~object.__exit__` method as a cleanup function by

Lib/asyncio/__init__.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,24 @@
5151
def __getattr__(name: str):
5252
import warnings
5353

54-
deprecated = {
55-
"AbstractEventLoopPolicy",
56-
"DefaultEventLoopPolicy",
57-
"WindowsSelectorEventLoopPolicy",
58-
"WindowsProactorEventLoopPolicy",
59-
}
60-
if name in deprecated:
61-
warnings._deprecated(f"asyncio.{name}", remove=(3, 16))
62-
# deprecated things have underscores in front of them
63-
return globals()["_" + name]
54+
match name:
55+
case "AbstractEventLoopPolicy":
56+
warnings._deprecated(f"asyncio.{name}", remove=(3, 16))
57+
return events._AbstractEventLoopPolicy
58+
case "DefaultEventLoopPolicy":
59+
warnings._deprecated(f"asyncio.{name}", remove=(3, 16))
60+
if sys.platform == 'win32':
61+
return windows_events._DefaultEventLoopPolicy
62+
return unix_events._DefaultEventLoopPolicy
63+
case "WindowsSelectorEventLoopPolicy":
64+
if sys.platform == 'win32':
65+
warnings._deprecated(f"asyncio.{name}", remove=(3, 16))
66+
return windows_events._WindowsSelectorEventLoopPolicy
67+
# Else fall through to the AttributeError below.
68+
case "WindowsProactorEventLoopPolicy":
69+
if sys.platform == 'win32':
70+
warnings._deprecated(f"asyncio.{name}", remove=(3, 16))
71+
return windows_events._WindowsProactorEventLoopPolicy
72+
# Else fall through to the AttributeError below.
6473

6574
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

Lib/asyncio/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def callback():
6464
except BaseException as exc:
6565
future.set_exception(exc)
6666

67-
loop.call_soon_threadsafe(callback, context=self.context)
67+
self.loop.call_soon_threadsafe(callback, context=self.context)
6868

6969
try:
7070
return future.result()

Lib/asyncio/events.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,11 @@
55
# SPDX-FileCopyrightText: Copyright (c) 2015-2021 MagicStack Inc. http://magic.io
66

77
__all__ = (
8-
"_AbstractEventLoopPolicy",
98
"AbstractEventLoop",
109
"AbstractServer",
1110
"Handle",
1211
"TimerHandle",
13-
"_get_event_loop_policy",
1412
"get_event_loop_policy",
15-
"_set_event_loop_policy",
1613
"set_event_loop_policy",
1714
"get_event_loop",
1815
"set_event_loop",
@@ -791,7 +788,10 @@ def _init_event_loop_policy():
791788
global _event_loop_policy
792789
with _lock:
793790
if _event_loop_policy is None: # pragma: no branch
794-
from . import _DefaultEventLoopPolicy
791+
if sys.platform == 'win32':
792+
from .windows_events import _DefaultEventLoopPolicy
793+
else:
794+
from .unix_events import _DefaultEventLoopPolicy
795795
_event_loop_policy = _DefaultEventLoopPolicy()
796796

797797

Lib/asyncio/unix_events.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828

2929
__all__ = (
3030
'SelectorEventLoop',
31-
'_DefaultEventLoopPolicy',
3231
'EventLoop',
3332
)
3433

Lib/test/libregrtest/save_env.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def get_asyncio_events__event_loop_policy(self):
9797
return support.maybe_get_event_loop_policy()
9898
def restore_asyncio_events__event_loop_policy(self, policy):
9999
asyncio = self.get_module('asyncio')
100-
asyncio._set_event_loop_policy(policy)
100+
asyncio.events._set_event_loop_policy(policy)
101101

102102
def get_sys_argv(self):
103103
return id(sys.argv), sys.argv, sys.argv[:]

0 commit comments

Comments
 (0)