[gobject-introspection/wip/nielsdg/python-formatter-out-params] docwriter: Fix (out) arguments for Python




commit bdc5f027d1ab4b1ba8735dc7edc27e550780974a
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Sun Dec 27 17:14:19 2020 +0100

    docwriter: Fix (out) arguments for Python
    
    The documentation formatter for Python3 doesn't properly deal with
    `(out)` arguments, which leads to those being added as function
    arguments, rather than return values. This commit fixes that by mostly
    copying the logic from the GJS formatter.
    
    For future work, it might be worth looking into whether Python type
    annotations can be used to add types to arguments.
    
    Fixes https://gitlab.gnome.org/GNOME/gobject-introspection/-/issues/235

 .../doctemplates/mallard/Python/function.tmpl      | 10 ++---
 giscanner/docwriter.py                             | 52 +++++++++++++++++++++-
 2 files changed, 56 insertions(+), 6 deletions(-)
---
diff --git a/giscanner/doctemplates/mallard/Python/function.tmpl 
b/giscanner/doctemplates/mallard/Python/function.tmpl
index 7ad1ac04..10481a35 100644
--- a/giscanner/doctemplates/mallard/Python/function.tmpl
+++ b/giscanner/doctemplates/mallard/Python/function.tmpl
@@ -23,7 +23,7 @@
 % if formatter.get_in_parameters(node):
 @accepts(${', '.join((formatter.format_type(arg.type) for arg in formatter.get_in_parameters(node)))})
 % endif
-@returns(${formatter.format_type(node.retval.type) | x})
+@returns(${', '.join((formatter.format_type(arg.type) for arg in formatter.get_out_parameters(node)))})
 def ${node.name}(${', '.join((formatter.format_parameter_name(node, arg) for arg in 
formatter.get_in_parameters(node)))}):
     # Python wrapper for ${node.symbol}()
   </code></synopsis></%block>
@@ -36,12 +36,12 @@ def ${node.name}(${', '.join((formatter.format_parameter_name(node, arg) for arg
 ${formatter.format(node, arg.doc)}
 </item>
 % endfor
-% if node.retval and node.retval.type.ctype != 'void':
+% for arg in formatter.get_out_parameters(node):
 <item>
-<title><code>Returns</code></title>
-{formatter.format(node, node.retval.doc)}
+<title><code>${(arg.argname + ' (out)')}</code></title>
+${formatter.format(node, arg.doc)}
 </item>
-% endif
+% endfor
 </terms>
 % endif
 </%block>
diff --git a/giscanner/docwriter.py b/giscanner/docwriter.py
index 786da80d..280d1ae8 100644
--- a/giscanner/docwriter.py
+++ b/giscanner/docwriter.py
@@ -810,7 +810,57 @@ class DocFormatterPython(DocFormatterIntrospectableBase):
             return func.name
 
     def get_in_parameters(self, node):
-        return node.all_parameters
+        skip = set()
+        for param in node.parameters:
+            if param.direction == ast.PARAM_DIRECTION_OUT:
+                skip.add(param)
+            if param.closure_name is not None:
+                skip.add(node.get_parameter(param.closure_name))
+            if param.destroy_name is not None:
+                skip.add(node.get_parameter(param.destroy_name))
+            if isinstance(param.type, ast.Array) and param.type.length_param_name is not None:
+                skip.add(node.get_parameter(param.type.length_param_name))
+
+        params = []
+        for param in node.parameters:
+            if param not in skip:
+                params.append(param)
+        return params
+
+    def get_out_parameters(self, node):
+        # First make a list of parameters we should skip anyhow
+        skip = set()
+        for param in node.parameters:
+            if param.direction == ast.PARAM_DIRECTION_IN:
+                skip.add(param)
+            if param.closure_name is not None:
+                skip.add(node.get_parameter(param.closure_name))
+            if param.destroy_name is not None:
+                skip.add(node.get_parameter(param.destroy_name))
+            if isinstance(param.type, ast.Array) and param.type.length_param_name is not None:
+                skip.add(node.get_parameter(param.type.length_param_name))
+
+        # Now build the actual list of out parameters
+        params = []
+        # First the return value
+        if node.retval.type.target_fundamental != 'none':
+            name = 'return_value'
+            if node.retval.type.target_fundamental == 'gboolean':
+                name = 'ok'
+
+            ret_param = ast.Parameter(name, node.retval.type,
+                                      ast.PARAM_DIRECTION_OUT)
+            ret_param.doc = node.retval.doc
+            params.append(ret_param)
+        # Next, each parameter marked as (out)
+        for param in node.parameters:
+            if param not in skip:
+                params.append(param)
+
+        if len(params) == 1:
+            params[0].argname = 'Returns'
+
+        return params
 
 
 class DocFormatterGjs(DocFormatterIntrospectableBase):


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