Mercurial > libervia-backend
annotate src/bridge/bridge_constructor/dbus_core_template.py @ 419:6c167a2e04b8
bridge: added generic D-Bus exception management + asyncCreateProfile method
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 02 Nov 2011 22:47:59 +0100 |
parents | 3ea41a199b36 |
children | 6c20c76abdcc |
rev | line source |
---|---|
267 | 1 #!/usr/bin/python |
2 #-*- coding: utf-8 -*- | |
3 | |
4 """ | |
5 SAT: a jabber client | |
6 Copyright (C) 2009, 2010, 2011 Jérôme Poisson (goffi@goffi.org) | |
7 | |
8 This program is free software: you can redistribute it and/or modify | |
9 it under the terms of the GNU General Public License as published by | |
10 the Free Software Foundation, either version 3 of the License, or | |
11 (at your option) any later version. | |
12 | |
13 This program is distributed in the hope that it will be useful, | |
14 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 GNU General Public License for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with this program. If not, see <http://www.gnu.org/licenses/>. | |
20 """ | |
21 | |
22 | |
23 from bridge import Bridge | |
24 import dbus | |
25 import dbus.service | |
26 import dbus.mainloop.glib | |
272
1d2e0dfe7114
bridge: core & frontend sides of bridge are now generated
Goffi <goffi@goffi.org>
parents:
267
diff
changeset
|
27 from logging import debug, info |
267 | 28 |
29 const_INT_PREFIX = "org.goffi.SAT" #Interface prefix | |
419
6c167a2e04b8
bridge: added generic D-Bus exception management + asyncCreateProfile method
Goffi <goffi@goffi.org>
parents:
371
diff
changeset
|
30 const_ERROR_PREFIX = const_INT_PREFIX+".error" |
359
eb9d33ba4e36
bridge: templates' constants can now be overrided
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
31 const_OBJ_PATH = '/org/goffi/SAT/bridge' |
371
3ea41a199b36
bridge refactoring: categories are now core and plugin instead of communication and request
Goffi <goffi@goffi.org>
parents:
359
diff
changeset
|
32 const_CORE_SUFFIX = ".core" |
3ea41a199b36
bridge refactoring: categories are now core and plugin instead of communication and request
Goffi <goffi@goffi.org>
parents:
359
diff
changeset
|
33 const_PLUGIN_SUFFIX = ".plugin" |
267 | 34 |
419
6c167a2e04b8
bridge: added generic D-Bus exception management + asyncCreateProfile method
Goffi <goffi@goffi.org>
parents:
371
diff
changeset
|
35 class GenericException(dbus.DBusException): |
6c167a2e04b8
bridge: added generic D-Bus exception management + asyncCreateProfile method
Goffi <goffi@goffi.org>
parents:
371
diff
changeset
|
36 def __init__(self, name): |
6c167a2e04b8
bridge: added generic D-Bus exception management + asyncCreateProfile method
Goffi <goffi@goffi.org>
parents:
371
diff
changeset
|
37 super(GenericException,self).__init__() |
6c167a2e04b8
bridge: added generic D-Bus exception management + asyncCreateProfile method
Goffi <goffi@goffi.org>
parents:
371
diff
changeset
|
38 self._dbus_error_name = const_ERROR_PREFIX+"."+name |
6c167a2e04b8
bridge: added generic D-Bus exception management + asyncCreateProfile method
Goffi <goffi@goffi.org>
parents:
371
diff
changeset
|
39 |
267 | 40 class DbusObject(dbus.service.Object): |
41 | |
42 def __init__(self, bus, path): | |
43 dbus.service.Object.__init__(self, bus, path) | |
44 debug("Init DbusObject...") | |
45 self.cb={} | |
46 | |
47 def register(self, name, cb): | |
48 self.cb[name]=cb | |
49 | |
50 ### signals ### | |
51 | |
371
3ea41a199b36
bridge refactoring: categories are now core and plugin instead of communication and request
Goffi <goffi@goffi.org>
parents:
359
diff
changeset
|
52 @dbus.service.signal(const_INT_PREFIX+const_PLUGIN_SUFFIX, |
3ea41a199b36
bridge refactoring: categories are now core and plugin instead of communication and request
Goffi <goffi@goffi.org>
parents:
359
diff
changeset
|
53 signature='') |
3ea41a199b36
bridge refactoring: categories are now core and plugin instead of communication and request
Goffi <goffi@goffi.org>
parents:
359
diff
changeset
|
54 def dummySignal(self): |
3ea41a199b36
bridge refactoring: categories are now core and plugin instead of communication and request
Goffi <goffi@goffi.org>
parents:
359
diff
changeset
|
55 #FIXME: workaround for addSignal (doesn't work if one method doensn't |
3ea41a199b36
bridge refactoring: categories are now core and plugin instead of communication and request
Goffi <goffi@goffi.org>
parents:
359
diff
changeset
|
56 # already exist for plugins), probably missing some initialisation, need |
3ea41a199b36
bridge refactoring: categories are now core and plugin instead of communication and request
Goffi <goffi@goffi.org>
parents:
359
diff
changeset
|
57 # further investigations |
3ea41a199b36
bridge refactoring: categories are now core and plugin instead of communication and request
Goffi <goffi@goffi.org>
parents:
359
diff
changeset
|
58 pass |
3ea41a199b36
bridge refactoring: categories are now core and plugin instead of communication and request
Goffi <goffi@goffi.org>
parents:
359
diff
changeset
|
59 |
267 | 60 ##SIGNALS_PART## |
61 | |
62 ### methods ### | |
63 | |
64 ##METHODS_PART## | |
65 | |
299
e044d1dc37d1
dbus bridge: asynchrone methods management
Goffi <goffi@goffi.org>
parents:
298
diff
changeset
|
66 def __attributes(self, in_sign): |
267 | 67 """Return arguments to user given a in_sign |
68 @param in_sign: in_sign in the short form (using s,a,i,b etc) | |
69 @return: list of arguments that correspond to a in_sign (e.g.: "sss" return "arg1, arg2, arg3")""" | |
70 i=0 | |
71 idx=0 | |
299
e044d1dc37d1
dbus bridge: asynchrone methods management
Goffi <goffi@goffi.org>
parents:
298
diff
changeset
|
72 attr=[] |
267 | 73 while i<len(in_sign): |
74 if in_sign[i] not in ['b','y','n','i','x','q','u','t','d','s','a']: | |
75 raise ParseError("Unmanaged attribute type [%c]" % in_sign[i]) | |
76 | |
299
e044d1dc37d1
dbus bridge: asynchrone methods management
Goffi <goffi@goffi.org>
parents:
298
diff
changeset
|
77 attr.append("arg_%i" % idx) |
267 | 78 idx+=1 |
79 | |
80 if in_sign[i] == 'a': | |
81 i+=1 | |
82 if in_sign[i]!='{' and in_sign[i]!='(': #FIXME: must manage tuples out of arrays | |
83 i+=1 | |
84 continue #we have a simple type for the array | |
85 opening_car = in_sign[i] | |
86 assert(opening_car in ['{','(']) | |
87 closing_car = '}' if opening_car == '{' else ')' | |
88 opening_count = 1 | |
89 while (True): #we have a dict or a list of tuples | |
90 i+=1 | |
91 if i>=len(in_sign): | |
92 raise ParseError("missing }") | |
93 if in_sign[i] == opening_car: | |
94 opening_count+=1 | |
95 if in_sign[i] == closing_car: | |
96 opening_count-=1 | |
97 if opening_count == 0: | |
98 break | |
99 i+=1 | |
299
e044d1dc37d1
dbus bridge: asynchrone methods management
Goffi <goffi@goffi.org>
parents:
298
diff
changeset
|
100 return attr |
267 | 101 |
299
e044d1dc37d1
dbus bridge: asynchrone methods management
Goffi <goffi@goffi.org>
parents:
298
diff
changeset
|
102 def addMethod(self, name, int_suffix, in_sign, out_sign, async=False, doc={}): |
267 | 103 """Dynamically add a method to Dbus Bridge""" |
299
e044d1dc37d1
dbus bridge: asynchrone methods management
Goffi <goffi@goffi.org>
parents:
298
diff
changeset
|
104 _attributes = self.__attributes(in_sign) |
e044d1dc37d1
dbus bridge: asynchrone methods management
Goffi <goffi@goffi.org>
parents:
298
diff
changeset
|
105 |
e044d1dc37d1
dbus bridge: asynchrone methods management
Goffi <goffi@goffi.org>
parents:
298
diff
changeset
|
106 if async: |
e044d1dc37d1
dbus bridge: asynchrone methods management
Goffi <goffi@goffi.org>
parents:
298
diff
changeset
|
107 _attributes.extend(['callback','errback']) |
e044d1dc37d1
dbus bridge: asynchrone methods management
Goffi <goffi@goffi.org>
parents:
298
diff
changeset
|
108 |
e044d1dc37d1
dbus bridge: asynchrone methods management
Goffi <goffi@goffi.org>
parents:
298
diff
changeset
|
109 attributes = ', '.join(_attributes) |
267 | 110 |
111 code = compile ('def '+name+' (self,'+attributes+'): return self.cb["'+name+'"]('+attributes+')', '<DBus bridge>','exec') | |
112 exec (code) | |
113 method = locals()[name] | |
299
e044d1dc37d1
dbus bridge: asynchrone methods management
Goffi <goffi@goffi.org>
parents:
298
diff
changeset
|
114 async_callbacks = ('callback', 'errback') if async else None |
267 | 115 setattr(DbusObject, name, dbus.service.method( |
299
e044d1dc37d1
dbus bridge: asynchrone methods management
Goffi <goffi@goffi.org>
parents:
298
diff
changeset
|
116 const_INT_PREFIX+int_suffix, in_signature=in_sign, out_signature=out_sign, |
e044d1dc37d1
dbus bridge: asynchrone methods management
Goffi <goffi@goffi.org>
parents:
298
diff
changeset
|
117 async_callbacks=async_callbacks)(method)) |
284
c25371424090
dbus bridge: fixed introspection for dynamically added methods and signals
Goffi <goffi@goffi.org>
parents:
272
diff
changeset
|
118 function = getattr(self, name) |
c25371424090
dbus bridge: fixed introspection for dynamically added methods and signals
Goffi <goffi@goffi.org>
parents:
272
diff
changeset
|
119 func_table = self._dbus_class_table[self.__class__.__module__ + '.' + self.__class__.__name__][function._dbus_interface] |
c25371424090
dbus bridge: fixed introspection for dynamically added methods and signals
Goffi <goffi@goffi.org>
parents:
272
diff
changeset
|
120 func_table[function.__name__] = function #Needed for introspection |
267 | 121 |
298
15c8916317d0
dbus bridge: added doc parameter, unmanaged yet
Goffi <goffi@goffi.org>
parents:
284
diff
changeset
|
122 def addSignal(self, name, int_suffix, signature, doc={}): |
267 | 123 """Dynamically add a signal to Dbus Bridge""" |
299
e044d1dc37d1
dbus bridge: asynchrone methods management
Goffi <goffi@goffi.org>
parents:
298
diff
changeset
|
124 attributes = ', '.join(self.__attributes(signature)) |
267 | 125 |
337
4402ac630712
bridge: async callback managed in bridge_constructor + misc
Goffi <goffi@goffi.org>
parents:
299
diff
changeset
|
126 #code = compile ('def '+name+' (self,'+attributes+'): debug ("'+name+' signal")', '<DBus bridge>','exec') #XXX: the debug is too annoying with xmllog |
4402ac630712
bridge: async callback managed in bridge_constructor + misc
Goffi <goffi@goffi.org>
parents:
299
diff
changeset
|
127 code = compile ('def '+name+' (self,'+attributes+'): pass', '<DBus bridge>','exec') |
267 | 128 exec (code) |
129 signal = locals()[name] | |
130 setattr(DbusObject, name, dbus.service.signal( | |
131 const_INT_PREFIX+int_suffix, signature=signature)(signal)) | |
284
c25371424090
dbus bridge: fixed introspection for dynamically added methods and signals
Goffi <goffi@goffi.org>
parents:
272
diff
changeset
|
132 function = getattr(self, name) |
c25371424090
dbus bridge: fixed introspection for dynamically added methods and signals
Goffi <goffi@goffi.org>
parents:
272
diff
changeset
|
133 func_table = self._dbus_class_table[self.__class__.__module__ + '.' + self.__class__.__name__][function._dbus_interface] |
c25371424090
dbus bridge: fixed introspection for dynamically added methods and signals
Goffi <goffi@goffi.org>
parents:
272
diff
changeset
|
134 func_table[function.__name__] = function #Needed for introspection |
267 | 135 |
136 class DBusBridge(Bridge): | |
137 def __init__(self): | |
138 dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) | |
139 Bridge.__init__(self) | |
140 info ("Init DBus...") | |
141 self.session_bus = dbus.SessionBus() | |
142 self.dbus_name = dbus.service.BusName(const_INT_PREFIX, self.session_bus) | |
359
eb9d33ba4e36
bridge: templates' constants can now be overrided
Goffi <goffi@goffi.org>
parents:
337
diff
changeset
|
143 self.dbus_bridge = DbusObject(self.session_bus, const_OBJ_PATH) |
267 | 144 |
145 ##DIRECT_CALLS## | |
146 | |
147 def register(self, name, callback): | |
148 debug("registering DBus bridge method [%s]", name) | |
149 self.dbus_bridge.register(name, callback) | |
150 | |
299
e044d1dc37d1
dbus bridge: asynchrone methods management
Goffi <goffi@goffi.org>
parents:
298
diff
changeset
|
151 def addMethod(self, name, int_suffix, in_sign, out_sign, method, async=False, doc={}): |
267 | 152 """Dynamically add a method to Dbus Bridge""" |
153 print ("Adding method [%s] to DBus bridge" % name) | |
299
e044d1dc37d1
dbus bridge: asynchrone methods management
Goffi <goffi@goffi.org>
parents:
298
diff
changeset
|
154 self.dbus_bridge.addMethod(name, int_suffix, in_sign, out_sign, async, doc) |
267 | 155 self.register(name, method) |
156 | |
298
15c8916317d0
dbus bridge: added doc parameter, unmanaged yet
Goffi <goffi@goffi.org>
parents:
284
diff
changeset
|
157 def addSignal(self, name, int_suffix, signature, doc={}): |
299
e044d1dc37d1
dbus bridge: asynchrone methods management
Goffi <goffi@goffi.org>
parents:
298
diff
changeset
|
158 self.dbus_bridge.addSignal(name, int_suffix, signature, doc) |
267 | 159 setattr(DBusBridge, name, getattr(self.dbus_bridge, name)) |
160 |