Skip to content

Commit d98015f

Browse files
authored
Merge branch 'main' into narrowing-to-constants-in-branches-with-is
2 parents d0f799f + f84ea11 commit d98015f

27 files changed

+216
-143
lines changed

Doc/library/stdtypes.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2562,6 +2562,19 @@ expression support in the :mod:`re` module).
25622562
after the separator. If the separator is not found, return a 3-tuple containing
25632563
two empty strings, followed by the string itself.
25642564

2565+
For example:
2566+
2567+
.. doctest::
2568+
2569+
>>> 'Monty Python'.rpartition(' ')
2570+
('Monty', ' ', 'Python')
2571+
>>> "Monty Python's Flying Circus".rpartition(' ')
2572+
("Monty Python's Flying", ' ', 'Circus')
2573+
>>> 'Monty Python'.rpartition('-')
2574+
('', '', 'Monty Python')
2575+
2576+
See also :meth:`partition`.
2577+
25652578

25662579
.. method:: str.rsplit(sep=None, maxsplit=-1)
25672580

Doc/library/tkinter.rst

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,12 @@ the modern themed widget set and API::
177177
.. attribute:: master
178178

179179
The widget object that contains this widget. For :class:`Tk`, the
180-
*master* is :const:`None` because it is the main window. The terms
180+
:attr:`!master` is :const:`None` because it is the main window. The terms
181181
*master* and *parent* are similar and sometimes used interchangeably
182182
as argument names; however, calling :meth:`winfo_parent` returns a
183-
string of the widget name whereas :attr:`master` returns the object.
183+
string of the widget name whereas :attr:`!master` returns the object.
184184
*parent*/*child* reflects the tree-like relationship while
185-
*master*/*slave* reflects the container structure.
185+
*master* (or *container*)/*content* reflects the container structure.
186186

187187
.. attribute:: children
188188

@@ -638,15 +638,15 @@ The Packer
638638
.. index:: single: packing (widgets)
639639

640640
The packer is one of Tk's geometry-management mechanisms. Geometry managers
641-
are used to specify the relative positioning of widgets within their container -
642-
their mutual *master*. In contrast to the more cumbersome *placer* (which is
641+
are used to specify the relative positioning of widgets within their container.
642+
In contrast to the more cumbersome *placer* (which is
643643
used less commonly, and we do not cover here), the packer takes qualitative
644644
relationship specification - *above*, *to the left of*, *filling*, etc - and
645645
works everything out to determine the exact placement coordinates for you.
646646

647-
The size of any *master* widget is determined by the size of the "slave widgets"
648-
inside. The packer is used to control where slave widgets appear inside the
649-
master into which they are packed. You can pack widgets into frames, and frames
647+
The size of any container widget is determined by the size of the "content widgets"
648+
inside. The packer is used to control where content widgets appear inside the
649+
container into which they are packed. You can pack widgets into frames, and frames
650650
into other frames, in order to achieve the kind of layout you desire.
651651
Additionally, the arrangement is dynamically adjusted to accommodate incremental
652652
changes to the configuration, once it is packed.
@@ -673,7 +673,7 @@ For more extensive information on the packer and the options that it can take,
673673
see the man pages and page 183 of John Ousterhout's book.
674674

675675
anchor
676-
Anchor type. Denotes where the packer is to place each slave in its parcel.
676+
Anchor type. Denotes where the packer is to place each content in its parcel.
677677

678678
expand
679679
Boolean, ``0`` or ``1``.
@@ -682,10 +682,10 @@ fill
682682
Legal values: ``'x'``, ``'y'``, ``'both'``, ``'none'``.
683683

684684
ipadx and ipady
685-
A distance - designating internal padding on each side of the slave widget.
685+
A distance - designating internal padding on each side of the content.
686686

687687
padx and pady
688-
A distance - designating external padding on each side of the slave widget.
688+
A distance - designating external padding on each side of the content.
689689

690690
side
691691
Legal values are: ``'left'``, ``'right'``, ``'top'``, ``'bottom'``.
@@ -758,8 +758,8 @@ subclassed from the :class:`Wm` class, and so can call the :class:`Wm` methods
758758
directly.
759759

760760
To get at the toplevel window that contains a given widget, you can often just
761-
refer to the widget's master. Of course if the widget has been packed inside of
762-
a frame, the master won't represent a toplevel window. To get at the toplevel
761+
refer to the widget's :attr:`master`. Of course if the widget has been packed inside of
762+
a frame, the :attr:`!master` won't represent a toplevel window. To get at the toplevel
763763
window that contains an arbitrary widget, you can call the :meth:`_root` method.
764764
This method begins with an underscore to denote the fact that this function is
765765
part of the implementation, and not an interface to Tk functionality.

Lib/email/_header_value_parser.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ def make_quoted_pairs(value):
101101
return str(value).replace('\\', '\\\\').replace('"', '\\"')
102102

103103

104+
def make_parenthesis_pairs(value):
105+
"""Escape parenthesis and backslash for use within a comment."""
106+
return str(value).replace('\\', '\\\\') \
107+
.replace('(', '\\(').replace(')', '\\)')
108+
109+
104110
def quote_string(value):
105111
escaped = make_quoted_pairs(value)
106112
return f'"{escaped}"'
@@ -943,7 +949,7 @@ def value(self):
943949
return ' '
944950

945951
def startswith_fws(self):
946-
return True
952+
return self and self[0] in WSP
947953

948954

949955
class ValueTerminal(Terminal):
@@ -2963,6 +2969,13 @@ def _refold_parse_tree(parse_tree, *, policy):
29632969
[ValueTerminal(make_quoted_pairs(p), 'ptext')
29642970
for p in newparts] +
29652971
[ValueTerminal('"', 'ptext')])
2972+
if part.token_type == 'comment':
2973+
newparts = (
2974+
[ValueTerminal('(', 'ptext')] +
2975+
[ValueTerminal(make_parenthesis_pairs(p), 'ptext')
2976+
if p.token_type == 'ptext' else p
2977+
for p in newparts] +
2978+
[ValueTerminal(')', 'ptext')])
29662979
if not part.as_ew_allowed:
29672980
wrap_as_ew_blocked += 1
29682981
newparts.append(end_ew_not_allowed)

Lib/test/test_email/test__header_value_parser.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3294,6 +3294,29 @@ def test_address_list_with_specials_in_long_quoted_string(self):
32943294
with self.subTest(to=to):
32953295
self._test(parser.get_address_list(to)[0], folded, policy=policy)
32963296

3297+
def test_address_list_with_long_unwrapable_comment(self):
3298+
policy = self.policy.clone(max_line_length=40)
3299+
cases = [
3300+
# (to, folded)
3301+
('(loremipsumdolorsitametconsecteturadipi)<spy@example.org>',
3302+
'(loremipsumdolorsitametconsecteturadipi)<spy@example.org>\n'),
3303+
('<spy@example.org>(loremipsumdolorsitametconsecteturadipi)',
3304+
'<spy@example.org>(loremipsumdolorsitametconsecteturadipi)\n'),
3305+
('(loremipsum dolorsitametconsecteturadipi)<spy@example.org>',
3306+
'(loremipsum dolorsitametconsecteturadipi)<spy@example.org>\n'),
3307+
('<spy@example.org>(loremipsum dolorsitametconsecteturadipi)',
3308+
'<spy@example.org>(loremipsum\n dolorsitametconsecteturadipi)\n'),
3309+
('(Escaped \\( \\) chars \\\\ in comments stay escaped)<spy@example.org>',
3310+
'(Escaped \\( \\) chars \\\\ in comments stay\n escaped)<spy@example.org>\n'),
3311+
('((loremipsum)(loremipsum)(loremipsum)(loremipsum))<spy@example.org>',
3312+
'((loremipsum)(loremipsum)(loremipsum)(loremipsum))<spy@example.org>\n'),
3313+
('((loremipsum)(loremipsum)(loremipsum) (loremipsum))<spy@example.org>',
3314+
'((loremipsum)(loremipsum)(loremipsum)\n (loremipsum))<spy@example.org>\n'),
3315+
]
3316+
for (to, folded) in cases:
3317+
with self.subTest(to=to):
3318+
self._test(parser.get_address_list(to)[0], folded, policy=policy)
3319+
32973320
# XXX Need tests with comments on various sides of a unicode token,
32983321
# and with unicode tokens in the comments. Spaces inside the quotes
32993322
# currently don't do the right thing.

Lib/test/test_io/test_bufferedio.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from collections import deque, UserList
1111
from itertools import cycle, count
1212
from test import support
13-
from test.support import os_helper, threading_helper
13+
from test.support import check_sanitizer, os_helper, threading_helper
1414
from .utils import byteslike, CTestCase, PyTestCase
1515

1616

@@ -623,6 +623,25 @@ def test_bad_readinto_type(self):
623623
bufio.readline()
624624
self.assertIsInstance(cm.exception.__cause__, TypeError)
625625

626+
@unittest.skipUnless(sys.maxsize > 2**32, 'requires 64bit platform')
627+
@unittest.skipIf(check_sanitizer(thread=True),
628+
'ThreadSanitizer aborts on huge allocations (exit code 66).')
629+
def test_read1_error_does_not_cause_reentrant_failure(self):
630+
self.addCleanup(os_helper.unlink, os_helper.TESTFN)
631+
with self.open(os_helper.TESTFN, "wb") as f:
632+
f.write(b"hello")
633+
634+
with self.open(os_helper.TESTFN, "rb", buffering=0) as raw:
635+
bufio = self.tp(raw, buffer_size=8)
636+
# To request a size that is far too huge to ever be satisfied,
637+
# so that the internal buffer allocation reliably fails with MemoryError.
638+
huge = sys.maxsize // 2 + 1
639+
with self.assertRaises(MemoryError):
640+
bufio.read1(huge)
641+
642+
# Used to crash before gh-143689:
643+
self.assertEqual(bufio.read1(1), b"h")
644+
626645

627646
class PyBufferedReaderTest(BufferedReaderTest, PyTestCase):
628647
tp = pyio.BufferedReader

Lib/test/test_pathlib/test_write.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,17 @@ def test_open_wb(self):
6565

6666
def test_write_bytes(self):
6767
p = self.root / 'fileA'
68-
p.write_bytes(b'abcdefg')
69-
self.assertEqual(self.ground.readbytes(p), b'abcdefg')
68+
data = b'abcdefg'
69+
self.assertEqual(len(data), p.write_bytes(data))
70+
self.assertEqual(self.ground.readbytes(p), data)
7071
# Check that trying to write str does not truncate the file.
7172
self.assertRaises(TypeError, p.write_bytes, 'somestr')
72-
self.assertEqual(self.ground.readbytes(p), b'abcdefg')
73+
self.assertEqual(self.ground.readbytes(p), data)
7374

7475
def test_write_text(self):
7576
p = self.root / 'fileA'
76-
p.write_text('äbcdefg', encoding='latin-1')
77+
data = 'äbcdefg'
78+
self.assertEqual(len(data), p.write_text(data, encoding='latin-1'))
7779
self.assertEqual(self.ground.readbytes(p), b'\xe4bcdefg')
7880
# Check that trying to write bytes does not truncate the file.
7981
self.assertRaises(TypeError, p.write_text, b'somebytes', encoding='utf-8')

Lib/test/test_unicodedata.py

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,7 @@ def test_method_checksum(self):
8383
self.assertEqual(result, self.expectedchecksum)
8484

8585

86-
class UnicodeFunctionsTest(unittest.TestCase):
87-
db = unicodedata
88-
old = False
89-
90-
# Update this if the database changes. Make sure to do a full rebuild
91-
# (e.g. 'make distclean && make') to get the correct checksum.
92-
expectedchecksum = ('83cc43a2fbb779185832b4c049217d80b05bf349'
93-
if quicktest else
94-
'65670ae03a324c5f9e826a4de3e25bae4d73c9b7')
86+
class BaseUnicodeFunctionsTest:
9587

9688
def test_function_checksum(self):
9789
db = self.db
@@ -589,6 +581,16 @@ def test_east_asian_width_unassigned(self):
589581
self.assertEqual(eaw(char), 'A')
590582
self.assertIs(self.db.name(char, None), None)
591583

584+
class UnicodeFunctionsTest(unittest.TestCase, BaseUnicodeFunctionsTest):
585+
db = unicodedata
586+
old = False
587+
588+
# Update this if the database changes. Make sure to do a full rebuild
589+
# (e.g. 'make distclean && make') to get the correct checksum.
590+
expectedchecksum = ('83cc43a2fbb779185832b4c049217d80b05bf349'
591+
if quicktest else
592+
'65670ae03a324c5f9e826a4de3e25bae4d73c9b7')
593+
592594
def test_isxidstart(self):
593595
self.assertTrue(self.db.isxidstart('S'))
594596
self.assertTrue(self.db.isxidstart('\u0AD0')) # GUJARATI OM
@@ -832,18 +834,13 @@ def graphemes(*args):
832834
['a', '\U0001F1FA\U0001F1E6', '\U0001F1FA\U0001F1F3'])
833835

834836

835-
class Unicode_3_2_0_FunctionsTest(UnicodeFunctionsTest):
837+
class Unicode_3_2_0_FunctionsTest(unittest.TestCase, BaseUnicodeFunctionsTest):
836838
db = unicodedata.ucd_3_2_0
837839
old = True
838840
expectedchecksum = ('f4526159891a4b766dd48045646547178737ba09'
839841
if quicktest else
840842
'f217b8688d7bdff31db4207e078a96702f091597')
841843

842-
test_grapheme_cluster_break = None
843-
test_indic_conjunct_break = None
844-
test_extended_pictographic = None
845-
test_grapheme_break = None
846-
847844

848845
class UnicodeMiscTest(unittest.TestCase):
849846
db = unicodedata

0 commit comments

Comments
 (0)