CLI: support defining custom commands via C++ & Python API

Add support for add-ons to define commands using the new argument
`-c` or `--command`.

Commands behave as follows:

- Passing in a command enables background mode without the need to pass
  in `--background`.
- All arguments following the command are passed to the command
  (without the need to use the `--` argument).
- Add-ons can define their own commands via
  `bpy.utils.register_cli_command` (see examples in API docs).
- Passing in `--command help` lists all available commands.

Ref !119115
This commit is contained in:
Campbell Barton
2024-03-08 11:07:41 +11:00
parent 5214e6f35d
commit 9372e0dfe0
15 changed files with 776 additions and 1 deletions

View File

@@ -0,0 +1,74 @@
"""
Using Python Argument Parsing
-----------------------------
This example shows how the Python ``argparse`` module can be used with a custom command.
Using ``argparse`` is generally recommended as it has many useful utilities and
generates a ``--help`` message for your command.
"""
import os
import sys
import bpy
def argparse_create():
import argparse
parser = argparse.ArgumentParser(
prog=os.path.basename(sys.argv[0]) + " --command keyconfig_export",
description="Write key-configuration to a file.",
)
parser.add_argument(
"-o", "--output",
dest="output",
metavar='OUTPUT',
type=str,
help="The path to write the keymap to.",
required=True,
)
parser.add_argument(
"-a", "--all",
dest="all",
action="store_true",
help="Write all key-maps (not only customized key-maps).",
required=False,
)
return parser
def keyconfig_export(argv):
parser = argparse_create()
args = parser.parse_args(argv)
# Ensure the key configuration is loaded in background mode.
bpy.utils.keyconfig_init()
bpy.ops.preferences.keyconfig_export(
filepath=args.output,
all=args.all,
)
return 0
cli_commands = []
def register():
cli_commands.append(bpy.utils.register_cli_command("keyconfig_export", keyconfig_export))
def unregister():
for cmd in cli_commands:
bpy.utils.unregister_cli_command(cmd)
cli_commands.clear()
if __name__ == "__main__":
register()

View File

@@ -0,0 +1,43 @@
"""
Custom Commands
---------------
Registering commands makes it possible to conveniently expose command line
functionality via commands passed to (``-c`` / ``--command``).
"""
import sys
import os
def sysinfo_command(argv):
import tempfile
import sys_info
if argv and argv[0] == "--help":
print("Print system information & exit!")
return 0
with tempfile.TemporaryDirectory() as tempdir:
filepath = os.path.join(tempdir, "system_info.txt")
sys_info.write_sysinfo(filepath)
with open(filepath, "r", encoding="utf-8") as fh:
sys.stdout.write(fh.read())
return 0
cli_commands = []
def register():
cli_commands.append(bpy.utils.register_cli_command("sysinfo", sysinfo_command))
def unregister():
for cmd in cli_commands:
bpy.utils.unregister_cli_command(cmd)
cli_commands.clear()
if __name__ == "__main__":
register()