def printCache():
print "Print cache function is deprecated";
+import other
+
+# Build a dictionary mapping state values to names based on the prefix of the
+# enum constants.
+STATE_VALUE_TO_NAME = dict(((value, name[6:].lower().replace('_', ' '))
+ for name, value
+ in vars(other).items()
+ if name.startswith('STATE_')))
+
+# Build a dictionary mapping relation values to names based on the prefix of
+# the enum constants.
+RELATION_VALUE_TO_NAME = dict(((value, name[9:].lower().replace('_', ' '))
+ for name, value
+ in vars(other).items()
+ if name.startswith('RELATION_')))
+
+del other
+
from constants import *
+
+from base import *
from other import *
-from accessible import *
+
+from test import *
+
#from utils import *
+++ /dev/null
-#Copyright (C) 2008 Codethink Ltd
-
-#This library is free software; you can redistribute it and/or
-#modify it under the terms of the GNU Lesser General Public
-#License version 2 as published by the Free Software Foundation.
-
-#This program is distributed in the hope that it will be useful,
-#but WITHOUT ANY WARRANTY; without even the implied warranty of
-#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-#GNU General Public License for more details.
-#You should have received a copy of the GNU Lesser General Public License
-#along with this program; if not, write to the Free Software
-#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-from base import BaseProxy
-
-class Accessible(BaseProxy):
- """
- The base interface which is implemented by all accessible objects.
- All objects support interfaces for querying their contained
- 'children' and position in the accessible-object hierarchy,
- whether or not they actually have children.
- """
-
- def getApplication(self, *args, **kwargs):
- """
- Get the containing Application for this object.
- @return the Application instance to which this object belongs.
- """
- func = self.get_dbus_method("getApplication")
- return func(*args, **kwargs)
-
- def getAttributes(self, *args, **kwargs):
- """
- Get a list of properties applied to this object as a whole, as
- an AttributeSet consisting of name-value pairs. As such these
- attributes may be considered weakly-typed properties or annotations,
- as distinct from the strongly-typed interface instance data declared
- using the IDL "attribute" keyword.
- Not all objects have explicit "name-value pair" AttributeSet
- properties.
- Attribute names and values may have any UTF-8 string value, however
- where possible, in order to facilitate consistent use and exposure
- of "attribute" properties by applications and AT clients, attribute
- names and values should chosen from a publicly-specified namespace
- where appropriate.
- Where possible, the names and values in the name-value pairs
- should be chosen from well-established attribute namespaces using
- standard semantics. For example, attributes of Accessible objects
- corresponding to XHTML content elements should correspond to
- attribute names and values specified in the w3c XHTML specification,
- at http://www.w3.org/TR/xhtml2, where such values are not already
- exposed via a more strongly-typed aspect of the AT-SPI API. Metadata
- names and values should be chosen from the 'Dublin Core' Metadata
- namespace using Dublin Core semantics: http://dublincore.org/dcregistry/
- Similarly, relevant structural metadata should be exposed using
- attribute names and values chosen from the CSS2 and WICD specification:
- http://www.w3.org/TR/1998/REC-CSS2-19980512 WICD (http://www.w3.org/TR/2005/WD-WICD-20051121/).
- @return : an AttributeSet encapsulating any "attribute values"
- currently defined for the object.
- """
- func = self.get_dbus_method("getAttributes")
- return func(*args, **kwargs)
-
- def getChildAtIndex(self, *args, **kwargs):
- """
- Get the accessible child of this object at index.
- @param : index
- an in parameter indicating which child is requested (zero-indexed).
- @return : the 'nth' Accessible child of this object.
- """
- func = self.get_dbus_method("getChildAtIndex")
- return func(*args, **kwargs)
-
- def getIndexInParent(self, *args, **kwargs):
- """
- Get the index of this object in its parent's child list.
- @return : a long integer indicating this object's index in the
- parent's list.
- """
- func = self.get_dbus_method("getIndexInParent")
- return func(*args, **kwargs)
-
- def getLocalizedRoleName(self, *args, **kwargs):
- """
- Get a string indicating the type of UI role played by this object,
- translated to the current locale.
- @return : a UTF-8 string indicating the type of UI role played
- by this object.
- """
- func = self.get_dbus_method("getLocalizedRoleName")
- return func(*args, **kwargs)
-
- def getRelationSet(self, *args, **kwargs):
- """
- Get a set defining this object's relationship to other accessible
- objects.
- @return : a RelationSet defining this object's relationships.
- """
- func = self.get_dbus_method("getRelationSet")
- return func(*args, **kwargs)
-
- def getRole(self, *args, **kwargs):
- """
- Get the Role indicating the type of UI role played by this object.
- @return : a Role indicating the type of UI role played by this
- object.
- """
- func = self.get_dbus_method("getRole")
- return func(*args, **kwargs)
-
- def getRoleName(self, *args, **kwargs):
- """
- Get a string indicating the type of UI role played by this object.
- @return : a UTF-8 string indicating the type of UI role played
- by this object.
- """
- func = self.get_dbus_method("getRoleName")
- return func(*args, **kwargs)
-
- def getState(self, *args, **kwargs):
- """
- Get the current state of the object as a StateSet.
- @return : a StateSet encapsulating the currently true states
- of the object.
- """
- func = self.get_dbus_method("getState")
- return func(*args, **kwargs)
-
- def isEqual(self, *args, **kwargs):
- """
- Determine whether an Accessible refers to the same object as
- another. This method should be used rather than brute-force comparison
- of object references (i.e. "by-value" comparison), as two object
- references may have different apparent values yet refer to the
- same object.
- @param : obj
- an Accessible object reference to compare to
- @return : a boolean indicating whether the two object references
- point to the same object.
- """
- func = self.get_dbus_method("isEqual")
- return func(*args, **kwargs)
-
- def unimplemented(self, *args, **kwargs):
- """
- /cond future expansion
- """
- func = self.get_dbus_method("unimplemented")
- return func(*args, **kwargs)
-
- def get_childCount(self):
- self._pgetter(self._dbus_interface, "childCount")
- def set_childCount(self, value):
- self._psetter(self._dbus_interface, "childCount", value)
- _childCountDoc = \
- """
- childCount: the number of children contained by this object.
- """
- childCount = property(fget=get_childCount, fset=set_childCount, doc=_childCountDoc)
-
- def get_description(self):
- self._pgetter(self._dbus_interface, "description")
- def set_description(self, value):
- self._psetter(self._dbus_interface, "description", value)
- _descriptionDoc = \
- """
- a string describing the object in more detail than name.
- """
- description = property(fget=get_description, fset=set_description, doc=_descriptionDoc)
-
- def get_name(self):
- self._pgetter(self._dbus_interface, "name")
- def set_name(self, value):
- self._psetter(self._dbus_interface, "name", value)
- _nameDoc = \
- """
- a (short) string representing the object's name.
- """
- name = property(fget=get_name, fset=set_name, doc=_nameDoc)
-
- def get_parent(self):
- self._pgetter(self._dbus_interface, "parent")
- def set_parent(self, value):
- self._psetter(self._dbus_interface, "parent", value)
- _parentDoc = \
- """
- an Accessible object which is this object's containing object.
- """
- parent = property(fget=get_parent, fset=set_parent, doc=_parentDoc)
#along with this program; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-from weakref import proxy
+import dbus as _dbus
+from dbus.proxies import Interface as _Interface
-from dbus.proxies import Interface, ProxyObject
from dbus.exceptions import *
+from factory import create_accessible, add_accessible_class
+
+import constants
class AccessibleObjectNoLongerExists(Exception):
pass
#------------------------------------------------------------------------------
-class Enum(int):
+class _Enum(int):
def __str__(self):
return self._enum_lookup(int(self))
#------------------------------------------------------------------------------
-class BaseProxy(Interface):
- """
- The base D-Bus proxy for a remote object that implements one or more
- of the AT-SPI interfaces.
- This class must be further specialised as the cache stores are different
- for Desktop objects and other Accessible objects.
- """
-
- def __new__(cls, *args, **kwargs):
- Interface.__new__(cls, *args, **kwargs)
+class _BaseProxyMeta(type):
+ def __init__(cls, *args, **kwargs):
+ type.__init__(cls, *args, **kwargs)
queryable_interfaces = {
- 'Accessible':ATSPI_ACCESSIBLE,
- 'Action':ATSPI_ACTION,
- 'Application':ATSPI_APPLICATION,
- 'Collection':ATSPI_COLLECTION,
- 'Component':ATSPI_COMPONENT,
- 'Desktop':ATSPI_DESKTOP,
- 'Document':ATSPI_DOCUMENT,
- 'EditableText':ATSPI_EDITABLE_TEXT,
- 'Hypertext':ATSPI_HYPERTEXT,
- 'Hyperlink':ATSPI_HYPERLINK,
- 'Image':ATSPI_IMAGE,
- 'Selection':ATSPI_SELECTION,
- 'StreamableContent':ATSPI_STREAMABLE_CONTENT,
- 'Table':ATSPI_TABLE,
- 'Text':ATSPI_TEXT,
- 'Value':ATSPI_VALUE,
+ 'Accessible':constants.ATSPI_ACCESSIBLE,
+ 'Action':constants.ATSPI_ACTION,
+ 'Application':constants.ATSPI_APPLICATION,
+ 'Collection':constants.ATSPI_COLLECTION,
+ 'Component':constants.ATSPI_COMPONENT,
+ 'Desktop':constants.ATSPI_DESKTOP,
+ 'Document':constants.ATSPI_DOCUMENT,
+ 'EditableText':constants.ATSPI_EDITABLE_TEXT,
+ 'Hypertext':constants.ATSPI_HYPERTEXT,
+ 'Hyperlink':constants.ATSPI_HYPERLINK,
+ 'Image':constants.ATSPI_IMAGE,
+ 'Selection':constants.ATSPI_SELECTION,
+ 'StreamableContent':constants.ATSPI_STREAMABLE_CONTENT,
+ 'Table':constants.ATSPI_TABLE,
+ 'Text':constants.ATSPI_TEXT,
+ 'Value':constants.ATSPI_VALUE,
}
for interface in queryable_interfaces.keys():
return self.queryInterface(object, queryable_interfaces[interface])
setattr(cls, name, new_query)
- def __init__(self, obj, cache, path, interface):
+#------------------------------------------------------------------------------
+
+class _BaseProxy(_Interface):
+ """
+ The base D-Bus proxy for a remote object that implements one or more
+ of the AT-SPI interfaces.
+ """
+
+ __metaclass__ = _BaseProxyMeta
+
+ def __init__(self, cache, app_name, acc_path, parent, interface, dbus_object=None, connection=None):
"""
Create a D-Bus Proxy for an ATSPI interface.
- obj - The D-Bus proxy object this interface uses for D-Bus calls.
- cache - Cache storing data for this object.
- path - The object path of the remote object.
- interface - The name of the ATSPI interface that this proxy implements.
+ cache - ApplicationCache, where the cached data for the accessible can be obtained.
+ app_name - D-Bus bus name of the application this accessible belongs to.
+ acc_path - D-Bus object path of the server side accessible object.
+ parent - Parent accessible.
+ interface - D-Bus interface of the object. Used to decide which accessible class to instanciate.
+ dbus_object(kwarg) - The D-Bus proxy object used by the accessible for D-Bus method calls.
"""
- Interface.__init__(self, obj, interface)
+ self._cache = cache
+ self._app_name = app_name
+ self._acc_path = acc_path
+ self._parent = parent
- self._cobj = ref(cache)
- self._path = path
+ if not dbus_object:
+ dbus_object = connection.get_object(self._app_name, self._acc_path, introspect=False)
+ self._dbus_object = dbus_object
+
+ _Interface.__init__(self, self._dbus_object, interface)
self._pgetter = self.get_dbus_method("Get", dbus_interface="org.freedesktop.DBus.Properties")
self._psetter = self.get_dbus_method("Set", dbus_interface="org.freedesktop.DBus.Properties")
def __getattr__(self, *args, **kwargs):
- """
- The __getattr__ function must return the D-Bus method wrapped in a
- method to translate exceptions.
- """
- # Need to throw an AccessibleObjectNoLongerExists exception
- # on D-Bus error of the same type.
- try:
- return Interface.__getattr__(self, *args, **kwargs)
- except UnknownMethodException, e:
- raise NotImplementedError(e)
- except DBusException, e:
- raise LookupError(e)
+ method = _Interface.__getattr__(self, *args, **kwargs)
- @property
- def _cache(self):
- c = self._cobj()
- if not c:
- raise AccessibleObjectNoLongerExits("Application has been removed")
+ def dbus_method_func(*args, **kwargs):
+ # TODO Need to throw an AccessibleObjectNoLongerExists exception
+ # on D-Bus error of the same type.
+ try:
+ method(*args, **kwargs)
+ except UnknownMethodException, e:
+ raise NotImplementedError(e)
+ except DBusException, e:
+ raise LookupError(e)
+
+ return dbus_method_func
@property
- def _data(self):
+ def cached_data(self):
try:
- data = self._cache._objects[self._path]
+ return self._cache[self._app_name][self._acc_path]
except KeyError:
- raise AccessibleObjectNoLongerExists, 'Cache data cannot be found for path %s' % (self._path,)
- return data
+ raise AccessibleObjectNoLongerExists, \
+ 'Cache data cannot be found for path %s in app %s' % (self._acc_path, self._app_name)
@property
def interfaces(self):
return self._data.interfaces
def queryInterface(self, interface):
+ """
+ Gets a different accessible interface for this object
+ or raises a NotImplemented error if the given interface
+ is not supported.
+ """
if interface in self._data.interfaces:
- return self._cache.proxyFactory(self._path, interface, dbus_obj=self._obj)
+ return create_accessible(self._cache,
+ self._app_name,
+ self._acc_path,
+ self._parent,
+ interface,
+ dbus_object=self._dbus_object)
else:
raise NotImplementedError(
"%s not supported by accessible object at path %s"
% (interface, self.path))
+#------------------------------------------------------------------------------
+
+class Accessible(_BaseProxy):
+ """
+ The base interface which is implemented by all accessible objects.
+ All objects support interfaces for querying their contained
+ 'children' and position in the accessible-object hierarchy,
+ whether or not they actually have children.
+ """
+
+ def getApplication(self):
+ """
+ Get the containing Application for this object.
+ @return the Application instance to which this object belongs.
+ """
+ application_root = self._cache.get_application_root(self._app_name)
+ return create_accessible(self._cache,
+ self._app_name,
+ application_root,
+ constants.NULL_BUS_NAME,
+ constants.NULL_OBJECT_PATH,
+ constants.ATSPI_ACCESSIBLE,
+ dbus_object=self._dbus_object)
+
+ def getAttributes(self, *args, **kwargs):
+ """
+ Get a list of properties applied to this object as a whole, as
+ an AttributeSet consisting of name-value pairs. As such these
+ attributes may be considered weakly-typed properties or annotations,
+ as distinct from the strongly-typed interface instance data declared
+ using the IDL "attribute" keyword.
+ Not all objects have explicit "name-value pair" AttributeSet
+ properties.
+ Attribute names and values may have any UTF-8 string value, however
+ where possible, in order to facilitate consistent use and exposure
+ of "attribute" properties by applications and AT clients, attribute
+ names and values should chosen from a publicly-specified namespace
+ where appropriate.
+ Where possible, the names and values in the name-value pairs
+ should be chosen from well-established attribute namespaces using
+ standard semantics. For example, attributes of Accessible objects
+ corresponding to XHTML content elements should correspond to
+ attribute names and values specified in the w3c XHTML specification,
+ at http://www.w3.org/TR/xhtml2, where such values are not already
+ exposed via a more strongly-typed aspect of the AT-SPI API. Metadata
+ names and values should be chosen from the 'Dublin Core' Metadata
+ namespace using Dublin Core semantics: http://dublincore.org/dcregistry/
+ Similarly, relevant structural metadata should be exposed using
+ attribute names and values chosen from the CSS2 and WICD specification:
+ http://www.w3.org/TR/1998/REC-CSS2-19980512 WICD (http://www.w3.org/TR/2005/WD-WICD-20051121/).
+ @return : an AttributeSet encapsulating any "attribute values"
+ currently defined for the object.
+ """
+ func = self.get_dbus_method("getAttributes")
+ return func(*args, **kwargs)
+
+ def getChildAtIndex(self, index):
+ """
+ Get the accessible child of this object at index.
+ @param : index
+ an in parameter indicating which child is requested (zero-indexed).
+ @return : the 'nth' Accessible child of this object.
+ """
+ path = self.cached_data.children[index]
+ return create_accessible(self._cache,
+ self._app_name,
+ path,
+ self,
+ constants.ATSPI_ACCESSIBLE,
+ dbus_object=self._dbus_object)
+
+ def getIndexInParent(self, *args, **kwargs):
+ """
+ Get the index of this object in its parent's child list.
+ @return : a long integer indicating this object's index in the
+ parent's list.
+ """
+ func = self.get_dbus_method("getIndexInParent")
+ return func(*args, **kwargs)
+
+ def getLocalizedRoleName(self, *args, **kwargs):
+ """
+ Get a string indicating the type of UI role played by this object,
+ translated to the current locale.
+ @return : a UTF-8 string indicating the type of UI role played
+ by this object.
+ """
+ func = self.get_dbus_method("getLocalizedRoleName")
+ return func(*args, **kwargs)
+
+ def getRelationSet(self, *args, **kwargs):
+ """
+ Get a set defining this object's relationship to other accessible
+ objects.
+ @return : a RelationSet defining this object's relationships.
+ """
+ func = self.get_dbus_method("getRelationSet")
+ return func(*args, **kwargs)
+
+ def getRole(self):
+ """
+ Get the Role indicating the type of UI role played by this object.
+ @return : a Role indicating the type of UI role played by this
+ object.
+ """
+ return self.cached_data.role
+
+ def getRoleName(self, *args, **kwargs):
+ """
+ Get a string indicating the type of UI role played by this object.
+ @return : a UTF-8 string indicating the type of UI role played
+ by this object.
+ """
+ func = self.get_dbus_method("getRoleName")
+ return func(*args, **kwargs)
+
+ def getState(self, *args, **kwargs):
+ """
+ Get the current state of the object as a StateSet.
+ @return : a StateSet encapsulating the currently true states
+ of the object.
+ """
+ func = self.get_dbus_method("getState")
+ return func(*args, **kwargs)
+
+ def isEqual(self, accessible):
+ """
+ Determine whether an Accessible refers to the same object as
+ another. This method should be used rather than brute-force comparison
+ of object references (i.e. "by-value" comparison), as two object
+ references may have different apparent values yet refer to the
+ same object.
+ @param : obj
+ an Accessible object reference to compare to
+ @return : a boolean indicating whether the two object references
+ point to the same object.
+ """
+ return (self._app_name == accessible._app_name) and \
+ (self._acc_path == accessible._acc_path)
+
+ def unimplemented(self, *args, **kwargs):
+ """
+ /cond future expansion
+ """
+ func = self.get_dbus_method("unimplemented")
+ return func(*args, **kwargs)
+
+ def get_childCount(self):
+ return len(self.cached_data.children)
+ _childCountDoc = \
+ """
+ childCount: the number of children contained by this object.
+ """
+ childCount = property(fget=get_childCount, doc=_childCountDoc)
+
+ def get_description(self):
+ return self.cached_data.description
+ _descriptionDoc = \
+ """
+ a string describing the object in more detail than name.
+ """
+ description = property(fget=get_description, doc=_descriptionDoc)
+
+ def get_name(self):
+ return self.cached_data.name
+ _nameDoc = \
+ """
+ a (short) string representing the object's name.
+ """
+ name = property(fget=get_name, doc=_nameDoc)
+
+ def get_parent(self):
+ # The parent attribute is part of the base proxy
+ return self._parent
+ _parentDoc = \
+ """
+ an Accessible object which is this object's containing object.
+ """
+ parent = property(fget=get_parent, doc=_parentDoc)
+
+# ATTENTION - Register the Accessible class with the accessible factory.
+add_accessible_class(constants.ATSPI_ACCESSIBLE, Accessible)
+
#END----------------------------------------------------------------------------
#along with this program; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-from base import AccessibleObjectNoLongerExists
-from factory import interfaceFactory
+import dbus as _dbus
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
-class BaseCache(object):
- """
- Base object for the Desktop, Accessible and Application caches.
-
- Abstracts common initialization.
- """
-
+class _BaseCache(object):
def __init__(self, connection, bus_name):
"""
self._connection = connection
self._bus_name = bus_name
- obj = connection.get_object(bus_name, self._PATH)
- itf = dbus.Interface(obj, self._INTERFACE)
+ obj = connection.get_object(bus_name, self._PATH, introspect=False)
+ itf = _dbus.Interface(obj, self._INTERFACE)
self._objects = {}
- getMethod = itf.get_dbus_method(self._GET_METHOD)
- self._updateObjects(getMethod)
+ get_method = itf.get_dbus_method(self._GET_METHOD)
+ self._update_objects(get_method())
- self._signalMatch = itf.connect_to_signal(self._UPDATE_SIGNAL, self._updateHandler)
+ self._signalMatch = itf.connect_to_signal(self._UPDATE_SIGNAL, self._update_handler)
- def _updateHandler(self, updates):
+ def __getitem__(self, key):
+ return self._objects[key]
+
+ def __contains__(self, key):
+ return key in self._objects
+
+ def _update_handler(self, updates):
update, remove = updates
- self._removeObjects(update)
- self._updateObjects(remove)
+ self._remove_objects(update)
+ self._update_objects(remove)
- def _updateObjects(self, objects):
+ def _update_objects(self, objects):
for data in objects:
#First element is the object path.
path = data[0]
else:
self._objects[path] = _CacheData(data)
- def _removeObjects(self, paths):
+ def _remove_objects(self, paths):
for path in paths:
del(self._objects[path])
- def getAccessible(self, path, interface, dbus_object=None):
- """
- Gets a client side proxy for the accessible object found
- at the path.
-
- path - The D-Bus path of the remote object.
- interface - The interface that the accessible object should support.
- dbus_object=None - The D-Bus proxy object backing this interface.
- """
- if path in self._objects:
- if not dbus_object:
- dbus_object = self._connection.get_object(self._bus_name, path, introspect=False)
- return interfaceFactory(proxy, self, path, interface)
- else:
- raise AccessibleObjectNoLongerExists, "D-Bus reference not found in cache"
-
#------------------------------------------------------------------------------
-class AccessibleCache(BaseCache):
+class AccessibleCache(_BaseCache):
"""
There is one accessible cache per application.
For each application the accessible cache stores
It also acts as the factory for creating client
side proxies for these accessible objects.
+
+ connection - DBus connection.
+ busName - Name of DBus connection where cache interface resides.
"""
_PATH = '/org/freedesktop/atspi/tree'
_UPDATE_SIGNAL = 'updateTree'
def __init__(self, connection, bus_name):
- BaseCache.__init__(self, connection, bus_name)
+ _BaseCache.__init__(self, connection, bus_name)
- obj = connection.get_object(_self.bus_name, self._PATH)
- itf = dbus.Interface(obj, self._INTERFACE)
+ obj = connection.get_object(self._bus_name, self._PATH, introspect=False)
+ itf = _dbus.Interface(obj, self._INTERFACE)
self._root = itf.getRoot()
- def getRootAccessible(self):
- """
- Gets the accessible object at the root of the tree.
- """
- return self.getAccessible(self._root)
-
-#------------------------------------------------------------------------------
-
-class DesktopCache(BaseCache):
- """
- Cache of desktop objects obtained from the registry.
-
- The desktop interface on the registry object is the
- same as that of the general tree interface on the
- applications.
-
- The difference is that the children data refers to
- bus names of the applications rather than the object
- paths of particular accessible objects within an application.
- """
-
- _PATH = '/org/freedesktop/atspi/registry'
- _INTERFACE = 'org.freedesktop.atspi.Registry'
- _GET_METHOD = 'getDesktops'
- _UPDATE_SIGNAL = 'updateDesktops'
-
- def __init__(self, connection, bus_name):
- self._app_cache = ApplicationCache(connection, bus_name)
-
- def getApplication(self, name):
- try:
- self._app_cache[name].getRootAccessible()
- except KeyError:
- raise AccessibleObjectNoLongerExists("Application no longer exists")
-
-#------------------------------------------------------------------------------
-
-class ApplicationCache(object):
- """
- Holds a mapping of bus names of each accessible application
- to the applications accessible cache.
-
- Makes calls and recieves updates from the registry
- daemon to keep the cache up to date.
- """
+ def _get_root(self):
+ return self._root
- _PATH = '/org/freedesktop/atspi/registry'
- _INTERFACE = 'org.freedesktop.atspi.Registry'
- _GET_METHOD = 'getApplications'
- _UPDATE_SIGNAL = 'updateApplications'
-
- def _updateApplications(self, names):
- for name in names:
- if name not in self._applications:
- self._applications[name] = AccessibleCache(self._connection,
- self._busName,
- self._treePath)
-
- def _removeApplications(self, names):
- for name in names:
- del(self._applications[name])
+ root = property(fget=_get_root)
#END---------------------------------------------------------------------------
['focus:']
}
-import other
-
-# Build a dictionary mapping state values to names based on the prefix of the
-# enum constants.
-STATE_VALUE_TO_NAME = dict(((value, name[6:].lower().replace('_', ' '))
- for name, value
- in vars(other).items()
- if name.startswith('STATE_')))
-
-# Build a dictionary mapping relation values to names based on the prefix of
-# the enum constants.
-RELATION_VALUE_TO_NAME = dict(((value, name[9:].lower().replace('_', ' '))
- for name, value
- in vars(other).items()
- if name.startswith('RELATION_')))
-
-del other
+ATSPI_ACCESSIBLE = 'org.freedesktop.atspi.Accessible'
+ATSPI_ACTION = 'org.freedesktop.atspi.Action'
+ATSPI_APPLICATION = 'org.freedesktop.atspi.Application'
+ATSPI_COMPONENT = 'org.freedesktop.atspi.Component'
+ATSPI_COLLECTION = 'org.freedesktop.atspi.Collection'
+ATSPI_DESKTOP = 'org.freedesktop.atspi.Desktop'
+ATSPI_DOCUMENT = 'org.freedesktop.atspi.Document'
+ATSPI_EDITABLE_TEXT = 'org.freedesktop.atspi.EditableText'
+ATSPI_HYPERLINK = 'org.freedesktop.atspi.Hyperlink'
+ATSPI_HYPERTEXT = 'org.freedesktop.atspi.Hypertext'
+ATSPI_IMAGE = 'org.freedesktop.atspi.Image'
+ATSPI_LOGIN_HELPER = 'org.freedesktop.atspi.LoginHelper'
+ATSPI_SELECTION = 'org.freedesktop.atspi.Selection'
+ATSPI_SELECTOR = 'org.freedesktop.atspi.Selector'
+ATSPI_STREAMABLE_CONTENT = 'org.freedesktop.atspi.Content'
+ATSPI_TABLE = 'org.freedesktop.atspi.Table'
+ATSPI_TEXT = 'org.freedesktop.atspi.Text'
+ATSPI_VALUE = 'org.freedesktop.atspi.Value'
+++ /dev/null
-#Copyright (C) 2008 Codethink Ltd
-
-#This library is free software; you can redistribute it and/or
-#modify it under the terms of the GNU Lesser General Public
-#License version 2 as published by the Free Software Foundation.
-
-#This program is distributed in the hope that it will be useful,
-#but WITHOUT ANY WARRANTY; without even the implied warranty of
-#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-#GNU General Public License for more details.
-#You should have received a copy of the GNU Lesser General Public License
-#along with this program; if not, write to the Free Software
-#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-from base import BaseProxy
-
-from accessible import Accessible
-
-class Desktop(Accessible):
- """
- The desktop class implements the
- accessible interface, but uses a different
- method to access its chilren and to obtain cached
- data.
-
- This is because application caches are separate
- and the children of the desktop are applications.
- The child access must get the root accessible
- of the application cache that is accessed.
-
- The data is accessed from the desktop cache.
- """
-
- @property
- def _data(self):
- try:
- data = self._cache._objects[self._path]
- except KeyError, ReferenceError:
- raise AccessibleObjectNoLongerExists, 'Cache data cannot be found for path %s' % (self._path,)
- return data
-
- def getApplication(self, *args, **kwargs):
- """
- Get the containing Application for this object.
- @return the Application instance to which this object belongs.
- """
- func = self.get_dbus_method("getApplication")
- return func(*args, **kwargs)
-
- def getAttributes(self, *args, **kwargs):
- """
- Get a list of properties applied to this object as a whole, as
- an AttributeSet consisting of name-value pairs. As such these
- attributes may be considered weakly-typed properties or annotations,
- as distinct from the strongly-typed interface instance data declared
- using the IDL "attribute" keyword.
- Not all objects have explicit "name-value pair" AttributeSet
- properties.
- Attribute names and values may have any UTF-8 string value, however
- where possible, in order to facilitate consistent use and exposure
- of "attribute" properties by applications and AT clients, attribute
- names and values should chosen from a publicly-specified namespace
- where appropriate.
- Where possible, the names and values in the name-value pairs
- should be chosen from well-established attribute namespaces using
- standard semantics. For example, attributes of Accessible objects
- corresponding to XHTML content elements should correspond to
- attribute names and values specified in the w3c XHTML specification,
- at http://www.w3.org/TR/xhtml2, where such values are not already
- exposed via a more strongly-typed aspect of the AT-SPI API. Metadata
- names and values should be chosen from the 'Dublin Core' Metadata
- namespace using Dublin Core semantics: http://dublincore.org/dcregistry/
- Similarly, relevant structural metadata should be exposed using
- attribute names and values chosen from the CSS2 and WICD specification:
- http://www.w3.org/TR/1998/REC-CSS2-19980512 WICD (http://www.w3.org/TR/2005/WD-WICD-20051121/).
- @return : an AttributeSet encapsulating any "attribute values"
- currently defined for the object.
- """
- func = self.get_dbus_method("getAttributes")
- return func(*args, **kwargs)
-
- def getChildAtIndex(self, *args, **kwargs):
- """
- Get the accessible child of this object at index.
- @param : index
- an in parameter indicating which child is requested (zero-indexed).
- @return : the 'nth' Accessible child of this object.
- """
- func = self.get_dbus_method("getChildAtIndex")
- return func(*args, **kwargs)
-
- def getIndexInParent(self, *args, **kwargs):
- """
- Get the index of this object in its parent's child list.
- @return : a long integer indicating this object's index in the
- parent's list.
- """
- func = self.get_dbus_method("getIndexInParent")
- return func(*args, **kwargs)
-
- def getLocalizedRoleName(self, *args, **kwargs):
- """
- Get a string indicating the type of UI role played by this object,
- translated to the current locale.
- @return : a UTF-8 string indicating the type of UI role played
- by this object.
- """
- func = self.get_dbus_method("getLocalizedRoleName")
- return func(*args, **kwargs)
-
- def getRelationSet(self, *args, **kwargs):
- """
- Get a set defining this object's relationship to other accessible
- objects.
- @return : a RelationSet defining this object's relationships.
- """
- func = self.get_dbus_method("getRelationSet")
- return func(*args, **kwargs)
-
- def getRole(self, *args, **kwargs):
- """
- Get the Role indicating the type of UI role played by this object.
- @return : a Role indicating the type of UI role played by this
- object.
- """
- func = self.get_dbus_method("getRole")
- return func(*args, **kwargs)
-
- def getRoleName(self, *args, **kwargs):
- """
- Get a string indicating the type of UI role played by this object.
- @return : a UTF-8 string indicating the type of UI role played
- by this object.
- """
- func = self.get_dbus_method("getRoleName")
- return func(*args, **kwargs)
-
- def getState(self, *args, **kwargs):
- """
- Get the current state of the object as a StateSet.
- @return : a StateSet encapsulating the currently true states
- of the object.
- """
- func = self.get_dbus_method("getState")
- return func(*args, **kwargs)
-
- def isEqual(self, *args, **kwargs):
- """
- Determine whether an Accessible refers to the same object as
- another. This method should be used rather than brute-force comparison
- of object references (i.e. "by-value" comparison), as two object
- references may have different apparent values yet refer to the
- same object.
- @param : obj
- an Accessible object reference to compare to
- @return : a boolean indicating whether the two object references
- point to the same object.
- """
- func = self.get_dbus_method("isEqual")
- return func(*args, **kwargs)
-
- def unimplemented(self, *args, **kwargs):
- """
- /cond future expansion
- """
- func = self.get_dbus_method("unimplemented")
- return func(*args, **kwargs)
-
- def get_childCount(self):
- self._pgetter(self._dbus_interface, "childCount")
- def set_childCount(self, value):
- self._psetter(self._dbus_interface, "childCount", value)
- _childCountDoc = \
- """
- childCount: the number of children contained by this object.
- """
- childCount = property(fget=get_childCount, fset=set_childCount, doc=_childCountDoc)
-
- def get_description(self):
- self._pgetter(self._dbus_interface, "description")
- def set_description(self, value):
- self._psetter(self._dbus_interface, "description", value)
- _descriptionDoc = \
- """
- a string describing the object in more detail than name.
- """
- description = property(fget=get_description, fset=set_description, doc=_descriptionDoc)
-
- def get_name(self):
- self._pgetter(self._dbus_interface, "name")
- def set_name(self, value):
- self._psetter(self._dbus_interface, "name", value)
- _nameDoc = \
- """
- a (short) string representing the object's name.
- """
- name = property(fget=get_name, fset=set_name, doc=_nameDoc)
-
- def get_parent(self):
- self._pgetter(self._dbus_interface, "parent")
- def set_parent(self, value):
- self._psetter(self._dbus_interface, "parent", value)
- _parentDoc = \
- """
- an Accessible object which is this object's containing object.
- """
- parent = property(fget=get_parent, fset=set_parent, doc=_parentDoc)
#along with this program; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-from base import *
-from accessible import *
+#------------------------------------------------------------------------------
-ATSPI_ACCESSIBLE = 'org.freedesktop.atspi.Accessible'
-ATSPI_ACTION = 'org.freedesktop.atspi.Action'
-ATSPI_APPLICATION = 'org.freedesktop.atspi.Application'
-ATSPI_COMPONENT = 'org.freedesktop.atspi.Component'
-ATSPI_DOCUMENT = 'org.freedesktop.atspi.Document'
-ATSPI_EDITABLE_TEXT = 'org.freedesktop.atspi.EditableText'
-ATSPI_HYPERLINK = 'org.freedesktop.atspi.Hyperlink'
-ATSPI_HYPERTEXT = 'org.freedesktop.atspi.Hypertext'
-ATSPI_IMAGE = 'org.freedesktop.atspi.Image'
-ATSPI_LOGIN_HELPER = 'org.freedesktop.atspi.LoginHelper'
-ATSPI_SELECTION = 'org.freedesktop.atspi.Selection'
-ATSPI_SELECTOR = 'org.freedesktop.atspi.Selector'
-ATSPI_STREAMABLE_CONTENT = 'org.freedesktop.atspi.Content'
-ATSPI_TABLE = 'org.freedesktop.atspi.Table'
-ATSPI_TEXT = 'org.freedesktop.atspi.Text'
-ATSPI_VALUE = 'org.freedesktop.atspi.Value'
+class AccessibleFactory(object):
+ __accessible_interfaces = {}
-#------------------------------------------------------------------------------
+ def create_accessible(self, cache, app_name, acc_path, parent, interface, dbus_object=None, connection=None):
+ class_ = self.__accessible_interfaces[interface]
+ return class_(cache,
+ app_name,
+ acc_path,
+ parent,
+ interface,
+ dbus_object=dbus_object,
+ connection=connection)
+
+ def add_accessible_class(self, name, cls):
+ self.__accessible_interfaces[name] = cls
-_interfaces = {
- ATSPI_ACCESSIBLE:Accessible,
- #ATSPI_ACTION:
- #ATSPI_APPLICATION:
- #ATSPI_COMPONENT:
- #ATSPI_DOCUMENT:
- #ATSPI_EDITABLE_TEXT:
- #ATSPI_HYPERLINK:
- #ATSPI_HYPERTEXT:
- #ATSPI_IMAGE:
- #ATSPI_LOGIN_HELPER:
- #ATSPI_SELECTION:
- #ATSPI_SELECTOR:
- #ATSPI_STREAMABLE_CONTENT:
- #ATSPI_TABLE:
- #ATSPI_TEXT:
- #ATSPI_TREE:
- #ATSPI_VALUE:
-}
+_factory = AccessibleFactory()
-def interfaceFactory(self, busobject, cache, app, path, interface):
+def create_accessible(cache, app_name, acc_path, parent, interface, dbus_object=None, connection=None):
"""
- The queryInterfaces method needs to return
- different atspi interfaces depending on the interface name.
- This class registers names and ATSPI interface
- classes to perform this task.
+ Used to create different python classes for each of the accessible interfaces.
+
+ The decision on which class to create is based on the name of the
+ accessible interface.
+
+ cache - ApplicationCache, where the cached data for the accessible can be obtained.
+ app_name - D-Bus bus name of the application this accessible belongs to.
+ acc_path - D-Bus object path of the server side accessible object.
+ app_parent - D-Bus bus name of the parent objects application.
+ acc_parent - D-Bus object path of the parent accessible.
+ interface - D-Bus interface of the object. Used to decide which accessible class to instanciate.
+ dbus_object(kwarg) - The D-Bus proxy object used by the accessible for D-Bus method calls.
+ connection(kwarg) - Client side D-Bus connection, provided if no D-Bus proxy is available.
"""
- return _interfaces[interface](object, cache, app, path, interface)
+ return _factory.create_accessible(cache,
+ app_name,
+ acc_path,
+ parent,
+ interface,
+ dbus_object=dbus_object,
+ connection=connection)
+
+def add_accessible_class(name, cls):
+ _factory.add_accessible_class(name, cls)
#END----------------------------------------------------------------------------
#along with this program; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-from base import *
-from accessible import *
+from base import _BaseProxy, _Enum
+from base import Accessible as _Accessible
-class Action(BaseProxy):
+class Action(_BaseProxy):
"""
nActions = property(fget=get_nActions, fset=set_nActions, doc=_nActionsDoc)
-class Application(Accessible):
+class Application(_Accessible):
"""
height = property(fget=_get_height, fset=_set_height)
-class Collection(BaseProxy):
+class Collection(_BaseProxy):
def createMatchRule(self, *args, **kwargs):
func = self.get_dbus_method("createMatchRule")
func = self.get_dbus_method("unImplemented4")
return func(*args, **kwargs)
- class MatchType(Enum):
+ class MatchType(_Enum):
_enum_lookup = {
0:'MATCH_INVALID',
1:'MATCH_ALL',
MATCH_NONE = MatchType(3)
- class SortOrder(Enum):
+ class SortOrder(_Enum):
_enum_lookup = {
0:'SORT_ORDER_INVALID',
1:'SORT_ORDER_CANONICAL',
SORT_ORDER_TAB = SortOrder(3)
- class TreeTraversalType(Enum):
+ class TreeTraversalType(_Enum):
_enum_lookup = {
0:'TREE_RESTRICT_CHILDREN',
1:'TREE_RESTRICT_SIBLING',
self[1] = val
id = property(fget=_get_id, fset=_set_id)
-class CommandListener(BaseProxy):
+class CommandListener(_BaseProxy):
"""
An interface which should be implemented by assistive technologies
or other clients of the Selector interface, over which notifications
return func(*args, **kwargs)
-class Component(BaseProxy):
+class Component(_BaseProxy):
"""
return func(*args, **kwargs)
-class ComponentLayer(Enum):
+class ComponentLayer(_Enum):
_enum_lookup = {
0:'LAYER_INVALID',
1:'LAYER_BACKGROUND',
}
-class ContentStream(BaseProxy):
+class ContentStream(_BaseProxy):
"""
An interface by which the requested data from a StreamableContent
object may be read by the client.
class NotSupported(Exception):
pass
- class SeekType(Enum):
+ class SeekType(_Enum):
"""
Specifies the meaning of a seek 'offset'. Not all SeekTypes are
supported by all StreamableContent data sources, for instance
self[6] = val
is_text = property(fget=_get_is_text, fset=_set_is_text)
-class DeviceEventController(BaseProxy):
+class DeviceEventController(_BaseProxy):
"""
The interface via which clients request notification of device
events, and through which device events may be simulated.
return func(*args, **kwargs)
-class DeviceEventListener(BaseProxy):
+class DeviceEventListener(_BaseProxy):
"""
This interface should be implemented by AT-SPI clients who wish
to make use of the DeviceEventController to receive device event
return func(*args, **kwargs)
-class Document(BaseProxy):
+class Document(_BaseProxy):
"""
Primarily a 'tagging' interface which indicates the start of
document content in the Accessibility hierarchy. Accessible objects
func = self.get_dbus_method("unImplemented_")
return func(*args, **kwargs)
-class Text(BaseProxy):
+class Text(_BaseProxy):
"""
The text interface should be implemented by objects which place
textual information onscreen as character strings or glyphs.
self[3] = val
any_data = property(fget=_get_any_data, fset=_set_any_data)
-class EventListener(BaseProxy):
+class EventListener(_BaseProxy):
"""
A generic interface implemented by objects for the receipt of
event notifications. EventListener is the interface from which
global_ = property(fget=_get_global_, fset=_set_global_)
-class EventType(Enum):
+class EventType(_Enum):
_enum_lookup = {
0:'KEY_PRESSED_EVENT',
1:'KEY_RELEASED_EVENT',
3:'BUTTON_RELEASED_EVENT',
}
-class Hyperlink(BaseProxy):
+class Hyperlink(_BaseProxy):
"""
Instances of Hyperlink are returned by Hypertext objects, and
are the means by which end users and clients interact with linked,
startIndex = property(fget=get_startIndex, fset=set_startIndex, doc=_startIndexDoc)
-class Hypertext(BaseProxy):
+class Hypertext(_BaseProxy):
"""
An interface used for objects which implement linking between
multiple resource or content locations, or multiple 'markers'
return func(*args, **kwargs)
-class Image(BaseProxy):
+class Image(_BaseProxy):
"""
An interface implemented by objects which render image data or
pictorial information to the screen. When onscreen components
self[3] = val
unused = property(fget=_get_unused, fset=_set_unused)
-class KeyEventType(Enum):
+class KeyEventType(_Enum):
_enum_lookup = {
0:'KEY_PRESSED',
1:'KEY_RELEASED',
}
-class KeySynthType(Enum):
+class KeySynthType(_Enum):
_enum_lookup = {
0:'KEY_PRESS',
1:'KEY_RELEASE',
4:'KEY_STRING',
}
-class LOCALE_TYPE(Enum):
+class LOCALE_TYPE(_Enum):
_enum_lookup = {
0:'LOCALE_TYPE_MESSAGES',
1:'LOCALE_TYPE_COLLATE',
5:'LOCALE_TYPE_TIME',
}
-class LoginHelper(BaseProxy):
+class LoginHelper(_BaseProxy):
"""
An interface for use by assistive technologies by which they
can access system information and services on a 'need to know'
func = self.get_dbus_method("unImplemented4")
return func(*args, **kwargs)
- class DeviceReq(Enum):
+ class DeviceReq(_Enum):
_enum_lookup = {
0:'GUI_EVENTS',
1:'CORE_KEYBOARD',
self[0] = val
winID = property(fget=_get_winID, fset=_set_winID)
-class ModifierType(Enum):
+class ModifierType(_Enum):
_enum_lookup = {
0:'MODIFIER_SHIFT',
1:'MODIFIER_SHIFTLOCK',
return func(*args, **kwargs)
-class Relation(BaseProxy):
+class Relation(_BaseProxy):
"""
An interface via which objects' non-hierarchical relationships
to one another are indicated. An instance of Relations represents
return func(*args, **kwargs)
-class RelationType(Enum):
+class RelationType(_Enum):
_enum_lookup = {
0:'RELATION_NULL',
1:'RELATION_LABEL_FOR',
18:'RELATION_LAST_DEFINED',
}
-class Role(Enum):
+class Role(_Enum):
_enum_lookup = {
0:'ROLE_INVALID',
1:'ROLE_ACCELERATOR_LABEL',
90:'ROLE_LAST_DEFINED',
}
-class Selection(BaseProxy):
+class Selection(_BaseProxy):
"""
An interface which indicates that an object exposes a 'selection'
model, allowing the selection of one or more of its children.
nSelectedChildren = property(fget=get_nSelectedChildren, fset=set_nSelectedChildren, doc=_nSelectedChildrenDoc)
-class Selector(BaseProxy):
+class Selector(_BaseProxy):
"""
This interface is intended for use by assistive technologies
and related user-agents. Via this interface, an assistive technology
"""
supportsReplace = property(fget=get_supportsReplace, fset=set_supportsReplace, doc=_supportsReplaceDoc)
- class CommandResult(Enum):
+ class CommandResult(_Enum):
"""
A code returned by a call to activateCommand, indicating the
result of the activation request.
COMMAND_RESULT_SUCCESS = CommandResult(1)
-class StateSet(BaseProxy):
+class StateSet(_BaseProxy):
"""
The StateSet interface encapsulates a collection of state information.
It allows comparison of state information between object instances,
return func(*args, **kwargs)
-class StateType(Enum):
+class StateType(_Enum):
_enum_lookup = {
0:'STATE_INVALID',
1:'STATE_ACTIVE',
41:'STATE_LAST_DEFINED',
}
-class StreamableContent(BaseProxy):
+class StreamableContent(_BaseProxy):
"""
An interface whereby an object allows its backing content to
be streamed to clients. Negotiation of content type is allowed.
return func(*args, **kwargs)
-class TEXT_BOUNDARY_TYPE(Enum):
+class TEXT_BOUNDARY_TYPE(_Enum):
_enum_lookup = {
0:'TEXT_BOUNDARY_CHAR',
1:'TEXT_BOUNDARY_WORD_START',
6:'TEXT_BOUNDARY_LINE_END',
}
-class TEXT_CLIP_TYPE(Enum):
+class TEXT_CLIP_TYPE(_Enum):
_enum_lookup = {
0:'TEXT_CLIP_NONE',
1:'TEXT_CLIP_MIN',
3:'TEXT_CLIP_BOTH',
}
-class Table(BaseProxy):
+class Table(_BaseProxy):
"""
An interface used by containers whose contained data is arranged
in a "tabular" (i.e. row-column) fashion. Tables may resemble
-class Value(BaseProxy):
+class Value(_BaseProxy):
"""
An interface supporting controls which allow a one-dimensional,
scalar quantity to be modified or which reflect a scalar quantity.
TEXT_CLIP_MIN = TEXT_CLIP_TYPE(1)
TEXT_CLIP_NONE = TEXT_CLIP_TYPE(0)
-
-
--- /dev/null
+#Copyright (C) 2008 Codethink Ltd
+
+#This library is free software; you can redistribute it and/or
+#modify it under the terms of the GNU Lesser General Public
+#License version 2 as published by the Free Software Foundation.
+
+#This program is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#GNU General Public License for more details.
+#You should have received a copy of the GNU Lesser General Public License
+#along with this program; if not, write to the Free Software
+#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+from cache import AccessibleCache
+from factory import create_accessible
+
+import constants
+
+#------------------------------------------------------------------------------
+
+class TestApplicationCache(object):
+ """
+ Test application cache. Accesses single AccessibleCache.
+ """
+
+ def __init__(self, connection, bus_name):
+ self._connection = connection
+ self._bus_name = bus_name
+ self._accessible_cache = AccessibleCache(connection, bus_name)
+
+ def __getitem__(self, key):
+ return self._accessible_cache
+
+ def __contains__(self, key):
+ if key == self._bus_name:
+ return True
+ else:
+ return False
+
+ def get_root(self):
+ return create_accessible(self,
+ self._bus_name,
+ self._accessible_cache.root,
+ None,
+ constants.ATSPI_ACCESSIBLE,
+ connection=self._connection)
+
+ root = property(fget=get_root)
except Exception:
raise LookupError
acc = acc.parent
+
+del constants
G_MODULE_EXPORT void
test_next (int argc, char *argv[])
{
- g_print("Moving to next stage\n");
+ ;
}
G_MODULE_EXPORT void
test_finished (int argc, char *argv[])
{
- g_print("Test has completed\n");
+ ;
}
G_MODULE_EXPORT AtkObject *
"<node name=\"/org/codethink/atspi/test\">"
" <interface name=\"org.codethink.atspi.test\">"
" <method name=\"next\"/>"
+" <method name=\"finish\"/>"
" <signal name=\"started\"/>"
" </interface>"
"</node>";
DBusMessage *reply = NULL;
- g_print("\nRecieved test interface message\n");
-
g_return_val_if_fail(iface != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
if (!strcmp(iface, "org.codethink.atspi.test"))
result = DBUS_HANDLER_RESULT_HANDLED;
}
- if (!strcmp(member, "finished"))
+ if (!strcmp(member, "finish"))
{
((VoidVoid) test_module_finished)();
reply = dbus_message_new_method_return (message);
from xml.dom import minidom
import os
-from pasytest import PasyTestSuite
+from pasytest import PasyTest as _PasyTest
-def createNode(accessible, parentElement):
+import pyatspi
+
+def _createNode(accessible, parentElement):
e = minidom.Element("accessible")
e.attributes["name"] = accessible.name
- e.attributes["role"] = str(int(accessible.role))
+ e.attributes["role"] = str(int(accessible.getRole()))
e.attributes["description"] = accessible.description
- for i in range(0, accessible.numChildren):
- createNode(accessible.getChild(i), e)
+ for i in range(0, accessible.childCount):
+ _createNode(accessible.getChildAtIndex(i), e)
parentElement.appendChild(e)
-class TreeTestSuite(PasyTestSuite):
+class AccessibleTest(_PasyTest):
+
+ __tests__ = ["setup", "tree"]
- __tests__ = ["accessibleTree"]
+ def __init__(self, bus, path):
+ _PasyTest.__init__(self, "Accessible", False)
+ self._bus = bus
+ self._path = path
- def __init__(self, bus, name):
- PasyTestSuite.__init__(self, "Tree")
- self._cache = getAccessibleCache(bus, name)
+ def setup(self):
+ self._cache = pyatspi.TestApplicationCache(self._bus, self._path)
- def accessibleTree(test):
- root = self._cache.getRootAccessible()
+ def tree(self):
+ """
+ This is a mild stress test for the
+ methods:
+
+ getChildAtIndex
+
+ And the attributes:
+
+ name
+ description
+
+ It checks a tree of these values is correctly
+ passed from Application to AT.
+ """
+ root = self._cache.root
doc = minidom.Document()
- createNode(root, doc)
+ _createNode(root, doc)
answer = doc.toprettyxml()
correct = os.path.join(os.environ["TEST_DATA_DIRECTORY"],
file = open(correct)
cstring = file.read()
- test.assertEqual(answer, cstring, "Object tree not passed correctly")
-
- test.win()
+ self.assertEqual(answer, cstring, "Object tree not passed correctly")
#along with this program; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+import gobject
from Events import Events
+import traceback
+
PASY_TEST_NOT_STARTED = 0
PASY_TEST_IN_PROGRESS = 1
PASY_TEST_FAIL = 2
self._state = PASY_TEST_NOT_STARTED
self._name = name
- self._test = test
def win(self):
if self._state == PASY_TEST_IN_PROGRESS:
def run(self):
self._state = PASY_TEST_IN_PROGRESS
- self.entry(self)
+ self.entry()
+
+ def report(self):
+ if self._state == PASY_TEST_WIN:
+ return "%s - PASSED" % (self._name,)
+ elif self._state == PASY_TEST_FAIL:
+ return "%s - FAILED - %s" % (self._name, self.failMsg)
+ else:
+ return "%s - INCOMPLETE" %s (self._name,)
@property
def state(self):
self._func = func
def entry(self):
- self._func(self)
+ try:
+ self._func()
+ except Exception, e:
+ self.fail(e.message)
+ traceback.print_exc()
+ self.win()
class PasyTest(PasyTestStep):
__tests__ = []
def __init__(self, name, cont):
- PasyTest.__init__(self, name)
+ PasyTestStep.__init__(self, name)
self._cont = cont
self._tests = []
- for name in __tests__:
- func = self.__getattr__(name)
+ for name in self.__tests__:
+ func = getattr(self, name)
self._addfunc(func.func_name, func)
def _addfunc(self, name, func):
- functest = PasyTestFunc(self, func.func_name, func)
- self.add(functest)
+ functest = PasyTestFunc(func.func_name, func)
self._tests.append(functest)
def entry(self):
- self._iter = self._test_iterator
+ self._iter = self._test_iterator()
gobject.idle_add(self.idle_handler)
def idle_handler(self):
if step.state == PASY_TEST_WIN or self._cont == True:
gobject.idle_add(self.idle_handler)
elif step.state == PASY_TEST_FAIL and self._cont == False:
- self.fail()
- step.events.failed += finished_handler
+ self.fail("Sub test %s Failed" % step._name)
+ step.events.finished += finished_handler
step.run()
except StopIteration:
# No More tests, check for success or fail
def _test_iterator(self):
for test in self._tests:
yield test
+
+ def report(self):
+ if self._state == PASY_TEST_WIN:
+ header = "%s - PASSED" % (self._name,)
+ elif self._state == PASY_TEST_FAIL:
+ header = "%s - FAILED - %s" % (self._name, self.failMsg)
+ else:
+ header = "%s - INCOMPLETE" %s (self._name,)
+
+ step_messages = []
+ for test in self._tests:
+ step_messages.append(test.report())
+
+ step_report = "\n\t".join(step_messages)
+ return header + "\n\t" + step_report
-export PYTHONPATH=../../../
+export PYTHONPATH=../../
export TEST_DATA_DIRECTORY=../data
export TEST_ATSPI_LIBRARY=../../atk-adaptor/.libs/libspiatk.so
#!/usr/bin/python
+import gobject
import dbus
import sys
import time
from random import randint
-def runTestApp(module_name, dbus_name=None):
+from optparse import OptionParser
+from pasytest import PasyTest
+
+from dbus.mainloop.glib import DBusGMainLoop
+
+DBusGMainLoop(set_as_default=True)
+
+def run_test_app(module_name, dbus_name=None):
import os
from subprocess import Popen
raw_input(wait_message % (module_name, pop.pid))
def main(argv):
- testModule = argv[1]
+ parser = OptionParser()
+ parser.add_option("-l", "--library", dest="test_library")
+ parser.add_option("-m", "--module", dest="test_module")
+ parser.add_option("-n", "--name", dest="test_name")
+ (options, args) = parser.parse_args()
- # TODO Modify this function to add registryd as an option
bus = dbus.SessionBus()
name = "test.atspi.R" + str(randint(1, 1000))
- app = runTestApp(testModule, name)
- # Wait a little time for the app to start up
- # TODO connect this up to the apps start signal
+ app = run_test_app(options.test_library, name)
time.sleep(1)
+ print "Started test app on bus name %s" % (name,)
to = bus.get_object(name, "/org/codethink/atspi/test")
test = dbus.Interface(to, "org.codethink.atspi.test")
- # Run the test script here FIXME
+ # Run the test script here
+ module = __import__(options.test_module)
+ test_class = getattr(module, options.test_name)
+ test_object = test_class(bus, name)
+ test_object.run()
+
+ loop = gobject.MainLoop()
+
+ def finished_handler():
+ loop.quit()
+ print "\n" + test_object.report() + "\n"
+ test.finish()
+
+ test_object.events.finished += finished_handler
- # Inform the test app it can shut down.
- test.finish()
+ loop.run()
if __name__=="__main__":
sys.exit(main(sys.argv))