From 5cb8468f3b9949c0c1a1adc04c60d11fd6e5ad2e Mon Sep 17 00:00:00 2001 From: Marcus Huewe Date: Fri, 11 Feb 2011 02:43:10 +0100 Subject: [PATCH] - don't fail if terminal encoding doesn't support unicode (fixes #660445) - added util.safewriter.SafeWriter class --- osc/commandline.py | 13 +++++-------- osc/core.py | 17 +++++------------ osc/util/__init__.py | 2 +- osc/util/safewriter.py | 29 +++++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 21 deletions(-) create mode 100644 osc/util/safewriter.py diff --git a/osc/commandline.py b/osc/commandline.py index e30becf9..442074ae 100644 --- a/osc/commandline.py +++ b/osc/commandline.py @@ -9,6 +9,7 @@ import cmdln import conf import oscerr import sys +from util import safewriter from optparse import SUPPRESS_HELP MAN_HEADER = r""".TH %(ucname)s "1" "%(date)s" "%(name)s %(version)s" "User Commands" @@ -63,6 +64,8 @@ class Osc(cmdln.Cmdln): def __init__(self, *args, **kwargs): cmdln.Cmdln.__init__(self, *args, **kwargs) cmdln.Cmdln.do_help.aliases.append('h') + sys.stderr = safewriter.SafeWriter(sys.stderr) + sys.stdout = safewriter.SafeWriter(sys.stdout) def get_version(self): return get_osc_version() @@ -349,10 +352,7 @@ class Osc(cmdln.Cmdln): elif not opts.binaries: if not args: for prj in meta_get_project_list(apiurl, opts.deleted): - try: - print prj - except UnicodeEncodeError: - print prj.encode('unicode_escape') + print prj elif len(args) == 1: if opts.verbose: @@ -361,10 +361,7 @@ class Osc(cmdln.Cmdln): if opts.expand: raise oscerr.WrongOptions('Sorry, the --expand option is not implemented for projects.') for pkg in meta_get_packagelist(apiurl, project, opts.deleted): - try: - print pkg - except UnicodeEncodeError: - print pkg.encode('unicode_escape') + print pkg elif len(args) == 2 or len(args) == 3: link_seen = False diff --git a/osc/core.py b/osc/core.py index 32deb7cb..7845d9e1 100644 --- a/osc/core.py +++ b/osc/core.py @@ -2500,7 +2500,7 @@ class Request: def list_view(self): """return "list view" format""" - import textwrap, locale + import textwrap lines = ['%6s State:%-10s By:%-12s When:%-19s' % (self.reqid, self.state.name, self.state.who, self.state.when)] tmpl = ' %(type)-16s %(source)-50s %(target)s' for action in self.actions: @@ -2512,14 +2512,12 @@ class Request: if history: lines.append(' From: %s' % ' -> '.join(history)) if self.description: - descr = self.description.encode(locale.getpreferredencoding(), 'replace') - lines.append(textwrap.fill(descr, width=80, initial_indent=' Descr: ', + lines.append(textwrap.fill(self.description, width=80, initial_indent=' Descr: ', subsequent_indent=' ')) return '\n'.join(lines) def __str__(self): """return "detailed" format""" - import locale lines = ['Request: #%s\n' % self.reqid] for action in self.actions: tmpl = ' %(type)-13s %(source)s %(target)s' @@ -2529,7 +2527,7 @@ class Request: lines.append(tmpl % Request.format_action(action, show_srcupdate=True)) lines.append('\n\nMessage:') if self.description: - lines.append(self.description.encode(locale.getpreferredencoding(), 'replace')) + lines.append(self.description) else: lines.append('') if self.state: @@ -5892,13 +5890,8 @@ def request_interactive_review(apiurl, request, initial_cmd=''): tmpfile = None def print_request(request): - try: - # FIXME: print can fail with unicode chars in the string. - # Here we fix the symptoms, not the cause. - # UnicodeEncodeError: 'ascii' codec can't encode character u'\u2002' in position 309: ordinal not in range(128) - print request - except: - print request.__str__().encode('ascii', 'xmlcharrefreplace') + print request + print_request(request) try: prompt = '(a)ccept/(d)ecline/(r)evoke/c(l)one/(s)kip/(c)ancel > ' diff --git a/osc/util/__init__.py b/osc/util/__init__.py index 0f20b65e..74769f95 100644 --- a/osc/util/__init__.py +++ b/osc/util/__init__.py @@ -1 +1 @@ -__all__ = ['ar', 'cpio', 'debquery', 'packagequery', 'rpmquery'] +__all__ = ['ar', 'cpio', 'debquery', 'packagequery', 'rpmquery', 'safewriter'] diff --git a/osc/util/safewriter.py b/osc/util/safewriter.py new file mode 100644 index 00000000..e4448ccf --- /dev/null +++ b/osc/util/safewriter.py @@ -0,0 +1,29 @@ +# be careful when debugging this code: +# don't add print statements when setting sys.stdout = SafeWriter(sys.stdout)... +class SafeWriter: + """ + Safely write an (unicode) str. In case of an "UnicodeEncodeError" the + the str is encoded with the "encoding" encoding. + All getattr, setattr calls are passed through to the "writer" instance. + """ + def __init__(self, writer, encoding='unicode_escape'): + self.__dict__['writer'] = writer + self.__dict__['encoding'] = encoding + + def __get_writer(self): + return self.__dict__['writer'] + + def __get_encoding(self): + return self.__dict__['encoding'] + + def write(self, s): + try: + self.__get_writer().write(s) + except UnicodeEncodeError, e: + self.__get_writer().write(s.encode(self.__get_encoding())) + + def __getattr__(self, name): + return getattr(self.__get_writer(), name) + + def __setattr__(self, name, value): + setattr(self.__get_writer(), name, value)