Merge lp:~hid-iwata/bzr/fix-mojibake into lp:bzr

Proposed by IWATA Hidetaka
Status: Needs review
Proposed branch: lp:~hid-iwata/bzr/fix-mojibake
Merge into: lp:bzr
Diff against target: 68 lines (+31/-2)
2 files modified
bzrlib/commands.py (+9/-2)
bzrlib/trace.py (+22/-0)
To merge this branch: bzr merge lp:~hid-iwata/bzr/fix-mojibake
Reviewer Review Type Date Requested Status
bzr-core Pending
Review via email: mp+119051@code.launchpad.net

Description of the change

Workaround for #777996 and #909152

Unreadable error message can be a huge blocker for newbie users.
This patch may not be perfect, but I think this is better than now.

To post a comment you must log in.
Revision history for this message
Martin Packman (gz) wrote :

This is close to the right fix for this (longstanding and very annoying) issue.

I really think we want to do the decoding inside trace.report_exception rather than wrapping the stream passed to allow it to be stupid, what do you think?

Revision history for this message
IWATA Hidetaka (hid-iwata) wrote :

All stderr output must be encoded to terminal-encoding, even if stderr.encoding is None. (qbzr requires such behavior)
inside trace.report_exception, err_file can be any other file-like-object and I don't know which encoding to choose.
This is the reason why I use wrapped stream.

Unmerged revisions

6545. By IWATA Hidetaka

Consider decoding error.

6544. By IWATA Hidetaka

Fix mojibake of localized error message.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bzrlib/commands.py'
--- bzrlib/commands.py 2012-03-13 17:25:29 +0000
+++ bzrlib/commands.py 2012-08-09 21:38:46 +0000
@@ -918,6 +918,13 @@
918 os.close(pffileno)918 os.close(pffileno)
919 os.remove(pfname)919 os.remove(pfname)
920920
921def _err_file():
922 """
923 Get file like object which exception is written to.
924 """
925 return trace.EncodedOutputStream(sys.stderr,
926 osutils.get_terminal_encoding(),
927 'replace')
921928
922def exception_to_return_code(the_callable, *args, **kwargs):929def exception_to_return_code(the_callable, *args, **kwargs):
923 """UI level helper for profiling and coverage.930 """UI level helper for profiling and coverage.
@@ -932,7 +939,7 @@
932 # used to handle AssertionError and KeyboardInterrupt939 # used to handle AssertionError and KeyboardInterrupt
933 # specially here, but hopefully they're handled ok by the logger now940 # specially here, but hopefully they're handled ok by the logger now
934 exc_info = sys.exc_info()941 exc_info = sys.exc_info()
935 exitcode = trace.report_exception(exc_info, sys.stderr)942 exitcode = trace.report_exception(exc_info, _err_file())
936 if os.environ.get('BZR_PDB'):943 if os.environ.get('BZR_PDB'):
937 print '**** entering debugger'944 print '**** entering debugger'
938 tb = exc_info[2]945 tb = exc_info[2]
@@ -1252,7 +1259,7 @@
1252 except Exception, e:1259 except Exception, e:
1253 if (isinstance(e, (OSError, IOError))1260 if (isinstance(e, (OSError, IOError))
1254 or not getattr(e, 'internal_error', True)):1261 or not getattr(e, 'internal_error', True)):
1255 trace.report_exception(sys.exc_info(), sys.stderr)1262 trace.report_exception(sys.exc_info(), _err_file())
1256 return 31263 return 3
1257 else:1264 else:
1258 raise1265 raise
12591266
=== modified file 'bzrlib/trace.py'
--- bzrlib/trace.py 2012-02-01 13:24:42 +0000
+++ bzrlib/trace.py 2012-08-09 21:38:46 +0000
@@ -610,6 +610,28 @@
610 # to the file so there's no danger of getting into a loop here.610 # to the file so there's no danger of getting into a loop here.
611 mutter("Logging record unformattable: %s %% %s", msg, args)611 mutter("Logging record unformattable: %s %% %s", msg, args)
612612
613class EncodedOutputStream(object):
614 def __init__(self, stream, encoding=None, errors='strict'):
615 self.stream = stream
616 if encoding is None:
617 encoding = getattr(stream, "encoding", "ascii")
618 self.encoding = encoding
619 self.errors = errors
620
621 def write(self, text):
622 if isinstance(text, unicode):
623 self.stream.write(text.encode(self.encoding, self.errors))
624 else:
625 try:
626 text = text.decode("utf-8")
627 self.stream.write(text.encode(self.encoding, self.errors))
628 except UnicodeError:
629 self.stream.write(text)
630
631 def __getattr__(self, name):
632 """Redirect to self.stream"""
633 return getattr(self.stream, name)
634
613635
614class Config(object):636class Config(object):
615 """Configuration of message tracing in bzrlib.637 """Configuration of message tracing in bzrlib.