It's not a shifting goalpost. My original statement was that:
def foo():
raise Exception
defines a function which 1) has no explicit return statement and 2)
does not return None. I stand by that statement. There is no possible
codepath, no possible calling sequence, no possible execution
environment, which will cause that function to return None.
Well, for varying definitions of "that function", you can do [snip modified functions]
Beyond that, I'm sure one could resort to bytecode hacking to have "that
function" skip the raise...
Now who's shifting the goalposts? Whether you edit the function's source
code, wrap it in a decorator, or hack it's byte-code, it's not the same
function as the one Roy showed above by any reasonable definition of "the
same". As an intellectual exercise of how one might subvert the standard
semantics of the Python compiler, it is interesting to consider (say)
byte-code hacks that turn this source code:
def foo():
raise Exception
into something that returns None, but by the same logic one might say
that this function:
def spam():
return 42
connects to some database over the Internet and deletes any table
containing more than seven records. If we're going to allow those sorts
of debating shenanigans, the obvious counter is "yes, but when I said
that the function doesn't return None, I actually meant that it doesn't
solve the Halting Problem, and it still doesn't do that, so I win nyah
nyah nyah".