Coverage for arrakis_server/channel.py: 90.5%

1# Copyright (c) 2025, California Institute of Technology and contributors

2#

3# You should have received a copy of the licensing terms for this

4# software included in the file "LICENSE" located in the top-level

5# directory of this package. If you did not, you can view a copy at

6# https://git.ligo.org/ngdd/arrakis-python/-/raw/main/LICENSE

7

8"""Server-specific channel information."""

9

10 from __future__ import annotations

11

12 from dataclasses import dataclass

13 from functools import cached_property

14

15 from arrakis.channel import Channel as BaseChannel

16

17

18@dataclass(frozen=True, order=True)

19 class Channel(BaseChannel):

20 """Metadata associated with a channel.

21

22 Channels have the form {domain}:{subsystem}-*.

23

24 Parameters

25 ----------

26 name : str

27 The name associated with this channel.

28 data_type : numpy.dtype

29 The data type associated with this channel.

30 sample_rate : float

31 The sampling rate associated with this channel.

32 time : int, optional

33 The timestamp when this metadata became active.

34 publisher : str

35 The publisher associated with this channel.

36 partition_id : str, optional

37 The partition ID associated with this channel.

38 expected_latency: int, optional

39 Expected publication latency for this channel's data, in

40 seconds.

41

42 """

43

44 def validate(self) -> None:

45 components = self.name.split(":")

46 if len(components) != 2 or "-" not in self.name:

47 raise ValueError(

48 "channel is malformed, needs to be in the form {domain}:{subsystem}-*"

49 )

50

51 @cached_property

52 def subsystem(self) -> str:

53 """The subsystem associated with a given channel."""

54 _, rest = self.name.split(":")

55 return rest.split("-")[0]

56

57

58 def extract_channel_scope(channel: str) -> tuple[str, str]:

59 """Given a channel name, extracts the channel's scope.

60

61 Parameters

62 ----------

63 channel : str

64 The channel with the form {domain}:{subsystem}-*.

65

66 Returns

67 -------

68 tuple[str, str]

69 The domain and the subsystem, respectively.

70 """

71 components = channel.split(":")

72 if len(components) != 2 or "-" not in channel:

73 raise ValueError(

74 "channel is malformed, needs to be in the form {domain}:{subsystem}-*"

75 )

76

77 domain, rest = components

78 subsystem = rest.split("-")[0]

79

80 return domain, subsystem