blob: 8904478f1ab28d0647a73de5d5430370535f7fa9 [file] [log] [blame]
Yury Selivanov6370f342017-12-10 18:36:12 -05001"""Abstract Protocol base classes."""
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07002
Yury Selivanov6370f342017-12-10 18:36:12 -05003__all__ = (
4 'BaseProtocol', 'Protocol', 'DatagramProtocol',
Yury Selivanov631fd382018-01-28 16:30:26 -05005 'SubprocessProtocol', 'BufferedProtocol',
Yury Selivanov6370f342017-12-10 18:36:12 -05006)
Guido van Rossum27b7c7e2013-10-17 13:40:50 -07007
8
9class BaseProtocol:
Guido van Rossum9204af42013-11-30 15:35:42 -080010 """Common base class for protocol interfaces.
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070011
12 Usually user implements protocols that derived from BaseProtocol
13 like Protocol or ProcessProtocol.
14
15 The only case when BaseProtocol should be implemented directly is
16 write-only transport like write pipe
17 """
18
19 def connection_made(self, transport):
20 """Called when a connection is made.
21
22 The argument is the transport representing the pipe connection.
23 To receive data, wait for data_received() calls.
24 When the connection is closed, connection_lost() is called.
25 """
26
27 def connection_lost(self, exc):
28 """Called when the connection is lost or closed.
29
30 The argument is an exception object or None (the latter
31 meaning a regular EOF is received or the connection was
32 aborted or closed).
33 """
34
Guido van Rossum355491d2013-10-18 15:17:11 -070035 def pause_writing(self):
36 """Called when the transport's buffer goes over the high-water mark.
37
38 Pause and resume calls are paired -- pause_writing() is called
39 once when the buffer goes strictly over the high-water mark
40 (even if subsequent writes increases the buffer size even
41 more), and eventually resume_writing() is called once when the
42 buffer size reaches the low-water mark.
43
44 Note that if the buffer size equals the high-water mark,
45 pause_writing() is not called -- it must go strictly over.
46 Conversely, resume_writing() is called when the buffer size is
47 equal or lower than the low-water mark. These end conditions
48 are important to ensure that things go as expected when either
49 mark is zero.
50
51 NOTE: This is the only Protocol callback that is not called
52 through EventLoop.call_soon() -- if it were, it would have no
53 effect when it's most needed (when the app keeps writing
54 without yielding until pause_writing() is called).
55 """
56
57 def resume_writing(self):
58 """Called when the transport's buffer drains below the low-water mark.
59
60 See pause_writing() for details.
61 """
62
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070063
64class Protocol(BaseProtocol):
Guido van Rossum9204af42013-11-30 15:35:42 -080065 """Interface for stream protocol.
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070066
67 The user should implement this interface. They can inherit from
68 this class but don't need to. The implementations here do
69 nothing (they don't raise exceptions).
70
71 When the user wants to requests a transport, they pass a protocol
72 factory to a utility function (e.g., EventLoop.create_connection()).
73
74 When the connection is made successfully, connection_made() is
75 called with a suitable transport object. Then data_received()
76 will be called 0 or more times with data (bytes) received from the
77 transport; finally, connection_lost() will be called exactly once
78 with either an exception object or None as an argument.
79
80 State machine of calls:
81
82 start -> CM [-> DR*] [-> ER?] -> CL -> end
Victor Stinner54a231d2015-01-29 13:33:15 +010083
84 * CM: connection_made()
85 * DR: data_received()
86 * ER: eof_received()
87 * CL: connection_lost()
Guido van Rossum27b7c7e2013-10-17 13:40:50 -070088 """
89
90 def data_received(self, data):
91 """Called when some data is received.
92
93 The argument is a bytes object.
94 """
95
96 def eof_received(self):
97 """Called when the other end calls write_eof() or equivalent.
98
99 If this returns a false value (including None), the transport
100 will close itself. If it returns a true value, closing the
101 transport is up to the protocol.
102 """
103
104
Yury Selivanov631fd382018-01-28 16:30:26 -0500105class BufferedProtocol(BaseProtocol):
106 """Interface for stream protocol with manual buffer control.
107
108 Important: this has been been added to asyncio in Python 3.7
Yury Selivanov07627e92018-01-28 23:51:08 -0500109 *on a provisional basis*! Consider it as an experimental API that
Yury Selivanov631fd382018-01-28 16:30:26 -0500110 might be changed or removed in Python 3.8.
111
112 Event methods, such as `create_server` and `create_connection`,
113 accept factories that return protocols that implement this interface.
114
115 The idea of BufferedProtocol is that it allows to manually allocate
116 and control the receive buffer. Event loops can then use the buffer
117 provided by the protocol to avoid unnecessary data copies. This
118 can result in noticeable performance improvement for protocols that
119 receive big amounts of data. Sophisticated protocols can allocate
120 the buffer only once at creation time.
121
122 State machine of calls:
123
124 start -> CM [-> GB [-> BU?]]* [-> ER?] -> CL -> end
125
126 * CM: connection_made()
127 * GB: get_buffer()
128 * BU: buffer_updated()
129 * ER: eof_received()
130 * CL: connection_lost()
131 """
132
133 def get_buffer(self):
134 """Called to allocate a new receive buffer.
135
136 Must return an object that implements the
137 :ref:`buffer protocol <bufferobjects>`.
138 """
139
140 def buffer_updated(self, nbytes):
141 """Called when the buffer was updated with the received data.
142
143 *nbytes* is the total number of bytes that were written to
144 the buffer.
145 """
146
147 def eof_received(self):
148 """Called when the other end calls write_eof() or equivalent.
149
150 If this returns a false value (including None), the transport
151 will close itself. If it returns a true value, closing the
152 transport is up to the protocol.
153 """
154
155
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700156class DatagramProtocol(BaseProtocol):
Guido van Rossum9204af42013-11-30 15:35:42 -0800157 """Interface for datagram protocol."""
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700158
159 def datagram_received(self, data, addr):
160 """Called when some datagram is received."""
161
Guido van Rossum2335de72013-11-15 16:51:48 -0800162 def error_received(self, exc):
163 """Called when a send or receive operation raises an OSError.
164
165 (Other than BlockingIOError or InterruptedError.)
166 """
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700167
168
169class SubprocessProtocol(BaseProtocol):
Guido van Rossum9204af42013-11-30 15:35:42 -0800170 """Interface for protocol for subprocess calls."""
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700171
172 def pipe_data_received(self, fd, data):
Guido van Rossum2335de72013-11-15 16:51:48 -0800173 """Called when the subprocess writes data into stdout/stderr pipe.
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700174
Yury Selivanovdec1a452014-02-18 22:27:48 -0500175 fd is int file descriptor.
Guido van Rossum27b7c7e2013-10-17 13:40:50 -0700176 data is bytes object.
177 """
178
179 def pipe_connection_lost(self, fd, exc):
180 """Called when a file descriptor associated with the child process is
181 closed.
182
183 fd is the int file descriptor that was closed.
184 """
185
186 def process_exited(self):
Guido van Rossum2335de72013-11-15 16:51:48 -0800187 """Called when subprocess has exited."""
Yury Selivanov631fd382018-01-28 16:30:26 -0500188
189
190def _is_buffered_protocol(proto):
191 return hasattr(proto, 'get_buffer') and not hasattr(proto, 'data_received')