title: Understanding python asyncio Protocol
body: <p>I am lacking understanding on how Python asyncio and protocols are working.</p>
  
  <p>Documentaion that seems relevant:<br>
  <a href="https://docs.python.org/3/library/asyncio-protocol.html#asyncio.Protocol" rel="nofollow noreferrer"><code>class asyncio.Protocol</code></a><br>
  <a href="https://docs.python.org/3/library/asyncio-protocol.html#asyncio.Protocol.eof_received" rel="nofollow noreferrer"><code>Protocol.eof_received()</code></a>  state machine shows relevant transitions
  <a href="https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.run_until_complete" rel="nofollow noreferrer"><code>AbstractEventLoop.run_until_complete(future)</code></a> </p>
  
  <p>Example code that is echo tcp client:</p>
  
  <pre><code>import asyncio
  
  class EchoClientProtocol(asyncio.Protocol):
      def __init__(self, message, loop):
          self.message = message.encode()
  
      def connection_made(self, transport):
          self.transport = transport
          self.write_data()
  
      def data_received(self, data):
          print('Data received: {!r}',len(data))
          self.write_data()
  
      def eof_received(self):
          print("eof")
          return True
  
      def write_data(self):
          print("write")
          self.transport.write(self.message)
  
      def connection_lost(self, exc):
          print('The server closed the connection')
          print('Stop the event loop')
  
  
  loop = asyncio.get_event_loop()
  message = 'Hello World!'
  
  coro = loop.create_connection(lambda: EchoClientProtocol(message, loop),
                                '127.0.0.1', 5676)
  loop.run_until_complete(coro)
  print("done")
  </code></pre>
  
  <p>Output when connceted on echo server:</p>
  
  <pre><code>write
  Data received: {!r} 12
  write
  done
  </code></pre>
  
  <p>From what I understand this should run until connection is closed. </p>
  
  <p>From: <a href="https://docs.python.org/3/library/asyncio-protocol.html#connection-callbacks" rel="nofollow noreferrer">Connection callbacks</a></p>
  
  <p>connection_made() and connection_lost() are called exactly once per successful connection. All other callbacks will be called between those two methods, which allows for easier resource management in your protocol implementation.</p>
  
  <p>and from also state machine:</p>
  
  <pre><code>start 
  -&gt; connection_made
  [-&gt; data_received]*
  [-&gt; eof_received]?
  -&gt; connection_lost 
  -&gt; end
  </code></pre>
  
  <p>But, function <code>EchoClientProtocol.connection_lost</code> is never called and 
  <code>loop.run_until_complete(coro)</code> terminates before Protocol completes. </p>
  
  <p>Question is:<br>
  How to get coroutine/future that wraps protocol in a way that coroutine completes when end state of protocol is reached and loop.run_until_complete returns on such event.</p>