Skip to content

Commit 065e221

Browse files
committed
Fixes issue gregmalcolm#72 - Update to Colorama 0.2.7
This fixes random crashes on Windows. See the issue for more details.
1 parent 574550a commit 065e221

File tree

12 files changed

+386
-140
lines changed

12 files changed

+386
-140
lines changed

python2/libs/colorama/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
from .initialise import init
1+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
2+
from .initialise import init, deinit, reinit
23
from .ansi import Fore, Back, Style
34
from .ansitowin32 import AnsiToWin32
45

5-
VERSION = '0.1.18'
6+
VERSION = '0.2.7'
67

python2/libs/colorama/ansi.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
12
'''
23
This module generates ANSI character codes to printing colors to terminals.
34
See: http://en.wikipedia.org/wiki/ANSI_escape_code

python2/libs/colorama/ansitowin32.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
1+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
22
import re
33
import sys
44

@@ -123,7 +123,7 @@ def write(self, text):
123123
def reset_all(self):
124124
if self.convert:
125125
self.call_win32('m', (0,))
126-
else:
126+
elif is_a_tty(self.wrapped):
127127
self.wrapped.write(Style.RESET_ALL)
128128

129129

@@ -173,4 +173,17 @@ def call_win32(self, command, params):
173173
args = func_args[1:]
174174
kwargs = dict(on_stderr=self.on_stderr)
175175
func(*args, **kwargs)
176+
elif command in ('H', 'f'): # set cursor position
177+
func = winterm.set_cursor_position
178+
func(params, on_stderr=self.on_stderr)
179+
elif command in ('J'):
180+
func = winterm.erase_data
181+
func(params, on_stderr=self.on_stderr)
182+
elif command == 'A':
183+
if params == () or params == None:
184+
num_rows = 1
185+
else:
186+
num_rows = params[0]
187+
func = winterm.cursor_up
188+
func(num_rows, on_stderr=self.on_stderr)
176189

python2/libs/colorama/initialise.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
12
import atexit
23
import sys
34

@@ -7,6 +8,9 @@
78
orig_stdout = sys.stdout
89
orig_stderr = sys.stderr
910

11+
wrapped_stdout = sys.stdout
12+
wrapped_stderr = sys.stderr
13+
1014
atexit_done = False
1115

1216

@@ -16,18 +20,31 @@ def reset_all():
1620

1721
def init(autoreset=False, convert=None, strip=None, wrap=True):
1822

19-
if wrap==False and (autoreset==True or convert==True or strip==True):
23+
if not wrap and any([autoreset, convert, strip]):
2024
raise ValueError('wrap=False conflicts with any other arg=True')
2125

22-
sys.stdout = wrap_stream(orig_stdout, convert, strip, autoreset, wrap)
23-
sys.stderr = wrap_stream(orig_stderr, convert, strip, autoreset, wrap)
26+
global wrapped_stdout, wrapped_stderr
27+
sys.stdout = wrapped_stdout = \
28+
wrap_stream(orig_stdout, convert, strip, autoreset, wrap)
29+
sys.stderr = wrapped_stderr = \
30+
wrap_stream(orig_stderr, convert, strip, autoreset, wrap)
2431

2532
global atexit_done
2633
if not atexit_done:
2734
atexit.register(reset_all)
2835
atexit_done = True
2936

3037

38+
def deinit():
39+
sys.stdout = orig_stdout
40+
sys.stderr = orig_stderr
41+
42+
43+
def reinit():
44+
sys.stdout = wrapped_stdout
45+
sys.stderr = wrapped_stdout
46+
47+
3148
def wrap_stream(stream, convert, strip, autoreset, wrap):
3249
if wrap:
3350
wrapper = AnsiToWin32(stream,
@@ -36,3 +53,4 @@ def wrap_stream(stream, convert, strip, autoreset, wrap):
3653
stream = wrapper.stream
3754
return stream
3855

56+

python2/libs/colorama/win32.py

Lines changed: 99 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,134 @@
1+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
12

23
# from winbase.h
34
STDOUT = -11
45
STDERR = -12
56

67
try:
78
from ctypes import windll
9+
from ctypes import wintypes
810
except ImportError:
911
windll = None
1012
SetConsoleTextAttribute = lambda *_: None
1113
else:
1214
from ctypes import (
13-
byref, Structure, c_char, c_short, c_uint32, c_ushort
15+
byref, Structure, c_char, c_short, c_uint32, c_ushort, POINTER
1416
)
1517

16-
handles = {
17-
STDOUT: windll.kernel32.GetStdHandle(STDOUT),
18-
STDERR: windll.kernel32.GetStdHandle(STDERR),
19-
}
20-
21-
SHORT = c_short
22-
WORD = c_ushort
23-
DWORD = c_uint32
24-
TCHAR = c_char
25-
26-
class COORD(Structure):
27-
"""struct in wincon.h"""
28-
_fields_ = [
29-
('X', SHORT),
30-
('Y', SHORT),
31-
]
32-
33-
class SMALL_RECT(Structure):
34-
"""struct in wincon.h."""
35-
_fields_ = [
36-
("Left", SHORT),
37-
("Top", SHORT),
38-
("Right", SHORT),
39-
("Bottom", SHORT),
40-
]
41-
4218
class CONSOLE_SCREEN_BUFFER_INFO(Structure):
4319
"""struct in wincon.h."""
4420
_fields_ = [
45-
("dwSize", COORD),
46-
("dwCursorPosition", COORD),
47-
("wAttributes", WORD),
48-
("srWindow", SMALL_RECT),
49-
("dwMaximumWindowSize", COORD),
21+
("dwSize", wintypes._COORD),
22+
("dwCursorPosition", wintypes._COORD),
23+
("wAttributes", wintypes.WORD),
24+
("srWindow", wintypes.SMALL_RECT),
25+
("dwMaximumWindowSize", wintypes._COORD),
5026
]
27+
def __str__(self):
28+
return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % (
29+
self.dwSize.Y, self.dwSize.X
30+
, self.dwCursorPosition.Y, self.dwCursorPosition.X
31+
, self.wAttributes
32+
, self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right
33+
, self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X
34+
)
35+
36+
_GetStdHandle = windll.kernel32.GetStdHandle
37+
_GetStdHandle.argtypes = [
38+
wintypes.DWORD,
39+
]
40+
_GetStdHandle.restype = wintypes.HANDLE
5141

52-
def GetConsoleScreenBufferInfo(stream_id):
42+
_GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo
43+
_GetConsoleScreenBufferInfo.argtypes = [
44+
wintypes.HANDLE,
45+
POINTER(CONSOLE_SCREEN_BUFFER_INFO),
46+
]
47+
_GetConsoleScreenBufferInfo.restype = wintypes.BOOL
48+
49+
_SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute
50+
_SetConsoleTextAttribute.argtypes = [
51+
wintypes.HANDLE,
52+
wintypes.WORD,
53+
]
54+
_SetConsoleTextAttribute.restype = wintypes.BOOL
55+
56+
_SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition
57+
_SetConsoleCursorPosition.argtypes = [
58+
wintypes.HANDLE,
59+
wintypes._COORD,
60+
]
61+
_SetConsoleCursorPosition.restype = wintypes.BOOL
62+
63+
_FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA
64+
_FillConsoleOutputCharacterA.argtypes = [
65+
wintypes.HANDLE,
66+
c_char,
67+
wintypes.DWORD,
68+
wintypes._COORD,
69+
POINTER(wintypes.DWORD),
70+
]
71+
_FillConsoleOutputCharacterA.restype = wintypes.BOOL
72+
73+
_FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute
74+
_FillConsoleOutputAttribute.argtypes = [
75+
wintypes.HANDLE,
76+
wintypes.WORD,
77+
wintypes.DWORD,
78+
wintypes._COORD,
79+
POINTER(wintypes.DWORD),
80+
]
81+
_FillConsoleOutputAttribute.restype = wintypes.BOOL
82+
83+
handles = {
84+
STDOUT: _GetStdHandle(STDOUT),
85+
STDERR: _GetStdHandle(STDERR),
86+
}
87+
88+
def GetConsoleScreenBufferInfo(stream_id=STDOUT):
5389
handle = handles[stream_id]
5490
csbi = CONSOLE_SCREEN_BUFFER_INFO()
55-
success = windll.kernel32.GetConsoleScreenBufferInfo(
91+
success = _GetConsoleScreenBufferInfo(
5692
handle, byref(csbi))
57-
# This fails when imported via setup.py when installing using 'pip'
58-
# presumably the fix is that running setup.py should not trigger all
59-
# this activity.
60-
# assert success
6193
return csbi
6294

6395
def SetConsoleTextAttribute(stream_id, attrs):
6496
handle = handles[stream_id]
65-
success = windll.kernel32.SetConsoleTextAttribute(handle, attrs)
66-
assert success
97+
return _SetConsoleTextAttribute(handle, attrs)
6798

6899
def SetConsoleCursorPosition(stream_id, position):
100+
position = wintypes._COORD(*position)
101+
# If the position is out of range, do nothing.
102+
if position.Y <= 0 or position.X <= 0:
103+
return
104+
# Adjust for Windows' SetConsoleCursorPosition:
105+
# 1. being 0-based, while ANSI is 1-based.
106+
# 2. expecting (x,y), while ANSI uses (y,x).
107+
adjusted_position = wintypes._COORD(position.Y - 1, position.X - 1)
108+
# Adjust for viewport's scroll position
109+
sr = GetConsoleScreenBufferInfo(STDOUT).srWindow
110+
adjusted_position.Y += sr.Top
111+
adjusted_position.X += sr.Left
112+
# Resume normal processing
69113
handle = handles[stream_id]
70-
position = COORD(*position)
71-
success = windll.kernel32.SetConsoleCursorPosition(handle, position)
72-
assert success
114+
return _SetConsoleCursorPosition(handle, adjusted_position)
73115

74116
def FillConsoleOutputCharacter(stream_id, char, length, start):
75117
handle = handles[stream_id]
76-
char = TCHAR(char)
77-
length = DWORD(length)
78-
start = COORD(*start)
79-
num_written = DWORD(0)
80-
# AttributeError: function 'FillConsoleOutputCharacter' not found
81-
# could it just be that my types are wrong?
82-
success = windll.kernel32.FillConsoleOutputCharacter(
118+
char = c_char(char)
119+
length = wintypes.DWORD(length)
120+
num_written = wintypes.DWORD(0)
121+
# Note that this is hard-coded for ANSI (vs wide) bytes.
122+
success = _FillConsoleOutputCharacterA(
83123
handle, char, length, start, byref(num_written))
84-
assert success
85124
return num_written.value
86125

87-
88-
if __name__=='__main__':
89-
x = GetConsoleScreenBufferInfo(STDOUT)
90-
print(x.dwSize)
91-
print(x.dwCursorPosition)
92-
print(x.wAttributes)
93-
print(x.srWindow)
94-
print(x.dwMaximumWindowSize)
95-
126+
def FillConsoleOutputAttribute(stream_id, attr, length, start):
127+
''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )'''
128+
handle = handles[stream_id]
129+
attribute = wintypes.WORD(attr)
130+
length = wintypes.DWORD(length)
131+
num_written = wintypes.DWORD(0)
132+
# Note that this is hard-coded for ANSI (vs wide) bytes.
133+
return _FillConsoleOutputAttribute(
134+
handle, attribute, length, start, byref(num_written))

python2/libs/colorama/winterm.py

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
1+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
22
from . import win32
33

44

@@ -22,8 +22,7 @@ class WinStyle(object):
2222
class WinTerm(object):
2323

2424
def __init__(self):
25-
self._default = \
26-
win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes
25+
self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes
2726
self.set_attrs(self._default)
2827
self._default_fore = self._fore
2928
self._default_back = self._back
@@ -67,3 +66,55 @@ def set_console(self, attrs=None, on_stderr=False):
6766
handle = win32.STDERR
6867
win32.SetConsoleTextAttribute(handle, attrs)
6968

69+
def get_position(self, handle):
70+
position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition
71+
# Because Windows coordinates are 0-based,
72+
# and win32.SetConsoleCursorPosition expects 1-based.
73+
position.X += 1
74+
position.Y += 1
75+
return position
76+
77+
def set_cursor_position(self, position=None, on_stderr=False):
78+
if position is None:
79+
#I'm not currently tracking the position, so there is no default.
80+
#position = self.get_position()
81+
return
82+
handle = win32.STDOUT
83+
if on_stderr:
84+
handle = win32.STDERR
85+
win32.SetConsoleCursorPosition(handle, position)
86+
87+
def cursor_up(self, num_rows=0, on_stderr=False):
88+
if num_rows == 0:
89+
return
90+
handle = win32.STDOUT
91+
if on_stderr:
92+
handle = win32.STDERR
93+
position = self.get_position(handle)
94+
adjusted_position = (position.Y - num_rows, position.X)
95+
self.set_cursor_position(adjusted_position, on_stderr)
96+
97+
def erase_data(self, mode=0, on_stderr=False):
98+
# 0 (or None) should clear from the cursor to the end of the screen.
99+
# 1 should clear from the cursor to the beginning of the screen.
100+
# 2 should clear the entire screen. (And maybe move cursor to (1,1)?)
101+
#
102+
# At the moment, I only support mode 2. From looking at the API, it
103+
# should be possible to calculate a different number of bytes to clear,
104+
# and to do so relative to the cursor position.
105+
if mode[0] not in (2,):
106+
return
107+
handle = win32.STDOUT
108+
if on_stderr:
109+
handle = win32.STDERR
110+
# here's where we'll home the cursor
111+
coord_screen = win32.COORD(0,0)
112+
csbi = win32.GetConsoleScreenBufferInfo(handle)
113+
# get the number of character cells in the current buffer
114+
dw_con_size = csbi.dwSize.X * csbi.dwSize.Y
115+
# fill the entire screen with blanks
116+
win32.FillConsoleOutputCharacter(handle, ' ', dw_con_size, coord_screen)
117+
# now set the buffer's attributes accordingly
118+
win32.FillConsoleOutputAttribute(handle, self.get_attrs(), dw_con_size, coord_screen );
119+
# put the cursor at (0, 0)
120+
win32.SetConsoleCursorPosition(handle, (coord_screen.X, coord_screen.Y))

python3/libs/colorama/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
from .initialise import init
1+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
2+
from .initialise import init, deinit, reinit
23
from .ansi import Fore, Back, Style
34
from .ansitowin32 import AnsiToWin32
45

5-
VERSION = '0.1.18'
6+
VERSION = '0.2.7'
67

python3/libs/colorama/ansi.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
12
'''
23
This module generates ANSI character codes to printing colors to terminals.
34
See: http://en.wikipedia.org/wiki/ANSI_escape_code

0 commit comments

Comments
 (0)