From bb08f81247eb9a7700fe47e533add0141fc4bbb0 Mon Sep 17 00:00:00 2001 From: Nikita Nemkin Date: Sat, 13 Apr 2013 17:55:42 +0600 Subject: [PATCH] Attribute docstrings support for cdef public attributes. --- Cython/Compiler/AutoDocTransforms.py | 20 +++++++++++++++++-- Cython/Compiler/Nodes.py | 10 ++++++---- Cython/Compiler/ParseTreeTransforms.py | 18 +---------------- Cython/Compiler/Parsing.py | 8 ++++++++ tests/errors/w_attr_docstrings.pyx | 26 +++++++++++++++++++++++++ tests/run/embedsignatures.pyx | 35 ++++++++++++++++++++++++++++++++++ 6 files changed, 94 insertions(+), 23 deletions(-) create mode 100644 tests/errors/w_attr_docstrings.pyx diff --git a/Cython/Compiler/AutoDocTransforms.py b/Cython/Compiler/AutoDocTransforms.py index da5ebd8..408ce9a 100644 --- a/Cython/Compiler/AutoDocTransforms.py +++ b/Cython/Compiler/AutoDocTransforms.py @@ -127,7 +127,6 @@ class EmbedSignature(CythonTransform): else: return signature - def __call__(self, node): if not Options.docstrings: return node @@ -206,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 diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 6c14241..8a1bb57 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -1202,6 +1202,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): @@ -4286,15 +4288,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) diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index a168790..405fb7c 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -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 diff --git a/Cython/Compiler/Parsing.py b/Cython/Compiler/Parsing.py index 86006d0..fb8d908 100644 --- a/Cython/Compiler/Parsing.py +++ b/Cython/Compiler/Parsing.py @@ -2808,11 +2808,19 @@ def p_c_func_or_var_declaration(s, pos, ctx): assignable = 1, nonempty = 1) declarators.append(declarator) s.expect_newline("Syntax error in C variable declaration") + if ctx.level == 'c_class': + doc_pos = s.position() + doc = p_doc_string(s) + if doc and ctx.visibility not in ('public', 'readonly'): + warning(doc_pos, "Private attributes don't support docstrings.", 1) + 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) diff --git a/tests/errors/w_attr_docstrings.pyx b/tests/errors/w_attr_docstrings.pyx new file mode 100644 index 0000000..252dfea --- /dev/null +++ b/tests/errors/w_attr_docstrings.pyx @@ -0,0 +1,26 @@ +# mode: error +# tag: werror + +cdef class A: + cdef a + """docstring""" + + cdef int b + """docstring""" + + cdef public c + """docstring""" + + cdef public dict d + """docstring""" + + cdef readonly e + """docstring""" + + cdef readonly list e + """docstring""" + +_ERRORS = """ +6:4: Private attributes don't support docstrings. +9:4: Private attributes don't support docstrings. +""" diff --git a/tests/run/embedsignatures.pyx b/tests/run/embedsignatures.pyx index 55ee1ae..e931241 100644 --- a/tests/run/embedsignatures.pyx +++ b/tests/run/embedsignatures.pyx @@ -7,13 +7,24 @@ __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 docstring + >>> print (Ext.a.__doc__) Ext.a(self) @@ -166,12 +177,36 @@ __doc__ = ur""" cdef class Ext: cdef public int attr0 + """attr0 docstring""" cdef public attr1 + """attr1 docstring""" cdef public list attr2 cdef public Ext attr3 + cdef int attr4 + cdef attr5 + """private 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 + + property attr5: + """attr5 docstring""" + def __get__(self): + return self.attr4 + def __init__(self, a, b, c=None): pass -- 2.7.4