Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/zmq/sugar/frame.py: 35%

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

51 statements  

1"""0MQ Frame pure Python methods.""" 

2 

3# Copyright (C) PyZMQ Developers 

4# Distributed under the terms of the Modified BSD License. 

5 

6import zmq 

7from zmq.backend import Frame as FrameBase 

8 

9from .attrsettr import AttributeSetter 

10 

11 

12def _draft(v, feature): 

13 zmq.error._check_version(v, feature) 

14 if not zmq.DRAFT_API: 

15 raise RuntimeError( 

16 f"libzmq and pyzmq must be built with draft support for {feature}" 

17 ) 

18 

19 

20class Frame(FrameBase, AttributeSetter): 

21 """ 

22 A zmq message Frame class for non-copying send/recvs and access to message properties. 

23 

24 A ``zmq.Frame`` wraps an underlying ``zmq_msg_t``. 

25 

26 Message *properties* can be accessed by treating a Frame like a dictionary (``frame["User-Id"]``). 

27 

28 .. versionadded:: 14.4, libzmq 4 

29 

30 Frames created by ``recv(copy=False)`` can be used to access message properties and attributes, 

31 such as the CURVE User-Id. 

32 

33 For example:: 

34 

35 frames = socket.recv_multipart(copy=False) 

36 user_id = frames[0]["User-Id"] 

37 

38 This class is used if you want to do non-copying send and recvs. 

39 When you pass a chunk of bytes to this class, e.g. ``Frame(buf)``, the 

40 ref-count of `buf` is increased by two: once because the Frame saves `buf` as 

41 an instance attribute and another because a ZMQ message is created that 

42 points to the buffer of `buf`. This second ref-count increase makes sure 

43 that `buf` lives until all messages that use it have been sent. 

44 Once 0MQ sends all the messages and it doesn't need the buffer of ``buf``, 

45 0MQ will call ``Py_DECREF(s)``. 

46 

47 Parameters 

48 ---------- 

49 

50 data : object, optional 

51 any object that provides the buffer interface will be used to 

52 construct the 0MQ message data. 

53 track : bool 

54 whether a MessageTracker_ should be created to track this object. 

55 Tracking a message has a cost at creation, because it creates a threadsafe 

56 Event object. 

57 copy : bool 

58 default: use copy_threshold 

59 Whether to create a copy of the data to pass to libzmq 

60 or share the memory with libzmq. 

61 If unspecified, copy_threshold is used. 

62 copy_threshold: int 

63 default: :const:`zmq.COPY_THRESHOLD` 

64 If copy is unspecified, messages smaller than this many bytes 

65 will be copied and messages larger than this will be shared with libzmq. 

66 """ 

67 

68 def __getitem__(self, key): 

69 # map Frame['User-Id'] to Frame.get('User-Id') 

70 return self.get(key) 

71 

72 def __repr__(self): 

73 """Return the str form of the message.""" 

74 nbytes = len(self) 

75 msg_suffix = "" 

76 if nbytes > 16: 

77 msg_bytes = bytes(memoryview(self.buffer)[:12]) 

78 if nbytes >= 1e9: 

79 unit = "GB" 

80 n = nbytes // 1e9 

81 elif nbytes >= 2**20: 

82 unit = "MB" 

83 n = nbytes // 1e6 

84 elif nbytes >= 1e3: 

85 unit = "kB" 

86 n = nbytes // 1e3 

87 else: 

88 unit = "B" 

89 n = nbytes 

90 msg_suffix = f'...{n:.0f}{unit}' 

91 else: 

92 msg_bytes = self.bytes 

93 

94 _module = self.__class__.__module__ 

95 if _module == "zmq.sugar.frame": 

96 _module = "zmq" 

97 return f"<{_module}.{self.__class__.__name__}({msg_bytes!r}{msg_suffix})>" 

98 

99 @property 

100 def group(self): 

101 """The RADIO-DISH group of the message. 

102 

103 Requires libzmq >= 4.2 and pyzmq built with draft APIs enabled. 

104 

105 .. versionadded:: 17 

106 """ 

107 _draft((4, 2), "RADIO-DISH") 

108 return self.get('group') 

109 

110 @group.setter 

111 def group(self, group): 

112 _draft((4, 2), "RADIO-DISH") 

113 self.set('group', group) 

114 

115 @property 

116 def routing_id(self): 

117 """The CLIENT-SERVER routing id of the message. 

118 

119 Requires libzmq >= 4.2 and pyzmq built with draft APIs enabled. 

120 

121 .. versionadded:: 17 

122 """ 

123 _draft((4, 2), "CLIENT-SERVER") 

124 return self.get('routing_id') 

125 

126 @routing_id.setter 

127 def routing_id(self, routing_id): 

128 _draft((4, 2), "CLIENT-SERVER") 

129 self.set('routing_id', routing_id) 

130 

131 

132# keep deprecated alias 

133Message = Frame 

134__all__ = ['Frame', 'Message']