diff --git a/bootstrap.py b/bootstrap.py index e6b4208..71b28a8 100755 --- a/bootstrap.py +++ b/bootstrap.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- """ Bootstrap helps you to test scripts without installing them by patching your PYTHONPATH on the fly @@ -10,20 +9,21 @@ __authors__ = ["Frédéric-Emmanuel Picca", "Jérôme Kieffer"] __contact__ = "jerome.kieffer@esrf.eu" __license__ = "MIT" -__date__ = "12/07/2024" +__date__ = "02/09/2026" -import sys +import argparse +import logging import os import subprocess -import logging -if sys.version_info[:2] < (3, 11): - import tomli -else: +import sys + +try: import tomllib as tomli +except ImportError: + import tomli logging.basicConfig() logger = logging.getLogger("bootstrap") -LIBPATH = "" def get_project_name(root_dir): """Retrieve project name by running python setup.py --name in root_dir. @@ -50,9 +50,10 @@ def build_project(name, root_dir): libdir = "Lib" # extra = ["--buildtype", "plain"] - build = os.path.join(root_dir, "build") + build_dir = f"build_py{sys.version_info[0]}{sys.version_info[1]}" + build = os.path.join(root_dir, build_dir) if not(os.path.isdir(build) and os.path.isdir(os.path.join(build, name))): - p = subprocess.Popen(["meson", "setup", "build"], + p = subprocess.Popen(["meson", "setup", build_dir], shell=False, cwd=root_dir, env=os.environ) p.wait() p = subprocess.Popen(["meson", "configure", "--prefix", "/"] + extra, @@ -77,12 +78,14 @@ def build_project(name, root_dir): home = os.path.join(build, libdir, python_version, "site-packages") home = os.path.abspath(home) - cnt = 0 + tmp = [] while not os.path.isdir(home): - cnt += 1 - home = os.path.split(home)[0] - for _ in range(cnt): - n = os.listdir(home)[0] + home, last = os.path.split(home) + tmp.append(last) + for _ in tmp: + for n in os.listdir(home): + if os.path.isdir(os.path.join(home, n)): + break home = os.path.join(home, n) logger.warning("Building %s to %s", name, home) @@ -98,7 +101,7 @@ def execfile(fullpath, globals=None, locals=None): except UnicodeDecodeError: raise SyntaxError("Not a Python script") code = compile(data, fullpath, 'exec') - exec(code, globals, locals) + exec(code, globals, locals) # noqa: S102 def run_file(filename, argv): @@ -117,14 +120,14 @@ def run_file(filename, argv): # Providing globals() as locals will force to feed the file into # globals() (for examples imports). # Without this any function call from the executed file loses imports - old_argv = sys.argv - sys.argv = full_args - logger.info("Patch the sys.argv: %s", sys.argv) - logger.info("Executing %s.main()", filename) - print("########### EXECFILE ###########") - module_globals = globals().copy() - module_globals['__file__'] = filename try: + old_argv = sys.argv + sys.argv = full_args + logger.info("Patch the sys.argv: %s", sys.argv) + logger.info("Executing %s.main()", filename) + print("########### EXECFILE ###########") + module_globals = globals().copy() + module_globals['__file__'] = filename execfile(filename, module_globals, module_globals) finally: sys.argv = old_argv @@ -155,10 +158,10 @@ def run_entry_point(target_name, entry_point, argv): logger.info("Execute target %s (function %s from module %s) using importlib", target_name, function_name, module_name) full_args = [target_name] full_args.extend(argv) - old_argv = sys.argv - sys.argv = full_args - print("########### IMPORTLIB ###########") try: + old_argv = sys.argv + sys.argv = full_args + print("########### IMPORTLIB ###########") module = importlib.import_module(module_name) if hasattr(module, function_name): func = getattr(module, function_name) @@ -177,7 +180,7 @@ def find_executable(target): - Then search the script from the PATH environment variable. :param str target: Name of the script - :returns: Returns a tuple: kind, name. + :returns: Returns a tuple: (kind, name) or (kind, name, entry_point). """ if os.path.isfile(target): return ("path", os.path.abspath(target)) @@ -192,50 +195,95 @@ def find_executable(target): for script, entry_point in scripts.items(): if script == target: - print(script, entry_point) + #print(script, entry_point) return ("entry_point", target, entry_point) return None, None -PROJECT_DIR = os.path.dirname(os.path.abspath(__file__)) -PROJECT_NAME = get_project_name(PROJECT_DIR) -logger.info("Project name: %s", PROJECT_NAME) - -if __name__ == "__main__": - LIBPATH = build_project(PROJECT_NAME, PROJECT_DIR) - if len(sys.argv) < 2: - logger.warning("usage: ./bootstrap.py