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