Repository: psf/black
Pull request: Wrap `loop.run_in_executor` up in `asyncio.ensure_future` for reliable cross-platform berhavior.
Closes #494

Task completion should also remove the task from `pending`.

Only replicates on some platforms. (eg. Can replicate on Python 3.7+, with either Windows or whatever default Linux distro Travis uses.)

Problem statement:
Black is not formatting code on Python 3.7 on some platform configurations (Windows, Ubuntu)
Howdy! Sorry you're having trouble. To expedite your experience,
provide some basics for me:

Operating system: Windows 10 64bit
Python version: Python 3.7.0 (32Bit)
*Black* version: 18.6b4
Does also happen on master: Yes

When running black for directory it fails without any error when formatting.

As far as I can tell it happens here:
`black.py@445`

```py
tasks = {
        loop.run_in_executor(
            executor,
            format_file_in_place,
            src,
            line_length,
            fast,
            write_back,
            mode,
            lock,
        ): src
        for src in sorted(sources)
    }
```

So I'm not sure if it's an bug in black or somewhere deeper. Or it might just be a feature of running 32bit python3 on windows 64bit.
It doesn't happen when using py3.7 64bit. Nor on py3.6 64bit. When I have a moment I'll test it on py3.6 32bit.

Hints from issue discussion:
Interesting, some related tests indeed fail on a 32bit 3.7.0, but not 3.6.5. I'll look into this.
Sounds like an issue with asyncio.
Just confirming this issue here too. The traceback I see for it is...

```python
Traceback (most recent call last):
  File "/home/travis/virtualenv/python3.7-dev/bin/black", line 11, in <module>
    sys.exit(main())
  File "/home/travis/virtualenv/python3.7-dev/lib/python3.7/site-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/home/travis/virtualenv/python3.7-dev/lib/python3.7/site-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/home/travis/virtualenv/python3.7-dev/lib/python3.7/site-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/travis/virtualenv/python3.7-dev/lib/python3.7/site-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/home/travis/virtualenv/python3.7-dev/lib/python3.7/site-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/home/travis/virtualenv/python3.7-dev/lib/python3.7/site-packages/black.py", line 372, in main
    executor=executor,
  File "/opt/python/3.7-dev/lib/python3.7/asyncio/base_events.py", line 495, in run_until_complete
    return future.result()
  File "/home/travis/virtualenv/python3.7-dev/lib/python3.7/site-packages/black.py", line 486, in schedule_formatting
    src = tasks.pop(task)
KeyError: <Task finished coro=<BaseEventLoop.run_in_executor() done, defined at /opt/python/3.7-dev/lib/python3.7/asyncio/base_events.py:653> result=False>
```
This is not specifically a windows issue. Eg. Same issue replicates running on travis/linux here: https://travis-ci.org/encode/starlette/jobs/439045800
But it is limited to 3.7.

Commit message: Ensure that 'tasks.keys()' are always Task instances

Patch to review:
diff --git a/black.py b/black.py
index 32693227ed2..b0a9a32a40f 100644
--- a/black.py
+++ b/black.py
@@ -464,15 +464,17 @@ async def schedule_formatting(
         manager = Manager()
         lock = manager.Lock()
     tasks = {
-        loop.run_in_executor(
-            executor,
-            format_file_in_place,
-            src,
-            line_length,
-            fast,
-            write_back,
-            mode,
-            lock,
+        asyncio.create_task(
+            loop.run_in_executor(
+                executor,
+                format_file_in_place,
+                src,
+                line_length,
+                fast,
+                write_back,
+                mode,
+                lock,
+            )
         ): src
         for src in sorted(sources)
     }


Code review comments:
diff_hunk: @@ -464,15 +464,17 @@ def reformat_one(
         manager = Manager()
         lock = manager.Lock()
     tasks = {
-        loop.run_in_executor(
-            executor,
-            format_file_in_place,
-            src,
-            line_length,
-            fast,
-            write_back,
-            mode,
-            lock,
+        asyncio.create_task(
path: black.py
text: @user1:
create_task is new in 3.7, so we can't use it yet in Black, since we support 3.6 (https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task)