Skip to content

Commit a0cb053

Browse files
Merge remote-tracking branch 'origin/main' into fix-clean
2 parents 17e29a0 + 1ac9d13 commit a0cb053

18 files changed

Lines changed: 190 additions & 23 deletions

Doc/using/configure.rst

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,6 +1650,9 @@ Linker flags
16501650
value to be able to build extension modules using the
16511651
directories specified in the environment variables.
16521652

1653+
Please consider using ``EXE_LDFLAGS`` if the supplied linker flags are
1654+
executable specific, e.g. GCC's ``-pie`` flag.
1655+
16531656
.. envvar:: LIBS
16541657

16551658
Linker flags to pass libraries to the linker when linking the Python
@@ -1685,6 +1688,30 @@ Linker flags
16851688

16861689
.. versionadded:: 3.8
16871690

1691+
.. envvar:: EXE_LDFLAGS
1692+
1693+
Linker flags used for building executable targets such as the
1694+
interpreter. If supplied, :envvar:`PY_CORE_EXE_LDFLAGS`
1695+
will be used in replacement of :envvar:`PY_CORE_LDFLAGS`.
1696+
1697+
.. versionadded:: 3.15
1698+
1699+
.. envvar:: CONFIGURE_EXE_LDFLAGS
1700+
1701+
Value of :envvar:`EXE_LDFLAGS` variable passed to the ``./configure``
1702+
script.
1703+
1704+
.. versionadded:: 3.15
1705+
1706+
.. envvar:: PY_CORE_EXE_LDFLAGS
1707+
1708+
Linker flags used for building the interpreter and
1709+
executable targets.
1710+
1711+
Default: ``$(PY_CORE_LDFLAGS)``
1712+
1713+
.. versionadded:: 3.15
1714+
16881715

16891716
.. rubric:: Footnotes
16901717

Lib/_osx_support.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
_UNIVERSAL_CONFIG_VARS = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS', 'BASECFLAGS',
1818
'BLDSHARED', 'LDSHARED', 'CC', 'CXX',
1919
'PY_CFLAGS', 'PY_LDFLAGS', 'PY_CPPFLAGS',
20-
'PY_CORE_CFLAGS', 'PY_CORE_LDFLAGS')
20+
'PY_CORE_CFLAGS', 'PY_CORE_LDFLAGS',
21+
'PY_CORE_EXE_LDFLAGS')
2122

2223
# configuration variables that may contain compiler calls
2324
_COMPILER_CONFIG_VARS = ('BLDSHARED', 'LDSHARED', 'CC', 'CXX')

Lib/test/pythoninfo.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,7 @@ def collect_sysconfig(info_add):
528528
'PY_CFLAGS',
529529
'PY_CFLAGS_NODIST',
530530
'PY_CORE_LDFLAGS',
531+
'PY_CORE_EXE_LDFLAGS',
531532
'PY_LDFLAGS',
532533
'PY_LDFLAGS_NODIST',
533534
'PY_STDMODULE_CFLAGS',

Lib/test/test__osx_support.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def setUp(self):
2525
'CFLAGS', 'LDFLAGS', 'CPPFLAGS',
2626
'BASECFLAGS', 'BLDSHARED', 'LDSHARED', 'CC',
2727
'CXX', 'PY_CFLAGS', 'PY_LDFLAGS', 'PY_CPPFLAGS',
28-
'PY_CORE_CFLAGS', 'PY_CORE_LDFLAGS'
28+
'PY_CORE_CFLAGS', 'PY_CORE_LDFLAGS', 'PY_CORE_EXE_LDFLAGS'
2929
)
3030

3131
def add_expected_saved_initial_values(self, config_vars, expected_vars):

Lib/test/test_traceback.py

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,18 @@
99
import builtins
1010
import unittest
1111
import unittest.mock
12+
import os
1213
import re
1314
import tempfile
1415
import random
1516
import string
17+
import importlib.machinery
18+
import sysconfig
1619
from test import support
1720
import shutil
1821
from test.support import (Error, captured_output, cpython_only, ALWAYS_EQ,
1922
requires_debug_ranges, has_no_debug_ranges,
20-
requires_subprocess)
23+
requires_subprocess, os_helper)
2124
from test.support.os_helper import TESTFN, temp_dir, unlink
2225
from test.support.script_helper import assert_python_ok, assert_python_failure, make_script
2326
from test.support.import_helper import forget
@@ -5194,6 +5197,56 @@ def test_windows_only_module_error(self):
51945197
else:
51955198
self.fail("ModuleNotFoundError was not raised")
51965199

5200+
@unittest.skipIf(not importlib.machinery.EXTENSION_SUFFIXES, 'Platform does not support extension modules')
5201+
def test_find_incompatible_extension_modules(self):
5202+
"""_find_incompatible_extension_modules assumes the last extension in
5203+
importlib.machinery.EXTENSION_SUFFIXES (defined in Python/dynload_*.c)
5204+
is untagged (eg. .so, .pyd).
5205+
5206+
This test exists to make sure that assumption is correct.
5207+
"""
5208+
last_extension_suffix = importlib.machinery.EXTENSION_SUFFIXES[-1]
5209+
if shlib_suffix := sysconfig.get_config_var('SHLIB_SUFFIX'):
5210+
self.assertEqual(last_extension_suffix, shlib_suffix)
5211+
else:
5212+
before_dot, *extensions = last_extension_suffix.split('.')
5213+
expected_prefixes = ['']
5214+
if os.name == 'nt':
5215+
# Windows puts the debug tag in the module file stem (eg. foo_d.pyd)
5216+
expected_prefixes.append('_d')
5217+
self.assertIn(before_dot, expected_prefixes, msg=(
5218+
f'Unexpected prefix {before_dot!r} in extension module '
5219+
f'suffix {last_extension_suffix!r}. '
5220+
'traceback._find_incompatible_extension_module needs to be '
5221+
'updated to take this into account!'
5222+
))
5223+
# if SHLIB_SUFFIX is not define, we assume the native
5224+
# shared library suffix only contains one extension
5225+
# (eg. '.so', bad eg. '.cpython-315-x86_64-linux-gnu.so')
5226+
self.assertEqual(len(extensions), 1, msg=(
5227+
'The last suffix in importlib.machinery.EXTENSION_SUFFIXES '
5228+
'contains more than one extension, so it is probably different '
5229+
'than SHLIB_SUFFIX. It probably contains an ABI tag! '
5230+
'If this is a false positive, define SHLIB_SUFFIX in sysconfig.'
5231+
))
5232+
5233+
@unittest.skipIf(not importlib.machinery.EXTENSION_SUFFIXES, 'Platform does not support extension modules')
5234+
def test_incompatible_extension_modules_hint(self):
5235+
untagged_suffix = importlib.machinery.EXTENSION_SUFFIXES[-1]
5236+
with os_helper.temp_dir() as tmp:
5237+
# create a module with a incompatible ABI tag
5238+
incompatible_module = f'foo.some-abi{untagged_suffix}'
5239+
open(os.path.join(tmp, incompatible_module), "wb").close()
5240+
# try importing it
5241+
code = f'''
5242+
import sys
5243+
sys.path.insert(0, {tmp!r})
5244+
import foo
5245+
'''
5246+
_, _, stderr = assert_python_failure('-c', code, __cwd=tmp)
5247+
hint = f'Although a module with this name was found for a different Python version ({incompatible_module}).'
5248+
self.assertIn(hint, stderr.decode())
5249+
51975250

51985251
class TestColorizedTraceback(unittest.TestCase):
51995252
maxDiff = None

Lib/test/test_type_params.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,13 @@ def test_incorrect_mro_explicit_object(self):
152152
with self.assertRaisesRegex(TypeError, r"\(MRO\) for bases object, Generic"):
153153
class My[X](object): ...
154154

155+
def test_compile_error_in_type_param_bound(self):
156+
# This should not crash, see gh-145187
157+
check_syntax_error(
158+
self,
159+
"if True:\n class h[l:{7for*()in 0}]:2"
160+
)
161+
155162

156163
class TypeParamsNonlocalTest(unittest.TestCase):
157164
def test_nonlocal_disallowed_01(self):

Lib/test/test_unicodedata.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,12 @@ def test_decomposition(self):
378378
# New in 17.0.0
379379
self.assertEqual(self.db.decomposition('\uA7F1'), '' if self.old else '<super> 0053')
380380

381+
# Hangul characters
382+
self.assertEqual(self.db.decomposition('\uAC00'), '1100 1161')
383+
self.assertEqual(self.db.decomposition('\uD4DB'), '1111 1171 11B6')
384+
self.assertEqual(self.db.decomposition('\uC2F8'), '110A 1161')
385+
self.assertEqual(self.db.decomposition('\uD7A3'), '1112 1175 11C2')
386+
381387
self.assertRaises(TypeError, self.db.decomposition)
382388
self.assertRaises(TypeError, self.db.decomposition, 'xx')
383389

@@ -687,9 +693,9 @@ class UnicodeFunctionsTest(unittest.TestCase, BaseUnicodeFunctionsTest):
687693

688694
# Update this if the database changes. Make sure to do a full rebuild
689695
# (e.g. 'make distclean && make') to get the correct checksum.
690-
expectedchecksum = ('668dbbea1136e69d4f00677a5988b23bc78aefc6'
696+
expectedchecksum = ('00b13fa975a60b1d3f490f1fc8c126ab24990c75'
691697
if quicktest else
692-
'b869af769bd8fe352c04622ab90533dc54df5cf3')
698+
'ebfc9dd281c2226998fd435744dd2e9321899beb')
693699

694700
@requires_resource('network')
695701
def test_all_names(self):
@@ -1068,9 +1074,9 @@ def test_block_invalid_input(self):
10681074
class Unicode_3_2_0_FunctionsTest(unittest.TestCase, BaseUnicodeFunctionsTest):
10691075
db = unicodedata.ucd_3_2_0
10701076
old = True
1071-
expectedchecksum = ('2164a66700e03cba9c9f5ed9e9a8d594d2da136a'
1077+
expectedchecksum = ('cb5bbbd1f55b67371e18222b90a8e21c87f16b72'
10721078
if quicktest else
1073-
'a8276cec9b6991779c5bdaa46c1ae7cc50bc2403')
1079+
'74936dffe949d99203a47e6a66565b2fc337bae7')
10741080

10751081

10761082
class UnicodeMiscTest(unittest.TestCase):

Lib/traceback.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import collections.abc
44
import itertools
55
import linecache
6+
import os
67
import sys
78
import textwrap
89
import types
@@ -12,6 +13,7 @@
1213
import tokenize
1314
import io
1415
import importlib.util
16+
import pathlib
1517
import _colorize
1618

1719
from contextlib import suppress
@@ -1129,6 +1131,11 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None,
11291131
self._str += (". Site initialization is disabled, did you forget to "
11301132
+ "add the site-packages directory to sys.path "
11311133
+ "or to enable your virtual environment?")
1134+
elif abi_tag := _find_incompatible_extension_module(module_name):
1135+
self._str += (
1136+
". Although a module with this name was found for a "
1137+
f"different Python version ({abi_tag})."
1138+
)
11321139
else:
11331140
suggestion = _compute_suggestion_error(exc_value, exc_traceback, module_name)
11341141
if suggestion:
@@ -1880,3 +1887,32 @@ def _levenshtein_distance(a, b, max_cost):
18801887
# Everything in this row is too big, so bail early.
18811888
return max_cost + 1
18821889
return result
1890+
1891+
1892+
def _find_incompatible_extension_module(module_name):
1893+
import importlib.machinery
1894+
import importlib.resources.readers
1895+
1896+
if not module_name or not importlib.machinery.EXTENSION_SUFFIXES:
1897+
return
1898+
1899+
# We assume the last extension is untagged (eg. .so, .pyd)!
1900+
# tests.test_traceback.MiscTest.test_find_incompatible_extension_modules
1901+
# tests that assumption.
1902+
untagged_suffix = importlib.machinery.EXTENSION_SUFFIXES[-1]
1903+
# On Windows the debug tag is part of the module file stem, instead of the
1904+
# extension (eg. foo_d.pyd), so let's remove it and just look for .pyd.
1905+
if os.name == 'nt':
1906+
untagged_suffix = untagged_suffix.removeprefix('_d')
1907+
1908+
parent, _, child = module_name.rpartition('.')
1909+
if parent:
1910+
traversable = importlib.resources.files(parent)
1911+
else:
1912+
traversable = importlib.resources.readers.MultiplexedPath(
1913+
*map(pathlib.Path, filter(os.path.isdir, sys.path))
1914+
)
1915+
1916+
for entry in traversable.iterdir():
1917+
if entry.name.startswith(child + '.') and entry.name.endswith(untagged_suffix):
1918+
return entry.name

Makefile.pre.in

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,11 @@ PY_STDMODULE_CFLAGS= $(PY_CFLAGS) $(PY_CFLAGS_NODIST) $(PY_CPPFLAGS) $(CFLAGSFOR
123123
PY_BUILTIN_MODULE_CFLAGS= $(PY_STDMODULE_CFLAGS) -DPy_BUILD_CORE_BUILTIN
124124
PY_CORE_CFLAGS= $(PY_STDMODULE_CFLAGS) -DPy_BUILD_CORE
125125
# Linker flags used for building the interpreter object files
126+
# In particular, EXE_LDFLAGS is an extra flag to provide fine grain distinction between
127+
# LDFLAGS used to build executables and shared targets.
126128
PY_CORE_LDFLAGS=$(PY_LDFLAGS) $(PY_LDFLAGS_NODIST)
129+
CONFIGURE_EXE_LDFLAGS=@EXE_LDFLAGS@
130+
PY_CORE_EXE_LDFLAGS:= $(if $(CONFIGURE_EXE_LDFLAGS), $(CONFIGURE_EXE_LDFLAGS) $(PY_LDFLAGS_NODIST), $(PY_CORE_LDFLAGS))
127131
# Strict or non-strict aliasing flags used to compile dtoa.c, see above
128132
CFLAGS_ALIASING=@CFLAGS_ALIASING@
129133

@@ -986,7 +990,7 @@ clinic-tests: check-clean-src $(srcdir)/Lib/test/clinic.test.c
986990

987991
# Build the interpreter
988992
$(BUILDPYTHON): Programs/python.o $(LINK_PYTHON_DEPS)
989-
$(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS)
993+
$(LINKCC) $(PY_CORE_EXE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS)
990994

991995
platform: $(PYTHON_FOR_BUILD_DEPS) pybuilddir.txt
992996
$(RUNSHARED) $(PYTHON_FOR_BUILD) -c 'import sys ; from sysconfig import get_platform ; print("%s-%d.%d" % (get_platform(), *sys.version_info[:2]))' >platform
@@ -1676,7 +1680,7 @@ regen-re: $(BUILDPYTHON)
16761680
$(RUNSHARED) ./$(BUILDPYTHON) $(srcdir)/Tools/build/generate_re_casefix.py $(srcdir)/Lib/re/_casefix.py
16771681

16781682
Programs/_testembed: Programs/_testembed.o $(LINK_PYTHON_DEPS)
1679-
$(LINKCC) $(PY_CORE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/_testembed.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS)
1683+
$(LINKCC) $(PY_CORE_EXE_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/_testembed.o $(LINK_PYTHON_OBJS) $(LIBS) $(MODLIBS) $(SYSLIBS)
16801684

16811685
############################################################################
16821686
# "Bootstrap Python" used to run Programs/_freeze_module.py

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1916,6 +1916,7 @@ Guo Ci Teo
19161916
Mikhail Terekhov
19171917
Victor Terrón
19181918
Pablo Galindo
1919+
Rue Ching Teh
19191920
Richard M. Tew
19201921
Srinivas Reddy Thatiparthy
19211922
Tobias Thelen

0 commit comments

Comments
 (0)