Commit bb32de01 authored by Stefan Behnel's avatar Stefan Behnel

Make "__doc__" available to the class body if it has a docstring.

Closes #1635.
parent 580984ec
......@@ -47,6 +47,9 @@ Bugs fixed
as integer 0 instead of the expected float value.
Patch by Kryštof Pilnáček. (Github issue #2133)
* ``__doc__`` was not available inside of the class body during class creation.
(Github issue #1635)
* Setting ``language_level=2`` in a file did not work if ``language_level=3``
was enabled globally before.
Patch by Jeroen Demeyer. (Github issue #2791)
......
......@@ -1300,6 +1300,8 @@ class ControlFlowAnalysis(CythonTransform):
self.env_stack.append(self.env)
self.env = node.scope
self.flow.nextblock()
if node.doc_node:
self.flow.mark_assignment(node.doc_node, fake_rhs_expr, node.doc_node.entry)
self.visitchildren(node, ('body',))
self.flow.nextblock()
self.env = self.env_stack.pop()
......
......@@ -4429,7 +4429,7 @@ class PyClassDefNode(ClassDefNode):
# A Python class definition.
#
# name EncodedString Name of the class
# doc string or None
# doc string or None The class docstring
# body StatNode Attribute definition code
# entry Symtab.Entry
# scope PyClassScope
......@@ -4437,17 +4437,19 @@ class PyClassDefNode(ClassDefNode):
#
# The following subnodes are constructed internally:
#
# doc_node NameNode '__doc__' name that is made available to the class body
# dict DictNode Class dictionary or Py3 namespace
# classobj ClassNode Class object
# target NameNode Variable to assign class object to
child_attrs = ["body", "dict", "metaclass", "mkw", "bases", "class_result",
child_attrs = ["doc_node", "body", "dict", "metaclass", "mkw", "bases", "class_result",
"target", "class_cell", "decorators"]
decorators = None
class_result = None
is_py3_style_class = False # Python3 style class (kwargs)
metaclass = None
mkw = None
doc_node = None
def __init__(self, pos, name, bases, doc, body, decorators=None,
keyword_args=None, force_py3_semantics=False):
......@@ -4461,6 +4463,7 @@ class PyClassDefNode(ClassDefNode):
if self.doc and Options.docstrings:
doc = embed_position(self.pos, self.doc)
doc_node = ExprNodes.StringNode(pos, value=doc)
self.doc_node = ExprNodes.NameNode(name=EncodedString('__doc__'), type=py_object_type, pos=pos)
else:
doc_node = None
......@@ -4565,6 +4568,8 @@ class PyClassDefNode(ClassDefNode):
cenv = self.create_scope(env)
cenv.directives = env.directives
cenv.class_obj_cname = self.target.entry.cname
if self.doc_node:
self.doc_node.analyse_target_declaration(cenv)
self.body.analyse_declarations(cenv)
def analyse_expressions(self, env):
......
......@@ -14,10 +14,21 @@ doctest = u"""# Python 3 gets all of these right ...
>>> C.__doc__
'\\n This is a class docstring.\\n '
>>> C.docstring_copy_C
'\\n This is a class docstring.\\n '
>>> CS.docstring_copy_C
'\\n This is a class docstring.\\n '
>>> CS.__doc__
'\\n This is a subclass docstring.\\n '
>>> CS.docstring_copy_CS
'\\n This is a subclass docstring.\\n '
>>> CSS.docstring_copy_CS
'\\n This is a subclass docstring.\\n '
>>> print(CSS.__doc__)
None
>>> CSS.docstring_copy_CSS
'A module docstring'
>>> T.__doc__
'\\n This is an extension type docstring.\\n '
......@@ -34,22 +45,38 @@ Compare with standard Python:
>>> Pyf.__doc__
'\\n This is a function docstring.\\n '
>>> class PyC:
>>> class PyC(object):
... '''
... This is a class docstring.
... '''
>>> class PyCS(C):
... docstring_copy_C = __doc__
>>> class PyCS(PyC):
... '''
... This is a subclass docstring.
... '''
>>> class PyCSS(CS):
... pass
... docstring_copy_CS = __doc__
>>> class PyCSS(PyCS):
... docstring_copy_CSS = __doc__
>>> PyC.__doc__
'\\n This is a class docstring.\\n '
>>> PyC.docstring_copy_C
'\\n This is a class docstring.\\n '
>>> PyCS.docstring_copy_C
'\\n This is a class docstring.\\n '
>>> PyCSS.docstring_copy_C
'\\n This is a class docstring.\\n '
>>> PyCS.__doc__
'\\n This is a subclass docstring.\\n '
>>> PyCS.docstring_copy_CS
'\\n This is a subclass docstring.\\n '
>>> PyCSS.docstring_copy_CS
'\\n This is a subclass docstring.\\n '
>>> PyCSS.__doc__
>>> PyCSS.docstring_copy_CSS
'A module docstring'
"""
__test__ = {"test_docstrings" : doctest}
......@@ -59,18 +86,24 @@ def f():
This is a function docstring.
"""
class C:
class C(object):
"""
This is a class docstring.
"""
docstring_copy_C = __doc__
class CS(C):
"""
This is a subclass docstring.
"""
docstring_copy_CS = __doc__
class CSS(CS):
pass
docstring_copy_CSS = __doc__
cdef class T:
"""
......
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