Repository: sanic-org/sanic

Issue:
Incorrect documentation for AsyncioServer or missing __getattr__ on AsyncioServer
**Describe the bug**
The described sample code for the AsyncIO server is out of date (https://sanic.readthedocs.io/en/latest/sanic/asyncio_python37.html) or a resultant merge stripped a `__getattr__` handler from the AsyncIOServer class. 

I discovered this while bootstrapping a mock Azure API inside pytest for my API server (all Sanic because, why not?)

**Code snippet**
```
#!/usr/bin/env python3
import socket
import asyncio

from sanic import Sanic
from sanic.response import text

async def main():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
    sock.bind(("", 0))
    print(sock.getsockname())

    app = Sanic("azure_test_api")

    @app.get("/")
    async def test_index(request):
        return text('test')

    server = await app.create_server(
        sock=sock,
        return_asyncio_server=True,
        asyncio_server_kwargs=dict(start_serving=False),
    )
    # The docs say this
    await server.start_serving()
    await server.serve_forever()
    # but only this works ;)
    # await server.server.start_serving()
    # await server.server.serve_forever()

if __name__ == "__main__":
    asyncio.set_event_loop_policy(asyncio.DefaultEventLoopPolicy())
    asyncio.run(main())
```

**Expected behavior**
I expect the docs to be updated or the following added to the AsyncIOServer class in server.py (https://github.com/huge-success/sanic/blob/2f776eba85b80ed5ee7e75badb92028ee1df0f4f/sanic/server.py#L671) -

```
    def __getattr__(self, prop_name):
         if not self.server:
            raise AttributeError('{} not found on {}'.format(prop_name, self)
         return getattr(self.server, prop_name)

```

**Environment (please complete the following information):**
 - OS: osx
 - Version 10.14.6 (18G95)


**Additional context**
N/A


Discussion:
Hi @autumnjolitz 
This might be a problem introduced by my changes in this PR: https://github.com/huge-success/sanic/pull/1676
I didn't test those changes on python3.7, nor with the "server.start_serving()" or "server.serve_forever()" methods.
We can change the documentation to reflect the code changes you mentioned, or we can add those properties to the AsyncioServer proxy object in a future Sanic version.
I think the better change is the second described by @ashleysommer: changing the code to reflect the existing documentation to undo the regression. 👍

PRS welcome.

Resolving patch:
diff --git a/sanic/server.py b/sanic/server.py
--- a/sanic/server.py
+++ b/sanic/server.py
@@ -735,6 +735,26 @@ def close(self):
             task = asyncio.ensure_future(coro, loop=self.loop)
             return task
 
+    def start_serving(self):
+        if self.server:
+            try:
+                return self.server.start_serving()
+            except AttributeError:
+                raise NotImplementedError(
+                    "server.start_serving not available in this version "
+                    "of asyncio or uvloop."
+                )
+
+    def serve_forever(self):
+        if self.server:
+            try:
+                return self.server.serve_forever()
+            except AttributeError:
+                raise NotImplementedError(
+                    "server.serve_forever not available in this version "
+                    "of asyncio or uvloop."
+                )
+
     def __await__(self):
         """Starts the asyncio server, returns AsyncServerCoro"""
         task = asyncio.ensure_future(self.serve_coro)


Test patch:
diff --git a/tests/test_app.py b/tests/test_app.py
--- a/tests/test_app.py
+++ b/tests/test_app.py
@@ -44,7 +44,7 @@ def test_create_asyncio_server(app):
 @pytest.mark.skipif(
     sys.version_info < (3, 7), reason="requires python3.7 or higher"
 )
-def test_asyncio_server_start_serving(app):
+def test_asyncio_server_no_start_serving(app):
     if not uvloop_installed():
         loop = asyncio.get_event_loop()
         asyncio_srv_coro = app.create_server(
@@ -54,6 +54,22 @@ def test_asyncio_server_start_serving(app):
         srv = loop.run_until_complete(asyncio_srv_coro)
         assert srv.is_serving() is False
 
+@pytest.mark.skipif(
+    sys.version_info < (3, 7), reason="requires python3.7 or higher"
+)
+def test_asyncio_server_start_serving(app):
+    if not uvloop_installed():
+        loop = asyncio.get_event_loop()
+        asyncio_srv_coro = app.create_server(
+            return_asyncio_server=True,
+            asyncio_server_kwargs=dict(start_serving=False),
+        )
+        srv = loop.run_until_complete(asyncio_srv_coro)
+        assert srv.is_serving() is False
+        loop.run_until_complete(srv.start_serving())
+        assert srv.is_serving() is True
+        srv.close()
+        # Looks like we can't easily test `serve_forever()`
 
 def test_app_loop_not_running(app):
     with pytest.raises(SanicException) as excinfo: