[Python-Dev] decimal.py signals & traps
David Goodger
goodger at python.org
Thu Jul 8 03:55:11 CEST 2004
There's a problem in the decimal.py API regarding signals & traps. I
noticed Raymond's checkin enabling certain traps (thanks Raymond!), so
I updated my copy and played around a bit:
>>> from decimal import Decimal
>>> Decimal('1')/0
Traceback (most recent call last):
...
decimal.DivisionByZero: x / 0
As expected. But:
>>> Decimal('0')/0
Decimal("NaN")
I expected this to raise decimal.DivisionUndefined. Even worse:
>>> Decimal('bogus')
Decimal("NaN")
That should have raised decimal.ConversionSyntax. This behavior
obviously doesn't agree with:
[Tim Peters]
> You can't get a NaN or infinity from finite operands without
> signaling one of the 3 I recommend trap-enabling, so enabling those
> traps stops their program the instant the first NaN or infinity
> appears.
The problem is that the implementation associates traps with what it
calls "signals" but the spec & PEP 327 call "conditions". I believe
that led to a misunderstanding:
[Tim Peters]
> I'm still of the opinion that the invalid-operation, overflow, and
> division-by-zero traps should be enabled by default, and the others
> disabled
Tim is referring to traps associated with spec/PEP-defined "signals".
Raymond implemented the default-enabled traps like this:
_default_traps.update(
{DivisionByZero:1, Overflow:1, InvalidOperation:1})
Take a look at the "Signal" column of the table in
<http://www.python.org/peps/pep-0327.html#exceptional-conditions>.
The "invalid-operation" *signal* is associated with 5 different
*conditions*: conversion syntax, division impossible, division
undefined, invalid context, and invalid operation. The spec/PEP lists
12 conditions and 8 signals, but
>>> len(decimal.Signals)
13
decimal.Signals is actually a list of spec/PEP *conditions*, with
decimal.DecimalException (the base exception class) also included.
The easy solution is to change
_default_traps.update(
{DivisionByZero:1, Overflow:1, InvalidOperation:1})
to
_default_traps.update(
{DivisionByZero:1, Overflow:1, InvalidOperation:1,
ConversionSyntax:1, DivisionImpossible:1, DivisionUndefined:1,
InvalidContext})
But I don't think that's the best solution. It still leaves the
mismatch between spec/PEP "signals" and implementation "signals".
Should traps be set on spec/PEP conditions, or spec/PEP signals? If
the former, decimal.Signals should at least be renamed to
decimal.Conditions. If the latter, decimal.py's implementation of
exceptions needs to be reworked.
--
David Goodger <http://python.net/~goodger>
More information about the Python-Dev
mailing list