2008-07-28 Mark Doffman <mark.doffman@codethink.co.uk>
[platform/core/uifw/at-spi2-atk.git] / pyatspi / base.py
1 #Copyright (C) 2008 Codethink Ltd
2
3 #This library is free software; you can redistribute it and/or
4 #modify it under the terms of the GNU Lesser General Public
5 #License version 2 as published by the Free Software Foundation.
6
7 #This program is distributed in the hope that it will be useful,
8 #but WITHOUT ANY WARRANTY; without even the implied warranty of
9 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 #GNU General Public License for more details.
11 #You should have received a copy of the GNU Lesser General Public License
12 #along with this program; if not, write to the Free Software
13 #Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
14
15 from weakref import ref
16
17 from dbus.proxies import Interface, ProxyObject
18 from dbus.exceptions import *
19
20 from factory import interfaceFactory
21
22 class AccessibleObjectNoLongerExists(Exception):
23         pass
24
25 #------------------------------------------------------------------------------
26
27 class Enum(object):
28         def __str__(self):
29                 return self._enum_lookup(int(self))
30
31 #------------------------------------------------------------------------------
32
33 class BaseProxyMeta(type):
34         def __init__(cls):
35                 type.__init__(cls)
36
37                 queryable_interfaces = { 
38                         'Accessible':ATSPI_ACCESSIBLE,
39                         'Action':ATSPI_ACTION,
40                         'Application':ATSPI_APPLICATION,
41                         'Collection':ATSPI_COLLECTION,
42                         'Component':ATSPI_COMPONENT,
43                         'Desktop':ATSPI_DESKTOP,
44                         'Document':ATSPI_DOCUMENT,
45                         'EditableText':ATSPI_EDITABLE_TEXT,
46                         'Hypertext':ATSPI_HYPERTEXT,
47                         'Hyperlink':ATSPI_HYPERLINK,
48                         'Image':ATSPI_IMAGE,
49                         'Selection':ATSPI_SELECTION,
50                         'StreamableContent':ATSPI_STREAMABLE_CONTENT,
51                         'Table':ATSPI_TABLE,
52                         'Text':ATSPI_TEXT,
53                         'Value':ATSPI_VALUE,
54                 }
55
56                 for interface in queryable_interfaces.keys():
57                         name = 'query%s' % interface
58                         def new_query(self, object):
59                                 return self.queryInterface(object, queryable_interfaces[interface])
60                         setattr(cls, name, new_query) 
61
62 #------------------------------------------------------------------------------
63
64 class BaseProxy(Interface):
65         """
66         A D-Bus proxy for a remote object that implements one or more of the AT-SPI
67         Accessibility interfaces.
68         """
69         
70         __metaclass__ = BaseProxyMeta
71
72         def __init__(self, busobject, cache, app, path, interface):
73                 """
74                 Create a D-Bus Proxy for an ATSPI interface.
75
76                 busobject - The D-Bus proxy object this interface uses for D-Bus calls.
77                 cache - The accessible cache that this object is owned by.
78                 path - The object path of the remote object.
79                 app - The bus name of the application this object belongs to.
80                 interface - The name of the ATSPI interface that this proxy implements.
81                 """
82                 Interface.__init__(self, busobject, interface)
83
84                 self._cache = cache
85
86                 self._path = path
87                 self._app = app
88
89                 self._pgetter = self.get_dbus_method("Get", dbus_interface="org.freedesktop.DBus.Properties")
90                 self._psetter = self.get_dbus_method("Set", dbus_interface="org.freedesktop.DBus.Properties")
91
92         def __getattr__(self, *args, **kwargs):
93                 """
94                 The __getattr__ function must return the D-Bus method wrapped in a
95                 method to translate exceptions.
96                 """
97                 # Need to throw an AccessibleObjectNoLongerExists exception
98                 # on D-Bus error of the same type.
99                 try:
100                         return Interface.__getattr__(self, *args, **kwargs)
101                 except UnknownMethodException, e:
102                         raise NotImplementedError(e)
103                 except DBusException, e:
104                         raise LookupError(e)
105
106         @property
107         def _data(self):
108                 try:
109                         data = self._cache._objects[self._path]
110                 except KeyError:
111                         raise AccessibleObjectNoLongerExists, 'Cache data cannot be found for path %s' % (self._path,)
112                 return data
113
114         @property
115         def interfaces(self):
116                 return self._data.interfaces
117
118         def queryInterface(self, interface):
119                 if interface in self._data.interfaces:
120                         return interfaceFactory(self._obj, self._cache, self._app, self._path, interface)
121                 else:
122                         raise NotImplementedError(
123                                 "%s not supported by accessible object at path %s"
124                                 % (interface, self.path))
125
126 #END----------------------------------------------------------------------------