1 from Cython
.Compiler
.Visitor
import CythonTransform
2 from Cython
.Compiler
.StringEncoding
import EncodedString
3 from Cython
.Compiler
import Options
4 from Cython
.Compiler
import PyrexTypes
, ExprNodes
6 class EmbedSignature(CythonTransform
):
8 def __init__(self
, context
):
9 super(EmbedSignature
, self
).__init
__(context
)
10 self
.denv
= None # XXX
11 self
.class_name
= None
12 self
.class_node
= None
19 'in': 4, 'not in': 4, 'is': 4, 'is not': 4, '<': 4, '<=': 4, '>': 4, '>=': 4, '!=': 4, '==': 4,
25 '*': 10, '/': 10, '//': 10, '%': 10,
26 # unary: '+': 11, '-': 11, '~': 11
29 def _fmt_expr_node(self
, node
, precedence
=0):
30 if isinstance(node
, ExprNodes
.BinopNode
) and not node
.inplace
:
31 new_prec
= self
.binop_precedence
.get(node
.operator
, 0)
32 result
= '%s %s %s' % (self
._fmt
_expr
_node
(node
.operand1
, new_prec
),
34 self
._fmt
_expr
_node
(node
.operand2
, new_prec
))
35 if precedence
> new_prec
:
36 result
= '(%s)' % result
37 elif isinstance(node
, ExprNodes
.UnopNode
):
38 result
= '%s%s' % (node
.operator
,
39 self
._fmt
_expr
_node
(node
.operand
, self
.unop_precedence
))
40 if precedence
> self
.unop_precedence
:
41 result
= '(%s)' % result
42 elif isinstance(node
, ExprNodes
.AttributeNode
):
43 result
= '%s.%s' % (self
._fmt
_expr
_node
(node
.obj
), node
.attribute
)
48 def _fmt_arg_defv(self
, arg
):
49 default_val
= arg
.default
53 denv
= self
.denv
# XXX
54 ctval
= default_val
.compile_time_value(self
.denv
)
55 repr_val
= repr(ctval
)
56 if isinstance(default_val
, ExprNodes
.UnicodeNode
):
57 if repr_val
[:1] != 'u':
58 return u
'u%s' % repr_val
59 elif isinstance(default_val
, ExprNodes
.BytesNode
):
60 if repr_val
[:1] != 'b':
61 return u
'b%s' % repr_val
62 elif isinstance(default_val
, ExprNodes
.StringNode
):
63 if repr_val
[:1] in 'ub':
68 return self
._fmt
_expr
_node
(default_val
)
69 except AttributeError, e
:
72 def _fmt_arg(self
, arg
):
73 if arg
.type is PyrexTypes
.py_object_type
or arg
.is_self_arg
:
76 doc
= arg
.type.declaration_code(arg
.name
, for_display
=1)
78 arg_defv
= self
._fmt
_arg
_defv
(arg
)
80 doc
= doc
+ ('=%s' % arg_defv
)
83 def _fmt_arglist(self
, args
,
89 if not hide_self
or not arg
.entry
.is_self_arg
:
90 arg_doc
= self
._fmt
_arg
(arg
)
91 arglist
.append(arg_doc
)
93 arglist
.insert(npargs
, '*%s' % pargs
.name
)
95 arglist
.insert(npargs
, '*')
97 arglist
.append('**%s' % kargs
.name
)
100 def _fmt_ret_type(self
, ret
):
101 if ret
is PyrexTypes
.py_object_type
:
104 return ret
.declaration_code("", for_display
=1)
106 def _fmt_signature(self
, cls_name
, func_name
, args
,
107 npargs
=0, pargs
=None,
108 nkargs
=0, kargs
=None,
109 return_type
=None, hide_self
=False):
110 arglist
= self
._fmt
_arglist
(args
,
114 arglist_doc
= ', '.join(arglist
)
115 func_doc
= '%s(%s)' % (func_name
, arglist_doc
)
117 func_doc
= '%s.%s' % (cls_name
, func_doc
)
119 ret_doc
= self
._fmt
_ret
_type
(return_type
)
121 func_doc
= '%s -> %s' % (func_doc
, ret_doc
)
124 def _embed_signature(self
, signature
, node_doc
):
126 return "%s\n%s" % (signature
, node_doc
)
130 def __call__(self
, node
):
131 if not Options
.docstrings
:
134 return super(EmbedSignature
, self
).__call
__(node
)
136 def visit_ClassDefNode(self
, node
):
137 oldname
= self
.class_name
138 oldclass
= self
.class_node
139 self
.class_node
= node
142 self
.class_name
= node
.name
143 except AttributeError:
145 self
.class_name
= node
.class_name
146 self
.visitchildren(node
)
147 self
.class_name
= oldname
148 self
.class_node
= oldclass
151 def visit_DefNode(self
, node
):
152 if not self
.current_directives
['embedsignature']:
155 is_constructor
= False
157 if node
.entry
.is_special
:
158 is_constructor
= self
.class_node
and node
.name
== '__init__'
159 if not is_constructor
:
161 class_name
, func_name
= None, self
.class_name
164 class_name
, func_name
= self
.class_name
, node
.name
166 nkargs
= getattr(node
, 'num_kwonly_args', 0)
167 npargs
= len(node
.args
) - nkargs
168 signature
= self
._fmt
_signature
(
169 class_name
, func_name
, node
.args
,
170 npargs
, node
.star_arg
,
171 nkargs
, node
.starstar_arg
,
172 return_type
=None, hide_self
=hide_self
)
175 doc_holder
= self
.class_node
.entry
.type.scope
177 doc_holder
= node
.entry
179 if doc_holder
.doc
is not None:
180 old_doc
= doc_holder
.doc
181 elif not is_constructor
and getattr(node
, 'py_func', None) is not None:
182 old_doc
= node
.py_func
.entry
.doc
185 new_doc
= self
._embed
_signature
(signature
, old_doc
)
186 doc_holder
.doc
= EncodedString(new_doc
)
187 if not is_constructor
and getattr(node
, 'py_func', None) is not None:
188 node
.py_func
.entry
.doc
= EncodedString(new_doc
)
191 def visit_CFuncDefNode(self
, node
):
192 if not self
.current_directives
['embedsignature']:
194 if not node
.overridable
: # not cpdef FOO(...):
197 signature
= self
._fmt
_signature
(
198 self
.class_name
, node
.declarator
.base
.name
,
199 node
.declarator
.args
,
200 return_type
=node
.return_type
)
202 if node
.entry
.doc
is not None:
203 old_doc
= node
.entry
.doc
204 elif getattr(node
, 'py_func', None) is not None:
205 old_doc
= node
.py_func
.entry
.doc
208 new_doc
= self
._embed
_signature
(signature
, old_doc
)
209 node
.entry
.doc
= EncodedString(new_doc
)
210 if hasattr(node
, 'py_func') and node
.py_func
is not None:
211 node
.py_func
.entry
.doc
= EncodedString(new_doc
)
214 def visit_PropertyNode(self
, node
):
215 if not self
.current_directives
['embedsignature']:
219 if entry
.visibility
== 'public':
220 # property synthesised from a cdef public attribute
221 type_name
= entry
.type.declaration_code("", for_display
=1)
222 if not entry
.type.is_pyobject
:
223 type_name
= "'%s'" % type_name
224 elif entry
.type.is_extension_type
:
225 type_name
= entry
.type.module_name
+ '.' + type_name
226 signature
= '%s: %s' % (entry
.name
, type_name
)
227 new_doc
= self
._embed
_signature
(signature
, entry
.doc
)
228 entry
.doc
= EncodedString(new_doc
)