[issue47121] math.isfinite() can raise exception when called on a number

2022-04-08 Thread Thomas Fischbacher


Thomas Fischbacher  added the comment:

Tim, the problem may well be simply due to the documentation of math.isfinite() 
being off here.

This is what we currently have:

https://docs.python.org/3/library/math.html#math.isfinite

===
math.isfinite(x)
Return True if x is neither an infinity nor a NaN, and False otherwise. (Note 
that 0.0 is considered finite.)

New in version 3.2.
===

If this were re-worded as follows (and corresponding changes were made to other 
such functions), everyone would know what the expectations and behavior are:

===
math.isfinite(x)

If `x` is a `float` instance, this evaluates to `True` if `x` is
neither a float infinity nor a NaN, and `False` otherwise.
If `x` is not a `float` instance, this is evaluates to
`math.isfinite(float(x))`.

New in version 3.2.
===

This would be an accurate defining description of the actual behavior. Note 
that, "thanks to PEP-484", this abbreviation would currently be ambiguous 
though:

===
math.isfinite(x)

If `x` is a float, this evaluates to `True` if `x` is
neither a float infinity nor a NaN, and `False` otherwise.
If `x` is not a float, this is evaluates to
`math.isfinite(float(x))`.

New in version 3.2.
===

("ambiguous" since "float" means different things as a static type and as a 
numbers class - and it is not clear what would be referred to here).

Changing/generalizing the behavior might potentially be an interesting other 
proposal, but I would argue that then one would want to change the behavior of 
quite a few other functions here as well, and all this should then perhaps go 
into some other `xmath` (or so) module - bit like it is with `cmath`.

However, since the Python philosophy is to not rely on bureaucracy to enforce 
contracts (as C++, Java, etc. do it), but instead to rely on people's ability 
to define their own contracts, making the math.isfinite() contract more 
accurate w.r.t. actual behavior in the CPython implementation via extra 
clarification looks like a good thing to do, no?

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue47121] math.isfinite() can raise exception when called on a number

2022-04-05 Thread Tim Peters


Tim Peters  added the comment:

I'll testify that I won't volunteer one second of my time pursuing these 
abstract "purity" crusades ;-) `isfinite()` et alia were added to supply 
functions defined by current standards to work on IEEE floating-point values. 
People working with floats have reasonable expectations that Python will supply 
workalikes for industry-stand float functions.

If was had to cater to all possible "numberish" types, we'd never add anything 
new again :-( Doing that in a principled way requires dedicated new dunder 
methods, and that's a high bar.

That I said, I extended math.log() decades ago to work on giant integers. It 
was useful for real projects I was working on at the time - I was scratching my 
own itches.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue47121] math.isfinite() can raise exception when called on a number

2022-04-05 Thread Raymond Hettinger


Raymond Hettinger  added the comment:

> isfinite() should return True for all ints, without needing
> to coerce them to float

Whoa there.  You're venturing into changing what those math functions were all 
about and the core approach to how they operate.

A zigzag to this new direction would need discussion with all the math folks.  
Many tools in the math module are thin wrapper around libmath and we never 
intended to be universal handlers of all numeric types.  We have a lot of 
functions that start by coercing their input to a float.

My two cents is that this would open an endless can of worms and make everyone 
pay a time and complexity cost for a feature that almost no one needs.  AFAICT 
is more of a purity issue than an actual practical need that would warrant 
separate code paths (for example, we recently closed an issue where someone 
wanted math.log() to have a separate code path for Fraction inputs where it 
return log(f.numerator) - log(f.denominator) with the goal of handling 
fractional values smaller than float_min).

--
nosy: +mark.dickinson, tim.peters

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue47121] math.isfinite() can raise exception when called on a number

2022-04-05 Thread Steven D'Aprano


Steven D'Aprano  added the comment:

Isn't this just a quality of implementation issue?

math.isfinite should return True for all ints, since all ints are finite. 
(There are no int infinities or NANs). There is no need to coerce them to float 
to know that they are finite.

Likewise for Fractions. If they overflow, that could be caught and True 
returned.

Decimal infinities convert to float infinities, so the only way you can get an 
overflow error is if the Decimal is finite but too big to convert. So again, 
isfinite could (should?) catch the overflow error and return True.

Any numeric type that has an infinity which does not coerce to float infinity, 
but overflows instead, is buggy, and its not isfinite's responsibility to 
protect against that.

So here is my suggestion:

isfinite() should return True for all ints, without needing to coerce them to 
float. For other numeric types, it should try to coerce them to float, and 
catch OverflowError and raise True. This should be documented, so that other 
numeric types know what contract they are required to follow (infinity coerces 
to float infinity).

I'm going to change this to an enhancement for 3.11 (or 3.12).

--
nosy: +steven.daprano
type:  -> enhancement
versions: +Python 3.11

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue47121] math.isfinite() can raise exception when called on a number

2022-03-25 Thread Serhiy Storchaka


Serhiy Storchaka  added the comment:

Most (but not all) functions in the math module implicitly convert its 
arguments to float. Here we can get an OverflowError. Do we want to add a note 
to every function that does it? Or add a general note at the top of the file 
and add exclusion notes to functions which do not convert arguments to float?

BTW, there is a general note: "Except when explicitly
noted otherwise, all return values are floats."

--
nosy: +serhiy.storchaka

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue47121] math.isfinite() can raise exception when called on a number

2022-03-25 Thread Thomas Fischbacher


Thomas Fischbacher  added the comment:

The problem with PEP-484 is that if one wants to use static type analysis, 
neither of these options are good:

- Use static annotations on functions, and additionally spec
  out expectations in docstrings. Do note that the two types places
  where "float" is mentioned here refer to different concepts.
  This looks as if there were duplication, but there actually
  isn't, since the claims are different. This is confusing as hell.

def foo(x: float) -> float:
  """Foos the barbaz

  Args:
x: float, the foobar
  Returns:
float, the foofoo"""

The floats in the docstring give me a guarantee: "If I feed in a float, I am 
guaranteed to receive back a float". The floats in the static type annotation 
merely say "yeah, can be float or int, and I'd call it ok in these cases" - 
that's a very different statement.

- Just go with static annotations, drop mention of types
  from docstrings, and accept that we lose the ability to
  stringently reason about the behavior of code.

With respect to this latter option, I think we can wait for "losing the ability 
to stringently reason about the behavior of code" to cause major security 
headaches. That's basically opening up the door to many problems at the level 
of "I can crash the webserver by requesting the url http://lpt1;.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue47121] math.isfinite() can raise exception when called on a number

2022-03-25 Thread Raymond Hettinger


Raymond Hettinger  added the comment:

The math.isfinite() docs could be changed to something like, "coerces x to a 
float if possible and then returns True if x is neither an infinity nor a NaN, 
and False otherwise."  Or there could be a general note about which functions 
(most of them) coerce to float (which can fail).

With respect to typing and PEP-484, I don't see a bug or documentation issue.  
Types relationships are useful for verifying which methods are available, but 
they don't make promises about the range of valid values.  For example 
math.sqrt(float) -> float promises which types are acceptable but doesn't 
promise that negative inputs won't raise an exception.  Likewise, "n: int=10; 
len(range(n))" is type correct but will raise an OverflowError for "n = 
10**100".

--
assignee:  -> docs@python
components: +Documentation
nosy: +docs@python, rhettinger

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue47121] math.isfinite() can raise exception when called on a number

2022-03-25 Thread Nathaniel Manista


Change by Nathaniel Manista :


--
nosy: +Nathaniel Manista

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue47121] math.isfinite() can raise exception when called on a number

2022-03-25 Thread Thomas Fischbacher


New submission from Thomas Fischbacher :

>>> help(math.isfinite)
isfinite(x, /)
Return True if x is neither an infinity nor a NaN, and False otherwise.

So, one would expect the following expression to return `True` or `False`. We 
instead observe:

>>> math.isfinite(10**1000)
Traceback (most recent call last):
  File "", line 1, in 
OverflowError: int too large to convert to float

(There likewise is a corresponding issue with other, similar, functions).

This especially hurts since PEP-484 states that having a Sequence[float] `xs` 
does not allow us to infer that `all(issubclass(type(x), float) for x in xs)` 
actually holds - since a PEP-484 "float" actually does also include "int" (and 
still, issubclass(int, float) == False).

Now, strictly speaking, `help(math)` states that

DESCRIPTION
This module provides access to the mathematical functions
defined by the C standard.

...but according to "man 3 isfinite", the math.h "isfinite" is a macro and not 
a function - and the man page does not show type information for that reason.

--
messages: 416010
nosy: tfish2
priority: normal
severity: normal
status: open
title: math.isfinite() can raise exception when called on a number

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com