Coverage for /home/runner/work/zserio/zserio/compiler/extensions/python/runtime/src/zserio/enum.py: 100%

30 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2024-12-05 10:43 +0000

1""" 

2The module provides custom zserio Enum which allows to mark enum items deprecated. 

3""" 

4 

5import enum 

6import typing 

7import warnings 

8 

9 

10class _EnumType(enum.EnumMeta): 

11 """ 

12 Special enum meta class which fires a warning whenever a deprecated enum item is accessed. 

13 """ 

14 

15 def __getattribute__(cls, name): 

16 obj = super().__getattribute__(name) 

17 if isinstance(obj, enum.Enum) and obj._is_deprecated: 

18 warnings.warn(DeprecationWarning(f"Enum item '{obj}' is deprecated!"), stacklevel=2) 

19 return obj 

20 

21 def __getitem__(cls, name): 

22 member = super().__getitem__(name) 

23 if member._is_deprecated: 

24 warnings.warn(DeprecationWarning(f"Enum item '{member}' is deprecated!"), stacklevel=2) 

25 return member 

26 

27 def __call__(cls, value, names=None): 

28 # Python 3.12.3 has changed default value for 'names' from 'None' to '_not_given' 

29 if names is None: 

30 obj = super().__call__(value) 

31 else: 

32 obj = super().__call__(value, names=names) 

33 if isinstance(obj, enum.Enum) and obj._is_deprecated: 

34 warnings.warn(DeprecationWarning(f"Enum item '{obj}' is deprecated!"), stacklevel=2) 

35 return obj 

36 

37 

38class DeprecatedItem: 

39 """ 

40 Marker used to make enum items deprecated. 

41 

42 Just use the class instead of creating an instance. 

43 

44 Example: 

45 

46 .. code:: python 

47 

48 import zserio 

49 

50 class MyEnum(zserio.Enum): 

51 STABLE = 1, 

52 OLD = 2, zserio.DeprecatedItem 

53 NEW = 3 

54 """ 

55 

56 

57class Enum(enum.Enum, metaclass=_EnumType): 

58 """ 

59 Custom zserio enum base class which allows to mark items deprecated. 

60 """ 

61 

62 def __new__(cls, value: typing.Any, deprecated: typing.Optional[DeprecatedItem] = None): 

63 """ 

64 Creator method which allows to mark the item as deprecated. 

65 

66 :param value: The enum item value. 

67 :param deprecated: DeprecatedItem or None. 

68 

69 :returns: Instance of the enum item. 

70 """ 

71 

72 member = object.__new__(cls) 

73 member._value_ = value 

74 if deprecated is not None and deprecated != DeprecatedItem: 

75 raise ValueError( 

76 f"Invalid argument 'deprecated', which is {deprecated}! " f"Expecting {DeprecatedItem} or None." 

77 ) 

78 member._is_deprecated = deprecated is not None # type: ignore[attr-defined] 

79 return member