[Python-Dev] decimal.py signals & traps (original) (raw)

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