2008-05-28 Mark Doffman <mark.doffman@codethink.co.uk>
[platform/core/uifw/at-spi2-atk.git] / pyatspi / accessible.py
index 3766985..80a7589 100644 (file)
@@ -120,31 +120,44 @@ def _updateCache(event):
     return
 
 def _getAndCache(acc, value_name, get_method):
-    if _CACHE_LEVEL != constants.CACHE_PROPERTIES:
-      return get_method()
+  '''
+  If property caching is enabled, use the cached proprty, or get the 
+  property and cache it. If property caching is disabled, simply get the 
+  property.
+
+  @param value_name: The name of the value, like 'role' or 'description'.
+  @type value_name: string
+  @param get_method: Method used to get the property, should not have any 
+  arguments.
+  @type get_method: callable
+  @return: Value of property we are retrieving.
+  @rtype: object
+  '''
+  if _CACHE_LEVEL != constants.CACHE_PROPERTIES:
+    return get_method()
     
-    cache = _ACCESSIBLE_CACHE
-    h = hash(acc)
+  cache = _ACCESSIBLE_CACHE
+  h = hash(acc)
 
+  try:
+    pc = acc._property_cache
+  except AttributeError:
     try:
-      pc = acc._property_cache
-    except AttributeError:
-      try:
-        pc = cache[h]
-      except KeyError:
-        # no cached info for this accessible yet
-        pc = _PropertyCache()
-        cache[h] = pc
-      acc._property_cache = pc  
+      pc = cache[h]
+    except KeyError:
+      # no cached info for this accessible yet
+      pc = _PropertyCache()
+      cache[h] = pc
+    acc._property_cache = pc  
     
-    try:
-      value = getattr(pc, value_name)
-    except AttributeError:
-      # no cached property of this type
-      value = get_method()
-      setattr(pc, value_name, value)
+  try:
+    value = getattr(pc, value_name)
+  except AttributeError:
+    # no cached property of this type
+    value = get_method()
+    setattr(pc, value_name, value)
     
-    return value
+  return value
   
 
 def _makeQuery(interface):
@@ -590,9 +603,9 @@ class _AccessibleMixin(object):
 
   def getApplication(self):
     '''
-    Gets the most-parent accessible (the application) of this accessible. Tries 
-    using the getApplication method introduced in AT-SPI 1.7.0 first before 
-    resorting to traversing parent links.
+    Gets the most-parent accessible (the application) of this
+    accessible. Tries using the getApplication method introduced in
+    AT-SPI 1.7.0 first before resorting to traversing parent links.
     
     @warning: Cycles involving more than the previously traversed accessible 
       are not detected by this code.
@@ -600,18 +613,27 @@ class _AccessibleMixin(object):
     @rtype: Accessibility.Application
     '''
     try:
-      return self._mix_getApplication()
+      app = self._mix_getApplication()
     except AttributeError:
-      pass
+      app = None
+
+    # Some toolkits (e.g., Java) do not support getApplication yet and
+    # will return None as a result.
+    #
+    if app:
+      return app
+
+    # If we didn't find anything, traverse up the tree, making sure to
+    # attempt to turn the thing we found into an Application object.
+    #
     curr = self
     try:
       while curr.parent is not None and (not curr.parent == curr):
         curr = curr.parent
-      return curr
-    except Exception:
-      pass
-    # return None if the application isn't reachable for any reason
-    return None
+      curr.ref()
+      return curr._narrow(Accessibility.Application)
+    except:
+      return None
 
 class _RelationMixin(object):
   '''