This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: BaseException DeprecationError raises inappropriately
Type: behavior Stage: commit review
Components: Interpreter Core Versions: Python 2.6
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: georg.brandl Nosy List: aisaac, barry, brett.cannon, dgrisby, exarkun, ezio.melotti, georg.brandl, ivank, loewis
Priority: release blocker Keywords: patch

Created on 2009-09-05 16:24 by aisaac, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
less-deprecated-message.patch exarkun, 2009-09-16 14:05
exception-message-fix-2.diff georg.brandl, 2009-09-16 19:20
Messages (25)
msg92281 - (view) Author: Alan Isaac (aisaac) Date: 2009-09-05 16:24
In Python 2.6 if I subclass Exception and intialize my instances with a
`message` attribute, I get a DeprecationError via BaseException.

Of course there is no problem in Py3, because adding a `message`
attribute to instances of a subclass is in fact **not** a problem and
will **not** be disallowed.  I.e., the DeprecationError is raised
incorrectly in Python 2.6.

I am not sure how to raise a DeprecationError *only* in the correct
cases, but certainly the current behavior can be much improved.  As a
crude example, if the `args` passed to BaseException has length 0, then
a flag could be set not to raise this DeprecationError.  Even if not
perfect, this would be **much** better than the current behavior, since
it is common practice not to pass the subclass's initialization
arguments on to Exception.__init__.

This behavior can be expected to affect entire libraries and therefore
should be fixed.  (Eg., it affects docutils.)  I.e., "change the name of
your variable" is the wrong answer to this bug report.
msg92295 - (view) Author: Jean-Paul Calderone (exarkun) * (Python committer) Date: 2009-09-05 20:15
This also affects Twisted.  We worked around it a couple months ago by
putting a read-only `message` property onto our Exception subclass
(Here's the revision: <http://twistedmatrix.com/trac/changeset/27062>).
 This seemed reasonable enough, but it turns out that it's incompatible
with PyPy so we'll probably have to do something else instead.
msg92296 - (view) Author: ivank (ivank) Date: 2009-09-05 21:03
That trac link should be http://twistedmatrix.com/trac/changeset/27062
msg92362 - (view) Author: Duncan Grisby (dgrisby) Date: 2009-09-07 11:57
This affects my application too. We have a large body of code that uses
exception classes automatically generated from CORBA IDL, with
attributes named "message". It is infeasible for us to change to use a
different attribute name. We've ended up with dirty hacks all over the
place to suppress the warnings.
msg92384 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2009-09-07 19:11
If someone can come up w/ a patch to make this work for all of you I would 
be happy to review it and backport to 2.6. But the deprecation warning 
cannot go away as it's needed for anyone who came to rely on the feature 
in their 2.5 code from Python.
msg92386 - (view) Author: Jean-Paul Calderone (exarkun) * (Python committer) Date: 2009-09-07 19:35
After looking at this more carefully, I find myself wondering what
exactly is being deprecated at all.

Brett said:
> it's needed for anyone who came to rely on the feature  in their 2.5
code from Python.

Can someone help me understand what the feature is?
msg92387 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2009-09-07 19:44
On Mon, Sep 7, 2009 at 12:35, Jean-Paul Calderone<report@bugs.python.org> wrote:
>
> Jean-Paul Calderone <exarkun@divmod.com> added the comment:
>
> After looking at this more carefully, I find myself wondering what
> exactly is being deprecated at all.

The message attribute as introduced in Python 2.5 based on
http://www.python.org/dev/peps/pep-0348/ .

>
> Brett said:
>> it's needed for anyone who came to rely on the feature  in their 2.5
> code from Python.
>
> Can someone help me understand what the feature is?
>
> ----------
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <http://bugs.python.org/issue6844>
> _______________________________________
>
msg92388 - (view) Author: Jean-Paul Calderone (exarkun) * (Python committer) Date: 2009-09-07 20:01
Hm.  That PEP is marked as rejected, though.  I guess it was partially
implemented, those changes included in the Python 2.5 release, and then
it was decided that it was a bad idea, rejected, and the changes undone
for 3.x (what about 2.7)?  Or did something else happen?

I did a simple search on the PEP for the word "message", but the word
doesn't appear anywhere in the text!  So I guess it's a feature that's
implied by the PEP, but I would appreciate some help figuring out the
implication.

Here's what I do see:

  - If one argument is passed to BaseException.__init__, then the value
is used as the value for the message attribute.
  - If zero or more than one arguments are passed, then the attribute is
given the empty string for a value.
  - If zero or one arguments are passed, the message attribute is used
as the string representation of the exception instance.

The deprecation warning emitted in 2.6 doesn't tell me which of these
things is deprecated, though.  Is there something more to the message
attribute, or are one or more of the above list things which should no
longer be relied on?
msg92390 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2009-09-07 20:32
On Mon, Sep 7, 2009 at 13:01, Jean-Paul Calderone<report@bugs.python.org> wrote:
>
> Jean-Paul Calderone <exarkun@divmod.com> added the comment:
>
> Hm.  That PEP is marked as rejected, though.  I guess it was partially
> implemented, those changes included in the Python 2.5 release, and then
> it was decided that it was a bad idea, rejected, and the changes undone
> for 3.x (what about 2.7)?  Or did something else happen?
>

I screwed up and pasted in the URL for the wrong PEP. Sorry about
that. Written a few too many PEPs involving exceptions. The correct
one is http://www.python.org/dev/peps/pep-0352/ .

> I did a simple search on the PEP for the word "message", but the word
> doesn't appear anywhere in the text!  So I guess it's a feature that's
> implied by the PEP, but I would appreciate some help figuring out the
> implication.
>
> Here's what I do see:
>
>  - If one argument is passed to BaseException.__init__, then the value
> is used as the value for the message attribute.
>  - If zero or more than one arguments are passed, then the attribute is
> given the empty string for a value.
>  - If zero or one arguments are passed, the message attribute is used
> as the string representation of the exception instance.
>
> The deprecation warning emitted in 2.6 doesn't tell me which of these
> things is deprecated, though.  Is there something more to the message
> attribute, or are one or more of the above list things which should no
> longer be relied on?

The 'message' attribute itself is deprecated as it didn't exist prior
to being introduced in 2.5. The original idea was to not let
BaseException take multiple arguments to its constructor and have
message be what replaced 'args'. But when I tried to do that at PyCon
2007 the pain was too great so it was decided a more long-term
strategy to making BaseException accept a single argument was needed.
So the 'message' attribute that got added to BaseException was
retracted.
msg92392 - (view) Author: Alan Isaac (aisaac) Date: 2009-09-07 21:53
> The 'message' attribute itself is deprecated
> as it didn't exist prior to being introduced in 2.5.

That seems to me to be the wrong way to phrase it, and indeed that kind
of phrasing implies the current bug.  For example, it leads to the
incorrect statement that "The 'message' attribute ... didn't exist prior
to being introduced in 2.5."  But looking at the docutils and Twisted
code bases, to take two examples, tells us that it **did** exist: a slew
of instances had this attribute.  The correct statement, that
BaseException did not initialize a `message` attribute, is an entirely
different matter.

Imo, deprecating setting and accessing an **instance attribute** is just
flat out wrong and grossly violates inheritability promises.  As we have
seen.

I think (?) that what was desired to be deprecated is the combination of

- setting a message attribute via BaseException.__init__, AND
- accessing an instances message attribute that was set *this way*

But in fact the setting cannot really be deprecated because it is
implicit: it is something currently done by BaseException, not by the
user.  So I think (?) the best we can do is look at whether the user
initializes BaseException (**not** the derived classes) with a single
argument, which is a nonempty string, and then tries to access this as a
`message` attribute.  Which is why I originally proposed setting a flag
when BaseException.__init__ is called and conditioning the deprecation
warning on this flag.  (E.g., the flag could be set if and only if the
user calls BaseException.__init__(instance, string).)

In any case, I think Jean-Paul is asking exactly the right question
(i.e., just what exactly is being deprecated?).  A more careful answer
will hopefully lead to less buggy DeprecationWarning.
msg92393 - (view) Author: Jean-Paul Calderone (exarkun) * (Python committer) Date: 2009-09-07 21:57
Alright.  So in Python 3.1, this is the behavior:

>>> BaseException().message
(attribute error)
>>> BaseException("foo").message
(attribute error)
>>> BaseException("foo", "bar").message
(attribute error)
>>> x = BaseException()
>>> x.message = "foo"
>>> x.message
'foo'
>>> x = BaseException("foo")
>>> x.message = "bar"
>>> x.message
'bar'
>>> x = BaseException("foo")
>>> x.message = "bar"
>>> x.message
'bar'

So I propose the following as the new behavior for 2.x:

>>> BaseException().message
(deprecation warning)
''
>>> BaseException("foo").message
(deprecation warning)
'foo'
>>> BaseException("foo", "bar").message
(deprecation warning)
''
>>> x = BaseException()
>>> x.message = "foo"
>>> x.message
'foo'
>>> x = BaseException("foo")
>>> x.message = "bar"
>>> x.message
'bar'
>>> x = BaseException("foo", "bar")
>>> x.message = "baz"
>>> x.message
'baz'

Summarized: emit a warning when the same code in Python 3.1 would raise
an exception; let all other cases pass.

There is one other case that I would think about changing, but I don't
see how it can, given the behavior that is implemented in 3.1 already. 
BaseException("a message") is a Python 2.5-supported way of creating an
exception with a value for its message attribute.  This no longer works
in Python 3.1.  So, arguably, this is another case where a deprecation
warning should be emitted.  However, this would be pretty obnoxious,
since BaseException("a message") in Python 2.4 (by way of Exception("a
message"), of course, since Python 2.4 did not have BaseException) was
perfectly valid.  It seems like BaseException(string) should have been
deprecated and BaseException(tuple) been made the preferred API.  That's
for another time, though.

How does the above proposed deprecation behavior sound?
msg92394 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2009-09-07 22:07
On Mon, Sep 7, 2009 at 14:57, Jean-Paul Calderone<report@bugs.python.org> wrote:
>
> Jean-Paul Calderone <exarkun@divmod.com> added the comment:
>
> Alright.  So in Python 3.1, this is the behavior:
>
>>>> BaseException().message
> (attribute error)
>>>> BaseException("foo").message
> (attribute error)
>>>> BaseException("foo", "bar").message
> (attribute error)
>>>> x = BaseException()
>>>> x.message = "foo"
>>>> x.message
> 'foo'
>>>> x = BaseException("foo")
>>>> x.message = "bar"
>>>> x.message
> 'bar'
>>>> x = BaseException("foo")
>>>> x.message = "bar"
>>>> x.message
> 'bar'
>
> So I propose the following as the new behavior for 2.x:
>
>>>> BaseException().message
> (deprecation warning)
> ''
>>>> BaseException("foo").message
> (deprecation warning)
> 'foo'
>>>> BaseException("foo", "bar").message
> (deprecation warning)
> ''
>>>> x = BaseException()
>>>> x.message = "foo"
>>>> x.message
> 'foo'
>>>> x = BaseException("foo")
>>>> x.message = "bar"
>>>> x.message
> 'bar'
>>>> x = BaseException("foo", "bar")
>>>> x.message = "baz"
>>>> x.message
> 'baz'
>
> Summarized: emit a warning when the same code in Python 3.1 would raise
> an exception; let all other cases pass.
>
> There is one other case that I would think about changing, but I don't
> see how it can, given the behavior that is implemented in 3.1 already.
> BaseException("a message") is a Python 2.5-supported way of creating an
> exception with a value for its message attribute.  This no longer works
> in Python 3.1.  So, arguably, this is another case where a deprecation
> warning should be emitted.  However, this would be pretty obnoxious,
> since BaseException("a message") in Python 2.4 (by way of Exception("a
> message"), of course, since Python 2.4 did not have BaseException) was
> perfectly valid.  It seems like BaseException(string) should have been
> deprecated and BaseException(tuple) been made the preferred API.  That's
> for another time, though.
>
> How does the above proposed deprecation behavior sound?

Works for me. If someone can create a patch for that I will review it
and apply it to 2.6 (the warning will be removed from 2.7 and so will
the attribute).
msg92439 - (view) Author: Jean-Paul Calderone (exarkun) * (Python committer) Date: 2009-09-09 01:57
Can I add a field to the PyBaseExceptionObject struct?
msg92442 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2009-09-09 02:18
I had a feeling you were going to ask that. =) I think it's fine, and from 
what I can tell from PEP 384 it's okay as long as it is in no way publicly 
exposed. But I have added Martin to the nosy list to make sure I am not 
messing up the ABI somehow in a micro release.
msg92454 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2009-09-09 16:22
Making this a release blocker to see what Barry thinks of this.
msg92556 - (view) Author: Alan Isaac (aisaac) Date: 2009-09-12 23:30
Since you are working on this, can you see if 
http://bugs.python.org/issue6108 
is related or in any case can be fixed at the same time?

Thanks.
msg92562 - (view) Author: Jean-Paul Calderone (exarkun) * (Python committer) Date: 2009-09-13 05:08
FWIW, I'm waiting to hear about the acceptability of adding fields to
the exception structure(s) before I work on this patch.
msg92679 - (view) Author: Barry A. Warsaw (barry) * (Python committer) Date: 2009-09-16 12:24
I agree that this is a release blocker for 2.6.3
msg92687 - (view) Author: Jean-Paul Calderone (exarkun) * (Python committer) Date: 2009-09-16 14:05
I'm not sure I'll be able to work on this again for a while after this
morning, so here's a patch.  I don't really understand how the exception
structs are involved here, so I don't really know why the patch works,
but it seems to.  If there's something wrong with it, someone else may
need to fix it in order to have it ready for 2.6.3.
msg92708 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2009-09-16 19:20
The patch leads to crashes with all the exceptions that have their own
structs; since they are derived from BaseException they must start with
the same binary layout as PyBaseExceptionObject (pointers to any
exception will be cast to PyBaseExceptionObject).

This also shows one way in which this change can mess up third-party
extensions (though I don't know if anybody does that): if some extension
created new exception classes doing it the way we do, e.g. for SyntaxError.

However, I have a different suggestion: we could put a user-set
"message" in the __dict__.  The getter would then check for that first
and only warn if it falls back to self->message. See attached patch.
msg92709 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2009-09-16 19:28
Huh. I just made some tests to find out if exceptions with a message set
survive pickling in 2.6.2 and unpickling in patched trunk.

I found that the message attribute isn't pickled at all in 2.6.2, so
there should be no cross-version compatibility problems with pickles.
msg92710 - (view) Author: Alan Isaac (aisaac) Date: 2009-09-16 19:38
I hope it is not too annoying to link these ...

I asked thhis of Jean-Paul but now I'll ask it of George.
Since you are working on this, can you see if 
http://bugs.python.org/issue6108 
is related or in any case can be fixed at the same time?

Thanks.
msg92712 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2009-09-16 19:41
Yes, it should be fixed, but it is not related.  I'm setting it as a
release blocker as well.
msg92714 - (view) Author: Brett Cannon (brett.cannon) * (Python committer) Date: 2009-09-16 20:01
Just looked at the patch and it looks good to me. I say go ahead and 
commit, Georg.
msg92718 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2009-09-16 20:35
OK, I added another test for pickling, committed in r74845, and
backported to 2.6 in r74848.
History
Date User Action Args
2022-04-11 14:56:52adminsetgithub: 51093
2009-12-11 23:13:02ezio.melottilinkissue5716 superseder
2009-09-16 20:35:23georg.brandlsetstatus: open -> closed
resolution: fixed
messages: + msg92718
2009-09-16 20:01:31brett.cannonsetassignee: loewis -> georg.brandl
messages: + msg92714
stage: commit review
2009-09-16 19:41:31georg.brandlsetmessages: + msg92712
2009-09-16 19:38:35aisaacsetmessages: + msg92710
2009-09-16 19:28:50georg.brandlsetmessages: + msg92709
2009-09-16 19:20:22georg.brandlsetfiles: + exception-message-fix-2.diff

messages: + msg92708
2009-09-16 14:05:42exarkunsetfiles: + less-deprecated-message.patch
keywords: + patch
messages: + msg92687
2009-09-16 12:24:34barrysetnosy: + barry
messages: + msg92679
2009-09-13 05:17:00ezio.melottisetnosy: + ezio.melotti
2009-09-13 05:08:03exarkunsetmessages: + msg92562
2009-09-12 23:30:14aisaacsetmessages: + msg92556
2009-09-09 16:22:01brett.cannonsetpriority: release blocker

messages: + msg92454
2009-09-09 02:18:44brett.cannonsetassignee: loewis

messages: + msg92442
nosy: + loewis
2009-09-09 01:57:12exarkunsetmessages: + msg92439
2009-09-07 22:07:54brett.cannonsetmessages: + msg92394
2009-09-07 21:57:54exarkunsetmessages: + msg92393
2009-09-07 21:53:30aisaacsetmessages: + msg92392
2009-09-07 20:34:40georg.brandlsetnosy: + georg.brandl
2009-09-07 20:32:47brett.cannonsetmessages: + msg92390
2009-09-07 20:01:48exarkunsetmessages: + msg92388
2009-09-07 19:44:24brett.cannonsetmessages: + msg92387
2009-09-07 19:35:26exarkunsetmessages: + msg92386
2009-09-07 19:11:36brett.cannonsetmessages: + msg92384
2009-09-07 19:04:12brett.cannonsetnosy: + brett.cannon
2009-09-07 11:57:06dgrisbysetnosy: + dgrisby
messages: + msg92362
2009-09-05 21:03:15ivanksetnosy: + ivank
messages: + msg92296
2009-09-05 20:15:40exarkunsetnosy: + exarkun
messages: + msg92295
2009-09-05 16:24:53aisaaccreate