|
5 | 5 | """ |
6 | 6 |
|
7 | 7 | import array |
| 8 | +import codecs |
| 9 | +import copy |
| 10 | +import functools |
8 | 11 | import operator |
9 | 12 | import os |
| 13 | +import pickle |
10 | 14 | import re |
11 | 15 | import sys |
12 | | -import copy |
13 | | -import functools |
14 | | -import pickle |
15 | 16 | import tempfile |
16 | 17 | import textwrap |
17 | 18 | import threading |
@@ -1654,6 +1655,29 @@ def test_take_bytes_optimization(self): |
1654 | 1655 | bytes_header_size = sys.getsizeof(b'') |
1655 | 1656 | self.assertEqual(ba.__alloc__(), 499 + bytes_header_size) |
1656 | 1657 |
|
| 1658 | + def test_take_bytes_hash(self): |
| 1659 | + # gh-158219: bytearray constructor must not use a bytes object |
| 1660 | + # if its hash value is already cached. |
| 1661 | + |
| 1662 | + def encode(string, errors='strict'): |
| 1663 | + encoded = string.encode('utf-8') |
| 1664 | + hash(encoded) # a codec may hash its own output |
| 1665 | + return encoded, len(string) |
| 1666 | + |
| 1667 | + def hashing_codec(name): |
| 1668 | + if name != 'test_take_bytes_hash': |
| 1669 | + return None |
| 1670 | + return codecs.CodecInfo(encode, None, name=name) |
| 1671 | + |
| 1672 | + codecs.register(hashing_codec) |
| 1673 | + self.addCleanup(codecs.unregister, hashing_codec) |
| 1674 | + |
| 1675 | + ba = bytearray('hello', 'test_take_bytes_hash') |
| 1676 | + ba[0] = ord('H') |
| 1677 | + taken = ba.take_bytes() |
| 1678 | + self.assertEqual(taken, b'Hello') |
| 1679 | + self.assertEqual(hash(taken), hash(b'Hello')) |
| 1680 | + |
1657 | 1681 | def test_take_bytes_reentrant_resize(self): |
1658 | 1682 | # gh-153570: n.__index__() can resize the bytearray, so take_bytes() |
1659 | 1683 | # must re-read the size afterwards. It cached the size before the |
|
0 commit comments