Skip to content

Commit

Permalink
Fixed colorized output on Windows with Python 3.
Browse files Browse the repository at this point in the history
Closes #87.
  • Loading branch information
jkbrzt committed Aug 17, 2012
1 parent 86256af commit 4660da9
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 20 deletions.
2 changes: 2 additions & 0 deletions README.rst
Expand Up @@ -957,6 +957,8 @@ Changelog
*You can click a version name to see a diff with the previous one.*
* `0.2.8dev`_
* Fixed colorized output on Windows with Python 3.
* Fixed installation on Windows with Python 3.
* CRLF HTTP header field separation in the output.
* Added exit status code ``2`` for timed-out requests.
* Added ``--colors`` and ``--format`` in addition to ``--pretty``, to
Expand Down
30 changes: 18 additions & 12 deletions httpie/core.py
Expand Up @@ -10,22 +10,21 @@
5. Exit.
"""
from _socket import gaierror
import sys
import json
import errno
from pprint import pformat

import requests
import requests.auth
from requests.compat import str
from requests.compat import str, is_py3
from httpie import __version__ as httpie_version
from requests import __version__ as requests_version
from pygments import __version__ as pygments_version

from .cli import parser
from .models import Environment
from .output import output_stream, write
from .output import output_stream, write, write_with_colors_win_p3k
from . import EXIT


Expand Down Expand Up @@ -115,19 +114,20 @@ def error(msg, *args):
status = EXIT.OK

if debug:
sys.stderr.write('HTTPie version: %s\n' % httpie_version)
sys.stderr.write('Requests version: %s\n' % requests_version)
sys.stderr.write('Pygments version: %s\n' % pygments_version)
sys.stderr.write('HTTPie %s\n' % httpie_version)
sys.stderr.write('Requests %s\n' % requests_version)
sys.stderr.write('Pygments %s\n' % pygments_version)
sys.stderr.write('Python %s %s\n' % (sys.version, sys.platform))

try:
args = parser.parse_args(args=args, env=env)
kwargs = get_requests_kwargs(args)
requests_kwargs = get_requests_kwargs(args)

if args.debug:
sys.stderr.write(
'\n>>> requests.request(%s)\n\n' % pformat(kwargs))
'\n>>> requests.request(%s)\n\n' % pformat(requests_kwargs))

response = requests.request(**kwargs)
response = requests.request(**requests_kwargs)

if args.check_status:
status = get_exist_status(response.status_code,
Expand All @@ -137,10 +137,16 @@ def error(msg, *args):

stream = output_stream(args, env, response.request, response)

write_kwargs = {
'stream': stream,
'outfile': env.stdout,
'flush': env.stdout_isatty or args.stream
}
try:
write(stream=stream,
outfile=env.stdout,
flush=env.stdout_isatty or args.stream)
if env.is_windows and is_py3 and 'colors' in args.prettify:
write_with_colors_win_p3k(**write_kwargs)
else:
write(**write_kwargs)

except IOError as e:
if not traceback and e.errno == errno.EPIPE:
Expand Down
12 changes: 7 additions & 5 deletions httpie/models.py
Expand Up @@ -18,14 +18,16 @@ class Environment(object):
if progname not in ['http', 'https']:
progname = 'http'

if is_windows:
import colorama.initialise
colorama.initialise.init()

stdin_isatty = sys.stdin.isatty()
stdin = sys.stdin
stdout_isatty = sys.stdout.isatty()
stdout = sys.stdout

if stdout_isatty and is_windows:
from colorama.initialise import wrap_stream
stdout = wrap_stream(sys.stdout, convert=None,
strip=None, autoreset=True, wrap=True)
else:
stdout = sys.stdout
stderr = sys.stderr

# Can be set to 0 to disable colors completely.
Expand Down
17 changes: 17 additions & 0 deletions httpie/output.py
Expand Up @@ -61,6 +61,23 @@ def write(stream, outfile, flush):
outfile.flush()


def write_with_colors_win_p3k(stream, outfile, flush):
"""Like `write`, but colorized chunks are written as text
directly to `outfile` to ensure it gets processed by colorama.
Applies only to Windows with Python 3 and colorized terminal output.
"""
color = b'\x1b['
encoding = outfile.encoding
for chunk in stream:
if color in chunk:
outfile.write(chunk.decode(encoding))
else:
outfile.buffer.write(chunk)
if flush:
outfile.flush()


def output_stream(args, env, request, response):
"""Build and return a chain of iterators over the `request`-`response`
exchange each of which yields `bytes` chunks.
Expand Down
15 changes: 12 additions & 3 deletions tests/tests.py
Expand Up @@ -33,9 +33,9 @@
except ImportError:
from urllib2 import urlopen
try:
from unittest import skipIf
from unittest import skipIf, skip
except ImportError:

skip = lambda msg: lambda self: None
def skipIf(cond, reason):
def decorator(test_method):
if cond:
Expand All @@ -47,7 +47,6 @@ def decorator(test_method):
from requests.compat import is_windows, is_py26, bytes, str



#################################################################
# Utils/setup
#################################################################
Expand Down Expand Up @@ -863,6 +862,7 @@ def test_error_response_exits_0_without_check_status(self):
self.assertEqual(r.exit_status, EXIT.OK)
self.assertTrue(not r.stderr)

@skip('httpbin.org always returns 500')
def test_timeout_exit_status(self):
r = http(
'--timeout=0.5',
Expand Down Expand Up @@ -917,6 +917,15 @@ def test_5xx_check_status_exits_5(self):
self.assertEqual(r.exit_status, EXIT.ERROR_HTTP_5XX)


class WindowsOnlyTests(BaseTestCase):

@skip('FIXME: kills the runner')
#@skipIf(not is_windows, 'windows-only')
def test_windows_colorized_output(self):
# Spits out the colorized output.
http(httpbin('/get'), env=Environment())


class FakeWindowsTest(BaseTestCase):

def test_stdout_redirect_not_supported_on_windows(self):
Expand Down

5 comments on commit 4660da9

@shanselman
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I "http PUT httpbin.org/put hello=world" I'm only seeing yellow color on "1.1 200" as in "HTTP/1.1 200 OK" and everything else is the default color.

@jkbrzt
Copy link
Member Author

@jkbrzt jkbrzt commented on 4660da9 Aug 17, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What Windows version and terminal emulator do you use?

You can try to play with different values for the --style option to see which one gives the best result. I've tested it on Windows 7 with PowerShell and the best style seemed to be fruity so I made it default for Windows, but maybe there is a better one.

Cheers for all the feedback!

@shanselman
Copy link

@shanselman shanselman commented on 4660da9 Aug 17, 2012 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shanselman
Copy link

@shanselman shanselman commented on 4660da9 Aug 17, 2012 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jkbrzt
Copy link
Member Author

@jkbrzt jkbrzt commented on 4660da9 Aug 18, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 149cbc1. Solarized isn't very Windows-friendly though.

I've now tested the default Windows style fruity with cmd.exe and it provides the same result as PowerShell for me:

HTTPie colors in cmd.exe

I'm quite not sure why it doesn't work in your environment.

Please sign in to comment.