My take on this is that it's actually a valid suggestion, albeit wrapped in some unhelpful language.

This is a more common example, in my opinion:

=== fileA.py ===

class MyClass:
    def do_thing(self, arg_a, arg_b):
        pass

=== fileB.py ===
...
class MySubClass(MyClass):
    pass

=== main.py ===
...
MySubclass().do_thing(1)

If you run the above (with trivial imports filled in etc.)
Then the traceback gives:

Traceback (most recent call last):
  File "c.py", line 3, in <module>
    B().do_thing()
TypeError: do_thing() takes exactly 3 arguments (1 given)

So Python has identified that a function 'do_thing' is being called incorrectly, but /where/ is do_thing defined?   This problem gets much harder if there are multiple definitions of 'do_thing' in the codebase, as alluded to in the original mail.

Paul's suggestion is that python should add the source location of the function being called into the error message somewhere.

The "it is/isn't a stack frame" issue is one possible solution, and comes down to a potential *semantic only* disagreement on how functions are called with python.

If you take traditional runtime-less languages, then the responsibility for unpacking and handling arguments is considered part of the function being called.
With C, for example, typically the compiler inserts a header (can't remember the better term for this right now)  at the start of a function, which moves the function arguments around as needed, so any failure match the arguments originates from within the called function (this is even more obvious with VA_ARGS for example).

Obviously, in languages with a runtime, such as python, the responsibility for matching arguments with function signatures can sit outside of the runtime function call context, and runtime-internal machinery information is not typically included in stack-traces.  Therefore, it appears (although I don't think this was part of any specific plan?) that the error originates from the call site (where the function is being called from) because this is the last point that was executing any python code.

So, the suggestion, as I understand it, is that a small conceptual shift is made in how we think about the mechanics of calling a function within python, such that the assignment and binding of function arguments are conceptually performed 'inside' the function being called (I assume you could equate this to the function 'def' line being executed).  If we do this, then it becomes easy to consider the TypeError as originating from within the called function, and therefore python will print the exact location of the function that's being called *as well as* the location of the call site (in the frame above).  Internally, the python runtime would have to go out of its way to  enter this 'fake' frame before generating the exception as, in reality the frame isn't entered (as I understand it) until after the arguments have been assigned correctly to the signature.  But this seems like it should be relatively simple and non-invasive to do.

The above makes sense to me, apologies if it's not very understandable to others.

Thanks

Steve



On Mon, Feb 22, 2021 at 10:39 PM Ned Batchelder <ned@nedbatchelder.com> wrote:

On 2/22/21 3:06 PM, Paul Sokolovsky wrote:
>
> No, I'm proposing to stop faking lack of the last stack frame due to
> CPython's implementation details. See the original message for more
> info.

I'm trying to understand what last stack frame (or lack of a last stack
frame, or the faking of a lack of a last stack frame) you are talking
about.  Your original message shows some tracebacks, but doesn't have
the code that produced them.  It's hard to understand what you are
referring to.

--Ned.
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-leave@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/KTBIYQDPHOHNYGTWWXT2KRODRHZDZWQX/
Code of Conduct: http://python.org/psf/codeofconduct/