The eval does the compilation. It can find that you want to go deeper with nested calls than sys.getrecursionlimit().
The recursion can be both direct (the function calls itself directly) or indirect (the function is called by another function which in turn was once called by this function). But when the call depth is greater than expected (1000 for the Python implementation at the time of writing), the call can be part of the indirect recursion that needs go even deeper to manifest itself to be recursive. In other words, if the maximum call depth is reached (and the depth is reasonable to think this way), it is fine to name it recursion that cannot be done.
The definitive answer can be found in sources... But I was just curious, so I did the following experiment. I tried to write the code that defines enough of distinct functions (with numbered identifiers) that call the next one -- except the last one that actually does not call the first one recursively.
def fn1():
print('fn1() is going to call fn2()')
fn2()
def fn2():
print('fn2() is going to call fn3()')
fn3()
def fn3():
print('fn3() does not call anything.')
fn1()
The last line starts the nested calls and it prints.
fn1() is going to call fn2()
fn2() is going to call fn3()
fn3() does not call anything.
We can generate the source as a string, and then we can use the compile built-in function and then exec it:
#!python3
import textwrap
n = 1000
print('n =', n)
lst = []
for i in range(1, n+1):
if i == n:
fndef = textwrap.dedent('''\
def fn{}():
print('fn{}() does not call anything.')
fn1()
'''.format(i, i))
else:
fndef = textwrap.dedent('''\
def fn{}():
print('fn{}() is going to call fn{}()')
fn{}()
'''.format(i, i, i+1, i+1))
if n <= 10:
print(fndef)
lst.append(fndef)
ast = compile('\n'.join(lst), '<string>', 'exec')
exec(ast)
Notice the n = 1000 at the beginning of the source. When executed and the stdout and stderr redirected to the files, I could observe:
n = 1000
fn1() is going to call fn2()
fn2() is going to call fn3()
fn3() is going to call fn4()
...
fn992() is going to call fn993()
fn993() is going to call fn994()
fn994() is going to call fn995()
Traceback (most recent call last):
File "a.py", line 28, in <module>
exec(ast)
File "<string>", line 4000, in <module>
File "<string>", line 3, in fn1
File "<string>", line 7, in fn2
File "<string>", line 11, in fn3
...
File "<string>", line 3967, in fn992
File "<string>", line 3971, in fn993
File "<string>", line 3975, in fn994
File "<string>", line 3978, in fn995
RuntimeError: maximum recursion depth exceeded
Conclusion: Python calls it recursion not only during eval when it is recursion but it was not executed, yet (as the question shows). Python may call it recursion even in the case when there is actually no recursion.
Better conclusion: Who cares when it is clear that the code could be a recursion or not, during compilation or in runtime. It would not work anyway :)
pdbon your script tell you anything?