efficient vim config
[dotfiles/.git] / .local / lib / python2.7 / site-packages / trollius / transports.py
1 """Abstract Transport class."""
2
3 from trollius import compat
4
5 __all__ = ['BaseTransport', 'ReadTransport', 'WriteTransport',
6            'Transport', 'DatagramTransport', 'SubprocessTransport',
7            ]
8
9
10 class BaseTransport(object):
11     """Base class for transports."""
12
13     def __init__(self, extra=None):
14         if extra is None:
15             extra = {}
16         self._extra = extra
17
18     def get_extra_info(self, name, default=None):
19         """Get optional transport information."""
20         return self._extra.get(name, default)
21
22     def close(self):
23         """Close the transport.
24
25         Buffered data will be flushed asynchronously.  No more data
26         will be received.  After all buffered data is flushed, the
27         protocol's connection_lost() method will (eventually) called
28         with None as its argument.
29         """
30         raise NotImplementedError
31
32
33 class ReadTransport(BaseTransport):
34     """Interface for read-only transports."""
35
36     def pause_reading(self):
37         """Pause the receiving end.
38
39         No data will be passed to the protocol's data_received()
40         method until resume_reading() is called.
41         """
42         raise NotImplementedError
43
44     def resume_reading(self):
45         """Resume the receiving end.
46
47         Data received will once again be passed to the protocol's
48         data_received() method.
49         """
50         raise NotImplementedError
51
52
53 class WriteTransport(BaseTransport):
54     """Interface for write-only transports."""
55
56     def set_write_buffer_limits(self, high=None, low=None):
57         """Set the high- and low-water limits for write flow control.
58
59         These two values control when to call the protocol's
60         pause_writing() and resume_writing() methods.  If specified,
61         the low-water limit must be less than or equal to the
62         high-water limit.  Neither value can be negative.
63
64         The defaults are implementation-specific.  If only the
65         high-water limit is given, the low-water limit defaults to a
66         implementation-specific value less than or equal to the
67         high-water limit.  Setting high to zero forces low to zero as
68         well, and causes pause_writing() to be called whenever the
69         buffer becomes non-empty.  Setting low to zero causes
70         resume_writing() to be called only once the buffer is empty.
71         Use of zero for either limit is generally sub-optimal as it
72         reduces opportunities for doing I/O and computation
73         concurrently.
74         """
75         raise NotImplementedError
76
77     def get_write_buffer_size(self):
78         """Return the current size of the write buffer."""
79         raise NotImplementedError
80
81     def write(self, data):
82         """Write some data bytes to the transport.
83
84         This does not block; it buffers the data and arranges for it
85         to be sent out asynchronously.
86         """
87         raise NotImplementedError
88
89     def writelines(self, list_of_data):
90         """Write a list (or any iterable) of data bytes to the transport.
91
92         The default implementation concatenates the arguments and
93         calls write() on the result.
94         """
95         data = compat.flatten_list_bytes(list_of_data)
96         self.write(data)
97
98     def write_eof(self):
99         """Close the write end after flushing buffered data.
100
101         (This is like typing ^D into a UNIX program reading from stdin.)
102
103         Data may still be received.
104         """
105         raise NotImplementedError
106
107     def can_write_eof(self):
108         """Return True if this transport supports write_eof(), False if not."""
109         raise NotImplementedError
110
111     def abort(self):
112         """Close the transport immediately.
113
114         Buffered data will be lost.  No more data will be received.
115         The protocol's connection_lost() method will (eventually) be
116         called with None as its argument.
117         """
118         raise NotImplementedError
119
120
121 class Transport(ReadTransport, WriteTransport):
122     """Interface representing a bidirectional transport.
123
124     There may be several implementations, but typically, the user does
125     not implement new transports; rather, the platform provides some
126     useful transports that are implemented using the platform's best
127     practices.
128
129     The user never instantiates a transport directly; they call a
130     utility function, passing it a protocol factory and other
131     information necessary to create the transport and protocol.  (E.g.
132     EventLoop.create_connection() or EventLoop.create_server().)
133
134     The utility function will asynchronously create a transport and a
135     protocol and hook them up by calling the protocol's
136     connection_made() method, passing it the transport.
137
138     The implementation here raises NotImplemented for every method
139     except writelines(), which calls write() in a loop.
140     """
141
142
143 class DatagramTransport(BaseTransport):
144     """Interface for datagram (UDP) transports."""
145
146     def sendto(self, data, addr=None):
147         """Send data to the transport.
148
149         This does not block; it buffers the data and arranges for it
150         to be sent out asynchronously.
151         addr is target socket address.
152         If addr is None use target address pointed on transport creation.
153         """
154         raise NotImplementedError
155
156     def abort(self):
157         """Close the transport immediately.
158
159         Buffered data will be lost.  No more data will be received.
160         The protocol's connection_lost() method will (eventually) be
161         called with None as its argument.
162         """
163         raise NotImplementedError
164
165
166 class SubprocessTransport(BaseTransport):
167
168     def get_pid(self):
169         """Get subprocess id."""
170         raise NotImplementedError
171
172     def get_returncode(self):
173         """Get subprocess returncode.
174
175         See also
176         http://docs.python.org/3/library/subprocess#subprocess.Popen.returncode
177         """
178         raise NotImplementedError
179
180     def get_pipe_transport(self, fd):
181         """Get transport for pipe with number fd."""
182         raise NotImplementedError
183
184     def send_signal(self, signal):
185         """Send signal to subprocess.
186
187         See also:
188         docs.python.org/3/library/subprocess#subprocess.Popen.send_signal
189         """
190         raise NotImplementedError
191
192     def terminate(self):
193         """Stop the subprocess.
194
195         Alias for close() method.
196
197         On Posix OSs the method sends SIGTERM to the subprocess.
198         On Windows the Win32 API function TerminateProcess()
199          is called to stop the subprocess.
200
201         See also:
202         http://docs.python.org/3/library/subprocess#subprocess.Popen.terminate
203         """
204         raise NotImplementedError
205
206     def kill(self):
207         """Kill the subprocess.
208
209         On Posix OSs the function sends SIGKILL to the subprocess.
210         On Windows kill() is an alias for terminate().
211
212         See also:
213         http://docs.python.org/3/library/subprocess#subprocess.Popen.kill
214         """
215         raise NotImplementedError
216
217
218 class _FlowControlMixin(Transport):
219     """All the logic for (write) flow control in a mix-in base class.
220
221     The subclass must implement get_write_buffer_size().  It must call
222     _maybe_pause_protocol() whenever the write buffer size increases,
223     and _maybe_resume_protocol() whenever it decreases.  It may also
224     override set_write_buffer_limits() (e.g. to specify different
225     defaults).
226
227     The subclass constructor must call super(Class, self).__init__(extra).  This
228     will call set_write_buffer_limits().
229
230     The user may call set_write_buffer_limits() and
231     get_write_buffer_size(), and their protocol's pause_writing() and
232     resume_writing() may be called.
233     """
234
235     def __init__(self, extra=None, loop=None):
236         super(_FlowControlMixin, self).__init__(extra)
237         assert loop is not None
238         self._loop = loop
239         self._protocol_paused = False
240         self._set_write_buffer_limits()
241
242     def _maybe_pause_protocol(self):
243         size = self.get_write_buffer_size()
244         if size <= self._high_water:
245             return
246         if not self._protocol_paused:
247             self._protocol_paused = True
248             try:
249                 self._protocol.pause_writing()
250             except Exception as exc:
251                 self._loop.call_exception_handler({
252                     'message': 'protocol.pause_writing() failed',
253                     'exception': exc,
254                     'transport': self,
255                     'protocol': self._protocol,
256                 })
257
258     def _maybe_resume_protocol(self):
259         if (self._protocol_paused and
260             self.get_write_buffer_size() <= self._low_water):
261             self._protocol_paused = False
262             try:
263                 self._protocol.resume_writing()
264             except Exception as exc:
265                 self._loop.call_exception_handler({
266                     'message': 'protocol.resume_writing() failed',
267                     'exception': exc,
268                     'transport': self,
269                     'protocol': self._protocol,
270                 })
271
272     def get_write_buffer_limits(self):
273         return (self._low_water, self._high_water)
274
275     def _set_write_buffer_limits(self, high=None, low=None):
276         if high is None:
277             if low is None:
278                 high = 64*1024
279             else:
280                 high = 4*low
281         if low is None:
282             low = high // 4
283         if not high >= low >= 0:
284             raise ValueError('high (%r) must be >= low (%r) must be >= 0' %
285                              (high, low))
286         self._high_water = high
287         self._low_water = low
288
289     def set_write_buffer_limits(self, high=None, low=None):
290         self._set_write_buffer_limits(high=high, low=low)
291         self._maybe_pause_protocol()
292
293     def get_write_buffer_size(self):
294         raise NotImplementedError