Source code for dbusmock.__main__

"""Main entry point for running mock server."""

# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation; either version 3 of the License, or (at your option) any
# later version.  See http://www.gnu.org/copyleft/lgpl.html for the full text
# of the license.

[docs] __author__ = "Martin Pitt"
import argparse import json import os import platform import subprocess import sys import dbusmock.mockobject import dbusmock.testcase
[docs] def parse_args(): """Parse command line arguments""" parser = argparse.ArgumentParser(description="mock D-Bus object") parser.add_argument( "-s", "--system", action="store_true", help="put object(s) on system bus (default: session bus or template's SYSTEM_BUS flag)", ) parser.add_argument( "--session", action="store_true", help="put object(s) on session bus (default without template; overrides template's SYSTEM_BUS flag)", ) parser.add_argument( "-l", "--logfile", metavar="PATH", help="path of log file", ) parser.add_argument( "-t", "--template", metavar="NAME", help="template to load (instead of specifying name, path, interface)", ) parser.add_argument( "name", metavar="NAME", nargs="?", help='D-Bus name to claim (e. g. "com.example.MyService") (if not using -t)', ) parser.add_argument( "path", metavar="PATH", nargs="?", help="D-Bus object path for initial/main object (if not using -t)", ) parser.add_argument( "interface", metavar="INTERFACE", nargs="?", help="main D-Bus interface name for initial object (if not using -t)", ) parser.add_argument( "-m", "--is-object-manager", action="store_true", help="automatically implement the org.freedesktop.DBus.ObjectManager interface", ) parser.add_argument( "-p", "--parameters", help="JSON dictionary of parameters to pass to the template", ) parser.add_argument( "-e", "--exec", nargs=argparse.REMAINDER, help="Command to run in the mock environment", ) arguments = parser.parse_args() if arguments.template: if arguments.name or arguments.path or arguments.interface: parser.error("--template and specifying NAME/PATH/INTERFACE are mutually exclusive") else: if not arguments.name or not arguments.path or not arguments.interface: parser.error("Not using a template, you must specify NAME, PATH, and INTERFACE") if arguments.system and arguments.session: parser.error("--system and --session are mutually exclusive") return arguments
if __name__ == "__main__": import ctypes import dbus.mainloop.glib import dbus.service
[docs] args = parse_args()
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) system_bus = args.system if args.template: module = dbusmock.mockobject.load_module(args.template) args.name = module.BUS_NAME args.path = module.MAIN_OBJ if not args.session and not args.system: system_bus = module.SYSTEM_BUS if hasattr(module, "IS_OBJECT_MANAGER"): args.is_object_manager = module.IS_OBJECT_MANAGER else: args.is_object_manager = False if args.is_object_manager and not hasattr(module, "MAIN_IFACE"): args.interface = dbusmock.mockobject.OBJECT_MANAGER_IFACE else: args.interface = module.MAIN_IFACE bus = dbusmock.testcase.DBusTestCase.get_dbus(system_bus) # quit mock when the bus is going down should_run = {True} bus.add_signal_receiver( should_run.pop, signal_name="Disconnected", path="/org/freedesktop/DBus/Local", dbus_interface="org.freedesktop.DBus.Local", ) bus_name = dbus.service.BusName(args.name, bus, allow_replacement=True, replace_existing=True, do_not_queue=True) main_object = dbusmock.mockobject.DBusMockObject( bus_name, args.path, args.interface, {}, args.logfile, args.is_object_manager ) parameters = None if args.parameters: try: parameters = json.loads(args.parameters) except ValueError as detail: sys.stderr.write(f"Malformed JSON given for parameters: {detail}\n") sys.exit(2) if not isinstance(parameters, dict): sys.stderr.write("JSON parameters must be a dictionary\n") sys.exit(2) if args.template: main_object.AddTemplate(args.template, parameters) if platform.system() == "Darwin": libglib = ctypes.cdll.LoadLibrary("libglib-2.0.dylib") else: libglib = ctypes.cdll.LoadLibrary("libglib-2.0.so.0") dbusmock.mockobject.objects[args.path] = main_object if args.exec: with subprocess.Popen(args.exec) as exec_proc: exit_status = set() @ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_int) def on_process_watch(_pid, status): """Check if the launched process is still alive""" if os.WIFEXITED(status): exit_status.add(os.WEXITSTATUS(status)) else: exit_status.add(1) should_run.pop() libglib.g_child_watch_add(exec_proc.pid, on_process_watch) while should_run: libglib.g_main_context_iteration(None, True) try: exec_proc.terminate() exec_proc.wait() except ProcessLookupError: pass sys.exit(exit_status.pop() if exit_status else exec_proc.returncode) else: while should_run: libglib.g_main_context_iteration(None, True)