classification
Title: Unspecific errors with metaclass
Type: Stage:
Components: Interpreter Core Versions: Python 2.4
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: mwh Nosy List: mwh, rhettinger, theller
Priority: high Keywords:

Created on 2004-08-23 09:33 by theller, last changed 2004-09-16 16:42 by rhettinger. This issue is now closed.

Files
File name Uploaded Description Edit
mc.py theller, 2004-08-23 09:33
module-init-error.diff mwh, 2004-09-10 13:55 simple patch
ceval.diff rhettinger, 2004-09-13 05:07 Augment error message in ceval.c
extend_exception.c theller, 2004-09-16 13:49 Function which adds text to an exception, and raises another exception.
Messages (14)
msg22178 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2004-08-23 09:33
Metaclass errors give only unspecific tracebacks.
The attached sample, with Python 2.3:

Traceback (most recent call last):
  File "mc.py", line 10, in ?
    class Z(X, Y):
TypeError: Cannot create a consistent method resolution
order (MRO) for bases X, Y

With Python 2.4, it prints:

Traceback (most recent call last):
  File "mc.py", line 10, in ?
    class Z(X, Y):
TypeError: Error when calling the metaclass.
Make sure the base arguments are valid.
msg22179 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2004-08-23 11:36
Logged In: YES 
user_id=6656

Argh argh argh.

This is a result of fixing bug #963956.  While the fix was well-
intentioned, I don't know if it's really the right thing... I suspect 
putting a more informative message in module_new might suffice.

Raymond's way of fixing the bug also neatly (and 
presumbably accidentally) sidestepped the tests that attempted to 
make sure you got a decent error message for this.

Raymond, what do you think?  I don't think the check in 
ceval.c:build_class can survive as is.
msg22180 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2004-08-23 16:07
Logged In: YES 
user_id=80475

Since 2.398 only replaces one type error with another, it's
really just about the contest of the error message.  Feel
free to remove or clarify the new message.

The core issue is that the lower level routines don't know
enough to create an informative error message and yet the
high level routines don't want to mask the information that
was available at the lower level.  Without considerable
effort, some of the error messages will be completely opaque
and uninformative, cryptic, or misleading (bug 963956 being
a prime example).

My preference is to opt for the higher level message, but
tastes vary.  

If you want to go for the gold, one possibility is to
capture the text of the lower level TypeError and append it
to the high level message.  The resulting messages may be
scary but at least they'll point a specific cause and be
suggestive of how to fix it.
msg22181 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2004-09-10 13:55
Logged In: YES 
user_id=6656

> The core issue is that the lower level routines don't know
> enough to create an informative error message

That needs to be at least somewhat equivocal: sometimes they
do...

Isn't the attached sufficient?  It makes the word 'module'
appear in the error message you get when you try to subclass
a module, at least.
msg22182 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2004-09-10 14:22
Logged In: YES 
user_id=80475

If you want the best of all worlds.  Grab the text from the
underlying TypeError and append it to the higher level
message before re-raising TypeError.

I'm happy with whatever you decide to do.  When deciding, be
sure to consider bug #963956 -- it is a small disaster with
the msg appearing totally unrelated to what caused it.

And, no, the statement wasn't equivocal.  Low level routines
cannot know for all time and all situtations the context in
which they were called.  Sometimes they are fortunate and
tend to be called by only one thing or in just one context;
however, that is subject to change as soon as new high level
routine decides to use that building block.

In this particular case, the metaclass function call can
launch just about anything.  The callee really has no way of
knowing the circumstances of how it was called -- in this
case, one of the implicit actions of metaclasses.
msg22183 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2004-09-10 14:37
Logged In: YES 
user_id=6656

Unfortunately, I think

> Grab the text from the
> underlying TypeError and append it to the higher level
> message before re-raising TypeError.

might be a bit of a bear to implement.  If I'm being dumb
about this, feel free to apply the cluestick (bearing in
mind that in general stringifying the TypeError may execute
Python code).

There probably is no ideal solution to this -- it's a knotty
problem.  The problem with current CVS is that it can lose
information, whereas before it failed to add it...
msg22184 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2004-09-13 04:18
Logged In: YES 
user_id=80475

The attached patch implements an augmented error message
that preserves the traceback and detailed message while
providing a hint about the high level routine that called it.

Here's a sample run:

>>> class T(bool):
	pass


Traceback (most recent call last):
  File "<pyshell#2>", line 1, in -toplevel-
    class T(bool):
TypeError: Error when calling the metaclass bases
    type 'bool' is not an acceptable base type
msg22185 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2004-09-16 00:02
Logged In: YES 
user_id=80475

Michael, Thomas, any thoughts on the patch?
msg22186 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2004-09-16 11:01
Logged In: YES 
user_id=6656

I like it.  I hope to be more specific than that soon :)

Sorry for the delay...
msg22187 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2004-09-16 12:57
Logged In: YES 
user_id=11105

ceval.diff: What happens when pvalue is not a string?
And, isn't it required to call PyErr_NormalizeException()
after the PyErr_Fetch?

BTW: I'm currently working on a somewhat similar problem
(augmenting an error message with more info) in a non-python
core project.  I'll take this code and upload a patch using
this approach.
msg22188 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2004-09-16 13:49
Logged In: YES 
user_id=11105

I don't have time to cook up a complete patch for ceval.c,
but the attached extend_exception.c file contains a function
which works for me, in another context.

It could be used to raise a type error containing the
original exception's text.
msg22189 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2004-09-16 13:57
Logged In: YES 
user_id=6656

Raymond's patch strikes me as a nicely simple approach.

Thomas' strikes me as though it should be made into some
general function which build_class should use.  This is
probably objectively the better solution, but risks opening
a large can of worms...
msg22190 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2004-09-16 14:14
Logged In: YES 
user_id=11105

After reading Raymond's patch again - if it fixes the
original problem, mwh's comment is probably right.
msg22191 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2004-09-16 16:42
Logged In: YES 
user_id=80475

Made minor adjustments to the patch (the PyErr_Clear() was
not needed) and applied as Python/ceval.c 2.417.

If someone comes up with a better solution, feel free to
apply it.
History
Date User Action Args
2004-08-23 09:33:02thellercreate