Opened 5 years ago

Closed 18 months ago

#13476 closed New feature (fixed)

Enable colors on Windows if pyreadline is installed.

Reported by: buriy Owned by: buriy
Component: Core (Management commands) Version: master
Severity: Normal Keywords: windows console colors
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: yes
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description

Python module pyreadline makes possible ansi color handling for windows.

Attachments (2)

13476-concept.patch (1.1 KB) - added by buriy 5 years ago.
I attached a patch to prove it's working. Though, accurate patch should not attempt to mangle sys.stdout and sys.stderr but add everywhere a variable pointing to the right console handle instead.
13476-better.patch (1.6 KB) - added by buriy 5 years ago.
Better patch

Download all attachments as: .zip

Change History (15)

Changed 5 years ago by buriy

I attached a patch to prove it's working. Though, accurate patch should not attempt to mangle sys.stdout and sys.stderr but add everywhere a variable pointing to the right console handle instead.

comment:1 Changed 5 years ago by buriy

  • Needs documentation set
  • Needs tests unset
  • Patch needs improvement set
  • Summary changed from Enable colors in win32 if pyreadline is installed. to Enable colors on Windows if pyreadline is installed.

Patch clearly needs improvement.
Also ticket needs documentation note(s) to mention that users need to install pyreadline to enable console colors.

comment:2 follow-up: Changed 5 years ago by russellm

  • Triage Stage changed from Unreviewed to Accepted

No problem with the broader idea of allowing color terminal support for Windows. However, it's going to need to be a clean implementation. If Windows has a problem with ANSI color codes, I'm more inclined to accept this as a limitation of the platform than I am to accept a messy munging of stdout/stderr handling.

Changed 5 years ago by buriy

Better patch

comment:3 in reply to: ↑ 2 Changed 5 years ago by buriy

  • Owner changed from nobody to buriy
  • Status changed from new to assigned

I fixed a bug that pipeline redirection didn't work on Windows after applying patch. Now it's 100% good patch.

Replying to russellm:

No problem with the broader idea of allowing color terminal support for Windows. However, it's going to need to be a clean implementation. If Windows has a problem with ANSI color codes, I'm more inclined to accept this as a limitation of the platform than I am to accept a messy munging of stdout/stderr handling.

I thought a bit more. Regarding a "clean implementation".

ANSI colors were never a part of Windows, and IPython use PyReadline for this -- and IMHO we can't do anything better than use PyReadline.
PyReadline use ctypes and creates windows Console using native function calls.

So we have 5 ways:

  1. Substitute stdout with one from PyReadline and use ANSI colors.
  2. Use windows console output commands for Windows, not ANSI. We won't be able to use strings with color information at all.
  3. Use not sys.stdout but our own console, accessible from some get_console() or BaseCommand.console property.

This would work, but amount of changes would be large, and backwards compatibility for user commands is not guaranteed.
In fact, IPython does exactly this: it stores its own console handler, since "import sys; sys.stdout" gives you unpatched version.

  1. Both (3) and reimplement the pyreadline code.
  2. Screw that Windows. If you use Windows, you're loser, Django will never be that perfect on Windows. (This is my brain translation of "accept this as a limitation of a platform")

The code itself is quite large to be included in Django: http://bazaar.launchpad.net/~pyreadline/pyreadline/1.5/files/head:/pyreadline/console/ ,
so IMHO (3) is better than (4).

But I think the approach (1) is better than (3):

  • Django plugins creators can use colors, and be sure colors will work on windows platform (not sure for PocketPC, it has to work since console works the same there, but I was unable to google any proof).
  • It doesn't require to use console variable, so one can continue to use print ... and sys.stdout.write calls.
  • Only windows users' console will be replaced, so they'll get an "ANSI console" emulation.
  • Console is patched only when color_style() is called.
  • Old sys.stdout is saved at console_stdout, and sys.stderr in console_stderr,
  • Console is patched only once, determined by "type(sys.stdout) is file and sys.stdout.isatty()" line.
  • The only check that won't work is type(sys.stdout) is not a 'file' any more, but pyreadline.console.Console. I don't know why they did so. But a) this was not a part of Django public contract, and b) nobody should check this -- file contract is that it has .write() method

However someone should write in a documentation, that in attempt to make console work in Windows, we replace it with pyreadline.console.Console, and so one can use full ANSI output, and if they don't want -- one can just replace console with their class before us or after us, we patch console once and only if it's not patched yet.

Maybe it is also a good idea to ask people to patch their console manually if they want colors.
They just need to insert 20 lines of code in their settings.py (or maybe .pythonrc ? -- i'm not sure on this), and it will work.
Or I can pack those 20 lines into a library that will do that hack on import.
Call it "ansi-colors-on-windows" and add to pypi. Django will stay clean then. Probably docs proposing usage of this package should be written anyway -- colors are valuable addition for runserver, different sql outputs -- well, you know.

comment:4 Changed 5 years ago by Alex

FWIW there's no need to backup sys.stdout and sys.stderr is that way, they're made available as sys.__stdout__ and sys.__stderr__

comment:5 Changed 4 years ago by gabrielhurley

  • Component changed from django-admin.py runserver to Core (Management commands)

comment:6 Changed 4 years ago by julien

  • Severity set to Normal
  • Type set to New feature

comment:7 Changed 4 years ago by jacob

  • milestone 1.3 deleted

Milestone 1.3 deleted

comment:11 Changed 3 years ago by aaugustin

  • UI/UX unset

Change UI/UX from NULL to False.

comment:12 Changed 3 years ago by aaugustin

  • Easy pickings unset

Change Easy pickings from NULL to False.

comment:13 follow-up: Changed 19 months ago by ramiro

IMHO we should try hard to not keep adding code to Django that deals with platforms limitations/particularities.

Contributor buriy has done a good work enumerating the options in comment:3. Other options available are:

  1. Use the colorama lib (https://pypi.python.org/pypi/colorama)
  2. Rely on the user having installed the ANSICON external app (http://adoxa.hostmyway.net/ansicon/). The code modification is essentially a one-liner:
diff --git a/django/core/management/color.py b/django/core/management/color.py
index 20e31ff..4276c7d 100644
--- a/django/core/management/color.py
+++ b/django/core/management/color.py
@@ -13,10 +13,11 @@ def supports_color():
     Returns True if the running system's terminal supports color, and False
     otherwise.
     """
-    unsupported_platform = (sys.platform in ('win32', 'Pocket PC'))
+    plat = sys.platform
+    supported_platform = plat != 'Pocket PC' and (plat != 'win32' or 'ANSICON' in os.environ)
     # isatty is not always implemented, #6223.
     is_a_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()
-    if unsupported_platform or not is_a_tty:
+    if not supported_platform or not is_a_tty:
         return False
     return True

Googling shows there are other open source projects that have chosen this path (Cucumber, RSpec).

6, just like the options that involve dependency on pyreadline, imply adding a soft third party Python module dependency and/or code to deal with the issue.

I'm ready to either simply close this ticket or to commit the above patch.

Last edited 19 months ago by ramiro (previous) (diff)

comment:14 in reply to: ↑ 13 Changed 19 months ago by ramiro

Replying to ramiro:

IMHO we should try hard to not keep adding code to Django that deals with platforms limitations/particularities.

I meant: Try hard to not keep adding code to Django that deals with platforms limitations/particularities for non essential functionality like e.g. the dev server and its reloading mechanism and this one: management commands color output.

Last edited 19 months ago by ramiro (previous) (diff)

comment:15 Changed 19 months ago by claudep

+1 for your proposal (7), with docs of course.

Last edited 19 months ago by claudep (previous) (diff)

comment:16 Changed 18 months ago by Ramiro Morales <cramm0@…>

  • Resolution set to fixed
  • Status changed from assigned to closed

In 12615dab78cb6fc7d8c74b7b65a4136b0feeb33f:

Fixed #13476 -- Added support for color in console output under Windows.

Detect and use the services of the ANSICON third-party tool if it's
available.

Note: See TracTickets for help on using tickets.
Back to Top