initialise.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
  2. import atexit
  3. import contextlib
  4. import sys
  5. from .ansitowin32 import AnsiToWin32
  6. def _wipe_internal_state_for_tests():
  7. global orig_stdout, orig_stderr
  8. orig_stdout = None
  9. orig_stderr = None
  10. global wrapped_stdout, wrapped_stderr
  11. wrapped_stdout = None
  12. wrapped_stderr = None
  13. global atexit_done
  14. atexit_done = False
  15. global fixed_windows_console
  16. fixed_windows_console = False
  17. try:
  18. # no-op if it wasn't registered
  19. atexit.unregister(reset_all)
  20. except AttributeError:
  21. # python 2: no atexit.unregister. Oh well, we did our best.
  22. pass
  23. def reset_all():
  24. if AnsiToWin32 is not None: # Issue #74: objects might become None at exit
  25. AnsiToWin32(orig_stdout).reset_all()
  26. def init(autoreset=False, convert=None, strip=None, wrap=True):
  27. if not wrap and any([autoreset, convert, strip]):
  28. raise ValueError('wrap=False conflicts with any other arg=True')
  29. global wrapped_stdout, wrapped_stderr
  30. global orig_stdout, orig_stderr
  31. orig_stdout = sys.stdout
  32. orig_stderr = sys.stderr
  33. if sys.stdout is None:
  34. wrapped_stdout = None
  35. else:
  36. sys.stdout = wrapped_stdout = \
  37. wrap_stream(orig_stdout, convert, strip, autoreset, wrap)
  38. if sys.stderr is None:
  39. wrapped_stderr = None
  40. else:
  41. sys.stderr = wrapped_stderr = \
  42. wrap_stream(orig_stderr, convert, strip, autoreset, wrap)
  43. global atexit_done
  44. if not atexit_done:
  45. atexit.register(reset_all)
  46. atexit_done = True
  47. def deinit():
  48. if orig_stdout is not None:
  49. sys.stdout = orig_stdout
  50. if orig_stderr is not None:
  51. sys.stderr = orig_stderr
  52. def just_fix_windows_console():
  53. global fixed_windows_console
  54. if sys.platform != "win32":
  55. return
  56. if fixed_windows_console:
  57. return
  58. if wrapped_stdout is not None or wrapped_stderr is not None:
  59. # Someone already ran init() and it did stuff, so we won't second-guess them
  60. return
  61. # On newer versions of Windows, AnsiToWin32.__init__ will implicitly enable the
  62. # native ANSI support in the console as a side-effect. We only need to actually
  63. # replace sys.stdout/stderr if we're in the old-style conversion mode.
  64. new_stdout = AnsiToWin32(sys.stdout, convert=None, strip=None, autoreset=False)
  65. if new_stdout.convert:
  66. sys.stdout = new_stdout
  67. new_stderr = AnsiToWin32(sys.stderr, convert=None, strip=None, autoreset=False)
  68. if new_stderr.convert:
  69. sys.stderr = new_stderr
  70. fixed_windows_console = True
  71. @contextlib.contextmanager
  72. def colorama_text(*args, **kwargs):
  73. init(*args, **kwargs)
  74. try:
  75. yield
  76. finally:
  77. deinit()
  78. def reinit():
  79. if wrapped_stdout is not None:
  80. sys.stdout = wrapped_stdout
  81. if wrapped_stderr is not None:
  82. sys.stderr = wrapped_stderr
  83. def wrap_stream(stream, convert, strip, autoreset, wrap):
  84. if wrap:
  85. wrapper = AnsiToWin32(stream,
  86. convert=convert, strip=strip, autoreset=autoreset)
  87. if wrapper.should_wrap():
  88. stream = wrapper.stream
  89. return stream
  90. # Use this for initial setup as well, to reduce code duplication
  91. _wipe_internal_state_for_tests()