Skip to content

Commit fdb8a3e

Browse files
authored
Merge branch '3.12' into backport-c39ae89-3.12
2 parents 421992e + f65aa0d commit fdb8a3e

14 files changed

+247
-8
lines changed

.github/workflows/reusable-windows.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ env:
2020
2121
jobs:
2222
build:
23-
name: >-
24-
build${{ inputs.arch != 'arm64' && ' and test' || '' }}
25-
(${{ inputs.arch }})
23+
name: ${{ inputs.arch == 'arm64' && 'build' || 'build and test' }} (${{ inputs.arch }})
2624
runs-on: windows-latest
2725
timeout-minutes: 60
2826
env:

Doc/library/errno.rst

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,171 @@ defined by the module. The specific list of defined symbols is available as
665665

666666
.. versionadded:: 3.11
667667

668+
669+
.. data:: ENOMEDIUM
670+
671+
No medium found
672+
673+
674+
.. data:: EMEDIUMTYPE
675+
676+
Wrong medium type
677+
678+
679+
.. data:: ENOKEY
680+
681+
Required key not available
682+
683+
684+
.. data:: EKEYEXPIRED
685+
686+
Key has expired
687+
688+
689+
.. data:: EKEYREVOKED
690+
691+
Key has been revoked
692+
693+
694+
.. data:: EKEYREJECTED
695+
696+
Key was rejected by service
697+
698+
699+
.. data:: ERFKILL
700+
701+
Operation not possible due to RF-kill
702+
703+
704+
.. data:: ELOCKUNMAPPED
705+
706+
Locked lock was unmapped
707+
708+
709+
.. data:: ENOTACTIVE
710+
711+
Facility is not active
712+
713+
714+
.. data:: EAUTH
715+
716+
Authentication error
717+
718+
.. versionadded:: 3.2
719+
720+
721+
.. data:: EBADARCH
722+
723+
Bad CPU type in executable
724+
725+
.. versionadded:: 3.2
726+
727+
728+
.. data:: EBADEXEC
729+
730+
Bad executable (or shared library)
731+
732+
.. versionadded:: 3.2
733+
734+
735+
.. data:: EBADMACHO
736+
737+
Malformed Mach-o file
738+
739+
.. versionadded:: 3.2
740+
741+
742+
.. data:: EDEVERR
743+
744+
Device error
745+
746+
.. versionadded:: 3.2
747+
748+
749+
.. data:: EFTYPE
750+
751+
Inappropriate file type or format
752+
753+
.. versionadded:: 3.2
754+
755+
756+
.. data:: ENEEDAUTH
757+
758+
Need authenticator
759+
760+
.. versionadded:: 3.2
761+
762+
763+
.. data:: ENOATTR
764+
765+
Attribute not found
766+
767+
.. versionadded:: 3.2
768+
769+
770+
.. data:: ENOPOLICY
771+
772+
Policy not found
773+
774+
.. versionadded:: 3.2
775+
776+
777+
.. data:: EPROCLIM
778+
779+
Too many processes
780+
781+
.. versionadded:: 3.2
782+
783+
784+
.. data:: EPROCUNAVAIL
785+
786+
Bad procedure for program
787+
788+
.. versionadded:: 3.2
789+
790+
791+
.. data:: EPROGMISMATCH
792+
793+
Program version wrong
794+
795+
.. versionadded:: 3.2
796+
797+
798+
.. data:: EPROGUNAVAIL
799+
800+
RPC prog. not avail
801+
802+
.. versionadded:: 3.2
803+
804+
805+
.. data:: EPWROFF
806+
807+
Device power is off
808+
809+
.. versionadded:: 3.2
810+
811+
812+
.. data:: EBADRPC
813+
814+
RPC struct is bad
815+
816+
.. versionadded:: 3.2
817+
818+
819+
.. data:: ERPCMISMATCH
820+
821+
RPC version wrong
822+
823+
.. versionadded:: 3.2
824+
825+
826+
.. data:: ESHLIBVERS
827+
828+
Shared library version mismatch
829+
830+
.. versionadded:: 3.2
831+
832+
668833
.. data:: ENOTCAPABLE
669834

670835
Capabilities insufficient. This error is mapped to the exception

Lib/http/client.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ def read(self, amt=None):
472472
if self.chunked:
473473
return self._read_chunked(amt)
474474

475-
if amt is not None:
475+
if amt is not None and amt >= 0:
476476
if self.length is not None and amt > self.length:
477477
# clip the read to the "end of response"
478478
amt = self.length
@@ -590,6 +590,8 @@ def _get_chunk_left(self):
590590

591591
def _read_chunked(self, amt=None):
592592
assert self.chunked != _UNKNOWN
593+
if amt is not None and amt < 0:
594+
amt = None
593595
value = []
594596
try:
595597
while (chunk_left := self._get_chunk_left()) is not None:

Lib/imaplib.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@
5252
# search command can be quite large, so we now use 1M.
5353
_MAXLINE = 1000000
5454

55+
# Data larger than this will be read in chunks, to prevent extreme
56+
# overallocation.
57+
_SAFE_BUF_SIZE = 1 << 20
5558

5659
# Commands
5760

@@ -315,7 +318,13 @@ def open(self, host='', port=IMAP4_PORT, timeout=None):
315318

316319
def read(self, size):
317320
"""Read 'size' bytes from remote."""
318-
return self.file.read(size)
321+
cursize = min(size, _SAFE_BUF_SIZE)
322+
data = self.file.read(cursize)
323+
while cursize < size and len(data) == cursize:
324+
delta = min(cursize, size - cursize)
325+
data += self.file.read(delta)
326+
cursize += delta
327+
return data
319328

320329

321330
def readline(self):

Lib/subprocess.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,8 @@
4343
import builtins
4444
import errno
4545
import io
46-
import locale
4746
import os
4847
import time
49-
import signal
5048
import sys
5149
import threading
5250
import warnings
@@ -138,6 +136,8 @@ def __init__(self, returncode, cmd, output=None, stderr=None):
138136

139137
def __str__(self):
140138
if self.returncode and self.returncode < 0:
139+
# Lazy import to improve module import time
140+
import signal
141141
try:
142142
return "Command '%s' died with %r." % (
143143
self.cmd, signal.Signals(-self.returncode))
@@ -375,6 +375,8 @@ def _text_encoding():
375375
if sys.flags.utf8_mode:
376376
return "utf-8"
377377
else:
378+
# Lazy import to improve module import time
379+
import locale
378380
return locale.getencoding()
379381

380382

@@ -1655,6 +1657,9 @@ def send_signal(self, sig):
16551657
# Don't signal a process that we know has already died.
16561658
if self.returncode is not None:
16571659
return
1660+
1661+
# Lazy import to improve module import time
1662+
import signal
16581663
if sig == signal.SIGTERM:
16591664
self.terminate()
16601665
elif sig == signal.CTRL_C_EVENT:
@@ -1759,6 +1764,9 @@ def _posix_spawn(self, args, executable, env, restore_signals,
17591764

17601765
kwargs = {}
17611766
if restore_signals:
1767+
# Lazy import to improve module import time
1768+
import signal
1769+
17621770
# See _Py_RestoreSignals() in Python/pylifecycle.c
17631771
sigset = []
17641772
for signame in ('SIGPIPE', 'SIGXFZ', 'SIGXFSZ'):
@@ -2208,9 +2216,13 @@ def send_signal(self, sig):
22082216
def terminate(self):
22092217
"""Terminate the process with SIGTERM
22102218
"""
2219+
# Lazy import to improve module import time
2220+
import signal
22112221
self.send_signal(signal.SIGTERM)
22122222

22132223
def kill(self):
22142224
"""Kill the process with SIGKILL
22152225
"""
2226+
# Lazy import to improve module import time
2227+
import signal
22162228
self.send_signal(signal.SIGKILL)

Lib/test/test_httplib.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,25 @@ def test_chunked(self):
10781078
self.assertEqual(resp.read(), expected)
10791079
resp.close()
10801080

1081+
# Explicit full read
1082+
for n in (-123, -1, None):
1083+
with self.subTest('full read', n=n):
1084+
sock = FakeSocket(chunked_start + last_chunk + chunked_end)
1085+
resp = client.HTTPResponse(sock, method="GET")
1086+
resp.begin()
1087+
self.assertTrue(resp.chunked)
1088+
self.assertEqual(resp.read(n), expected)
1089+
resp.close()
1090+
1091+
# Read first chunk
1092+
with self.subTest('read1(-1)'):
1093+
sock = FakeSocket(chunked_start + last_chunk + chunked_end)
1094+
resp = client.HTTPResponse(sock, method="GET")
1095+
resp.begin()
1096+
self.assertTrue(resp.chunked)
1097+
self.assertEqual(resp.read1(-1), b"hello worl")
1098+
resp.close()
1099+
10811100
# Various read sizes
10821101
for n in range(1, 12):
10831102
sock = FakeSocket(chunked_start + last_chunk + chunked_end)

Lib/test/test_imaplib.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,20 @@ def handle(self):
901901
self.assertRaises(imaplib.IMAP4.error,
902902
self.imap_class, *server.server_address)
903903

904+
def test_truncated_large_literal(self):
905+
size = 0
906+
class BadHandler(SimpleIMAPHandler):
907+
def handle(self):
908+
self._send_textline('* OK {%d}' % size)
909+
self._send_textline('IMAP4rev1')
910+
911+
for exponent in range(15, 64):
912+
size = 1 << exponent
913+
with self.subTest(f"size=2e{size}"):
914+
with self.reaped_server(BadHandler) as server:
915+
with self.assertRaises(imaplib.IMAP4.abort):
916+
self.imap_class(*server.server_address)
917+
904918
@threading_helper.reap_threads
905919
def test_simple_with_statement(self):
906920
# simplest call
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix incorrect handling of negative read sizes in :meth:`HTTPResponse.read
2+
<http.client.HTTPResponse.read>`. Patch by Yury Manushkin.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
In :mod:`sqlite3`, handle out-of-memory when creating user-defined SQL
2+
functions.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Improve import time of :mod:`subprocess` by lazy importing ``locale`` and
2+
``signal``. Patch by Taneli Hukkinen.

0 commit comments

Comments
 (0)