Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / third_party / cython / src / Cython / Compiler / AutoDocTransforms.py
blob408ce9abb176810ea6995d0e1aea1a4b87d6bcc1
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
14 unop_precedence = 11
15 binop_precedence = {
16 'or': 1,
17 'and': 2,
18 'not': 3,
19 'in': 4, 'not in': 4, 'is': 4, 'is not': 4, '<': 4, '<=': 4, '>': 4, '>=': 4, '!=': 4, '==': 4,
20 '|': 5,
21 '^': 6,
22 '&': 7,
23 '<<': 8, '>>': 8,
24 '+': 9, '-': 9,
25 '*': 10, '/': 10, '//': 10, '%': 10,
26 # unary: '+': 11, '-': 11, '~': 11
27 '**': 12}
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),
33 node.operator,
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)
44 else:
45 result = node.name
46 return result
48 def _fmt_arg_defv(self, arg):
49 default_val = arg.default
50 if not default_val:
51 return None
52 try:
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':
64 return repr_val[1:]
65 return repr_val
66 except Exception:
67 try:
68 return self._fmt_expr_node(default_val)
69 except AttributeError, e:
70 return '<???>'
72 def _fmt_arg(self, arg):
73 if arg.type is PyrexTypes.py_object_type or arg.is_self_arg:
74 doc = arg.name
75 else:
76 doc = arg.type.declaration_code(arg.name, for_display=1)
77 if arg.default:
78 arg_defv = self._fmt_arg_defv(arg)
79 if arg_defv:
80 doc = doc + ('=%s' % arg_defv)
81 return doc
83 def _fmt_arglist(self, args,
84 npargs=0, pargs=None,
85 nkargs=0, kargs=None,
86 hide_self=False):
87 arglist = []
88 for arg in 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)
92 if pargs:
93 arglist.insert(npargs, '*%s' % pargs.name)
94 elif nkargs:
95 arglist.insert(npargs, '*')
96 if kargs:
97 arglist.append('**%s' % kargs.name)
98 return arglist
100 def _fmt_ret_type(self, ret):
101 if ret is PyrexTypes.py_object_type:
102 return None
103 else:
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,
111 npargs, pargs,
112 nkargs, kargs,
113 hide_self=hide_self)
114 arglist_doc = ', '.join(arglist)
115 func_doc = '%s(%s)' % (func_name, arglist_doc)
116 if cls_name:
117 func_doc = '%s.%s' % (cls_name, func_doc)
118 if return_type:
119 ret_doc = self._fmt_ret_type(return_type)
120 if ret_doc:
121 func_doc = '%s -> %s' % (func_doc, ret_doc)
122 return func_doc
124 def _embed_signature(self, signature, node_doc):
125 if node_doc:
126 return "%s\n%s" % (signature, node_doc)
127 else:
128 return signature
130 def __call__(self, node):
131 if not Options.docstrings:
132 return node
133 else:
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
140 try:
141 # PyClassDefNode
142 self.class_name = node.name
143 except AttributeError:
144 # CClassDefNode
145 self.class_name = node.class_name
146 self.visitchildren(node)
147 self.class_name = oldname
148 self.class_node = oldclass
149 return node
151 def visit_DefNode(self, node):
152 if not self.current_directives['embedsignature']:
153 return node
155 is_constructor = False
156 hide_self = False
157 if node.entry.is_special:
158 is_constructor = self.class_node and node.name == '__init__'
159 if not is_constructor:
160 return node
161 class_name, func_name = None, self.class_name
162 hide_self = True
163 else:
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)
173 if signature:
174 if is_constructor:
175 doc_holder = self.class_node.entry.type.scope
176 else:
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
183 else:
184 old_doc = None
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)
189 return node
191 def visit_CFuncDefNode(self, node):
192 if not self.current_directives['embedsignature']:
193 return node
194 if not node.overridable: # not cpdef FOO(...):
195 return node
197 signature = self._fmt_signature(
198 self.class_name, node.declarator.base.name,
199 node.declarator.args,
200 return_type=node.return_type)
201 if signature:
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
206 else:
207 old_doc = None
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)
212 return node
214 def visit_PropertyNode(self, node):
215 if not self.current_directives['embedsignature']:
216 return node
218 entry = node.entry
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)
229 return node