Skip to content

Commit 0923704

Browse files
StanFromIrelandyihong0618grayjk
authored
[3.13] gh-139246: zero-width word paste can be wrong in default repl (GH-139254) (GH-141166)
(cherry picked from commit 4e6dba0) Signed-off-by: yihong0618 <[email protected]> Co-authored-by: yihong <[email protected]> Co-authored-by: grayjk <[email protected]>
1 parent 353bfc8 commit 0923704

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

Lib/_pyrepl/utils.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@
1414
def str_width(c: str) -> int:
1515
if ord(c) < 128:
1616
return 1
17+
# gh-139246 for zero-width joiner and combining characters
18+
if unicodedata.combining(c):
19+
return 0
20+
category = unicodedata.category(c)
21+
if category == "Cf" and c != "\u00ad":
22+
return 0
1723
w = unicodedata.east_asian_width(c)
1824
if w in ("N", "Na", "H", "A"):
1925
return 1

Lib/test/test_pyrepl/test_utils.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,29 @@
55

66
class TestUtils(TestCase):
77
def test_str_width(self):
8-
characters = ['a', '1', '_', '!', '\x1a', '\u263A', '\uffb9']
8+
characters = [
9+
'a',
10+
'1',
11+
'_',
12+
'!',
13+
'\x1a',
14+
'\u263A',
15+
'\uffb9',
16+
'\N{LATIN SMALL LETTER E WITH ACUTE}', # é
17+
'\N{LATIN SMALL LETTER E WITH CEDILLA}', # ȩ
18+
'\u00ad',
19+
]
920
for c in characters:
1021
self.assertEqual(str_width(c), 1)
1122

23+
zero_width_characters = [
24+
'\N{COMBINING ACUTE ACCENT}',
25+
'\N{ZERO WIDTH JOINER}',
26+
]
27+
for c in zero_width_characters:
28+
with self.subTest(character=c):
29+
self.assertEqual(str_width(c), 0)
30+
1231
characters = [chr(99989), chr(99999)]
1332
for c in characters:
1433
self.assertEqual(str_width(c), 2)
@@ -25,3 +44,5 @@ def test_wlen(self):
2544

2645
self.assertEqual(wlen('hello'), 5)
2746
self.assertEqual(wlen('hello' + '\x1a'), 7)
47+
self.assertEqual(wlen('e\N{COMBINING ACUTE ACCENT}'), 1)
48+
self.assertEqual(wlen('a\N{ZERO WIDTH JOINER}b'), 2)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fix: paste zero-width in default repl width is wrong.

0 commit comments

Comments
 (0)