Details
Description
Performing arithmetic with enum members behaves extremely erratically, especially on Python 3.
Attached you can find a test case (enum_bug.py) performing several operations with enum member PySide2.QtCore.Qt.Key.Key_1; similar results can be obtained with other non-flags enum values; notice that all tests are repeated 4 times as some results are flapping.
Running it on my Ubuntu 16.04 amd64 machine with Python 2.7.12 and PySide2 5.11.2 (installed today using pip) I get that (see out_py2.txt attached):
- regular sum/multiplication with integers both on the left and on the right works fine;
- summing with float values on the right seems to demote the float value to integer and sum it with the enum value;
- summing with float values on the left returns garbage results except for 0.0
- summing/multiplying with strings containing the text representation of a valid number on the right magically seems to sum/multiply with the conversion of such string to int (!!);
- summing/multiplying with non-numeric strings on the right alternates between "the specified operation with the string evaluated to -1", and "throws internal exceptions";
- doing the same with a generic object() is pretty much the same;
- summing/multiplying with strings (both numeric and non-numeric) on the left behaves as if you summed/multiplied by the length of the string (?!?);
- doing the same with a generic object returns garbage values (although from the values I'd bet that it's performing the requested operation with the numeric value of the pointer to the given object ).
Re-running it with Python 3.5.2 (again, PySide2 5.11.2 installed today using pip3), I get similar results (see out_py3.txt attached), but with some extra twists:
- summing integers on the left behaves as if the integer you sum is clamped between -1 and +1; incidentally, this is how we discovered the problem in first place (we were doing QKeyEvent.key() - Qt.Key.Key_1, which returned negative values);
- several tests that in Python 2 flap between string-evaluated-as-minus-one and plain exceptions here always throw an exception.
These last tests were repeated also on an Arch Linux machine (Python 3.7.0), with identical results (except of course for the pointer values returned by the sum/multiply with object() on the left)
Long story short, it seems that there's something really fishy going on in the arithmetic operators of enum types.
Ideally, they should behave as in PyQt or as in C++ - convert the enum value to integer and then behave "as normal" (which includes throwing exceptions if passed unexpected types); if that's complicated, just accept integer values and throw in all other cases.