[gobject-introspection] Better handle classes with non-standard to_underscore names.



commit aa94335b84d17512281ab3ed4cd20fb1fad9dcd8
Author: C. Scott Ananian <cscott litl com>
Date:   Tue May 19 20:17:08 2009 -0400

    Better handle classes with non-standard to_underscore names.
    
    Previously we tried to guess what the "underscore version" of a class name
    would be, but for classes like NMSetting8021x we'd guess "nm_setting8021x"
    instead of "nm_setting_802_1x".  All such guesses are subject to error:
    instead let's try to use the prefix of the _get_type() method instead, and
    only guess if that doesn't work.
    
    We do this for both class names and when detecting methods.  An additional
    type with a "non-standard" underscored version (TestWi8021x) added to the
    everything.[ch] test suite to test proper conversion.
    
    GdkWindow and GObject have unusual get_type methods; add special quirks
    to handle these (at least until the methods are renamed upstream).
    
    (Slightly modified for PEP8 compliance by Colin Walters)
    
    Signed-off-by: Colin Walters <walters verbum org>
---
 giscanner/glibtransformer.py  |   29 ++++++++++-
 tests/everything/everything.c |  106 +++++++++++++++++++++++++++++++++++++++++
 tests/everything/everything.h |   24 +++++++++
 3 files changed, 157 insertions(+), 2 deletions(-)

diff --git a/giscanner/glibtransformer.py b/giscanner/glibtransformer.py
index 0f5b0c9..6a0dee0 100644
--- a/giscanner/glibtransformer.py
+++ b/giscanner/glibtransformer.py
@@ -60,6 +60,18 @@ SYMBOL_BLACKLIST = [
 SYMBOL_BLACKLIST_RE = [re.compile(x) for x in \
                            [r'\w+_marshal_[A-Z]+__', ]]
 
+GET_TYPE_OVERRIDES = {
+    # this is a special case, from glibtransforer.py:create_gobject
+    'intern': 'g_object_get_type',
+    # this is presumably a typo, should be fixed upstream
+    'g_gstring_get_type': 'g_string_get_type',
+    # this is historical cruft: there's a deprecated
+    #   #define gdk_window_get_type gdk_window_get_window_type
+    # upstream; this method can be renamed properly upstream once
+    # that deprecated alias is removed (in some future release)
+    'gdk_window_object_get_type': 'gdk_window_get_type',
+}
+
 
 class IntrospectionBinary(object):
 
@@ -213,6 +225,10 @@ class GLibTransformer(object):
     def _register_internal_type(self, type_name, node):
         self._names.type_names[type_name] = (None, node)
         uscored = to_underscores(type_name).lower()
+        # prefer the prefix of the get_type method, if there is one
+        if hasattr(node, 'get_type'):
+            uscored = GET_TYPE_OVERRIDES.get(node.get_type, node.get_type)
+            uscored = uscored[:-len('_get_type')]
         self._uscore_type_names[uscored] = node
         # Besides the straight underscore conversion, we also try
         # removing the underscores from the namespace as a possible C
@@ -220,7 +236,9 @@ class GLibTransformer(object):
         suffix = self._transformer.remove_prefix(type_name)
         prefix = type_name[:-len(suffix)]
         no_uscore_prefixed = (prefix + '_' + to_underscores(suffix)).lower()
-        self._uscore_type_names[no_uscore_prefixed] = node
+        # since this is a guess, don't overwrite any 'real' prefix
+        if no_uscore_prefixed not in self._uscore_type_names:
+            self._uscore_type_names[no_uscore_prefixed] = node
 
     def _resolve_quarks(self):
         for node in self._error_quark_functions:
@@ -401,7 +419,7 @@ class GLibTransformer(object):
         target_klass = None
         prefix_components = None
         methname = None
-        for i in xrange(1, len(components)-1):
+        for i in xrange(1, len(components)):
             prefix_components = '_'.join(components[0:-i])
             methname = '_'.join(components[-i:])
             target_klass = self._uscore_type_names.get(prefix_components)
@@ -446,6 +464,13 @@ class GLibTransformer(object):
             argtype = target_arg.type.ctype.replace('*', '')
             name = self._transformer.remove_prefix(argtype)
             name_uscore = to_underscores_noprefix(name).lower()
+            # prefer the prefix of the _get_type method, if there is one
+            if argtype in self._names.type_names:
+                node = self._names.type_names[argtype][1]
+                if hasattr(node, 'get_type'):
+                    name_uscore = GET_TYPE_OVERRIDES.get(node.get_type,
+                                                         node.get_type)
+                    name_uscore = name_uscore[:-len('_get_type')]
             name_offset = func.symbol.find(name_uscore)
             if name_offset < 0:
                 return None
diff --git a/tests/everything/everything.c b/tests/everything/everything.c
index 7c9e4e5..52dec4b 100644
--- a/tests/everything/everything.c
+++ b/tests/everything/everything.c
@@ -1345,3 +1345,109 @@ test_interface_get_type(void)
     return type;
 }
 
+/* gobject with non-standard prefix */
+G_DEFINE_TYPE(TestWi8021x, test_wi_802_1x, G_TYPE_OBJECT);
+
+enum
+{
+  PROP_TEST_WI_802_1X_TESTBOOL = 1
+};
+
+static void
+test_wi_802_1x_set_property (GObject      *object,
+                             guint         property_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+  TestWi8021x *self = TEST_WI_802_1X (object);
+
+  switch (property_id)
+    {
+    case PROP_TEST_WI_802_1X_TESTBOOL:
+      test_wi_802_1x_set_testbool (self, g_value_get_boolean (value));
+      break;
+
+    default:
+      /* We don't have any other property... */
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+test_wi_802_1x_get_property (GObject    *object,
+                        guint       property_id,
+                        GValue     *value,
+                        GParamSpec *pspec)
+{
+  TestWi8021x *self = TEST_WI_802_1X (object);
+
+  switch (property_id)
+    {
+    case PROP_TEST_WI_802_1X_TESTBOOL:
+      g_value_set_boolean (value, test_wi_802_1x_get_testbool (self));
+      break;
+
+    default:
+      /* We don't have any other property... */
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+      break;
+    }
+}
+
+static void
+test_wi_802_1x_dispose (GObject *gobject)
+{
+  /* Chain up to the parent class */
+  G_OBJECT_CLASS (test_wi_802_1x_parent_class)->dispose (gobject);
+}
+
+static void
+test_wi_802_1x_class_init (TestWi8021xClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GParamSpec *pspec;
+
+  gobject_class->set_property = test_wi_802_1x_set_property;
+  gobject_class->get_property = test_wi_802_1x_get_property;
+  gobject_class->dispose = test_wi_802_1x_dispose;
+
+  pspec = g_param_spec_boolean ("testbool",
+                                "Nick for testbool",
+                                "Blurb for testbool",
+                                TRUE,
+                                G_PARAM_READWRITE);
+  g_object_class_install_property (gobject_class,
+                                   PROP_TEST_WI_802_1X_TESTBOOL,
+                                   pspec);
+}
+
+static void
+test_wi_802_1x_init (TestWi8021x *obj)
+{
+  obj->testbool = TRUE;
+}
+
+TestWi8021x *
+test_wi_802_1x_new (void)
+{
+  return g_object_new (TEST_TYPE_WI_802_1X, NULL);
+}
+
+void
+test_wi_802_1x_set_testbool (TestWi8021x *obj, gboolean val)
+{
+  obj->testbool = val;
+}
+
+gboolean
+test_wi_802_1x_get_testbool (TestWi8021x *obj)
+{
+  return obj->testbool;
+}
+
+int
+test_wi_802_1x_static_method (int x)
+{
+  return 2*x;
+}
diff --git a/tests/everything/everything.h b/tests/everything/everything.h
index 9f4c7d7..2a7e3cd 100644
--- a/tests/everything/everything.h
+++ b/tests/everything/everything.h
@@ -258,4 +258,28 @@ struct _TestInterfaceIface {
 
 GType test_interface_get_type (void) G_GNUC_CONST;
 
+/* gobject with non-standard prefix */
+#define TEST_TYPE_WI_802_1X              (test_wi_802_1x_get_type ())
+#define TEST_WI_802_1X(object)        (G_TYPE_CHECK_INSTANCE_CAST ((object), TEST_TYPE_WI_802_1X, TestWi8021x))
+#define TEST_IS_WI_802_1X(object)     (G_TYPE_CHECK_INSTANCE_TYPE ((object), TEST_TYPE_WI_802_1X))
+#define TEST_WI_802_1X_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_WI_802_1X, TestWi8021xClass))
+
+typedef struct
+{
+  GObject parent_instance;
+
+  gboolean testbool;
+} TestWi8021x;
+
+typedef struct
+{
+  GObjectClass parent_class;
+} TestWi8021xClass;
+
+GType        test_wi_802_1x_get_type (void);
+TestWi8021x* test_wi_802_1x_new (void);
+gboolean     test_wi_802_1x_get_testbool (TestWi8021x *obj);
+void         test_wi_802_1x_set_testbool (TestWi8021x *obj, gboolean v);
+int          test_wi_802_1x_static_method (int x);
+
 #endif /* __GITESTTYPES_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]