I am trying to use dbus to drive Inkscape from scripts
This code - which I got from here - works ok:
# Start after inkscape is running.
print ("DBus test")
import gi
gi.require_version("Gio", "2.0")
from gi.repository import Gio, GLib
try:
bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
except BaseException:
print("No DBus bus")
exit()
print ("Got DBus bus")
proxy = Gio.DBusProxy.new_sync(bus, Gio.DBusProxyFlags.NONE, None,
'org.freedesktop.DBus',
'/org/freedesktop/DBus',
'org.freedesktop.DBus', None)
names_list = proxy.call_sync('ListNames', None, Gio.DBusCallFlags.NO_AUTO_START, 500, None)
# names_list is a GVariant, must unpack
names = names_list.unpack()[0]
# Look for Inkscape; names is a tuple.
for name in names:
if ('org.inkscape.Inkscape' in name):
print ("Found: " + name)
break
print ("Name: " + name)
appGroupName = "/org/inkscape/Inkscape"
winGroupName = appGroupName + "/window/1"
docGroupName = appGroupName + "/document/1"
applicationGroup = Gio.DBusActionGroup.get( bus, name, appGroupName)
windowGroup = Gio.DBusActionGroup.get(bus, name, winGroupName)
documentGroup = Gio.DBusActionGroup.get(bus, name, docGroupName)
# Activate actions. Draw a few objects first.
applicationGroup.activate_action('select-all', GLib.Variant.new_string('all'))
applicationGroup.activate_action('object-rotate-90-cw', None)
windowGroup.activate_action('tool-switch', GLib.Variant.new_string('Arc'))
windowGroup.activate_action('canvas-zoom-page', None)
When I try to translate it to use dbus
like this:
#!/usr/bin/env python
# Start after Inkscape is running.
import dbus
from xml.etree import ElementTree as ET
print("DBus test")
try:
# Connect to the session bus
bus = dbus.SessionBus()
except dbus.exceptions.DBusException as e:
print(f"No DBus bus: {e}")
exit()
print("Got DBus bus")
# Get the list of names on the bus
proxy = bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
interface = dbus.Interface(proxy, 'org.freedesktop.DBus')
names = interface.ListNames()
# Look for Inkscape
name = None
for n in names:
if 'org.inkscape.Inkscape' in n:
name = n
print(f"Found: {name}")
break
if not name:
print("Inkscape not found")
exit()
print(f"Name: {name}")
appGroupName = "/org/inkscape/Inkscape"
winGroupName = appGroupName + "/window/1"
docGroupName = appGroupName + "/document/1"
def activate_action(group, action, parameter=None):
try:
group.Activate(action, parameter, dbus_interface='org.gtk.Actions')
print(f"Activated action: {action} with parameter: {parameter}")
except dbus.exceptions.DBusException as e:
print(f"Failed to activate action {action}: {e}")
applicationGroup = bus.get_object(name, appGroupName)
windowGroup = bus.get_object(name, winGroupName)
documentGroup = bus.get_object(name, docGroupName)
# Activate actions. Draw a few objects first.
activate_action(applicationGroup, 'select-all', 'all')
activate_action(applicationGroup, 'object-rotate-90-cw')
it fails with this message:
ERROR:dbus.connection:Unable to set arguments ('select-all', 'all') according to signature 'sava{sv}': <class 'TypeError'>: More items found in D-Bus signature than in Python arguments
Traceback (most recent call last):
File "/home/simone/inkscape_experiments/dbus_05.py", line 54, in <module>
activate_action(applicationGroup, 'select-all', 'all')
File "/home/simone/inkscape_experiments/dbus_05.py", line 44, in activate_action
group.Activate(action, parameter, dbus_interface='org.gtk.Actions')
File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 72, in __call__
return self._proxy_method(*args, **keywords)
File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 141, in __call__
return self._connection.call_blocking(self._named_service,
File "/usr/lib/python3/dist-packages/dbus/connection.py", line 643, in call_blocking
message.append(signature=signature, *args)
TypeError: More items found in D-Bus signature than in Python arguments
What's the issue here? is there a way to inspect d-bus signatures and use that to call things correctly?
Error shows signature 'sava{sv}'
.
I found
TypeError: More items found in D-Bus signature than in Python arguments)
with similar 'as'
and explanation as Array with Strings
which means list [String1, String2, ...]
What the heck is a dbus argument of type a{sa{sv}} in the Network Manager API?
with similar 'a{sv}'
and explanation as Array with Strings and Variants
which means dictionary {String1:Variant1, String2:Variant2, ...}
Get 'state' from dbus using python - Stack Overflow
with More items found in D-Bus signature than in Python arguments
And all of this may suggest that 'sava{sv}'
means 's,av,a{sv}'
and it may need:
String
, Array of Variants
(list), Array of Strings and Variants
(dict)
group.Activate(String, [Variant, ...], {String:Variant, ...})
So I tested
group.Activate('select-all', ['all'], {}, dbus_interface='org.gtk.Actions')
group.Activate('object-rotate-90-cw', [], {}, dbus_interface='org.gtk.Actions')
And it works for me.
Finally I created function with *args
and **kwargs
def activate_action(group, action, *args, **kwargs): # with * and **
try:
# without * and ** to keep it as list and dict
group.Activate(action, args, kwargs, dbus_interface='org.gtk.Actions')
print(f"Activated action: {action} with parameters: args:{args} kwargs:{kwargs}")
except dbus.exceptions.DBusException as e:
print(f"Failed to activate action {action}: {e}")
activate_action(applicationGroup, 'select-all', 'all')
activate_action(applicationGroup, 'object-rotate-90-cw')