summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Pogonyshev <pogonyshev@gmx.net>2008-07-14 18:19:25 +0000
committerPaul Pogonyshev <paulp@src.gnome.org>2008-07-14 18:19:25 +0000
commiteeac05d5cbd42308c33e777aecbf00595256519d (patch)
tree3400ea9d0fb8e6b62fe317a5e77424164433d221
parent5905589cd3e35d4e1fe11f60d56560936be7ae8c (diff)
downloadpygobject-eeac05d5cbd42308c33e777aecbf00595256519d.tar.gz
pygobject-eeac05d5cbd42308c33e777aecbf00595256519d.tar.xz
pygobject-eeac05d5cbd42308c33e777aecbf00595256519d.zip
New class. (MethodDefBase.__init__): Make 'self.ret' a 'ReturnType'
2008-07-14 Paul Pogonyshev <pogonyshev@gmx.net> * codegen/definitions.py (ReturnType): New class. (MethodDefBase.__init__): Make 'self.ret' a 'ReturnType' instance, not string. Accept 'optional' flag. * codegen/argtypes.py (ArgMatcher.get_reverse_ret): Test if 'ptype' has true 'optional' attribute and copy it to 'props' then. * codegen/reversewrapper.py (ReturnType.support_optional): New class field, False by default. (GObjectReturn.support_optional, GObjectReturn.write_decl) (GObjectReturn.write_conversion): Support optional return. svn path=/trunk/; revision=796
-rw-r--r--ChangeLog12
-rw-r--r--codegen/argtypes.py11
-rw-r--r--codegen/definitions.py18
-rw-r--r--codegen/reversewrapper.py34
4 files changed, 65 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index abd0f1a..26bff50 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
2008-07-14 Paul Pogonyshev <pogonyshev@gmx.net>
+ * codegen/definitions.py (ReturnType): New class.
+ (MethodDefBase.__init__): Make 'self.ret' a 'ReturnType' instance,
+ not string. Accept 'optional' flag.
+
+ * codegen/argtypes.py (ArgMatcher.get_reverse_ret): Test if
+ 'ptype' has true 'optional' attribute and copy it to 'props' then.
+
+ * codegen/reversewrapper.py (ReturnType.support_optional): New
+ class field, False by default.
+ (GObjectReturn.support_optional, GObjectReturn.write_decl)
+ (GObjectReturn.write_conversion): Support optional return.
+
* pygobject-2.0.pc.in: Add 'codegendir' variable.
* codegen/pygtk-codegen-2.0.in: Make 'codegendir' refer to
PyGObject's codegen, not PyGTK's one --- the latter will be
diff --git a/codegen/argtypes.py b/codegen/argtypes.py
index 061c6f8..9230193 100644
--- a/codegen/argtypes.py
+++ b/codegen/argtypes.py
@@ -917,10 +917,19 @@ class ArgMatcher:
return registry['GBoxed'], props
else:
raise ArgTypeNotFoundError("No ArgType for %s" % (ptype,))
+
def get_reverse(self, ptype):
return self._get_reverse_common(ptype, self.reverse_argtypes)
+
def get_reverse_ret(self, ptype):
- return self._get_reverse_common(ptype, self.reverse_rettypes)
+ ret, props = self._get_reverse_common(ptype, self.reverse_rettypes)
+ if hasattr(ptype, 'optional') and ptype.optional:
+ if ret.supports_optional:
+ props['optional'] = True
+ else:
+ raise ArgTypeNotFoundError("Unsupported 'optional' for %s"
+ % (ptype,))
+ return ret, props
def object_is_a(self, otype, parent):
if otype == None: return 0
diff --git a/codegen/definitions.py b/codegen/definitions.py
index 617bcbe..5da488b 100644
--- a/codegen/definitions.py
+++ b/codegen/definitions.py
@@ -31,6 +31,17 @@ class Parameter(object):
if old.pnull is not None:
self.pnull = old.pnull
+# We currently subclass 'str' to make impact on the rest of codegen as
+# little as possible. Later we can subclass 'object' instead, but
+# then we must find and adapt all places which expect return types to
+# be strings.
+class ReturnType(str):
+ def __new__(cls, *args, **kwds):
+ return str.__new__(cls, *args[:1])
+ def __init__(self, type_name, optional=False):
+ str.__init__(self, type_name)
+ self.optional = optional
+
# Parameter for property based constructors
class Property(object):
def __init__(self, pname, optional, argname):
@@ -297,7 +308,12 @@ class MethodDefBase(Definition):
elif arg[0] == 'gtype-id':
self.typecode = arg[1]
elif arg[0] == 'return-type':
- self.ret = arg[1]
+ type_name = arg[1]
+ optional = False
+ for prop in arg[2:]:
+ if prop[0] == 'optional':
+ optional = True
+ self.ret = ReturnType(type_name, optional)
elif arg[0] == 'caller-owns-return':
self.caller_owns_return = arg[1] in ('t', '#t')
elif arg[0] == 'unblock-threads':
diff --git a/codegen/reversewrapper.py b/codegen/reversewrapper.py
index ffd50ec..ed48629 100644
--- a/codegen/reversewrapper.py
+++ b/codegen/reversewrapper.py
@@ -359,6 +359,8 @@ class TypeHandler(object):
class ReturnType(TypeHandler):
+ supports_optional = False
+
def get_c_type(self):
raise NotImplementedError
@@ -479,23 +481,39 @@ argtypes.matcher.register_reverse('GObject*', GObjectParam)
class GObjectReturn(ReturnType):
+ supports_optional = True
+
def get_c_type(self):
return self.props.get('c_type', 'GObject *')
def write_decl(self):
- self.wrapper.add_declaration("%s retval;" % self.get_c_type())
+ if not self.props.get('optional'):
+ self.wrapper.add_declaration("%s retval;" % self.get_c_type())
+ else:
+ self.wrapper.add_declaration("%s retval = NULL;" % self.get_c_type())
def write_error_return(self):
self.wrapper.write_code("return NULL;")
def write_conversion(self):
- self.wrapper.write_code(
- code=None,
- failure_expression="!PyObject_TypeCheck(py_retval, &PyGObject_Type)",
- failure_exception='PyErr_SetString(PyExc_TypeError, "retval should be a GObject");')
- self.wrapper.write_code("retval = (%s) pygobject_get(py_retval);"
- % self.get_c_type())
- self.wrapper.write_code("g_object_ref((GObject *) retval);")
+ if not self.props.get('optional'):
+ self.wrapper.write_code(
+ code=None,
+ failure_expression="!PyObject_TypeCheck(py_retval, &PyGObject_Type)",
+ failure_exception='PyErr_SetString(PyExc_TypeError, "retval should be a GObject");')
+ self.wrapper.write_code("retval = (%s) pygobject_get(py_retval);"
+ % self.get_c_type())
+ self.wrapper.write_code("g_object_ref((GObject *) retval);")
+ else:
+ self.wrapper.write_code(
+ code=None,
+ failure_expression="py_retval != Py_None && !PyObject_TypeCheck(py_retval, &PyGObject_Type)",
+ failure_exception='PyErr_SetString(PyExc_TypeError, "retval should be None or a GObject");')
+ self.wrapper.write_code("if (py_retval != Py_None) {\n"
+ " retval = (%s) pygobject_get(py_retval);\n"
+ " g_object_ref((GObject *) retval);\n"
+ "}\n"
+ % self.get_c_type())
argtypes.matcher.register_reverse_ret('GObject*', GObjectReturn)