Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/dissect/cstruct/types/flag.py: 38%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

29 statements  

1from __future__ import annotations 

2 

3from enum import IntFlag 

4 

5from dissect.cstruct.types.base import BaseType 

6from dissect.cstruct.types.enum import PY_311, EnumMetaType 

7 

8 

9class Flag(BaseType, IntFlag, metaclass=EnumMetaType): 

10 """Flag type supercharged with cstruct functionality. 

11 

12 Flags are (mostly) compatible with the Python 3 standard library ``IntFlag`` with some notable differences: 

13 - Flag members are only considered equal if the flag class is the same 

14 

15 Flags can be made using any integer type. 

16 

17 Example: 

18 When using the default C-style parser, the following syntax is supported:: 

19 

20 flag <name> [: <type>] { 

21 <values> 

22 }; 

23 

24 For example, a flag that has A=1, B=4 and C=8 could be written like so:: 

25 

26 flag Test : uint16 { 

27 A, B=4, C 

28 }; 

29 """ 

30 

31 def __repr__(self) -> str: 

32 result = super().__repr__() 

33 if not self.__class__.__name__: 

34 # Deal with anonymous flags by stripping off the first bit 

35 # I.e. <.RED: 1> -> <RED: 1> 

36 result = f"<{result[2:]}" 

37 return result 

38 

39 if PY_311: 

40 

41 def __str__(self) -> str: 

42 # We differentiate with standard Python flags in that we use a more descriptive str representation 

43 # Standard Python flags just use the integer value as str, we use FlagName.ValueName 

44 # In case of anonymous flags, we just use the ValueName 

45 base = f"{self.__class__.__name__}." if self.__class__.__name__ else "" 

46 return f"{base}{self.name}" 

47 

48 else: 

49 

50 def __str__(self) -> str: 

51 result = IntFlag.__str__(self) 

52 if not self.__class__.__name__: 

53 # Deal with anonymous flags 

54 # I.e. .RED -> RED 

55 result = result[1:] 

56 return result 

57 

58 def __eq__(self, other: int | Flag) -> bool: 

59 if isinstance(other, Flag) and other.__class__ is not self.__class__: 

60 return False 

61 

62 # Python <= 3.10 compatibility 

63 if isinstance(other, Flag): 

64 other = other.value 

65 

66 return self.value == other 

67 

68 def __ne__(self, value: int | Flag) -> bool: 

69 return not self.__eq__(value) 

70 

71 def __hash__(self) -> int: 

72 return hash((self.__class__, self.name, self.value))