mirror of
https://github.com/inventree/InvenTree.git
synced 2026-10-14 14:11:55 +00:00
Improve status code comparison (#13006)
Fixes bug caused by override of BaseEnum.__new__ which broke comparison of status code values
This commit is contained in:
1 parent
7e89e93252
commit
34ea373d88
2 files changed
+62
-7
No files matched your search
@@ -9,6 +9,18 @@ from typing import Optional
|
||||
logger = logging.getLogger('inventree')
|
||||
|
||||
|
||||
def _new_int(cls, value):
|
||||
"""Construct a new int-based enum member with the provided value as its int payload.
|
||||
|
||||
Non-integer values (which are not valid status codes, and are ignored by
|
||||
StatusCode._is_element) fall back to a zero payload.
|
||||
"""
|
||||
if isinstance(value, int):
|
||||
return int.__new__(cls, value)
|
||||
|
||||
return int.__new__(cls)
|
||||
|
||||
|
||||
class BaseEnum(enum.IntEnum):
|
||||
"""An `Enum` capable of having its members have docstrings.
|
||||
|
||||
@@ -16,8 +28,13 @@ class BaseEnum(enum.IntEnum):
|
||||
"""
|
||||
|
||||
def __new__(cls, *args):
|
||||
"""Assign values on creation."""
|
||||
obj = object.__new__(cls)
|
||||
"""Assign values on creation.
|
||||
|
||||
Note: The underlying int payload must be set (via int.__new__) to match the value,
|
||||
otherwise any operation which uses the raw int (e.g. '!=', '<', bool(), json.dumps)
|
||||
would see 0 for every member.
|
||||
"""
|
||||
obj = _new_int(cls, args[0])
|
||||
obj._value_ = args[0]
|
||||
return obj
|
||||
|
||||
@@ -51,10 +68,13 @@ class BaseEnum(enum.IntEnum):
|
||||
return hash(self.value)
|
||||
|
||||
def __ne__(self, obj):
|
||||
"""Override inequality operator to allow comparison with int."""
|
||||
if type(self) is type(obj):
|
||||
return super().__ne__(obj)
|
||||
return self.value != obj
|
||||
"""Override inequality operator to remain consistent with __eq__."""
|
||||
result = self.__eq__(obj)
|
||||
|
||||
if result is NotImplemented:
|
||||
return result
|
||||
|
||||
return not result
|
||||
|
||||
|
||||
class StatusCode(BaseEnum):
|
||||
@@ -72,7 +92,7 @@ class StatusCode(BaseEnum):
|
||||
|
||||
def __new__(cls, *args):
|
||||
"""Define object out of args."""
|
||||
obj = int.__new__(cls)
|
||||
obj = _new_int(cls, args[0])
|
||||
obj._value_ = args[0]
|
||||
|
||||
# Normal item definition
|
||||
|
||||
@@ -123,6 +123,41 @@ class GeneralStateTest(InvenTreeTestCase):
|
||||
# label
|
||||
self.assertEqual(GeneralStatus.label(10), 'Pending')
|
||||
|
||||
def test_int_payload(self):
|
||||
"""The underlying int payload of each member matches its value.
|
||||
|
||||
Regression test: members were previously constructed with a zero int payload,
|
||||
so any operation using the raw int ('!=' between members of the same class,
|
||||
ordering, bool(), arithmetic, json serialization) was silently wrong.
|
||||
"""
|
||||
import json
|
||||
|
||||
from build.status_codes import BuildStatus
|
||||
|
||||
for cls in [GeneralStatus, BuildStatus]:
|
||||
for member in cls.values():
|
||||
self.assertEqual(int.__repr__(member), str(member.value))
|
||||
|
||||
pending, complete = GeneralStatus.PENDING, GeneralStatus.COMPLETE
|
||||
|
||||
# Comparison between members of the same class
|
||||
self.assertNotEqual(pending, complete)
|
||||
self.assertEqual(pending, GeneralStatus.PENDING)
|
||||
self.assertNotEqual(BuildStatus.PENDING, BuildStatus.COMPLETE)
|
||||
self.assertLess(pending, complete)
|
||||
self.assertEqual(sorted([complete, pending]), [pending, complete])
|
||||
|
||||
# Comparison against raw integers
|
||||
self.assertEqual(pending, 10)
|
||||
self.assertNotEqual(pending, 20)
|
||||
self.assertEqual(10, pending)
|
||||
self.assertNotEqual(20, pending)
|
||||
|
||||
self.assertTrue(bool(pending))
|
||||
self.assertEqual(pending + 1, 11)
|
||||
self.assertEqual(f'{complete:d}', '30')
|
||||
self.assertEqual(json.dumps({'status': complete}), '{"status": 30}')
|
||||
|
||||
def test_color(self):
|
||||
"""Test that the color enum validation works."""
|
||||
with self.assertRaises(ValueError) as e:
|
||||
|
||||
Reference in new issue
Block a user