Skip to content

Commit 7553e10

Browse files
authored
Merge branch 'main' into specialize-for-iter-range
2 parents 7ba5753 + 1adca08 commit 7553e10

File tree

18 files changed

+379
-355
lines changed

18 files changed

+379
-355
lines changed

Doc/c-api/arg.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,7 @@ Building values
685685
686686
``p`` (:class:`bool`) [int]
687687
Convert a C :c:expr:`int` to a Python :class:`bool` object.
688+
688689
.. versionadded:: 3.14
689690
690691
``c`` (:class:`bytes` of length 1) [char]

Doc/c-api/unicode.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,22 @@ access to internal read-only data of Unicode objects:
191191
.. versionadded:: 3.2
192192
193193
194+
.. c:function:: Py_hash_t PyUnstable_Unicode_GET_CACHED_HASH(PyObject *str)
195+
196+
If the hash of *str*, as returned by :c:func:`PyObject_Hash`, has been
197+
cached and is immediately available, return it.
198+
Otherwise, return ``-1`` *without* setting an exception.
199+
200+
If *str* is not a string (that is, if ``PyUnicode_Check(obj)``
201+
is false), the behavior is undefined.
202+
203+
This function never fails with an exception.
204+
205+
Note that there are no guarantees on when an object's hash is cached,
206+
and the (non-)existence of a cached hash does not imply that the string has
207+
any other properties.
208+
209+
194210
Unicode Character Properties
195211
""""""""""""""""""""""""""""
196212

Doc/tutorial/modules.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,16 @@ called :file:`fibo.py` in the current directory with the following contents::
2727

2828
# Fibonacci numbers module
2929

30-
def fib(n): # write Fibonacci series up to n
30+
def fib(n):
31+
"""Write Fibonacci series up to n."""
3132
a, b = 0, 1
3233
while a < n:
3334
print(a, end=' ')
3435
a, b = b, a+b
3536
print()
3637

37-
def fib2(n): # return Fibonacci series up to n
38+
def fib2(n):
39+
"""Return Fibonacci series up to n."""
3840
result = []
3941
a, b = 0, 1
4042
while a < n:

Doc/whatsnew/3.15.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,10 @@ New features
304304
input string contains non-ASCII characters.
305305
(Contributed by Victor Stinner in :gh:`133968`.)
306306

307+
* Add :c:type:`PyUnstable_Unicode_GET_CACHED_HASH` to get the cached hash of
308+
a string. See the documentation for caveats.
309+
(Contributed by Petr Viktorin in :gh:`131510`)
310+
307311

308312
Porting to Python 3.15
309313
----------------------

Include/cpython/unicodeobject.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,17 @@ static inline Py_ssize_t PyUnicode_GET_LENGTH(PyObject *op) {
300300
}
301301
#define PyUnicode_GET_LENGTH(op) PyUnicode_GET_LENGTH(_PyObject_CAST(op))
302302

303+
/* Returns the cached hash, or -1 if not cached yet. */
304+
static inline Py_hash_t
305+
PyUnstable_Unicode_GET_CACHED_HASH(PyObject *op) {
306+
assert(PyUnicode_Check(op));
307+
#ifdef Py_GIL_DISABLED
308+
return _Py_atomic_load_ssize_relaxed(&_PyASCIIObject_CAST(op)->hash);
309+
#else
310+
return _PyASCIIObject_CAST(op)->hash;
311+
#endif
312+
}
313+
303314
/* Write into the canonical representation, this function does not do any sanity
304315
checks and is intended for usage in loops. The caller should cache the
305316
kind and data pointers obtained from other function calls.

Lib/os.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ def _add(str, fn):
118118
_add("HAVE_FCHMODAT", "chmod")
119119
_add("HAVE_FCHOWNAT", "chown")
120120
_add("HAVE_FSTATAT", "stat")
121+
_add("HAVE_LSTAT", "lstat")
121122
_add("HAVE_FUTIMESAT", "utime")
122123
_add("HAVE_LINKAT", "link")
123124
_add("HAVE_MKDIRAT", "mkdir")

Lib/test/support/__init__.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,31 @@ def check_sizeof(test, o, size):
945945
% (type(o), result, size)
946946
test.assertEqual(result, size, msg)
947947

948+
def subTests(arg_names, arg_values, /, *, _do_cleanups=False):
949+
"""Run multiple subtests with different parameters.
950+
"""
951+
single_param = False
952+
if isinstance(arg_names, str):
953+
arg_names = arg_names.replace(',',' ').split()
954+
if len(arg_names) == 1:
955+
single_param = True
956+
arg_values = tuple(arg_values)
957+
def decorator(func):
958+
if isinstance(func, type):
959+
raise TypeError('subTests() can only decorate methods, not classes')
960+
@functools.wraps(func)
961+
def wrapper(self, /, *args, **kwargs):
962+
for values in arg_values:
963+
if single_param:
964+
values = (values,)
965+
subtest_kwargs = dict(zip(arg_names, values))
966+
with self.subTest(**subtest_kwargs):
967+
func(self, *args, **kwargs, **subtest_kwargs)
968+
if _do_cleanups:
969+
self.doCleanups()
970+
return wrapper
971+
return decorator
972+
948973
#=======================================================================
949974
# Decorator/context manager for running a code in a different locale,
950975
# correctly resetting it afterwards.

Lib/test/test_capi/test_unicode.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,6 +1739,20 @@ def test_pep393_utf8_caching_bug(self):
17391739
# Check that the second call returns the same result
17401740
self.assertEqual(getargs_s_hash(s), chr(k).encode() * (i + 1))
17411741

1742+
@support.cpython_only
1743+
@unittest.skipIf(_testcapi is None, 'need _testcapi module')
1744+
def test_GET_CACHED_HASH(self):
1745+
from _testcapi import unicode_GET_CACHED_HASH
1746+
content_bytes = b'some new string'
1747+
# avoid parser interning & constant folding
1748+
obj = str(content_bytes, 'ascii')
1749+
# impl detail: fresh strings do not have cached hash
1750+
self.assertEqual(unicode_GET_CACHED_HASH(obj), -1)
1751+
# impl detail: adding string to a dict caches its hash
1752+
{obj: obj}
1753+
# impl detail: ASCII string hashes are equal to bytes ones
1754+
self.assertEqual(unicode_GET_CACHED_HASH(obj), hash(content_bytes))
1755+
17421756

17431757
class PyUnicodeWriterTest(unittest.TestCase):
17441758
def create_writer(self, size):

0 commit comments

Comments
 (0)