From b933c9b41120ab4caa00a378deeadafba885f72a Mon Sep 17 00:00:00 2001 From: geisserml Date: Wed, 21 Feb 2024 17:53:18 +0100 Subject: [PATCH] Correctly handle print_info() for api_main() --- src/ctypesgen/__init__.py | 3 +++ src/ctypesgen/__main__.py | 18 +++++++++----- src/ctypesgen/printer_python.py | 44 +++++++++++++++------------------ 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/ctypesgen/__init__.py b/src/ctypesgen/__init__.py index 85459bf..25c85e8 100644 --- a/src/ctypesgen/__init__.py +++ b/src/ctypesgen/__init__.py @@ -55,6 +55,9 @@ # Helper modules from . import messages +# Entry points +from .__main__ import main, api_main + __version__ = version.VERSION.partition("-")[-1] VERSION = __version__ PYPDFIUM2_SPECIFIC = True diff --git a/src/ctypesgen/__main__.py b/src/ctypesgen/__main__.py index bf4604c..ab61afe 100644 --- a/src/ctypesgen/__main__.py +++ b/src/ctypesgen/__main__.py @@ -7,6 +7,7 @@ import argparse import itertools from pathlib import Path +from pprint import pformat from ctypesgen import ( messages as msgs, @@ -16,7 +17,9 @@ printer_python, printer_json, ) - +from ctypesgen.printer_python import ( + txtpath, PRIVATE_PATHS, +) # -- Argparse-based entry point -- @@ -25,7 +28,8 @@ def main(given_argv=sys.argv[1:]): args = get_parser().parse_args(given_argv) postparse(args) - main_impl(args, given_argv) + cmd_str = " ".join(["ctypesgen"] + [shlex.quote(txtpath(a)) for a in given_argv]) + main_impl(args, cmd_str) def postparse(args): args.cppargs = list( itertools.chain(*args.cppargs) ) @@ -49,9 +53,11 @@ def api_main(args): real_args = defaults.copy() real_args.update(args) real_args = argparse.Namespace(**real_args) - given_argv = "Unknown API Call".split(" ") # FIXME - return main_impl(real_args, given_argv=given_argv) + args_str = str(pformat(args)) + for p, x in PRIVATE_PATHS: + args_str = args_str.replace(p, x) + return main_impl(real_args, f"ctypesgen.api_main(\n{args_str}\n)") # Adapted from https://stackoverflow.com/a/59395868/15547292 @@ -70,7 +76,7 @@ def _get_parser_requires(parser): # -- Main implementation -- -def main_impl(args, given_argv): +def main_impl(args, cmd_str): assert args.headers or args.system_headers, "Either --headers or --system-headers required." @@ -105,7 +111,7 @@ def main_impl(args, given_argv): raise RuntimeError("No target members found.") printer = {"py": printer_python, "json": printer_json}[args.output_language].WrapperPrinter msgs.status_message(f"Printing to {args.output}.") - printer(args.output, args, data, given_argv) + printer(args.output, args, data, cmd_str) msgs.status_message("Wrapping complete.") diff --git a/src/ctypesgen/printer_python.py b/src/ctypesgen/printer_python.py index c00410d..adee104 100755 --- a/src/ctypesgen/printer_python.py +++ b/src/ctypesgen/printer_python.py @@ -1,4 +1,3 @@ -import shlex import shutil from pathlib import Path from textwrap import indent @@ -22,12 +21,26 @@ def paragraph_ctx(txt): file.write(f"\n# -- End {txt} --") return paragraph_ctx +PRIVATE_PATHS = [(str(Path.home()), "~")] +if Path.cwd() != Path("/"): # don't strip unix root + PRIVATE_PATHS += [(str(Path.cwd()), ".")] +# sort descending by length to avoid interference +PRIVATE_PATHS.sort(key=lambda x: len(x[0]), reverse=True) + +def txtpath(s): + # Returns a path string suitable for embedding into the output, with private paths stripped + s = str(s) + for p, x in PRIVATE_PATHS: + if s.startswith(p): + return x + s[len(p):] + return s + # Important: Concerning newlines handling, please read docs/dev_comments.md class WrapperPrinter: - def __init__(self, outpath, opts, data, argv): + def __init__(self, outpath, opts, data, cmd_str): self.opts = opts @@ -35,7 +48,7 @@ def __init__(self, outpath, opts, data, argv): self.paragraph_ctx = ParagraphCtxFactory(self.file) - self.print_info(argv) + self.print_info(cmd_str) self.file.write( "\n\nimport ctypes" "\nfrom ctypes import *" @@ -65,26 +78,11 @@ def __init__(self, outpath, opts, data, argv): for fp in opts.inserted_files: self.file.write("\n\n\n") - self._embed_file(fp, f"inserted file '{self._txtpath(fp)}'") + self._embed_file(fp, f"inserted file '{txtpath(fp)}'") self.file.write("\n") - PRIVATE_PATHS_TABLE = [(str(Path.home()), "~")] - if Path.cwd() != Path("/"): # don't strip unix root - PRIVATE_PATHS_TABLE += [(str(Path.cwd()), ".")] - # sort descending by length to avoid interference - PRIVATE_PATHS_TABLE.sort(key=lambda x: len(x[0]), reverse=True) - - @classmethod - def _txtpath(cls, s): - # Returns a path string suitable for embedding into the output, with private paths stripped - s = str(s) - for p, x in cls.PRIVATE_PATHS_TABLE: - if s.startswith(p): - return x + s[len(p):] - return s - def _embed_file(self, fp, desc): with self.paragraph_ctx(desc), open(fp, "r") as src_fh: self.file.write("\n\n") @@ -99,13 +97,11 @@ def _srcinfo(self, src): if fp in ("", ""): self.file.write(f"# {fp}\n") else: - self.file.write(f"# {self._txtpath(fp)}: {lineno}\n") + self.file.write(f"# {txtpath(fp)}: {lineno}\n") - def print_info(self, argv): - argv = [self._txtpath(a) for a in argv] - argv_str = ' '.join([shlex.quote(a) for a in argv]) - self.file.write(f'R"""\nAuto-generated by:\nctypesgen {argv_str}\n"""') + def print_info(self, cmd_str): + self.file.write(f'R"""\nAuto-generated by:\n{cmd_str}\n"""') def print_loader(self, opts):