8000 gh-93939: Add script to check extension modules by tiran · Pull Request #94545 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-93939: Add script to check extension modules #94545

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jul 5, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Improve doc string, rename checker script
  • Loading branch information
tiran committed Jul 4, 2022
commit ab9e52bc58877951a54daca12dd0525866058de6
2 changes: 1 addition & 1 deletion Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -919,7 +919,7 @@ oldsharedmods: $(SHAREDMODS) pybuilddir.txt
done

checksharedmods: oldsharedmods sharedmods $(PYTHON_FOR_BUILD_DEPS)
@$(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/Tools/scripts/check_modules.py
@$(RUNSHARED) $(PYTHON_FOR_BUILD) $(srcdir)/Tools/scripts/check_extension_modules.py

Modules/Setup.local:
@# Create empty Setup.local when file was deleted by user
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
"""Check extension modules

The script checks extension and built-in modules. It verifies that the
modules have been built and that they can be import successfully. Missing
modules and failed imports are reported to the user. Shared extension
files are renamed on failed import.

Module information are parsed from several sources:

- core modules hard-coded in Modules/config.c.in
- Windows-specific modyles that are hard-coded in PC/config.c
- MODULE_{name}_STATE entries in Makefile (provided through sysconfig)
- Various makesetup files:
- $(srcdir)/Modules/Setup
- Modules/Setup.[local|bootstrap|stdlib] files, which are generated
from $(srcdir)/Modules/Setup.*.in files

See --help for more information
"""
import argparse
import collections
import enum
import logging
from operator import mod
import os
import pathlib
import re
Expand Down Expand Up @@ -47,22 +65,47 @@
logger = logging.getLogger(__name__)

parser = argparse.ArgumentParser(
prog="check_modules", description="Check extension modules"
prog="check_extension_modules",
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter,
)

parser.add_argument(
"--verbose",
action="store_true",
help="Verbose, report builtin, shared, and unavailable modules",
)

parser.add_argument(
"--debug",
action="store_true",
help="Enable debug logging",
)

parser.add_argument(
"--verbose",
action="store_true",
help="Verbose output",
"--strict",
action=argparse.BooleanOptionalAction,
help=(
"Strict check, fail when a module is missing or fails to import"
"(default: no, unless env var PYTHONSTRICTEXTENSIONBUILD is set)"
),
default=bool(os.environ.get("PYTHONSTRICTEXTENSIONBUILD")),
)

parser.add_argument(
"--cross-compiling",
action=argparse.BooleanOptionalAction,
help=(
"Use cross-compiling checks "
"(default: no, unless env var _PYTHON_HOST_PLATFORM is set)."
),
default="_PYTHON_HOST_PLATFORM" in os.environ,
)

parser.add_argument(
"--list-module-names",
action="store_true",
help="Print a list of module names to stdout",
help="Print a list of module names to stdout and exit",
)


Expand Down Expand Up @@ -94,9 +137,9 @@ class ModuleChecker:
"Modules/Setup.stdlib",
)

def __init__(self):
self.cross_compiling = "_PYTHON_HOST_PLATFORM" in os.environ
self.strict_extensions_build = os.environ.get("PYTHONSTRICTEXTENSIONBUILD")
def __init__(self, cross_compiling: bool = False, strict: bool = False):
self.cross_compiling = cross_compiling
self.strict_extensions_build = strict
self.ext_suffix = sysconfig.get_config_var("EXT_SUFFIX")
self.platform = sysconfig.get_platform()
self.builddir = self.get_builddir()
Expand Down Expand Up @@ -349,9 +392,22 @@ def get_location(self, modinfo: ModuleInfo) -> pathlib.Path:
else:
return None

def _check_file(self, modinfo: ModuleInfo, spec: ModuleSpec):
"""Check that the module file is present and not empty"""
if spec.loader is BuiltinImporter:
return
try:
st = os.stat(spec.origin)
except FileNotFoundError:
logger.error("%s (%s) is missing", modinfo.name, spec.origin)
raise
if not st.st_size:
raise ImportError(f"{spec.origin} is an empty file")

def check_module_import(self, modinfo: ModuleInfo):
"""Attempt to import module and report errors"""
spec = self.get_spec(modinfo)
self._check_file(modinfo, spec)
try:
with warnings.catch_warnings():
# ignore deprecation warning from deprecated modules
Expand All @@ -367,11 +423,7 @@ def check_module_import(self, modinfo: ModuleInfo):
def check_module_cross(self, modinfo: ModuleInfo):
"""Sanity check for cross compiling"""
spec = self.get_spec(modinfo)
8000 if spec.loader is BuiltinImporter:
return
st = os.stat(spec.origin)
if not st.st_size:
raise ImportError(f"{spec.origin} is an empty file")
self._check_file(modinfo, spec)

def rename_module(self, modinfo: ModuleInfo) -> None:
"""Rename module file"""
Expand Down Expand Up @@ -406,22 +458,29 @@ def rename_module(self, modinfo: ModuleInfo) -> None:

def main():
args = parser.parse_args()
print(args)
if args.debug:
args.verbose = True
logging.basicConfig(
level=logging.DEBUG if args.debug else logging.INFO,
format="[%(levelname)s] %(message)s",
)

checker = ModuleChecker()
checker = ModuleChecker(
cross_compiling=args.cross_compiling,
strict=args.strict,
)
if args.list_module_names:
names = checker.list_module_names(all=True)
for name in sorted(names):
print(name)
else:
checker.check()
checker.summary(verbose=args.verbose)
checker.check_strict_build()
try:
checker.check_strict_build()
except RuntimeError as e:
parser.exit(1, f"\nError: {e}\n")


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion Tools/scripts/generate_stdlib_module_names.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import sys
import sysconfig

from check_modules import ModuleChecker
from check_extension_modules import ModuleChecker


SRC_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
Expand Down
0