Merge lp:~tfukushima/glance/colorized-log into lp:~glance-coresec/glance/cactus-trunk

Proposed by Taku Fukushima
Status: Merged
Approved by: Jay Pipes
Approved revision: 88
Merged at revision: 88
Proposed branch: lp:~tfukushima/glance/colorized-log
Merge into: lp:~glance-coresec/glance/cactus-trunk
Diff against target: 238 lines (+213/-0)
1 file modified
run_tests.py (+213/-0)
To merge this branch: bzr merge lp:~tfukushima/glance/colorized-log
Reviewer Review Type Date Requested Status
Jay Pipes (community) Approve
Rick Harris Pending
Review via email: mp+53444@code.launchpad.net

Description of the change

I stole the colorized code from nova.

To post a comment you must log in.
Revision history for this message
Jay Pipes (jaypipes) wrote :

Hi Taku!

Thanks for adding some colour into our lives! :)

One little thing that I would guess is also a mistake in the original code, too:

234 + stream.wirte('E')

Correct that little typo and I'm good to approve this.

-jay

review: Needs Fixing
lp:~tfukushima/glance/colorized-log updated
88. By Taku Fukushima

Fix typo

Revision history for this message
Taku Fukushima (tfukushima) wrote :

Hi Jay,

Thank you for reviewing my code and sorry for my late reply.
I fixed my typo and push it to my branch.
Please check it.

Best regards,
Taku Fukushima

On Wed, Mar 16, 2011 at 1:39 AM, Jay Pipes <email address hidden> wrote:
> Review: Needs Fixing
> Hi Taku!
>
> Thanks for adding some colour into our lives! :)
>
> One little thing that I would guess is also a mistake in the original code, too:
>
> 234     + stream.wirte('E')
>
> Correct that little typo and I'm good to approve this.
>
> -jay
> --
> https://code.launchpad.net/~tfukushima/glance/colorized-log/+merge/53444
> You are the owner of lp:~tfukushima/glance/colorized-log.
>
>

Revision history for this message
Jay Pipes (jaypipes) wrote :

thx Taku! lgtm.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'run_tests.py'
2--- run_tests.py 2011-01-27 04:19:13 +0000
3+++ run_tests.py 2011-03-16 06:46:28 +0000
4@@ -16,6 +16,40 @@
5 # See the License for the specific language governing permissions and
6 # limitations under the License.
7
8+# Colorizer Code is borrowed from Twisted:
9+# Copyright (c) 2001-2010 Twisted Matrix Laboratories.
10+#
11+# Permission is hereby granted, free of charge, to any person obtaining
12+# a copy of this software and associated documentation files (the
13+# "Software"), to deal in the Software without restriction, including
14+# without limitation the rights to use, copy, modify, merge, publish,
15+# distribute, sublicense, and/or sell copies of the Software, and to
16+# permit persons to whom the Software is furnished to do so, subject to
17+# the following conditions:
18+#
19+# The above copyright notice and this permission notice shall be
20+# included in all copies or substantial portions of the Software.
21+#
22+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29+
30+"""Unittest runner for glance
31+
32+To run all test::
33+ python run_tests.py
34+
35+To run a single test::
36+ python run_tests.py test_stores:TestSwiftBackend.test_get
37+
38+To run a single test module::
39+ python run_tests.py test_stores
40+"""
41+
42 import gettext
43 import os
44 import unittest
45@@ -26,14 +60,193 @@
46 from nose import core
47
48
49+class _AnsiColorizer(object):
50+ """
51+ A colorizer is an object that loosely wraps around a stream, allowing
52+ callers to write text to the stream in a particular color.
53+
54+ Colorizer classes must implement C{supported()} and C{write(text, color)}.
55+ """
56+ _colors = dict(black=30, red=31, green=32, yellow=33,
57+ blue=34, magenta=35, cyan=36, white=37)
58+
59+ def __init__(self, stream):
60+ self.stream = stream
61+
62+ def supported(cls, stream=sys.stdout):
63+ """
64+ A class method that returns True if the current platform supports
65+ coloring terminal output using this method. Returns False otherwise.
66+ """
67+ if not stream.isatty():
68+ return False # auto color only on TTYs
69+ try:
70+ import curses
71+ except ImportError:
72+ return False
73+ else:
74+ try:
75+ try:
76+ return curses.tigetnum("colors") > 2
77+ except curses.error:
78+ curses.setupterm()
79+ return curses.tigetnum("colors") > 2
80+ except:
81+ raise
82+ # guess false in case of error
83+ return False
84+ supported = classmethod(supported)
85+
86+ def write(self, text, color):
87+ """
88+ Write the given text to the stream in the given color.
89+
90+ @param text: Text to be written to the stream.
91+
92+ @param color: A string label for a color. e.g. 'red', 'white'.
93+ """
94+ color = self._colors[color]
95+ self.stream.write('\x1b[%s;1m%s\x1b[0m' % (color, text))
96+
97+
98+class _Win32Colorizer(object):
99+ """
100+ See _AnsiColorizer docstring.
101+ """
102+ def __init__(self, stream):
103+ from win32console import GetStdHandle, STD_OUT_HANDLE, \
104+ FOREGROUND_RED, FOREGROUND_BLUE, FOREGROUND_GREEN, \
105+ FOREGROUND_INTENSITY
106+ red, green, blue, bold = (FOREGROUND_RED, FOREGROUND_GREEN,
107+ FOREGROUND_BLUE, FOREGROUND_INTENSITY)
108+ self.stream = stream
109+ self.screenBuffer = GetStdHandle(STD_OUT_HANDLE)
110+ self._colors = {
111+ 'normal': red | green | blue,
112+ 'red': red | bold,
113+ 'green': green | bold,
114+ 'blue': blue | bold,
115+ 'yellow': red | green | bold,
116+ 'magenta': red | blue | bold,
117+ 'cyan': green | blue | bold,
118+ 'white': red | green | blue | bold
119+ }
120+
121+ def supported(cls, stream=sys.stdout):
122+ try:
123+ import win32console
124+ screenBuffer = win32console.GetStdHandle(
125+ win32console.STD_OUT_HANDLE)
126+ except ImportError:
127+ return False
128+ import pywintypes
129+ try:
130+ screenBuffer.SetConsoleTextAttribute(
131+ win32console.FOREGROUND_RED |
132+ win32console.FOREGROUND_GREEN |
133+ win32console.FOREGROUND_BLUE)
134+ except pywintypes.error:
135+ return False
136+ else:
137+ return True
138+ supported = classmethod(supported)
139+
140+ def write(self, text, color):
141+ color = self._colors[color]
142+ self.screenBuffer.SetConsoleTextAttribute(color)
143+ self.stream.write(text)
144+ self.screenBuffer.SetConsoleTextAttribute(self._colors['normal'])
145+
146+
147+class _NullColorizer(object):
148+ """
149+ See _AnsiColorizer docstring.
150+ """
151+ def __init__(self, stream):
152+ self.stream = stream
153+
154+ def supported(cls, stream=sys.stdout):
155+ return True
156+ supported = classmethod(supported)
157+
158+ def write(self, text, color):
159+ self.stream.write(text)
160+
161+
162 class GlanceTestResult(result.TextTestResult):
163 def __init__(self, *args, **kw):
164 result.TextTestResult.__init__(self, *args, **kw)
165 self._last_case = None
166+ self.colorizer = None
167+ # NOTE(vish, tfukushima): reset stdout for the terminal check
168+ stdout = sys.__stdout__
169+ for colorizer in [_Win32Colorizer, _AnsiColorizer, _NullColorizer]:
170+ if colorizer.supported():
171+ self.colorizer = colorizer(self.stream)
172+ break
173+ sys.stdout = stdout
174
175 def getDescription(self, test):
176 return str(test)
177
178+ # NOTE(vish, tfukushima): copied from unittest with edit to add color
179+ def addSuccess(self, test):
180+ unittest.TestResult.addSuccess(self, test)
181+ if self.showAll:
182+ self.colorizer.write("OK", 'green')
183+ self.stream.writeln()
184+ elif self.dots:
185+ self.stream.write('.')
186+ self.stream.flush()
187+
188+ # NOTE(vish, tfukushima): copied from unittest with edit to add color
189+ def addFailure(self, test, err):
190+ unittest.TestResult.addFailure(self, test, err)
191+ if self.showAll:
192+ self.colorizer.write("FAIL", 'red')
193+ self.stream.writeln()
194+ elif self.dots:
195+ self.stream.write('F')
196+ self.stream.flush()
197+
198+ # NOTE(vish, tfukushima): copied from unittest with edit to add color
199+ def addError(self, test, err):
200+ """Overrides normal addError to add support for errorClasses.
201+ If the exception is a registered class, the error will be added
202+ to the list for that class, not errors.
203+ """
204+ stream = getattr(self, 'stream', None)
205+ ec, ev, tb = err
206+ try:
207+ exc_info = self._exc_info_to_string(err, test)
208+ except TypeError:
209+ # This is for compatibility with Python 2.3.
210+ exc_info = self._exc_info_to_string(err)
211+ for cls, (storage, label, isfail) in self.errorClasses.items():
212+ if result.isclass(ec) and issubclass(ec, cls):
213+ if isfail:
214+ test.passwd = False
215+ storage.append((test, exc_info))
216+ # Might get patched into a streamless result
217+ if stream is not None:
218+ if self.showAll:
219+ message = [label]
220+ detail = result._exception_details(err[1])
221+ if detail:
222+ message.append(detail)
223+ stream.writeln(": ".join(message))
224+ elif self.dots:
225+ stream.write(label[:1])
226+ return
227+ self.errors.append((test, exc_info))
228+ test.passed = False
229+ if stream is not None:
230+ if self.showAll:
231+ self.colorizer.write("ERROR", 'red')
232+ self.stream.writeln()
233+ elif self.dots:
234+ stream.write('E')
235+
236 def startTest(self, test):
237 unittest.TestResult.startTest(self, test)
238 current_case = test.test.__class__.__name__

Subscribers

People subscribed via source and target branches