[pygobject/gtk-3.0] Refactor field access



commit 21e1971920ade8b9ae3ea68ab8829ee124f678ed
Author: John Stowers <john stowers gmail com>
Date:   Mon Jul 5 17:39:12 2010 +1200

    Refactor field access
    
    	* Add implementation for boxed and pointer types
    	* Remove direct field access for GObject types for
    	  the sake of GSEAL compatibility.
    	* Add new defs cababilities, getter-{propname,funcname}
    	  which can work around this. Print a deprecation warning
    	  in any field access for GObjects

 codegen/codegen.py     |   44 +++++++++++++++++++++++++++++++++-----------
 codegen/definitions.py |   42 ++++++++++++++++++++++++++++++++++--------
 2 files changed, 67 insertions(+), 19 deletions(-)
---
diff --git a/codegen/codegen.py b/codegen/codegen.py
index 008f01c..660c29a 100755
--- a/codegen/codegen.py
+++ b/codegen/codegen.py
@@ -156,7 +156,7 @@ class Wrapper:
         '%(funcname)s(PyObject *self, void *closure)\n'
         '{\n'
         '%(varlist)s'
-        '    ret = %(field)s;\n'
+        '    %(assignment)s\n'
         '%(codeafter)s\n'
         '}\n\n'
         )
@@ -243,9 +243,12 @@ class Wrapper:
         return string.lower(string.replace(self.objinfo.typecode,
                                            '_TYPE_', '_', 1))
 
-    def get_field_accessor(self, fieldname):
+    def get_original_type(self):
         raise NotImplementedError
 
+    def get_field_accessor(self, fieldname):
+        return '%s->%s' % (self.get_original_type(), fieldname)
+
     def get_initial_class_substdict(self): return {}
 
     def get_initial_constructor_substdict(self, constructor):
@@ -675,6 +678,13 @@ class Wrapper:
 ''' % vars())
             self.fp.write('    return 0;\n}\n')
 
+    def get_field_assignment(self, ftype, cfname, getter_propname, getter_funcname):
+        if getter_funcname:
+            func = '%s_%s(%s);' % (self.get_lower_name(), getter_funcname, self.get_original_type())
+        else:
+            func = self.get_field_accessor(cfname)
+        return 'ret = %s;' % func
+
     def write_getsets(self):
         lower_name = self.get_lower_name()
         getsets_name = lower_name + '_getsets'
@@ -686,7 +696,7 @@ class Wrapper:
         if not self.objinfo.fields:
             return '0'
         getsets = []
-        for ftype, cfname in self.objinfo.fields:
+        for ftype, cfname, getter_propname, getter_funcname in self.objinfo.fields:
             fname = cfname.replace('.', '_')
             gettername = '0'
             settername = '0'
@@ -708,7 +718,7 @@ class Wrapper:
                     self.fp.write(self.getter_tmpl %
                                   { 'funcname': funcname,
                                     'varlist': info.varlist,
-                                    'field': self.get_field_accessor(cfname),
+                                    'assignment' : self.get_field_assignment(ftype, cfname, getter_propname, getter_funcname),
                                     'codeafter': info.get_codeafter() })
                     gettername = funcname
                 except argtypes.ArgTypeError, ex:
@@ -947,6 +957,7 @@ class GObjectWrapper(Wrapper):
         '%(codeafter)s\n'
         '}\n\n'
         )
+
     def __init__(self, parser, objinfo, overrides, fp=FileOutput(sys.stdout)):
         Wrapper.__init__(self, parser, objinfo, overrides, fp)
         if self.objinfo:
@@ -958,9 +969,21 @@ class GObjectWrapper(Wrapper):
                  'tp_weaklistoffset' : 'offsetof(PyGObject, weakreflist)',
                  'tp_dictoffset'     : 'offsetof(PyGObject, inst_dict)' }
 
-    def get_field_accessor(self, fieldname):
+    def get_original_type(self):
         castmacro = string.replace(self.objinfo.typecode, '_TYPE_', '_', 1)
-        return '%s(pygobject_get(self))->%s' % (castmacro, fieldname)
+        return '%s(pygobject_get(self))' % castmacro
+
+    def get_field_assignment(self, ftype, cfname, getter_propname, getter_funcname):
+        py_fname =" %s.%s" % (self.objinfo.c_name, cfname)
+        warn = 'PyErr_Warn(PyExc_DeprecationWarning, "%s should not be accessed directly");\n' % py_fname
+        if getter_funcname:
+            custom = 'ret = %s_%s(%s);' % (self.get_lower_name(), getter_funcname, self.get_original_type())
+        elif getter_propname:
+            custom = 'g_object_get(pygobject_get(self), "%s", &ret, NULL);' % getter_propname
+        else:
+            custom = warn + '    return NULL; /* FIXME-FIELD: %s */' % py_fname
+
+        return custom
 
     def get_initial_constructor_substdict(self, constructor):
         substdict = Wrapper.get_initial_constructor_substdict(self,
@@ -1271,8 +1294,8 @@ class GBoxedWrapper(Wrapper):
                  'tp_weaklistoffset' : '0',
                  'tp_dictoffset'     : '0' }
 
-    def get_field_accessor(self, fieldname):
-        return 'pyg_boxed_get(self, %s)->%s' % (self.objinfo.c_name, fieldname)
+    def get_original_type(self):
+        return 'pyg_boxed_get(self, %s)' % self.objinfo.c_name
 
     def get_initial_constructor_substdict(self, constructor):
         substdict = Wrapper.get_initial_constructor_substdict(
@@ -1318,9 +1341,8 @@ class GPointerWrapper(GBoxedWrapper):
                  'tp_weaklistoffset' : '0',
                  'tp_dictoffset'     : '0' }
 
-    def get_field_accessor(self, fieldname):
-        return 'pyg_pointer_get(self, %s)->%s' % (self.objinfo.c_name,
-                                                  fieldname)
+    def get_original_type(self):
+        return 'pyg_pointer_get(self, %s)' % self.objinfo.c_name
 
     def get_initial_constructor_substdict(self, constructor):
         substdict = Wrapper.get_initial_constructor_substdict(
diff --git a/codegen/definitions.py b/codegen/definitions.py
index aca5adb..31dd973 100644
--- a/codegen/definitions.py
+++ b/codegen/definitions.py
@@ -12,6 +12,32 @@ def unescape(s):
 def make_docstring(lines):
     return "(char *) " + '\n'.join(['"%s"' % unescape(s) for s in lines])
 
+def field_list_parse_one(outlist, parg):
+    ftype = parg[0]
+    fname = parg[1]
+    getter_propname = ""
+    getter_funcname = ""
+    for farg in parg[2:]:
+        assert isinstance(farg, tuple)
+        if farg[0] == 'getter-propname':
+            getter_propname = farg[1]
+        elif farg[0] == 'getter-funcname':
+            getter_funcname = farg[1]
+    outlist.append((ftype, fname, getter_propname, getter_funcname))
+
+def field_list_print_one(ftype, fname, getter_propname, getter_funcname):
+    if getter_propname or getter_funcname:
+        extra = ' ('
+        if getter_propname:
+            extra += 'getter-propname "%s"' % getter_propname
+        elif getter_funcname:
+            extra += 'getter-funcname "%s"' % getter_funcname
+        extra += ')'
+    else:
+        extra = ''
+
+    return '("%s" "%s"%s)' % (ftype, fname, extra)
+
 # New Parameter class, wich emulates a tuple for compatibility reasons
 class Parameter(object):
     def __init__(self, ptype, pname, pdflt, pnull, pdir=None):
@@ -115,7 +141,7 @@ class ObjectDef(Definition):
                 self.typecode = arg[1]
             elif arg[0] == 'fields':
                 for parg in arg[1:]:
-                    self.fields.append((parg[0], parg[1]))
+                    field_list_parse_one(self.fields, parg)
             elif arg[0] == 'implements':
                 self.implements.append(arg[1])
     def merge(self, old):
@@ -138,8 +164,8 @@ class ObjectDef(Definition):
             fp.write('  (gtype-id "' + self.typecode + '")\n')
         if self.fields:
             fp.write('  (fields\n')
-            for (ftype, fname) in self.fields:
-                fp.write('    \'("' + ftype + '" "' + fname + '")\n')
+            for (ftype, fname, getter_propname, getter_funcname) in self.fields:
+                fp.write('    \'' + field_list_print_one(ftype, fname, getter_propname, getter_funcname) + '\n')
             fp.write('  )\n')
         fp.write(')\n\n')
 
@@ -235,7 +261,7 @@ class BoxedDef(Definition):
                 self.release = arg[1]
             elif arg[0] == 'fields':
                 for parg in arg[1:]:
-                    self.fields.append((parg[0], parg[1]))
+                    field_list_parse_one(self.fields, parg)
     def merge(self, old):
         # currently the .h parser doesn't try to work out what fields of
         # an object structure should be public, so we just copy the list
@@ -255,8 +281,8 @@ class BoxedDef(Definition):
             fp.write('  (release-func "' + self.release + '")\n')
         if self.fields:
             fp.write('  (fields\n')
-            for (ftype, fname) in self.fields:
-                fp.write('    \'("' + ftype + '" "' + fname + '")\n')
+            for (ftype, fname, getter_propname, getter_funcname) in self.fields:
+                fp.write('    \'' + field_list_print_one(ftype, fname, getter_propname, getter_funcname) + '\n')
             fp.write('  )\n')
         fp.write(')\n\n')
 
@@ -276,7 +302,7 @@ class PointerDef(Definition):
                 self.typecode = arg[1]
             elif arg[0] == 'fields':
                 for parg in arg[1:]:
-                    self.fields.append((parg[0], parg[1]))
+                    field_list_parse_one(self.fields, parg)
     def merge(self, old):
         # currently the .h parser doesn't try to work out what fields of
         # an object structure should be public, so we just copy the list
@@ -293,7 +319,7 @@ class PointerDef(Definition):
         if self.fields:
             fp.write('  (fields\n')
             for (ftype, fname) in self.fields:
-                fp.write('    \'("' + ftype + '" "' + fname + '")\n')
+                fp.write('    \'' + field_list_print_one(ftype, fname, getter_propname, getter_funcname) + '\n')
             fp.write('  )\n')
         fp.write(')\n\n')
 



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