Merge ~adam-collard/maas:3.3-colorama-strikes-back into maas:3.3

Proposed by Adam Collard
Status: Merged
Approved by: Adam Collard
Approved revision: 7cea3eb896f76a8cefd2a8fe9b38a271ccb38b07
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~adam-collard/maas:3.3-colorama-strikes-back
Merge into: maas:3.3
Diff against target: 96 lines (+18/-22)
3 files modified
src/maascli/__init__.py (+0/-13)
src/maascli/tests/test_integration.py (+1/-4)
src/maascli/utils.py (+17/-5)
Reviewer Review Type Date Requested Status
Adam Collard (community) Approve
Review via email: mp+434512@code.launchpad.net

Commit message

get original stdout from Colorama

When colorama is present, Django loads it automatically. This module
interferes with the CLI raw output, so we need to get the original
stdout descriptor.

Cherry pick of dc4621928f2d3713dd0c632e98d4ecf1491f5b77

To post a comment you must log in.
Revision history for this message
Adam Collard (adam-collard) wrote :

self-approve backport

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maascli/__init__.py b/src/maascli/__init__.py
2index fc57914..e309b21 100644
3--- a/src/maascli/__init__.py
4+++ b/src/maascli/__init__.py
5@@ -25,25 +25,12 @@ def snap_setup():
6 )
7
8
9-def disable_colorama():
10- """Django pulls Colorama automatically if it's in PYTHONPATH, which
11- interferes with our raw output mode"""
12- try:
13- import colorama
14-
15- colorama.deinit()
16- except (ImportError, OSError):
17- pass
18-
19-
20 def main(argv=sys.argv):
21 # If no arguments have been passed be helpful and point out --help.
22 verbose_errors = "MAAS_CLI_VERBOSE_ERRORS" in os.environ
23
24 snap_setup()
25
26- disable_colorama()
27-
28 parser = prepare_parser(argv)
29
30 try:
31diff --git a/src/maascli/tests/test_integration.py b/src/maascli/tests/test_integration.py
32index 9cef775..4f61d1a 100644
33--- a/src/maascli/tests/test_integration.py
34+++ b/src/maascli/tests/test_integration.py
35@@ -8,7 +8,7 @@ import os.path
36 import random
37 from subprocess import CalledProcessError, check_output, STDOUT
38
39-from maascli import disable_colorama, main
40+from maascli import main
41 from maascli.config import ProfileConfig
42 from maascli.testing.config import make_configs
43 from maascli.utils import handler_command_name
44@@ -74,9 +74,6 @@ class TestMain(MAASTestCase):
45 handler_name = handler_command_name(resource_name)
46 command = "maas", profile_name, handler_name
47
48- # Trying to disable colorama conflicts with the CaptureStandardIO below
49- self.patch(disable_colorama)
50-
51 with CaptureStandardIO() as stdio:
52 error = self.assertRaises(SystemExit, main, command)
53
54diff --git a/src/maascli/utils.py b/src/maascli/utils.py
55index f35e929..f38aa5b 100644
56--- a/src/maascli/utils.py
57+++ b/src/maascli/utils.py
58@@ -150,6 +150,22 @@ def print_response_headers(headers, file=None):
59 print(form % (cap(header), headers[header]), file=file)
60
61
62+def get_orig_stdout(file):
63+ # Get the underlying buffer if we're writing to stdout. This allows us to
64+ # write bytes directly, without attempting to convert the bytes to unicode.
65+ # Unicode output may not be desired; the HTTP response could be raw bytes.
66+ try:
67+ import colorama
68+
69+ if isinstance(file, colorama.ansitowin32.StreamWrapper):
70+ file = colorama.initialise.orig_stdout
71+ except (ImportError, OSError):
72+ pass
73+ if isinstance(file, io.TextIOWrapper):
74+ file = file.buffer
75+ return file
76+
77+
78 def print_response_content(response, content, file=None):
79 """Write the response's content to stdout.
80
81@@ -159,14 +175,10 @@ def print_response_content(response, content, file=None):
82 :param file: a binary stream opened for writing (optional)
83 """
84 file = sys.stdout if file is None else file
85+ file = get_orig_stdout(file)
86 is_tty = file.isatty()
87 success = response.status // 100 == 2
88 is_textual = is_response_textual(response)
89- # Get the underlying buffer if we're writing to stdout. This allows us to
90- # write bytes directly, without attempting to convert the bytes to unicode.
91- # Unicode output may not be desired; the HTTP response could be raw bytes.
92- if isinstance(file, io.TextIOWrapper):
93- file = file.buffer
94 if is_tty and success and is_textual:
95 file.write(b"Success.\n")
96 file.write(b"Machine-readable output follows:\n")

Subscribers

People subscribed via source and target branches