[issue35712] Make NotImplemented unusable in boolean context

2021-09-20 Thread Alex Waygood


Alex Waygood  added the comment:

Thanks, Serhiy, that makes sense. I'll consider raising this elsewhere, as you 
suggest.

--

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2021-09-20 Thread Serhiy Storchaka


Serhiy Storchaka  added the comment:

Interesting, it is because object().__eq__(object()) returns NotImplemented 
instead of False.

object.__eq__ could return False if arguments have same type (or in some other 
cases). I think it would not break anything, and it would fix your case. But I 
am not sure that it is worth to change this. Using bound methods __eq__ and 
__ne__ is an antipattern, and we should not encourage this, even if it is safe 
as in your case. If you want to discuss this more, it is better to do this on a 
mailing-list or Discuss.

Your code can be rewritten as:

def other_colour(self):
for other in CardColour:
if self != other:
return other
assert False, "not reachable"

--

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2021-09-20 Thread Alex Waygood


Alex Waygood  added the comment:

Thanks, Vedran. I read https://bugs.python.org/issue35712#msg349303 before 
adding my message, but am not quite clear why my snippet is the same situation. 

`next(filter((2).__eq__, 'text'))` surely returns 't' because `(2).__eq__('t')` 
returns `NotImplemented`, and `NotImplemented` is truthy. (Apologies if my 
understanding is wrong here.)

I'm unclear, however, why `x.__ne__(y)` should ever return `NotImplemented` (or 
even have the possibility of returning `NotImplemented`) if it is known that 
both `x` and `y` are members of the same `Enum`. The documentation for `Enum`s 
clearly states that equality comparisons between members of the same enum are 
defined (https://docs.python.org/3/library/enum.html#comparisons).

If the argument is "filter should never be used with a predicate that could 
return `NotImplemented` in some situations", then I think that could usefully 
be added to the documentation for `filter`. Moreover, if that is the argument, 
then I don't understand why the following does not raise a DeprecationWarning:

```
>>> next(filter((2).__eq__, (2, 3, 4)))
2
```

Again, apologies if I'm missing something here.

--

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2021-09-20 Thread Vedran Čačić

Vedran Čačić  added the comment:

Please see the message https://bugs.python.org/issue35712#msg349303. Filtering 
with those dunder sesqui-dispatch methods really is a bug magnet.

--

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2021-09-20 Thread Alex Waygood


Alex Waygood  added the comment:

The following code now leads to a `DeprecationWarning`, but I am unclear why it 
should.

```
>>> from enum import Enum
>>> 
>>> class CardColour(Enum):
... """Enumeration of the two colours in a pack of cards."""
... 
... BLACK = 'black'
... RED = 'red'
... 
... def other_colour(self):
... """Given one colour, get the other one."""
... return next(filter(self.__ne__, CardColour))
... 
>>> CardColour.BLACK.other_colour()
:5: DeprecationWarning: NotImplemented should not be used in a boolean 
context

```

If I change the last line of `other_colour` to either `return next(colour for 
colour in CardColour if colour != self)` or `return next(colour for colour in 
CardColour if colour is not self)`, the warning goes away.

Is this intended behaviour?

--
nosy: +AlexWaygood

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2020-11-09 Thread Guido van Rossum


Change by Guido van Rossum :


--
nosy:  -gvanrossum

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2020-11-09 Thread Serhiy Storchaka


Serhiy Storchaka  added the comment:

I am sad that such code (as well as my former code in total_ordering) no longer 
works, but this is just a clever trick, and the code can be written in less 
clever but more explicit way.

On other hand, the warning helps to catch common mistakes like

   not self.__lt__(other)
   self.__lt__(other) or self.__eq__(other)
   super().__eq__(other) and self.x == other.x

Even non-beginners often make such kind of mistakes, and it is hard to catch 
them if you have not trained yourself specially. I suggest you to include 
lessons about writing complex comparison methods in your course for advanced 
users.

--

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2020-11-09 Thread Raymond Hettinger


Raymond Hettinger  added the comment:

> I assume you've been recommending this?

Not really, but it does come up and I've seen it in customer code more than 
once.

I do show people this:

>>> data = [10.5, 3.27, float('Nan'), 56.1]
>>> list(filter(isfinite, data))
[10.5, 3.27, 56.1]
>>> list(filterfalse(isnan, data))
[10.5, 3.27, 56.1]

The question does arise about how to do this for None using functional 
programming.  The answer is a bit awkward:

>>> from operator import is_not
>>> from functools import partial
>>> data = [10.5, 3.27, None, 56.1]
>>> list(filter(partial(is_not, None), data))
[10.5, 3.27, 56.1]

>From a teaching point of view, the important part is to show that this code 
>does not do what people typically expect:

>>> data = [10.5, 0.0, float('NaN'), 3.27, None, 56.1]
>>> list(filter(None, data))
[10.5, nan, 3.27, 56.1]

FWIW, this issue isn't important to me.  Just wanted to note that one of the 
idioms no longer works.  There are of course other ways to do it.

--

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2020-11-09 Thread Guido van Rossum


Guido van Rossum  added the comment:

That's off topic for this issue -- you can go to python-ideas to propose that.

--

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2020-11-09 Thread Vedran Čačić

Vedran Čačić  added the comment:

... as it probably should: look at https://bugs.python.org/msg349303

Yes, filtering comprehensions are a frequently used niche, and too long in the 
"official" parlance. I seem to recall that 

[x in mylist if x is not None]

(instead of triple-x version) was rejected because it was too hard to parse. 
Maybe now we can really implement it?

--

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2020-11-09 Thread Guido van Rossum


Guido van Rossum  added the comment:

> list(filter(None.__ne__, L))

I assume you've been recommending this? To me it looks obfuscated. People 
should just use a comprehension, e.g.

[x for x in L if x is not None]

--

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2020-11-09 Thread Raymond Hettinger


Raymond Hettinger  added the comment:

One of the idioms for removing None no longer works:

>>> L = [0, 23, 234, 89, None, 0, 35, 9]
>>> list(filter(None.__ne__, L))
Warning (from warnings module):
  File "", line 1
DeprecationWarning: NotImplemented should not be used in a boolean context
[0, 23, 234, 89, 0, 35, 9]

--
nosy: +rhettinger

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2020-03-12 Thread Ethan Furman


Ethan Furman  added the comment:

Hmm.  Okay, I'm happy with just raising a TypeError in NotImplemented.__bool__.

--

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2020-03-11 Thread Serhiy Storchaka


Serhiy Storchaka  added the comment:

> How is -1 interpreted?  Does it become a TypeError?

It is interpreted as error. It requires an exception be set. If you return -1 
without setting an exception you will usually get a SystemError or crash. Oh, 
and this may happen during executing other code, so you will search a bug in 
wrong place.

You cannot change this without breaking the C and Python API in hard way.

> So my thinking is that when the interpreter gets the `NotImplemented` 
> returned by either `if a` or by `if not a` that it would be converted to a 
> `TypeError`

> and the `and` machinery sees it has a `NotImplemented` and raises a 
> `TypeError`.

So you literally want NotImplemented raising a TypeError in boolean context 
except the "not" operator, and redefine `not a` from

False if a else True

to

NotImplemented if a is NotImplemented else False if a else True

You can do this, but this is a different issue, and I doubt that it will solve 
many problems.

--

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2020-03-11 Thread Ethan Furman


Ethan Furman  added the comment:

Serhiy:
--
> First, it is impossible. nb_bool and PyObject_IsTrue() can return
> only three value: 1 for true, 0 for false, and -1 for error.

Huh.  How is -1 interpreted?  Does it become a TypeError?


> It is not possible to represent NotImplemented without breaking all
> extensions.
> 
> Currently
> 
> if not a:
> b()
> else:
> c()
> 
> is equivalent to
> 
>if a:
>c()
> else:
> b()
> 
> If a is NotImplemented, what branch be executed in every case?

Side-stepping to other __dunder__ methods for a moment: if, for example, both 
__add__ and __radd__ return NotImplemented then the interpreter will convert 
that into a TypeError.

So my thinking is that when the interpreter gets the `NotImplemented` returned 
by either `if a` or by `if not a` that it would be converted to a `TypeError`, 
meaning none of the branches would be executed as an exception would be raised 
instead.

> Second, it would not help. Because real-world examples are not always so
> trivial as "return not self.__lt__(other)". It may be a part of more
> complex expression, e.g.:
> 
> return super().__eq__(other) and self.attr == other.attr

I don't see the problem -- breaking it down:

return super().__eq__(other) and self.attr == other.attr

becomes

return NotImplemented and ...

and the `and` machinery sees it has a `NotImplemented` and raises a 
`TypeError`.  The same would be true if the `__eq__` operation returned 
`NotImplemented`.

So to make that work, `and` and `or` would have to check if one of the operands 
is `NotImplemented`.  Are there others that would need to have that check?

The reason I would prefer this solution is that if it could behave as I 
described above, the `TypeError` would point at the user's line of code as 
being the problem, and not inside the __dunder__:

class NoAdd:
#
def __add__(self, other):
return NotImplemented
#
def __radd__(self, other):
# fake a NotImplemented TypeError from bool(NotImplemented)
raise TypeError("cannot boolean NotImplemented")

# what we should see, since the error is in the users' code
--> NoAdd() + 7
Traceback (most recent call last):
  File "", line 1, in 
TypeError: unsupported operand type(s) for +: 'NoAdd' and 'int'

# what we will see -- a leaky implementation detail
--> 7 + NoAdd()
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 6, in __radd__
TypeError: cannot boolean NotImplemented

--

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2020-03-11 Thread Serhiy Storchaka


Serhiy Storchaka  added the comment:

No.

First, it is impossible. nb_bool and PyObject_IsTrue() can return only three 
value: 1 for true, 0 for false, and -1 for error. It is not possible to 
represent NotImplemented without breaking all extensions.

Currently

if not a:
b()
else:
c()

is equivalent to

if a:
c()
else:
b()

If a is NotImplemented, what branch be executed in every case?

Second, it would not help. Because real-world examples are not always so 
trivial as "return not self.__lt__(other)". It may be a part of more complex 
expression, e.g.:

return super().__eq__(other) and self.attr == other.attr

So it may help in some examples, but make bugs in other examples even more 
mystical.

--

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2020-03-11 Thread Ethan Furman


Ethan Furman  added the comment:

I know I'm late to the party, but if

  bool(NotImplemented)

returned `NotImplemented` wouldn't that solve the problem?

def __ge__(self, other):
return not self.__lt__(other)

then

   if __lt__ returns   then __gt__ returns

 NotImplemented  NotImplemented
 TrueFalse
 False   True

Correct code (which checks for NotImplemented) would still work, and buggy code 
(which just returns the bool() of NotImplemented), would then be correct.

--
nosy: +ethan.furman

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2020-03-03 Thread Serhiy Storchaka


Change by Serhiy Storchaka :


--
resolution:  -> fixed
stage: patch review -> resolved
status: open -> closed

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2020-03-03 Thread Serhiy Storchaka


Serhiy Storchaka  added the comment:


New changeset 469325c30e147680543b2f5118b83fd95055a499 by MojoVampire in branch 
'master':
bpo-35712: Make using NotImplemented in a boolean context issue a deprecation 
warning (GH-13195)
https://github.com/python/cpython/commit/469325c30e147680543b2f5118b83fd95055a499


--

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2019-08-09 Thread Vedran Čačić

Vedran Čačić  added the comment:

Another reason why current behavior is confusing: what do you think

filter(2 .__eq__, 'text')

should yield? :-o

(Yes, I know this isn't the right way to do it, but

(element for element in 'text' if element == 2)

is twice longer.:)

--
nosy: +veky

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2019-08-07 Thread Serhiy Storchaka


Serhiy Storchaka  added the comment:

I do not have a strong opinion, so I suggest to not mention neither TypeError, 
nor RuntimeWarning. After some time of using a DeprecationWarning we can have 
have some information about whether there is a code which can't be fixed if 
bool(NotImplemented) will raise an error.

--

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2019-08-07 Thread Josh Rosenberg


Josh Rosenberg  added the comment:

In the docs for my PR, I mention using NotImplemented in a boolean context is 
deprecated, raising DeprecationWarning, and will raise TypeError in a future 
version of Python. Serhiy has suggested the end state might be RuntimeWarning 
instead of TypeError. I'm in favor of it ending up as an error, but not rigid 
on it. Does anyone else have a strong opinion among the following options?

1. DeprecationWarning, documented as eventual TypeError (current PR)
2. DeprecationWarning, documented as eventual RuntimeWarning
3. Immediate RuntimeWarning, no DeprecationWarning period (since a warning only 
causes stderr output by default, it doesn't prevent working code from working 
unless warnings are explicitly configured to become exceptions)

--

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2019-07-26 Thread Josh Rosenberg


Josh Rosenberg  added the comment:

Moving to 3.9 target, per Serhiy's request. PR has been rebased against master, 
including updating the What's New info to be in the 3.9 version, not 3.8.

--
versions: +Python 3.9 -Python 3.8

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2019-05-08 Thread Josh Rosenberg


Josh Rosenberg  added the comment:

I've submitted a PR for this. I did discover a use case for boolean evaluation 
while doing this in the functools.total_ordering helpers. While it's 
legitimate, it *looks* wrong (the code looks like it didn't consider the 
possibility of NotImplemented even though it did), and really only applies to 
the case total_ordering handles on behalf of most folks (implementing one 
comparator in terms of two others).

The specific case was:

def _le_from_lt(self, other, NotImplemented=NotImplemented):
 'Return a <= b.  Computed by @total_ordering from (a < b) or (a == b).'
 op_result = self.__lt__(other)
 return op_result or self == other

(with a similar implementation for _ge_from_gt). It happens to work because the 
return value of __lt__ is used directly for both True and NotImplemented cases, 
with only False delegating to equality. It's not at all clear that that's 
correct at first glance though, and the fix to avoid the warning is simple, 
matching the other 10 comparator helpers by explicit checking for 
NotImplemented via:

if op_result is NotImplemented:
return NotImplemented

That's about the strongest case I can find for "legitimate" use of 
NotImplemented in a boolean context, so I figured I'd point it out explicitly 
so people knew it existed.

If that makes an eventual TypeError a non-starter, I'd still like that usage to 
emit a warning (e.g. a RuntimeWarning) simply because the utility of that one 
little shortcut pales in comparison to the damage done by the *many* misuses 
that occur.

--

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2019-05-08 Thread Josh Rosenberg


Change by Josh Rosenberg :


--
keywords: +patch
pull_requests: +13106
stage: test needed -> patch review

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2019-01-11 Thread Terry J. Reedy


Terry J. Reedy  added the comment:

I consider it a nice feature of Python that all builtin objects, and, AFAIK 
(and Josh, apparently), all stdlib class instances, have a boolean value.  (I 
am aware of numpy's element-wise behavior.)  I hate to give this up.  This is 
part of Python's general avoidance of singular exceptions and exceptions to 
exceptions.  This proposal would be the latter: "An object is truthy, unless 
its class makes it false, unless it is NotImplemented and a TypeError."

If this exception is made, I expect that there will be proposals to extend the 
exception to other objects, such as Ellipsis.

--
nosy: +terry.reedy
stage:  -> test needed
type: behavior -> enhancement
versions: +Python 3.8

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2019-01-11 Thread Guido van Rossum


Guido van Rossum  added the comment:

I agree.

On Thu, Jan 10, 2019 at 11:24 PM Serhiy Storchaka 
wrote:

>
> Serhiy Storchaka  added the comment:
>
> This is a common mistake. Even the default implementation of object.__ne__
> had a bug, fixed only 4 years ago in issue21408. There were several errors
> in stdlib. I am sure there is a lot of occurrences of this errors in a
> third party code.
>
> So I like this idea. This can help to fix hidden errors in existing code.
> But I share also Josh's concerns.
>
> There is related common mistake. In C code, the result of
> PyObject_IsTrue() often is treated as just a boolean, without checking for
> errors. Fortunately, in the current CPython code it is handled properly,
> but I am sure this error still is occurred in third-party extensions.
>
> When these two errors (using NotImplemented in the boolean context and
> ignoring the error in PyObject_IsTrue() in the C code) meet, this can lead
> to manifestation of more weird bugs than treating NotImplemented as true:
> from a crash in debug build to raising an exception in the following
> unrelated code.
>
> I suggest to start emitting a DeprecationWarning or a FutureWarning in
> NotImplemented.__bool__.
>
> --
> nosy: +gvanrossum, serhiy.storchaka
>
> ___
> Python tracker 
> 
> ___
>
-- 
--Guido (mobile)

--

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2019-01-10 Thread Serhiy Storchaka


Serhiy Storchaka  added the comment:

This is a common mistake. Even the default implementation of object.__ne__ had 
a bug, fixed only 4 years ago in issue21408. There were several errors in 
stdlib. I am sure there is a lot of occurrences of this errors in a third party 
code.

So I like this idea. This can help to fix hidden errors in existing code. But I 
share also Josh's concerns.

There is related common mistake. In C code, the result of PyObject_IsTrue() 
often is treated as just a boolean, without checking for errors. Fortunately, 
in the current CPython code it is handled properly, but I am sure this error 
still is occurred in third-party extensions.

When these two errors (using NotImplemented in the boolean context and ignoring 
the error in PyObject_IsTrue() in the C code) meet, this can lead to 
manifestation of more weird bugs than treating NotImplemented as true: from a 
crash in debug build to raising an exception in the following unrelated code.

I suggest to start emitting a DeprecationWarning or a FutureWarning in 
NotImplemented.__bool__.

--
nosy: +gvanrossum, serhiy.storchaka

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2019-01-10 Thread Steven D'Aprano


Steven D'Aprano  added the comment:

> the canonical __ne__ delegation to __eq__ for any class should be implemented 
> as something like

I disagree that your code snippet is the canonical way to write __ne__. I'd 
write it like this:

def __ne__(self, other):
return not (self == other)

Or just not write it at all. Python will automatically call __eq__ going back 
to Python 2.4 (and possibly older).

Delegating to __eq__ directly is the wrong way to do it.

> NotImplemented is a sentinel value that should never be evaluated in a 
> boolean context

I don't see why not. I can't think of any use-cases where I would want to 
*specifically* use NotImplemented in a boolean context, but I see no good 
reason why I would want it to fail if one happened to do so.

--
nosy: +steven.daprano

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2019-01-10 Thread Karthikeyan Singaravelan


Karthikeyan Singaravelan  added the comment:

Seems related issue22978

--
nosy: +xtreak

___
Python tracker 

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



[issue35712] Make NotImplemented unusable in boolean context

2019-01-10 Thread Josh Rosenberg


New submission from Josh Rosenberg :

I don't really expect this to go anywhere until Python 4 (*maybe* 3.9 after a 
deprecation period), but it seems like it would have been a good idea to make 
NotImplementedType's __bool__ explicitly raise a TypeError (rather than leaving 
it unset, so NotImplemented evaluates as truthy). Any correct use of 
NotImplemented per its documented intent would never evaluate it in a boolean 
context, but rather use identity testing, e.g. back in the Py2 days, the 
canonical __ne__ delegation to __eq__ for any class should be implemented as 
something like:

def __ne__(self, other):
equal = self.__eq__(other)
return equal if equal is NotImplemented else not equal

Problem is, a lot of folks would make mistakes like doing:

def __ne__(self, other):
return not self.__eq__(other)

which silently returns False when __eq__ returns NotImplemented, rather than 
returning NotImplemented and allowing Python to check the mirrored operation. 
Similar issues arise when hand-writing the other rich comparison operators in 
terms of each other.

It seems like, given NotImplemented is a sentinel value that should never be 
evaluated in a boolean context, at some point it might be nice to explicitly 
prevent it, to avoid errors like this.

Main argument against it is that I don't know of any other type/object that 
explicitly makes itself unevaluable in a boolean context, so this could be 
surprising if someone uses NotImplemented as a sentinel unrelated to its 
intended purpose and suffers the problem.

--
messages: 333421
nosy: josh.r
priority: normal
severity: normal
status: open
title: Make NotImplemented unusable in boolean context
type: behavior

___
Python tracker 

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