[pyatspi2] Modifications to use the new leasing scheme.
- From: Mark Doffman <markdoffman src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [pyatspi2] Modifications to use the new leasing scheme.
- Date: Mon, 11 Jan 2010 14:02:41 +0000 (UTC)
commit 1b3c04a07e9180fa4b9352ac624e86f6a6425dd9
Author: Mark Doffman <mark doffman codethink co uk>
Date: Tue Jan 5 01:42:56 2010 -0800
Modifications to use the new leasing scheme.
The 'cache' of accessible objects is temporarily diabled.
pyatspi/accessible.py | 290 ++++++++++++++-------------------------
pyatspi/action.py | 2 +-
pyatspi/appevent.py | 134 +-----------------
pyatspi/cache.py | 188 ++++++--------------------
pyatspi/collection.py | 3 +-
pyatspi/component.py | 3 +-
pyatspi/desktop.py | 88 ++++---------
pyatspi/factory.py | 68 +++++-----
pyatspi/hyperlink.py | 3 +-
pyatspi/hypertext.py | 3 +-
pyatspi/registry.py | 44 +++----
pyatspi/relation.py | 8 +-
pyatspi/selection.py | 3 +-
pyatspi/table.py | 15 +--
tests/pyatspi/collectiontest.py | 2 +-
15 files changed, 245 insertions(+), 609 deletions(-)
---
diff --git a/pyatspi/accessible.py b/pyatspi/accessible.py
index 825b601..f430f9b 100644
--- a/pyatspi/accessible.py
+++ b/pyatspi/accessible.py
@@ -36,7 +36,6 @@ __all__ = [
"BoundingBox",
"BaseProxy",
"AccessibleMeta",
- "AccessibleImplCached",
"Accessible",
]
@@ -133,19 +132,18 @@ class BaseProxy (object):
__metaclass__ = AccessibleMeta
- def __init__(self, app_name, acc_path, acc_factory, dbus_interface, dbus_object):
+ def __init__(self, factory, name, path, dbus_object):
"""
Create a D-Bus Proxy for an ATSPI interface.
- 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.
- acc_factory - Factory used to create new accessible objects.
+ factory - Factory used to create new accessible objects.
+ name - D-Bus bus name of the application this accessible belongs to.
+ path - D-Bus object path of the server side accessible object.
dbus_object - The D-Bus proxy object used by the accessible for D-Bus method calls.
"""
- self._app_name = app_name
- self._acc_path = acc_path
- self._acc_factory = acc_factory
- self._dbus_interface = dbus_interface
+ self._acc_factory = factory
+ self._app_name = name
+ self._acc_path = path
self._dbus_object = dbus_object
self._pgetter = self._dbus_object.get_dbus_method("Get",
@@ -154,6 +152,10 @@ class BaseProxy (object):
dbus_interface="org.freedesktop.DBus.Properties")
@property
+ def acc_factory (self):
+ return self._acc_factory
+
+ @property
def app_name (self):
return self._app_name
@@ -162,14 +164,6 @@ class BaseProxy (object):
return self._acc_path
@property
- def acc_factory (self):
- return self._acc_factory
-
- @property
- def dbus_interface (self):
- return self._dbus_interface
-
- @property
def dbus_object (self):
return self._dbus_object
@@ -193,7 +187,6 @@ class BaseProxy (object):
method = self.dbus_object.get_dbus_method(*args, **kwargs)
def dbus_method_func(*iargs, **ikwargs):
-
# Need to throw an AccessibleObjectNoLongerExists exception
# on D-Bus error of the same type.
@@ -208,163 +201,17 @@ class BaseProxy (object):
#------------------------------------------------------------------------------
-class AccessibleImpl (BaseProxy):
-
- def getApplication(self):
- return self.acc_factory.create_application(self.app_name)
-
- def getAttributes(self):
- func = self.get_dbus_method("GetAttributes", dbus_interface=ATSPI_ACCESSIBLE)
- attr = func ()
- return [key + ':' + value for key, value in attr.iteritems()]
-
- def getChildAtIndex(self, index):
- count = Int32(self._pgetter(self.dbus_interface, "ChildCount"))
- if index >= count:
- raise IndexError
- func = self.get_dbus_method("GetChildAtIndex", dbus_interface=ATSPI_ACCESSIBLE)
- (name, path) = func (index)
- if (name == ""):
- name = self._app_name
- return self.acc_factory.create_accessible(name, path, ATSPI_ACCESSIBLE)
-
- def getLocalizedRoleName(self):
- func = self.get_dbus_method("GetLocalizedRoleName", dbus_interface=ATSPI_ACCESSIBLE)
- return func()
-
- def getRelationSet(self):
- func = self.get_dbus_method("GetRelationSet", dbus_interface=ATSPI_ACCESSIBLE)
- relation_set = func()
- return _marshal_relation_set(self.acc_factory, self._app_name, relation_set)
-
- def getIndexInParent(self):
- func = self.get_dbus_method("getIndexInParent", dbus_interface=ATSPI_ACCESSIBLE)
- return func()
-
- def getRole(self):
- func = self.get_dbus_method("GetRole", dbus_interface=ATSPI_ACCESSIBLE)
- return func()
-
- def getRoleName(self):
- func = self.get_dbus_method("GetRole", dbus_interface=ATSPI_ACCESSIBLE)
- return ROLE_NAMES[func()]
-
- def getState(self):
- func = self.get_dbus_method("GetState", dbus_interface=ATSPI_ACCESSIBLE)
- return _marshal_state_set(func())
-
- def get_childCount(self):
- return Int32(self._pgetter(self.dbus_interface, "ChildCount"))
-
- def get_description(self):
- return self._pgetter(self.dbus_interface, "Description")
-
- def get_name(self):
- return self._pgetter(self.dbus_interface, "Name")
-
- def get_parent(self):
- name, path = self._pgetter (self.dbus_interface, "Parent")
- return self.acc_factory.create_accessible(self._app_name,
- path,
- ATSPI_ACCESSIBLE)
-
- def get_interfaces (self):
- func = self.get_dbus_method("GetInterfaces", dbus_interface=ATSPI_ACCESSIBLE)
- return func()
-
-#------------------------------------------------------------------------------
-
-class AccessibleImplCached (AccessibleImpl):
-
- def __init__(self, cache, *args):
- BaseProxy.__init__(self, *args);
-
- self._relation_set = None
- self._cache = cache
-
- @property
- def cache (self):
- return self._cache
-
- @property
- def cached_data (self):
- return self.cache(self.app_name, self.acc_path)
-
- def getChildAtIndex(self, index):
- if (self.cached_data.state[0] & (1 << STATE_MANAGES_DESCENDANTS)):
- func = self.get_dbus_method("GetChildAtIndex", dbus_interface=ATSPI_ACCESSIBLE)
- (name, path) = func (index)
- if (name == ""):
- name = self._app_name
- return self.acc_factory.create_accessible(name, path, ATSPI_ACCESSIBLE)
- else:
- (name, path) = self.cached_data.children[index]
- if (name == ""):
- name = self._app_name
- return self.acc_factory.create_accessible(name, path, ATSPI_ACCESSIBLE)
-
- def getRelationSet(self):
- if self._relation_set is not None:
- return self._relation_set
- else:
- func = self.get_dbus_method("GetRelationSet", dbus_interface=ATSPI_ACCESSIBLE)
- relation_set = func()
- self._relation_set = _marshal_relation_set(self.acc_factory, self._app_name, relation_set)
- return self._relation_set
-
- def getIndexInParent(self):
- parent = self.get_parent()
- if parent == None:
- return -1
- for i in range(0, parent.childCount):
- child = parent.getChildAtIndex(i)
- if self == child:
- return i
- raise AccessibleObjectNoLongerExists("Child not found within parent")
-
- def getRole(self):
- return Role(self.cached_data.role)
-
- def getRoleName(self):
- return ROLE_NAMES[self.cached_data.role]
-
- def getState(self):
- return _marshal_state_set(self.cached_data.state)
-
- def get_childCount(self):
- if (self.cached_data.state[0] & (1 << STATE_MANAGES_DESCENDANTS)):
- return Int32(self._pgetter(self.dbus_interface, "ChildCount"))
- else:
- return len(self.cached_data.children)
-
- def get_description(self):
- return self.cached_data.description
-
- def get_name(self):
- return self.cached_data.name
-
- def get_parent(self):
- [name, path] = self.cached_data.parent
- if (name == ""):
- name = self._app_name
- return self.acc_factory.create_accessible(name,
- path,
- ATSPI_ACCESSIBLE)
-
- def get_interfaces (self):
- return self.cached_data.interfaces
-
-#------------------------------------------------------------------------------
-
class Accessible(BaseProxy):
"""
The interface which is implemented by all accessible objects.
"""
- def __init__(self, implementation, *args):
+ def __init__(self, cache, *args):
BaseProxy.__init__(self, *args);
- self._impl = implementation
+ self._cache = cache
+
+ self._relation_set = None
# Python object protocol --------------------------------------------------------
@@ -410,15 +257,29 @@ class Accessible(BaseProxy):
is not supported.
"""
if interface in self.interfaces or interface == "org.freedesktop.atspi.Collection":
- return self.acc_factory.create_accessible(self.app_name,
- self.acc_path,
- interface,
+ return self.acc_factory (self.app_name, self.acc_path, interface,
dbus_object=self.dbus_object)
else:
raise NotImplementedError(
"%s not supported by accessible object at path %s"
% (interface, self._acc_path))
+ # Cache data --------------------------------------------------------------------
+
+ @property
+ def cached (self):
+ if self._cache is not None:
+ return (self.app_name, self.acc_path) in self._cache
+ else:
+ return False
+
+ @property
+ def cached_data (self):
+ if self._cache is not None:
+ return self._cache[(self.app_name, self.acc_path)]
+ else:
+ raise KeyError ()
+
# Accessible interface ----------------------------------------------------------
def getApplication(self):
@@ -426,7 +287,12 @@ class Accessible(BaseProxy):
Get the containing Application for this object.
@return the Application instance to which this object belongs.
"""
- return self._impl.getApplication();
+ if self.cached:
+ return self.acc_factory (*self.cached_data.application)
+ else:
+ func = self.get_dbus_method("GetApplication", dbus_interface=ATSPI_ACCESSIBLE)
+ name, path = func ()
+ return self.acc_factory (name, path, ATSPI_ACCESSIBLE)
def getAttributes(self):
"""
@@ -459,7 +325,9 @@ class Accessible(BaseProxy):
currently defined for the object. An attribute set is a list of strings
with each string comprising an name-value pair format 'name:value'.
"""
- return self._impl.getAttributes();
+ func = self.get_dbus_method("GetAttributes", dbus_interface=ATSPI_ACCESSIBLE)
+ attr = func ()
+ return [key + ':' + value for key, value in attr.items()]
def getChildAtIndex(self, index):
"""
@@ -468,7 +336,16 @@ class Accessible(BaseProxy):
an in parameter indicating which child is requested (zero-indexed).
@return : the 'nth' Accessible child of this object.
"""
- return self._impl.getChildAtIndex(index);
+ if self.cached:
+ (name, path) = self.cached_data.children[index]
+ else:
+ count = Int32(self._pgetter(ATSPI_ACCESSIBLE, "ChildCount"))
+ if index >= count:
+ raise IndexError
+ func = self.get_dbus_method("GetChildAtIndex", dbus_interface=ATSPI_ACCESSIBLE)
+ (name, path) = func (index)
+
+ return self.acc_factory (name, path, ATSPI_ACCESSIBLE)
def getIndexInParent(self):
"""
@@ -476,7 +353,18 @@ class Accessible(BaseProxy):
@return : a long integer indicating this object's index in the
parent's list.
"""
- return self._impl.getIndexInParent()
+ if self.cached:
+ parent = self.get_parent()
+ if parent == None:
+ return -1
+ for i in range(0, parent.childCount):
+ child = parent.getChildAtIndex(i)
+ if self == child:
+ return i
+ raise AccessibleObjectNoLongerExists("Child not found within parent")
+ else:
+ func = self.get_dbus_method("GetIndexInParent", dbus_interface=ATSPI_ACCESSIBLE)
+ return func()
def getLocalizedRoleName(self):
"""
@@ -485,7 +373,8 @@ class Accessible(BaseProxy):
@return : a UTF-8 string indicating the type of UI role played
by this object.
"""
- return self._impl.getLocalizedRoleName()
+ func = self.get_dbus_method("GetLocalizedRoleName", dbus_interface=ATSPI_ACCESSIBLE)
+ return func()
def getRelationSet(self):
"""
@@ -493,7 +382,13 @@ class Accessible(BaseProxy):
objects.
@return : a RelationSet defining this object's relationships.
"""
- return self._impl.getRelationSet()
+ if self._relation_set is not None:
+ return self._relation_set
+ else:
+ func = self.get_dbus_method("GetRelationSet", dbus_interface=ATSPI_ACCESSIBLE)
+ relation_set = func()
+ self._relation_set = _marshal_relation_set(self.acc_factory, self._app_name, relation_set)
+ return self._relation_set
def getRole(self):
"""
@@ -501,7 +396,11 @@ class Accessible(BaseProxy):
@return : a Role indicating the type of UI role played by this
object.
"""
- return self._impl.getRole()
+ if self.cached:
+ return Role(self.cached_data.role)
+ else:
+ func = self.get_dbus_method("GetRole", dbus_interface=ATSPI_ACCESSIBLE)
+ return Role(func())
def getRoleName(self):
"""
@@ -509,7 +408,7 @@ class Accessible(BaseProxy):
@return : a UTF-8 string indicating the type of UI role played
by this object.
"""
- return self._impl.getRoleName()
+ return ROLE_NAMES[self.getRole()]
def getState(self):
"""
@@ -517,7 +416,11 @@ class Accessible(BaseProxy):
@return : a StateSet encapsulating the currently true states
of the object.
"""
- return self._impl.getState()
+ if self.cached:
+ return _marshal_state_set(cached_data.state)
+ else:
+ func = self.get_dbus_method("GetState", dbus_interface=ATSPI_ACCESSIBLE)
+ return _marshal_state_set(func())
def isEqual(self, other):
"""
@@ -534,7 +437,10 @@ class Accessible(BaseProxy):
return self.__eq__(other)
def get_childCount(self):
- return self._impl.get_childCount()
+ if self.cached:
+ return len(self.cached_data.children)
+ else:
+ return Int32(self._pgetter(ATSPI_ACCESSIBLE, "ChildCount"))
_childCountDoc = \
"""
childCount: the number of children contained by this object.
@@ -544,7 +450,10 @@ class Accessible(BaseProxy):
getChildCount = get_childCount
def get_description(self):
- return self._impl.get_description()
+ if self.cached:
+ return self.cached_data.description
+ else:
+ return self._pgetter(ATSPI_ACCESSIBLE, "Description")
_descriptionDoc = \
"""
a string describing the object in more detail than name.
@@ -552,7 +461,10 @@ class Accessible(BaseProxy):
description = property(fget=get_description, doc=_descriptionDoc)
def get_name(self):
- return self._impl.get_name()
+ if self.cached:
+ return self.cached_data.name
+ else:
+ return self._pgetter(ATSPI_ACCESSIBLE, "Name")
_nameDoc = \
"""
a (short) string representing the object's name.
@@ -560,7 +472,11 @@ class Accessible(BaseProxy):
name = property(fget=get_name, doc=_nameDoc)
def get_parent(self):
- return self._impl.get_parent()
+ if self.cached:
+ name, path = self.cached_data.parent
+ else:
+ name, path = self._pgetter (ATSPI_ACCESSIBLE, "Parent")
+ return self.acc_factory (name, path, ATSPI_ACCESSIBLE)
_parentDoc = \
"""
an Accessible object which is this object's containing object.
@@ -568,7 +484,11 @@ class Accessible(BaseProxy):
parent = property(fget=get_parent, doc=_parentDoc)
def get_interfaces(self):
- return self._impl.get_interfaces()
+ if self.cached:
+ return self.cached_data.interfaces
+ else:
+ func = self.get_dbus_method("GetInterfaces", dbus_interface=ATSPI_ACCESSIBLE)
+ return func()
_interfacesDoc = \
"""
D-Bus interfaces supported by this accessible object.
diff --git a/pyatspi/action.py b/pyatspi/action.py
index f0359df..466631e 100644
--- a/pyatspi/action.py
+++ b/pyatspi/action.py
@@ -96,7 +96,7 @@ class Action(Accessible):
return func(index)
def get_nActions(self):
- return dbus.Int32(self._pgetter(self._dbus_interface, "NActions"))
+ return dbus.Int32(self._pgetter(ATSPI_ACTION, "NActions"))
_nActionsDoc = \
"""
nActions: a long containing the number of actions this object
diff --git a/pyatspi/appevent.py b/pyatspi/appevent.py
index 47df10f..3cfb14a 100644
--- a/pyatspi/appevent.py
+++ b/pyatspi/appevent.py
@@ -18,6 +18,7 @@ from accessible import BoundingBox
from exceptions import *
from busutils import AccessibilityBus
+from factory import AccessibleFactory
__all__ = [
"Event",
@@ -275,9 +276,9 @@ class Event(object):
def source(self):
if not self._source:
try:
- self._source = self._acc_factory.create_accessible(self._source_application,
- self._source_path,
- interfaces.ATSPI_ACCESSIBLE)
+ self._source = self._acc_factory (self._source_application,
+ self._source_path,
+ interfaces.ATSPI_ACCESSIBLE)
except AccessibleObjectNoLongerExists:
pass
return self._source
@@ -308,119 +309,14 @@ class _ApplicationEventRegister (object):
def __init__ (self):
self._bus = AccessibilityBus ()
- self._cache = None
- self._factory = None
- self._event_listeners = {}
-
- # All of this special casing is for the 'faked'
- # events caused by cache updates.
+ self._factory = AccessibleFactory ()
- self._name_type = EventType("object:property-change:name")
- self._name_listeners = {}
- self._description_type = EventType("object:property-change:description")
- self._description_listeners = {}
- self._parent_type = EventType("object:property-change:parent")
- self._parent_listeners = {}
- self._children_changed_type = EventType("object:children-changed")
- self._children_changed_listeners = {}
+ self._event_listeners = {}
def _callClients(self, register, event):
for client in register.keys():
client(event)
- def setCache (self, cache):
- self._cache = cache
-
- def setFactory (self, factory):
- self._factory = factory
-
- def notifyNameChange(self, name, path, acc_name):
- event = Event(("accessible-name", 0, 0, acc_name),
- self._factory,
- path,
- name,
- "org.freedesktop.atspi.Event.Object",
- "property-change")
-
- self._callClients(self._name_listeners, event)
-
- def notifyDescriptionChange(self, name, path, acc_desc):
- event = Event(("accessible-description", 0, 0, acc_desc),
- self._factory,
- path,
- name,
- "org.freedesktop.atspi.Event.Object",
- "property-change")
-
- self._callClients(self._description_listeners, event)
-
- def notifyParentChange(self, name, path):
- event = Event(("accessible-parent", 0, 0, ""),
- self._factory,
- path,
- name,
- "org.freedesktop.atspi.Event.Object",
- "property-change")
-
- self._callClients(self._parent_listeners, event)
-
- def notifyChildrenChange(self, name, path, added):
- if added:
- detail = "add"
- else:
- detail = "remove"
- event = Event((detail, 0, 0, ""),
- self._factory,
- path,
- name,
- "org.freedesktop.atspi.Event.Object",
- "children-changed")
-
- self._callClients(self._children_changed_listeners, event)
-
- def _registerFake(self, type, register, client, *names):
- """
- Registers a client from a register of clients
- for 'Fake' events emitted by the cache.
- """
- try:
- registered = register[client]
- except KeyError:
- registered = []
- register[client] = registered
-
- for name in names:
- new_type = EventType(name)
- if new_type.is_subtype(type):
- registered.append(new_type.name)
-
- if registered == []:
- del(register[client])
-
- def _deregisterFake(self, type, register, client, *names):
- """
- Deregisters a client from a register of clients
- for 'Fake' events emitted by the cache.
- """
- try:
- registered = register[client]
- except KeyError:
- return True
-
- for name in names:
- remove_type = EventType(name)
-
- copy = registered[:]
- for i in range(0, len(copy)):
- type_name = copy[i]
- registered_type = EventType(type_name)
-
- if remove_type.is_subtype(registered_type):
- del(registered[i])
-
- if registered == []:
- del(register[client])
-
def registerEventListener(self, client, *names):
try:
registered = self._event_listeners[client]
@@ -476,24 +372,6 @@ class _ApplicationEventRegister (object):
class _NullApplicationEventRegister (object):
- def setCache (self, cache):
- pass
-
- def setFactory (self, factory):
- pass
-
- def notifyNameChange(self, name, path, acc_name):
- pass
-
- def notifyDescriptionChange(self, name, path, acc_desc):
- pass
-
- def notifyParentChange(self, name, path):
- pass
-
- def notifyChildrenChange(self, name, path, added):
- pass
-
def registerEventListener(self, client, *names):
pass
diff --git a/pyatspi/cache.py b/pyatspi/cache.py
index 99de6f9..49ea2a0 100644
--- a/pyatspi/cache.py
+++ b/pyatspi/cache.py
@@ -23,50 +23,11 @@ from busutils import AccessibilityBus
__all__ = [
"ApplicationCache",
- "TestApplicationCache",
"AccessibleCache"
]
#------------------------------------------------------------------------------
-class TestApplicationCache(object):
-
- """
- Test application store, accesses a single application.
-
- The store object acts as a central class for creating accessible objects.
- It interfaces with the ATSPI registry to keep account of all accessible
- applications. It contains the accessible cache objects from each application.
-
- @registry: Each accessible cache object must have a reference to the registry
- object to send update events.
-
- @connection: D-Bus connection used to access applications.
-
- @bus_name: The test store only accesses one accessible application, this is its
- D-Bus path.
- """
-
- def __init__(self, event_dispatcher, connection, bus_name):
- self._application_list = [bus_name]
- self._application_cache = {bus_name:AccessibleCache(event_dispatcher, connection, bus_name)}
-
- @property
- def application_list (self):
- return self._application_list
-
- def get_app_root (self, app_name):
- return self._application_cache[app_name].root
-
- def __call__ (self, app_name, acc_path):
- """
- Returns the cache tuple for the given application and accessible
- object path. Throws an IndexError if the cache data is not found.
- """
- return self._application_cache[app_name][acc_path]
-
-#------------------------------------------------------------------------------
-
class ApplicationCache(object):
"""
Keeps a store of the caches for all accessible applications.
@@ -83,7 +44,6 @@ class ApplicationCache(object):
def __init__(self, event_dispatcher):
self._connection = AccessibilityBus ()
- self._event_dispatcher = event_dispatcher
self._factory = None
self._application_list = []
@@ -115,16 +75,6 @@ class ApplicationCache(object):
self._application_cache[bus_name] = AccessibleCache(self._event_dispatcher,
bus_name)
- def set_factory (self, factory):
- self._factory = factory
-
- @property
- def application_list (self):
- return self._application_list
-
- def get_app_root (self, app_name):
- return self._application_cache[app_name].root
-
def __call__ (self, app_name, acc_path):
"""
Returns the cache tuple for the given application and accessible
@@ -132,41 +82,35 @@ class ApplicationCache(object):
"""
return self._application_cache[app_name][acc_path]
+ def __getitem__ (self, key):
+ try:
+ name, path = key
+ return self._application_cache[app_name][key]
+ except Exception:
+ raise KeyError ()
+
+ def __contains__ (self, key):
+ try:
+ name, path = key
+ return key in self._application_cache[app_name]
+ except Exception:
+ return False
+
def _update_handler (self, update_type, bus_name):
if update_type == ApplicationCache._APPLICATIONS_ADD:
- #TODO Check that app does not already exist
self._application_list.append(bus_name)
self._application_cache[bus_name] = AccessibleCache(self._event_dispatcher,
bus_name)
- self._event_dispatcher.notifyChildrenChange(ATSPI_REGISTRY_NAME,
- ATSPI_DESKTOP_PATH,
- True)
-
elif update_type == ApplicationCache._APPLICATIONS_REMOVE:
- #TODO Fail safely if app does not exist
self._application_list.remove(bus_name)
del(self._application_cache[bus_name])
- self._event_dispatcher.notifyChildrenChange(ATSPI_REGISTRY_NAME,
- ATSPI_DESKTOP_PATH,
- False)
-
- def _refresh(self):
- new = self._app_register.getApplications()
- removed = [item for item in self._application_list if item not in new]
- added = [item for item in new if item not in self._application_list]
- for item in added:
- self._update_handler (self._APPLICATIONS_ADD, item)
- for item in removed:
- self._update_handler (self._APPLICATIONS_REMOVE, item)
-
- for item in self._application_cache.values():
- item._refresh()
#------------------------------------------------------------------------------
class _CacheData(object):
__slots__ = [
'path',
+ 'application',
'parent',
'interfaces',
'children',
@@ -181,6 +125,7 @@ class _CacheData(object):
def __str__(self):
return (str(self.path) + '\n' +
+ str(self.application) + '\n' +
str(self.parent) + '\n' +
str(self.children) + '\n' +
str(self.interfaces) + '\n' +
@@ -191,6 +136,7 @@ class _CacheData(object):
def _update(self, data):
(self.path,
+ self.application,
self.parent,
self.children,
self.interfaces,
@@ -228,9 +174,9 @@ class AccessibleCache(object):
busName - Name of DBus connection where cache interface resides.
"""
- _PATH = '/org/freedesktop/atspi/tree'
- _INTERFACE = 'org.freedesktop.atspi.Tree'
- _GET_METHOD = 'GetTree'
+ _PATH = '/org/at_spi/cache'
+ _INTERFACE = 'org.freedesktop.atspi.Cache'
+ _GET_METHOD = 'GetItems'
_UPDATE_SIGNAL = 'UpdateAccessible'
_REMOVE_SIGNAL = 'RemoveAccessible'
@@ -256,87 +202,37 @@ class AccessibleCache(object):
self._updateMatch = self._tree_itf.connect_to_signal(self._UPDATE_SIGNAL, self._update_single)
self._removeMatch = self._tree_itf.connect_to_signal(self._REMOVE_SIGNAL, self._remove_object)
- self._root = self._tree_itf.GetRoot()
-
- def set_factory (self, factory):
- pass
-
- @property
- def application_list (self):
- return [self._bus_name]
-
- def get_app_root (self, app_name):
- if app_name != self._bus_name:
- raise KeyError
- return self._root
-
- def __call__ (self, app_name, acc_path):
- """
- Returns the cache tuple for the given application and accessible
- object path. Throws an IndexError if the cache data is not found.
- """
- if app_name != self._bus_name:
- raise KeyError
- return self[acc_path]
-
def __getitem__(self, key):
- return self._objects[key]
+ try:
+ name, path = key
+ if name != self_bus_name:
+ raise KeyError ()
+ return self._objects[path]
+ except Exception:
+ raise KeyError ()
def __contains__(self, key):
- return key in self._objects
-
- def _dispatch_event(self, olddata, newdata):
- if olddata.name != newdata.name:
- self._event_dispatcher.notifyNameChange(self._bus_name, newdata.path, newdata.name)
-
- if olddata.description != newdata.description:
- self._event_dispatcher.notifyDescriptionChange(self._bus_name, newdata.path, newdata.description)
-
- if olddata.parent != newdata.parent:
- self._event_dispatcher.notifyParentChange(self._bus_name, newdata.path)
-
- removed, added = _list_items_added_removed (olddata.children, newdata.children)
-
- if added:
- self._event_dispatcher.notifyChildrenChange(self._bus_name, newdata.path, True)
-
- if removed:
- self._event_dispatcher.notifyChildrenChange(self._bus_name, newdata.path, False)
-
- # TODO This should be the other way around. Single is more common than many.
- def _update_single(self, object):
- self._update_objects ([object])
-
- def _update_objects(self, objects):
- cache_update_objects = []
+ try:
+ name, path = key
+ if name != self_bus_name:
+ return False
+ return path in self._objects
+ except Exception:
+ return False
+
+ def _update_object (self, object):
+ #First element is the object path.
+ path = data[0]
+ self._objects[path] = _CacheData (data)
+
+ def _update_objects (self, objects):
for data in objects:
- #First element is the object path.
- path = data[0]
- if path in self._objects:
- olddata = self._objects[path]
- newdata = _CacheData(data)
- cache_update_objects.append((olddata, newdata))
- self._objects[path] = newdata
- else:
- self._objects[path] = _CacheData(data)
- for old, new in cache_update_objects:
- self._dispatch_event(old, new)
+ self._update_object (data)
def _remove_object(self, path):
- # TODO I'm squashing a possible error here
- # I've seen things appear to be deleted twice
- # which needs investigation
try:
del(self._objects[path])
except KeyError:
pass
- def _refresh(self):
- get_method = self._tree_itf.get_dbus_method(self._GET_METHOD)
- self._update_objects(get_method())
-
- @property
- def root(self):
- return self._root
-
#END----------------------------------------------------------------------------
diff --git a/pyatspi/collection.py b/pyatspi/collection.py
index ffaa87c..0a4efff 100644
--- a/pyatspi/collection.py
+++ b/pyatspi/collection.py
@@ -102,8 +102,7 @@ class Collection(Accessible):
(name, path) = ret[i]
if (name == ""):
name = self._app_name
- ret[i] = self.acc_factory.create_accessible(name, path,
- ATSPI_ACCESSIBLE)
+ ret[i] = self.acc_factory (name, path, ATSPI_ACCESSIBLE)
return ret;
def getMatches(self, rule, sortby, count, traverse):
diff --git a/pyatspi/component.py b/pyatspi/component.py
index 10c23b0..7df6b05 100644
--- a/pyatspi/component.py
+++ b/pyatspi/component.py
@@ -103,8 +103,7 @@ class Component(Accessible):
(name, path) = func(x, y, UInt32(coord_type))
if (name == ""):
name = self._app_name
- return self.acc_factory.create_accessible(name, path,
- interfaces.ATSPI_ACCESSIBLE)
+ return self.acc_factory (name, path, interfaces.ATSPI_ACCESSIBLE)
def getAlpha(self):
"""
diff --git a/pyatspi/desktop.py b/pyatspi/desktop.py
index c901955..80e80ca 100644
--- a/pyatspi/desktop.py
+++ b/pyatspi/desktop.py
@@ -1,4 +1,4 @@
-#Copyright (C) 2008 Codethink Ltd
+#Copyright (C) 2008, 2009, 2010 Codethink Ltd
#This library is free software; you can redistribute it and/or
#modify it under the terms of the GNU Lesser General Public
@@ -23,10 +23,10 @@ from component import LAYER_WIDGET
import dbus
from busutils import AccessibilityBus
+from factory import AccessibleFactory
__all__ = [
"Desktop",
- "CachedDesktop",
"TestDesktop",
]
@@ -138,11 +138,15 @@ class BaseDesktop (object):
The interface which is implemented by all accessible objects.
"""
+ _CACHE_PATH = '/org/at_spi/cache'
+ _CACHE_INTERFACE = 'org.freedesktop.atspi.Cache'
+
__metaclass__ = AccessibleMeta
- def __init__ (self, acc_factory):
- self._acc_factory = acc_factory
- self._acc_factory.set_desktop (self)
+ def __init__(self, cache):
+ self._cache = cache
+ self._connection = AccessibilityBus ()
+ self._acc_factory = AccessibleFactory ()
@property
def app_name (self):
@@ -234,6 +238,7 @@ class BaseDesktop (object):
# Accessible interface ----------------------------------------------------------
+
def getApplication(self):
"""
Get the containing Application for this object.
@@ -410,29 +415,18 @@ class TestDesktop (BaseDesktop):
Does not use the registry daemon.
"""
- _TREE_PATH = '/org/freedesktop/atspi/tree'
- _TREE_INTERFACE = 'org.freedesktop.atspi.Tree'
+ def __init__(self, app_name, *args):
+ BaseDesktop.__init__(self, *args)
- def __init__(self, app_name, factory):
- BaseDesktop.__init__(self, factory);
- obj = AccessibilityBus().get_object (app_name,
- self._TREE_PATH)
- tree = dbus.Interface (obj, self._TREE_INTERFACE)
+ obj = self._connection.get_object (app_name, self._CACHE_PATH)
+ cache = dbus.Interface (obj, self._CACHE_INTERFACE)
self._single_app = app_name
- self._root = tree.GetRoot ()
+ self._root = cache.GetRoot ()
def getChildAtIndex(self, index):
- #TODO - Check index
- return self._acc_factory.create_accessible (self._single_app,
- self._root,
- interfaces.ATSPI_APPLICATION)
-
- def create_application (self, app_name):
- #TODO - Check name
- return self._acc_factory.create_accessible (self._single_app,
- self._root,
- interfaces.ATSPI_APPLICATION)
+ name, path = self._root
+ return self.acc_factory (name, path, interfaces.ATSPI_APPLICATION)
def get_childCount(self):
return 1
@@ -446,9 +440,6 @@ class Desktop (BaseDesktop):
Does use the registry daemon.
"""
- _TREE_PATH = '/org/freedesktop/atspi/tree'
- _TREE_INTERFACE = 'org.freedesktop.atspi.Tree'
-
def __init__(self, *args):
BaseDesktop.__init__(self, *args);
@@ -457,49 +448,18 @@ class Desktop (BaseDesktop):
interfaces.ATSPI_REGISTRY_PATH)
self._app_register = dbus.Interface(obj, interfaces.ATSPI_REGISTRY_INTERFACE)
- def create_application (self, app_name):
- obj = self._connection.get_object (app_name,
- self._TREE_PATH)
- tree = dbus.Interface (obj, self._TREE_INTERFACE)
- root = tree.GetRoot ()
-
- return self.acc_factory.create_accessible (app_name,
- root,
- interfaces.ATSPI_APPLICATION)
-
def getChildAtIndex(self, index):
applications = self._app_register.GetApplications()
- return self.acc_factory.create_application(applications[index])
-
- def get_childCount(self):
- applications = self._app_register.GetApplications()
- return len (applications)
-
-#------------------------------------------------------------------------------
-
-class CachedDesktop (BaseDesktop):
- """
- Uses the cache to manage applications.
- """
- def __init__(self, cache, *args):
- BaseDesktop.__init__(self, *args);
- self.cache = cache
+ app_name = applications[index]
+ obj = self._connection.get_object (app_name, self._CACHE_PATH)
+ cache = dbus.Interface (obj, self._CACHE_INTERFACE)
+ name, path = cache.GetRoot ()
- def create_application (self, app_name):
- if app_name == interfaces.ATSPI_REGISTRY_NAME:
- acc_path = interfaces.ATSPI_DESKTOP_PATH
- else:
- acc_path = self.cache.get_app_root(app_name)
-
- return self.acc_factory.create_accessible (app_name,
- acc_path,
- interfaces.ATSPI_APPLICATION)
-
- def getChildAtIndex(self, index):
- return self.create_application (self.cache.application_list[index])
+ return self.acc_factory (name, path, interfaces.ATSPI_APPLICATION)
def get_childCount(self):
- return len(self.cache.application_list)
+ applications = self._app_register.GetApplications()
+ return len (applications)
#END----------------------------------------------------------------------------
diff --git a/pyatspi/factory.py b/pyatspi/factory.py
index a2d266c..ea60d1e 100644
--- a/pyatspi/factory.py
+++ b/pyatspi/factory.py
@@ -19,7 +19,6 @@ from action import *
from application import *
from collection import *
from component import *
-from desktop import *
from document import *
from editabletext import *
from hyperlink import *
@@ -31,14 +30,17 @@ from text import *
from table import *
from value import *
-from accessible import AccessibleImpl, AccessibleImplCached
+import dbus
+
from busutils import AccessibilityBus
-import dbus
+__all__ = [
+ "AccessibleFactory"
+ ]
#------------------------------------------------------------------------------
-class Factory (object):
+class _AccessibleFactory (object):
def __init__ (self):
@@ -62,10 +64,16 @@ class Factory (object):
interfaces.ATSPI_VALUE:Value,
}
- def set_desktop (self, desktop):
- self._desktop = desktop
+ self._cache = None
+ self._desktop = None
+
+ def set_cache (self, cache):
+ self._cache = cache
- def create_accessible (self, name, path, itf, dbus_object=None):
+ def set_desktop (self, desktop):
+ self._desktop = desktop
+
+ def __call__ (self, name, path, itf, dbus_object=None):
if dbus_object == None:
dbus_object = self._connection.get_object (name, path)
@@ -73,33 +81,23 @@ class Factory (object):
if name == interfaces.ATSPI_REGISTRY_NAME or path == interfaces.ATSPI_DESKTOP_PATH:
return self._desktop
else:
- impl = self._get_accessible_impl (name, path, dbus_object)
- return self._interfaces[itf] (impl, name, path, self, itf, dbus_object)
-
- def create_application (self, name):
- return self._desktop.create_application (name)
-
-#------------------------------------------------------------------------------
-
-class CachedAccessibleFactory (Factory):
-
- def __init__ (self, cache, *args):
- Factory.__init__(self, *args)
- self._cache = cache
-
- def _get_accessible_impl (self, name, path, dbus_object):
- return AccessibleImplCached (self._cache,
- name,
- path,
- self,
- interfaces.ATSPI_ACCESSIBLE,
- dbus_object)
-
-#------------------------------------------------------------------------------
-
-class AccessibleFactory (Factory):
-
- def _get_accessible_impl (self, name, path, dbus_object):
- return AccessibleImpl (name, path, self, interfaces.ATSPI_ACCESSIBLE, dbus_object)
+ return self._interfaces[itf] (self._cache, self, name, path, dbus_object)
+
+class AccessibleFactory (_AccessibleFactory):
+ """
+ Shared instance of the D-Bus bus used for accessibility.
+ """
+
+ _shared_instance = None
+
+ def __new__ (cls):
+ if AccessibleFactory._shared_instance:
+ return AccessibleFactory._shared_instance
+ else:
+ AccessibleFactory._shared_instance = _AccessibleFactory.__new__ (cls)
+ return AccessibleFactory._shared_instance
+
+ def __init__ (self):
+ _AccessibleFactory.__init__ (self)
#END----------------------------------------------------------------------------
diff --git a/pyatspi/hyperlink.py b/pyatspi/hyperlink.py
index a4151e2..23f8516 100644
--- a/pyatspi/hyperlink.py
+++ b/pyatspi/hyperlink.py
@@ -50,8 +50,7 @@ class Hyperlink(Accessible):
ith anchor can be accessed.
"""
func = self.get_dbus_method("getObject", dbus_interface=ATSPI_HYPERLINK)
- return self.acc_factory.create_accessible(self._app_name, func(index),
- ATSPI_ACCESSIBLE)
+ return self.acc_factory (self._app_name, func(index), ATSPI_ACCESSIBLE)
def getURI(self, index):
"""
diff --git a/pyatspi/hypertext.py b/pyatspi/hypertext.py
index 226f42d..ace75c5 100644
--- a/pyatspi/hypertext.py
+++ b/pyatspi/hypertext.py
@@ -39,8 +39,7 @@ class Hypertext(Accessible):
@return the Hyperlink in this Hypertext object.
"""
func = self.get_dbus_method("getLink", dbus_interface=ATSPI_HYPERTEXT)
- return self.acc_factory.create_accessible(self._app_name, func(index),
- interfaces.ATSPI_HYPERLINK)
+ return self.acc_factory (self._app_name, func(index), interfaces.ATSPI_HYPERLINK)
def getLinkIndex(self, character_index):
"""
diff --git a/pyatspi/registry.py b/pyatspi/registry.py
index e4bdf39..0042203 100644
--- a/pyatspi/registry.py
+++ b/pyatspi/registry.py
@@ -24,7 +24,7 @@
import dbus
import os as _os
-from factory import CachedAccessibleFactory, AccessibleFactory
+from factory import AccessibleFactory
from appevent import _ApplicationEventRegister, _NullApplicationEventRegister
from deviceevent import _DeviceEventRegister, _NullDeviceEventRegister
from desktop import *
@@ -84,7 +84,7 @@ class Registry(object):
self.device_event_register = None
self.app_event_register = None
self.desktop = None
- self.accessible_factory = None
+
self.main_loop = gobject.MainLoop()
def __call__(self):
@@ -114,6 +114,9 @@ class Registry(object):
@param app_name: D-Bus name of the application to connect to when not using the registry daemon.
"""
+
+ factory = AccessibleFactory()
+
# Set up the device event controllers
if app_name:
devreg = _NullDeviceEventRegister()
@@ -122,29 +125,23 @@ class Registry(object):
devreg = _DeviceEventRegister()
appreg = _ApplicationEventRegister()
- # Set up the cache / desktop and accesible factories.
- if main_loop_type == MAIN_LOOP_GLIB:
- if app_name:
- cache = AccessibleCache(appreg, app_name)
- else:
- cache = ApplicationCache(appreg)
-
- appreg.setCache (cache)
- factory = CachedAccessibleFactory (cache)
- cache.set_factory(factory)
- desktop = CachedDesktop (cache, factory)
-
- elif main_loop_type == MAIN_LOOP_NONE:
- factory = AccessibleFactory()
- if app_name:
- desktop = TestDesktop (app_name, factory)
- else:
- desktop = Desktop (factory)
+ if app_name:
+ desktop = TestDesktop (app_name, factory)
else:
- raise Exception ("Unknown main loop specified")
-
- appreg.setFactory (factory)
+ desktop = Desktop (factory)
+
+ # Set up the cache
+ cache = None
+
+ #if main_loop_type == MAIN_LOOP_GLIB:
+ # if app_name:
+ # cache = AccessibleCache(app_name)
+ # else:
+ # cache = ApplicationCache()
+
+ factory.set_cache (cache)
+ factory.set_desktop (desktop)
# Create the registry object
self.has_implementations = True
@@ -152,7 +149,6 @@ class Registry(object):
self.device_event_register = devreg
self.app_event_register = appreg
self.desktop = desktop
- self.accessible_factory = factory
def _set_default_registry (self):
self._set_registry (MAIN_LOOP_GLIB)
diff --git a/pyatspi/relation.py b/pyatspi/relation.py
index 23b1235..98c3234 100644
--- a/pyatspi/relation.py
+++ b/pyatspi/relation.py
@@ -101,11 +101,11 @@ class Relation(object):
a "one-to-many" correspondance.
"""
- def __init__(self, cache, app_name, type, objects):
+ def __init__(self, factory, app_name, type, objects):
self._type = type
self._objects = objects
- self._cache = cache
+ self._factory = factory
self._app_name = app_name
def getNTargets(self):
@@ -135,8 +135,6 @@ class Relation(object):
(name, path) = self._objects[index]
if (name == ""):
name = self._app_name
- return self._cache.create_accessible(name,
- path,
- interfaces.ATSPI_ACCESSIBLE)
+ return self._factory (name, path, interfaces.ATSPI_ACCESSIBLE)
#END----------------------------------------------------------------------------
diff --git a/pyatspi/selection.py b/pyatspi/selection.py
index a3e4a00..832800c 100644
--- a/pyatspi/selection.py
+++ b/pyatspi/selection.py
@@ -85,8 +85,7 @@ class Selection(Accessible):
(name, path) = func (index)
if (name == ""):
name = self._app_name
- return self.acc_factory.create_accessible(name, path,
- ATSPI_ACCESSIBLE)
+ return self.acc_factory (name, path, ATSPI_ACCESSIBLE)
def isChildSelected(self, index):
"""
diff --git a/pyatspi/table.py b/pyatspi/table.py
index b7b68b9..eb5aa13 100644
--- a/pyatspi/table.py
+++ b/pyatspi/table.py
@@ -75,8 +75,7 @@ class Table(Accessible):
(name, path) = func(row, column)
if (name == ""):
name = self._app_name
- return self.acc_factory.create_accessible(name, path,
- ATSPI_ACCESSIBLE)
+ return self.acc_factory (name, path, ATSPI_ACCESSIBLE)
def getColumnAtIndex(self, index):
"""
@@ -128,8 +127,7 @@ class Table(Accessible):
if available.
"""
func = self.get_dbus_method("GetColumnHeader", dbus_interface=ATSPI_TABLE)
- return self.acc_factory.create_accessible(self._app_name, func(index),
- ATSPI_ACCESSIBLE)
+ return self.acc_factory (self._app_name, func(index), ATSPI_ACCESSIBLE)
def getIndexAt(self, row, column):
"""
@@ -236,8 +234,7 @@ class Table(Accessible):
(name, path) = func (row)
if (name == ""):
name = self._app_name
- return self.acc_factory.create_accessible(name, path,
- ATSPI_ACCESSIBLE)
+ return self.acc_factory (name, path, ATSPI_ACCESSIBLE)
def getSelectedColumns(self):
"""
@@ -318,8 +315,7 @@ class Table(Accessible):
(name, path) = self._pgetter(self._dbus_interface, "Caption")
if (name == ""):
name = self._app_name
- return self.acc_factory.create_accessible(name, path,
- ATSPI_ACCESSIBLE)
+ return self.acc_factory (name, path, ATSPI_ACCESSIBLE)
_captionDoc = \
"""
An Accessible which represents of a caption for a Table.
@@ -369,8 +365,7 @@ class Table(Accessible):
(name, path) = self._pgetter(self._dbus_interface, "Summary")
if (name == ""):
name = self._app_name
- return self.acc_factory.create_accessible(name, path,
- ATSPI_ACCESSIBLE)
+ return self.acc_factory (name, path, ATSPI_ACCESSIBLE)
_summaryDoc = \
"""
An accessible object which summarizes the contents of a Table.
diff --git a/tests/pyatspi/collectiontest.py b/tests/pyatspi/collectiontest.py
index d4e8403..87341c0 100644
--- a/tests/pyatspi/collectiontest.py
+++ b/tests/pyatspi/collectiontest.py
@@ -37,7 +37,7 @@ class AccessibleTest(_PasyTest):
]
def __init__(self, bus, path):
- _PasyTest.__init__(self, "Accessible", False)
+ _PasyTest.__init__(self, "Collection", False)
self._bus = bus
self._path = path
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]