From 8f73b526cad425cd65287f53859e45a7ba79e575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 26 Apr 2025 12:59:53 +0200 Subject: [PATCH 1/6] expose `HASHLIB_GIL_MINSIZE` --- Modules/_hashopenssl.c | 11 +++++++++++ Modules/blake2module.c | 2 ++ Modules/hmacmodule.c | 17 +++++++++++++++++ Modules/md5module.c | 19 +++++++++++-------- Modules/sha1module.c | 27 +++++++++++++++++---------- Modules/sha2module.c | 7 +++++++ Modules/sha3module.c | 6 ++++-- 7 files changed, 69 insertions(+), 20 deletions(-) diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 756a8b70931baa..2dda213583f7a8 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -2358,6 +2358,16 @@ hashlib_exception(PyObject *module) return 0; } +static int +hashlib_constants(PyObject *module) +{ + if (PyModule_AddIntConstant(module, "GIL_MINSIZE", + HASHLIB_GIL_MINSIZE) < 0) + { + return -1; + } + return 0; +} static PyModuleDef_Slot hashlib_slots[] = { {Py_mod_exec, hashlib_init_hashtable}, @@ -2367,6 +2377,7 @@ static PyModuleDef_Slot hashlib_slots[] = { {Py_mod_exec, hashlib_md_meth_names}, {Py_mod_exec, hashlib_init_constructors}, {Py_mod_exec, hashlib_exception}, + {Py_mod_exec, hashlib_constants}, {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, {Py_mod_gil, Py_MOD_GIL_NOT_USED}, {0, NULL} diff --git a/Modules/blake2module.c b/Modules/blake2module.c index 0b0642c1e04e5a..a340c116477df7 100644 --- a/Modules/blake2module.c +++ b/Modules/blake2module.c @@ -229,6 +229,8 @@ blake2_exec(PyObject *m) // good a place as any to probe the CPU flags. detect_cpu_features(&st->flags); + ADD_INT_CONST("GIL_MINSIZE", HASHLIB_GIL_MINSIZE); + st->blake2b_type = (PyTypeObject *)PyType_FromModuleAndSpec( m, &blake2b_type_spec, NULL); diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index f75854c6ef5c91..5a57cbbc4fa15c 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -1679,6 +1679,20 @@ hmacmodule_init_strings(hmacmodule_state *state) return 0; } +static int +hmacmodule_init_globals(PyObject *module, hmacmodule_state *state) +{ +#define ADD_INT_CONST(NAME, VALUE) \ + do { \ + if (PyModule_AddIntConstant(module, (NAME), (VALUE)) < 0) { \ + return -1; \ + } \ + } while (0) + ADD_INT_CONST("GIL_MINSIZE", HASHLIB_GIL_MINSIZE); +#undef ADD_INT_CONST + return 0; +} + static void hmacmodule_init_cpu_features(hmacmodule_state *state) { @@ -1769,6 +1783,9 @@ hmacmodule_exec(PyObject *module) if (hmacmodule_init_strings(state) < 0) { return -1; } + if (hmacmodule_init_globals(module, state) < 0) { + return -1; + } hmacmodule_init_cpu_features(state); return 0; } diff --git a/Modules/md5module.c b/Modules/md5module.c index bb5107700235e4..32819ce4eff0c9 100644 --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -370,6 +370,9 @@ md5_exec(PyObject *m) if (PyModule_AddObjectRef(m, "MD5Type", (PyObject *)st->md5_type) < 0) { return -1; } + if (PyModule_AddIntConstant(m, "GIL_MINSIZE", HASHLIB_GIL_MINSIZE) < 0) { + return -1; + } return 0; } @@ -383,14 +386,14 @@ static PyModuleDef_Slot _md5_slots[] = { static struct PyModuleDef _md5module = { - PyModuleDef_HEAD_INIT, - .m_name = "_md5", - .m_size = sizeof(MD5State), - .m_methods = MD5_functions, - .m_slots = _md5_slots, - .m_traverse = _md5_traverse, - .m_clear = _md5_clear, - .m_free = _md5_free, + PyModuleDef_HEAD_INIT, + .m_name = "_md5", + .m_size = sizeof(MD5State), + .m_methods = MD5_functions, + .m_slots = _md5_slots, + .m_traverse = _md5_traverse, + .m_clear = _md5_clear, + .m_free = _md5_free, }; PyMODINIT_FUNC diff --git a/Modules/sha1module.c b/Modules/sha1module.c index 98948bcc570a9d..19963cca85f890 100644 --- a/Modules/sha1module.c +++ b/Modules/sha1module.c @@ -362,8 +362,15 @@ _sha1_exec(PyObject *module) st->sha1_type = (PyTypeObject *)PyType_FromModuleAndSpec( module, &sha1_type_spec, NULL); if (PyModule_AddObjectRef(module, - "SHA1Type", - (PyObject *)st->sha1_type) < 0) { + "SHA1Type", + (PyObject *)st->sha1_type) < 0) + { + return -1; + } + if (PyModule_AddIntConstant(module, + "GIL_MINSIZE", + HASHLIB_GIL_MINSIZE) < 0) + { return -1; } @@ -381,14 +388,14 @@ static PyModuleDef_Slot _sha1_slots[] = { }; static struct PyModuleDef _sha1module = { - PyModuleDef_HEAD_INIT, - .m_name = "_sha1", - .m_size = sizeof(SHA1State), - .m_methods = SHA1_functions, - .m_slots = _sha1_slots, - .m_traverse = _sha1_traverse, - .m_clear = _sha1_clear, - .m_free = _sha1_free + PyModuleDef_HEAD_INIT, + .m_name = "_sha1", + .m_size = sizeof(SHA1State), + .m_methods = SHA1_functions, + .m_slots = _sha1_slots, + .m_traverse = _sha1_traverse, + .m_clear = _sha1_clear, + .m_free = _sha1_free }; PyMODINIT_FUNC diff --git a/Modules/sha2module.c b/Modules/sha2module.c index e35bbb8a4ce6df..72f8b5970c4677 100644 --- a/Modules/sha2module.c +++ b/Modules/sha2module.c @@ -894,6 +894,13 @@ static int sha2_exec(PyObject *module) return -1; } + if (PyModule_AddIntConstant(module, + "GIL_MINSIZE", + HASHLIB_GIL_MINSIZE) < 0) + { + return -1; + } + return 0; } diff --git a/Modules/sha3module.c b/Modules/sha3module.c index e4109b53eda6fe..61592d84aa3ba0 100644 --- a/Modules/sha3module.c +++ b/Modules/sha3module.c @@ -639,8 +639,10 @@ _sha3_exec(PyObject *m) init_sha3type(shake_256_type, SHAKE256_spec); #undef init_sha3type - if (PyModule_AddStringConstant(m, "implementation", - "HACL") < 0) { + if (PyModule_AddStringConstant(m, "implementation", "HACL") < 0) { + return -1; + } + if (PyModule_AddIntConstant(m, "GIL_MINSIZE", HASHLIB_GIL_MINSIZE) < 0) { return -1; } From f791c734e2a8c141268df368b7e253285e8d9ba1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 26 Apr 2025 13:27:34 +0200 Subject: [PATCH 2/6] use exposed `GIL_MINSIZE` constant in tests --- Lib/test/test_hashlib.py | 26 ++++++++++++++++++++++---- Lib/test/test_hmac.py | 24 ++++++++++++++++++++---- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index 53afb2a8c631d7..f9f23994f25ff3 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -20,7 +20,7 @@ import warnings from test import support from test.support import _4G, bigmemtest -from test.support.import_helper import import_fresh_module +from test.support.import_helper import import_fresh_module, import_module from test.support import requires_resource from test.support import threading_helper from http.client import HTTPException @@ -95,6 +95,19 @@ def read_vectors(hash_name): yield parts +def find_gil_minsize(*modules_names, default=2048): + gil_minsize = default + for module_name in modules_names: + if SKIP_SHA3 and module_name == '_sha3': + continue + try: + module = importlib.import_module(module_name) + except ImportError: + continue + gil_minsize = max(gil_minsize, module.GIL_MINSIZE) + return gil_minsize + + class HashLibTestCase(unittest.TestCase): supported_hash_names = ( 'md5', 'MD5', 'sha1', 'SHA1', 'sha224', 'SHA224', 'sha256', 'SHA256', @@ -913,9 +926,12 @@ def test_case_shake256_vector(self): def test_gil(self): # Check things work fine with an input larger than the size required - # for multithreaded operation (which is hardwired to 2048). - gil_minsize = 2048 - + # for multithreaded operation. Currently, all cryptographic modules + # have the same constant value (2048) but in the future it might not + # be the case. + gil_minsize = find_gil_minsize( + '_md5', '_sha1', '_sha2', '_sha3', '_blake2', '_hashlib', + ) for cons in self.hash_constructors: m = cons(usedforsecurity=False) m.update(b'1') @@ -925,6 +941,8 @@ def test_gil(self): m = cons(b'x' * gil_minsize, usedforsecurity=False) m.update(b'1') + def test_sha256_gil(self): + gil_minsize = find_gil_minsize('_sha2', '_hashlib') m = hashlib.sha256() m.update(b'1') m.update(b'#' * gil_minsize) diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py index 8370ba30601fae..bd459f447db9e2 100644 --- a/Lib/test/test_hmac.py +++ b/Lib/test/test_hmac.py @@ -1102,6 +1102,11 @@ def HMAC(self, key, msg=None): """Create a HMAC object.""" raise NotImplementedError + @property + def gil_minsize(self): + """Get the maximal input length for the GIL to be held.""" + raise NotImplementedError + def check_update(self, key, chunks): chunks = list(chunks) msg = b''.join(chunks) @@ -1120,11 +1125,10 @@ def test_update(self): self.check_update(key, [msg]) def test_update_large(self): - HASHLIB_GIL_MINSIZE = 2048 - + gil_minsize = self.gil_minsize key = random.randbytes(16) - top = random.randbytes(HASHLIB_GIL_MINSIZE + 1) - bot = random.randbytes(HASHLIB_GIL_MINSIZE + 1) + top = random.randbytes(gil_minsize + 1) + bot = random.randbytes(gil_minsize + 1) self.check_update(key, [top, bot]) def test_update_exceptions(self): @@ -1140,6 +1144,10 @@ class PyUpdateTestCase(PyModuleMixin, UpdateTestCaseMixin, unittest.TestCase): def HMAC(self, key, msg=None): return self.hmac.HMAC(key, msg, digestmod='sha256') + @property + def gil_minsize(self): + self.skipTest("GIL is always held") + @hashlib_helper.requires_openssl_hashdigest('sha256') class OpenSSLUpdateTestCase(UpdateTestCaseMixin, unittest.TestCase): @@ -1147,6 +1155,10 @@ class OpenSSLUpdateTestCase(UpdateTestCaseMixin, unittest.TestCase): def HMAC(self, key, msg=None): return _hashlib.hmac_new(key, msg, digestmod='sha256') + @property + def gil_minsize(self): + return _hashlib.GIL_MINSIZE + class BuiltinUpdateTestCase(BuiltinModuleMixin, UpdateTestCaseMixin, unittest.TestCase): @@ -1156,6 +1168,10 @@ def HMAC(self, key, msg=None): # are still built, making it possible to use SHA-2 hashes. return self.hmac.new(key, msg, digestmod='sha256') + @property + def gil_minsize(self): + return self.hmac.GIL_MINSIZE + class CopyBaseTestCase: From f0d1664006db6295b06405a5295725cae2733bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 27 Apr 2025 11:27:56 +0200 Subject: [PATCH 3/6] rename `GIL_MINSIZE` to `_GIL_MINSIZE` --- Lib/test/test_hashlib.py | 2 +- Lib/test/test_hmac.py | 4 ++-- Modules/_hashopenssl.c | 2 +- Modules/blake2module.c | 2 +- Modules/hmacmodule.c | 2 +- Modules/md5module.c | 2 +- Modules/sha1module.c | 2 +- Modules/sha2module.c | 2 +- Modules/sha3module.c | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index f9f23994f25ff3..d3c12ca69d6ef6 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -104,7 +104,7 @@ def find_gil_minsize(*modules_names, default=2048): module = importlib.import_module(module_name) except ImportError: continue - gil_minsize = max(gil_minsize, module.GIL_MINSIZE) + gil_minsize = max(gil_minsize, module._GIL_MINSIZE) return gil_minsize diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py index bd459f447db9e2..ce3b8b2e8d0356 100644 --- a/Lib/test/test_hmac.py +++ b/Lib/test/test_hmac.py @@ -1157,7 +1157,7 @@ def HMAC(self, key, msg=None): @property def gil_minsize(self): - return _hashlib.GIL_MINSIZE + return _hashlib._GIL_MINSIZE class BuiltinUpdateTestCase(BuiltinModuleMixin, @@ -1170,7 +1170,7 @@ def HMAC(self, key, msg=None): @property def gil_minsize(self): - return self.hmac.GIL_MINSIZE + return self.hmac._GIL_MINSIZE class CopyBaseTestCase: diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 2dda213583f7a8..469a39cde7a2f7 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -2361,7 +2361,7 @@ hashlib_exception(PyObject *module) static int hashlib_constants(PyObject *module) { - if (PyModule_AddIntConstant(module, "GIL_MINSIZE", + if (PyModule_AddIntConstant(module, "_GIL_MINSIZE", HASHLIB_GIL_MINSIZE) < 0) { return -1; diff --git a/Modules/blake2module.c b/Modules/blake2module.c index a340c116477df7..f9acc57f1b2fa3 100644 --- a/Modules/blake2module.c +++ b/Modules/blake2module.c @@ -229,7 +229,7 @@ blake2_exec(PyObject *m) // good a place as any to probe the CPU flags. detect_cpu_features(&st->flags); - ADD_INT_CONST("GIL_MINSIZE", HASHLIB_GIL_MINSIZE); + ADD_INT_CONST("_GIL_MINSIZE", HASHLIB_GIL_MINSIZE); st->blake2b_type = (PyTypeObject *)PyType_FromModuleAndSpec( m, &blake2b_type_spec, NULL); diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index 5a57cbbc4fa15c..76079a7679426b 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -1688,7 +1688,7 @@ hmacmodule_init_globals(PyObject *module, hmacmodule_state *state) return -1; \ } \ } while (0) - ADD_INT_CONST("GIL_MINSIZE", HASHLIB_GIL_MINSIZE); + ADD_INT_CONST("_GIL_MINSIZE", HASHLIB_GIL_MINSIZE); #undef ADD_INT_CONST return 0; } diff --git a/Modules/md5module.c b/Modules/md5module.c index 32819ce4eff0c9..c36eb41d4d201e 100644 --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -370,7 +370,7 @@ md5_exec(PyObject *m) if (PyModule_AddObjectRef(m, "MD5Type", (PyObject *)st->md5_type) < 0) { return -1; } - if (PyModule_AddIntConstant(m, "GIL_MINSIZE", HASHLIB_GIL_MINSIZE) < 0) { + if (PyModule_AddIntConstant(m, "_GIL_MINSIZE", HASHLIB_GIL_MINSIZE) < 0) { return -1; } diff --git a/Modules/sha1module.c b/Modules/sha1module.c index 19963cca85f890..f4a00cdb422156 100644 --- a/Modules/sha1module.c +++ b/Modules/sha1module.c @@ -368,7 +368,7 @@ _sha1_exec(PyObject *module) return -1; } if (PyModule_AddIntConstant(module, - "GIL_MINSIZE", + "_GIL_MINSIZE", HASHLIB_GIL_MINSIZE) < 0) { return -1; diff --git a/Modules/sha2module.c b/Modules/sha2module.c index 72f8b5970c4677..e88d7cb2d456bf 100644 --- a/Modules/sha2module.c +++ b/Modules/sha2module.c @@ -895,7 +895,7 @@ static int sha2_exec(PyObject *module) } if (PyModule_AddIntConstant(module, - "GIL_MINSIZE", + "_GIL_MINSIZE", HASHLIB_GIL_MINSIZE) < 0) { return -1; diff --git a/Modules/sha3module.c b/Modules/sha3module.c index 61592d84aa3ba0..a7edf5c66a1e76 100644 --- a/Modules/sha3module.c +++ b/Modules/sha3module.c @@ -642,7 +642,7 @@ _sha3_exec(PyObject *m) if (PyModule_AddStringConstant(m, "implementation", "HACL") < 0) { return -1; } - if (PyModule_AddIntConstant(m, "GIL_MINSIZE", HASHLIB_GIL_MINSIZE) < 0) { + if (PyModule_AddIntConstant(m, "_GIL_MINSIZE", HASHLIB_GIL_MINSIZE) < 0) { return -1; } From 8ac8aa04b140033776e2588834c0977a74fa726b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 27 Apr 2025 11:30:07 +0200 Subject: [PATCH 4/6] only use default GIL_MINSIZE if none can be found --- Lib/test/test_hashlib.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index d3c12ca69d6ef6..cb48ecea62191d 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -20,6 +20,7 @@ import warnings from test import support from test.support import _4G, bigmemtest +from test.support import hashlib_helper from test.support.import_helper import import_fresh_module, import_module from test.support import requires_resource from test.support import threading_helper @@ -96,7 +97,7 @@ def read_vectors(hash_name): def find_gil_minsize(*modules_names, default=2048): - gil_minsize = default + sizes = [] for module_name in modules_names: if SKIP_SHA3 and module_name == '_sha3': continue @@ -104,8 +105,8 @@ def find_gil_minsize(*modules_names, default=2048): module = importlib.import_module(module_name) except ImportError: continue - gil_minsize = max(gil_minsize, module._GIL_MINSIZE) - return gil_minsize + sizes.append(module._GIL_MINSIZE) + return max(sizes, default=default) class HashLibTestCase(unittest.TestCase): From ca0ab3b10f9e139fb505b33483904460ab9378cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 27 Apr 2025 11:56:42 +0200 Subject: [PATCH 5/6] update --- Lib/test/support/hashlib_helper.py | 20 ++++++++++++++++++++ Lib/test/test_hashlib.py | 23 +++++------------------ 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/Lib/test/support/hashlib_helper.py b/Lib/test/support/hashlib_helper.py index 06fac410a5e20f..5043f08dd93de6 100644 --- a/Lib/test/support/hashlib_helper.py +++ b/Lib/test/support/hashlib_helper.py @@ -1,5 +1,6 @@ import functools import hashlib +import importlib import unittest from test.support.import_helper import import_module @@ -100,3 +101,22 @@ def wrapper(*args, **kwargs): def decorator(func_or_class): return _decorate_func_or_class(func_or_class, decorator_func) return decorator + + +def find_gil_minsize(modules_names, default=2048): + """Get the largest GIL_MINSIZE value for the given cryptographic modules. + + The valid module names are the following: + + - _hashlib + - _md5, _sha1, _sha2, _sha3, _blake2 + - _hmac + """ + sizes = [] + for module_name in modules_names: + try: + module = importlib.import_module(module_name) + except ImportError: + continue + sizes.append(getattr(module, '_GIL_MINSIZE', default)) + return max(sizes, default=default) diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index cb48ecea62191d..d752b2a647c6ea 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -21,7 +21,7 @@ from test import support from test.support import _4G, bigmemtest from test.support import hashlib_helper -from test.support.import_helper import import_fresh_module, import_module +from test.support.import_helper import import_fresh_module from test.support import requires_resource from test.support import threading_helper from http.client import HTTPException @@ -96,19 +96,6 @@ def read_vectors(hash_name): yield parts -def find_gil_minsize(*modules_names, default=2048): - sizes = [] - for module_name in modules_names: - if SKIP_SHA3 and module_name == '_sha3': - continue - try: - module = importlib.import_module(module_name) - except ImportError: - continue - sizes.append(module._GIL_MINSIZE) - return max(sizes, default=default) - - class HashLibTestCase(unittest.TestCase): supported_hash_names = ( 'md5', 'MD5', 'sha1', 'SHA1', 'sha224', 'SHA224', 'sha256', 'SHA256', @@ -930,10 +917,10 @@ def test_gil(self): # for multithreaded operation. Currently, all cryptographic modules # have the same constant value (2048) but in the future it might not # be the case. - gil_minsize = find_gil_minsize( - '_md5', '_sha1', '_sha2', '_sha3', '_blake2', '_hashlib', - ) + mods = ['_md5', '_sha1', '_sha2', '_sha3', '_blake2', '_hashlib'] + gil_minsize = hashlib_helper.find_gil_minsize(mods) for cons in self.hash_constructors: + # constructors belong to one of the above modules m = cons(usedforsecurity=False) m.update(b'1') m.update(b'#' * gil_minsize) @@ -943,7 +930,7 @@ def test_gil(self): m.update(b'1') def test_sha256_gil(self): - gil_minsize = find_gil_minsize('_sha2', '_hashlib') + gil_minsize = hashlib_helper.find_gil_minsize(['_sha2', '_hashlib']) m = hashlib.sha256() m.update(b'1') m.update(b'#' * gil_minsize) From a166e4f268b54fde4907cf6b941119ce9a24898c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 27 Apr 2025 23:56:26 +0200 Subject: [PATCH 6/6] do not skip a test The pure Python implementation actually calls the underlying C functions so in a sense we may still release the GIL. --- Lib/test/test_hmac.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_hmac.py b/Lib/test/test_hmac.py index 4251f3609f7b99..70c7943772249e 100644 --- a/Lib/test/test_hmac.py +++ b/Lib/test/test_hmac.py @@ -1136,7 +1136,7 @@ def test_update_exceptions(self): self.assertRaises(TypeError, h.update, msg) -@hashlib_helper.requires_hashdigest('sha256') +@requires_builtin_sha2() class PyUpdateTestCase(PyModuleMixin, UpdateTestCaseMixin, unittest.TestCase): def HMAC(self, key, msg=None): @@ -1144,7 +1144,7 @@ def HMAC(self, key, msg=None): @property def gil_minsize(self): - self.skipTest("GIL is always held") + return sha2._GIL_MINSIZE @hashlib_helper.requires_openssl_hashdigest('sha256')