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: decimal.py: use DivisionImpossible and DivisionUndefined
Type: behavior Stage: needs patch
Components: Versions: Python 3.1, Python 3.2, Python 2.7, Python 2.6
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: mark.dickinson Nosy List: mark.dickinson, skrah
Priority: normal Keywords:

Created on 2009-10-03 13:30 by skrah, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
div-deccheck2.py skrah, 2009-10-03 13:30 div-deccheck2.py
Messages (6)
msg93490 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2009-10-03 13:30
In many cases, decimal.py sets InvalidOperation instead of
DivisionImpossible or DivisionUndefined.

Mark, could I persuade you to isolate these cases by running a modified
deccheck2.py from mpdecimal (See attachment), which does not suppress
differences in the division functions?
msg93496 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2009-10-03 15:26
Just to be clear, the decimal context doesn't (and shouldn't) know about DivisionImpossible:  there's 
no DivisionImpossible signal or trap described in the specification, but just a DivisionImpossible 
heading in the 'exceptional conditions' section of the spec.  And that DivisionImpossible condition 
signals InvalidOperation (according to the spec).  (And similarly for DivisionUndefined.)

So I don't think decimal.py is in violation of the specification here.

But decimal.py could be changed so that a call to _raise_error(context, DivisionImpossible, ...)
results in the DivisionImpossible exception being raised instead of the InvalidOperation exception.
This shouldn't break anything, since DivisionImpossible is a subclass of InvalidOperation.

Note that the appropriate sections of decimal.py do already raise the right conditions (unless some 
have been missed):  e.g., in Decimal._divide, we have the lines:

    # Here the quotient is too large to be representable                                                                                                                                              
    ans = context._raise_error(DivisionImpossible,
                               'quotient too large in //, % or divmod')

But the Context._raise_error method currently translates all the exceptional conditions to their 
corresponding signals, hence raises InvalidOperation in this case.
msg93498 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2009-10-03 15:33
Closed issue 7047 as a duplicate of this one:  
_raise_error(ConversionSyntax) also raises (if trapped) the 
InvalidOperation exception, when it could reasonably raise 
ConversionSyntax instead.  It's the same cause as above:  _raise_error 
translates each exceptional condition to the corresponding signal.
msg93509 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2009-10-03 22:06
Thanks for the explanation, and I agree that decimal.py is perfectly
correct. I based the report on the fact that decNumber updates the
context status with e.g. Division_impossible. But Division_impossible is
one of the flags that form IEEE_754_Invalid_operation, so presumably the
intention is to signal IEEE_754_Invalid_operation by means of flagging
Division_impossible.

On a side note, I find the distinction between signals and exceptional
conditions (mandated by the spec, as you pointed out) needlessly
complicated and I'm happy to see that note 5 under "Abstract
representation of context" says this might change in the future.

I'm all for raising DivisionImpossible, if it is not too much trouble.
msg95789 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2009-11-28 15:36
I think it's actually easier for the user if we keep the exception type 
as it is, so that it's clear which flag it corresponds to.  This didn't 
occur to me until I looked at the section of the doctests (around line 
100 in decimal.py) that looks like:

>>> print c.divide(Decimal(0), Decimal(0))
Traceback (most recent call last):
  ...
  ...
  ...
InvalidOperation: 0 / 0
>>> print c.flags[InvalidOperation]
1

If the traceback specified 'DivisionUndefined' instead then the user has 
to figure out that the corresponding flag/trap is InvalidOperation.

Of course this could be worked around by giving a more detailed error 
message, e.g. DivisionUndefined: (InvalidOperation) 0/0, but this 
doesn't seem worth changing to me.
msg95835 - (view) Author: Stefan Krah (skrah) * (Python committer) Date: 2009-11-30 12:50
I agree that it might add confusion. In the C-module,I currently
do this:

>>> Decimal(0) / 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
cdecimal.InvalidOperation: [<class 'cdecimal.DivisionUndefined'>]


But since you already have a detailed error message, this doesn't
seem necessary for decimal.py.

Close this one?
History
Date User Action Args
2022-04-11 14:56:53adminsetgithub: 51295
2009-11-30 19:31:24rhettingersetstatus: open -> closed
resolution: rejected
2009-11-30 12:50:21skrahsetmessages: + msg95835
2009-11-28 15:36:19mark.dickinsonsetmessages: + msg95789
2009-10-03 22:06:47skrahsetmessages: + msg93509
2009-10-03 15:33:57mark.dickinsonsetpriority: normal
assignee: mark.dickinson
stage: needs patch
type: behavior
versions: + Python 2.6, Python 3.1, Python 2.7, Python 3.2
2009-10-03 15:33:03mark.dickinsonsetmessages: + msg93498
2009-10-03 15:30:52mark.dickinsonlinkissue7047 superseder
2009-10-03 15:26:17mark.dickinsonsetmessages: + msg93496
2009-10-03 13:30:55skrahcreate