Repository: iterative/dvc

Issue:
pipeline show --ascii: `An operation was attempted on something that is not a socket`
From https://gist.github.com/artichaud1/e61905d826bc2bdbaaf7f3e05e812501 

```
λ dvc pipeline show --ascii -v
Error: Traceback (most recent call last):
  File "c:\users\klahrichi\appdata\local\continuum\anaconda3\lib\site-packages\dvc\main.py", line 22, in main
    ret = cmd.run_cmd()
  File "c:\users\klahrichi\appdata\local\continuum\anaconda3\lib\site-packages\dvc\command\base.py", line 41, in run_cmd
    return self.run()
  File "c:\users\klahrichi\appdata\local\continuum\anaconda3\lib\site-packages\dvc\command\pipeline.py", line 98, in run
    self.args.outs)
  File "c:\users\klahrichi\appdata\local\continuum\anaconda3\lib\site-packages\dvc\command\pipeline.py", line 79, in _show_ascii
    d.draw()
  File "c:\users\klahrichi\appdata\local\continuum\anaconda3\lib\site-packages\dvc\dagascii.py", line 278, in draw
    canvas.draw()
  File "c:\users\klahrichi\appdata\local\continuum\anaconda3\lib\site-packages\dvc\dagascii.py", line 23, in draw
    Screen.wrapper(self._do_draw)
  File "c:\users\klahrichi\appdata\local\continuum\anaconda3\lib\site-packages\asciimatics\screen.py", line 1170, in wrapper
    return func(screen)
  File "c:\users\klahrichi\appdata\local\continuum\anaconda3\lib\site-packages\dvc\dagascii.py", line 67, in _do_draw
    select.select([sys.stdin], [], [], None)
OSError: [WinError 10038] An operation was attempted on something that is not a socket

Error: Unexpected error: [WinError 10038] An operation was attempted on something that is not a socket
```


Discussion:

Resolving patch:
diff --git a/dvc/dagascii.py b/dvc/dagascii.py
--- a/dvc/dagascii.py
+++ b/dvc/dagascii.py
@@ -7,7 +7,7 @@
 
 
 class AsciiCanvas(object):
-    TIMEOUT = 1
+    TIMEOUT = 10
 
     def __init__(self, cols, lines):
         assert cols > 1
@@ -27,6 +27,7 @@ def draw(self):
                 print(''.join(line))
 
     def _do_draw(self, screen):  # pragma: no cover
+        from dvc.system import System
         from asciimatics.event import KeyboardEvent
 
         offset_x = 0
@@ -66,12 +67,12 @@ def _do_draw(self, screen):  # pragma: no cover
             # NOTE: get_event() doesn't block by itself,
             # so we have to do the blocking ourselves.
             #
-            # NOTE: using formally private method while waiting for PR [1]
-            # to get merged. After that need to adjust asciimatics version
-            # requirements.
+            # NOTE: using this workaround while waiting for PR [1]
+            # to get merged and released. After that need to adjust
+            # asciimatics version requirements.
             #
             # [1] https://github.com/peterbrittain/asciimatics/pull/188
-            screen._wait_for_input(self.TIMEOUT)
+            System.wait_for_input(self.TIMEOUT)
 
             event = screen.get_event()
             if not isinstance(event, KeyboardEvent):
diff --git a/dvc/system.py b/dvc/system.py
--- a/dvc/system.py
+++ b/dvc/system.py
@@ -205,3 +205,38 @@ def inode(path):
         assert inode >= 0
         assert inode < 2**64
         return inode
+
+    @staticmethod
+    def _wait_for_input_windows(timeout):
+        import sys
+        import ctypes
+        import msvcrt
+        from ctypes.wintypes import DWORD, HANDLE
+
+        # https://docs.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-waitforsingleobject
+        WAIT_OBJECT_0 = 0
+        WAIT_TIMEOUT = 0x00000102
+
+        func = ctypes.windll.kernel32.WaitForSingleObject
+        func.argtypes = [HANDLE, DWORD]
+        func.restype = DWORD
+
+        rc = func(msvcrt.get_osfhandle(sys.stdin.fileno()), timeout * 1000)
+        if rc not in [WAIT_OBJECT_0, WAIT_TIMEOUT]:
+            raise RuntimeError(rc)
+
+    @staticmethod
+    def _wait_for_input_posix(timeout):
+        import sys
+        import select
+        try:
+            select.select([sys.stdin], [], [], timeout)
+        except select.error:
+            pass
+
+    @staticmethod
+    def wait_for_input(timeout):
+        if System.is_unix():
+            return System._wait_for_input_posix(timeout)
+        else:
+            return System._wait_for_input_windows(timeout)
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -22,7 +22,7 @@
     "jsonpath-rw==1.4.0",
     "requests>=2.18.4",
     "grandalf==0.6",
-    "asciimatics==1.10.0",
+    "asciimatics>=1.10.0",
     "distro>=1.3.0",
 ]
 


Test patch: