Cython has moved to github.

cython-devel

view Cython/Compiler/AutoDocTransforms.py @ 1157:075511424c24

Automatic embedding of signatures in docstring (#2)
author LisandroDalcin
date Fri Sep 19 16:28:36 2008 +0200 (3 years ago)
parents
children 137cca05a493
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_arg_type(self, arg):
21 try:
22 return arg.base_type.name
23 except AttributeError:
24 return ""
26 def _fmt_arg_name(self, arg):
27 try:
28 return arg.declarator.name
29 except AttributeError:
30 return arg.declarator.base.name
32 def _fmt_arg_defv(self, arg):
33 if not arg.default:
34 return None
35 try:
36 denv = self.denv # XXX
37 ctval = arg.default.compile_time_value(self.denv)
38 return '%s' % ctval
39 except Exception:
40 try:
41 return arg.default.name # XXX
42 except AttributeError:
43 return '<???>'
45 def _fmt_arg(self, arg):
46 arg_type = self._fmt_arg_type(arg)
47 arg_name = self._fmt_arg_name(arg)
48 arg_defv = self._fmt_arg_defv(arg)
49 doc = arg_name
50 if arg_type:
51 doc = ('%s ' % arg_type) + doc
52 if arg_defv:
53 doc = doc + ('=%s' % arg_defv)
54 return doc
56 def _fmt_arglist(self, args,
57 npargs=0, pargs=None,
58 nkargs=0, kargs=None):
59 arglist = []
60 for arg in args:
61 arg_doc = self._fmt_arg(arg)
62 arglist.append(arg_doc)
63 if pargs:
64 arglist.insert(npargs, '*%s' % pargs.name)
65 elif nkargs:
66 arglist.insert(npargs, '*')
67 if kargs:
68 arglist.append('**%s' % kargs.name)
69 return arglist
71 def _fmt_signature(self, cls_name, func_name, args,
72 npargs=0, pargs=None,
73 nkargs=0, kargs=None,
74 return_type=None):
75 arglist = self._fmt_arglist(args,
76 npargs, pargs,
77 nkargs, kargs)
78 arglist = ', '.join(arglist)
79 func_doc = '%s(%s)' % (func_name, arglist)
80 if cls_name:
81 func_doc = ('%s.' % cls_name) + func_doc
82 if return_type:
83 func_doc = func_doc + ' -> %s' % return_type
84 return func_doc
86 def _embed_signature(self, signature, node_doc):
87 if node_doc:
88 return signature + '\n' + node_doc
89 else:
90 return signature
92 def visit_ClassDefNode(self, node):
93 oldincls = self.is_in_class
94 oldname = self.class_name
95 self.is_in_class = True
96 try:
97 # PyClassDefNode
98 self.class_name = node.name
99 except AttributeError:
100 # CClassDefNode
101 self.class_name = node.class_name
102 self.visitchildren(node)
103 self.is_in_class = oldincls
104 self.class_name = oldname
105 return node
107 def visit_FuncDefNode(self, node):
108 signature = None
109 if type(node) is DefNode: # def FOO(...):
110 special_method = (self.is_in_class and \
111 self.SPECIAL_METHOD_RE.match(node.name))
112 if not special_method:
113 nkargs = getattr(node, 'num_kwonly_args', 0)
114 npargs = len(node.args) - nkargs
115 signature = self._fmt_signature(
116 self.class_name, node.name, node.args,
117 npargs, node.star_arg,
118 nkargs, node.starstar_arg,
119 return_type=None)
120 elif type(node) is CFuncDefNode:
121 if node.overridable: # cpdef FOO(...):
122 signature = self._fmt_signature(
123 self.class_name, node.declarator.base.name,
124 node.declarator.args,
125 return_type=node.base_type.name)
126 else: # should not fall here ...
127 assert False
128 if signature:
129 if Options.docstrings and node.options['embedsignature']:
130 new_doc = self._embed_signature(signature, node.doc)
131 node.doc = EncodedString(new_doc) # XXX
132 return node