Skip to content

Commit e12cb28

Browse files
Merge branch 'main' into ssl-bugfix-116810
2 parents c98be51 + 126910e commit e12cb28

25 files changed

+668
-293
lines changed

Doc/library/xml.etree.elementtree.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -971,7 +971,7 @@ Element Objects
971971

972972
.. method:: extend(subelements)
973973

974-
Appends *subelements* from a sequence object with zero or more elements.
974+
Appends *subelements* from an iterable of elements.
975975
Raises :exc:`TypeError` if a subelement is not an :class:`Element`.
976976

977977
.. versionadded:: 3.2

Include/internal/pycore_opcode_metadata.h

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/opcode_ids.h

Lines changed: 32 additions & 31 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/_opcode_metadata.py

Lines changed: 33 additions & 31 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/_pydatetime.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,17 @@ def _need_normalize_century():
215215
_normalize_century = True
216216
return _normalize_century
217217

218+
_supports_c99 = None
219+
def _can_support_c99():
220+
global _supports_c99
221+
if _supports_c99 is None:
222+
try:
223+
_supports_c99 = (
224+
_time.strftime("%F", (1900, 1, 1, 0, 0, 0, 0, 1, 0)) == "1900-01-01")
225+
except ValueError:
226+
_supports_c99 = False
227+
return _supports_c99
228+
218229
# Correctly substitute for %z and %Z escapes in strftime formats.
219230
def _wrap_strftime(object, format, timetuple):
220231
# Don't call utcoffset() or tzname() unless actually needed.
@@ -272,14 +283,20 @@ def _wrap_strftime(object, format, timetuple):
272283
# strftime is going to have at this: escape %
273284
Zreplace = s.replace('%', '%%')
274285
newformat.append(Zreplace)
275-
elif ch in 'YG' and object.year < 1000 and _need_normalize_century():
276-
# Note that datetime(1000, 1, 1).strftime('%G') == '1000' so
277-
# year 1000 for %G can go on the fast path.
286+
# Note that datetime(1000, 1, 1).strftime('%G') == '1000' so
287+
# year 1000 for %G can go on the fast path.
288+
elif ((ch in 'YG' or ch in 'FC' and _can_support_c99()) and
289+
object.year < 1000 and _need_normalize_century()):
278290
if ch == 'G':
279291
year = int(_time.strftime("%G", timetuple))
280292
else:
281293
year = object.year
282-
push('{:04}'.format(year))
294+
if ch == 'C':
295+
push('{:02}'.format(year // 100))
296+
else:
297+
push('{:04}'.format(year))
298+
if ch == 'F':
299+
push('-{:02}-{:02}'.format(*timetuple[1:3]))
283300
else:
284301
push('%')
285302
push(ch)

Lib/test/datetimetester.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1710,13 +1710,22 @@ def test_strftime_y2k(self):
17101710
(1000, 0),
17111711
(1970, 0),
17121712
)
1713-
for year, offset in dataset:
1714-
for specifier in 'YG':
1713+
specifiers = 'YG'
1714+
if _time.strftime('%F', (1900, 1, 1, 0, 0, 0, 0, 1, 0)) == '1900-01-01':
1715+
specifiers += 'FC'
1716+
for year, g_offset in dataset:
1717+
for specifier in specifiers:
17151718
with self.subTest(year=year, specifier=specifier):
17161719
d = self.theclass(year, 1, 1)
17171720
if specifier == 'G':
1718-
year += offset
1719-
self.assertEqual(d.strftime(f"%{specifier}"), f"{year:04d}")
1721+
year += g_offset
1722+
if specifier == 'C':
1723+
expected = f"{year // 100:02d}"
1724+
else:
1725+
expected = f"{year:04d}"
1726+
if specifier == 'F':
1727+
expected += f"-01-01"
1728+
self.assertEqual(d.strftime(f"%{specifier}"), expected)
17201729

17211730
def test_replace(self):
17221731
cls = self.theclass

Lib/test/test_xml_etree.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2423,6 +2423,22 @@ def test_39495_treebuilder_start(self):
24232423
self.assertRaises(TypeError, ET.TreeBuilder().start, "tag")
24242424
self.assertRaises(TypeError, ET.TreeBuilder().start, "tag", None)
24252425

2426+
def test_issue123213_correct_extend_exception(self):
2427+
# Does not hide the internal exception when extending the element
2428+
self.assertRaises(ZeroDivisionError, ET.Element('tag').extend,
2429+
(1/0 for i in range(2)))
2430+
2431+
# Still raises the TypeError when extending with a non-iterable
2432+
self.assertRaises(TypeError, ET.Element('tag').extend, None)
2433+
2434+
# Preserves the TypeError message when extending with a generator
2435+
def f():
2436+
raise TypeError("mymessage")
2437+
2438+
self.assertRaisesRegex(
2439+
TypeError, 'mymessage',
2440+
ET.Element('tag').extend, (f() for i in range(2)))
2441+
24262442

24272443

24282444
# --------------------------------------------------------------------
@@ -3748,6 +3764,22 @@ def test_setslice_negative_steps(self):
37483764
e[1::-sys.maxsize<<64] = [ET.Element('d')]
37493765
self.assertEqual(self._subelem_tags(e), ['a0', 'd', 'a2', 'a3'])
37503766

3767+
def test_issue123213_setslice_exception(self):
3768+
e = ET.Element('tag')
3769+
# Does not hide the internal exception when assigning to the element
3770+
with self.assertRaises(ZeroDivisionError):
3771+
e[:1] = (1/0 for i in range(2))
3772+
3773+
# Still raises the TypeError when assigning with a non-iterable
3774+
with self.assertRaises(TypeError):
3775+
e[:1] = None
3776+
3777+
# Preserve the original TypeError message when assigning.
3778+
def f():
3779+
raise TypeError("mymessage")
3780+
3781+
with self.assertRaisesRegex(TypeError, 'mymessage'):
3782+
e[:1] = (f() for i in range(2))
37513783

37523784
class IOTest(unittest.TestCase):
37533785
def test_encoding(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix valgrind warning by initializing the f-string buffers to 0 in the
2+
tokenizer. Patch by Pablo Galindo
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Restore printout of GC stats when ``gc.set_debug(gc.DEBUG_STATS)`` is
2+
called. This featue was accidentally removed when implementing incremental
3+
GC.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
On some platforms such as Linux, year with century was not 0-padded when formatted by :meth:`~.datetime.strftime` with C99-specific specifiers ``'%C'`` or ``'%F'``. The 0-padding behavior is now guaranteed when the format specifiers ``'%C'`` and ``'%F'`` are supported by the C library.
2+
Patch by Ben Hsing

0 commit comments

Comments
 (0)