Issue 33219: x in IntFlag should test raise TypeError if x is not an IntFlag (original) (raw)

Created on 2018-04-03 20:38 by Dutcho, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (7)
msg314893 - (view) Author: (Dutcho) Date: 2018-04-03 20:38
While `enum.IntFlag.__and__` accepts an int arg `other` and converts it to `IntFlag` before masking, `enum.IntFlag.__contains__` handles an int arg `other` no different from a different type arg `other` (i.e. returns `True` in Python 3.6 due to issue 33217, but would raise `TypeError` after that's fixed): >>> import enum >>> ABC = enum.Flag('ABC', 'a, b, c') >>> ac = ABC.a | ABC.c >>> ABC.b in ac # works False >>> 2 in ac # should be the same; no exception due to issue 33217 True >>> ac & 3 # works, equivalent to ac & ABC(3) <ABC.a: 1> This is caused by a lack of specialized `IntFlag.__contains__`, so `Flag.__contains__` does the work. Can be fixed by adding a specialization, which (like in `IntFlag.__and__`) tests for `isinstance(other, (IntFlag, int))`. >>> def __contains__(self, other): ... if not isinstance(other, (self.__class__, int)): ... return TypeError ... return other & self == other # conversion of int to IntFlag implicitly handled by IntFlag.__and__ >>> IntFlag.__contains__ = __contains__
msg314897 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2018-04-03 21:10
will not be "fixed" with a TypeError, but incorrect Falses are also bad. Rather than add __contains__ to IntFlag (and every other Flag mixin), I think the best answer is to adjust Flag.__contains__ a little bit more to check if `other` is of the same type as the mixin class, and if so see if it's one of the values. Thank you for being thorough and finding this problem as well.
msg314912 - (view) Author: Nitish (nitishch) * Date: 2018-04-04 02:37
@Ethan Furman how can Flag do that? IntFlag can deal with int values too. Would it be possible to deal with int values in this case in Flag.__contains__?
msg314951 - (view) Author: (Dutcho) Date: 2018-04-04 21:03
@Nitish The easiest way would probably be to change __contains__ in Flag to: def __contains__(self, other): try: return other & self == other # leave selection of _value_ attribute (if other is Flag) or conversion (if other is int mixin of IntFlag) to __and__ except TypeError: return False Although this would be somewhat convoluted (the generic delegation to __and__ isn't clear at first sight and therefore less maintainable) and may lead to confusing error messages
msg314959 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2018-04-04 23:14
Nitish, Flag can check if the current Flag class has a mixin, and if so if the object being checked for is of that same type. Dutcho, my apologies. Looks like I did not fully understand how __contains__ is supposed to work and a TypeError is completely appropriate. Looking into deprecation cycles now to get the change scheduled.
msg314993 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2018-04-05 16:32
is tracking member-containment checks; modifying this one to track class-containment checks. Given class Color(Enum): RED = 1 class Fruit(Enum): APPLE = 1 then --> Fruit.APPLE in Color False --> Fruit.APPLE in Fruit True --> 1 in Fruit TypeError The last is currently returning False instead of raising a TypeError.
msg315233 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2018-04-12 21:34
This and are similar enough I'm going to track it in .
History
Date User Action Args
2022-04-11 14:58:59 admin set github: 77400
2018-04-12 21:34:06 ethan.furman set status: open -> closedsuperseder: x in enum.Flag member is True when x is not a Flagmessages: + resolution: duplicatestage: needs patch -> resolved
2018-04-05 16:32:04 ethan.furman set versions: + Python 3.7title: x in IntFlag() should test int x's inclusion in IntFlag -> x in IntFlag should test raise TypeError if x is not an IntFlagmessages: + type: enhancement -> behaviorstage: needs patch
2018-04-04 23:14:49 ethan.furman set messages: +
2018-04-04 21:03:56 Dutcho set messages: +
2018-04-04 02:37:00 nitishch set nosy: + nitishchmessages: +
2018-04-03 21:10:50 ethan.furman set keywords: + easymessages: +
2018-04-03 20:49:59 ethan.furman set assignee: ethan.furmannosy: + barry, eli.bendersky, ethan.furmanversions: + Python 3.8, - Python 3.6
2018-04-03 20:38:20 Dutcho create