Last active
January 26, 2026 23:58
-
-
Save mara004/ec32b465789f67ea086720f8c66eb878 to your computer and use it in GitHub Desktop.
Wrap a python module's CLI entrypoint with argfiles support
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #! /usr/bin/env python3 | |
| # SPDX-FileCopyrightText: 2026 mara004 <geisserml@gmail.com> | |
| # SPDX-License-Identifier: BSD-2-Clause | |
| import sys | |
| import shlex | |
| from pathlib import Path | |
| from importlib import import_module | |
| from importlib.metadata import entry_points | |
| def _read_argfiles(argv, parents): | |
| #print(argv, parents) | |
| for arg in argv: | |
| if arg.startswith("@"): | |
| argfile_path = Path(arg[1:]).expanduser().resolve() | |
| if argfile_path in parents: | |
| raise RuntimeError("self-includes are prohibited (would be infinite recursion)") | |
| argfile_content = argfile_path.read_text().strip() | |
| for l in argfile_content.split("\n"): | |
| parents.append(argfile_path) | |
| try: | |
| yield from _read_argfiles(shlex.split(l), parents) | |
| finally: | |
| parents.pop() #popped = ... | |
| #assert popped is argfile_path | |
| else: | |
| yield arg | |
| def main(): | |
| if sys.argv[1] in ("-h", "--help"): | |
| print(f"Usage: {sys.argv[0]} MODNAME ARGFILE_ARGS", file=sys.stderr) | |
| return | |
| modname = sys.argv[1] | |
| ep, = entry_points(group="console_scripts", name=modname) | |
| modpath, funcname = ep.value.rsplit(":", maxsplit=1) | |
| # list slicing copies | |
| parents = [] | |
| argv_iter = _read_argfiles(sys.argv[2:], parents) | |
| sys.argv.clear() | |
| sys.argv.append(modname) | |
| sys.argv.extend(argv_iter) | |
| #assert not parents # len 0 | |
| module = import_module(modpath) | |
| func = getattr(module, funcname) | |
| func() | |
| if __name__ == "__main__": | |
| main() |
Author
Author
todo: a ValueError would perhaps fit better than a RuntimeError for the recursive includes
Author
Another idea: we could change parents to a list (created in main()) and use append/pop.
This may avoid the tuple re-creations parents=(*parents, argfile_path).
Author
Done, I think.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See also ctypesgen/ctypesgen#223 (comment) (thread) for background.