| # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. |
| import atexit |
| import contextlib |
| import sys |
| |
| from .ansitowin32 import AnsiToWin32 |
| |
| |
| def _wipe_internal_state_for_tests(): |
| global orig_stdout, orig_stderr |
| orig_stdout = None |
| orig_stderr = None |
| |
| global wrapped_stdout, wrapped_stderr |
| wrapped_stdout = None |
| wrapped_stderr = None |
| |
| global atexit_done |
| atexit_done = False |
| |
| global fixed_windows_console |
| fixed_windows_console = False |
| |
| try: |
| # no-op if it wasn't registered |
| atexit.unregister(reset_all) |
| except AttributeError: |
| # python 2: no atexit.unregister. Oh well, we did our best. |
| pass |
| |
| |
| def reset_all(): |
| if AnsiToWin32 is not None: # Issue #74: objects might become None at exit |
| AnsiToWin32(orig_stdout).reset_all() |
| |
| |
| def init(autoreset=False, convert=None, strip=None, wrap=True): |
| |
| if not wrap and any([autoreset, convert, strip]): |
| raise ValueError('wrap=False conflicts with any other arg=True') |
| |
| global wrapped_stdout, wrapped_stderr |
| global orig_stdout, orig_stderr |
| |
| orig_stdout = sys.stdout |
| orig_stderr = sys.stderr |
| |
| if sys.stdout is None: |
| wrapped_stdout = None |
| else: |
| sys.stdout = wrapped_stdout = \ |
| wrap_stream(orig_stdout, convert, strip, autoreset, wrap) |
| if sys.stderr is None: |
| wrapped_stderr = None |
| else: |
| sys.stderr = wrapped_stderr = \ |
| wrap_stream(orig_stderr, convert, strip, autoreset, wrap) |
| |
| global atexit_done |
| if not atexit_done: |
| atexit.register(reset_all) |
| atexit_done = True |
| |
| |
| def deinit(): |
| if orig_stdout is not None: |
| sys.stdout = orig_stdout |
| if orig_stderr is not None: |
| sys.stderr = orig_stderr |
| |
| |
| def just_fix_windows_console(): |
| global fixed_windows_console |
| |
| if sys.platform != "win32": |
| return |
| if fixed_windows_console: |
| return |
| if wrapped_stdout is not None or wrapped_stderr is not None: |
| # Someone already ran init() and it did stuff, so we won't second-guess them |
| return |
| |
| # On newer versions of Windows, AnsiToWin32.__init__ will implicitly enable the |
| # native ANSI support in the console as a side-effect. We only need to actually |
| # replace sys.stdout/stderr if we're in the old-style conversion mode. |
| new_stdout = AnsiToWin32(sys.stdout, convert=None, strip=None, autoreset=False) |
| if new_stdout.convert: |
| sys.stdout = new_stdout |
| new_stderr = AnsiToWin32(sys.stderr, convert=None, strip=None, autoreset=False) |
| if new_stderr.convert: |
| sys.stderr = new_stderr |
| |
| fixed_windows_console = True |
| |
| @contextlib.contextmanager |
| def colorama_text(*args, **kwargs): |
| init(*args, **kwargs) |
| try: |
| yield |
| finally: |
| deinit() |
| |
| |
| def reinit(): |
| if wrapped_stdout is not None: |
| sys.stdout = wrapped_stdout |
| if wrapped_stderr is not None: |
| sys.stderr = wrapped_stderr |
| |
| |
| def wrap_stream(stream, convert, strip, autoreset, wrap): |
| if wrap: |
| wrapper = AnsiToWin32(stream, |
| convert=convert, strip=strip, autoreset=autoreset) |
| if wrapper.should_wrap(): |
| stream = wrapper.stream |
| return stream |
| |
| |
| # Use this for initial setup as well, to reduce code duplication |
| _wipe_internal_state_for_tests() |