Index: third_party/cython/src/Cython/Compiler/AutoDocTransforms.py |
diff --git a/third_party/cython/src/Cython/Compiler/AutoDocTransforms.py b/third_party/cython/src/Cython/Compiler/AutoDocTransforms.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..408ce9abb176810ea6995d0e1aea1a4b87d6bcc1 |
--- /dev/null |
+++ b/third_party/cython/src/Cython/Compiler/AutoDocTransforms.py |
@@ -0,0 +1,229 @@ |
+from Cython.Compiler.Visitor import CythonTransform |
+from Cython.Compiler.StringEncoding import EncodedString |
+from Cython.Compiler import Options |
+from Cython.Compiler import PyrexTypes, ExprNodes |
+ |
+class EmbedSignature(CythonTransform): |
+ |
+ def __init__(self, context): |
+ super(EmbedSignature, self).__init__(context) |
+ self.denv = None # XXX |
+ 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: |
+ return None |
+ try: |
+ denv = self.denv # XXX |
+ ctval = default_val.compile_time_value(self.denv) |
+ repr_val = repr(ctval) |
+ if isinstance(default_val, ExprNodes.UnicodeNode): |
+ if repr_val[:1] != 'u': |
+ return u'u%s' % repr_val |
+ elif isinstance(default_val, ExprNodes.BytesNode): |
+ if repr_val[:1] != 'b': |
+ return u'b%s' % repr_val |
+ elif isinstance(default_val, ExprNodes.StringNode): |
+ if repr_val[:1] in 'ub': |
+ return repr_val[1:] |
+ return repr_val |
+ except Exception: |
+ try: |
+ return self._fmt_expr_node(default_val) |
+ except AttributeError, e: |
+ return '<???>' |
+ |
+ def _fmt_arg(self, arg): |
+ if arg.type is PyrexTypes.py_object_type or arg.is_self_arg: |
+ doc = arg.name |
+ else: |
+ doc = arg.type.declaration_code(arg.name, for_display=1) |
+ if arg.default: |
+ arg_defv = self._fmt_arg_defv(arg) |
+ if arg_defv: |
+ doc = doc + ('=%s' % arg_defv) |
+ return doc |
+ |
+ def _fmt_arglist(self, args, |
+ npargs=0, pargs=None, |
+ nkargs=0, kargs=None, |
+ hide_self=False): |
+ arglist = [] |
+ for arg in args: |
+ if not hide_self or not arg.entry.is_self_arg: |
+ arg_doc = self._fmt_arg(arg) |
+ arglist.append(arg_doc) |
+ if pargs: |
+ arglist.insert(npargs, '*%s' % pargs.name) |
+ elif nkargs: |
+ arglist.insert(npargs, '*') |
+ if kargs: |
+ arglist.append('**%s' % kargs.name) |
+ return arglist |
+ |
+ def _fmt_ret_type(self, ret): |
+ if ret is PyrexTypes.py_object_type: |
+ return None |
+ else: |
+ return ret.declaration_code("", for_display=1) |
+ |
+ def _fmt_signature(self, cls_name, func_name, args, |
+ npargs=0, pargs=None, |
+ nkargs=0, kargs=None, |
+ return_type=None, hide_self=False): |
+ arglist = self._fmt_arglist(args, |
+ npargs, pargs, |
+ nkargs, kargs, |
+ hide_self=hide_self) |
+ arglist_doc = ', '.join(arglist) |
+ func_doc = '%s(%s)' % (func_name, arglist_doc) |
+ if cls_name: |
+ func_doc = '%s.%s' % (cls_name, func_doc) |
+ if return_type: |
+ ret_doc = self._fmt_ret_type(return_type) |
+ if ret_doc: |
+ func_doc = '%s -> %s' % (func_doc, ret_doc) |
+ return func_doc |
+ |
+ def _embed_signature(self, signature, node_doc): |
+ if node_doc: |
+ return "%s\n%s" % (signature, node_doc) |
+ else: |
+ return signature |
+ |
+ def __call__(self, node): |
+ if not Options.docstrings: |
+ return node |
+ else: |
+ return super(EmbedSignature, self).__call__(node) |
+ |
+ def visit_ClassDefNode(self, node): |
+ oldname = self.class_name |
+ oldclass = self.class_node |
+ self.class_node = node |
+ try: |
+ # PyClassDefNode |
+ self.class_name = node.name |
+ except AttributeError: |
+ # CClassDefNode |
+ self.class_name = node.class_name |
+ self.visitchildren(node) |
+ self.class_name = oldname |
+ self.class_node = oldclass |
+ return node |
+ |
+ def visit_DefNode(self, node): |
+ if not self.current_directives['embedsignature']: |
+ return node |
+ |
+ is_constructor = False |
+ hide_self = False |
+ if node.entry.is_special: |
+ is_constructor = self.class_node and node.name == '__init__' |
+ if not is_constructor: |
+ return node |
+ class_name, func_name = None, self.class_name |
+ hide_self = True |
+ else: |
+ class_name, func_name = self.class_name, node.name |
+ |
+ nkargs = getattr(node, 'num_kwonly_args', 0) |
+ npargs = len(node.args) - nkargs |
+ signature = self._fmt_signature( |
+ class_name, func_name, node.args, |
+ npargs, node.star_arg, |
+ nkargs, node.starstar_arg, |
+ return_type=None, hide_self=hide_self) |
+ if signature: |
+ if is_constructor: |
+ doc_holder = self.class_node.entry.type.scope |
+ else: |
+ doc_holder = node.entry |
+ |
+ if doc_holder.doc is not None: |
+ old_doc = doc_holder.doc |
+ elif not is_constructor and getattr(node, 'py_func', None) is not None: |
+ old_doc = node.py_func.entry.doc |
+ else: |
+ old_doc = None |
+ new_doc = self._embed_signature(signature, old_doc) |
+ doc_holder.doc = EncodedString(new_doc) |
+ if not is_constructor and getattr(node, 'py_func', None) is not None: |
+ node.py_func.entry.doc = EncodedString(new_doc) |
+ return node |
+ |
+ def visit_CFuncDefNode(self, node): |
+ if not self.current_directives['embedsignature']: |
+ return node |
+ if not node.overridable: # not cpdef FOO(...): |
+ return node |
+ |
+ signature = self._fmt_signature( |
+ self.class_name, node.declarator.base.name, |
+ node.declarator.args, |
+ return_type=node.return_type) |
+ if signature: |
+ if node.entry.doc is not None: |
+ old_doc = node.entry.doc |
+ elif getattr(node, 'py_func', None) is not None: |
+ old_doc = node.py_func.entry.doc |
+ else: |
+ old_doc = None |
+ new_doc = self._embed_signature(signature, old_doc) |
+ node.entry.doc = EncodedString(new_doc) |
+ if hasattr(node, 'py_func') and node.py_func is not None: |
+ node.py_func.entry.doc = EncodedString(new_doc) |
+ return node |
+ |
+ def visit_PropertyNode(self, node): |
+ if not self.current_directives['embedsignature']: |
+ return node |
+ |
+ entry = node.entry |
+ if entry.visibility == 'public': |
+ # property synthesised from a cdef public attribute |
+ type_name = entry.type.declaration_code("", for_display=1) |
+ if not entry.type.is_pyobject: |
+ type_name = "'%s'" % type_name |
+ elif entry.type.is_extension_type: |
+ type_name = entry.type.module_name + '.' + type_name |
+ signature = '%s: %s' % (entry.name, type_name) |
+ new_doc = self._embed_signature(signature, entry.doc) |
+ entry.doc = EncodedString(new_doc) |
+ return node |