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
......@@ -177,3 +210,20 @@ class EmbedSignature(CythonTransform):
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,15 +165,53 @@ __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
"""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