[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Python-Dev] Enum, Flag, __contains__, and False vs TypeError

On Wed, 4 Apr 2018 at 11:30 Ethan Furman <ethan at stoneleaf.us> wrote:

> API question.
> Background:
> ----------
> When doing checks such as
> --> 3 in [4, 5, 6]
> --> 'test' in {'test':True, 'live':False}
> the result is True or False.
> When doing checks such as
> --> 3 in 'hello world'
> --> [4, 5, 6] in {'test':True, 'live':False}
> the result is a TypeError.
> The general rule seems to be that if it is impossible for the in-question
> object to be in the container object then a
> TypeError is raised, otherwise True or False is returned.
> Question 1:
> ----------
> (A) A standard Enum class is a container of Enum members.  It cannot hold
> anything else.  However, it has been returning
> False both in cases where the in-question object was an Enum of a
> different class (a Fruit in a Color, for example) and
> when the in-question object was not even an Enum ('apple' in Fruit, for
> example).
> (B) The waters get even more muddied when Fruit has a str mixin, so
> `Fruit.APPLE == 'apple' is True` -- in that case,
> should `'orange' in Fruit` return True, False, or raise TypeError?
> Question 2:
> ----------
> (A) The new Flag type allows `in` tests on the members themselves; so, for
> example:
> --> SomeFlag.ONE in SomeFlag.One|SomeFlag.TWO
> True
> The question, of course, is what to do when a non-Flag member is tested
> for:
> --> 'apple' in SomeFlag.ONE
> # False or TypeError?
> --> 2 in SomeFlag.TWO
> # True or TypeError?
> (B) And, of course, the same muddier question arises with IntFlag, where
> SomeFlag.TWO == 2 is True.
> My thoughts:
> -----------
> For question 1A (pure Enum):  I'm thinking a TypeError should be raised
> when the in-question object is not an Enum
> member of any kind -- it simply is not possible for that object to ever be
> in an Enum, and is surely a bug.

Yes, although it sounds like it already does the other thing, so do you
want to start raising TypeError immediately or go for a deprecation period?

> For question 1B (mixed Enum):  if 1A is TypeError, then 1B should also be
> TypeError at least for non-mixin in-question
> types (so checking for 1 in StrEnum would be a TypeError), but I'm torn
> between TypeError and True/False for cases where
> the in-question type matches the mixin type ('apple' in StrEnum)....  On
> the one hand, even though an Enum member might
> be equal to some other type, that other type will not have the Enum
> attributes, etc, and a True answer would lead one to
> believe you could access `.name` and `.value`, etc., while a False answer
> would lead one to believe there was no match
> even though equality tests pass; on the other hand, how strong is the
> "container" aspect of a mixed Enum?  How often is
> the test `'apple' in Fruit` meant to discover if you have a Fruit member
> vs whether you have something that could be a
> Fruit member?  Also, how important is it to be consistent with IntFlag,
> which I definitely think should return
> True/False for int checks?

I think this is a design question as to how interchangeable you want these
kind of enums to be, and I personally have no opinion as I have never
needed to use them.

> For question 2A (pure Flag):  I'm comfortable sticking with a TypeError
> (assuming we switch to TypeError for 1A).

Makes sense.

> For question 2B (int Flag):  I think a TypeError if the in-question object
> is not an int is appropriate (assuming
> TypeError for 1A and 2A), but if it is an int, True/False seems the better
> path.  My reasoning being that Flag and
> IntFlag are more similar to sets than lists, and IntFlag is specifically
> meant to work with ints, and a test of `2 in
> some_int_flags` is more concerned with a flag being set than with .name or
> .value attributes that may or may not exist
> on the in-question object.

Same as above; no experience so no opinion.

> Any and all thoughts appreciated.
> --
> ~Ethan~
> _______________________________________________
> Python-Dev mailing list
> Python-Dev at python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/brett%40python.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20180404/6335c798/attachment.html>