mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-05-05 11:08:03 +02:00
* python/dbus_bindings.pyx.in:
- added new type classes for hinting to the marashaler what type to send over the wire - added int16 and uint16 marshalers - Fixed a bug in the type constants that caused int32 to go out as uint16 over the wire * python/dbus.py: split up into different files and renamed _dbus.py * python/__init__.py, python/_util.py, python/decorators.py, python/exceptions.py, python/proxies.py, python/services.py, python/types.py: new files split off from dbus.py * python/Makefile.am: Add new files, remove dbus.py and install all python files to <python module dir>/dbus * python/examples/*: Added #!/usr/bin/env python to the top of every example. Patch provided by Tatavarty Kalyan
This commit is contained in:
parent
eb8bfeb8f2
commit
ac3b8d0a70
19 changed files with 778 additions and 568 deletions
17
ChangeLog
17
ChangeLog
|
|
@ -1,3 +1,20 @@
|
|||
2005-05-01 John (J5) Palmieri <johnp@redhat.com>
|
||||
|
||||
* python/dbus_bindings.pyx.in:
|
||||
- added new type classes for hinting to the marashaler what type
|
||||
to send over the wire
|
||||
- added int16 and uint16 marshalers
|
||||
- Fixed a bug in the type constants that caused int32 to go out
|
||||
as uint16 over the wire
|
||||
* python/dbus.py: split up into different files and renamed _dbus.py
|
||||
* python/__init__.py, python/_util.py, python/decorators.py,
|
||||
python/exceptions.py, python/proxies.py, python/services.py,
|
||||
python/types.py: new files split off from dbus.py
|
||||
* python/Makefile.am: Add new files, remove dbus.py and
|
||||
install all python files to <python module dir>/dbus
|
||||
* python/examples/*: Added #!/usr/bin/env python to the top of
|
||||
every example. Patch provided by Tatavarty Kalyan
|
||||
|
||||
2005-04-25 John (J5) Palmieri <johnp@redhat.com>
|
||||
|
||||
* NEWS: Update to 0.33
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ SUBDIRS=examples
|
|||
|
||||
INCLUDES=-I$(top_builddir) -I$(top_builddir)/dbus $(DBUS_CLIENT_CFLAGS) $(DBUS_GLIB_CFLAGS) $(DBUS_GLIB_TOOL_CFLAGS) $(PYTHON_INCLUDES)
|
||||
|
||||
dbusdir = $(pythondir)
|
||||
dbus_PYTHON = dbus.py
|
||||
dbusdir = $(pythondir)/dbus
|
||||
dbus_PYTHON = __init__.py _dbus.py decorators.py exceptions.py services.py proxies.py _util.py types.py
|
||||
|
||||
dbusbindingsdir = $(pythondir)
|
||||
dbusbindingsdir = $(pythondir)/dbus
|
||||
dbusbindings_LTLIBRARIES = dbus_bindings.la
|
||||
|
||||
dbus_bindings_la_LDFLAGS = -module -avoid-version -fPIC -export-symbols-regex initdbus_bindings
|
||||
|
|
|
|||
6
python/__init__.py
Normal file
6
python/__init__.py
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
from _dbus import *
|
||||
from decorators import *
|
||||
from services import *
|
||||
from types import *
|
||||
|
||||
version = (0, 40, 1)
|
||||
219
python/_dbus.py
Normal file
219
python/_dbus.py
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
|
||||
"""Module for high-level communication over the FreeDesktop.org Bus (DBus)
|
||||
|
||||
DBus allows you to share and access remote objects between processes
|
||||
running on the desktop, and also to access system services (such as
|
||||
the print spool).
|
||||
|
||||
To use DBus, first get a Bus object, which provides a connection to one
|
||||
of a few standard dbus-daemon instances that might be running. From the
|
||||
Bus you can get a RemoteService. A service is provided by an application or
|
||||
process connected to the Bus, and represents a set of objects. Once you
|
||||
have a RemoteService you can get a RemoteObject that implements a specific interface
|
||||
(an interface is just a standard group of member functions). Then you can call
|
||||
those member functions directly.
|
||||
|
||||
You can think of a complete method call as looking something like:
|
||||
|
||||
Bus:SESSION -> Service:org.gnome.Evolution -> Object:/org/gnome/Evolution/Inbox -> Interface: org.gnome.Evolution.MailFolder -> Method: Forward('message1', 'seth@gnome.org')
|
||||
|
||||
This communicates over the SESSION Bus to the org.gnome.Evolution process to call the
|
||||
Forward method of the /org/gnome/Evolution/Inbox object (which provides the
|
||||
org.gnome.Evolution.MailFolder interface) with two string arguments.
|
||||
|
||||
For example, the dbus-daemon itself provides a service and some objects:
|
||||
|
||||
# Get a connection to the desktop-wide SESSION bus
|
||||
bus = dbus.Bus(dbus.Bus.TYPE_SESSION)
|
||||
|
||||
# Get the service provided by the dbus-daemon named org.freedesktop.DBus
|
||||
dbus_service = bus.get_service('org.freedesktop.DBus')
|
||||
|
||||
# Get a reference to the desktop bus' standard object, denoted
|
||||
# by the path /org/freedesktop/DBus. The object /org/freedesktop/DBus
|
||||
# implements the 'org.freedesktop.DBus' interface
|
||||
dbus_object = dbus_service.get_object('/org/freedesktop/DBus',
|
||||
'org.freedesktop.DBus')
|
||||
|
||||
# One of the member functions in the org.freedesktop.DBus interface
|
||||
# is ListServices(), which provides a list of all the other services
|
||||
# registered on this bus. Call it, and print the list.
|
||||
print(dbus_object.ListServices())
|
||||
"""
|
||||
|
||||
import dbus_bindings
|
||||
from decorators import *
|
||||
from proxies import *
|
||||
from exceptions import *
|
||||
from services import *
|
||||
|
||||
import re
|
||||
import inspect
|
||||
|
||||
_threads_initialized = 0
|
||||
def init_gthreads ():
|
||||
global _threads_initialized
|
||||
if not _threads_initialized:
|
||||
dbus_bindings.init_gthreads ()
|
||||
_threads_initialized = 1
|
||||
|
||||
class Bus:
|
||||
"""A connection to a DBus daemon.
|
||||
|
||||
One of three possible standard buses, the SESSION, SYSTEM,
|
||||
or STARTER bus
|
||||
"""
|
||||
TYPE_SESSION = dbus_bindings.BUS_SESSION
|
||||
TYPE_SYSTEM = dbus_bindings.BUS_SYSTEM
|
||||
TYPE_STARTER = dbus_bindings.BUS_STARTER
|
||||
|
||||
"""bus_type=[Bus.TYPE_SESSION | Bus.TYPE_SYSTEM | Bus.TYPE_STARTER]
|
||||
"""
|
||||
|
||||
START_REPLY_SUCCESS = dbus_bindings.DBUS_START_REPLY_SUCCESS
|
||||
START_REPLY_ALREADY_RUNNING = dbus_bindings.DBUS_START_REPLY_ALREADY_RUNNING
|
||||
|
||||
def __init__(self, bus_type=TYPE_SESSION, glib_mainloop=True):
|
||||
self._connection = dbus_bindings.bus_get(bus_type)
|
||||
|
||||
self._connection.add_filter(self._signal_func)
|
||||
self._match_rule_to_receivers = { }
|
||||
if (glib_mainloop):
|
||||
self._connection.setup_with_g_main()
|
||||
|
||||
def get_connection(self):
|
||||
return self._connection
|
||||
|
||||
def get_session():
|
||||
"""Static method that returns the session bus"""
|
||||
return SessionBus()
|
||||
|
||||
get_session = staticmethod(get_session)
|
||||
|
||||
def get_system():
|
||||
"""Static method that returns the system bus"""
|
||||
return SystemBus()
|
||||
|
||||
get_system = staticmethod(get_system)
|
||||
|
||||
|
||||
def get_starter():
|
||||
"""Static method that returns the starter bus"""
|
||||
return StarterBus()
|
||||
|
||||
get_starter = staticmethod(get_starter)
|
||||
|
||||
|
||||
def get_object(self, named_service, object_path):
|
||||
"""Get a proxy object to call over the bus"""
|
||||
return ProxyObject(self, named_service, object_path)
|
||||
|
||||
def add_signal_receiver(self, handler_function, signal_name=None, dbus_interface=None, named_service=None, path=None):
|
||||
match_rule = self._get_match_rule(signal_name, dbus_interface, named_service, path)
|
||||
|
||||
if (not self._match_rule_to_receivers.has_key(match_rule)):
|
||||
self._match_rule_to_receivers[match_rule] = [handler_function]
|
||||
else:
|
||||
self._match_rule_to_receivers[match_rule].append(handler_function)
|
||||
|
||||
dbus_bindings.bus_add_match(self._connection, match_rule)
|
||||
|
||||
def remove_signal_receiver(self, handler_function, signal_name=None, dbus_interface=None, named_service=None, path=None):
|
||||
match_rule = self._get_match_rule(signal_name, dbus_interface, named_service, path)
|
||||
|
||||
if self._match_rule_to_receivers.has_key(match_rule):
|
||||
if self._match_rule_to_receivers[match_rule].__contains__(handler_function):
|
||||
self._match_rule_to_receivers[match_rule].pop(handler_function)
|
||||
dbus_bindings.bus_remove_match(self._connection, match_rule)
|
||||
|
||||
def get_unix_user(self, named_service):
|
||||
"""Get the unix user for the given named_service on this Bus"""
|
||||
return dbus_bindings.bus_get_unix_user(self._connection, named_service)
|
||||
|
||||
#TODO: Rethink match rules. Right now matches have to be exact.
|
||||
def _get_match_rule(self, signal_name, dbus_interface, named_service, path):
|
||||
match_rule = "type='signal'"
|
||||
if (dbus_interface):
|
||||
match_rule = match_rule + ",interface='%s'" % (dbus_interface)
|
||||
if (named_service):
|
||||
if (named_service[0] != ':' and named_service != "org.freedesktop.DBus"):
|
||||
bus_object = self.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
|
||||
named_service = bus_object.GetNameOwner(named_service, dbus_interface='org.freedesktop.DBus')
|
||||
|
||||
match_rule = match_rule + ",sender='%s'" % (named_service)
|
||||
if (path):
|
||||
match_rule = match_rule + ",path='%s'" % (path)
|
||||
if (signal_name):
|
||||
match_rule = match_rule + ",member='%s'" % (signal_name)
|
||||
return match_rule
|
||||
|
||||
def _signal_func(self, connection, message):
|
||||
if (message.get_type() != dbus_bindings.MESSAGE_TYPE_SIGNAL):
|
||||
return dbus_bindings.HANDLER_RESULT_NOT_YET_HANDLED
|
||||
|
||||
dbus_interface = message.get_interface()
|
||||
named_service = message.get_sender()
|
||||
path = message.get_path()
|
||||
signal_name = message.get_member()
|
||||
|
||||
match_rule = self._get_match_rule(signal_name, dbus_interface, named_service, path)
|
||||
|
||||
if (self._match_rule_to_receivers.has_key(match_rule)):
|
||||
receivers = self._match_rule_to_receivers[match_rule]
|
||||
|
||||
for receiver in receivers:
|
||||
args = message.get_args_list()
|
||||
receiver(*args)
|
||||
|
||||
def start_service_by_name(self, named_service):
|
||||
return dbus_bindings.bus_start_service_by_name(self._connection, named_service)
|
||||
|
||||
class SystemBus(Bus):
|
||||
"""The system-wide message bus
|
||||
"""
|
||||
def __init__(self):
|
||||
Bus.__init__(self, Bus.TYPE_SYSTEM)
|
||||
|
||||
class SessionBus(Bus):
|
||||
"""The session (current login) message bus
|
||||
"""
|
||||
def __init__(self):
|
||||
Bus.__init__(self, Bus.TYPE_SESSION)
|
||||
|
||||
class StarterBus(Bus):
|
||||
"""The bus that activated this process (if
|
||||
this process was launched by DBus activation)
|
||||
"""
|
||||
def __init__(self):
|
||||
Bus.__init__(self, Bus.TYPE_STARTER)
|
||||
|
||||
|
||||
class Interface:
|
||||
"""An inteface into a remote object
|
||||
|
||||
An Interface can be used to wrap ProxyObjects
|
||||
so that calls can be routed to their correct
|
||||
dbus interface
|
||||
"""
|
||||
|
||||
def __init__(self, object, dbus_interface):
|
||||
self._obj = object
|
||||
self._dbus_interface = dbus_interface
|
||||
|
||||
def connect_to_signal(self, signal_name, handler_function, dbus_interface = None):
|
||||
if not dbus_interface:
|
||||
dbus_interface = self._dbus_interface
|
||||
|
||||
self._obj.connect_to_signal(signal_name, handler_function, dbus_interface)
|
||||
|
||||
def __getattr__(self, member, **keywords):
|
||||
if (keywords.has_key('dbus_interface')):
|
||||
_dbus_interface = keywords['dbus_interface']
|
||||
else:
|
||||
_dbus_interface = self._dbus_interface
|
||||
|
||||
if member == '__call__':
|
||||
return object.__call__
|
||||
else:
|
||||
return self._obj.__getattr__(member, dbus_interface=_dbus_interface)
|
||||
|
||||
12
python/_util.py
Normal file
12
python/_util.py
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import re
|
||||
|
||||
def _validate_interface_or_name(value):
|
||||
elements = value.split('.')
|
||||
if len(elements) <= 1:
|
||||
raise ValidationException("%s must contain at least two elements seperated by a period ('.')"%(value))
|
||||
|
||||
validate = re.compile('[A-Za-z][\w_]*')
|
||||
for element in elements:
|
||||
if not validate.match(element):
|
||||
raise ValidationException("Element %s of %s has invalid characters"%(element ,value))
|
||||
|
||||
562
python/dbus.py
562
python/dbus.py
|
|
@ -1,562 +0,0 @@
|
|||
|
||||
"""Module for high-level communication over the FreeDesktop.org Bus (DBus)
|
||||
|
||||
DBus allows you to share and access remote objects between processes
|
||||
running on the desktop, and also to access system services (such as
|
||||
the print spool).
|
||||
|
||||
To use DBus, first get a Bus object, which provides a connection to one
|
||||
of a few standard dbus-daemon instances that might be running. From the
|
||||
Bus you can get a RemoteService. A service is provided by an application or
|
||||
process connected to the Bus, and represents a set of objects. Once you
|
||||
have a RemoteService you can get a RemoteObject that implements a specific interface
|
||||
(an interface is just a standard group of member functions). Then you can call
|
||||
those member functions directly.
|
||||
|
||||
You can think of a complete method call as looking something like:
|
||||
|
||||
Bus:SESSION -> Service:org.gnome.Evolution -> Object:/org/gnome/Evolution/Inbox -> Interface: org.gnome.Evolution.MailFolder -> Method: Forward('message1', 'seth@gnome.org')
|
||||
|
||||
This communicates over the SESSION Bus to the org.gnome.Evolution process to call the
|
||||
Forward method of the /org/gnome/Evolution/Inbox object (which provides the
|
||||
org.gnome.Evolution.MailFolder interface) with two string arguments.
|
||||
|
||||
For example, the dbus-daemon itself provides a service and some objects:
|
||||
|
||||
# Get a connection to the desktop-wide SESSION bus
|
||||
bus = dbus.Bus(dbus.Bus.TYPE_SESSION)
|
||||
|
||||
# Get the service provided by the dbus-daemon named org.freedesktop.DBus
|
||||
dbus_service = bus.get_service('org.freedesktop.DBus')
|
||||
|
||||
# Get a reference to the desktop bus' standard object, denoted
|
||||
# by the path /org/freedesktop/DBus. The object /org/freedesktop/DBus
|
||||
# implements the 'org.freedesktop.DBus' interface
|
||||
dbus_object = dbus_service.get_object('/org/freedesktop/DBus',
|
||||
'org.freedesktop.DBus')
|
||||
|
||||
# One of the member functions in the org.freedesktop.DBus interface
|
||||
# is ListServices(), which provides a list of all the other services
|
||||
# registered on this bus. Call it, and print the list.
|
||||
print(dbus_object.ListServices())
|
||||
"""
|
||||
|
||||
import dbus_bindings
|
||||
import re
|
||||
import inspect
|
||||
|
||||
|
||||
version = (0, 40, 0)
|
||||
|
||||
_threads_initialized = 0
|
||||
def init_gthreads ():
|
||||
global _threads_initialized
|
||||
if not _threads_initialized:
|
||||
dbus_bindings.init_gthreads ()
|
||||
_threads_initialized = 1
|
||||
|
||||
def _validate_interface_or_name(value):
|
||||
elements = value.split('.')
|
||||
if len(elements) <= 1:
|
||||
raise ValidationException("%s must contain at least two elements seperated by a period ('.')"%(value))
|
||||
|
||||
validate = re.compile('[A-Za-z][\w_]*')
|
||||
for element in elements:
|
||||
if not validate.match(element):
|
||||
raise ValidationException("Element %s of %s has invalid characters"%(element ,value))
|
||||
|
||||
|
||||
#Decorators
|
||||
def method(dbus_interface):
|
||||
_validate_interface_or_name(dbus_interface)
|
||||
|
||||
def decorator(func):
|
||||
func._dbus_is_method = True
|
||||
func._dbus_interface = dbus_interface
|
||||
func._dbus_args = inspect.getargspec(func)[0]
|
||||
func._dbus_args.pop(0)
|
||||
return func
|
||||
|
||||
return decorator
|
||||
|
||||
def signal(dbus_interface):
|
||||
_validate_interface_or_name(dbus_interface)
|
||||
def decorator(func):
|
||||
def emit_signal(self, *args, **keywords):
|
||||
func(self, *args, **keywords)
|
||||
message = dbus_bindings.Signal(self._object_path, dbus_interface, func.__name__)
|
||||
iter = message.get_iter(True)
|
||||
for arg in args:
|
||||
iter.append(arg)
|
||||
|
||||
self._connection.send(message)
|
||||
|
||||
emit_signal._dbus_is_signal = True
|
||||
emit_signal._dbus_interface = dbus_interface
|
||||
emit_signal.__name__ = func.__name__
|
||||
emit_signal._dbus_args = inspect.getargspec(func)[0]
|
||||
emit_signal._dbus_args.pop(0)
|
||||
return emit_signal
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
class Bus:
|
||||
"""A connection to a DBus daemon.
|
||||
|
||||
One of three possible standard buses, the SESSION, SYSTEM,
|
||||
or STARTER bus
|
||||
"""
|
||||
TYPE_SESSION = dbus_bindings.BUS_SESSION
|
||||
TYPE_SYSTEM = dbus_bindings.BUS_SYSTEM
|
||||
TYPE_STARTER = dbus_bindings.BUS_STARTER
|
||||
|
||||
"""bus_type=[Bus.TYPE_SESSION | Bus.TYPE_SYSTEM | Bus.TYPE_STARTER]
|
||||
"""
|
||||
|
||||
START_REPLY_SUCCESS = dbus_bindings.DBUS_START_REPLY_SUCCESS
|
||||
START_REPLY_ALREADY_RUNNING = dbus_bindings.DBUS_START_REPLY_ALREADY_RUNNING
|
||||
|
||||
def __init__(self, bus_type=TYPE_SESSION, glib_mainloop=True):
|
||||
self._connection = dbus_bindings.bus_get(bus_type)
|
||||
|
||||
self._connection.add_filter(self._signal_func)
|
||||
self._match_rule_to_receivers = { }
|
||||
if (glib_mainloop):
|
||||
self._connection.setup_with_g_main()
|
||||
|
||||
def get_connection(self):
|
||||
return self._connection
|
||||
|
||||
def get_session():
|
||||
"""Static method that returns the session bus"""
|
||||
return SessionBus()
|
||||
|
||||
get_session = staticmethod(get_session)
|
||||
|
||||
def get_system():
|
||||
"""Static method that returns the system bus"""
|
||||
return SystemBus()
|
||||
|
||||
get_system = staticmethod(get_system)
|
||||
|
||||
|
||||
def get_starter():
|
||||
"""Static method that returns the starter bus"""
|
||||
return StarterBus()
|
||||
|
||||
get_starter = staticmethod(get_starter)
|
||||
|
||||
|
||||
def get_object(self, named_service, object_path):
|
||||
"""Get a proxy object to call over the bus"""
|
||||
return ProxyObject(self, named_service, object_path)
|
||||
|
||||
def add_signal_receiver(self, handler_function, signal_name=None, dbus_interface=None, named_service=None, path=None):
|
||||
match_rule = self._get_match_rule(signal_name, dbus_interface, named_service, path)
|
||||
|
||||
if (not self._match_rule_to_receivers.has_key(match_rule)):
|
||||
self._match_rule_to_receivers[match_rule] = [handler_function]
|
||||
else:
|
||||
self._match_rule_to_receivers[match_rule].append(handler_function)
|
||||
|
||||
dbus_bindings.bus_add_match(self._connection, match_rule)
|
||||
|
||||
def remove_signal_receiver(self, handler_function, signal_name=None, dbus_interface=None, named_service=None, path=None):
|
||||
match_rule = self._get_match_rule(signal_name, dbus_interface, named_service, path)
|
||||
|
||||
if self._match_rule_to_receivers.has_key(match_rule):
|
||||
if self._match_rule_to_receivers[match_rule].__contains__(handler_function):
|
||||
self._match_rule_to_receivers[match_rule].pop(handler_function)
|
||||
dbus_bindings.bus_remove_match(self._connection, match_rule)
|
||||
|
||||
def get_unix_user(self, named_service):
|
||||
"""Get the unix user for the given named_service on this Bus"""
|
||||
return dbus_bindings.bus_get_unix_user(self._connection, named_service)
|
||||
|
||||
def _get_match_rule(self, signal_name, dbus_interface, named_service, path):
|
||||
match_rule = "type='signal'"
|
||||
if (dbus_interface):
|
||||
match_rule = match_rule + ",interface='%s'" % (dbus_interface)
|
||||
if (named_service):
|
||||
if (named_service[0] != ':' and named_service != "org.freedesktop.DBus"):
|
||||
bus_object = self.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
|
||||
named_service = bus_object.GetNameOwner(named_service, dbus_interface='org.freedesktop.DBus')
|
||||
|
||||
match_rule = match_rule + ",sender='%s'" % (named_service)
|
||||
if (path):
|
||||
match_rule = match_rule + ",path='%s'" % (path)
|
||||
if (signal_name):
|
||||
match_rule = match_rule + ",member='%s'" % (signal_name)
|
||||
return match_rule
|
||||
|
||||
def _signal_func(self, connection, message):
|
||||
if (message.get_type() != dbus_bindings.MESSAGE_TYPE_SIGNAL):
|
||||
return dbus_bindings.HANDLER_RESULT_NOT_YET_HANDLED
|
||||
|
||||
dbus_interface = message.get_interface()
|
||||
named_service = message.get_sender()
|
||||
path = message.get_path()
|
||||
signal_name = message.get_member()
|
||||
|
||||
match_rule = self._get_match_rule(signal_name, dbus_interface, named_service, path)
|
||||
|
||||
if (self._match_rule_to_receivers.has_key(match_rule)):
|
||||
receivers = self._match_rule_to_receivers[match_rule]
|
||||
|
||||
for receiver in receivers:
|
||||
args = message.get_args_list()
|
||||
receiver(*args)
|
||||
|
||||
def start_service_by_name(self, named_service):
|
||||
return dbus_bindings.bus_start_service_by_name(self._connection, named_service)
|
||||
|
||||
class SystemBus(Bus):
|
||||
"""The system-wide message bus
|
||||
"""
|
||||
def __init__(self):
|
||||
Bus.__init__(self, Bus.TYPE_SYSTEM)
|
||||
|
||||
class SessionBus(Bus):
|
||||
"""The session (current login) message bus
|
||||
"""
|
||||
def __init__(self):
|
||||
Bus.__init__(self, Bus.TYPE_SESSION)
|
||||
|
||||
class StarterBus(Bus):
|
||||
"""The bus that activated this process (if
|
||||
this process was launched by DBus activation)
|
||||
"""
|
||||
def __init__(self):
|
||||
Bus.__init__(self, Bus.TYPE_STARTER)
|
||||
|
||||
|
||||
class Interface:
|
||||
"""An inteface into a remote object
|
||||
|
||||
An Interface can be used to wrap ProxyObjects
|
||||
so that calls can be routed to their correct
|
||||
dbus interface
|
||||
"""
|
||||
|
||||
def __init__(self, object, dbus_interface):
|
||||
self._obj = object
|
||||
self._dbus_interface = dbus_interface
|
||||
|
||||
def connect_to_signal(self, signal_name, handler_function, dbus_interface = None):
|
||||
if not dbus_interface:
|
||||
dbus_interface = self._dbus_interface
|
||||
|
||||
self._obj.connect_to_signal(signal_name, handler_function, dbus_interface)
|
||||
|
||||
def __getattr__(self, member, **keywords):
|
||||
if (keywords.has_key('dbus_interface')):
|
||||
_dbus_interface = keywords['dbus_interface']
|
||||
else:
|
||||
_dbus_interface = self._dbus_interface
|
||||
|
||||
if member == '__call__':
|
||||
return object.__call__
|
||||
else:
|
||||
return self._obj.__getattr__(member, dbus_interface=_dbus_interface)
|
||||
|
||||
class ProxyObject:
|
||||
"""A proxy to the remote Object.
|
||||
|
||||
A ProxyObject is provided by the Bus. ProxyObjects
|
||||
have member functions, and can be called like normal Python objects.
|
||||
"""
|
||||
def __init__(self, bus, named_service, object_path):
|
||||
self._bus = bus
|
||||
self._named_service = named_service
|
||||
self._object_path = object_path
|
||||
|
||||
def connect_to_signal(self, signal_name, handler_function, dbus_interface=None):
|
||||
self._bus.add_signal_receiver(handler_function,
|
||||
signal_name=signal_name,
|
||||
dbus_interface=dbus_interface,
|
||||
named_service=self._named_service,
|
||||
path=self._object_path)
|
||||
|
||||
|
||||
|
||||
def __getattr__(self, member, **keywords):
|
||||
if member == '__call__':
|
||||
return object.__call__
|
||||
else:
|
||||
iface = None
|
||||
if (keywords.has_key('dbus_interface')):
|
||||
iface = keywords['dbus_interface']
|
||||
|
||||
return ProxyMethod(self._bus.get_connection(),
|
||||
self._named_service,
|
||||
self._object_path, iface, member)
|
||||
|
||||
|
||||
class ProxyMethod:
|
||||
"""A proxy Method.
|
||||
|
||||
Typically a member of a ProxyObject. Calls to the
|
||||
method produce messages that travel over the Bus and are routed
|
||||
to a specific named Service.
|
||||
"""
|
||||
def __init__(self, connection, named_service, object_path, dbus_interface, method_name):
|
||||
self._connection = connection
|
||||
self._named_service = named_service
|
||||
self._object_path = object_path
|
||||
self._method_name = method_name
|
||||
self._dbus_interface = dbus_interface
|
||||
|
||||
def __call__(self, *args, **keywords):
|
||||
dbus_interface = self._dbus_interface
|
||||
if (keywords.has_key('dbus_interface')):
|
||||
dbus_interface = keywords['dbus_interface']
|
||||
|
||||
reply_handler = None
|
||||
if (keywords.has_key('reply_handler')):
|
||||
reply_handler = keywords['reply_handler']
|
||||
|
||||
error_handler = None
|
||||
if (keywords.has_key('error_handler')):
|
||||
error_handler = keywords['error_handler']
|
||||
|
||||
if not(reply_handler and error_handler):
|
||||
if reply_handler:
|
||||
raise MissingErrorself, HandlerException()
|
||||
elif error_handler:
|
||||
raise MissingReplyHandlerException()
|
||||
|
||||
message = dbus_bindings.MethodCall(self._object_path, dbus_interface, self._method_name)
|
||||
message.set_destination(self._named_service)
|
||||
|
||||
# Add the arguments to the function
|
||||
iter = message.get_iter(True)
|
||||
for arg in args:
|
||||
iter.append(arg)
|
||||
|
||||
if reply_handler:
|
||||
result = self._connection.send_with_reply_handlers(message, -1, reply_handler, error_handler)
|
||||
args_tuple = (result,)
|
||||
else:
|
||||
reply_message = self._connection.send_with_reply_and_block(message, -1)
|
||||
args_tuple = reply_message.get_args_list()
|
||||
|
||||
if len(args_tuple) == 0:
|
||||
return
|
||||
elif len(args_tuple) == 1:
|
||||
return args_tuple[0]
|
||||
else:
|
||||
return args_tuple
|
||||
|
||||
class Service:
|
||||
"""A base class for exporting your own Services across the Bus
|
||||
|
||||
Just inherit from Service, providing the name of your service
|
||||
(e.g. org.designfu.SampleService).
|
||||
"""
|
||||
def __init__(self, named_service, bus=None):
|
||||
self._named_service = named_service
|
||||
|
||||
if bus == None:
|
||||
# Get the default bus
|
||||
self._bus = Bus()
|
||||
else:
|
||||
self._bus = bus
|
||||
|
||||
dbus_bindings.bus_request_name(self._bus.get_connection(), named_service)
|
||||
|
||||
def get_bus(self):
|
||||
"""Get the Bus this Service is on"""
|
||||
return self._bus
|
||||
|
||||
def get_name(self):
|
||||
"""Get the name of this service"""
|
||||
return self._named_service
|
||||
|
||||
def _dispatch_dbus_method_call(target_methods, self, argument_list, message):
|
||||
"""Calls method_to_call using argument_list, but handles
|
||||
exceptions, etc, and generates a reply to the DBus Message message
|
||||
"""
|
||||
try:
|
||||
target_method = None
|
||||
|
||||
dbus_interface = message.get_interface()
|
||||
if dbus_interface == None:
|
||||
if target_methods:
|
||||
target_method = target_methods[0]
|
||||
else:
|
||||
for dbus_method in target_methods:
|
||||
if dbus_method._dbus_interface == dbus_interface:
|
||||
target_method = dbus_method
|
||||
break
|
||||
|
||||
if target_method:
|
||||
retval = target_method(self, *argument_list)
|
||||
else:
|
||||
if not dbus_interface:
|
||||
raise UnknownMethodException('%s is not a valid method'%(message.get_member()))
|
||||
else:
|
||||
raise UnknownMethodException('%s is not a valid method of interface %s'%(message.get_member(), dbus_interface))
|
||||
except Exception, e:
|
||||
if e.__module__ == '__main__':
|
||||
# FIXME: is it right to use .__name__ here?
|
||||
error_name = e.__class__.__name__
|
||||
else:
|
||||
error_name = e.__module__ + '.' + str(e.__class__.__name__)
|
||||
error_contents = str(e)
|
||||
reply = dbus_bindings.Error(message, error_name, error_contents)
|
||||
else:
|
||||
reply = dbus_bindings.MethodReturn(message)
|
||||
if retval != None:
|
||||
iter = reply.get_iter(append=True)
|
||||
iter.append(retval)
|
||||
|
||||
return reply
|
||||
|
||||
class ObjectType(type):
|
||||
def __init__(cls, name, bases, dct):
|
||||
|
||||
#generate out vtable
|
||||
method_vtable = getattr(cls, '_dbus_method_vtable', {})
|
||||
reflection_data = getattr(cls, '_dbus_reflection_data', "")
|
||||
|
||||
reflection_interface_method_hash = {}
|
||||
reflection_interface_signal_hash = {}
|
||||
|
||||
for func in dct.values():
|
||||
if getattr(func, '_dbus_is_method', False):
|
||||
if method_vtable.has_key(func.__name__):
|
||||
method_vtable[func.__name__].append(func)
|
||||
else:
|
||||
method_vtable[func.__name__] = [func]
|
||||
|
||||
#generate a hash of interfaces so we can group
|
||||
#methods in the xml data
|
||||
if reflection_interface_method_hash.has_key(func._dbus_interface):
|
||||
reflection_interface_method_hash[func._dbus_interface].append(func)
|
||||
else:
|
||||
reflection_interface_method_hash[func._dbus_interface] = [func]
|
||||
|
||||
elif getattr(func, '_dbus_is_signal', False):
|
||||
if reflection_interface_signal_hash.has_key(func._dbus_interface):
|
||||
reflection_interface_signal_hash[func._dbus_interface].append(func)
|
||||
else:
|
||||
reflection_interface_signal_hash[func._dbus_interface] = [func]
|
||||
|
||||
for interface in reflection_interface_method_hash.keys():
|
||||
reflection_data = reflection_data + ' <interface name="%s">\n'%(interface)
|
||||
for func in reflection_interface_method_hash[interface]:
|
||||
reflection_data = reflection_data + ' <method name="%s">\n'%(func.__name__)
|
||||
for arg in func._dbus_args:
|
||||
reflection_data = reflection_data + ' <arg name="%s" type="v" />\n'%(arg)
|
||||
|
||||
#reclaim some memory
|
||||
func._dbus_args = None
|
||||
reflection_data = reflection_data + ' </method>\n'
|
||||
if reflection_interface_signal_hash.has_key(interface):
|
||||
for func in reflection_interface_signal_hash[interface]:
|
||||
reflection_data = reflection_data + ' <signal name="%s">\n'%(func.__name__)
|
||||
for arg in func._dbus_args:
|
||||
reflection_data = reflection_data + ' <arg name="%s" type="v" />\n'%(arg)
|
||||
#reclaim some memory
|
||||
func._dbus_args = None
|
||||
reflection_data = reflection_data + ' </signal>\n'
|
||||
|
||||
del reflection_interface_signal_hash[interface]
|
||||
reflection_data = reflection_data + ' </interface>\n'
|
||||
|
||||
for interface in reflection_interface_signal_hash.keys():
|
||||
reflection_data = reflection_data + ' <interface name="%s">\n'%(interface)
|
||||
|
||||
for func in reflection_interface_signal_hash[interface]:
|
||||
reflection_data = reflection_data + ' <signal name="%s">\n'%(func.__name__)
|
||||
for arg in func._dbus_args:
|
||||
reflection_data = reflection_data + ' <arg name="%s" type="v" />\n'%(arg)
|
||||
|
||||
#reclaim some memory
|
||||
func._dbus_args = None
|
||||
reflection_data = reflection_data + ' </signal>\n'
|
||||
|
||||
reflection_data = reflection_data + ' </interface>\n'
|
||||
|
||||
cls._dbus_reflection_data = reflection_data
|
||||
cls._dbus_method_vtable = method_vtable
|
||||
|
||||
super(ObjectType, cls).__init__(name, bases, dct)
|
||||
|
||||
|
||||
class Object:
|
||||
"""A base class for exporting your own Objects across the Bus.
|
||||
|
||||
Just inherit from Object and provide a list of methods to share
|
||||
across the Bus. These will appear as member functions of your
|
||||
ServiceObject.
|
||||
"""
|
||||
__metaclass__ = ObjectType
|
||||
|
||||
def __init__(self, object_path, service):
|
||||
self._object_path = object_path
|
||||
self._service = service
|
||||
self._bus = service.get_bus()
|
||||
|
||||
self._connection = self._bus.get_connection()
|
||||
|
||||
self._connection.register_object_path(object_path, self._unregister_cb, self._message_cb)
|
||||
|
||||
def _unregister_cb(self, connection):
|
||||
print ("Unregister")
|
||||
|
||||
def _message_cb(self, connection, message):
|
||||
target_method_name = message.get_member()
|
||||
target_methods = self._dbus_method_vtable[target_method_name]
|
||||
args = message.get_args_list()
|
||||
|
||||
reply = _dispatch_dbus_method_call(target_methods, self, args, message)
|
||||
|
||||
self._connection.send(reply)
|
||||
|
||||
@method('org.freedesktop.DBus.Introspectable')
|
||||
def Introspect(self):
|
||||
reflection_data = '<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">\n'
|
||||
reflection_data = reflection_data + '<node name="%s">\n'%(self._object_path)
|
||||
reflection_data = reflection_data + self._dbus_reflection_data
|
||||
reflection_data = reflection_data + '</node>\n'
|
||||
|
||||
return reflection_data
|
||||
|
||||
#Exceptions
|
||||
class MissingErrorHandlerException(Exception):
|
||||
def __init__(self):
|
||||
Exception.__init__(self)
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return "error_handler not defined: if you define a reply_handler you must also define an error_handler"
|
||||
|
||||
|
||||
class MissingReplyHandlerException(Exception):
|
||||
def __init__(self):
|
||||
Exception.__init__(self)
|
||||
|
||||
def __str__(self):
|
||||
return "reply_handler not defined: if you define an error_handler you must also define a reply_handler"
|
||||
|
||||
class ValidationException(Exception):
|
||||
def __init__(self, msg=''):
|
||||
self.msg = msg
|
||||
Exception.__init__(self)
|
||||
|
||||
def __str__(self):
|
||||
return "Error validating string: %s" % self.msg
|
||||
|
||||
class UnknownMethodException(Exception):
|
||||
def __init__(self, msg=''):
|
||||
self.msg = msg
|
||||
Exception.__init__(self)
|
||||
|
||||
def __str__(self):
|
||||
return "Unknown method: %s" % self.msg
|
||||
|
||||
ObjectPath = dbus_bindings.ObjectPath
|
||||
ByteArray = dbus_bindings.ByteArray
|
||||
|
||||
|
|
@ -82,6 +82,64 @@ class Signature(str):
|
|||
def __init__(self, value):
|
||||
str.__init__(value)
|
||||
|
||||
class Byte(int):
|
||||
def __init__(self, value):
|
||||
int.__init__(value)
|
||||
|
||||
class Boolean(int):
|
||||
def __init__(self, value):
|
||||
int.__init__(value)
|
||||
|
||||
class Int16(int):
|
||||
def __init__(self, value):
|
||||
int.__init__(value)
|
||||
|
||||
class UInt16(int):
|
||||
def __init__(self, value):
|
||||
if value < 0:
|
||||
raise TypeError('Unsigned integers must not have a negitive value')
|
||||
int.__init__(value)
|
||||
|
||||
class Int32(int):
|
||||
def __init__(self, value):
|
||||
int.__init__(value)
|
||||
|
||||
class UInt32(long):
|
||||
def __init__(self, value):
|
||||
if value < 0:
|
||||
raise TypeError('Unsigned integers must not have a negitive value')
|
||||
long.__init__(value)
|
||||
|
||||
class Int64(long):
|
||||
def __init__(self, value):
|
||||
long.__init__(value)
|
||||
|
||||
class UInt64(long):
|
||||
def __init__(self, value):
|
||||
if value < 0:
|
||||
raise TypeError('Unsigned integers must not have a negitive value')
|
||||
long.__init__(value)
|
||||
|
||||
class Double(float):
|
||||
def __init__(self, value):
|
||||
float.__init__(self, value)
|
||||
|
||||
class String(str):
|
||||
def __init__(self, value):
|
||||
str.__init__(value)
|
||||
|
||||
class Array(list):
|
||||
def __init__(self, value):
|
||||
list.__init__(value)
|
||||
|
||||
class Struct(tuple):
|
||||
def __init__(self, value):
|
||||
tuple.__init__(value)
|
||||
|
||||
class Dictionary(dict):
|
||||
def __init__(self, value):
|
||||
dict.__init__(value)
|
||||
|
||||
#forward delcerations
|
||||
cdef class Connection
|
||||
cdef class Message
|
||||
|
|
@ -707,7 +765,7 @@ cdef class MessageIter:
|
|||
ret = TYPE_STRING
|
||||
ret = str(chr(ret))
|
||||
elif ptype == float:
|
||||
ret = TYPE_FLOAT
|
||||
ret = TYPE_DOUBLE
|
||||
ret = str(chr(ret))
|
||||
elif ptype == dict:
|
||||
dict_list = value.items()
|
||||
|
|
@ -734,6 +792,52 @@ cdef class MessageIter:
|
|||
elif isinstance(Signature):
|
||||
ret = TYPE_SIGNATURE
|
||||
ret = str(chr(ret))
|
||||
elif isinstance(value, Byte):
|
||||
ret = TYPE_BYTE
|
||||
ret = str(chr(ret))
|
||||
elif isinstance(value, Boolean):
|
||||
ret = TYPE_BOOL
|
||||
ret = str(chr(ret))
|
||||
elif isinstance(value, Int16):
|
||||
ret = TYPE_INT16
|
||||
ret = str(chr(ret))
|
||||
elif isinstance(value, UInt16):
|
||||
ret = TYPE_UINT16
|
||||
ret = str(chr(ret))
|
||||
elif isinstance(value, Int32):
|
||||
ret = TYPE_INT32
|
||||
ret = str(chr(ret))
|
||||
elif isinstance(value, UInt32):
|
||||
ret = TYPE_UINT32
|
||||
ret = str(chr(ret))
|
||||
elif isinstance(value, Int64):
|
||||
ret = TYPE_INT64
|
||||
ret = str(chr(ret))
|
||||
elif isinstance(value, UInt64):
|
||||
ret = TYPE_UINT64
|
||||
ret = str(chr(ret))
|
||||
elif isinstance(value, Double):
|
||||
ret = TYPE_DOUBLE
|
||||
ret = str(chr(ret))
|
||||
elif isinstance(value, String):
|
||||
ret = TYPE_STRING
|
||||
ret = str(chr(ret))
|
||||
elif isinstance(value, Array):
|
||||
ret = str(chr(TYPE_ARRAY))
|
||||
ret = ret + self.python_value_to_dbus_sig(value[0], level)
|
||||
elif isinstance(value, Struct):
|
||||
ret = str(chr(STRUCT_BEGIN))
|
||||
for item in value:
|
||||
ret = ret + self.python_value_to_dbus_sig(item, level)
|
||||
ret = ret + str(chr(STRUCT_END))
|
||||
elif isinstance(value, Dictionary):
|
||||
dict_list = value.items()
|
||||
key, value = dict_list[0]
|
||||
|
||||
ret = str(chr(TYPE_ARRAY)) + str(chr(DICT_ENTRY_BEGIN))
|
||||
ret = ret + self.python_value_to_dbus_sig(key, level)
|
||||
ret = ret + self.python_value_to_dbus_sig(value, level)
|
||||
ret = ret + str(chr(DICT_ENTRY_END))
|
||||
else:
|
||||
raise TypeError, "Argument of unknown type '%s'" % (ptype)
|
||||
|
||||
|
|
@ -767,6 +871,32 @@ cdef class MessageIter:
|
|||
retval = self.append_array(value)
|
||||
elif isinstance(value, Signature):
|
||||
retval = self.append_signature(value)
|
||||
elif isinstance(value, Byte):
|
||||
retval = self.append_byte(value)
|
||||
elif isinstance(value, Boolean):
|
||||
retval = self.append_boolean(value)
|
||||
elif isinstance(value, Int16):
|
||||
retval = self.append_int16(value)
|
||||
elif isinstance(value, UInt16):
|
||||
retval = self.append_uint16(value)
|
||||
elif isinstance(value, Int32):
|
||||
retval = self.append_int32(value)
|
||||
elif isinstance(value, UInt32):
|
||||
retval = self.append_uint32(value)
|
||||
elif isinstance(value, Int64):
|
||||
retval = self.append_int64(value)
|
||||
elif isinstance(value, UInt64):
|
||||
retval = self.append_uint64(value)
|
||||
elif isinstance(value, Double):
|
||||
retval = self.append_double(value)
|
||||
elif isinstance(value, String):
|
||||
retval = self.append_string(value)
|
||||
elif isinstance(value, Array):
|
||||
retval = self.append_array(value)
|
||||
elif isinstance(value, Struct):
|
||||
retval = self.append_struct(value)
|
||||
elif isinstance(value, Dictionary):
|
||||
retval = self.append_dict(value)
|
||||
else:
|
||||
raise TypeError, "Argument of unknown type '%s'" % (value_type)
|
||||
|
||||
|
|
@ -784,7 +914,17 @@ cdef class MessageIter:
|
|||
|
||||
b = ord(value)
|
||||
return dbus_message_iter_append_basic(self.iter, TYPE_BYTE, <char *>&b)
|
||||
|
||||
|
||||
def append_int16(self, value):
|
||||
cdef dbus_int32_t c_value
|
||||
c_value = value
|
||||
return dbus_message_iter_append_basic(self.iter, TYPE_INT16, <dbus_int32_t *>&c_value)
|
||||
|
||||
def append_uint16(self, value):
|
||||
cdef dbus_uint32_t c_value
|
||||
c_value = value
|
||||
return dbus_message_iter_append_basic(self.iter, TYPE_UINT16, <dbus_uint32_t *>&c_value)
|
||||
|
||||
def append_int32(self, value):
|
||||
cdef dbus_int32_t c_value
|
||||
c_value = value
|
||||
|
|
@ -952,7 +1092,7 @@ cdef class MessageIter:
|
|||
|
||||
|
||||
(MESSAGE_TYPE_INVALID, MESSAGE_TYPE_METHOD_CALL, MESSAGE_TYPE_METHOD_RETURN, MESSAGE_TYPE_ERROR, MESSAGE_TYPE_SIGNAL) = range(5)
|
||||
(TYPE_INVALID, TYPE_BYTE, TYPE_BOOLEAN, TYPE_INT16, TYPE_UINT16, TYPE_INT32, TYPE_UINT32, TYPE_INT64, TYPE_UINT64, TYPE_DOUBLE, TYPE_STRING, TYPE_OBJECT_PATH, TYPE_SIGNATURE, TYPE_ARRAY, TYPE_STRUCT, STRUCT_BEGIN, STRUCT_END, TYPE_VARIANT, TYPE_DICT_ENTRY, DICT_ENTRY_BEGIN, DICT_ENTRY_END) = (0, ord('y'), ord('b'), ord('n'), ord('i'), ord('u'), ord('q'), ord('x'), ord('t'), ord('d'), ord('s'), ord('o'), ord('g'), ord('a'), ord('r'), ord('('), ord(')'), ord('v'), ord('e'), ord('{'), ord('}'))
|
||||
(TYPE_INVALID, TYPE_BYTE, TYPE_BOOLEAN, TYPE_INT16, TYPE_UINT16, TYPE_INT32, TYPE_UINT32, TYPE_INT64, TYPE_UINT64, TYPE_DOUBLE, TYPE_STRING, TYPE_OBJECT_PATH, TYPE_SIGNATURE, TYPE_ARRAY, TYPE_STRUCT, STRUCT_BEGIN, STRUCT_END, TYPE_VARIANT, TYPE_DICT_ENTRY, DICT_ENTRY_BEGIN, DICT_ENTRY_END) = (0, ord('y'), ord('b'), ord('n'), ord('q'), ord('i'), ord('u'), ord('x'), ord('t'), ord('d'), ord('s'), ord('o'), ord('g'), ord('a'), ord('r'), ord('('), ord(')'), ord('v'), ord('e'), ord('{'), ord('}'))
|
||||
(HANDLER_RESULT_HANDLED, HANDLER_RESULT_NOT_YET_HANDLED, HANDLER_RESULT_NEED_MEMORY) = range(3)
|
||||
|
||||
cdef class Message:
|
||||
|
|
|
|||
37
python/decorators.py
Normal file
37
python/decorators.py
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import _util
|
||||
import inspect
|
||||
|
||||
|
||||
def method(dbus_interface):
|
||||
_util._validate_interface_or_name(dbus_interface)
|
||||
|
||||
def decorator(func):
|
||||
func._dbus_is_method = True
|
||||
func._dbus_interface = dbus_interface
|
||||
func._dbus_args = inspect.getargspec(func)[0]
|
||||
func._dbus_args.pop(0)
|
||||
return func
|
||||
|
||||
return decorator
|
||||
|
||||
def signal(dbus_interface):
|
||||
_util._validate_interface_or_name(dbus_interface)
|
||||
def decorator(func):
|
||||
def emit_signal(self, *args, **keywords):
|
||||
func(self, *args, **keywords)
|
||||
message = dbus_bindings.Signal(self._object_path, dbus_interface, func.__name__)
|
||||
iter = message.get_iter(True)
|
||||
for arg in args:
|
||||
iter.append(arg)
|
||||
|
||||
self._connection.send(message)
|
||||
|
||||
emit_signal._dbus_is_signal = True
|
||||
emit_signal._dbus_interface = dbus_interface
|
||||
emit_signal.__name__ = func.__name__
|
||||
emit_signal._dbus_args = inspect.getargspec(func)[0]
|
||||
emit_signal._dbus_args.pop(0)
|
||||
return emit_signal
|
||||
|
||||
return decorator
|
||||
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import dbus
|
||||
|
||||
import pygtk
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import dbus
|
||||
import gtk
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import gtk
|
||||
import dbus
|
||||
import gobject
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import dbus
|
||||
|
||||
gconf_key = "/desktop/gnome/file_views/icon_theme"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import dbus
|
||||
|
||||
import gtk
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import dbus
|
||||
|
||||
import gtk
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""Lists services on the system bus
|
||||
"""
|
||||
import dbus
|
||||
|
|
|
|||
32
python/exceptions.py
Normal file
32
python/exceptions.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
class MissingErrorHandlerException(Exception):
|
||||
def __init__(self):
|
||||
Exception.__init__(self)
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return "error_handler not defined: if you define a reply_handler you must also define an error_handler"
|
||||
|
||||
|
||||
class MissingReplyHandlerException(Exception):
|
||||
def __init__(self):
|
||||
Exception.__init__(self)
|
||||
|
||||
def __str__(self):
|
||||
return "reply_handler not defined: if you define an error_handler you must also define a reply_handler"
|
||||
|
||||
class ValidationException(Exception):
|
||||
def __init__(self, msg=''):
|
||||
self.msg = msg
|
||||
Exception.__init__(self)
|
||||
|
||||
def __str__(self):
|
||||
return "Error validating string: %s" % self.msg
|
||||
|
||||
class UnknownMethodException(Exception):
|
||||
def __init__(self, msg=''):
|
||||
self.msg = msg
|
||||
Exception.__init__(self)
|
||||
|
||||
def __str__(self):
|
||||
return "Unknown method: %s" % self.msg
|
||||
|
||||
90
python/proxies.py
Normal file
90
python/proxies.py
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
import dbus_bindings
|
||||
|
||||
class ProxyObject:
|
||||
"""A proxy to the remote Object.
|
||||
|
||||
A ProxyObject is provided by the Bus. ProxyObjects
|
||||
have member functions, and can be called like normal Python objects.
|
||||
"""
|
||||
def __init__(self, bus, named_service, object_path):
|
||||
self._bus = bus
|
||||
self._named_service = named_service
|
||||
self._object_path = object_path
|
||||
|
||||
def connect_to_signal(self, signal_name, handler_function, dbus_interface=None):
|
||||
self._bus.add_signal_receiver(handler_function,
|
||||
signal_name=signal_name,
|
||||
dbus_interface=dbus_interface,
|
||||
named_service=self._named_service,
|
||||
path=self._object_path)
|
||||
|
||||
|
||||
|
||||
def __getattr__(self, member, **keywords):
|
||||
if member == '__call__':
|
||||
return object.__call__
|
||||
else:
|
||||
iface = None
|
||||
if (keywords.has_key('dbus_interface')):
|
||||
iface = keywords['dbus_interface']
|
||||
|
||||
return ProxyMethod(self._bus.get_connection(),
|
||||
self._named_service,
|
||||
self._object_path, iface, member)
|
||||
|
||||
|
||||
class ProxyMethod:
|
||||
"""A proxy Method.
|
||||
|
||||
Typically a member of a ProxyObject. Calls to the
|
||||
method produce messages that travel over the Bus and are routed
|
||||
to a specific named Service.
|
||||
"""
|
||||
def __init__(self, connection, named_service, object_path, dbus_interface, method_name):
|
||||
self._connection = connection
|
||||
self._named_service = named_service
|
||||
self._object_path = object_path
|
||||
self._method_name = method_name
|
||||
self._dbus_interface = dbus_interface
|
||||
|
||||
def __call__(self, *args, **keywords):
|
||||
dbus_interface = self._dbus_interface
|
||||
if (keywords.has_key('dbus_interface')):
|
||||
dbus_interface = keywords['dbus_interface']
|
||||
|
||||
reply_handler = None
|
||||
if (keywords.has_key('reply_handler')):
|
||||
reply_handler = keywords['reply_handler']
|
||||
|
||||
error_handler = None
|
||||
if (keywords.has_key('error_handler')):
|
||||
error_handler = keywords['error_handler']
|
||||
|
||||
if not(reply_handler and error_handler):
|
||||
if reply_handler:
|
||||
raise MissingErrorself, HandlerException()
|
||||
elif error_handler:
|
||||
raise MissingReplyHandlerException()
|
||||
|
||||
message = dbus_bindings.MethodCall(self._object_path, dbus_interface, self._method_name)
|
||||
message.set_destination(self._named_service)
|
||||
|
||||
# Add the arguments to the function
|
||||
iter = message.get_iter(True)
|
||||
for arg in args:
|
||||
iter.append(arg)
|
||||
|
||||
if reply_handler:
|
||||
result = self._connection.send_with_reply_handlers(message, -1, reply_handler, error_handler)
|
||||
args_tuple = (result,)
|
||||
else:
|
||||
reply_message = self._connection.send_with_reply_and_block(message, -1)
|
||||
args_tuple = reply_message.get_args_list()
|
||||
|
||||
if len(args_tuple) == 0:
|
||||
return
|
||||
elif len(args_tuple) == 1:
|
||||
return args_tuple[0]
|
||||
else:
|
||||
return args_tuple
|
||||
|
||||
187
python/services.py
Normal file
187
python/services.py
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
from decorators import *
|
||||
|
||||
import dbus_bindings
|
||||
|
||||
class Service:
|
||||
"""A base class for exporting your own Services across the Bus
|
||||
|
||||
Just inherit from Service, providing the name of your service
|
||||
(e.g. org.designfu.SampleService).
|
||||
"""
|
||||
def __init__(self, named_service, bus=None):
|
||||
self._named_service = named_service
|
||||
|
||||
if bus == None:
|
||||
# Get the default bus
|
||||
self._bus = Bus()
|
||||
else:
|
||||
self._bus = bus
|
||||
|
||||
dbus_bindings.bus_request_name(self._bus.get_connection(), named_service)
|
||||
|
||||
def get_bus(self):
|
||||
"""Get the Bus this Service is on"""
|
||||
return self._bus
|
||||
|
||||
def get_name(self):
|
||||
"""Get the name of this service"""
|
||||
return self._named_service
|
||||
|
||||
def _dispatch_dbus_method_call(target_methods, self, argument_list, message):
|
||||
"""Calls method_to_call using argument_list, but handles
|
||||
exceptions, etc, and generates a reply to the DBus Message message
|
||||
"""
|
||||
try:
|
||||
target_method = None
|
||||
|
||||
dbus_interface = message.get_interface()
|
||||
if dbus_interface == None:
|
||||
if target_methods:
|
||||
target_method = target_methods[0]
|
||||
else:
|
||||
for dbus_method in target_methods:
|
||||
if dbus_method._dbus_interface == dbus_interface:
|
||||
target_method = dbus_method
|
||||
break
|
||||
|
||||
if target_method:
|
||||
retval = target_method(self, *argument_list)
|
||||
else:
|
||||
if not dbus_interface:
|
||||
raise UnknownMethodException('%s is not a valid method'%(message.get_member()))
|
||||
else:
|
||||
raise UnknownMethodException('%s is not a valid method of interface %s'%(message.get_member(), dbus_interface))
|
||||
except Exception, e:
|
||||
if e.__module__ == '__main__':
|
||||
# FIXME: is it right to use .__name__ here?
|
||||
error_name = e.__class__.__name__
|
||||
else:
|
||||
error_name = e.__module__ + '.' + str(e.__class__.__name__)
|
||||
error_contents = str(e)
|
||||
reply = dbus_bindings.Error(message, error_name, error_contents)
|
||||
else:
|
||||
reply = dbus_bindings.MethodReturn(message)
|
||||
if retval != None:
|
||||
iter = reply.get_iter(append=True)
|
||||
iter.append(retval)
|
||||
|
||||
return reply
|
||||
|
||||
class ObjectType(type):
|
||||
def __init__(cls, name, bases, dct):
|
||||
|
||||
#generate out vtable
|
||||
method_vtable = getattr(cls, '_dbus_method_vtable', {})
|
||||
reflection_data = getattr(cls, '_dbus_reflection_data', "")
|
||||
|
||||
reflection_interface_method_hash = {}
|
||||
reflection_interface_signal_hash = {}
|
||||
|
||||
for func in dct.values():
|
||||
if getattr(func, '_dbus_is_method', False):
|
||||
if method_vtable.has_key(func.__name__):
|
||||
method_vtable[func.__name__].append(func)
|
||||
else:
|
||||
method_vtable[func.__name__] = [func]
|
||||
|
||||
#generate a hash of interfaces so we can group
|
||||
#methods in the xml data
|
||||
if reflection_interface_method_hash.has_key(func._dbus_interface):
|
||||
reflection_interface_method_hash[func._dbus_interface].append(func)
|
||||
else:
|
||||
reflection_interface_method_hash[func._dbus_interface] = [func]
|
||||
|
||||
elif getattr(func, '_dbus_is_signal', False):
|
||||
if reflection_interface_signal_hash.has_key(func._dbus_interface):
|
||||
reflection_interface_signal_hash[func._dbus_interface].append(func)
|
||||
else:
|
||||
reflection_interface_signal_hash[func._dbus_interface] = [func]
|
||||
|
||||
for interface in reflection_interface_method_hash.keys():
|
||||
reflection_data = reflection_data + ' <interface name="%s">\n'%(interface)
|
||||
for func in reflection_interface_method_hash[interface]:
|
||||
reflection_data = reflection_data + cls._reflect_on_method(func)
|
||||
|
||||
if reflection_interface_signal_hash.has_key(interface):
|
||||
for func in reflection_interface_signal_hash[interface]:
|
||||
reflection_data = reflection_data + cls._reflect_on_signal(func)
|
||||
|
||||
del reflection_interface_signal_hash[interface]
|
||||
|
||||
reflection_data = reflection_data + ' </interface>\n'
|
||||
|
||||
for interface in reflection_interface_signal_hash.keys():
|
||||
reflection_data = reflection_data + ' <interface name="%s">\n'%(interface)
|
||||
|
||||
for func in reflection_interface_signal_hash[interface]:
|
||||
reflection_data = reflection_data + cls._reflect_on_signal(func)
|
||||
|
||||
reflection_data = reflection_data + ' </interface>\n'
|
||||
|
||||
cls._dbus_reflection_data = reflection_data
|
||||
cls._dbus_method_vtable = method_vtable
|
||||
|
||||
super(ObjectType, cls).__init__(name, bases, dct)
|
||||
|
||||
#reflections on methods and signals may look like similar code but may in fact
|
||||
#diverge in the future so keep them seperate
|
||||
def _reflect_on_method(cls, func):
|
||||
reflection_data = ' <method name="%s">\n'%(func.__name__)
|
||||
for arg in func._dbus_args:
|
||||
reflection_data = reflection_data + ' <arg name="%s" type="v" />\n'%(arg)
|
||||
|
||||
#reclaim some memory
|
||||
func._dbus_args = None
|
||||
reflection_data = reflection_data + ' </method>\n'
|
||||
|
||||
return reflection_data
|
||||
|
||||
def _reflect_on_signal(cls, func):
|
||||
reflection_data = ' <signal name="%s">\n'%(func.__name__)
|
||||
for arg in func._dbus_args:
|
||||
reflection_data = reflection_data + ' <arg name="%s" type="v" />\n'%(arg)
|
||||
#reclaim some memory
|
||||
func._dbus_args = None
|
||||
reflection_data = reflection_data + ' </signal>\n'
|
||||
|
||||
return reflection_data
|
||||
|
||||
class Object:
|
||||
"""A base class for exporting your own Objects across the Bus.
|
||||
|
||||
Just inherit from Object and provide a list of methods to share
|
||||
across the Bus. These will appear as member functions of your
|
||||
ServiceObject.
|
||||
"""
|
||||
__metaclass__ = ObjectType
|
||||
|
||||
def __init__(self, object_path, service):
|
||||
self._object_path = object_path
|
||||
self._service = service
|
||||
self._bus = service.get_bus()
|
||||
|
||||
self._connection = self._bus.get_connection()
|
||||
|
||||
self._connection.register_object_path(object_path, self._unregister_cb, self._message_cb)
|
||||
|
||||
def _unregister_cb(self, connection):
|
||||
print ("Unregister")
|
||||
|
||||
def _message_cb(self, connection, message):
|
||||
target_method_name = message.get_member()
|
||||
target_methods = self._dbus_method_vtable[target_method_name]
|
||||
args = message.get_args_list()
|
||||
|
||||
reply = _dispatch_dbus_method_call(target_methods, self, args, message)
|
||||
|
||||
self._connection.send(reply)
|
||||
|
||||
@method('org.freedesktop.DBus.Introspectable')
|
||||
def Introspect(self):
|
||||
reflection_data = '<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">\n'
|
||||
reflection_data = reflection_data + '<node name="%s">\n'%(self._object_path)
|
||||
reflection_data = reflection_data + self._dbus_reflection_data
|
||||
reflection_data = reflection_data + '</node>\n'
|
||||
|
||||
return reflection_data
|
||||
|
||||
18
python/types.py
Normal file
18
python/types.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import dbus_bindings
|
||||
|
||||
ObjectPath = dbus_bindings.ObjectPath
|
||||
ByteArray = dbus_bindings.ByteArray
|
||||
Signature = dbus_bindings.Signature
|
||||
Byte = dbus_bindings.Byte
|
||||
Boolean = dbus_bindings.Boolean
|
||||
Int16 = dbus_bindings.Int16
|
||||
UInt16 = dbus_bindings.UInt16
|
||||
Int32 = dbus_bindings.Int32
|
||||
UInt32 = dbus_bindings.UInt32
|
||||
Int64 = dbus_bindings.Int64
|
||||
UInt64 = dbus_bindings.UInt64
|
||||
Double = dbus_bindings.Double
|
||||
String = dbus_bindings.String
|
||||
Array = dbus_bindings.Array
|
||||
Struct = dbus_bindings.Struct
|
||||
Dictionary = dbus_bindings.Dictionary
|
||||
Loading…
Add table
Reference in a new issue