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): ...@@ -11,6 +11,40 @@ class EmbedSignature(CythonTransform):
self.class_name = None self.class_name = None
self.class_node = 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): def _fmt_arg_defv(self, arg):
default_val = arg.default default_val = arg.default
if not default_val: if not default_val:
...@@ -31,8 +65,8 @@ class EmbedSignature(CythonTransform): ...@@ -31,8 +65,8 @@ class EmbedSignature(CythonTransform):
return repr_val return repr_val
except Exception: except Exception:
try: try:
return default_val.name # XXX return self._fmt_expr_node(default_val)
except AttributeError: except AttributeError, e:
return '<???>' return '<???>'
def _fmt_arg(self, arg): def _fmt_arg(self, arg):
...@@ -93,7 +127,6 @@ class EmbedSignature(CythonTransform): ...@@ -93,7 +127,6 @@ class EmbedSignature(CythonTransform):
else: else:
return signature return signature
def __call__(self, node): def __call__(self, node):
if not Options.docstrings: if not Options.docstrings:
return node return node
...@@ -172,8 +205,25 @@ class EmbedSignature(CythonTransform): ...@@ -172,8 +205,25 @@ class EmbedSignature(CythonTransform):
old_doc = node.py_func.entry.doc old_doc = node.py_func.entry.doc
else: else:
old_doc = None 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) node.entry.doc = EncodedString(new_doc)
if hasattr(node, 'py_func') and node.py_func is not None: if hasattr(node, 'py_func') and node.py_func is not None:
node.py_func.entry.doc = EncodedString(new_doc) node.py_func.entry.doc = EncodedString(new_doc)
return node 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): ...@@ -1204,6 +1204,8 @@ class CVarDefNode(StatNode):
self.entry = dest_scope.declare_var(name, type, declarator.pos, self.entry = dest_scope.declare_var(name, type, declarator.pos,
cname=cname, visibility=visibility, in_pxd=self.in_pxd, cname=cname, visibility=visibility, in_pxd=self.in_pxd,
api=self.api, is_cdef=1) api=self.api, is_cdef=1)
if Options.docstrings:
self.entry.doc = embed_position(self.pos, self.doc)
class CStructOrUnionDefNode(StatNode): class CStructOrUnionDefNode(StatNode):
...@@ -4288,15 +4290,15 @@ class PropertyNode(StatNode): ...@@ -4288,15 +4290,15 @@ class PropertyNode(StatNode):
# #
# name string # name string
# doc EncodedString or None Doc string # doc EncodedString or None Doc string
# entry Symtab.Entry
# body StatListNode # body StatListNode
child_attrs = ["body"] child_attrs = ["body"]
def analyse_declarations(self, env): def analyse_declarations(self, env):
entry = env.declare_property(self.name, self.doc, self.pos) self.entry = env.declare_property(self.name, self.doc, self.pos)
if entry: self.entry.scope.directives = env.directives
entry.scope.directives = env.directives self.body.analyse_declarations(self.entry.scope)
self.body.analyse_declarations(entry.scope)
def analyse_expressions(self, env): def analyse_expressions(self, env):
self.body = self.body.analyse_expressions(env) self.body = self.body.analyse_expressions(env)
......
...@@ -1800,23 +1800,7 @@ if VALUE is not None: ...@@ -1800,23 +1800,7 @@ if VALUE is not None:
attribute=entry.name), attribute=entry.name),
}, pos=entry.pos).stats[0] }, pos=entry.pos).stats[0]
property.name = entry.name property.name = entry.name
# --------------------------------------- property.doc = entry.doc
# 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)
# ---------------------------------------
return property return property
......
...@@ -2807,12 +2807,18 @@ def p_c_func_or_var_declaration(s, pos, ctx): ...@@ -2807,12 +2807,18 @@ def p_c_func_or_var_declaration(s, pos, ctx):
declarator = p_c_declarator(s, ctx, cmethod_flag = cmethod_flag, declarator = p_c_declarator(s, ctx, cmethod_flag = cmethod_flag,
assignable = 1, nonempty = 1) assignable = 1, nonempty = 1)
declarators.append(declarator) declarators.append(declarator)
doc_line = s.start_line + 1
s.expect_newline("Syntax error in C variable declaration") 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, result = Nodes.CVarDefNode(pos,
visibility = ctx.visibility, visibility = ctx.visibility,
base_type = base_type, base_type = base_type,
declarators = declarators, declarators = declarators,
in_pxd = ctx.level in ('module_pxd', 'c_class_pxd'), in_pxd = ctx.level in ('module_pxd', 'c_class_pxd'),
doc = doc,
api = ctx.api, api = ctx.api,
modifiers = modifiers, modifiers = modifiers,
overridable = ctx.overridable) overridable = ctx.overridable)
......
...@@ -1665,6 +1665,14 @@ class CBIntType(CIntType): ...@@ -1665,6 +1665,14 @@ class CBIntType(CIntType):
from_py_function = "__Pyx_PyObject_IsTrue" from_py_function = "__Pyx_PyObject_IsTrue"
exception_check = 1 # for C++ bool 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): def __repr__(self):
return "<CNumericType bint>" return "<CNumericType bint>"
......
...@@ -7,13 +7,25 @@ __doc__ = ur""" ...@@ -7,13 +7,25 @@ __doc__ = ur"""
>>> print (Ext.attr0.__doc__) >>> print (Ext.attr0.__doc__)
attr0: 'int' attr0: 'int'
attr0 docstring
>>> print (Ext.attr1.__doc__) >>> print (Ext.attr1.__doc__)
attr1: object attr1: object
attr1 docstring
>>> print (Ext.attr2.__doc__) >>> print (Ext.attr2.__doc__)
attr2: list attr2: list
>>> print (Ext.attr3.__doc__) >>> print (Ext.attr3.__doc__)
attr3: embedsignatures.Ext 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__) >>> print (Ext.a.__doc__)
Ext.a(self) Ext.a(self)
...@@ -114,6 +126,9 @@ __doc__ = ur""" ...@@ -114,6 +126,9 @@ __doc__ = ur"""
>>> print (f_si.__doc__) >>> print (f_si.__doc__)
f_si(signed int i) -> signed int f_si(signed int i) -> signed int
>>> print (f_bint.__doc__)
f_bint(bool i) -> bool
>>> print (f_l.__doc__) >>> print (f_l.__doc__)
f_l(long l) -> long f_l(long l) -> long
...@@ -150,14 +165,52 @@ __doc__ = ur""" ...@@ -150,14 +165,52 @@ __doc__ = ur"""
>>> print (f_my_f.__doc__) >>> print (f_my_f.__doc__)
f_my_f(MyFloat f) -> MyFloat 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 class Ext:
cdef public int attr0 cdef public int attr0
"""attr0 docstring"""
cdef public attr1 cdef public attr1
"""attr1 docstring"""
cdef public list attr2 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): def __init__(self, a, b, c=None):
pass pass
...@@ -270,6 +323,9 @@ cpdef unsigned int f_ui(unsigned int i): ...@@ -270,6 +323,9 @@ cpdef unsigned int f_ui(unsigned int i):
cpdef signed int f_si(signed int i): cpdef signed int f_si(signed int i):
return i return i
cpdef bint f_bint(bint i):
return i
cpdef long f_l(long l): cpdef long f_l(long l):
return l return l
...@@ -307,3 +363,22 @@ cpdef MyInt f_my_i(MyInt i): ...@@ -307,3 +363,22 @@ cpdef MyInt f_my_i(MyInt i):
ctypedef float MyFloat ctypedef float MyFloat
cpdef MyFloat f_my_f(MyFloat f): cpdef MyFloat f_my_f(MyFloat f):
return 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