| from __future__ import absolute_import
|
|
|
| from .Visitor import ScopeTrackingTransform
|
| from .Nodes import StatListNode, SingleAssignmentNode, CFuncDefNode, DefNode
|
| from .ExprNodes import DictNode, DictItemNode, NameNode, UnicodeNode
|
| from .PyrexTypes import py_object_type
|
| from .StringEncoding import EncodedString
|
| from . import Symtab
|
|
|
| class AutoTestDictTransform(ScopeTrackingTransform):
|
|
|
|
|
| excludelist = ['__cinit__', '__dealloc__', '__richcmp__',
|
| '__nonzero__', '__bool__',
|
| '__len__', '__contains__']
|
|
|
| def visit_ModuleNode(self, node):
|
| if node.is_pxd:
|
| return node
|
| self.scope_type = 'module'
|
| self.scope_node = node
|
|
|
| if not self.current_directives['autotestdict']:
|
| return node
|
| self.all_docstrings = self.current_directives['autotestdict.all']
|
| self.cdef_docstrings = self.all_docstrings or self.current_directives['autotestdict.cdef']
|
|
|
| assert isinstance(node.body, StatListNode)
|
|
|
|
|
| if u'__test__' in node.scope.entries:
|
|
|
| return node
|
|
|
| pos = node.pos
|
|
|
| self.tests = []
|
| self.testspos = node.pos
|
|
|
| test_dict_entry = node.scope.declare_var(EncodedString(u'__test__'),
|
| py_object_type,
|
| pos,
|
| visibility='public')
|
| create_test_dict_assignment = SingleAssignmentNode(pos,
|
| lhs=NameNode(pos, name=EncodedString(u'__test__'),
|
| entry=test_dict_entry),
|
| rhs=DictNode(pos, key_value_pairs=self.tests))
|
| self.visitchildren(node)
|
| node.body.stats.append(create_test_dict_assignment)
|
| return node
|
|
|
| def add_test(self, testpos, path, doctest):
|
| pos = self.testspos
|
| keystr = u'%s (line %d)' % (path, testpos[1])
|
| key = UnicodeNode(pos, value=EncodedString(keystr))
|
| value = UnicodeNode(pos, value=doctest)
|
| self.tests.append(DictItemNode(pos, key=key, value=value))
|
|
|
| def visit_ExprNode(self, node):
|
|
|
|
|
| return node
|
|
|
| def visit_FuncDefNode(self, node):
|
| if not node.doc or (isinstance(node, DefNode) and node.fused_py_func):
|
| return node
|
| if not self.cdef_docstrings:
|
| if isinstance(node, CFuncDefNode) and not node.py_func:
|
| return node
|
| if not self.all_docstrings and '>>>' not in node.doc:
|
| return node
|
|
|
| pos = self.testspos
|
| if self.scope_type == 'module':
|
| path = node.entry.name
|
| elif self.scope_type in ('pyclass', 'cclass'):
|
| if isinstance(node, CFuncDefNode):
|
| if node.py_func is not None:
|
| name = node.py_func.name
|
| else:
|
| name = node.entry.name
|
| else:
|
| name = node.name
|
| if self.scope_type == 'cclass' and name in self.excludelist:
|
| return node
|
| if self.scope_type == 'pyclass':
|
| class_name = self.scope_node.name
|
| else:
|
| class_name = self.scope_node.class_name
|
| if isinstance(node.entry.scope, Symtab.PropertyScope):
|
| property_method_name = node.entry.scope.name
|
| path = "%s.%s.%s" % (class_name, node.entry.scope.name,
|
| node.entry.name)
|
| else:
|
| path = "%s.%s" % (class_name, node.entry.name)
|
| else:
|
| assert False
|
| self.add_test(node.pos, path, node.doc)
|
| return node
|
|
|