Repository: pallets/click

Issue:
Characters getting from terminal using getchar returns bytes
Hello,
it is said in the documentation that _getchar_ function **always returns unicode** [there](http://click.pocoo.org/6/utils/#getting-characters-from-terminal), but when i tried to use the code snippet of the documentation on my **windows 10** machine, i always fell on `"invalid input :("`

I inspected the type of value returned and I realized that it was _**bytes**_. So either you have to change the documentation and the code like this:
```python
    click.echo('Continue? [yn] ', nl=False)
    c = click.getchar()
    if c == b'y':
        click.echo('We will go on')
    elif c == b'n':
        click.echo('Abort!')
    else:
        click.echo('Invalid input :(')
```

either the problem have to be solved..

I'm using click 6.7, python 3.6 and I'm working under windows 10.


Discussion:

Resolving patch:
diff --git a/click/_termui_impl.py b/click/_termui_impl.py
--- a/click/_termui_impl.py
+++ b/click/_termui_impl.py
@@ -529,7 +529,9 @@ def _unquote_file(url):
 def _translate_ch_to_exc(ch):
     if ch == '\x03':
         raise KeyboardInterrupt()
-    if ch == '\x04':
+    if ch == '\x04' and not WIN:  # Unix-like, Ctrl+D
+        raise EOFError()
+    if ch == '\x1a' and WIN:      # Windows, Ctrl+Z
         raise EOFError()
 
 
@@ -541,16 +543,46 @@ def raw_terminal():
         yield
 
     def getchar(echo):
-        rv = msvcrt.getch()
+        # The function `getch` will return a bytes object corresponding to
+        # the pressed character. Since Windows 10 build 1803, it will also
+        # return \x00 when called a second time after pressing a regular key.
+        #
+        # `getwch` does not share this probably-bugged behavior. Moreover, it
+        # returns a Unicode object by default, which is what we want.
+        #
+        # Either of these functions will return \x00 or \xe0 to indicate
+        # a special key, and you need to call the same function again to get
+        # the "rest" of the code. The fun part is that \u00e0 is
+        # "latin small letter a with grave", so if you type that on a French
+        # keyboard, you _also_ get a \xe0.
+        # E.g., consider the Up arrow. This returns \xe0 and then \x48. The
+        # resulting Unicode string reads as "a with grave" + "capital H".
+        # This is indistinguishable from when the user actually types
+        # "a with grave" and then "capital H".
+        #
+        # When \xe0 is returned, we assume it's part of a special-key sequence
+        # and call `getwch` again, but that means that when the user types
+        # the \u00e0 character, `getchar` doesn't return until a second
+        # character is typed.
+        # The alternative is returning immediately, but that would mess up
+        # cross-platform handling of arrow keys and others that start with
+        # \xe0. Another option is using `getch`, but then we can't reliably
+        # read non-ASCII characters, because return values of `getch` are
+        # limited to the current 8-bit codepage.
+        #
+        # Anyway, Click doesn't claim to do this Right(tm), and using `getwch`
+        # is doing the right thing in more situations than with `getch`.
         if echo:
-            msvcrt.putchar(rv)
+            func = msvcrt.getwche
+        else:
+            func = msvcrt.getwch
+
+        rv = func()
+        if rv in (u'\x00', u'\xe0'):
+            # \x00 and \xe0 are control characters that indicate special key,
+            # see above.
+            rv += func()
         _translate_ch_to_exc(rv)
-        if PY2:
-            enc = getattr(sys.stdin, 'encoding', None)
-            if enc is not None:
-                rv = rv.decode(enc, 'replace')
-            else:
-                rv = rv.decode('cp1252', 'replace')
         return rv
 else:
     import tty
diff --git a/click/termui.py b/click/termui.py
--- a/click/termui.py
+++ b/click/termui.py
@@ -557,6 +557,10 @@ def getchar(echo=False):
     Note that this will always read from the terminal, even if something
     is piped into the standard input.
 
+    Note for Windows: in rare cases when typing non-ASCII characters, this
+    function might wait for a second character and then return both at once.
+    This is because certain Unicode characters look like special-key markers.
+
     .. versionadded:: 2.0
 
     :param echo: if set to `True`, the character read will also show up on


Test patch: