bpo-42545: Improve the error message in the stable API script (GH-23648)

This commit is contained in:
Pablo Galindo 2020-12-04 23:19:21 +00:00 committed by GitHub
parent 85f1dedb8d
commit 79c1849b9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 40 additions and 20 deletions

View File

@ -60,15 +60,33 @@ def get_exported_symbols(library, dynamic=False):
yield symbol yield symbol
def check_library(library, abi_funcs, dynamic=False): def check_library(stable_abi_file, library, abi_funcs, dynamic=False):
available_symbols = set(get_exported_symbols(library, dynamic)) available_symbols = set(get_exported_symbols(library, dynamic))
missing_symbols = abi_funcs - available_symbols missing_symbols = abi_funcs - available_symbols
if missing_symbols: if missing_symbols:
print( raise Exception(
f"Some symbols from the stable ABI are missing: {', '.join(missing_symbols)}" f"""\
Some symbols from the limited API are missing: {', '.join(missing_symbols)}
This error means that there are some missing symbols among the ones exported
in the Python library ("libpythonx.x.a" or "libpythonx.x.so"). This normally
means that some symbol, function implementation or a prototype, belonging to
a symbol in the limited API has been deleted or is missing.
Check if this was a mistake and if not, update the file containing the limited
API symbols. This file is located at:
{stable_abi_file}
You can read more about the limited API and its contracts at:
https://docs.python.org/3/c-api/stable.html
And in PEP 384:
https://www.python.org/dev/peps/pep-0384/
"""
) )
return 1
return 0
def generate_limited_api_symbols(args): def generate_limited_api_symbols(args):
@ -107,7 +125,6 @@ def generate_limited_api_symbols(args):
) )
for symbol in sorted(stable_symbols): for symbol in sorted(stable_symbols):
output_file.write(f"{symbol}\n") output_file.write(f"{symbol}\n")
sys.exit(0)
def get_limited_api_macros(headers): def get_limited_api_macros(headers):
@ -187,21 +204,24 @@ def check_symbols(parser_args):
if symbol and not symbol.startswith("#") if symbol and not symbol.startswith("#")
} }
ret = 0 try:
# static library # static library
LIBRARY = sysconfig.get_config_var("LIBRARY") LIBRARY = sysconfig.get_config_var("LIBRARY")
if not LIBRARY: if not LIBRARY:
raise Exception("failed to get LIBRARY variable from sysconfig") raise Exception("failed to get LIBRARY variable from sysconfig")
ret = check_library(LIBRARY, abi_funcs) check_library(parser_args.stable_abi_file, LIBRARY, abi_funcs)
# dynamic library # dynamic library
LDLIBRARY = sysconfig.get_config_var("LDLIBRARY") LDLIBRARY = sysconfig.get_config_var("LDLIBRARY")
if not LDLIBRARY: if not LDLIBRARY:
raise Exception("failed to get LDLIBRARY variable from sysconfig") raise Exception("failed to get LDLIBRARY variable from sysconfig")
if LDLIBRARY != LIBRARY: if LDLIBRARY != LIBRARY:
ret |= check_library(LDLIBRARY, abi_funcs, dynamic=True) check_library(
parser_args.stable_abi_file, LDLIBRARY, abi_funcs, dynamic=True
sys.exit(ret) )
except Exception as e:
print(e, file=sys.stderr)
sys.exit(1)
def main(): def main():