new autotestdict.{cdef,all} directives that put cdef and non-doctest docstrings into...
authorStefan Behnel <scoder@users.berlios.de>
Wed, 3 Nov 2010 09:20:29 +0000 (10:20 +0100)
committerStefan Behnel <scoder@users.berlios.de>
Wed, 3 Nov 2010 09:20:29 +0000 (10:20 +0100)
--HG--
rename : tests/run/autotestdict.pyx => tests/run/autotestdict_all.pyx
rename : tests/run/autotestdict.pyx => tests/run/autotestdict_cdef.pyx

Cython/Compiler/AnalysedTreeTransforms.py
Cython/Compiler/Options.py
tests/run/autotestdict.pyx
tests/run/autotestdict_all.pyx [new file with mode: 0644]
tests/run/autotestdict_cdef.pyx [new file with mode: 0644]
tests/run/autotestdict_skip.pyx

index 69667abf6589c1bdb08f12de15ab245fe33942b3..38712049896f924cb9ea5fab07fa8de00f2a7898 100644 (file)
@@ -18,12 +18,13 @@ class AutoTestDictTransform(ScopeTrackingTransform):
     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)
 
@@ -59,8 +60,10 @@ class AutoTestDictTransform(ScopeTrackingTransform):
     def visit_FuncDefNode(self, node):
         if not node.doc:
             return node
-        if isinstance(node, CFuncDefNode) and not node.py_func:
-            # skip non-cpdef cdef functions
+        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
@@ -68,7 +71,10 @@ class AutoTestDictTransform(ScopeTrackingTransform):
             path = node.entry.name
         elif self.scope_type in ('pyclass', 'cclass'):
             if isinstance(node, CFuncDefNode):
-                name = node.py_func.name
+                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.blacklist:
index f36a33a05ceb82a1dc8d84b809db8c687127237c..a21fd8dfaaefdc1e8e9276a0c38608682d746db1 100644 (file)
@@ -68,6 +68,8 @@ directive_defaults = {
     'infer_types': None,
     'infer_types.verbose': False,
     'autotestdict': True,
+    'autotestdict.cdef': False,
+    'autotestdict.all': False,
     'language_level': 2,
     
     'warn': None,
@@ -97,6 +99,8 @@ directive_scopes = { # defaults to available everywhere
     'final' : ('cclass',),   # add 'method' in the future
     'internal' : ('cclass',),
     'autotestdict' : ('module',),
+    'autotestdict.all' : ('module',),
+    'autotestdict.cdef' : ('module',),
     'test_assert_path_exists' : ('function',),
     'test_fail_if_path_exists' : ('function',),
 }
index 0e3bc09ee285a703ec3560218c35efec97d4ae89..1e740c083da37d5254da1f279e19f0a25e6fd7b4 100644 (file)
@@ -1,23 +1,20 @@
 # Directive defaults to True
 
 """
-Tests doctesthack compiler directive.
+Tests autotestdict compiler directive.
 
-The doctests are actually run as part of this test;
-which makes the test flow a bit untraditional. Both
-module test and individual tests are run; finally,
+Both module test and individual tests are run; finally,
 all_tests_run() is executed which does final validation.
 
 >>> items = list(__test__.items())
 >>> items.sort()
 >>> for key, value in items:
 ...     print('%s ; %s' % (key, value))
-MyCdefClass.cpdef_method (line 79) ; >>> add_log("cpdef class method")
-MyCdefClass.method (line 76) ; >>> add_log("cdef class method")
-MyClass.method (line 65) ; >>> add_log("class method")
-doc_without_test (line 47) ; Some docs
-mycpdeffunc (line 53) ; >>> add_log("cpdef")
-myfunc (line 44) ; >>> add_log("def")
+MyCdefClass.cpdef_method (line 76) ; >>> add_log("cpdef class method")
+MyCdefClass.method (line 73) ; >>> add_log("cdef class method")
+MyClass.method (line 62) ; >>> add_log("class method")
+mycpdeffunc (line 49) ; >>> add_log("cpdef")
+myfunc (line 40) ; >>> add_log("def")
 
 """
 
@@ -25,19 +22,18 @@ log = []
 
 cdef cdeffunc():
     """
-    Please don't include me!
-
     >>> True
     False
     """
+cdeffunc() # make sure it's being used
 
 def all_tests_run():
     log.sort()
-    assert log == [u'cdef class', u'cdef class method', u'class method', u'cpdef', u'cpdef class method', u'def'], log
+    assert log == [u'cdef class', u'cdef class method', u'class', u'class method', u'cpdef', u'cpdef class method', u'def'], log
 
 def add_log(s):
     log.append(unicode(s))
-    if len(log) == len(__test__):
+    if len(log) == len(__test__) + 2:
         # Final per-function doctest executed
         all_tests_run()
 
@@ -58,6 +54,7 @@ class MyClass:
     """
     Needs no hack
 
+    >>> add_log("class")
     >>> True
     True
     """
@@ -79,6 +76,9 @@ cdef class MyCdefClass:
     cpdef cpdef_method(self):
         """>>> add_log("cpdef class method")"""
 
+    cdef cdef_method(self):
+        """>>> add_log("cdef class method")"""
+
     def __cinit__(self):
         """
         Should not be included, as it can't be looked up with getattr
@@ -142,5 +142,3 @@ cdef class MyOtherCdefClass:
         >>> True
         False
         """
-
-cdeffunc()
diff --git a/tests/run/autotestdict_all.pyx b/tests/run/autotestdict_all.pyx
new file mode 100644 (file)
index 0000000..71deb43
--- /dev/null
@@ -0,0 +1,144 @@
+# cython: autotestdict.all=True
+
+"""
+Tests autotestdict compiler directive.
+
+Both module test and individual tests are run; finally,
+all_tests_run() is executed which does final validation.
+
+>>> items = list(__test__.items())
+>>> items.sort()
+>>> for key, value in items:
+...     print('%s ; %s' % (key, value))
+MyCdefClass.cdef_method (line 79) ; >>> add_log("cdef class method")
+MyCdefClass.cpdef_method (line 76) ; >>> add_log("cpdef class method")
+MyCdefClass.method (line 73) ; >>> add_log("cdef class method")
+MyClass.method (line 62) ; >>> add_log("class method")
+cdeffunc (line 26) ; >>> add_log("cdef")
+doc_without_test (line 43) ; Some docs
+mycpdeffunc (line 49) ; >>> add_log("cpdef")
+myfunc (line 40) ; >>> add_log("def")
+
+"""
+
+log = []
+
+cdef cdeffunc():
+    """>>> add_log("cdef")"""
+cdeffunc() # make sure it's being used
+
+def all_tests_run():
+    log.sort()
+    assert log == [u'cdef', u'cdef class', u'cdef class method', u'class', u'class method', u'cpdef', u'cpdef class method', u'def'], log
+
+def add_log(s):
+    log.append(unicode(s))
+    if len(log) == len(__test__):
+        # Final per-function doctest executed
+        all_tests_run()
+
+def myfunc():
+    """>>> add_log("def")"""
+
+def doc_without_test():
+    """Some docs"""
+
+def nodocstring():
+    pass
+
+cpdef mycpdeffunc():
+    """>>> add_log("cpdef")"""
+
+
+class MyClass:
+    """
+    Needs no hack
+
+    >>> add_log("class")
+    >>> True
+    True
+    """
+
+    def method(self):
+        """>>> add_log("class method")"""
+
+cdef class MyCdefClass:
+    """
+    Needs no hack
+
+    >>> add_log("cdef class")
+    >>> True
+    True
+    """
+    def method(self):
+        """>>> add_log("cdef class method")"""
+
+    cpdef cpdef_method(self):
+        """>>> add_log("cpdef class method")"""
+
+    cdef cdef_method(self):
+        """>>> add_log("cdef class method")"""
+
+    def __cinit__(self):
+        """
+        Should not be included, as it can't be looked up with getattr
+
+        >>> True
+        False
+        """
+
+    def __dealloc__(self):
+        """
+        Should not be included, as it can't be looked up with getattr
+
+        >>> True
+        False
+        """
+
+    def __richcmp__(self, other, int op):
+        """
+        Should not be included, as it can't be looked up with getattr in Py 2
+
+        >>> True
+        False
+        """
+
+    def __nonzero__(self):
+        """
+        Should not be included, as it can't be looked up with getattr in Py 3.1
+
+        >>> True
+        False
+        """
+
+    def __len__(self):
+        """
+        Should not be included, as it can't be looked up with getattr in Py 3.1
+
+        >>> True
+        False
+        """
+
+    def __contains__(self, value):
+        """
+        Should not be included, as it can't be looked up with getattr in Py 3.1
+
+        >>> True
+        False
+        """
+
+cdef class MyOtherCdefClass:
+    """
+    Needs no hack
+    
+    >>> True
+    True
+    """
+
+    def __bool__(self):
+        """
+        Should not be included, as it can't be looked up with getattr in Py 2
+
+        >>> True
+        False
+        """
diff --git a/tests/run/autotestdict_cdef.pyx b/tests/run/autotestdict_cdef.pyx
new file mode 100644 (file)
index 0000000..9ebd1c5
--- /dev/null
@@ -0,0 +1,143 @@
+# cython: autotestdict.cdef=True
+
+"""
+Tests autotestdict compiler directive.
+
+Both module test and individual tests are run; finally,
+all_tests_run() is executed which does final validation.
+
+>>> items = list(__test__.items())
+>>> items.sort()
+>>> for key, value in items:
+...     print('%s ; %s' % (key, value))
+MyCdefClass.cdef_method (line 78) ; >>> add_log("cdef class method")
+MyCdefClass.cpdef_method (line 75) ; >>> add_log("cpdef class method")
+MyCdefClass.method (line 72) ; >>> add_log("cdef class method")
+MyClass.method (line 61) ; >>> add_log("class method")
+cdeffunc (line 25) ; >>> add_log("cdef")
+mycpdeffunc (line 48) ; >>> add_log("cpdef")
+myfunc (line 39) ; >>> add_log("def")
+
+"""
+
+log = []
+
+cdef cdeffunc():
+    """>>> add_log("cdef")"""
+cdeffunc() # make sure it's being used
+
+def all_tests_run():
+    log.sort()
+    assert log == [u'cdef', u'cdef class', u'cdef class method', u'class', u'class method', u'cpdef', u'cpdef class method', u'def'], log
+
+def add_log(s):
+    log.append(unicode(s))
+    if len(log) == len(__test__) + 1:
+        # Final per-function doctest executed
+        all_tests_run()
+
+def myfunc():
+    """>>> add_log("def")"""
+
+def doc_without_test():
+    """Some docs"""
+
+def nodocstring():
+    pass
+
+cpdef mycpdeffunc():
+    """>>> add_log("cpdef")"""
+
+
+class MyClass:
+    """
+    Needs no hack
+
+    >>> add_log("class")
+    >>> True
+    True
+    """
+
+    def method(self):
+        """>>> add_log("class method")"""
+
+cdef class MyCdefClass:
+    """
+    Needs no hack
+
+    >>> add_log("cdef class")
+    >>> True
+    True
+    """
+    def method(self):
+        """>>> add_log("cdef class method")"""
+
+    cpdef cpdef_method(self):
+        """>>> add_log("cpdef class method")"""
+
+    cdef cdef_method(self):
+        """>>> add_log("cdef class method")"""
+
+    def __cinit__(self):
+        """
+        Should not be included, as it can't be looked up with getattr
+
+        >>> True
+        False
+        """
+
+    def __dealloc__(self):
+        """
+        Should not be included, as it can't be looked up with getattr
+
+        >>> True
+        False
+        """
+
+    def __richcmp__(self, other, int op):
+        """
+        Should not be included, as it can't be looked up with getattr in Py 2
+
+        >>> True
+        False
+        """
+
+    def __nonzero__(self):
+        """
+        Should not be included, as it can't be looked up with getattr in Py 3.1
+
+        >>> True
+        False
+        """
+
+    def __len__(self):
+        """
+        Should not be included, as it can't be looked up with getattr in Py 3.1
+
+        >>> True
+        False
+        """
+
+    def __contains__(self, value):
+        """
+        Should not be included, as it can't be looked up with getattr in Py 3.1
+
+        >>> True
+        False
+        """
+
+cdef class MyOtherCdefClass:
+    """
+    Needs no hack
+    
+    >>> True
+    True
+    """
+
+    def __bool__(self):
+        """
+        Should not be included, as it can't be looked up with getattr in Py 2
+
+        >>> True
+        False
+        """
index 8770b6667badbbce2d2957e9afe8ecca9c4b083e..9042606ddc7c635372bab5723069c908fafb1dae 100644 (file)
@@ -1,6 +1,6 @@
-#cython: doctesthack=True
+#cython: autotestdict=True
 """
-Tests that doctesthack doesn't come into effect when
+Tests that autotestdict doesn't come into effect when
 a __test__ is defined manually.
 
 If this doesn't work, then the function doctest should fail.