Home | History | Annotate | Download | only in test
      1 doctests = """
      2 
      3 Test simple loop with conditional
      4 
      5     >>> sum(i*i for i in range(100) if i&1 == 1)
      6     166650
      7 
      8 Test simple nesting
      9 
     10     >>> list((i,j) for i in range(3) for j in range(4) )
     11     [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)]
     12 
     13 Test nesting with the inner expression dependent on the outer
     14 
     15     >>> list((i,j) for i in range(4) for j in range(i) )
     16     [(1, 0), (2, 0), (2, 1), (3, 0), (3, 1), (3, 2)]
     17 
     18 Make sure the induction variable is not exposed
     19 
     20     >>> i = 20
     21     >>> sum(i*i for i in range(100))
     22     328350
     23     >>> i
     24     20
     25 
     26 Test first class
     27 
     28     >>> g = (i*i for i in range(4))
     29     >>> type(g)
     30     <type 'generator'>
     31     >>> list(g)
     32     [0, 1, 4, 9]
     33 
     34 Test direct calls to next()
     35 
     36     >>> g = (i*i for i in range(3))
     37     >>> g.next()
     38     0
     39     >>> g.next()
     40     1
     41     >>> g.next()
     42     4
     43     >>> g.next()
     44     Traceback (most recent call last):
     45       File "<pyshell#21>", line 1, in -toplevel-
     46         g.next()
     47     StopIteration
     48 
     49 Does it stay stopped?
     50 
     51     >>> g.next()
     52     Traceback (most recent call last):
     53       File "<pyshell#21>", line 1, in -toplevel-
     54         g.next()
     55     StopIteration
     56     >>> list(g)
     57     []
     58 
     59 Test running gen when defining function is out of scope
     60 
     61     >>> def f(n):
     62     ...     return (i*i for i in xrange(n))
     63     >>> list(f(10))
     64     [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
     65 
     66     >>> def f(n):
     67     ...     return ((i,j) for i in xrange(3) for j in xrange(n))
     68     >>> list(f(4))
     69     [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)]
     70     >>> def f(n):
     71     ...     return ((i,j) for i in xrange(3) for j in xrange(4) if j in xrange(n))
     72     >>> list(f(4))
     73     [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)]
     74     >>> list(f(2))
     75     [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)]
     76 
     77 Verify that parenthesis are required in a statement
     78 
     79     >>> def f(n):
     80     ...     return i*i for i in xrange(n)
     81     Traceback (most recent call last):
     82        ...
     83     SyntaxError: invalid syntax
     84 
     85 Verify that parenthesis are required when used as a keyword argument value
     86 
     87     >>> dict(a = i for i in xrange(10))
     88     Traceback (most recent call last):
     89        ...
     90     SyntaxError: invalid syntax
     91 
     92 Verify that parenthesis are required when used as a keyword argument value
     93 
     94     >>> dict(a = (i for i in xrange(10))) #doctest: +ELLIPSIS
     95     {'a': <generator object <genexpr> at ...>}
     96 
     97 Verify early binding for the outermost for-expression
     98 
     99     >>> x=10
    100     >>> g = (i*i for i in range(x))
    101     >>> x = 5
    102     >>> list(g)
    103     [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
    104 
    105 Verify that the outermost for-expression makes an immediate check
    106 for iterability
    107 
    108     >>> (i for i in 6)
    109     Traceback (most recent call last):
    110       File "<pyshell#4>", line 1, in -toplevel-
    111         (i for i in 6)
    112     TypeError: 'int' object is not iterable
    113 
    114 Verify late binding for the outermost if-expression
    115 
    116     >>> include = (2,4,6,8)
    117     >>> g = (i*i for i in range(10) if i in include)
    118     >>> include = (1,3,5,7,9)
    119     >>> list(g)
    120     [1, 9, 25, 49, 81]
    121 
    122 Verify late binding for the innermost for-expression
    123 
    124     >>> g = ((i,j) for i in range(3) for j in range(x))
    125     >>> x = 4
    126     >>> list(g)
    127     [(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)]
    128 
    129 Verify re-use of tuples (a side benefit of using genexps over listcomps)
    130 
    131     >>> tupleids = map(id, ((i,i) for i in xrange(10)))
    132     >>> int(max(tupleids) - min(tupleids))
    133     0
    134 
    135 Verify that syntax error's are raised for genexps used as lvalues
    136 
    137     >>> (y for y in (1,2)) = 10
    138     Traceback (most recent call last):
    139        ...
    140       File "<doctest test.test_genexps.__test__.doctests[40]>", line 1
    141     SyntaxError: can't assign to generator expression
    142 
    143     >>> (y for y in (1,2)) += 10
    144     Traceback (most recent call last):
    145        ...
    146       File "<doctest test.test_genexps.__test__.doctests[41]>", line 1
    147     SyntaxError: can't assign to generator expression
    148 
    149 
    150 ########### Tests borrowed from or inspired by test_generators.py ############
    151 
    152 Make a generator that acts like range()
    153 
    154     >>> yrange = lambda n:  (i for i in xrange(n))
    155     >>> list(yrange(10))
    156     [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    157 
    158 Generators always return to the most recent caller:
    159 
    160     >>> def creator():
    161     ...     r = yrange(5)
    162     ...     print "creator", r.next()
    163     ...     return r
    164     >>> def caller():
    165     ...     r = creator()
    166     ...     for i in r:
    167     ...             print "caller", i
    168     >>> caller()
    169     creator 0
    170     caller 1
    171     caller 2
    172     caller 3
    173     caller 4
    174 
    175 Generators can call other generators:
    176 
    177     >>> def zrange(n):
    178     ...     for i in yrange(n):
    179     ...         yield i
    180     >>> list(zrange(5))
    181     [0, 1, 2, 3, 4]
    182 
    183 
    184 Verify that a gen exp cannot be resumed while it is actively running:
    185 
    186     >>> g = (me.next() for i in xrange(10))
    187     >>> me = g
    188     >>> me.next()
    189     Traceback (most recent call last):
    190       File "<pyshell#30>", line 1, in -toplevel-
    191         me.next()
    192       File "<pyshell#28>", line 1, in <generator expression>
    193         g = (me.next() for i in xrange(10))
    194     ValueError: generator already executing
    195 
    196 Verify exception propagation
    197 
    198     >>> g = (10 // i for i in (5, 0, 2))
    199     >>> g.next()
    200     2
    201     >>> g.next()
    202     Traceback (most recent call last):
    203       File "<pyshell#37>", line 1, in -toplevel-
    204         g.next()
    205       File "<pyshell#35>", line 1, in <generator expression>
    206         g = (10 // i for i in (5, 0, 2))
    207     ZeroDivisionError: integer division or modulo by zero
    208     >>> g.next()
    209     Traceback (most recent call last):
    210       File "<pyshell#38>", line 1, in -toplevel-
    211         g.next()
    212     StopIteration
    213 
    214 Make sure that None is a valid return value
    215 
    216     >>> list(None for i in xrange(10))
    217     [None, None, None, None, None, None, None, None, None, None]
    218 
    219 Check that generator attributes are present
    220 
    221     >>> g = (i*i for i in range(3))
    222     >>> expected = set(['gi_frame', 'gi_running', 'next'])
    223     >>> set(attr for attr in dir(g) if not attr.startswith('__')) >= expected
    224     True
    225 
    226     >>> from test.test_support import HAVE_DOCSTRINGS
    227     >>> print(g.next.__doc__ if HAVE_DOCSTRINGS else 'x.next() -> the next value, or raise StopIteration')
    228     x.next() -> the next value, or raise StopIteration
    229     >>> import types
    230     >>> isinstance(g, types.GeneratorType)
    231     True
    232 
    233 Check the __iter__ slot is defined to return self
    234 
    235     >>> iter(g) is g
    236     True
    237 
    238 Verify that the running flag is set properly
    239 
    240     >>> g = (me.gi_running for i in (0,1))
    241     >>> me = g
    242     >>> me.gi_running
    243     0
    244     >>> me.next()
    245     1
    246     >>> me.gi_running
    247     0
    248 
    249 Verify that genexps are weakly referencable
    250 
    251     >>> import weakref
    252     >>> g = (i*i for i in range(4))
    253     >>> wr = weakref.ref(g)
    254     >>> wr() is g
    255     True
    256     >>> p = weakref.proxy(g)
    257     >>> list(p)
    258     [0, 1, 4, 9]
    259 
    260 
    261 """
    262 
    263 
    264 __test__ = {'doctests' : doctests}
    265 
    266 def test_main(verbose=None):
    267     import sys
    268     from test import test_support
    269     from test import test_genexps
    270     test_support.run_doctest(test_genexps, verbose)
    271 
    272     # verify reference counting
    273     if verbose and hasattr(sys, "gettotalrefcount"):
    274         import gc
    275         counts = [None] * 5
    276         for i in xrange(len(counts)):
    277             test_support.run_doctest(test_genexps, verbose)
    278             gc.collect()
    279             counts[i] = sys.gettotalrefcount()
    280         print counts
    281 
    282 if __name__ == "__main__":
    283     test_main(verbose=True)
    284