diff --git a/attest/reporters.py b/attest/reporters.py index 1b3de98..7568284 100644 --- a/attest/reporters.py +++ b/attest/reporters.py @@ -248,7 +248,8 @@ def begin(self, tests): from progressbar import ProgressBar, Percentage, ETA, SimpleProgress widgets = ['[', Percentage(), '] ', SimpleProgress(), ' ', ETA()] self.counter = 0 - self.progress = ProgressBar(maxval=len(tests), widgets=widgets) + self.progress = ProgressBar(maxval=len(tests), widgets=widgets, + fd=sys.stderr) self.progress.start() self.failures = [] @@ -282,9 +283,10 @@ def finished(self): print line formatter = Terminal256Formatter(style=self.style) - print highlight(result.traceback, + encoding = self._detect_code_encoding(result.raw_traceback[-1][0]) + print highlight(result.traceback.decode(encoding), PythonTracebackLexer(), - formatter) + formatter).encode(encoding) if result.assertion is not None: print highlight(result.assertion, PythonLexer(), formatter) @@ -299,6 +301,22 @@ def finished(self): if self.failures: raise SystemExit(1) + def _detect_code_encoding(self, filename): + """Detects code encoding from the magic encoding comment. + + """ + import re + comment_pattern = re.compile(r'\s*#?') + hint_pattern = re.compile(r'\s*#.*?coding(?::|\s*=)\s*([^\s]+)') + with open(filename) as pyfile: + for line in pyfile.xreadlines(): + if not comment_pattern.match(line): + break + match = hint_pattern.match(line) + if match is not None: + return match.group(1) + return 'ascii' + def auto_reporter(style=None): """Select a reporter based on the target output and installed diff --git a/attest/tests/reporters.py b/attest/tests/reporters.py index e11e3ac..ff39c3c 100644 --- a/attest/tests/reporters.py +++ b/attest/tests/reporters.py @@ -1,3 +1,4 @@ +# coding:utf-8 from __future__ import with_statement import sys @@ -111,3 +112,24 @@ def quickfix_reporter(): _meta.suite.run(attest.QuickFixReporter) assert out == ['%s:%d: TestFailure' % (SOURCEFILE, LINENO)] + + +@suite.test_if(COMPILES_AST) +def fancy_reporter_detects_encoding(): + """FancyReporter should detect code encoding.""" + + from pygments.style import Style + class NoStyle(Style): + default_style = '' + styles = {} + + suite_ = Tests() + @suite_.test + def unicode_failing(): + assert u'유니코드' == u'테스트' + + with attest.capture_output() as (out, err): + with Assert.raises(SystemExit): + suite_.run(attest.FancyReporter(NoStyle)) + + assert 'assert u\'유니코드\' == u\'테스트\'' in map(str.strip, out)