Skip to content

Commit b94fedc

Browse files
committed
Merge branch 'main' into core-header-refactor-2
2 parents 82cb3d5 + 978e37b commit b94fedc

38 files changed

+822
-464
lines changed

Doc/library/pickletools.rst

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ ordinary users of the :mod:`pickle` module probably won't find the
1919

2020
.. _pickletools-cli:
2121

22-
Command line usage
22+
Command-line usage
2323
------------------
2424

2525
.. versionadded:: 3.2
@@ -48,7 +48,7 @@ For example, with a tuple ``(1, 2)`` pickled in file ``x.pickle``:
4848
9: . STOP
4949
highest protocol among opcodes = 2
5050
51-
Command line options
51+
Command-line options
5252
^^^^^^^^^^^^^^^^^^^^
5353

5454
.. program:: pickletools
@@ -72,12 +72,16 @@ Command line options
7272

7373
.. option:: -p, --preamble=<preamble>
7474

75-
When more than one pickle file are specified, print given preamble
75+
When more than one pickle file is specified, print given preamble
7676
before each disassembly.
7777

78+
.. option:: pickle_file
7879

80+
A pickle file to read, or ``-`` to indicate reading from standard input.
7981

80-
Programmatic Interface
82+
83+
84+
Programmatic interface
8185
----------------------
8286

8387

Include/internal/pycore_pystate.h

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -52,36 +52,18 @@ extern const PyConfig* _PyInterpreterState_GetConfig(PyInterpreterState *interp)
5252

5353
/* Check if the current thread is the main thread.
5454
Use _Py_IsMainInterpreter() to check if it's the main interpreter. */
55-
static inline int
56-
_Py_IsMainThread(void)
57-
{
58-
unsigned long thread = PyThread_get_thread_ident();
59-
return (thread == _PyRuntime.main_thread);
60-
}
61-
55+
extern int _Py_IsMainThread(void);
6256

63-
static inline PyInterpreterState *
64-
_PyInterpreterState_Main(void)
65-
{
66-
return _PyRuntime.interpreters.main;
67-
}
57+
// Export for '_testinternalcapi' shared extension
58+
PyAPI_FUNC(PyInterpreterState*) _PyInterpreterState_Main(void);
6859

6960
static inline int
7061
_Py_IsMainInterpreter(PyInterpreterState *interp)
7162
{
7263
return (interp == _PyInterpreterState_Main());
7364
}
7465

75-
static inline int
76-
_Py_IsMainInterpreterFinalizing(PyInterpreterState *interp)
77-
{
78-
/* bpo-39877: Access _PyRuntime directly rather than using
79-
tstate->interp->runtime to support calls from Python daemon threads.
80-
After Py_Finalize() has been called, tstate can be a dangling pointer:
81-
point to PyThreadState freed memory. */
82-
return (_PyRuntimeState_GetFinalizing(&_PyRuntime) != NULL &&
83-
interp == &_PyRuntime._main_interpreter);
84-
}
66+
extern int _Py_IsMainInterpreterFinalizing(PyInterpreterState *interp);
8567

8668
// Export for _interpreters module.
8769
PyAPI_FUNC(PyObject *) _PyInterpreterState_GetIDObject(PyInterpreterState *);
@@ -94,17 +76,7 @@ PyAPI_FUNC(void) _PyErr_SetInterpreterAlreadyRunning(void);
9476

9577
extern int _PyThreadState_IsRunningMain(PyThreadState *);
9678
extern void _PyInterpreterState_ReinitRunningMain(PyThreadState *);
97-
98-
99-
static inline const PyConfig *
100-
_Py_GetMainConfig(void)
101-
{
102-
PyInterpreterState *interp = _PyInterpreterState_Main();
103-
if (interp == NULL) {
104-
return NULL;
105-
}
106-
return _PyInterpreterState_GetConfig(interp);
107-
}
79+
extern const PyConfig* _Py_GetMainConfig(void);
10880

10981

11082
/* Only handle signals on the main thread of the main interpreter. */

Lib/hmac.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ def __init__(self, key, msg=None, digestmod=''):
6565

6666
def _init_hmac(self, key, msg, digestmod):
6767
self._hmac = _hashopenssl.hmac_new(key, msg, digestmod=digestmod)
68+
self._inner = self._outer = None # because the slots are defined
6869
self.digest_size = self._hmac.digest_size
6970
self.block_size = self._hmac.block_size
7071

Lib/pickletools.py

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2845,7 +2845,7 @@ def __init__(self, value):
28452845
description='disassemble one or more pickle files')
28462846
parser.add_argument(
28472847
'pickle_file',
2848-
nargs='*', help='the pickle file')
2848+
nargs='+', help='the pickle file')
28492849
parser.add_argument(
28502850
'-o', '--output',
28512851
help='the file where the output should be written')
@@ -2863,26 +2863,23 @@ def __init__(self, value):
28632863
help='if more than one pickle file is specified, print this before'
28642864
' each disassembly')
28652865
args = parser.parse_args()
2866-
if not args.pickle_file:
2867-
parser.print_help()
2866+
annotate = 30 if args.annotate else 0
2867+
memo = {} if args.memo else None
2868+
if args.output is None:
2869+
output = sys.stdout
28682870
else:
2869-
annotate = 30 if args.annotate else 0
2870-
memo = {} if args.memo else None
2871-
if args.output is None:
2872-
output = sys.stdout
2873-
else:
2874-
output = open(args.output, 'w')
2875-
try:
2876-
for arg in args.pickle_file:
2877-
if len(args.pickle_file) > 1:
2878-
name = '<stdin>' if arg == '-' else arg
2879-
preamble = args.preamble.format(name=name)
2880-
output.write(preamble + '\n')
2881-
if arg == '-':
2882-
dis(sys.stdin.buffer, output, memo, args.indentlevel, annotate)
2883-
else:
2884-
with open(arg, 'rb') as f:
2885-
dis(f, output, memo, args.indentlevel, annotate)
2886-
finally:
2887-
if output is not sys.stdout:
2888-
output.close()
2871+
output = open(args.output, 'w')
2872+
try:
2873+
for arg in args.pickle_file:
2874+
if len(args.pickle_file) > 1:
2875+
name = '<stdin>' if arg == '-' else arg
2876+
preamble = args.preamble.format(name=name)
2877+
output.write(preamble + '\n')
2878+
if arg == '-':
2879+
dis(sys.stdin.buffer, output, memo, args.indentlevel, annotate)
2880+
else:
2881+
with open(arg, 'rb') as f:
2882+
dis(f, output, memo, args.indentlevel, annotate)
2883+
finally:
2884+
if output is not sys.stdout:
2885+
output.close()

Lib/test/support/hashlib_helper.py

Lines changed: 65 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import functools
22
import hashlib
33
import unittest
4+
from test.support.import_helper import import_module
45

56
try:
67
import _hashlib
@@ -12,44 +13,81 @@ def requires_hashlib():
1213
return unittest.skipIf(_hashlib is None, "requires _hashlib")
1314

1415

16+
def _decorate_func_or_class(func_or_class, decorator_func):
17+
if not isinstance(func_or_class, type):
18+
return decorator_func(func_or_class)
19+
20+
decorated_class = func_or_class
21+
setUpClass = decorated_class.__dict__.get('setUpClass')
22+
if setUpClass is None:
23+
def setUpClass(cls):
24+
super(decorated_class, cls).setUpClass()
25+
setUpClass.__qualname__ = decorated_class.__qualname__ + '.setUpClass'
26+
setUpClass.__module__ = decorated_class.__module__
27+
else:
28+
setUpClass = setUpClass.__func__
29+
setUpClass = classmethod(decorator_func(setUpClass))
30+
decorated_class.setUpClass = setUpClass
31+
return decorated_class
32+
33+
1534
def requires_hashdigest(digestname, openssl=None, usedforsecurity=True):
16-
"""Decorator raising SkipTest if a hashing algorithm is not available
35+
"""Decorator raising SkipTest if a hashing algorithm is not available.
1736
18-
The hashing algorithm could be missing or blocked by a strict crypto
19-
policy.
37+
The hashing algorithm may be missing, blocked by a strict crypto policy,
38+
or Python may be configured with `--with-builtin-hashlib-hashes=no`.
2039
2140
If 'openssl' is True, then the decorator checks that OpenSSL provides
22-
the algorithm. Otherwise the check falls back to built-in
23-
implementations. The usedforsecurity flag is passed to the constructor.
41+
the algorithm. Otherwise the check falls back to (optional) built-in
42+
HACL* implementations.
43+
44+
The usedforsecurity flag is passed to the constructor but has no effect
45+
on HACL* implementations.
2446
47+
Examples of exceptions being suppressed:
2548
ValueError: [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS
2649
ValueError: unsupported hash type md4
2750
"""
51+
if openssl and _hashlib is not None:
52+
def test_availability():
53+
_hashlib.new(digestname, usedforsecurity=usedforsecurity)
54+
else:
55+
def test_availability():
56+
hashlib.new(digestname, usedforsecurity=usedforsecurity)
57+
58+
def decorator_func(func):
59+
@functools.wraps(func)
60+
def wrapper(*args, **kwargs):
61+
try:
62+
test_availability()
63+
except ValueError as exc:
64+
msg = f"missing hash algorithm: {digestname!r}"
65+
raise unittest.SkipTest(msg) from exc
66+
return func(*args, **kwargs)
67+
return wrapper
68+
2869
def decorator(func_or_class):
29-
if isinstance(func_or_class, type):
30-
setUpClass = func_or_class.__dict__.get('setUpClass')
31-
if setUpClass is None:
32-
def setUpClass(cls):
33-
super(func_or_class, cls).setUpClass()
34-
setUpClass.__qualname__ = func_or_class.__qualname__ + '.setUpClass'
35-
setUpClass.__module__ = func_or_class.__module__
36-
else:
37-
setUpClass = setUpClass.__func__
38-
setUpClass = classmethod(decorator(setUpClass))
39-
func_or_class.setUpClass = setUpClass
40-
return func_or_class
41-
42-
@functools.wraps(func_or_class)
70+
return _decorate_func_or_class(func_or_class, decorator_func)
71+
return decorator
72+
73+
74+
def requires_openssl_hashdigest(digestname, *, usedforsecurity=True):
75+
"""Decorator raising SkipTest if an OpenSSL hashing algorithm is missing.
76+
77+
The hashing algorithm may be missing or blocked by a strict crypto policy.
78+
"""
79+
def decorator_func(func):
80+
@requires_hashlib()
81+
@functools.wraps(func)
4382
def wrapper(*args, **kwargs):
4483
try:
45-
if openssl and _hashlib is not None:
46-
_hashlib.new(digestname, usedforsecurity=usedforsecurity)
47-
else:
48-
hashlib.new(digestname, usedforsecurity=usedforsecurity)
84+
_hashlib.new(digestname, usedforsecurity=usedforsecurity)
4985
except ValueError:
50-
raise unittest.SkipTest(
51-
f"hash digest {digestname!r} is not available."
52-
)
53-
return func_or_class(*args, **kwargs)
86+
msg = f"missing OpenSSL hash algorithm: {digestname!r}"
87+
raise unittest.SkipTest(msg)
88+
return func(*args, **kwargs)
5489
return wrapper
90+
91+
def decorator(func_or_class):
92+
return _decorate_func_or_class(func_or_class, decorator_func)
5593
return decorator

0 commit comments

Comments
 (0)