Skip to content

Commit 9cb7a3d

Browse files
authored
Merge branch 'main' into zstd-clean
2 parents 1a54bf3 + 3f2f59a commit 9cb7a3d

35 files changed

+831
-195
lines changed

.github/workflows/mypy.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ on:
1313
- "Lib/test/libregrtest/**"
1414
- "Lib/tomllib/**"
1515
- "Misc/mypy/**"
16+
- "Tools/build/compute-changes.py"
1617
- "Tools/build/generate_sbom.py"
18+
- "Tools/build/verify_ensurepip_wheels.py"
19+
- "Tools/build/update_file.py"
1720
- "Tools/cases_generator/**"
1821
- "Tools/clinic/**"
1922
- "Tools/jit/**"

Doc/c-api/intro.rst

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -826,14 +826,17 @@ frequently used builds will be described in the remainder of this section.
826826
827827
Compiling the interpreter with the :c:macro:`!Py_DEBUG` macro defined produces
828828
what is generally meant by :ref:`a debug build of Python <debug-build>`.
829-
:c:macro:`!Py_DEBUG` is enabled in the Unix build by adding
830-
:option:`--with-pydebug` to the :file:`./configure` command.
831-
It is also implied by the presence of the
832-
not-Python-specific :c:macro:`!_DEBUG` macro. When :c:macro:`!Py_DEBUG` is enabled
833-
in the Unix build, compiler optimization is disabled.
829+
830+
On Unix, :c:macro:`!Py_DEBUG` can be enabled by adding :option:`--with-pydebug`
831+
to the :file:`./configure` command. This will also disable compiler optimization.
832+
833+
On Windows, selecting a debug build (e.g., by passing the :option:`-d` option to
834+
:file:`PCbuild/build.bat`) automatically enables :c:macro:`!Py_DEBUG`.
835+
Additionally, the presence of the not-Python-specific :c:macro:`!_DEBUG` macro,
836+
when defined by the compiler, will also implicitly enable :c:macro:`!Py_DEBUG`.
834837

835838
In addition to the reference count debugging described below, extra checks are
836-
performed, see :ref:`Python Debug Build <debug-build>`.
839+
performed. See :ref:`Python Debug Build <debug-build>` for more details.
837840

838841
Defining :c:macro:`Py_TRACE_REFS` enables reference tracing
839842
(see the :option:`configure --with-trace-refs option <--with-trace-refs>`).

Include/internal/pycore_crossinterp.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,14 @@ PyAPI_FUNC(int) _PyCode_GetXIData(
191191
PyThreadState *,
192192
PyObject *,
193193
_PyXIData_t *);
194+
PyAPI_FUNC(int) _PyCode_GetScriptXIData(
195+
PyThreadState *,
196+
PyObject *,
197+
_PyXIData_t *);
198+
PyAPI_FUNC(int) _PyCode_GetPureScriptXIData(
199+
PyThreadState *,
200+
PyObject *,
201+
_PyXIData_t *);
194202

195203

196204
/* using cross-interpreter data */

Include/internal/pycore_importdl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ extern int _PyImport_RunModInitFunc(
107107
#include <windows.h>
108108
typedef FARPROC dl_funcptr;
109109

110-
#ifdef _DEBUG
110+
#ifdef Py_DEBUG
111111
# define PYD_DEBUG_SUFFIX "_d"
112112
#else
113113
# define PYD_DEBUG_SUFFIX ""

Include/internal/pycore_pythonrun.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ extern int _PyRun_InteractiveLoopObject(
2525
PyObject *filename,
2626
PyCompilerFlags *flags);
2727

28+
extern int _PyObject_SupportedAsScript(PyObject *);
2829
extern const char* _Py_SourceAsString(
2930
PyObject *cmd,
3031
const char *funcname,

Lib/test/_code_definitions.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,32 @@
11

2+
def simple_script():
3+
assert True
4+
5+
6+
def complex_script():
7+
obj = 'a string'
8+
pickle = __import__('pickle')
9+
def spam_minimal():
10+
pass
11+
spam_minimal()
12+
data = pickle.dumps(obj)
13+
res = pickle.loads(data)
14+
assert res == obj, (res, obj)
15+
16+
17+
def script_with_globals():
18+
obj1, obj2 = spam(42)
19+
assert obj1 == 42
20+
assert obj2 is None
21+
22+
23+
def script_with_explicit_empty_return():
24+
return None
25+
26+
27+
def script_with_return():
28+
return True
29+
230

331
def spam_minimal():
432
# no arg defaults or kwarg defaults
@@ -141,6 +169,11 @@ def ham_C_closure(z):
141169

142170
TOP_FUNCTIONS = [
143171
# shallow
172+
simple_script,
173+
complex_script,
174+
script_with_globals,
175+
script_with_explicit_empty_return,
176+
script_with_return,
144177
spam_minimal,
145178
spam_with_builtins,
146179
spam_with_globals_and_builtins,
@@ -179,6 +212,10 @@ def ham_C_closure(z):
179212
]
180213

181214
STATELESS_FUNCTIONS = [
215+
simple_script,
216+
complex_script,
217+
script_with_explicit_empty_return,
218+
script_with_return,
182219
spam,
183220
spam_minimal,
184221
spam_with_builtins,
@@ -200,10 +237,26 @@ def ham_C_closure(z):
200237
]
201238
STATELESS_CODE = [
202239
*STATELESS_FUNCTIONS,
240+
script_with_globals,
203241
spam_with_globals_and_builtins,
204242
spam_full,
205243
]
206244

245+
PURE_SCRIPT_FUNCTIONS = [
246+
simple_script,
247+
complex_script,
248+
script_with_explicit_empty_return,
249+
spam_minimal,
250+
spam_with_builtins,
251+
spam_with_inner_not_closure,
252+
spam_with_inner_closure,
253+
]
254+
SCRIPT_FUNCTIONS = [
255+
*PURE_SCRIPT_FUNCTIONS,
256+
script_with_globals,
257+
spam_with_globals_and_builtins,
258+
]
259+
207260

208261
# generators
209262

Lib/test/pickletester.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,39 +2272,47 @@ def test_nonencodable_module_name_error(self):
22722272

22732273
def test_nested_lookup_error(self):
22742274
# Nested name does not exist
2275-
obj = REX('AbstractPickleTests.spam')
2275+
global TestGlobal
2276+
class TestGlobal:
2277+
class A:
2278+
pass
2279+
obj = REX('TestGlobal.A.B.C')
22762280
obj.__module__ = __name__
22772281
for proto in protocols:
22782282
with self.subTest(proto=proto):
22792283
with self.assertRaises(pickle.PicklingError) as cm:
22802284
self.dumps(obj, proto)
22812285
self.assertEqual(str(cm.exception),
22822286
f"Can't pickle {obj!r}: "
2283-
f"it's not found as {__name__}.AbstractPickleTests.spam")
2287+
f"it's not found as {__name__}.TestGlobal.A.B.C")
22842288
self.assertEqual(str(cm.exception.__context__),
2285-
"type object 'AbstractPickleTests' has no attribute 'spam'")
2289+
"type object 'A' has no attribute 'B'")
22862290

22872291
obj.__module__ = None
22882292
for proto in protocols:
22892293
with self.subTest(proto=proto):
22902294
with self.assertRaises(pickle.PicklingError) as cm:
22912295
self.dumps(obj, proto)
22922296
self.assertEqual(str(cm.exception),
2293-
f"Can't pickle {obj!r}: it's not found as __main__.AbstractPickleTests.spam")
2297+
f"Can't pickle {obj!r}: "
2298+
f"it's not found as __main__.TestGlobal.A.B.C")
22942299
self.assertEqual(str(cm.exception.__context__),
2295-
"module '__main__' has no attribute 'AbstractPickleTests'")
2300+
"module '__main__' has no attribute 'TestGlobal'")
22962301

22972302
def test_wrong_object_lookup_error(self):
22982303
# Name is bound to different object
2299-
obj = REX('AbstractPickleTests')
2304+
global TestGlobal
2305+
class TestGlobal:
2306+
pass
2307+
obj = REX('TestGlobal')
23002308
obj.__module__ = __name__
2301-
AbstractPickleTests.ham = []
23022309
for proto in protocols:
23032310
with self.subTest(proto=proto):
23042311
with self.assertRaises(pickle.PicklingError) as cm:
23052312
self.dumps(obj, proto)
23062313
self.assertEqual(str(cm.exception),
2307-
f"Can't pickle {obj!r}: it's not the same object as {__name__}.AbstractPickleTests")
2314+
f"Can't pickle {obj!r}: "
2315+
f"it's not the same object as {__name__}.TestGlobal")
23082316
self.assertIsNone(cm.exception.__context__)
23092317

23102318
obj.__module__ = None
@@ -2313,9 +2321,10 @@ def test_wrong_object_lookup_error(self):
23132321
with self.assertRaises(pickle.PicklingError) as cm:
23142322
self.dumps(obj, proto)
23152323
self.assertEqual(str(cm.exception),
2316-
f"Can't pickle {obj!r}: it's not found as __main__.AbstractPickleTests")
2324+
f"Can't pickle {obj!r}: "
2325+
f"it's not found as __main__.TestGlobal")
23172326
self.assertEqual(str(cm.exception.__context__),
2318-
"module '__main__' has no attribute 'AbstractPickleTests'")
2327+
"module '__main__' has no attribute 'TestGlobal'")
23192328

23202329
def test_local_lookup_error(self):
23212330
# Test that whichmodule() errors out cleanly when looking up

Lib/test/test_code.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,20 @@ def test_local_kinds(self):
673673
VARKWARGS = CO_FAST_LOCAL | CO_FAST_ARG_VAR | CO_FAST_ARG_KW
674674

675675
funcs = {
676+
defs.simple_script: {},
677+
defs.complex_script: {
678+
'obj': CO_FAST_LOCAL,
679+
'pickle': CO_FAST_LOCAL,
680+
'spam_minimal': CO_FAST_LOCAL,
681+
'data': CO_FAST_LOCAL,
682+
'res': CO_FAST_LOCAL,
683+
},
684+
defs.script_with_globals: {
685+
'obj1': CO_FAST_LOCAL,
686+
'obj2': CO_FAST_LOCAL,
687+
},
688+
defs.script_with_explicit_empty_return: {},
689+
defs.script_with_return: {},
676690
defs.spam_minimal: {},
677691
defs.spam_with_builtins: {
678692
'x': CO_FAST_LOCAL,
@@ -898,6 +912,19 @@ def new_var_counts(*,
898912
}
899913

900914
funcs = {
915+
defs.simple_script: new_var_counts(),
916+
defs.complex_script: new_var_counts(
917+
purelocals=5,
918+
globalvars=1,
919+
attrs=2,
920+
),
921+
defs.script_with_globals: new_var_counts(
922+
purelocals=2,
923+
globalvars=1,
924+
),
925+
defs.script_with_explicit_empty_return: new_var_counts(),
926+
defs.script_with_return: new_var_counts(),
927+
defs.spam_minimal: new_var_counts(),
901928
defs.spam_minimal: new_var_counts(),
902929
defs.spam_with_builtins: new_var_counts(
903930
purelocals=4,

Lib/test/test_crossinterp.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,126 @@ def test_other_objects(self):
758758
])
759759

760760

761+
class PureShareableScriptTests(_GetXIDataTests):
762+
763+
MODE = 'script-pure'
764+
765+
VALID_SCRIPTS = [
766+
'',
767+
'spam',
768+
'# a comment',
769+
'print("spam")',
770+
'raise Exception("spam")',
771+
"""if True:
772+
do_something()
773+
""",
774+
"""if True:
775+
def spam(x):
776+
return x
777+
class Spam:
778+
def eggs(self):
779+
return 42
780+
x = Spam().eggs()
781+
raise ValueError(spam(x))
782+
""",
783+
]
784+
INVALID_SCRIPTS = [
785+
' pass', # IndentationError
786+
'----', # SyntaxError
787+
"""if True:
788+
def spam():
789+
# no body
790+
spam()
791+
""", # IndentationError
792+
]
793+
794+
def test_valid_str(self):
795+
self.assert_roundtrip_not_equal([
796+
*self.VALID_SCRIPTS,
797+
], expecttype=types.CodeType)
798+
799+
def test_invalid_str(self):
800+
self.assert_not_shareable([
801+
*self.INVALID_SCRIPTS,
802+
])
803+
804+
def test_valid_bytes(self):
805+
self.assert_roundtrip_not_equal([
806+
*(s.encode('utf8') for s in self.VALID_SCRIPTS),
807+
], expecttype=types.CodeType)
808+
809+
def test_invalid_bytes(self):
810+
self.assert_not_shareable([
811+
*(s.encode('utf8') for s in self.INVALID_SCRIPTS),
812+
])
813+
814+
def test_pure_script_code(self):
815+
self.assert_roundtrip_equal_not_identical([
816+
*(f.__code__ for f in defs.PURE_SCRIPT_FUNCTIONS),
817+
])
818+
819+
def test_impure_script_code(self):
820+
self.assert_not_shareable([
821+
*(f.__code__ for f in defs.SCRIPT_FUNCTIONS
822+
if f not in defs.PURE_SCRIPT_FUNCTIONS),
823+
])
824+
825+
def test_other_code(self):
826+
self.assert_not_shareable([
827+
*(f.__code__ for f in defs.FUNCTIONS
828+
if f not in defs.SCRIPT_FUNCTIONS),
829+
*(f.__code__ for f in defs.FUNCTION_LIKE),
830+
])
831+
832+
def test_pure_script_function(self):
833+
self.assert_roundtrip_not_equal([
834+
*defs.PURE_SCRIPT_FUNCTIONS,
835+
], expecttype=types.CodeType)
836+
837+
def test_impure_script_function(self):
838+
self.assert_not_shareable([
839+
*(f for f in defs.SCRIPT_FUNCTIONS
840+
if f not in defs.PURE_SCRIPT_FUNCTIONS),
841+
])
842+
843+
def test_other_function(self):
844+
self.assert_not_shareable([
845+
*(f for f in defs.FUNCTIONS
846+
if f not in defs.SCRIPT_FUNCTIONS),
847+
*defs.FUNCTION_LIKE,
848+
])
849+
850+
def test_other_objects(self):
851+
self.assert_not_shareable([
852+
None,
853+
True,
854+
False,
855+
Ellipsis,
856+
NotImplemented,
857+
(),
858+
[],
859+
{},
860+
object(),
861+
])
862+
863+
864+
class ShareableScriptTests(PureShareableScriptTests):
865+
866+
MODE = 'script'
867+
868+
def test_impure_script_code(self):
869+
self.assert_roundtrip_equal_not_identical([
870+
*(f.__code__ for f in defs.SCRIPT_FUNCTIONS
871+
if f not in defs.PURE_SCRIPT_FUNCTIONS),
872+
])
873+
874+
def test_impure_script_function(self):
875+
self.assert_roundtrip_not_equal([
876+
*(f for f in defs.SCRIPT_FUNCTIONS
877+
if f not in defs.PURE_SCRIPT_FUNCTIONS),
878+
], expecttype=types.CodeType)
879+
880+
761881
class ShareableTypeTests(_GetXIDataTests):
762882

763883
MODE = 'xidata'

0 commit comments

Comments
 (0)