Skip to content

Commit 8d13583

Browse files
committed
update to python 3.12.6 and boost 1.86
1 parent 455b9ed commit 8d13583

Some content is hidden

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

91 files changed

+620
-343
lines changed

.github/workflows/CI_build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ jobs:
4343
if: matrix.build_configuration == 'Release'
4444
working-directory: installer
4545
run: |
46-
$env:PYTHONBUILDDIR_X64='..\packages\python.3.12.5\tools'
47-
$env:PYTHONBUILDDIR='..\packages\pythonx86.3.12.5\tools'
46+
$env:PYTHONBUILDDIR_X64='..\packages\python.3.12.6\tools'
47+
$env:PYTHONBUILDDIR='..\packages\pythonx86.3.12.6\tools'
4848
Rename-Item -Path ".\buildPaths.bat.orig" -NewName "buildPaths.bat"
4949
$env:WIX_PATH="C:\Program Files (x86)\WiX Toolset v3.11\bin"
5050
$env:PATH = $env:PATH + ';' + $env:WIX_PATH

PythonLib/full/asyncio/futures.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,9 +272,13 @@ def set_exception(self, exception):
272272
raise exceptions.InvalidStateError(f'{self._state}: {self!r}')
273273
if isinstance(exception, type):
274274
exception = exception()
275-
if type(exception) is StopIteration:
276-
raise TypeError("StopIteration interacts badly with generators "
277-
"and cannot be raised into a Future")
275+
if isinstance(exception, StopIteration):
276+
new_exc = RuntimeError("StopIteration interacts badly with "
277+
"generators and cannot be raised into a "
278+
"Future")
279+
new_exc.__cause__ = exception
280+
new_exc.__context__ = exception
281+
exception = new_exc
278282
self._exception = exception
279283
self._exception_tb = exception.__traceback__
280284
self._state = _FINISHED

PythonLib/full/code.py

Lines changed: 40 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -105,29 +105,21 @@ def showsyntaxerror(self, filename=None):
105105
The output is written by self.write(), below.
106106
107107
"""
108-
type, value, tb = sys.exc_info()
109-
sys.last_exc = value
110-
sys.last_type = type
111-
sys.last_value = value
112-
sys.last_traceback = tb
113-
if filename and type is SyntaxError:
114-
# Work hard to stuff the correct filename in the exception
115-
try:
116-
msg, (dummy_filename, lineno, offset, line) = value.args
117-
except ValueError:
118-
# Not the format we expect; leave it alone
119-
pass
120-
else:
121-
# Stuff in the right filename
122-
value = SyntaxError(msg, (filename, lineno, offset, line))
123-
sys.last_exc = sys.last_value = value
124-
if sys.excepthook is sys.__excepthook__:
125-
lines = traceback.format_exception_only(type, value)
126-
self.write(''.join(lines))
127-
else:
128-
# If someone has set sys.excepthook, we let that take precedence
129-
# over self.write
130-
self._call_excepthook(type, value, tb)
108+
try:
109+
typ, value, tb = sys.exc_info()
110+
if filename and typ is SyntaxError:
111+
# Work hard to stuff the correct filename in the exception
112+
try:
113+
msg, (dummy_filename, lineno, offset, line) = value.args
114+
except ValueError:
115+
# Not the format we expect; leave it alone
116+
pass
117+
else:
118+
# Stuff in the right filename
119+
value = SyntaxError(msg, (filename, lineno, offset, line))
120+
self._showtraceback(typ, value, None)
121+
finally:
122+
typ = value = tb = None
131123

132124
def showtraceback(self):
133125
"""Display the exception that just occurred.
@@ -137,32 +129,34 @@ def showtraceback(self):
137129
The output is written by self.write(), below.
138130
139131
"""
140-
sys.last_type, sys.last_value, last_tb = ei = sys.exc_info()
141-
sys.last_traceback = last_tb
142-
sys.last_exc = ei[1]
143132
try:
144-
if sys.excepthook is sys.__excepthook__:
145-
lines = traceback.format_exception(ei[0], ei[1], last_tb.tb_next)
146-
self.write(''.join(lines))
147-
else:
148-
# If someone has set sys.excepthook, we let that take precedence
149-
# over self.write
150-
self._call_excepthook(ei[0], ei[1], last_tb)
133+
typ, value, tb = sys.exc_info()
134+
self._showtraceback(typ, value, tb.tb_next)
151135
finally:
152-
last_tb = ei = None
136+
typ = value = tb = None
153137

154-
def _call_excepthook(self, typ, value, tb):
155-
try:
156-
sys.excepthook(typ, value, tb)
157-
except SystemExit:
158-
raise
159-
except BaseException as e:
160-
e.__context__ = None
161-
print('Error in sys.excepthook:', file=sys.stderr)
162-
sys.__excepthook__(type(e), e, e.__traceback__.tb_next)
163-
print(file=sys.stderr)
164-
print('Original exception was:', file=sys.stderr)
165-
sys.__excepthook__(typ, value, tb)
138+
def _showtraceback(self, typ, value, tb):
139+
sys.last_type = typ
140+
sys.last_traceback = tb
141+
sys.last_exc = sys.last_value = value = value.with_traceback(tb)
142+
if sys.excepthook is sys.__excepthook__:
143+
lines = traceback.format_exception(typ, value, tb)
144+
self.write(''.join(lines))
145+
else:
146+
# If someone has set sys.excepthook, we let that take precedence
147+
# over self.write
148+
try:
149+
sys.excepthook(typ, value, tb)
150+
except SystemExit:
151+
raise
152+
except BaseException as e:
153+
e.__context__ = None
154+
e = e.with_traceback(e.__traceback__.tb_next)
155+
print('Error in sys.excepthook:', file=sys.stderr)
156+
sys.__excepthook__(type(e), e, e.__traceback__)
157+
print(file=sys.stderr)
158+
print('Original exception was:', file=sys.stderr)
159+
sys.__excepthook__(typ, value, tb)
166160

167161
def write(self, data):
168162
"""Write a string.

PythonLib/full/email/utils.py

Lines changed: 142 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
specialsre = re.compile(r'[][\\()<>@,:;".]')
4949
escapesre = re.compile(r'[\\"]')
5050

51+
5152
def _has_surrogates(s):
5253
"""Return True if s may contain surrogate-escaped binary data."""
5354
# This check is based on the fact that unless there are surrogates, utf8
@@ -106,12 +107,127 @@ def formataddr(pair, charset='utf-8'):
106107
return address
107108

108109

110+
def _iter_escaped_chars(addr):
111+
pos = 0
112+
escape = False
113+
for pos, ch in enumerate(addr):
114+
if escape:
115+
yield (pos, '\\' + ch)
116+
escape = False
117+
elif ch == '\\':
118+
escape = True
119+
else:
120+
yield (pos, ch)
121+
if escape:
122+
yield (pos, '\\')
123+
124+
125+
def _strip_quoted_realnames(addr):
126+
"""Strip real names between quotes."""
127+
if '"' not in addr:
128+
# Fast path
129+
return addr
130+
131+
start = 0
132+
open_pos = None
133+
result = []
134+
for pos, ch in _iter_escaped_chars(addr):
135+
if ch == '"':
136+
if open_pos is None:
137+
open_pos = pos
138+
else:
139+
if start != open_pos:
140+
result.append(addr[start:open_pos])
141+
start = pos + 1
142+
open_pos = None
143+
144+
if start < len(addr):
145+
result.append(addr[start:])
146+
147+
return ''.join(result)
109148

110-
def getaddresses(fieldvalues):
111-
"""Return a list of (REALNAME, EMAIL) for each fieldvalue."""
112-
all = COMMASPACE.join(str(v) for v in fieldvalues)
113-
a = _AddressList(all)
114-
return a.addresslist
149+
150+
supports_strict_parsing = True
151+
152+
def getaddresses(fieldvalues, *, strict=True):
153+
"""Return a list of (REALNAME, EMAIL) or ('','') for each fieldvalue.
154+
155+
When parsing fails for a fieldvalue, a 2-tuple of ('', '') is returned in
156+
its place.
157+
158+
If strict is true, use a strict parser which rejects malformed inputs.
159+
"""
160+
161+
# If strict is true, if the resulting list of parsed addresses is greater
162+
# than the number of fieldvalues in the input list, a parsing error has
163+
# occurred and consequently a list containing a single empty 2-tuple [('',
164+
# '')] is returned in its place. This is done to avoid invalid output.
165+
#
166+
# Malformed input: getaddresses(['alice@example.com <bob@example.com>'])
167+
# Invalid output: [('', 'alice@example.com'), ('', 'bob@example.com')]
168+
# Safe output: [('', '')]
169+
170+
if not strict:
171+
all = COMMASPACE.join(str(v) for v in fieldvalues)
172+
a = _AddressList(all)
173+
return a.addresslist
174+
175+
fieldvalues = [str(v) for v in fieldvalues]
176+
fieldvalues = _pre_parse_validation(fieldvalues)
177+
addr = COMMASPACE.join(fieldvalues)
178+
a = _AddressList(addr)
179+
result = _post_parse_validation(a.addresslist)
180+
181+
# Treat output as invalid if the number of addresses is not equal to the
182+
# expected number of addresses.
183+
n = 0
184+
for v in fieldvalues:
185+
# When a comma is used in the Real Name part it is not a deliminator.
186+
# So strip those out before counting the commas.
187+
v = _strip_quoted_realnames(v)
188+
# Expected number of addresses: 1 + number of commas
189+
n += 1 + v.count(',')
190+
if len(result) != n:
191+
return [('', '')]
192+
193+
return result
194+
195+
196+
def _check_parenthesis(addr):
197+
# Ignore parenthesis in quoted real names.
198+
addr = _strip_quoted_realnames(addr)
199+
200+
opens = 0
201+
for pos, ch in _iter_escaped_chars(addr):
202+
if ch == '(':
203+
opens += 1
204+
elif ch == ')':
205+
opens -= 1
206+
if opens < 0:
207+
return False
208+
return (opens == 0)
209+
210+
211+
def _pre_parse_validation(email_header_fields):
212+
accepted_values = []
213+
for v in email_header_fields:
214+
if not _check_parenthesis(v):
215+
v = "('', '')"
216+
accepted_values.append(v)
217+
218+
return accepted_values
219+
220+
221+
def _post_parse_validation(parsed_email_header_tuples):
222+
accepted_values = []
223+
# The parser would have parsed a correctly formatted domain-literal
224+
# The existence of an [ after parsing indicates a parsing failure
225+
for v in parsed_email_header_tuples:
226+
if '[' in v[1]:
227+
v = ('', '')
228+
accepted_values.append(v)
229+
230+
return accepted_values
115231

116232

117233
def _format_timetuple_and_zone(timetuple, zone):
@@ -205,16 +321,33 @@ def parsedate_to_datetime(data):
205321
tzinfo=datetime.timezone(datetime.timedelta(seconds=tz)))
206322

207323

208-
def parseaddr(addr):
324+
def parseaddr(addr, *, strict=True):
209325
"""
210326
Parse addr into its constituent realname and email address parts.
211327
212328
Return a tuple of realname and email address, unless the parse fails, in
213329
which case return a 2-tuple of ('', '').
330+
331+
If strict is True, use a strict parser which rejects malformed inputs.
214332
"""
215-
addrs = _AddressList(addr).addresslist
216-
if not addrs:
217-
return '', ''
333+
if not strict:
334+
addrs = _AddressList(addr).addresslist
335+
if not addrs:
336+
return ('', '')
337+
return addrs[0]
338+
339+
if isinstance(addr, list):
340+
addr = addr[0]
341+
342+
if not isinstance(addr, str):
343+
return ('', '')
344+
345+
addr = _pre_parse_validation([addr])[0]
346+
addrs = _post_parse_validation(_AddressList(addr).addresslist)
347+
348+
if not addrs or len(addrs) > 1:
349+
return ('', '')
350+
218351
return addrs[0]
219352

220353

PythonLib/full/http/cookies.py

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,13 @@ def _quote(str):
184184
return '"' + str.translate(_Translator) + '"'
185185

186186

187-
_OctalPatt = re.compile(r"\\[0-3][0-7][0-7]")
188-
_QuotePatt = re.compile(r"[\\].")
187+
_unquote_sub = re.compile(r'\\(?:([0-3][0-7][0-7])|(.))').sub
188+
189+
def _unquote_replace(m):
190+
if m[1]:
191+
return chr(int(m[1], 8))
192+
else:
193+
return m[2]
189194

190195
def _unquote(str):
191196
# If there aren't any doublequotes,
@@ -205,30 +210,7 @@ def _unquote(str):
205210
# \012 --> \n
206211
# \" --> "
207212
#
208-
i = 0
209-
n = len(str)
210-
res = []
211-
while 0 <= i < n:
212-
o_match = _OctalPatt.search(str, i)
213-
q_match = _QuotePatt.search(str, i)
214-
if not o_match and not q_match: # Neither matched
215-
res.append(str[i:])
216-
break
217-
# else:
218-
j = k = -1
219-
if o_match:
220-
j = o_match.start(0)
221-
if q_match:
222-
k = q_match.start(0)
223-
if q_match and (not o_match or k < j): # QuotePatt matched
224-
res.append(str[i:k])
225-
res.append(str[k+1])
226-
i = k + 2
227-
else: # OctalPatt matched
228-
res.append(str[i:j])
229-
res.append(chr(int(str[j+1:j+4], 8)))
230-
i = j + 4
231-
return _nulljoin(res)
213+
return _unquote_sub(_unquote_replace, str)
232214

233215
# The _getdate() routine is used to set the expiration time in the cookie's HTTP
234216
# header. By default, _getdate() returns the current time in the appropriate

0 commit comments

Comments
 (0)