[pygobject] Remove Python keyword escapement in Repository.find_by_name



commit 99872a18ed1468b2c85cc7b96a0d12f2ae5167f0
Author: Simon Feltman <sfeltman src gnome org>
Date:   Thu Apr 11 04:09:59 2013 -0700

    Remove Python keyword escapement in Repository.find_by_name
    
    Strip trailing underscore from module level items before
    calling g_irepository_find_by_name. This fixes a problem
    with GI module level items having the same name as a Python
    keyword raising an AttributeError during access (Pango.break_).
    
    https://bugzilla.gnome.org/show_bug.cgi?id=697363

 gi/pygi-info.c                | 32 ++++++++++++++++++++++----------
 gi/pygi-info.h                |  2 ++
 gi/pygi-repository.c          | 16 ++++++++++++++++
 tests/test_overrides_pango.py |  5 +++++
 4 files changed, 45 insertions(+), 10 deletions(-)
---
diff --git a/gi/pygi-info.c b/gi/pygi-info.c
index 362e7cd..3bee1b1 100644
--- a/gi/pygi-info.c
+++ b/gi/pygi-info.c
@@ -90,8 +90,8 @@ _base_info_richcompare (PyGIBaseInfo *self, PyObject *other, int op)
 
 PYGLIB_DEFINE_TYPE("gi.BaseInfo", PyGIBaseInfo_Type, PyGIBaseInfo);
 
-static PyObject *
-_wrap_g_base_info_get_name (PyGIBaseInfo *self)
+gboolean
+_pygi_is_python_keyword (const gchar *name)
 {
     /* It may be better to use keyword.iskeyword(); keep in sync with
      * python -c 'import keyword; print(keyword.kwlist)' */
@@ -115,20 +115,32 @@ _wrap_g_base_info_get_name (PyGIBaseInfo *self)
     #error Need keyword list for this major Python version
 #endif
 
-    const gchar *name, **i;
-
-    name = g_base_info_get_name (self->info);
+    const gchar **i;
 
-    /* escape keywords */
     for (i = keywords; *i != NULL; ++i) {
         if (strcmp (name, *i) == 0) {
-            gchar *escaped = g_strconcat (name, "_", NULL);
-            PyObject *obj = PYGLIB_PyUnicode_FromString (escaped);
-            g_free (escaped);
-            return obj;
+            return TRUE;
         }
     }
 
+    return FALSE;
+}
+
+static PyObject *
+_wrap_g_base_info_get_name (PyGIBaseInfo *self)
+{
+    const gchar *name;
+
+    name = g_base_info_get_name (self->info);
+
+    /* escape keywords */
+    if (_pygi_is_python_keyword (name)) {
+        gchar *escaped = g_strconcat (name, "_", NULL);
+        PyObject *obj = PYGLIB_PyUnicode_FromString (escaped);
+        g_free (escaped);
+        return obj;
+    }
+
     return PYGLIB_PyUnicode_FromString (name);
 }
 
diff --git a/gi/pygi-info.h b/gi/pygi-info.h
index afd65dc..d550d8d 100644
--- a/gi/pygi-info.h
+++ b/gi/pygi-info.h
@@ -68,6 +68,8 @@ gsize _pygi_g_type_info_size (GITypeInfo *type_info);
 
 void _pygi_info_register_types (PyObject *m);
 
+gboolean _pygi_is_python_keyword (const gchar *name);
+
 G_END_DECLS
 
 #endif /* __PYGI_INFO_H__ */
diff --git a/gi/pygi-repository.c b/gi/pygi-repository.c
index d54326d..d7c65f5 100644
--- a/gi/pygi-repository.c
+++ b/gi/pygi-repository.c
@@ -120,13 +120,29 @@ _wrap_g_irepository_find_by_name (PyGIRepository *self,
     const char *name;
     GIBaseInfo *info;
     PyObject *py_info;
+    size_t len;
+    char *trimmed_name = NULL;
 
     if (!PyArg_ParseTupleAndKeywords (args, kwargs,
                                       "ss:Repository.find_by_name", kwlist, &namespace_, &name)) {
         return NULL;
     }
 
+    /* If the given name ends with an underscore, it might be due to usage
+     * as an accessible replacement for something in GI with the same name
+     * as a Python keyword. Test for this and trim it out if necessary.
+     */
+    len = strlen (name);
+    if (len > 0 && name[len-1] == '_') {
+        trimmed_name = g_strndup (name, len-1);
+        if (_pygi_is_python_keyword (trimmed_name)) {
+            name = trimmed_name;
+        }
+    }
+
     info = g_irepository_find_by_name (self->repository, namespace_, name);
+    g_free (trimmed_name);
+
     if (info == NULL) {
         Py_RETURN_NONE;
     }
diff --git a/tests/test_overrides_pango.py b/tests/test_overrides_pango.py
index 51f4f6a..42d4de9 100644
--- a/tests/test_overrides_pango.py
+++ b/tests/test_overrides_pango.py
@@ -30,3 +30,8 @@ class TestPango(unittest.TestCase):
 
         layout.set_markup("Foobar")
         self.assertEqual(layout.get_text(), "Foobar")
+
+    def test_break_keyword_escape(self):
+        # https://bugzilla.gnome.org/show_bug.cgi?id=697363
+        self.assertTrue(hasattr(Pango, 'break_'))
+        self.assertTrue(Pango.break_ is not None)


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