Show attribute access and binary operations in default values in autogenerated signat...
authorNikita Nemkin <nikita@nemkin.ru>
Sat, 13 Apr 2013 07:07:51 +0000 (13:07 +0600)
committerNikita Nemkin <nikita@nemkin.ru>
Sat, 13 Apr 2013 07:07:51 +0000 (13:07 +0600)
Cython/Compiler/AutoDocTransforms.py
tests/run/embedsignatures.pyx

index 2f73636..da5ebd8 100644 (file)
@@ -11,6 +11,40 @@ class EmbedSignature(CythonTransform):
         self.class_name = None
         self.class_node = None
 
+    unop_precedence = 11
+    binop_precedence = {
+        'or': 1,
+        'and': 2,
+        'not': 3,
+        'in': 4, 'not in': 4, 'is': 4, 'is not': 4, '<': 4, '<=': 4, '>': 4, '>=': 4, '!=': 4, '==': 4,
+        '|': 5,
+        '^': 6,
+        '&': 7,
+        '<<': 8, '>>': 8,
+        '+': 9, '-': 9,
+        '*': 10, '/': 10, '//': 10, '%': 10,
+        # unary: '+': 11, '-': 11, '~': 11
+        '**': 12}
+
+    def _fmt_expr_node(self, node, precedence=0):
+        if isinstance(node, ExprNodes.BinopNode) and not node.inplace:
+            new_prec = self.binop_precedence.get(node.operator, 0)
+            result = '%s %s %s' % (self._fmt_expr_node(node.operand1, new_prec),
+                                   node.operator,
+                                   self._fmt_expr_node(node.operand2, new_prec))
+            if precedence > new_prec:
+                result = '(%s)' % result
+        elif isinstance(node, ExprNodes.UnopNode):
+            result = '%s%s' % (node.operator,
+                               self._fmt_expr_node(node.operand, self.unop_precedence))
+            if precedence > self.unop_precedence:
+                result = '(%s)' % result
+        elif isinstance(node, ExprNodes.AttributeNode):
+            result = '%s.%s' % (self._fmt_expr_node(node.obj), node.attribute)
+        else:
+            result = node.name
+        return result
+
     def _fmt_arg_defv(self, arg):
         default_val = arg.default
         if not default_val:
@@ -31,8 +65,8 @@ class EmbedSignature(CythonTransform):
             return repr_val
         except Exception:
             try:
-                return default_val.name # XXX
-            except AttributeError:
+                return self._fmt_expr_node(default_val)
+            except AttributeError, e:
                 return '<???>'
 
     def _fmt_arg(self, arg):
index 0bfcdca..55ee1ae 100644 (file)
@@ -150,6 +150,17 @@ __doc__ = ur"""
     >>> print (f_my_f.__doc__)
     f_my_f(MyFloat f) -> MyFloat
 
+    >>> print (f_defexpr1.__doc__)
+    f_defexpr1(int x=FLAG1, int y=FLAG2)
+
+    >>> print (f_defexpr2.__doc__)
+    f_defexpr2(int x=FLAG1 | FLAG2, y=FLAG1 & FLAG2)
+
+    >>> print (f_defexpr3.__doc__)
+    f_defexpr3(int x=Ext.CONST1, f=__builtins__.abs)
+
+    >>> print (f_defexpr4.__doc__)
+    f_defexpr4(int x=(Ext.CONST1 + FLAG1) * Ext.CONST2)
 """
 
 cdef class Ext:
@@ -159,6 +170,8 @@ cdef class Ext:
     cdef public list attr2
     cdef public Ext  attr3
 
+    CONST1, CONST2 = 1, 2
+
     def __init__(self, a, b, c=None):
         pass
 
@@ -307,3 +320,19 @@ cpdef MyInt f_my_i(MyInt i):
 ctypedef float MyFloat
 cpdef MyFloat f_my_f(MyFloat f):
     return f
+
+cdef enum:
+    FLAG1
+    FLAG2
+
+cpdef f_defexpr1(int x = FLAG1, int y = FLAG2):
+    pass
+
+cpdef f_defexpr2(int x = FLAG1 | FLAG2, y = FLAG1 & FLAG2):
+    pass
+
+cpdef f_defexpr3(int x = Ext.CONST1, f = __builtins__.abs):
+    pass
+
+cpdef f_defexpr4(int x = (Ext.CONST1 + FLAG1) * Ext.CONST2):
+    pass