symbian-qemu-0.9.1-12/python-2.6.1/Misc/find_recursionlimit.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 #! /usr/bin/env python
       
     2 """Find the maximum recursion limit that prevents interpreter termination.
       
     3 
       
     4 This script finds the maximum safe recursion limit on a particular
       
     5 platform.  If you need to change the recursion limit on your system,
       
     6 this script will tell you a safe upper bound.  To use the new limit,
       
     7 call sys.setrecursionlimit().
       
     8 
       
     9 This module implements several ways to create infinite recursion in
       
    10 Python.  Different implementations end up pushing different numbers of
       
    11 C stack frames, depending on how many calls through Python's abstract
       
    12 C API occur.
       
    13 
       
    14 After each round of tests, it prints a message:
       
    15 "Limit of NNNN is fine".
       
    16 
       
    17 The highest printed value of "NNNN" is therefore the highest potentially
       
    18 safe limit for your system (which depends on the OS, architecture, but also
       
    19 the compilation flags). Please note that it is practically impossible to
       
    20 test all possible recursion paths in the interpreter, so the results of
       
    21 this test should not be trusted blindly -- although they give a good hint
       
    22 of which values are reasonable.
       
    23 
       
    24 NOTE: When the C stack space allocated by your system is exceeded due
       
    25 to excessive recursion, exact behaviour depends on the platform, although
       
    26 the interpreter will always fail in a likely brutal way: either a
       
    27 segmentation fault, a MemoryError, or just a silent abort.
       
    28 
       
    29 NB: A program that does not use __methods__ can set a higher limit.
       
    30 """
       
    31 
       
    32 import sys
       
    33 import itertools
       
    34 
       
    35 class RecursiveBlowup1:
       
    36     def __init__(self):
       
    37         self.__init__()
       
    38 
       
    39 def test_init():
       
    40     return RecursiveBlowup1()
       
    41 
       
    42 class RecursiveBlowup2:
       
    43     def __repr__(self):
       
    44         return repr(self)
       
    45 
       
    46 def test_repr():
       
    47     return repr(RecursiveBlowup2())
       
    48 
       
    49 class RecursiveBlowup4:
       
    50     def __add__(self, x):
       
    51         return x + self
       
    52 
       
    53 def test_add():
       
    54     return RecursiveBlowup4() + RecursiveBlowup4()
       
    55 
       
    56 class RecursiveBlowup5:
       
    57     def __getattr__(self, attr):
       
    58         return getattr(self, attr)
       
    59 
       
    60 def test_getattr():
       
    61     return RecursiveBlowup5().attr
       
    62 
       
    63 class RecursiveBlowup6:
       
    64     def __getitem__(self, item):
       
    65         return self[item - 2] + self[item - 1]
       
    66 
       
    67 def test_getitem():
       
    68     return RecursiveBlowup6()[5]
       
    69 
       
    70 def test_recurse():
       
    71     return test_recurse()
       
    72 
       
    73 def test_cpickle(_cache={}):
       
    74     try:
       
    75         import cPickle
       
    76     except ImportError:
       
    77         print "cannot import cPickle, skipped!"
       
    78         return
       
    79     l = None
       
    80     for n in itertools.count():
       
    81         try:
       
    82             l = _cache[n]
       
    83             continue  # Already tried and it works, let's save some time
       
    84         except KeyError:
       
    85             for i in range(100):
       
    86                 l = [l]
       
    87         cPickle.dumps(l, protocol=-1)
       
    88         _cache[n] = l
       
    89 
       
    90 def check_limit(n, test_func_name):
       
    91     sys.setrecursionlimit(n)
       
    92     if test_func_name.startswith("test_"):
       
    93         print test_func_name[5:]
       
    94     else:
       
    95         print test_func_name
       
    96     test_func = globals()[test_func_name]
       
    97     try:
       
    98         test_func()
       
    99     # AttributeError can be raised because of the way e.g. PyDict_GetItem()
       
   100     # silences all exceptions and returns NULL, which is usually interpreted
       
   101     # as "missing attribute".
       
   102     except (RuntimeError, AttributeError):
       
   103         pass
       
   104     else:
       
   105         print "Yikes!"
       
   106 
       
   107 limit = 1000
       
   108 while 1:
       
   109     check_limit(limit, "test_recurse")
       
   110     check_limit(limit, "test_add")
       
   111     check_limit(limit, "test_repr")
       
   112     check_limit(limit, "test_init")
       
   113     check_limit(limit, "test_getattr")
       
   114     check_limit(limit, "test_getitem")
       
   115     check_limit(limit, "test_cpickle")
       
   116     print "Limit of %d is fine" % limit
       
   117     limit = limit + 100