Commit ab4e40c1 authored by scoder's avatar scoder

Merge pull request #152 from Talanor/DocstringsError

Fix error when the first statement of Module/Function/Class is a littera...
parents f675f1ce 5dd16c54
...@@ -179,10 +179,35 @@ class PostParse(ScopeTrackingTransform): ...@@ -179,10 +179,35 @@ class PostParse(ScopeTrackingTransform):
'__cythonbufferdefaults__' : self.handle_bufferdefaults '__cythonbufferdefaults__' : self.handle_bufferdefaults
} }
def _visit_DocString(self, result):
if hasattr(result.body, 'stats') and result.body.stats:
firstNode = result.body.stats[0]
if isinstance(firstNode, Nodes.ExprStatNode) and firstNode.expr.is_string_literal:
result.body.stats = result.body.stats[1:]
self.doc = firstNode.expr.value
result.doc = self.doc
return firstNode.expr, result
return None, result
def visit_FuncDefNode(self, node):
docNode, result = self._visit_DocString(super(PostParse, self).visit_FuncDefNode(node))
return result
def visit_PyClassDefNode(self, node):
docNode, result = self._visit_DocString(super(PostParse, self).visit_PyClassDefNode(node))
if docNode:
result.classobj.doc = docNode
return result
def visit_CClassDefNode(self, node):
docNode, result = self._visit_DocString(super(PostParse, self).visit_CClassDefNode(node))
return result
def visit_ModuleNode(self, node): def visit_ModuleNode(self, node):
self.lambda_counter = 1 self.lambda_counter = 1
self.genexpr_counter = 1 self.genexpr_counter = 1
return super(PostParse, self).visit_ModuleNode(node) docNode, result = self._visit_DocString(super(PostParse, self).visit_ModuleNode(node))
return result
def visit_LambdaNode(self, node): def visit_LambdaNode(self, node):
# unpack a lambda expression into the corresponding DefNode # unpack a lambda expression into the corresponding DefNode
...@@ -1646,7 +1671,7 @@ if VALUE is not None: ...@@ -1646,7 +1671,7 @@ if VALUE is not None:
return None return None
else: else:
return self.visit_ClassDefNode(node) return self.visit_ClassDefNode(node)
def visit_CStructOrUnionDefNode(self, node): def visit_CStructOrUnionDefNode(self, node):
# Create a wrapper node if needed. # Create a wrapper node if needed.
# We want to use the struct type information (so it can't happen # We want to use the struct type information (so it can't happen
......
...@@ -175,6 +175,5 @@ cdef p_class_statement(PyrexScanner s, decorators) ...@@ -175,6 +175,5 @@ cdef p_class_statement(PyrexScanner s, decorators)
cdef p_c_class_definition(PyrexScanner s, pos, ctx) cdef p_c_class_definition(PyrexScanner s, pos, ctx)
cdef p_c_class_options(PyrexScanner s) cdef p_c_class_options(PyrexScanner s)
cdef p_property_decl(PyrexScanner s) cdef p_property_decl(PyrexScanner s)
cdef p_doc_string(PyrexScanner s)
cdef p_compiler_directive_comments(PyrexScanner s) cdef p_compiler_directive_comments(PyrexScanner s)
cdef p_cpp_class_definition(PyrexScanner s, pos, ctx) cdef p_cpp_class_definition(PyrexScanner s, pos, ctx)
...@@ -1099,10 +1099,7 @@ def p_expression_or_assignment(s): ...@@ -1099,10 +1099,7 @@ def p_expression_or_assignment(s):
rhs = p_testlist(s) rhs = p_testlist(s)
return Nodes.InPlaceAssignmentNode(lhs.pos, operator = operator, lhs = lhs, rhs = rhs) return Nodes.InPlaceAssignmentNode(lhs.pos, operator = operator, lhs = lhs, rhs = rhs)
expr = expr_list[0] expr = expr_list[0]
if isinstance(expr, (ExprNodes.UnicodeNode, ExprNodes.StringNode, ExprNodes.BytesNode)): return Nodes.ExprStatNode(expr.pos, expr = expr)
return Nodes.PassStatNode(expr.pos)
else:
return Nodes.ExprStatNode(expr.pos, expr = expr)
rhs = expr_list[-1] rhs = expr_list[-1]
if len(expr_list) == 2: if len(expr_list) == 2:
...@@ -1870,8 +1867,6 @@ def p_suite(s, ctx = Ctx(), with_doc = 0, with_pseudo_doc = 0): ...@@ -1870,8 +1867,6 @@ def p_suite(s, ctx = Ctx(), with_doc = 0, with_pseudo_doc = 0):
if s.sy == 'NEWLINE': if s.sy == 'NEWLINE':
s.next() s.next()
s.expect_indent() s.expect_indent()
if with_doc or with_pseudo_doc:
doc = p_doc_string(s)
body = p_statement_list(s, ctx) body = p_statement_list(s, ctx)
s.expect_dedent() s.expect_dedent()
else: else:
...@@ -2970,19 +2965,6 @@ def p_property_decl(s): ...@@ -2970,19 +2965,6 @@ def p_property_decl(s):
doc, body = p_suite(s, Ctx(level = 'property'), with_doc = 1) doc, body = p_suite(s, Ctx(level = 'property'), with_doc = 1)
return Nodes.PropertyNode(pos, name = name, doc = doc, body = body) return Nodes.PropertyNode(pos, name = name, doc = doc, body = body)
def p_doc_string(s):
if s.sy == 'BEGIN_STRING':
pos = s.position()
kind, bytes_result, unicode_result = p_cat_string_literal(s)
if s.sy != 'EOF':
s.expect_newline("Syntax error in doc string")
if kind in ('u', ''):
return unicode_result
warning(pos, "Python 3 requires docstrings to be unicode strings")
return bytes_result
else:
return None
def p_code(s, level=None, ctx=Ctx): def p_code(s, level=None, ctx=Ctx):
body = p_statement_list(s, ctx(level = level), first_statement = 1) body = p_statement_list(s, ctx(level = level), first_statement = 1)
if s.sy != 'EOF': if s.sy != 'EOF':
...@@ -3015,7 +2997,7 @@ def p_module(s, pxd, full_module_name, ctx=Ctx): ...@@ -3015,7 +2997,7 @@ def p_module(s, pxd, full_module_name, ctx=Ctx):
if 'language_level' in directive_comments: if 'language_level' in directive_comments:
s.context.set_language_level(directive_comments['language_level']) s.context.set_language_level(directive_comments['language_level'])
doc = p_doc_string(s) doc = None
if pxd: if pxd:
level = 'module_pxd' level = 'module_pxd'
else: else:
......
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