python-2.5.2/win32/Lib/test/test_genexps.py
changeset 0 ae805ac0140d
equal deleted inserted replaced
-1:000000000000 0:ae805ac0140d
       
     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 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     SyntaxError: can't assign to generator expression (<doctest test.test_genexps.__test__.doctests[40]>, line 1)
       
   141 
       
   142     >>> (y for y in (1,2)) += 10
       
   143     Traceback (most recent call last):
       
   144        ...
       
   145     SyntaxError: augmented assignment to generator expression not possible (<doctest test.test_genexps.__test__.doctests[41]>, line 1)
       
   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 xrange(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", r.next()
       
   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 = (me.next() for i in xrange(10))
       
   185     >>> me = g
       
   186     >>> me.next()
       
   187     Traceback (most recent call last):
       
   188       File "<pyshell#30>", line 1, in -toplevel-
       
   189         me.next()
       
   190       File "<pyshell#28>", line 1, in <generator expression>
       
   191         g = (me.next() for i in xrange(10))
       
   192     ValueError: generator already executing
       
   193 
       
   194 Verify exception propagation
       
   195 
       
   196     >>> g = (10 // i for i in (5, 0, 2))
       
   197     >>> g.next()
       
   198     2
       
   199     >>> g.next()
       
   200     Traceback (most recent call last):
       
   201       File "<pyshell#37>", line 1, in -toplevel-
       
   202         g.next()
       
   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     >>> g.next()
       
   207     Traceback (most recent call last):
       
   208       File "<pyshell#38>", line 1, in -toplevel-
       
   209         g.next()
       
   210     StopIteration
       
   211 
       
   212 Make sure that None is a valid return value
       
   213 
       
   214     >>> list(None for i in xrange(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', 'next'])
       
   221     >>> set(attr for attr in dir(g) if not attr.startswith('__')) >= expected
       
   222     True
       
   223 
       
   224     >>> print g.next.__doc__
       
   225     x.next() -> the next value, or raise StopIteration
       
   226     >>> import types
       
   227     >>> isinstance(g, types.GeneratorType)
       
   228     True
       
   229 
       
   230 Check the __iter__ slot is defined to return self
       
   231 
       
   232     >>> iter(g) is g
       
   233     True
       
   234 
       
   235 Verify that the running flag is set properly
       
   236 
       
   237     >>> g = (me.gi_running for i in (0,1))
       
   238     >>> me = g
       
   239     >>> me.gi_running
       
   240     0
       
   241     >>> me.next()
       
   242     1
       
   243     >>> me.gi_running
       
   244     0
       
   245 
       
   246 Verify that genexps are weakly referencable
       
   247 
       
   248     >>> import weakref
       
   249     >>> g = (i*i for i in range(4))
       
   250     >>> wr = weakref.ref(g)
       
   251     >>> wr() is g
       
   252     True
       
   253     >>> p = weakref.proxy(g)
       
   254     >>> list(p)
       
   255     [0, 1, 4, 9]
       
   256 
       
   257 
       
   258 """
       
   259 
       
   260 
       
   261 __test__ = {'doctests' : doctests}
       
   262 
       
   263 def test_main(verbose=None):
       
   264     import sys
       
   265     from test import test_support
       
   266     from test import test_genexps
       
   267     test_support.run_doctest(test_genexps, verbose)
       
   268 
       
   269     # verify reference counting
       
   270     if verbose and hasattr(sys, "gettotalrefcount"):
       
   271         import gc
       
   272         counts = [None] * 5
       
   273         for i in xrange(len(counts)):
       
   274             test_support.run_doctest(test_genexps, verbose)
       
   275             gc.collect()
       
   276             counts[i] = sys.gettotalrefcount()
       
   277         print counts
       
   278 
       
   279 if __name__ == "__main__":
       
   280     test_main(verbose=True)