Message314890
While `Flag() in Flag()` and `Flag() | Flag()` result in the expected outcomes, e.g. `str() in Flag()` unexpectedly returns `True`, whereas `Flag() | str()` as expected raises a TypeError.
>>> import enum
>>> ABC = enum.Flag('ABC', 'a, b, c')
>>> ac = ABC.a | ABC.c
>>> def test():
... for x in (*ABC, 'test'):
... print(x, end=' ')
... try:
... print(x in ac, end=' ')
... except TypeError as e:
... print(e, end=' ')
... try:
... print(x | ac)
... except TypeError as e:
... print(e)
>>> test()
ABC.a True ABC.c|a
ABC.b False ABC.c|b|a
ABC.c True ABC.c|a
test True unsupported operand type(s) for |: 'str' and 'ABC'
Likely cause is modelling of Flag.__contains__ after Flag.__and__ etc., which is incorrect as __contains__ doesn't have a reflected version like __and__ etc. have. The returned `NotImplemented` is therefore not handled by the interpreter, although it is converted to bool to satisfy __contains__ return type.
This can be fixed by redefinition of Flag.__contains__ to raise TypeError:
>>> def __contains__(self, other):
... if not isinstance(other, self.__class__):
... raise TypeError(f"unsupported operand type(s) for 'in': "
... f"{type(other).__qualname__!r} and {type(self).__qualname__!r}")
... return other & self == other
>>> enum.Flag.__contains__ = __contains__
>>> test()
ABC.a True ABC.c|a
ABC.b False ABC.c|b|a
ABC.c True ABC.c|a
test unsupported operand type(s) for 'in': 'str' and 'ABC' unsupported operand type(s) for |: 'str' and 'ABC' |
|
Date |
User |
Action |
Args |
2018-04-03 20:16:12 | Dutcho | set | recipients:
+ Dutcho |
2018-04-03 20:16:12 | Dutcho | set | messageid: <1522786572.96.0.467229070634.issue33217@psf.upfronthosting.co.za> |
2018-04-03 20:16:12 | Dutcho | link | issue33217 messages |
2018-04-03 20:16:12 | Dutcho | create | |
|