[pygobject] Add common attribute accessors to PyGIBaseInfo



commit bec0b543be8d993996d8a17c343c3f2f33a9398f
Author: Simon Feltman <sfeltman src gnome org>
Date:   Tue Jul 16 11:13:17 2013 -0700

    Add common attribute accessors to PyGIBaseInfo
    
    Add __name__, __module__, and __doc__ accessors to
    PyGIBaseInfo object. This is a precursory patch for setting
    up PyGICallableInfo as a directly callable object with lazy
    doc string evaluation.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=704037

 gi/_glib/pyglib-python-compat.h |    5 ++
 gi/pygi-info.c                  |   83 +++++++++++++++++++++++++++++++++++++-
 gi/types.py                     |    7 +--
 3 files changed, 88 insertions(+), 7 deletions(-)
---
diff --git a/gi/_glib/pyglib-python-compat.h b/gi/_glib/pyglib-python-compat.h
index 96c27ca..7b4c595 100644
--- a/gi/_glib/pyglib-python-compat.h
+++ b/gi/_glib/pyglib-python-compat.h
@@ -87,6 +87,8 @@ static int _pyglib_init_##modname(PyObject *module)
 #define PYGLIB_PyUnicode_AS_STRING PyString_AS_STRING
 #define PYGLIB_PyUnicode_GET_SIZE PyString_GET_SIZE
 #define PYGLIB_PyUnicode_Type PyString_Type
+#define PYGLIB_PyUnicode_InternFromString PyString_InternFromString
+#define PYGLIB_PyUnicode_InternInPlace PyString_InternInPlace
 
 #define PYGLIB_PyBytes_FromString PyString_FromString
 #define PYGLIB_PyBytes_FromStringAndSize PyString_FromStringAndSize
@@ -191,6 +193,9 @@ PyTypeObject symbol = {                                 \
 #define PYGLIB_PyUnicode_GET_SIZE PyUnicode_GET_SIZE
 #define PYGLIB_PyUnicode_Resize PyUnicode_Resize
 #define PYGLIB_PyUnicode_Type PyUnicode_Type
+#define PYGLIB_PyUnicode_InternFromString PyUnicode_InternFromString
+#define PYGLIB_PyUnicode_InternInPlace PyUnicode_InternInPlace
+
 #define PYGLIB_PyLong_Check PyLong_Check
 #define PYGLIB_PyLong_FromLong PyLong_FromLong
 #define PYGLIB_PyLong_AsLong PyLong_AsLong
diff --git a/gi/pygi-info.c b/gi/pygi-info.c
index c8dfb2b..0622fc8 100644
--- a/gi/pygi-info.c
+++ b/gi/pygi-info.c
@@ -27,6 +27,33 @@
 #include <pygobject.h>
 #include <pyglib-python-compat.h>
 
+
+/* _generate_doc_string
+ *
+ * C wrapper to call Python implemented "gi.docstring.generate_doc_string"
+ */
+static PyObject *
+_generate_doc_string(PyGIBaseInfo *self)
+{
+    static PyObject *_py_generate_doc_string = NULL;
+
+    if (_py_generate_doc_string == NULL) {
+        PyObject *mod = PyImport_ImportModule ("gi.docstring");
+        if (!mod)
+            return NULL;
+
+        _py_generate_doc_string = PyObject_GetAttrString (mod, "generate_doc_string");
+        if (_py_generate_doc_string == NULL) {
+            Py_DECREF (mod);
+            return NULL;
+        }
+        Py_DECREF (mod);
+    }
+
+    return PyObject_CallFunctionObjArgs (_py_generate_doc_string, self, NULL);
+}
+
+
 /* BaseInfo */
 
 static void
@@ -170,6 +197,55 @@ static PyMethodDef _PyGIBaseInfo_methods[] = {
     { NULL, NULL, 0 }
 };
 
+/* _base_info_getattro:
+ *
+ * The usage of __getattr__ is needed because the get/set method table
+ * does not work for __doc__.
+ */
+static PyObject *
+_base_info_getattro(PyGIBaseInfo *self, PyObject *name)
+{
+    PyObject *result;
+
+    static PyObject *docstr;
+    if (docstr == NULL) {
+        docstr= PYGLIB_PyUnicode_InternFromString("__doc__");
+        if (docstr == NULL)
+            return NULL;
+    }
+
+    Py_INCREF (name);
+    PYGLIB_PyUnicode_InternInPlace (&name);
+
+    if (name == docstr) {
+        result = _generate_doc_string (self);
+    } else {
+        result = PyObject_GenericGetAttr ((PyObject *)self, name);
+    }
+
+    Py_DECREF (name);
+    return result;
+}
+
+static PyObject *
+_base_info_attr_name(PyGIBaseInfo *self, void *closure)
+{
+    return _wrap_g_base_info_get_name (self);
+}
+
+static PyObject *
+_base_info_attr_module(PyGIBaseInfo *self, void *closure)
+{
+    return PYGLIB_PyUnicode_FromFormat ("gi.repository.%s",
+                                        g_base_info_get_namespace (self->info));
+}
+
+static PyGetSetDef _base_info_getsets[] = {
+        { "__name__", (getter)_base_info_attr_name, (setter)0, "Name", NULL},
+        { "__module__", (getter)_base_info_attr_module, (setter)0, "Module name", NULL},
+    { NULL, 0, 0 }
+};
+
 PyObject *
 _pygi_info_new (GIBaseInfo *info)
 {
@@ -1742,12 +1818,13 @@ _pygi_info_register_types (PyObject *m)
     PyGIBaseInfo_Type.tp_repr = (reprfunc) _base_info_repr;
     PyGIBaseInfo_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE);
     PyGIBaseInfo_Type.tp_weaklistoffset = offsetof(PyGIBaseInfo, inst_weakreflist);
-    PyGIBaseInfo_Type.tp_methods = _PyGIBaseInfo_methods; 
+    PyGIBaseInfo_Type.tp_methods = _PyGIBaseInfo_methods;
     PyGIBaseInfo_Type.tp_richcompare = (richcmpfunc)_base_info_richcompare;
+    PyGIBaseInfo_Type.tp_getset = _base_info_getsets;
+    PyGIBaseInfo_Type.tp_getattro = (getattrofunc) _base_info_getattro;
 
     if (PyType_Ready(&PyGIBaseInfo_Type))
-        return;   
- 
+        return;
     if (PyModule_AddObject(m, "BaseInfo", (PyObject *)&PyGIBaseInfo_Type))
         return;
 
diff --git a/gi/types.py b/gi/types.py
index 85eecf1..4e95ca2 100644
--- a/gi/types.py
+++ b/gi/types.py
@@ -28,7 +28,6 @@ import warnings
 from . import _gobject
 from ._gobject._gobject import GInterface
 from ._gobject.constants import TYPE_INVALID
-from .docstring import generate_doc_string
 
 from ._gi import \
     InterfaceInfo, \
@@ -51,9 +50,9 @@ def wraps_callable_info(info):
     """Similar to functools.wraps but with specific GICallableInfo support."""
     def update_func(func):
         func.__info__ = info
-        func.__name__ = info.get_name()
-        func.__module__ = 'gi.repository.' + info.get_namespace()
-        func.__doc__ = generate_doc_string(info)
+        func.__name__ = info.__name__
+        func.__module__ = info.__module__
+        func.__doc__ = info.__doc__
         return func
     return update_func
 


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