summaryrefslogtreecommitdiff
path: root/Cython/Compiler/AutoDocTransforms.py
diff options
context:
space:
mode:
Diffstat (limited to 'Cython/Compiler/AutoDocTransforms.py')
-rw-r--r--Cython/Compiler/AutoDocTransforms.py68
1 files changed, 54 insertions, 14 deletions
diff --git a/Cython/Compiler/AutoDocTransforms.py b/Cython/Compiler/AutoDocTransforms.py
index d3c0a1d0d..6c342f7ef 100644
--- a/Cython/Compiler/AutoDocTransforms.py
+++ b/Cython/Compiler/AutoDocTransforms.py
@@ -3,18 +3,48 @@ from __future__ import absolute_import, print_function
from .Visitor import CythonTransform
from .StringEncoding import EncodedString
from . import Options
-from . import PyrexTypes, ExprNodes
+from . import PyrexTypes
from ..CodeWriter import ExpressionWriter
+from .Errors import warning
class AnnotationWriter(ExpressionWriter):
+ """
+ A Cython code writer for Python expressions in argument/variable annotations.
+ """
+ def __init__(self, description=None):
+ """description is optional. If specified it is used in
+ warning messages for the nodes that don't convert to string properly.
+ If not specified then no messages are generated.
+ """
+ ExpressionWriter.__init__(self)
+ self.description = description
+ self.incomplete = False
def visit_Node(self, node):
self.put(u"<???>")
+ self.incomplete = True
+ if self.description:
+ warning(node.pos,
+ "Failed to convert code to string representation in {0}".format(
+ self.description), level=1)
def visit_LambdaNode(self, node):
# XXX Should we do better?
self.put("<lambda>")
+ self.incomplete = True
+ if self.description:
+ warning(node.pos,
+ "Failed to convert lambda to string representation in {0}".format(
+ self.description), level=1)
+
+ def visit_UnicodeNode(self, node):
+ # Discard Unicode prefix in annotations. Any tool looking at them
+ # would probably expect Py3 string semantics.
+ self.emit_string(node, "")
+
+ def visit_AnnotationNode(self, node):
+ self.put(node.string.unicode_value)
class EmbedSignature(CythonTransform):
@@ -25,6 +55,12 @@ class EmbedSignature(CythonTransform):
self.class_node = None
def _fmt_expr(self, node):
+ writer = ExpressionWriter()
+ result = writer.write(node)
+ # print(type(node).__name__, '-->', result)
+ return result
+
+ def _fmt_annotation(self, node):
writer = AnnotationWriter()
result = writer.write(node)
# print(type(node).__name__, '-->', result)
@@ -37,7 +73,7 @@ class EmbedSignature(CythonTransform):
doc = arg.type.declaration_code(arg.name, for_display=1)
if arg.annotation:
- annotation = self._fmt_expr(arg.annotation)
+ annotation = self._fmt_annotation(arg.annotation)
doc = doc + (': %s' % annotation)
if arg.default:
default = self._fmt_expr(arg.default)
@@ -50,12 +86,12 @@ class EmbedSignature(CythonTransform):
def _fmt_star_arg(self, arg):
arg_doc = arg.name
if arg.annotation:
- annotation = self._fmt_expr(arg.annotation)
+ annotation = self._fmt_annotation(arg.annotation)
arg_doc = arg_doc + (': %s' % annotation)
return arg_doc
def _fmt_arglist(self, args,
- npargs=0, pargs=None,
+ npoargs=0, npargs=0, pargs=None,
nkargs=0, kargs=None,
hide_self=False):
arglist = []
@@ -65,9 +101,11 @@ class EmbedSignature(CythonTransform):
arglist.append(arg_doc)
if pargs:
arg_doc = self._fmt_star_arg(pargs)
- arglist.insert(npargs, '*%s' % arg_doc)
+ arglist.insert(npargs + npoargs, '*%s' % arg_doc)
elif nkargs:
- arglist.insert(npargs, '*')
+ arglist.insert(npargs + npoargs, '*')
+ if npoargs:
+ arglist.insert(npoargs, '/')
if kargs:
arg_doc = self._fmt_star_arg(kargs)
arglist.append('**%s' % arg_doc)
@@ -80,12 +118,12 @@ class EmbedSignature(CythonTransform):
return ret.declaration_code("", for_display=1)
def _fmt_signature(self, cls_name, func_name, args,
- npargs=0, pargs=None,
+ npoargs=0, npargs=0, pargs=None,
nkargs=0, kargs=None,
return_expr=None,
return_type=None, hide_self=False):
arglist = self._fmt_arglist(args,
- npargs, pargs,
+ npoargs, npargs, pargs,
nkargs, kargs,
hide_self=hide_self)
arglist_doc = ', '.join(arglist)
@@ -94,7 +132,7 @@ class EmbedSignature(CythonTransform):
func_doc = '%s.%s' % (cls_name, func_doc)
ret_doc = None
if return_expr:
- ret_doc = self._fmt_expr(return_expr)
+ ret_doc = self._fmt_annotation(return_expr)
elif return_type:
ret_doc = self._fmt_ret_type(return_type)
if ret_doc:
@@ -147,11 +185,12 @@ class EmbedSignature(CythonTransform):
else:
class_name, func_name = self.class_name, node.name
+ npoargs = getattr(node, 'num_posonly_args', 0)
nkargs = getattr(node, 'num_kwonly_args', 0)
- npargs = len(node.args) - nkargs
+ npargs = len(node.args) - nkargs - npoargs
signature = self._fmt_signature(
class_name, func_name, node.args,
- npargs, node.star_arg,
+ npoargs, npargs, node.star_arg,
nkargs, node.starstar_arg,
return_expr=node.return_type_annotation,
return_type=None, hide_self=hide_self)
@@ -176,7 +215,7 @@ class EmbedSignature(CythonTransform):
def visit_CFuncDefNode(self, node):
if not self.current_directives['embedsignature']:
return node
- if not node.overridable: # not cpdef FOO(...):
+ if not node.overridable: # not cpdef FOO(...):
return node
signature = self._fmt_signature(
@@ -192,8 +231,9 @@ class EmbedSignature(CythonTransform):
old_doc = None
new_doc = self._embed_signature(signature, old_doc)
node.entry.doc = EncodedString(new_doc)
- if hasattr(node, 'py_func') and node.py_func is not None:
- node.py_func.entry.doc = EncodedString(new_doc)
+ py_func = getattr(node, 'py_func', None)
+ if py_func is not None:
+ py_func.entry.doc = EncodedString(new_doc)
return node
def visit_PropertyNode(self, node):