Repository: mkdocs/mkdocs

Issue:
Asyncio NotImplemented Error after Python 3.8.0
Using a new install of Python 3.8.0, pip installed latest version of MkDocs, and then tried to run `mkdocs serve`, which encountered the below error. 

I tried again on a new docs directory (`mkdocs new testing`), but encountered the same issue again. 

Python version: 3.8.0
OS: Windows 10 Pro v1709

error:
```
C:\dev\testing
λ  mkdocs serve
INFO    -  Building documentation...
INFO    -  Cleaning site directory
[I 191017 14:49:48 server:296] Serving on http://127.0.0.1:8000
Traceback (most recent call last):
  File "c:\users\aleksandr.skobelev\appdata\local\programs\python\python38\lib\runpy.py", line 192, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\users\aleksandr.skobelev\appdata\local\programs\python\python38\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "C:\Users\aleksandr.skobelev\AppData\Local\Programs\Python\Python38\Scripts\mkdocs.exe\__main__.py", line 9, in <module>
  File "c:\users\aleksandr.skobelev\appdata\local\programs\python\python38\lib\site-packages\click\core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "c:\users\aleksandr.skobelev\appdata\local\programs\python\python38\lib\site-packages\click\core.py", line 717, in main
    rv = self.invoke(ctx)
  File "c:\users\aleksandr.skobelev\appdata\local\programs\python\python38\lib\site-packages\click\core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "c:\users\aleksandr.skobelev\appdata\local\programs\python\python38\lib\site-packages\click\core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "c:\users\aleksandr.skobelev\appdata\local\programs\python\python38\lib\site-packages\click\core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "c:\users\aleksandr.skobelev\appdata\local\programs\python\python38\lib\site-packages\mkdocs\__main__.py", line 128, in serve_command
    serve.serve(
  File "c:\users\aleksandr.skobelev\appdata\local\programs\python\python38\lib\site-packages\mkdocs\commands\serve.py", line 124, in serve
    _livereload(host, port, config, builder, site_dir)
  File "c:\users\aleksandr.skobelev\appdata\local\programs\python\python38\lib\site-packages\mkdocs\commands\serve.py", line 58, in _livereload
    server.serve(root=site_dir, host=host, port=port, restart_delay=0)
  File "c:\users\aleksandr.skobelev\appdata\local\programs\python\python38\lib\site-packages\livereload\server.py", line 298, in serve
    self.application(
  File "c:\users\aleksandr.skobelev\appdata\local\programs\python\python38\lib\site-packages\livereload\server.py", line 253, in application
    app.listen(port, address=host)
  File "c:\users\aleksandr.skobelev\appdata\local\programs\python\python38\lib\site-packages\tornado\web.py", line 2112, in listen
    server.listen(port, address)
  File "c:\users\aleksandr.skobelev\appdata\local\programs\python\python38\lib\site-packages\tornado\tcpserver.py", line 152, in listen
    self.add_sockets(sockets)
  File "c:\users\aleksandr.skobelev\appdata\local\programs\python\python38\lib\site-packages\tornado\tcpserver.py", line 165, in add_sockets
    self._handlers[sock.fileno()] = add_accept_handler(
  File "c:\users\aleksandr.skobelev\appdata\local\programs\python\python38\lib\site-packages\tornado\netutil.py", line 279, in add_accept_handler
    io_loop.add_handler(sock, accept_handler, IOLoop.READ)
  File "c:\users\aleksandr.skobelev\appdata\local\programs\python\python38\lib\site-packages\tornado\platform\asyncio.py", line 99, in add_handler
    self.asyncio_loop.add_reader(fd, self._handle_events, fd, IOLoop.READ)
  File "c:\users\aleksandr.skobelev\appdata\local\programs\python\python38\lib\asyncio\events.py", line 501, in add_reader
    raise NotImplementedError
NotImplementedError
```


Discussion:
Thanks for the report. This appears to be related to tornadoweb/tornado#2608. I'm assuming this will need to be fixed by [lepture/python-livereload][1]. However, I don't see any reports there yet and I don't have a way to test this on Windows myself. If anyone can confirm this error exists in plain python-livereload on Windows, please report this upstream to that project. We will determine how to proceed based on that.

[1]: https://github.com/lepture/python-livereload
+1 
I've same error
As a test could someone who is getting the error confirm that the error also occurs when running these commands:

```
mkdocs build
livereload site
```

That runs livereload directly without MkDocs light wrapper. My expectation is that the error will also occur there. If it does, the error needs to be reported upstream to that project to be fixed. If it does not occur there, then we will fix it in MkDocs.
Python version:
```
E:\Sync\SKN\Projekty\2019_03_Roboty` Mobilne 1\Pliki\AlphaBot2>python --version
Python 3.8.0
```

mkdocs build command
```
E:\Sync\SKN\Projekty\2019_03_Roboty Mobilne 1\Pliki\AlphaBot2>mkdocs build
INFO    -  Cleaning site directory
INFO    -  Building documentation to directory: E:\Sync\SKN\Projekty\2019_03_Roboty Mobilne 1\Pliki\AlphaBot2\site
```

livereload site command
```
E:\Sync\SKN\Projekty\2019_03_Roboty Mobilne 1\Pliki\AlphaBot2>livereload site
[I 191026 22:40:22 server:296] Serving on http://127.0.0.1:35729
Traceback (most recent call last):
  File "c:\program files\python38\lib\runpy.py", line 192, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\program files\python38\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "C:\Program Files\Python38\Scripts\livereload.exe\__main__.py", line 7, in <module>
  File "c:\program files\python38\lib\site-packages\livereload\cli.py", line 60, in main
    server.serve(host=args.host, port=args.port, root=args.directory,
  File "c:\program files\python38\lib\site-packages\livereload\server.py", line 298, in serve
    self.application(
  File "c:\program files\python38\lib\site-packages\livereload\server.py", line 253, in application
    app.listen(port, address=host)
  File "c:\program files\python38\lib\site-packages\tornado\web.py", line 2112, in listen
    server.listen(port, address)
  File "c:\program files\python38\lib\site-packages\tornado\tcpserver.py", line 152, in listen
    self.add_sockets(sockets)
  File "c:\program files\python38\lib\site-packages\tornado\tcpserver.py", line 165, in add_sockets
    self._handlers[sock.fileno()] = add_accept_handler(
  File "c:\program files\python38\lib\site-packages\tornado\netutil.py", line 279, in add_accept_handler
    io_loop.add_handler(sock, accept_handler, IOLoop.READ)
  File "c:\program files\python38\lib\site-packages\tornado\platform\asyncio.py", line 99, in add_handler
    self.asyncio_loop.add_reader(fd, self._handle_events, fd, IOLoop.READ)
  File "c:\program files\python38\lib\asyncio\events.py", line 501, in add_reader
    raise NotImplementedError
NotImplementedError
```
@SaDiablo thanks for the update. I have used your error message to report the issue upstream to lepture/python-livereload#209. When we get a response there, it will inform us how to proceed here.
It happened the same to me once I updated the pip version using Chocolatey

```
PS C:\Users\daja0716\Seafile\Sync\Backup\my-wiki> python --version
Python 3.8.0

```
```
PS C:\Users\daja0716\Seafile\Sync\Backup\my-wiki> pip --version
pip 19.3.1 from c:\python38\lib\site-packages\pip (python 3.8)
```
OS: Windows 10 v1903

```
PS C:\Users\daja0716\Seafile\Sync\Backup\my-wiki> mkdocs serve
INFO    -  Building documentation...
INFO    -  Cleaning site directory
[I 191112 17:08:24 server:296] Serving on http://127.0.0.1:8000
Traceback (most recent call last):
  File "c:\python38\lib\runpy.py", line 192, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\python38\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "C:\Python38\Scripts\mkdocs.exe\__main__.py", line 7, in <module>
  File "c:\python38\lib\site-packages\click\core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "c:\python38\lib\site-packages\click\core.py", line 717, in main
    rv = self.invoke(ctx)
  File "c:\python38\lib\site-packages\click\core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "c:\python38\lib\site-packages\click\core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "c:\python38\lib\site-packages\click\core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "c:\python38\lib\site-packages\mkdocs\__main__.py", line 128, in serve_command
    serve.serve(
  File "c:\python38\lib\site-packages\mkdocs\commands\serve.py", line 124, in serve
    _livereload(host, port, config, builder, site_dir)
  File "c:\python38\lib\site-packages\mkdocs\commands\serve.py", line 58, in _livereload
    server.serve(root=site_dir, host=host, port=port, restart_delay=0)
  File "c:\python38\lib\site-packages\livereload\server.py", line 298, in serve
    self.application(
  File "c:\python38\lib\site-packages\livereload\server.py", line 253, in application
    app.listen(port, address=host)
  File "c:\python38\lib\site-packages\tornado\web.py", line 2112, in listen
    server.listen(port, address)
  File "c:\python38\lib\site-packages\tornado\tcpserver.py", line 152, in listen
    self.add_sockets(sockets)
  File "c:\python38\lib\site-packages\tornado\tcpserver.py", line 165, in add_sockets
    self._handlers[sock.fileno()] = add_accept_handler(
  File "c:\python38\lib\site-packages\tornado\netutil.py", line 279, in add_accept_handler
    io_loop.add_handler(sock, accept_handler, IOLoop.READ)
  File "c:\python38\lib\site-packages\tornado\platform\asyncio.py", line 99, in add_handler
    self.asyncio_loop.add_reader(fd, self._handle_events, fd, IOLoop.READ)
  File "c:\python38\lib\asyncio\events.py", line 501, in add_reader
    raise NotImplementedError
NotImplementedError
```


When running the 
```
mkdocs build
livereload site
```


```
PS C:\Users\daja0716\Seafile\Sync\Backup\my-wiki> mkdocs build
INFO    -  Cleaning site directory
INFO    -  Building documentation to directory: C:\Users\daja0716\Seafile\Sync\Backup\my-wiki\site
PS C:\Users\daja0716\Seafile\Sync\Backup\my-wiki> livereload site
[I 191112 17:15:15 server:296] Serving on http://127.0.0.1:35729
Traceback (most recent call last):
  File "c:\python38\lib\runpy.py", line 192, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\python38\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "C:\Python38\Scripts\livereload.exe\__main__.py", line 9, in <module>
  File "c:\python38\lib\site-packages\livereload\cli.py", line 60, in main
    server.serve(host=args.host, port=args.port, root=args.directory,
  File "c:\python38\lib\site-packages\livereload\server.py", line 298, in serve
    self.application(
  File "c:\python38\lib\site-packages\livereload\server.py", line 253, in application
    app.listen(port, address=host)
  File "c:\python38\lib\site-packages\tornado\web.py", line 2112, in listen
    server.listen(port, address)
  File "c:\python38\lib\site-packages\tornado\tcpserver.py", line 152, in listen
    self.add_sockets(sockets)
  File "c:\python38\lib\site-packages\tornado\tcpserver.py", line 165, in add_sockets
    self._handlers[sock.fileno()] = add_accept_handler(
  File "c:\python38\lib\site-packages\tornado\netutil.py", line 279, in add_accept_handler
    io_loop.add_handler(sock, accept_handler, IOLoop.READ)
  File "c:\python38\lib\site-packages\tornado\platform\asyncio.py", line 99, in add_handler
    self.asyncio_loop.add_reader(fd, self._handle_events, fd, IOLoop.READ)
  File "c:\python38\lib\asyncio\events.py", line 501, in add_reader
    raise NotImplementedError
NotImplementedError
```
Yes, we know it is a problem. However, the problem is upstream and we can only wait for it to be fixed there. Adding "me too" reports will not change that. 
If you have PHP installed, then you can build and then serve

```
mkdocs build
php -S 127.0.0.1:8000
```

If you made any change then open a new cmd and rebuild

`mkdocs build`
I just noticed [lepture/python-livereload][1] includes the text "MAINTAINERS NEEDED" in the Project Description at the top of the page. Given that no response has been made even if just to answer the question of how Python-Livereload plans to move forward, I think we will need to provide our own solution. However, it should be done in such a way that any upstream fix won't create a problem.

[1]: https://github.com/lepture/python-livereload

Resolving patch:
diff --git a/mkdocs/commands/serve.py b/mkdocs/commands/serve.py
--- a/mkdocs/commands/serve.py
+++ b/mkdocs/commands/serve.py
@@ -3,6 +3,7 @@
 import logging
 import shutil
 import tempfile
+import sys
 
 from os.path import isfile, join
 from mkdocs.commands.build import build
@@ -11,6 +12,26 @@
 log = logging.getLogger(__name__)
 
 
+def _init_asyncio_patch():
+    """
+    Select compatible event loop for Tornado 5+.
+
+    As of Python 3.8, the default event loop on Windows is `proactor`,
+    however Tornado requires the old default "selector" event loop.
+    As Tornado has decided to leave this to users to set, MkDocs needs
+    to set it. See https://github.com/tornadoweb/tornado/issues/2608.
+    """
+    if sys.platform.startswith("win") and sys.version_info >= (3, 8):
+        import asyncio
+        try:
+            from asyncio import WindowsSelectorEventLoopPolicy
+        except ImportError:
+            pass  # Can't assign a policy which doesn't exist.
+        else:
+            if not isinstance(asyncio.get_event_loop_policy(), WindowsSelectorEventLoopPolicy):
+                asyncio.set_event_loop_policy(WindowsSelectorEventLoopPolicy())
+
+
 def _get_handler(site_dir, StaticFileHandler):
 
     from tornado.template import Loader
@@ -33,6 +54,7 @@ def _livereload(host, port, config, builder, site_dir):
 
     # We are importing here for anyone that has issues with livereload. Even if
     # this fails, the --no-livereload alternative should still work.
+    _init_asyncio_patch()
     from livereload import Server
     import livereload.handlers
 
@@ -62,6 +84,7 @@ def _static_server(host, port, site_dir):
 
     # Importing here to seperate the code paths from the --livereload
     # alternative.
+    _init_asyncio_patch()
     from tornado import ioloop
     from tornado import web
 


Test patch: