https://github.com/python/cpython/commit/1259f1602f870185a4980c80c525e110c4b9c614
commit: 1259f1602f870185a4980c80c525e110c4b9c614
branch: main
author: Gregory P. Smith <[email protected]>
committer: gpshead <[email protected]>
date: 2026-10-31T05:57:17-07:00
summary:

gh-160518: Fix hz encoder dropping half of the ~~ escape (GH-160519)

Write both bytes of the escape before consuming the input character, so
that a retry after the output buffer is enlarged starts at the tilde.

files:
A Misc/NEWS.d/next/Library/2026-10-22-08-15-57.gh-issue-160518.hZt1Ld.rst
M Lib/test/test_codecencodings_cn.py

diff --git a/Lib/test/test_codecencodings_cn.py 
b/Lib/test/test_codecencodings_cn.py
index 2a450718d5aae5..35a2d7fb1ebf29 100644
--- a/Lib/test/test_codecencodings_cn.py
+++ b/Lib/test/test_codecencodings_cn.py
@@ -92,5 +92,15 @@ class Test_HZ(multibytecodec_support.TestBase, 
unittest.TestCase):
         (b'~{Dc~\n:C~}', 'strict', None), # ~\n only in ASCII mode
     )
 
+    def test_escape_at_buffer_boundary(self):
+        # '~~' must not be cut in two when the output buffer is enlarged.
+        for pairs in range(40):
+            for letters in range(3):
+                text = 'a\u4e2d' * pairs + 'x' * letters + '~{'
+                with self.subTest(pairs=pairs, letters=letters):
+                    encoded = text.encode('hz')
+                    self.assertEndsWith(encoded, b'~~{')
+                    self.assertEqual(encoded.decode('hz'), text)
+
 if __name__ == "__main__":
     unittest.main()
diff --git 
a/Misc/NEWS.d/next/Library/2026-10-22-08-15-57.gh-issue-160518.hZt1Ld.rst 
b/Misc/NEWS.d/next/Library/2026-10-22-08-15-57.gh-issue-160518.hZt1Ld.rst
new file mode 100644
index 00000000000000..3a3c6805ec82ae
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-10-22-08-15-57.gh-issue-160518.hZt1Ld.rst
@@ -0,0 +1,3 @@
+Fix the ``hz`` codec sometimes encoding ``~`` as a single ``~`` instead of
+``~~`` in text that mixes ASCII and Chinese characters, which produced data
+that did not decode back to the original text.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to