2008-08-25 Mark Doffman <mark.doffman@codethink.co.uk>
authorMark Doffman <mdoff@silver-wind.(none)>
Mon, 25 Aug 2008 10:25:25 +0000 (11:25 +0100)
committerMark Doffman <mdoff@silver-wind.(none)>
Mon, 25 Aug 2008 10:25:25 +0000 (11:25 +0100)
* pyatspi/relation.py
Fix the generation of target objects.

* pyatspi/accessible.py
Fix demarshalling of relation objects.

* pyatspi/base.py
Add a string representation of the accessible class.

* tests/pyatspi/realtiontest.py
Add a relation unit test.

* atk-adaptor/accessible.c
Fix bug in marshalling relation object.

atk-adaptor/accessible.c
pyatspi/accessible.py
pyatspi/base.py
pyatspi/relation.py
tests/apps/Makefile.am
tests/apps/relation-app.c [new file with mode: 0644]
tests/pyatspi/Makefile.am
tests/pyatspi/relationtest.py [new file with mode: 0644]

index d7970fe..8154e4c 100644 (file)
@@ -245,7 +245,7 @@ impl_getRelationSet (DBusConnection * bus, DBusMessage * message,
       char *path;
       if (!obj) continue;
       path = spi_dbus_get_path (obj);
-      dbus_message_iter_append (&iter_targets, DBUS_TYPE_OBJECT_PATH, &path);
+      dbus_message_iter_append_basic (&iter_targets, DBUS_TYPE_OBJECT_PATH, &path);
     }
     dbus_message_iter_close_container (&iter_struct, &iter_targets);
     dbus_message_iter_close_container (&iter_array, &iter_struct);
index 093ac03..ea5e049 100644 (file)
@@ -186,7 +186,7 @@ class Accessible(BaseProxy):
         """
         func = self.get_dbus_method("getRelationSet")
         relation_set = func()
-        return _marshal_relation_set(self._cache, self._dbus_object, self._app_name, relation_set)
+        return _marshal_relation_set(self._cache, self._app_name, relation_set)
     
     def getRole(self):
         """
index e8ed466..4fabeec 100644 (file)
@@ -109,6 +109,12 @@ class BaseProxy(Interface):
        def __getattr__(self, attr):
                raise AttributeError("\'%s\' has no attribute \'%s\'" % (self.__class__.__name__, attr))
 
+       def __str__(self):
+               try:
+                       return '[%s | %s]' % (self.getRoleName(), self.name)
+               except Exception:
+                       return '[DEAD]'
+
        def get_dbus_method(self, *args, **kwargs):
                method =  Interface.get_dbus_method(self, *args, **kwargs)
 
index 86e3a76..de91e25 100644 (file)
@@ -99,7 +99,7 @@ RELATION_VALUE_TO_NAME = dict(((value, name[9:].lower().replace('_', ' '))
 
 #------------------------------------------------------------------------------
 
-def _marshal_relation_set(cache, dbus_object, app_name, relation_set):
+def _marshal_relation_set(cache, app_name, relation_set):
        """
        The D-Bus protocol has a relation set passed as an array of
        relation types and object arrays.
@@ -107,7 +107,7 @@ def _marshal_relation_set(cache, dbus_object, app_name, relation_set):
        This function marshals the D-Bus message into a list of relation
        objects.
        """
-       return [Relation(cache, dbus_object, app_name, *relation) for relation in relation_set]
+       return [Relation(cache, app_name, *relation) for relation in relation_set]
 
 #------------------------------------------------------------------------------
 
@@ -118,11 +118,10 @@ class Relation(object):
     a "one-to-many" correspondance.
     """
 
-    def __init__(self, cache, dbus_object, app_name, type, objects):
+    def __init__(self, cache, app_name, type, objects):
        self._type = type
        self._objects = objects
 
-       self._dbus_object = dbus_object
        self._cache = cache
        self._app_name = app_name
     
@@ -154,6 +153,6 @@ class Relation(object):
                                 self._app_name,
                                 self._objects[index],
                                 interfaces.ATSPI_ACCESSIBLE,
-                                dbus_object=self._dbus_object)
+                                connection=self._cache._connection)
 
 #END----------------------------------------------------------------------------
index 7cd93d5..12a3257 100644 (file)
@@ -2,7 +2,8 @@ check_PROGRAMS = test-application
 check_LTLIBRARIES = libnoopapp.la \
                    libaccessibleapp.la \
                    libcomponentapp.la \
-                   libactionapp.la
+                   libactionapp.la \
+                   librelationapp.la
 
 test_application_CFLAGS = $(DBUS_GLIB_CFLAGS)  \
                          $(ATK_CFLAGS)         \
@@ -39,3 +40,8 @@ libactionapp_la_CFLAGS = $(TEST_APP_CFLAGS)
 libactionapp_la_LDFLAGS = $(TEST_APP_LDFLAGS)
 libactionapp_la_LIBADD = $(TEST_APP_LIBADD)
 libactionapp_la_SOURCES = action-app.c
+
+librelationapp_la_CFLAGS = $(TEST_APP_CFLAGS)
+librelationapp_la_LDFLAGS = $(TEST_APP_LDFLAGS)
+librelationapp_la_LIBADD = $(TEST_APP_LIBADD)
+librelationapp_la_SOURCES = relation-app.c
diff --git a/tests/apps/relation-app.c b/tests/apps/relation-app.c
new file mode 100644 (file)
index 0000000..5734ffe
--- /dev/null
@@ -0,0 +1,90 @@
+#include <gmodule.h>
+#include <atk/atk.h>
+#include <my-atk.h>
+
+static AtkObject *root_accessible;
+
+G_MODULE_EXPORT void
+test_init (gchar *path)
+{
+  AtkObject *r1, *r2, *r3;
+  AtkObject *m1, *m2, *m3;
+  AtkRelationSet *rset;
+  AtkRelation *rel;
+  AtkObject *rls[3];
+
+  root_accessible  = g_object_new(MY_TYPE_ATK_OBJECT, NULL);
+  
+  r1 = ATK_OBJECT(g_object_new(MY_TYPE_ATK_OBJECT,
+                                 "accessible-name", "r1",
+                                 "accessible-description", "",
+                                 "accessible-role", ATK_ROLE_INVALID,
+                                 NULL));
+  my_atk_object_add_child(MY_ATK_OBJECT(root_accessible), MY_ATK_OBJECT(r1));
+
+  r2 = ATK_OBJECT(g_object_new(MY_TYPE_ATK_OBJECT,
+                                 "accessible-name", "r2",
+                                 "accessible-description", "",
+                                 "accessible-role", ATK_ROLE_INVALID,
+                                 NULL));
+  my_atk_object_add_child(MY_ATK_OBJECT(root_accessible), MY_ATK_OBJECT(r2));
+
+  r3 = ATK_OBJECT(g_object_new(MY_TYPE_ATK_OBJECT,
+                                 "accessible-name", "r3",
+                                 "accessible-description", "",
+                                 "accessible-role", ATK_ROLE_INVALID,
+                                 NULL));
+  my_atk_object_add_child(MY_ATK_OBJECT(root_accessible), MY_ATK_OBJECT(r3));
+
+  m1 = ATK_OBJECT(g_object_new(MY_TYPE_ATK_OBJECT,
+                                 "accessible-name", "m1",
+                                 "accessible-description", "",
+                                 "accessible-role", ATK_ROLE_INVALID,
+                                 NULL));
+  my_atk_object_add_child(MY_ATK_OBJECT(root_accessible), MY_ATK_OBJECT(m1));
+
+  m2 = ATK_OBJECT(g_object_new(MY_TYPE_ATK_OBJECT,
+                                 "accessible-name", "m2",
+                                 "accessible-description", "",
+                                 "accessible-role", ATK_ROLE_INVALID,
+                                 NULL));
+  my_atk_object_add_child(MY_ATK_OBJECT(root_accessible), MY_ATK_OBJECT(m2));
+
+  m3 = ATK_OBJECT(g_object_new(MY_TYPE_ATK_OBJECT,
+                                 "accessible-name", "m3",
+                                 "accessible-description", "",
+                                 "accessible-role", ATK_ROLE_INVALID,
+                                 NULL));
+  my_atk_object_add_child(MY_ATK_OBJECT(root_accessible), MY_ATK_OBJECT(m3));
+
+  atk_object_add_relationship(root_accessible, ATK_RELATION_EMBEDS, r1);
+  atk_object_add_relationship(root_accessible, ATK_RELATION_PARENT_WINDOW_OF, r2);
+  atk_object_add_relationship(root_accessible, ATK_RELATION_DESCRIBED_BY, r3);
+
+  rls[0] = m1;
+  rls[1] = m2;
+  rls[2] = m3;
+
+  rset = atk_object_ref_relation_set(root_accessible);
+  rel = atk_relation_new(rls, 3, ATK_RELATION_POPUP_FOR);
+  atk_relation_set_add(rset, rel);
+  g_object_unref(G_OBJECT(rset));
+}
+
+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 *
+test_get_root (void)
+{
+  return root_accessible;
+}
index 8c22146..dbe32a8 100644 (file)
@@ -8,6 +8,7 @@ EXTRA_DIST = \
        Makefile.am\
        Makefile.in\
        setvars.sh\
+       relationtest.py\
        testrunner.py
 
 CLEANFILES = *.pyc
diff --git a/tests/pyatspi/relationtest.py b/tests/pyatspi/relationtest.py
new file mode 100644 (file)
index 0000000..6f93b14
--- /dev/null
@@ -0,0 +1,70 @@
+import dbus
+import gobject
+import os.path
+
+from xml.dom import minidom
+import os
+
+from pasytest import PasyTest as _PasyTest
+
+import pyatspi
+
+class RelationTest(_PasyTest):
+
+       __tests__ = ["setup",
+                    "teardown",
+                    "test_getRelationType",
+                    "test_getRelationTypeName",
+                    "test_getNTargets",
+                    "test_getTarget",
+                    ]
+
+       def __init__(self, bus, path):
+               _PasyTest.__init__(self, "Relation", False)
+               self._bus = bus
+               self._path = path
+
+       def setup(self, test):
+               self._registry = pyatspi.registry.Registry(self._path)
+               self._desktop = self._registry.getDesktop(0)
+               self._root = self._desktop[0]
+               self._rset = self._root.getRelationSet()
+               test.assertEqual(len(self._rset), 4, "Num relations expected %d, recieved %d" % (6, len(self._rset)))
+
+       def test_getRelationType(self, test):
+               expected = [pyatspi.RELATION_EMBEDS,
+                           pyatspi.RELATION_PARENT_WINDOW_OF,
+                           pyatspi.RELATION_DESCRIBED_BY,
+                           pyatspi.RELATION_POPUP_FOR,]
+               rtypes = [rel.getRelationType() for rel in self._rset]
+               for exp, type in zip(expected, rtypes):
+                       test.assertEqual(exp, type, "Relation type expected %s, recieved %s" % (exp, type))
+
+       def test_getRelationTypeName(self, test):
+               # FIXME This may not have been implemented in CORBA.
+               #       Completely unused?
+               pass
+
+       def test_getNTargets(self, test):
+               expected = [1, 1, 1, 3]
+               ntargs = [rel.getNTargets() for rel in self._rset]
+               for exp, ntarg in zip(expected, ntargs):
+                       test.assertEqual(exp, ntarg, "Number of targets expected %s, recieved %s" % (exp, ntarg))
+
+       def test_getTarget(self, test):
+               rone = self._rset[0]
+               tone = rone.getTarget(0)
+               tonename = tone.name
+               test.assertEqual(tonename, "r1", "Target name expected %s, recieved %s" % ("r1", tonename))
+               tonerole = tone.getRoleName()
+               test.assertEqual(tonerole, "invalid", "Target RoleName expected %s, recieved %s" % ("invalid", tonename))
+
+               rtwo = self._rset[3]
+               ttwo = rtwo.getTarget(2)
+               ttwoname = ttwo.name
+               test.assertEqual(ttwoname, "m3", "Target name expected %s, recieved %s" % ("m3", ttwoname))
+               ttworole = ttwo.getRoleName()
+               test.assertEqual(ttworole, "invalid", "Target RoleName expected %s, recieved %s" % ("invalid", ttwoname))
+
+       def teardown(self, test):
+               pass