Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

np.bool_ and bool are incompatible #10385

Closed
mlondschien opened this issue Apr 30, 2021 · 7 comments
Closed

np.bool_ and bool are incompatible #10385

mlondschien opened this issue Apr 30, 2021 · 7 comments
Labels
bug mypy got something wrong

Comments

@mlondschien
Copy link

Bug Report

From numpy/numpy#18876:

Reproducing code example:

# example.py
import numpy as np

def f(x: bool) -> bool:
    return x

y = np.bool_(True)

print(f(y))

yields

$ mypy example.py
example.py:9: error: Argument 1 to "f" has incompatible type "bool_"; expected "bool"
Found 1 error in 1 file (checked 1 source file)

The same happens for the inverse:

# example.py
import numpy as np

def f(x: np.bool_) -> np.bool_:
    return x

y = True

print(f(y))

results in

example.py:9: error: Argument 1 to "f" has incompatible type "bool"; expected "bool_"

np.float_ and np.int_ work fine.

As @BvB93 points out, this is not an issue that numpy can fix, as python does not allow creating subclasses of bool:

Runtime:

In [1]: class bool_(bool): pass
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-1-823896cfc52c> in <module>
----> 1 class bool_(bool): pass

TypeError: type 'bool' is not an acceptable base type

mypy:

In [2]: from typing import TYPE_CHECKING

In [3]: if TYPE_CHECKING:
   ...:     class bool_(bool): pass  # error: 'bool' is not a valid base class
   ...:

Is there a possibility to fix this within mypy? E.g. by adding a new Bool or BoolLike type that allows for comparisons. numpy could then possibly create np.bool_ as a subclass of Bool.

@mlondschien mlondschien added the bug mypy got something wrong label Apr 30, 2021
@mmiller-max
Copy link

👍 Would be good to have a fix for this!

@ethanhs
Copy link
Collaborator

ethanhs commented Nov 1, 2021

I think that you could maybe make a mypy plugin, but otherwise I'm not sure if there is much to be done here. A BookLike protocol could be made I suppose (anything that implements __bool__), but you should email the typing-sig mailing list about that if you want to make it happen.

@ethanhs ethanhs closed this as completed Nov 1, 2021
@pranavrajpal
Copy link
Contributor

What exactly is your use case for treating np.bool_ and bool as interchangeable? If np.bool_ isn't a subclass of bool according to Python itself, then allowing one to be used where the other is expected just seems like it would prevent mypy from noticing bugs that might arise from code that expects a bool but gets an np.bool_ (or vice versa), and can only handle one of those correctly.

@mmiller-max
Copy link

What exactly is your use case for treating np.bool_ and bool as interchangeable? If np.bool_ isn't a subclass of bool according to Python itself, then allowing one to be used where the other is expected just seems like it would prevent mypy from noticing bugs that might arise from code that expects a bool but gets an np.bool_ (or vice versa), and can only handle one of those correctly.

I can't answer for the original poster but yes I agree with this. I think I was imagining a parent class for both np.bool_ and bool.

For context, the issue arose for me when upgrading numpy versions, I'm guessing that where it previously outputted bool it switched to np.bool_ which was breaking mypy tests. As you point out this is actually a correct failure as they are different classes.

@BvB93
Copy link
Contributor

BvB93 commented Nov 4, 2021

While I don't think np.bool_ should be treated as a subtype of bool (or vice versa), some way of denoting that an object can safelly be used for truth-testing would be a useful feature, in my opinion. A SupportsBool protocol is currently effectivelly useless for this purpose due to the presence object.__bool__.

Perhaps something that similar to the strict_equality flag, except that works with explicitly defined __bool__ methods instead of __eq__?

@ethanhs
Copy link
Collaborator

ethanhs commented Nov 4, 2021

There is no object.__bool__ unless I'm mistaken? Though I think you mean "objects can be truthy/falsey". Regardless at the type level, in typeshed object doesn't have a __bool__ so I think a SupportsBool could work.

@BvB93
Copy link
Contributor

BvB93 commented Nov 5, 2021

There is no object.__bool__ unless I'm mistaken?

No, you're right here actually. Somehow I must have misremembered object.__bool__.
In that case, a SupportsBool protocol would probably be adequate here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

No branches or pull requests

5 participants