Bugs item #518846, was opened at 2002-02-17 12:09 Message generated for change (Comment added) made by bcannon You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=105470&aid=518846&group_id=5470
Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: Type/class unification Group: Python 2.5 >Status: Closed >Resolution: Fixed Priority: 5 Submitted By: Magnus Heino (magnusheino) Assigned to: Guido van Rossum (gvanrossum) Summary: exception cannot be new-style class Initial Comment: [EMAIL PROTECTED] magnus]$ python2.2 Python 2.2 (#1, Jan 26 2002, 14:27:24) [GCC 2.96 20000731 (Red Hat Linux 7.1 2.96-98)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> class foo(object): ... pass ... >>> raise foo() Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: exceptions must be strings, classes, or instances, not foo >>> ---------------------------------------------------------------------- >Comment By: Brett Cannon (bcannon) Date: 2006-02-28 20:34 Message: Logged In: YES user_id=357491 rev. 42711 (PEP 352 implementation) made built-in exceptions new-style. ---------------------------------------------------------------------- Comment By: Robey Pointer (robey1) Date: 2004-12-17 12:46 Message: Logged In: YES user_id=1179122 (I wish we could do this in email instead of cluttering up an already-messy bug...) Forget about throwing non-Exception-based objects: it's a red herring. The bug to focus on is the title: "exception cannot be new-style class". Bottom line: This subclass of Exception can not be raised in python 2.3: class MyException (Exception, object): pass pje's comment below from (2002-07-11 13:12) is a nice summary of how to solve it. ---------------------------------------------------------------------- Comment By: Martin v. Löwis (loewis) Date: 2004-12-16 05:00 Message: Logged In: YES user_id=21627 This statement, as literally made, is incorrect: >>> class X(Exception): ... pass ... >>> e=X() >>> type(e) <type 'instance'> >>> raise e Traceback (most recent call last): File "<stdin>", line 1, in ? __main__.X: <__main__.X instance at 0x401f2b4c> In this example, type(e) works, and x is an object which has Exception among its base classes. Still, I can throw x, despite your claim that I cannot. Even if I interpret your statement more literally (i.e. that you are talking about objects for which type(e) is a new-style class): Why do you think this statement explains there is a bug? As for why it is a new feature: it currently doesn't work, and anybody trying it will quickly find out that it doesn't work. The language reference says it doesn't work. The TypeError you get says it doesn't work. So that it doesn't work is clearly intentional; changing it will be a new feature. Notice that it is very difficult to implement this feature, as something needs to happen with strings and subtypes of str. Currently, string exceptions are caught by identity. If arbitrary objects can be used as exceptions, then strings should also be caught by type, not by identity; this is a backwards-incompatible change. A clean solution would be to deprecate string exceptions in 2.5, completely ban them in 2.6, and allow arbitrary objects to act as exceptions in 2.7. Please do read the entire thread of this RFE. ---------------------------------------------------------------------- Comment By: Robey Pointer (robey1) Date: 2004-12-15 15:39 Message: Logged In: YES user_id=1179122 Let me try to rephrase the problem so that it's obvious that this is a bug, and not a feature: 'type(e)' on an exception will not work in 2.3, and cannot be made to work from within python code. There's no way to throw an exception (ie an object with Exception in its ancestor list) that 'type(e)' will work on. :( ---------------------------------------------------------------------- Comment By: Martin v. Löwis (loewis) Date: 2004-12-15 13:59 Message: Logged In: YES user_id=21627 Whatever the solution to this problem, it is for sure that 2.4.x won't see it, because it will be a new feature. ---------------------------------------------------------------------- Comment By: Robey Pointer (robey1) Date: 2004-12-15 13:08 Message: Logged In: YES user_id=1179122 This caused me an hour of debugging a few nights ago. When using unified types, it's very confusing to find that not only does Exception not follow new-style object semantics, but it *can't*. Doing the obvious hack: class MyException (Exception, object): pass does not work! The interpreter (2.3) refuses to let you raise a unified-type object. And if you subclass exclusively from Exception, type(obj) returns 'instance' instead of the class (due to being an old-style object). Please fix this for 2.4! ---------------------------------------------------------------------- Comment By: Facundo Batista (facundobatista) Date: 2004-11-24 18:05 Message: Logged In: YES user_id=752496 Reproduced the bug in Py2.3. I think that this is a bug, at least because we "encourage" users to derive exceptions from Exception, so they should be able to not do it. The moment we say that they "must" derive from Exception, this can be closed (of course, this is my *very* personal opinion, ;) ---------------------------------------------------------------------- Comment By: Phillip J. Eby (pje) Date: 2002-07-11 13:12 Message: Logged In: YES user_id=56214 Just to make things even more interesting, the current 'raise' code *will* let you raise a new-style instance that derives from 'tuple'... of course, what it actually raises is the first element of said tuple-like thing. It seems to me that the very first thing that should be checked is whether the first argument to 'raise' is an instance of Exception, and if so, take its type and go from there. This would support both old and new-style instances of Exception subclasses, and I believe is the recommended approach to using 'raise'. (I.e., raise an instance of something that subclasses Exception.) All the other items like strings, tuples, etc., should be checked *after* a check for the "standard" approach, yes? ---------------------------------------------------------------------- Comment By: Walter Dörwald (doerwalter) Date: 2002-07-11 10:07 Message: Logged In: YES user_id=89016 test.py is a little script that executes various test cases. ---------------------------------------------------------------------- Comment By: Walter Dörwald (doerwalter) Date: 2002-07-11 09:12 Message: Logged In: YES user_id=89016 What about the following patch (diff.txt): It allows new style objects as exceptions and makes catching exceptions by basetype possible: class newint(int): pass try: raise newint(42) except int, exc: print exc With this patch subinstances of str become raisable and will be caught be type not identity. This could be changed to explicitely forbid str subinstances. And raise type(None), None becomes ambiguous: It is interpreted as raise type(None) i.e. it raises the type(None) object as an exception, not the object None (which is of type type(None)) As soon as Exception is a new style class we could limit the allowed objects to (sub)instances of Exception. ---------------------------------------------------------------------- Comment By: Guido van Rossum (gvanrossum) Date: 2002-04-05 16:07 Message: Logged In: YES user_id=6380 Sorry, HEAPTYPE is not the proper way to check for a new-style class; it would exclude any new-style classes defined by C code. I also think that if you want to do this it should done properly, and allow "raise C, C()" as well. At best there's agreement that it's not worth trying to fix Python to allow new-style classes as exceptions when we're also trying to encourage that exceptions derive from Exception. If your module declares its exceptions as deriving from Exception, a __metaclass__ = type should not have any effect on the exceptions you declare. So I'm not sure what your problem is? Here's another idea for a patch: a new-style class is allowed as long as it also inherits from Exception. (This is possible!) ---------------------------------------------------------------------- Comment By: Jeremy Hylton (jhylton) Date: 2002-04-05 15:49 Message: Logged In: YES user_id=31392 I don't realize there was agreement on this. (I didn't follow the discussion closely.) I don't understand why exceptions need to pass an isinstance() test on Exception. It didn't used to be this way, and it makes it hard to convert a module using __metaclass__ = type. ---------------------------------------------------------------------- Comment By: Martin v. Löwis (loewis) Date: 2002-04-05 15:44 Message: Logged In: YES user_id=21627 I thought the agreement was that this is not a bug: You cannot really expect exceptions to work unless you inherit from Exception. ---------------------------------------------------------------------- Comment By: Jeremy Hylton (jhylton) Date: 2002-04-05 15:38 Message: Logged In: YES user_id=31392 Martin, I think the attached patch is sufficient. It checks object type's for Py_TPFLAGS_HEAPTYPE. I believe this is the current way to spell "new-style class" although the spelling is odd if that's the meaning <0.2 wink>. If this patch makes sense to you, I'll flesh it out with some test cases and check it in. ---------------------------------------------------------------------- Comment By: Martin v. Löwis (loewis) Date: 2002-02-17 15:44 Message: Logged In: YES user_id=21627 Interesting. I think we need to deprecate, then remove string exception before allowing arbitrary objects as exceptions. Or we could allow strings to be caught either by __builtin__.str, or by an identical string. ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=105470&aid=518846&group_id=5470 _______________________________________________ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com