-
-
Notifications
You must be signed in to change notification settings - Fork 255
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Yet another attempt at supporting Windows 10's ANSI/VT console #139
Conversation
This is working for me on Windows 10. Python 3.6.2 |
Works fine for me on Windows 10 and Windows 10 insider build. Python 3.6 and Python 3.6.2 |
Works fine for me on Windows 10 Pro Fall update with python 3.6.2 ! :D |
While this works, both powershell and cmd crash after exiting one of my test programs. I'm utilizing the alternate screen which may be the cause. Try with this test code: from colorama import init, Fore, Back, Style
init()
print '\x1b[?1049h' # Alternate screen
print Fore.RED + Style.BRIGHT + '\x1b[4m\x1b[3mSome Text' # Underline + Bright + Italic
raw_input(Style.RESET_ALL + 'Press Enter')
print '\x1b[?1049l' # Exit alternate screen You may have to try to use powershell/cmd after the program exits to see the crash. I'm running on windows 10 pro version 1703 build 15063.674 Edit: I should note that I'm running this with python 2.7.11 |
@Eeems I think you just stumbled upon a bug in Windows 10's VT emulation, this will trigger the crash without colorama (Only Pywin32): import sys
import win32console
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
conout = win32console.GetStdHandle(win32console.STD_OUTPUT_HANDLE)
conout.SetConsoleMode(conout.GetConsoleMode() | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
print '\x1b[?1049h' # Alternate screen
print '\x1b[31m\x1b[1m\x1b[4m\x1b[3mSome Text' # Underline + Bright + Italic
raw_input('\x1b[0mPress Enter')
print '\x1b[?1049l' # Exit alternate screen I can't seem to find this using Google. Probably want to report this to Microsoft... somewhere... |
@segevfiner well great. Who knows how long before that is fixed. I'll poke around as to where I can report it tomorrow and update this with a reference number if I get one. Best I could find for a place to report these kind of things was the feedback hub. Here is the issue: https://aka.ms/Txnt6p |
I believe this bug you are encountering is the same one referenced here: It looks like a fix is being worked on. |
Thanks @tleonhardt |
@tleonhardt Looks like it's been shipped with 1809 |
VT100 control sequences are supported in cmd and PowerShell starting from Windows 10 Anniversary Update, but only if the ENABLE_VIRTUAL_TERMINAL_PROCESSING flag is set on the screen buffer handle using SetConsoleMode. Setting this flag does not seem to negatively affect third party terminal emulators with native ANSI support such as ConEmu, so hopefully there's no regression. References: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences https://docs.microsoft.com/en-us/windows/console/setconsolemode Credits: jarun#275 tartley/colorama#139
VT100 control sequences are supported in cmd and PowerShell starting from Windows 10 Anniversary Update, but only if the ENABLE_VIRTUAL_TERMINAL_PROCESSING flag is set on the screen buffer handle using SetConsoleMode. Setting this flag does not seem to negatively affect third party terminal emulators with native ANSI support such as ConEmu, so hopefully there's no regression. References: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences https://docs.microsoft.com/en-us/windows/console/setconsolemode Credits: jarun#275 tartley/colorama#139
Hey. FYI, yesterday I created a PR to test releases before we push them to PyPI. When that is merged, I'll be more confident about resuming merges and releases. I'll try to look at this PR soon. Thank you for creating it! |
Works for me, too. How can I help to get this PR merged? |
This looks superb, and I'd love to get it merged imminently for a forthcoming release. Unfortunately right now I can't merge it because it contains a bunch of code changes but no corresponding test changes. How would future contributors find out if their changes break your code? If nobody else steps up, I'll take a look at fixing the conflicts and adding tests for this change in the next few days. If I don't get to it, then it might not make it into the very next release, but I hope to pick up doing them more regularly going forward... Apolologies for ignoring this for years. Thank you for your graceful patience. |
5ee0651
to
7d3d3b9
Compare
@tartley I recently ran into this on a work project where we were setting up the windows console correctly to process our ansi escapes, but then a third-party dependency pulled in So.... is there any way I can help? I am, sadly, pretty familiar with the annoying details of Win32 (sample code; would you trust me to take over reviewing this, so you don't have to? For what it's worth:
|
@njsmith Hi, I am in awe of your stellar work, many thanks for your attention. What you say makes sense to me. I'm happy to defer to your judgement about atexit handling. Seems reasonable. I'm not opposed to the more end-to-end test you describe if you think it's worth it, but if memory serves we use shallow mock/unit tests everywhere else in Colorama, so I'd be happy with that. In my mind this is the significant fix that should drive the next release, and anything else merged before then will also go along for the ride. |
@njsmith Invite in your inbox |
Edits by maintainers is enabled for this PR in case you want to change something by yourself to drive this to be merged, rather than asking me to do so. I think PowerShell also enables VT handling, but it takes care to disable it before launching subprocesses so that they have to enable it by themselves. It might be a good idea to see how other libraries/tools that make use of this handle this correctly, as in, should we bother resetting it. |
Ah-ha, you're right. I wrote a little test script, that checks whether ANSI is enabled, and then unconditionally enables it: https://gist.github.com/njsmith/9cf1e9929947c6b7bb0ab330323beef4 When run from Powershell, it reports that ANSI is initially not enabled... but if I run it as a background job, so it and Powershell are running at the same time, then it reports that ANSI is initially enabled: So that confirms that Powershell enables ANSI while it's running, but disables it before running a child process. Furthermore, it always resets the state after a child process exits, no matter what state the child process left things in. You can see here that if we run the program multiple times, it always starts with a "clean slate", even though the previous invocation left the console in ANSI mode: I also tested under regular cmd.exe, and it turns out I misunderstood: I actually get the same results as with powershell. The reason I thought cmd.exe set it unconditionally is that if you do Finally, all the above tests were with the standard built-in console. I also installed Microsoft's newer/fancier terminal app through the Windows store. When using this terminal, it looks like ANSI escapes are unconditionally enabled by default: So, to sum up:
There are more complicated cases too, like if you have multiple programs running simultaneously in the same console. But in that case trying to reset the state is actually dangerous -- we might pull the rug out from underneath some other program, by disabling ANSI while the other program is still using it. Also, we can't 100% reliably reset the state anyway (there's no guarantee that And finally, the worst case outcome here is... some program accidentally gets ANSI support where it wasn't expecting it. But who cares – are there really programs out there that are intentionally emitting ANSI escapes at the console and relying on them not being interpreted and rendering weird control character garbage instead? Seems very unlikely. And they're already broken by MS's own Terminal app. So given all that, I'm pretty comfortable with simplifying this PR by dropping the |
Finally looping back around to this... I just pushed some fixes/cleanups to this PR branch. Changes:
I also tested this manually on Windows 10 (native ansi console), Windows 10 (jupyter notebook, so no console), Windows 7 (classic console, w/o native ansi), and Linux, and verified that it was taking the code paths I expected in each case. So hopefully that should have caught any egregious errors when touching real devices, even if we don't have automated tests for them... |
Oh shoot, test failures on py2 because of missing |
Ok, CI green! @segevfiner, @tartley any comments?
I would like to sneak one more feature in if I can: a more stripped-down version of |
Acknowledged. Thank you. Sounds great!. I'll check it out in a few hours... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great to me. Thanks to everyone who has contributed time, bug reports, knowledge and code along the way.
@njsmith I'm happy to await your "stripped down init()" new feature. That sounds like a very sensible idea, and as you've seen, things don't move quickly here so there is no rush. |
@njsmith Having a quick look through existing issues and PRs, obviously there are some well-known problems with the existing init() (apologies! When I wrote this I thought it was a one-off script to make my tests display a nice green "OK" at the end) An alternative version of 'init' might be able to easily avoid repeating these mistakes: Obviously I don't want to over-complicate your task. If these are trivially easy to accommodate, then great, but don't stress otherwise.
|
We have a release candidate on PyPI containing this PR. Thank you for your contributions! https://pypi.org/project/colorama/0.4.6rc1/ If nobody spots any problems with it, I'll push the final 0.4.6 tomorrow. |
0.4.6 Current release * tartley/colorama#139 Add alternative to 'init()', called 'just_fix_windows_console'. This fixes many longstanding problems with 'init', such as working incorrectly on modern Windows terminals, and wonkiness when init gets called multiple times. The intention is that it just makes all Windows terminals treat ANSI the same way as other terminals do. Many thanks the njsmith for fixing our messes. * tartley/colorama#352 Support Windows 10's ANSI/VT console. This didn't exist when Colorama was created, and avoiding us causing havok there is long overdue. Thanks to segeviner for the initial approach, and to njsmith for getting it merged. * tartley/colorama#338 Internal overhaul of package metadata declaration, which abolishes our use of the now heavily discouraged setuptools (and hence setup.py, setup.cfg and MANIFEST.in), in favor of hatchling (and hence pyproject.toml), generously contributed by ofek (author of hatchling). This includes dropping support Python3.5 and 3.6, which are EOL, and were already dropped from setuptools, so this should not affect our users. * tartley/colorama#353 Attention to detail award to LqdBcnAtWork for a spelling fix in demo06
This time I'm properly using ENABLE_VIRTUAL_TERMINAL_PROCESSING which is what really controls this. I enable it when first needed and disable it on
atexit
. Also, instead of checking for Windows versions, I check that enablingENABLE_VIRTUAL_TERMINAL_PROCESSING
works (Probably needs additional testing to make sure this doesn't unexpectedly break).One obvious benefit is that Windows 10, since the creators update, also implements 256-bit color and 24-color escapes. But there definitely may be many more codes which are supported by Windows but not by colorama.
Note that cmd has some weird behavior with this flag. It enables it when it runs, disables it when it invokes a program, and doesn't disable it when it exits. This might make you think it only works in PowerShell, which simply enables it and leaves it on (This behavior may of course change in future Windows versions).
Should be reviewed
AnsiToWin32
since I remember some Python libraries that use it directly and completely bypassinit
(For example py (Used by pytest) and click)._atexit_registered
once it's called fromatexit
, so that in case some code re-enables this duringatexit
, we will re-register the callback so it will be called again to cleanup.strip
/convert
, they are so easy to get wrong. Please check and double check me.Example
Previous/Other Attempts
#133
#105