fixed unset session bus address issue
[dbuscron] / dbuscron / bus.py
1 from __future__ import with_statement
2
3 import dbus, os
4
5 from dbuscron.logger import Logger
6 log = Logger(__name__)
7
8 def dbus_to_str(value):
9     try:
10         if isinstance(value, dbus.Byte):
11             result = str(int(value))
12         elif isinstance(value, dbus.ByteArray):
13             result = ','.join(str(ord(v)) for v in value)
14         elif isinstance(value, dbus.Array):
15             result = ','.join(dbus_to_str(v) for v in value)
16         elif isinstance(value, dbus.Dictionary):
17             result = ','.join('%s:%s' % (k, dbus_to_str(v)) for k, v in value.iteritems())
18         elif isinstance(value, dbus.String):
19             result = value.encode('utf-8')
20         else:
21             result = str(value)
22         return result
23     except Exception, e:
24         log.error('convert exception', e)
25         raise e
26
27
28 def get_dbus_message_type(message):
29     result = message.__class__.__name__[0:-7]
30     for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
31         result = result.replace(c, '_'+c.lower())
32     return result.strip('_')
33
34 class DbusBus(object):
35     __bus = None
36     __system_bus = None
37     __session_bus = None
38
39     def __new__(cls):
40         if not cls.__bus:
41             cls.__bus = super(DbusBus, cls).__new__(cls)
42         return cls.__bus
43
44     def __init__(self):
45         self.get_session_bus_address()
46         from dbus.mainloop.glib import DBusGMainLoop
47         DBusGMainLoop(set_as_default=True)
48
49     def get_session_bus_address(self):
50         try:
51             return os.environ['DBUS_SESSION_BUS_ADDRESS']
52         except KeyError:
53             with open('/tmp/session_bus_address.user', 'rb') as f:
54                 session_bus_address = f.readline().strip().split('=', 1).pop().strip("'\"")
55                 os.environ['DBUS_SESSION_BUS_ADDRESS'] = session_bus_address
56                 log('session bus address aquired', session_bus_address)
57                 return session_bus_address
58
59     @property
60     def system(self):
61         if not self.__system_bus:
62             self.__system_bus = dbus.SystemBus()
63         return self.__system_bus
64
65     @property
66     def session(self):
67         if not self.__session_bus:
68             self.__session_bus = dbus.SessionBus()
69         return self.__session_bus
70
71     def attach_handler(self, handler):
72         if self.__system_bus:
73             self.__system_bus.add_message_filter(handler)
74         if self.__session_bus:
75             self.__session_bus.add_message_filter(handler)
76     def listen(self):
77         from gobject import MainLoop
78         loop = MainLoop()
79         loop.run()
80
81 class DbusRule(object):
82     def __init__(self, bus_=None, type_=None, sender_=None, interface_=None, path_=None, member_=None, destination_=None, args_=[]):
83         self._bus         = bus_
84         self._type        = type_
85         self._sender      = sender_
86         self._interface   = interface_
87         self._path        = path_
88         self._member      = member_
89         self._destination = destination_
90         self._args        = args_
91
92     def register(self):
93         rule = str(self)
94         if rule:
95             self._bus.add_match_string(rule)
96
97     def unregister(self):
98         rule = str(self)
99         if rule:
100             self._bus.remove_match_string(rule)
101
102     def __del__(self):
103        self.unregister()
104
105     def __str__(self):
106         rule = []
107         for key in ['type', 'sender', 'interface', 'path', 'member', 'destination']:
108             value = getattr(self, '_'+key)
109             if value is not None:
110                 rule.append("%s='%s'" % (key, value))
111
112         if self._args:
113             for i, arg in enumerate(self._args):
114                 rule.append("arg%d%s='%s'" % (i, 'path' if arg.startswith('/') else '', arg))
115
116         return ','.join(rule)
117
118     def match(self, bus, message):
119
120         if self._bus not in (None, bus):
121             return False
122
123         if self._type is not None:
124             type_ = get_dbus_message_type(message)
125             if self._type != type_:
126                 return False
127
128         if self._sender not in (None, message.get_sender()):
129             return False
130
131         if self._interface not in (None, message.get_interface()):
132             return False
133
134         if self._path not in (None, message.get_path()):
135             return False
136
137         if self._member not in (None, message.get_member()):
138             return False
139
140         if self._destination not in (None, message.get_destination()):
141             return False
142
143         if self._args is not None:
144             args_ = message.get_args_list()
145             for i, arg in enumerate(args_):
146                 if i >= len(self._args):
147                     break
148                 if self._args[i] not in (None, str(arg)):
149                     return False
150
151         return True
152