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     <class '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     >>> next(g)
     38     0
     39     >>> next(g)
     40     1
     41     >>> next(g)
     42     4
     43     >>> next(g)
     44     Traceback (most recent call last):
     45       File "<pyshell#21>", line 1, in -toplevel-
     46         next(g)
     47     StopIteration
     48 
     49 Does it stay stopped?
     50 
     51     >>> next(g)
     52     Traceback (most recent call last):
     53       File "<pyshell#21>", line 1, in -toplevel-
     54         next(g)
     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 range(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 range(3) for j in range(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 range(3) for j in range(4) if j in range(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 range(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 range(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 range(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 = list(map(id, ((i,i) for i in range(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     SyntaxError: can't assign to generator expression
    141 
    142     >>> (y for y in (1,2)) += 10
    143     Traceback (most recent call last):
    144        ...
    145     SyntaxError: can't assign to generator expression
    146 
    147 
    148 ########### Tests borrowed from or inspired by test_generators.py ############
    149 
    150 Make a generator that acts like range()
    151 
    152     >>> yrange = lambda n:  (i for i in range(n))
    153     >>> list(yrange(10))
    154     [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    155 
    156 Generators always return to the most recent caller:
    157 
    158     >>> def creator():
    159     ...     r = yrange(5)
    160     ...     print("creator", next(r))
    161     ...     return r
    162     >>> def caller():
    163     ...     r = creator()
    164     ...     for i in r:
    165     ...             print("caller", i)
    166     >>> caller()
    167     creator 0
    168     caller 1
    169     caller 2
    170     caller 3
    171     caller 4
    172 
    173 Generators can call other generators:
    174 
    175     >>> def zrange(n):
    176     ...     for i in yrange(n):
    177     ...         yield i
    178     >>> list(zrange(5))
    179     [0, 1, 2, 3, 4]
    180 
    181 
    182 Verify that a gen exp cannot be resumed while it is actively running:
    183 
    184     >>> g = (next(me) for i in range(10))
    185     >>> me = g
    186     >>> next(me)
    187     Traceback (most recent call last):
    188       File "<pyshell#30>", line 1, in -toplevel-
    189         next(me)
    190       File "<pyshell#28>", line 1, in <generator expression>
    191         g = (next(me) for i in range(10))
    192     ValueError: generator already executing
    193 
    194 Verify exception propagation
    195 
    196     >>> g = (10 // i for i in (5, 0, 2))
    197     >>> next(g)
    198     2
    199     >>> next(g)
    200     Traceback (most recent call last):
    201       File "<pyshell#37>", line 1, in -toplevel-
    202         next(g)
    203       File "<pyshell#35>", line 1, in <generator expression>
    204         g = (10 // i for i in (5, 0, 2))
    205     ZeroDivisionError: integer division or modulo by zero
    206     >>> next(g)
    207     Traceback (most recent call last):
    208       File "<pyshell#38>", line 1, in -toplevel-
    209         next(g)
    210     StopIteration
    211 
    212 Make sure that None is a valid return value
    213 
    214     >>> list(None for i in range(10))
    215     [None, None, None, None, None, None, None, None, None, None]
    216 
    217 Check that generator attributes are present
    218 
    219     >>> g = (i*i for i in range(3))
    220     >>> expected = set(['gi_frame', 'gi_running'])
    221     >>> set(attr for attr in dir(g) if not attr.startswith('__')) >= expected
    222     True
    223 
    224     >>> from test.support import HAVE_DOCSTRINGS
    225     >>> print(g.__next__.__doc__ if HAVE_DOCSTRINGS else 'Implement next(self).')
    226     Implement next(self).
    227     >>> import types
    228     >>> isinstance(g, types.GeneratorType)
    229     True
    230 
    231 Check the __iter__ slot is defined to return self
    232 
    233     >>> iter(g) is g
    234     True
    235 
    236 Verify that the running flag is set properly
    237 
    238     >>> g = (me.gi_running for i in (0,1))
    239     >>> me = g
    240     >>> me.gi_running
    241     0
    242     >>> next(me)
    243     1
    244     >>> me.gi_running
    245     0
    246 
    247 Verify that genexps are weakly referencable
    248 
    249     >>> import weakref
    250     >>> g = (i*i for i in range(4))
    251     >>> wr = weakref.ref(g)
    252     >>> wr() is g
    253     True
    254     >>> p = weakref.proxy(g)
    255     >>> list(p)
    256     [0, 1, 4, 9]
    257 
    258 
    259 """
    260 
    261 import sys
    262 
    263 # Trace function can throw off the tuple reuse test.
    264 if hasattr(sys, 'gettrace') and sys.gettrace():
    265     __test__ = {}
    266 else:
    267     __test__ = {'doctests' : doctests}
    268 
    269 def test_main(verbose=None):
    270     from test import support
    271     from test import test_genexps
    272     support.run_doctest(test_genexps, verbose)
    273 
    274     # verify reference counting
    275     if verbose and hasattr(sys, "gettotalrefcount"):
    276         import gc
    277         counts = [None] * 5
    278         for i in range(len(counts)):
    279             support.run_doctest(test_genexps, verbose)
    280             gc.collect()
    281             counts[i] = sys.gettotalrefcount()
    282         print(counts)
    283 
    284 if __name__ == "__main__":
    285     test_main(verbose=True)
    286