Commit de5c0050 authored by scoder's avatar scoder

Merge pull request #216 from nnemkin/autodoc_improvements

Autodoc improvements
parents b87e6f85 409e24f6
......@@ -11,6 +11,40 @@ class EmbedSignature(CythonTransform):
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:
......@@ -31,8 +65,8 @@ class EmbedSignature(CythonTransform):
return repr_val
except Exception:
try:
return default_val.name # XXX
except AttributeError:
return self._fmt_expr_node(default_val)
except AttributeError, e:
return '<???>'
def _fmt_arg(self, arg):
......@@ -93,7 +127,6 @@ class EmbedSignature(CythonTransform):
else:
return signature
def __call__(self, node):
if not Options.docstrings:
return node
......@@ -172,8 +205,25 @@ class EmbedSignature(CythonTransform):
old_doc = node.py_func.entry.doc
else:
old_doc = None
new_doc = self._embed_signature(signature, old_doc)
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
......@@ -1204,6 +1204,8 @@ class CVarDefNode(StatNode):
self.entry = dest_scope.declare_var(name, type, declarator.pos,
cname=cname, visibility=visibility, in_pxd=self.in_pxd,
api=self.api, is_cdef=1)
if Options.docstrings:
self.entry.doc = embed_position(self.pos, self.doc)
class CStructOrUnionDefNode(StatNode):
......@@ -4288,15 +4290,15 @@ class PropertyNode(StatNode):
#
# name string
# doc EncodedString or None Doc string
# entry Symtab.Entry
# body StatListNode
child_attrs = ["body"]
def analyse_declarations(self, env):
entry = env.declare_property(self.name, self.doc, self.pos)
if entry:
entry.scope.directives = env.directives
self.body.analyse_declarations(entry.scope)
self.entry = env.declare_property(self.name, self.doc, self.pos)
self.entry.scope.directives = env.directives
self.body.analyse_declarations(self.entry.scope)
def analyse_expressions(self, env):
self.body = self.body.analyse_expressions(env)
......
......@@ -1800,23 +1800,7 @@ if VALUE is not None:
attribute=entry.name),
}, pos=entry.pos).stats[0]
property.name = entry.name
# ---------------------------------------
# XXX This should go to AutoDocTransforms
# ---------------------------------------
if (Options.docstrings and
self.current_directives['embedsignature']):
attr_name = entry.name
type_name = entry.type.declaration_code("", for_display=1)
default_value = ''
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
if entry.init is not None:
default_value = ' = ' + entry.init
docstring = attr_name + ': ' + type_name + default_value
property.doc = EncodedString(docstring)
# ---------------------------------------
property.doc = entry.doc
return property
......
......@@ -2807,12 +2807,18 @@ def p_c_func_or_var_declaration(s, pos, ctx):
declarator = p_c_declarator(s, ctx, cmethod_flag = cmethod_flag,
assignable = 1, nonempty = 1)
declarators.append(declarator)
doc_line = s.start_line + 1
s.expect_newline("Syntax error in C variable declaration")
if ctx.level == 'c_class' and s.start_line == doc_line:
doc = p_doc_string(s)
else:
doc = None
result = Nodes.CVarDefNode(pos,
visibility = ctx.visibility,
base_type = base_type,
declarators = declarators,
in_pxd = ctx.level in ('module_pxd', 'c_class_pxd'),
doc = doc,
api = ctx.api,
modifiers = modifiers,
overridable = ctx.overridable)
......
......@@ -1665,6 +1665,14 @@ class CBIntType(CIntType):
from_py_function = "__Pyx_PyObject_IsTrue"
exception_check = 1 # for C++ bool
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
if pyrex or for_display:
base_code = 'bool'
else:
base_code = public_decl('int', dll_linkage)
return self.base_declaration_code(base_code, entity_code)
def __repr__(self):
return "<CNumericType bint>"
......
......@@ -7,13 +7,25 @@ __doc__ = ur"""
>>> print (Ext.attr0.__doc__)
attr0: 'int'
attr0 docstring
>>> print (Ext.attr1.__doc__)
attr1: object
attr1 docstring
>>> print (Ext.attr2.__doc__)
attr2: list
>>> print (Ext.attr3.__doc__)
attr3: embedsignatures.Ext
>>> print (Ext.prop0.__doc__)
prop0 docstring
>>> print (Ext.prop1.__doc__)
None
>>> print (Ext.attr4.__doc__)
attr4 docstring
>>> print (Ext.attr5.__doc__)
attr5: 'int'
attr5 docstring
>>> print (Ext.a.__doc__)
Ext.a(self)
......@@ -114,6 +126,9 @@ __doc__ = ur"""
>>> print (f_si.__doc__)
f_si(signed int i) -> signed int
>>> print (f_bint.__doc__)
f_bint(bool i) -> bool
>>> print (f_l.__doc__)
f_l(long l) -> long
......@@ -150,14 +165,52 @@ __doc__ = ur"""
>>> print (f_my_f.__doc__)
f_my_f(MyFloat f) -> MyFloat
>>> print (f_defexpr1.__doc__)
f_defexpr1(int x=FLAG1, int y=FLAG2)
>>> print (f_defexpr2.__doc__)
f_defexpr2(int x=FLAG1 | FLAG2, y=FLAG1 & FLAG2)
>>> print (f_defexpr3.__doc__)
f_defexpr3(int x=Ext.CONST1, f=__builtins__.abs)
>>> print (f_defexpr4.__doc__)
f_defexpr4(int x=(Ext.CONST1 + FLAG1) * Ext.CONST2)
>>> print (f_defexpr5.__doc__)
f_defexpr5(int x=4)
"""
cdef class Ext:
cdef public int attr0
"""attr0 docstring"""
cdef public attr1
"""attr1 docstring"""
cdef public list attr2
cdef public Ext attr3
cdef public Ext attr3
"""NOT attr3 docstring"""
cdef int attr4
cdef public int \
attr5
"""attr5 docstring"""
CONST1, CONST2 = 1, 2
property prop0:
"""prop0 docstring"""
def __get__(self):
return self.attr0
property prop1:
def __get__(self):
return self.attr1
property attr4:
"""attr4 docstring"""
def __get__(self):
return self.attr4
def __init__(self, a, b, c=None):
pass
......@@ -270,6 +323,9 @@ cpdef unsigned int f_ui(unsigned int i):
cpdef signed int f_si(signed int i):
return i
cpdef bint f_bint(bint i):
return i
cpdef long f_l(long l):
return l
......@@ -307,3 +363,22 @@ cpdef MyInt f_my_i(MyInt i):
ctypedef float MyFloat
cpdef MyFloat f_my_f(MyFloat f):
return f
cdef enum:
FLAG1
FLAG2
cpdef f_defexpr1(int x = FLAG1, int y = FLAG2):
pass
cpdef f_defexpr2(int x = FLAG1 | FLAG2, y = FLAG1 & FLAG2):
pass
cpdef f_defexpr3(int x = Ext.CONST1, f = __builtins__.abs):
pass
cpdef f_defexpr4(int x = (Ext.CONST1 + FLAG1) * Ext.CONST2):
pass
cpdef f_defexpr5(int x = 2+2):
pass
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment