diff options
Diffstat (limited to 'Lib/getpass.py')
| -rw-r--r-- | Lib/getpass.py | 99 | 
1 files changed, 54 insertions, 45 deletions
diff --git a/Lib/getpass.py b/Lib/getpass.py index 0044742193..53c38b8897 100644 --- a/Lib/getpass.py +++ b/Lib/getpass.py @@ -15,7 +15,11 @@ On the Mac EasyDialogs.AskPassword is used, if available.  #          Guido van Rossum (Windows support and cleanup)  #          Gregory P. Smith (tty support & GetPassWarning) -import os, sys, warnings +import contextlib +import io +import os +import sys +import warnings  __all__ = ["getpass","getuser","GetPassWarning"] @@ -38,52 +42,57 @@ def unix_getpass(prompt='Password: ', stream=None):      Always restores terminal settings before returning.      """ -    fd = None -    tty = None -    try: -        # Always try reading and writing directly on the tty first. -        fd = os.open('/dev/tty', os.O_RDWR|os.O_NOCTTY) -        tty = os.fdopen(fd, 'w+', 1) -        input = tty -        if not stream: -            stream = tty -    except EnvironmentError as e: -        # If that fails, see if stdin can be controlled. +    passwd = None +    with contextlib.ExitStack() as stack:          try: -            fd = sys.stdin.fileno() -        except (AttributeError, ValueError): -            passwd = fallback_getpass(prompt, stream) -        input = sys.stdin -        if not stream: -            stream = sys.stderr - -    if fd is not None: -        passwd = None -        try: -            old = termios.tcgetattr(fd)     # a copy to save -            new = old[:] -            new[3] &= ~termios.ECHO  # 3 == 'lflags' -            tcsetattr_flags = termios.TCSAFLUSH -            if hasattr(termios, 'TCSASOFT'): -                tcsetattr_flags |= termios.TCSASOFT +            # Always try reading and writing directly on the tty first. +            fd = os.open('/dev/tty', os.O_RDWR|os.O_NOCTTY) +            tty = io.FileIO(fd, 'w+') +            stack.enter_context(tty) +            input = io.TextIOWrapper(tty) +            stack.enter_context(input) +            if not stream: +                stream = input +        except OSError as e: +            # If that fails, see if stdin can be controlled. +            stack.close() +            try: +                fd = sys.stdin.fileno() +            except (AttributeError, ValueError): +                fd = None +                passwd = fallback_getpass(prompt, stream) +            input = sys.stdin +            if not stream: +                stream = sys.stderr + +        if fd is not None:              try: -                termios.tcsetattr(fd, tcsetattr_flags, new) -                passwd = _raw_input(prompt, stream, input=input) -            finally: -                termios.tcsetattr(fd, tcsetattr_flags, old) -                stream.flush()  # issue7208 -        except termios.error: -            if passwd is not None: -                # _raw_input succeeded.  The final tcsetattr failed.  Reraise -                # instead of leaving the terminal in an unknown state. -                raise -            # We can't control the tty or stdin.  Give up and use normal IO. -            # fallback_getpass() raises an appropriate warning. -            del input, tty  # clean up unused file objects before blocking -            passwd = fallback_getpass(prompt, stream) - -    stream.write('\n') -    return passwd +                old = termios.tcgetattr(fd)     # a copy to save +                new = old[:] +                new[3] &= ~termios.ECHO  # 3 == 'lflags' +                tcsetattr_flags = termios.TCSAFLUSH +                if hasattr(termios, 'TCSASOFT'): +                    tcsetattr_flags |= termios.TCSASOFT +                try: +                    termios.tcsetattr(fd, tcsetattr_flags, new) +                    passwd = _raw_input(prompt, stream, input=input) +                finally: +                    termios.tcsetattr(fd, tcsetattr_flags, old) +                    stream.flush()  # issue7208 +            except termios.error: +                if passwd is not None: +                    # _raw_input succeeded.  The final tcsetattr failed.  Reraise +                    # instead of leaving the terminal in an unknown state. +                    raise +                # We can't control the tty or stdin.  Give up and use normal IO. +                # fallback_getpass() raises an appropriate warning. +                if stream is not input: +                    # clean up unused file objects before blocking +                    stack.close() +                passwd = fallback_getpass(prompt, stream) + +        stream.write('\n') +        return passwd  def win_getpass(prompt='Password: ', stream=None):  | 
