Cython has moved to github.
cython-devel
view Cython/Compiler/AutoDocTransforms.py @ 1159:d115fd6ed2df
Signature embedding: Proper display of native types (#2).
| author | LisandroDalcin |
|---|---|
| date | Sat Sep 20 13:34:03 2008 +0200 (3 years ago) |
| parents | 137cca05a493 |
| children | 947f6697b088 |
line source
1 import re
3 from Cython.Compiler.Visitor import CythonTransform
4 from Cython.Compiler.Nodes import DefNode, CFuncDefNode
5 from Cython.Compiler.Errors import CompileError
6 from Cython.Compiler.StringEncoding import EncodedString
7 from Cython.Compiler import Options
10 class EmbedSignature(CythonTransform):
12 SPECIAL_METHOD_RE = re.compile(r'__\w+__')
14 def __init__(self, context):
15 super(EmbedSignature, self).__init__(context)
16 self.denv = None # XXX
17 self.is_in_class = False
18 self.class_name = None
20 def _fmt_basic_c_type_modifiers(self, ctype):
21 longness = ctype.longness
22 modifiers = ''
23 if longness < 0:
24 modifiers = 'short '
25 elif longness > 0:
26 modifiers = 'long ' * longness
27 signed = ctype.signed
28 if signed == 0:
29 modifiers = 'unsigned ' + modifiers
30 elif signed == 2:
31 modifiers = 'signed ' + modifiers
32 return modifiers[:-1] # strip final space
34 def _fmt_arg_type(self, arg):
35 try:
36 base_type = arg.base_type
37 arg_type = base_type.name
38 except AttributeError:
39 return ''
40 if base_type.is_basic_c_type:
41 modifiers = self._fmt_basic_c_type_modifiers(base_type)
42 if modifiers:
43 arg_type = '%s %s' % (modifiers, arg_type)
44 return arg_type
46 def _fmt_arg_name(self, arg):
47 try:
48 return arg.declarator.name
49 except AttributeError:
50 return arg.declarator.base.name
52 def _fmt_arg_defv(self, arg):
53 if not arg.default:
54 return None
55 try:
56 denv = self.denv # XXX
57 ctval = arg.default.compile_time_value(self.denv)
58 return '%s' % ctval
59 except Exception:
60 try:
61 return arg.default.name # XXX
62 except AttributeError:
63 return '<???>'
65 def _fmt_arg(self, arg):
66 arg_type = self._fmt_arg_type(arg)
67 arg_name = self._fmt_arg_name(arg)
68 arg_defv = self._fmt_arg_defv(arg)
69 doc = arg_name
70 if arg_type:
71 doc = ('%s ' % arg_type) + doc
72 if arg_defv:
73 doc = doc + ('=%s' % arg_defv)
74 return doc
76 def _fmt_arglist(self, args,
77 npargs=0, pargs=None,
78 nkargs=0, kargs=None):
79 arglist = []
80 for arg in args:
81 arg_doc = self._fmt_arg(arg)
82 arglist.append(arg_doc)
83 if pargs:
84 arglist.insert(npargs, '*%s' % pargs.name)
85 elif nkargs:
86 arglist.insert(npargs, '*')
87 if kargs:
88 arglist.append('**%s' % kargs.name)
89 return arglist
91 def _fmt_ret_type(self, ret):
92 ret_type = ret.name
93 if ret_type is None:
94 return ''
95 modifiers = self._fmt_basic_c_type_modifiers(ret)
96 if modifiers:
97 ret_type = '%s %s' % (modifiers, ret_type)
98 return ret_type
100 def _fmt_signature(self, cls_name, func_name, args,
101 npargs=0, pargs=None,
102 nkargs=0, kargs=None,
103 return_type=None):
104 arglist = self._fmt_arglist(args,
105 npargs, pargs,
106 nkargs, kargs)
107 arglist_doc = ', '.join(arglist)
108 func_doc = '%s(%s)' % (func_name, arglist_doc)
109 if cls_name:
110 func_doc = '%s.%s' % (cls_name, func_doc)
111 if return_type:
112 ret_doc = self._fmt_ret_type(return_type)
113 if ret_doc:
114 func_doc = '%s -> %s' % (func_doc, ret_doc)
115 return func_doc
117 def _embed_signature(self, signature, node_doc):
118 if node_doc:
119 return signature + '\n' + node_doc
120 else:
121 return signature
124 def __call__(self, node):
125 if not Options.docstrings:
126 return node
127 else:
128 self.visitchildren(node)
129 return node
131 def visit_ClassDefNode(self, node):
132 oldincls = self.is_in_class
133 oldname = self.class_name
134 self.is_in_class = True
135 try:
136 # PyClassDefNode
137 self.class_name = node.name
138 except AttributeError:
139 # CClassDefNode
140 self.class_name = node.class_name
141 self.visitchildren(node)
142 self.is_in_class = oldincls
143 self.class_name = oldname
144 return node
146 def visit_FuncDefNode(self, node):
147 if not node.options['embedsignature']:
148 return node
150 signature = None
151 if type(node) is DefNode: # def FOO(...):
152 special_method = (self.is_in_class and \
153 self.SPECIAL_METHOD_RE.match(node.name))
154 if not special_method:
155 nkargs = getattr(node, 'num_kwonly_args', 0)
156 npargs = len(node.args) - nkargs
157 signature = self._fmt_signature(
158 self.class_name, node.name, node.args,
159 npargs, node.star_arg,
160 nkargs, node.starstar_arg,
161 return_type=None)
162 elif type(node) is CFuncDefNode:
163 if node.overridable: # cpdef FOO(...):
164 signature = self._fmt_signature(
165 self.class_name, node.declarator.base.name,
166 node.declarator.args,
167 return_type=node.base_type)
168 else: # should not fall here ...
169 assert False
170 if signature:
171 new_doc = self._embed_signature(signature, node.doc)
172 node.doc = EncodedString(new_doc) # XXX
173 return node
