Coverage for src/galaxy_beep_frame/frame/state.py: 100%

24 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-08-31 04:18 +0200

1"""FrameState class.""" 

2 

3from dataclasses import InitVar, dataclass, field 

4from typing import TYPE_CHECKING 

5 

6from galaxy_beep_frame.constant import ( 

7 CHANNEL_NUMBER_MAX, 

8 CHANNEL_NUMBER_MIN, 

9 MESSAGE_NUMBER_MAX, 

10 MESSAGE_NUMBER_MIN, 

11 SEQUENCE_NUMBER_MAX, 

12 SEQUENCE_NUMBER_MIN, 

13) 

14from galaxy_beep_frame.exception.frame import ( 

15 AboveRangeError, 

16 BelowRangeError, 

17) 

18 

19from .header_type import HeaderType 

20 

21if TYPE_CHECKING: 

22 from galaxy_beep_frame.header_type import PossibleHeaderType 

23 

24 from .base import Frame 

25 from .header_type.continuation_indicator import ( 

26 ContinuationIndicator, 

27 ) 

28 

29 

30@dataclass 

31class FrameState: 

32 """State of a BEEP frame.""" 

33 

34 frame: Frame 

35 header_type: HeaderType = field(init=False) 

36 

37 channel_number: int 

38 message_number: int 

39 sequence_number: int 

40 

41 answer_number: InitVar[int | None] 

42 continuation_indicator: InitVar[ContinuationIndicator] 

43 possible_header_type: InitVar[PossibleHeaderType] 

44 

45 def __post_init__( 

46 self, 

47 answer_number: int | None, 

48 continuation_indicator: ContinuationIndicator, 

49 possible_header_type: PossibleHeaderType, 

50 ) -> None: 

51 """Check numbers range.""" 

52 

53 if self.channel_number < CHANNEL_NUMBER_MIN: 

54 raise BelowRangeError( 

55 self.channel_number, 

56 CHANNEL_NUMBER_MIN, 

57 "channel number", 

58 ) 

59 if self.channel_number > CHANNEL_NUMBER_MAX: 

60 raise AboveRangeError( 

61 self.channel_number, 

62 CHANNEL_NUMBER_MAX, 

63 "channel number", 

64 ) 

65 

66 if self.message_number < MESSAGE_NUMBER_MIN: 

67 raise BelowRangeError( 

68 self.message_number, 

69 MESSAGE_NUMBER_MIN, 

70 "message number", 

71 ) 

72 if self.message_number > MESSAGE_NUMBER_MAX: 

73 raise AboveRangeError( 

74 self.message_number, 

75 MESSAGE_NUMBER_MAX, 

76 "message number", 

77 ) 

78 

79 if self.sequence_number < SEQUENCE_NUMBER_MIN: 

80 raise BelowRangeError( 

81 self.sequence_number, 

82 SEQUENCE_NUMBER_MIN, 

83 "sequence number", 

84 ) 

85 if self.sequence_number > SEQUENCE_NUMBER_MAX: 

86 raise AboveRangeError( 

87 self.sequence_number, 

88 SEQUENCE_NUMBER_MAX, 

89 "sequence number", 

90 ) 

91 

92 self.header_type = HeaderType.make( 

93 state=self, 

94 continuation_indicator=continuation_indicator, 

95 possible_header_type=possible_header_type, 

96 answer_number=answer_number, 

97 ) 

98 

99 def build(self, size: int) -> bytes: 

100 """Build the header of this Frame.""" 

101 

102 return self.header_type.build(size)